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
35char *print_macaddr(uint8_t *, int);
36
37static char *zip_flags(char);
38static char *zip_flags_long(char);
39
40void
41interpret_ddp_zip(int flags, struct zip_hdr *zip, int len)
42{
43	int cnt;
44	uint16_t net;
45	uint16_t range;
46	uint8_t *p;
47	char zone[33];
48	char defzone[60] = "";
49	char mcast[50] = "";
50	uint8_t gniflags;
51	uint8_t *tail = (uint8_t *)zip + len;
52
53	if (flags & F_SUM) {
54		if (len < sizeof (struct zip_hdr))
55			goto out;
56
57		switch (zip->zip_func) {
58		case ZIP_QUERY:
59			cnt = zip->zip_netcnt;
60			(void) snprintf(get_sum_line(), MAXLINE,
61			    "ZIP Query CNT = %d", cnt);
62			break;
63		case ZIP_REPLY:
64		case ZIP_EXT_REPLY:
65			cnt = zip->zip_netcnt;
66			(void) snprintf(get_sum_line(), MAXLINE,
67			    "ZIP Reply CNT = %d", cnt);
68			break;
69		case ZIP_GET_NET_INFO:
70			p = &zip->zip_func;
71
72			if ((p+6 > tail) || (p+7+p[6] > tail))
73				goto out;
74
75			(void) snprintf(get_sum_line(), MAXLINE,
76			    "ZIP GNI Zone = \"%.*s\"", p[6], &p[7]);
77			break;
78		case ZIP_GET_NET_INFO_REPLY:
79			p = &zip->zip_func;
80
81			gniflags = p[1];
82			(void) snprintf(get_sum_line(), MAXLINE,
83			    "ZIP GNI Rep Flags 0x%x (%s)",
84			    gniflags, zip_flags(gniflags));
85			break;
86		default:
87			(void) snprintf(get_sum_line(), MAXLINE,
88			    "ZIP CMD = %d", zip->zip_func);
89			break;
90		}
91	}
92
93	if (flags & F_DTAIL) {
94		show_header("ZIP:  ", "ZIP Header", len);
95		show_space();
96
97		(void) snprintf(get_line(0, 0), get_line_remain(),
98		    "Length = %d", len);
99
100		if (len < sizeof (struct zip_hdr))
101			goto out;
102
103		switch (zip->zip_func) {
104		case ZIP_QUERY:
105			(void) snprintf(get_line(0, 0), get_line_remain(),
106			    "Query, Network count = %d", zip->zip_netcnt);
107			cnt = zip->zip_netcnt;
108			p = (uint8_t *)(zip + 1);
109			while (cnt--) {
110				if (p+2 > tail)
111					goto out;
112				net = get_short(p);
113				p += 2;
114				(void) snprintf(get_line(0, 0),
115				    get_line_remain(), "Net = %d", net);
116			}
117			break;
118		case ZIP_REPLY:
119		case ZIP_EXT_REPLY:
120			cnt = zip->zip_netcnt;
121			(void) snprintf(get_line(0, 0), get_line_remain(),
122			    "Reply, Network count = %d", cnt);
123
124			p = (uint8_t *)(zip + 1);
125			while (cnt--) {
126				if (p+2 > tail)
127					goto out;
128				net = get_short(p);
129				p += 2;
130				if (p+1 > tail || (&p[1] + p[0]) > tail)
131					goto out;
132				(void) snprintf(get_line(0, 0),
133				    get_line_remain(),
134				    "Network = %d, Zone = \"%.*s\"",
135				    net, p[0], &p[1]);
136				p += p[0] + 1;
137			}
138			break;
139		case ZIP_GET_NET_INFO:
140			p = &zip->zip_func;
141			if (p+1 > tail || (&p[1] + p[0]) > tail)
142				goto out;
143			(void) snprintf(get_line(0, 0), get_line_remain(),
144			    "GetNetInfo Zone = \"%.*s\"", p[0], &p[1]);
145			break;
146		case ZIP_GET_NET_INFO_REPLY:
147			p = &zip->zip_func;
148			if (p+5 > tail)
149				goto out;
150			gniflags = p[1];
151			net = get_short(&p[2]);
152			range = get_short(&p[4]);
153
154			if (p+7 > tail || (&p[7] + p[6]) > tail)
155				goto out;
156			(void) snprintf(zone, sizeof (zone),
157			    "%.*s", p[6], &p[7]);
158			p = &p[7] + p[6];
159
160			if ((gniflags & ZIP_FLG_USEBRC) == 0) {
161				if (p+1 > tail || (&p[1] + p[0]) > tail)
162					goto out;
163				(void) snprintf(mcast, sizeof (mcast),
164				    "Multicast address = %s",
165				    print_macaddr(&p[1], p[0]));
166			}
167
168			if (gniflags & ZIP_FLG_ZINV) {
169				p = &p[1] + p[0];
170				if (p+1 > tail || (&p[1] + p[0]) > tail)
171					goto out;
172				(void) snprintf(defzone, sizeof (defzone),
173				    "Default Zone = \"%.*s\"",
174				    p[0], &p[1]);
175			}
176			(void) snprintf(get_line(0, 0), get_line_remain(),
177			    "GetNetInfo Reply, Flags 0x%x (%s)",
178			    gniflags, zip_flags_long(gniflags));
179
180			(void) snprintf(get_line(0, 0), get_line_remain(),
181			    "Network number = %d-%d", net, range);
182
183			(void) snprintf(get_line(0, 0), get_line_remain(),
184			    "Zone = \"%s\"", zone);
185
186			if (mcast[0])
187				(void) snprintf(get_line(0, 0),
188				    get_line_remain(),
189				    "%s", mcast);
190
191			if (defzone[0])
192				(void) snprintf(get_line(0, 0),
193				    get_line_remain(),
194				    "%s", defzone);
195
196			break;
197		case ZIP_NOTIFY:
198			p = &zip->zip_func;
199			if (p+5 > tail)
200				goto out;
201
202			gniflags = p[1];
203			net = get_short(&p[2]);
204			range = get_short(&p[4]);
205
206			if (p+7 > tail || (&p[7] + p[6]) > tail)
207				goto out;
208			(void) snprintf(zone, sizeof (zone),
209			    "%.*s", p[6], &p[7]);
210			p = &p[7] + p[6];
211
212			if ((gniflags & ZIP_FLG_USEBRC) == 0) {
213				if (p+1 > tail || (&p[1] + p[0]) > tail)
214					goto out;
215				(void) snprintf(mcast, sizeof (mcast),
216				    "New Multicast address = %s",
217				    print_macaddr(&p[1], p[0]));
218			}
219
220			if (p+1 > tail || (&p[1] + p[0]) > tail)
221				goto out;
222
223			p = &p[1] + p[0];
224
225			if (p+1 > tail || (&p[1] + p[0]) > tail)
226				goto out;
227
228			(void) snprintf(defzone, sizeof (defzone),
229			    "New Default Zone = \"%.*s\"",
230			    p[0], &p[1]);
231
232			(void) snprintf(get_line(0, 0), get_line_remain(),
233			    "Notify, Flags 0x%x (%s)",
234			    gniflags, zip_flags_long(gniflags));
235
236			(void) snprintf(get_line(0, 0), get_line_remain(),
237			    "Old Zone = \"%s\"", zone);
238
239			if (mcast[0])
240				(void) snprintf(get_line(0, 0),
241				    get_line_remain(), "%s", mcast);
242
243			if (defzone[0])
244				(void) snprintf(get_line(0, 0),
245				    get_line_remain(), "%s", defzone);
246
247			break;
248		default:
249			(void) snprintf(get_line(0, 0), get_line_remain(),
250			    "Op = %d", zip->zip_func);
251			break;
252		}
253	}
254	return;
255out:
256	if (flags & F_SUM)
257		(void) snprintf(get_sum_line(), MAXLINE,
258		    "ZIP (short packet)");
259	if (flags & F_DTAIL)
260		(void) snprintf(get_line(0, 0), get_line_remain(),
261		    "ZIP (short packet)");
262}
263
264static char *
265zip_flags(char flags)
266{
267	static char buf[50];
268	char *p = buf;
269	char *tail = &buf[sizeof (buf)];
270
271	buf[0] = '\0';
272
273	if (flags & ZIP_FLG_ZINV)
274		p += snprintf(p, tail-p, "IZ");
275
276	if (flags & ZIP_FLG_USEBRC)
277		p += snprintf(p, tail-p, p == buf ? "UB" : " UB");
278
279	if (flags & ZIP_FLG_ONEZ)
280		(void) snprintf(p, tail-p, p == buf ? "OOZ" : " OOZ");
281
282	return (buf);
283}
284
285static char *
286zip_flags_long(char flags)
287{
288	static char buf[50];
289	char *p = buf;
290	char *tail = &buf[sizeof (buf)];
291
292	buf[0] = '\0';
293
294	if (flags & ZIP_FLG_ZINV)
295		p += snprintf(p, tail-p, "ZoneInvalid");
296
297	if (flags & ZIP_FLG_USEBRC)
298		p += snprintf(p, tail-p,
299		    p == buf ? "UseBroadcast" : " UseBroadcast");
300
301	if (flags & ZIP_FLG_ONEZ)
302		(void) snprintf(p, tail-p,
303		    p == buf ? "OnlyOneZone" : " OnlyOneZone");
304
305	return (buf);
306}
307
308void
309interpret_atp_zip(int flags, struct atp_hdr *atp, int len)
310{
311	int cnt;
312	uint8_t *data;
313	uint8_t *tail = (uint8_t *)(atp+1) + len;
314
315	if (flags & F_SUM) {
316		if (len < 0) {
317			(void) snprintf(get_sum_line(), MAXLINE,
318			    "ZIP (short packet)");
319			return;
320		}
321
322		switch (atp_fun(atp->atp_ctrl)) {
323		case ATP_TREQ:
324			switch (atp->atp_user[0]) {
325			case ZIP_ATP_GETMYZONE:
326				(void) snprintf(get_sum_line(), MAXLINE,
327				    "ZIP GetMyZone");
328				break;
329
330			case ZIP_ATP_GETZONELIST:
331				(void) snprintf(get_sum_line(), MAXLINE,
332				    "ZIP GetZoneList");
333				break;
334
335			case ZIP_ATP_GETLOCALZONES:
336				(void) snprintf(get_sum_line(), MAXLINE,
337				    "ZIP GetLocalZones");
338				break;
339			}
340			break;
341		case ATP_TRESP:
342			cnt = get_short(&atp->atp_user[2]);
343			(void) snprintf(get_sum_line(), MAXLINE,
344			    "ZIP ZoneReply, Cnt = %d", cnt);
345
346			break;
347		}
348	}
349
350	if (flags & F_DTAIL) {
351		show_header("ZIP:  ", "ZIP Header", len);
352		show_space();
353
354		if (len < 0) {
355			(void) snprintf(get_line(0, 0), get_line_remain(),
356			    "ZIP (short packet)");
357			return;
358		}
359
360		switch (atp_fun(atp->atp_ctrl)) {
361		case ATP_TREQ:
362			switch (atp->atp_user[0]) {
363			case ZIP_ATP_GETMYZONE:
364				(void) snprintf(get_line(0, 0),
365				    get_line_remain(),
366				    "GetMyZone, Start Index = %d",
367				    get_short(&atp->atp_user[2]));
368				break;
369			case ZIP_ATP_GETZONELIST:
370				(void) snprintf(get_line(0, 0),
371				    get_line_remain(),
372				    "GetZoneList, Start Index = %d",
373				    get_short(&atp->atp_user[2]));
374				break;
375			case ZIP_ATP_GETLOCALZONES:
376				(void) snprintf(get_line(0, 0),
377				    get_line_remain(),
378				    "GetLocalZones, Start Index = %d",
379				    get_short(&atp->atp_user[2]));
380				break;
381			}
382			break;
383		case ATP_TRESP:
384			cnt = get_short(&atp->atp_user[2]);
385			(void) snprintf(get_line(0, 0), get_line_remain(),
386			    "ZoneReply, Number of Zones = %d, Length = %d",
387			    cnt, len);
388
389			data = (uint8_t *)atp + DDPHDR_SIZE + ATPHDR_SIZE;
390
391			while (cnt--) {
392				if (data > tail ||
393				    (&data[1] + data[0]) > tail) {
394					(void) snprintf(get_line(0, 0),
395					    get_line_remain(),
396					    "ZoneReply (short packet)");
397					return;
398				}
399				(void) snprintf(get_line(0, 0),
400				    get_line_remain(),
401				    "Zone = \"%.*s\"", data[0], &data[1]);
402				data += data[0] + 1;
403			}
404			break;
405		}
406	}
407}
408