1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <stdio.h>
30#include <sys/types.h>
31
32#include <at.h>
33#include <snoop.h>
34
35static void show_rtmp_tuples(uint8_t *, int);
36
37static char *
38rtmp_func_long(uint8_t fun)
39{
40	switch (fun) {
41	case RTMP_REQ:
42		return ("Request");
43	case RTMP_RDR_SH:
44		return ("Route Data Request, split horizon");
45	case RTMP_RDR_NSH:
46		return ("Route Data Request, no split horizon");
47	default:
48		return ("unknown");
49	}
50}
51
52static char *
53rtmp_func_short(uint8_t fun)
54{
55	switch (fun) {
56	case RTMP_REQ:
57		return ("Req");
58	case RTMP_RDR_SH:
59		return ("RDR, sh");
60	case RTMP_RDR_NSH:
61		return ("RDR, no sh");
62	default:
63		return ("unknown");
64	}
65}
66
67void
68interpret_rtmp(int flags, struct ddp_hdr *ddp, int len)
69{
70	uint8_t *data;
71	uint16_t snet;
72	uint8_t node;
73	int tuples;
74	int runt;
75	char extended;
76
77	len -= DDPHDR_SIZE;
78	if (len < 0)
79		goto out;
80
81	data = (uint8_t *)ddp + DDPHDR_SIZE;
82
83	switch (ddp->ddp_type) {
84	case DDP_TYPE_RTMPRQ:		/* simple rtmp */
85		if (len < 1)
86			goto out;
87
88		if (flags & F_SUM) {
89			(void) snprintf(get_sum_line(), MAXLINE,
90			    "RTMP F=%s",
91			    rtmp_func_short(data[0]));
92		}
93
94		if (flags & F_DTAIL) {
95			show_header("RTMP: ", "RTMP Header", len);
96			show_space();
97
98			(void) snprintf(get_line(0, 0), get_line_remain(),
99			    "Func = %d (%s)",
100			    data[0], rtmp_func_long(data[0]));
101		}
102		break;
103	case DDP_TYPE_RTMPRESP:		/* RTMP data */
104		if (len < 3)
105			goto out;
106
107		snet = get_short(data);
108		if (data[2] != 8)	/* ID length is always 8 */
109			return;
110		node = data[3];		/* assume id_len == 8 */
111		extended = (data[6] != RTMP_FILLER) &&
112		    (get_short(&data[4]) != 0);
113
114		tuples = (len - 4) / 3;
115		runt = (len - 4) % 3; /* integral length? */
116
117		if (flags & F_SUM) {
118			(void) snprintf(get_sum_line(), MAXLINE,
119			    "RTMP Data Snet=%d, Snode=%d%s",
120			    snet, node, runt != 0 ? " (short)" : "");
121		}
122
123		if (flags & F_DTAIL) {
124			show_header("RTMP: ", "RTMP Header", len);
125			show_space();
126
127			(void) snprintf(get_line(0, 0), get_line_remain(),
128			    "RTMP Data, Length = %d%s",
129			    len, runt != 0 ? " (short packet)" : "");
130			(void) snprintf(get_line(0, 0), get_line_remain(),
131			    "Senders Net = %d, Sender Node %d",
132			    snet, node);
133			if (extended)
134				show_rtmp_tuples(&data[4], tuples);
135			else
136				show_rtmp_tuples(&data[7], tuples-1);
137		}
138
139		break;
140	}
141	return;
142out:
143	if (flags & F_SUM) {
144		(void) snprintf(get_sum_line(), MAXLINE,
145		    "RTMP (short packet)");
146	}
147
148	if (flags & F_DTAIL) {
149		show_header("RTMP: ", "RTMP Header", len);
150		show_space();
151
152		(void) snprintf(get_line(0, 0), get_line_remain(),
153		    "(short packet)");
154	}
155}
156
157static void
158show_rtmp_tuples(uint8_t *p, int tuples)
159{
160	while (tuples > 0) {
161
162		if (p[2] & RTMP_EXTEND) { /* extended tuple? */
163
164			(void) snprintf(get_line(0, 0),
165			    get_line_remain(),
166			    "Network = %d-%d, Distance = %d",
167			    get_short(p), get_short(&p[3]),
168			    p[2] & RTMP_DIST_MASK);
169			p += 6;
170			tuples -= 2;
171		} else {
172
173			(void) snprintf(get_line(0, 0),
174			    get_line_remain(),
175			    "Network = %d, Distance = %d",
176			    get_short(p), p[2]);
177			p += 3;
178			tuples--;
179		}
180	}
181}
182