xref: /openbsd-src/usr.sbin/tcpdump/print-isoclns.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: print-isoclns.c,v 1.9 2000/10/03 14:31:57 ho Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993, 1994, 1995, 1996
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  *
23  * Original code by Matt Thomas, Digital Equipment Corporation
24  */
25 
26 #ifndef lint
27 static const char rcsid[] =
28     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-isoclns.c,v 1.9 2000/10/03 14:31:57 ho Exp $ (LBL)";
29 #endif
30 
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 
35 #ifdef __STDC__
36 struct mbuf;
37 struct rtentry;
38 #endif
39 #include <net/if.h>
40 
41 #include <netinet/in.h>
42 #include <netinet/if_ether.h>
43 
44 #include <stdio.h>
45 
46 #include "interface.h"
47 #include "addrtoname.h"
48 #include "ethertype.h"
49 
50 #define	CLNS	129
51 #define	ESIS	130
52 #define	ISIS	131
53 #define	NULLNS	0
54 
55 static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *);
56 static void esis_print(const u_char *, u_int);
57 
58 void
59 isoclns_print(const u_char *p, u_int length, u_int caplen,
60 	      const u_char *esrc, const u_char *edst)
61 {
62 	if (caplen < 1) {
63 		printf("[|iso-clns] ");
64 		if (!eflag)
65 			printf("%s > %s",
66 			       etheraddr_string(esrc),
67 			       etheraddr_string(edst));
68 		return;
69 	}
70 
71 	switch (*p) {
72 
73 	case CLNS:
74 		/* esis_print(&p, &length); */
75 		printf("iso-clns");
76 		if (!eflag)
77 			(void)printf(" %s > %s",
78 				     etheraddr_string(esrc),
79 				     etheraddr_string(edst));
80 		break;
81 
82 	case ESIS:
83 		printf("iso-esis");
84 		if (!eflag)
85 			(void)printf(" %s > %s",
86 				     etheraddr_string(esrc),
87 				     etheraddr_string(edst));
88 		esis_print(p, length);
89 		return;
90 
91 	case ISIS:
92 		printf("iso-isis");
93 		if (!eflag)
94 			(void)printf(" %s > %s",
95 				     etheraddr_string(esrc),
96 				     etheraddr_string(edst));
97 		/* isis_print(&p, &length); */
98 		(void)printf(" len=%d ", length);
99 		if (caplen > 1)
100 			default_print_unaligned(p, caplen);
101 		break;
102 
103 	case NULLNS:
104 		printf("iso-nullns");
105 		if (!eflag)
106 			(void)printf(" %s > %s",
107 				     etheraddr_string(esrc),
108 				     etheraddr_string(edst));
109 		break;
110 
111 	default:
112 		printf("iso-clns %02x", p[0]);
113 		if (!eflag)
114 			(void)printf(" %s > %s",
115 				     etheraddr_string(esrc),
116 				     etheraddr_string(edst));
117 		(void)printf(" len=%d ", length);
118 		if (caplen > 1)
119 			default_print_unaligned(p, caplen);
120 		break;
121 	}
122 }
123 
124 #define	ESIS_REDIRECT	6
125 #define	ESIS_ESH	2
126 #define	ESIS_ISH	4
127 
128 struct esis_hdr {
129 	u_char version;
130 	u_char reserved;
131 	u_char type;
132 	u_char tmo[2];
133 	u_char cksum[2];
134 };
135 
136 static void
137 esis_print(const u_char *p, u_int length)
138 {
139 	const u_char *ep;
140 	int li = p[1];
141 	const struct esis_hdr *eh = (const struct esis_hdr *) &p[2];
142 	u_char cksum[2];
143 	u_char off[2];
144 
145 	if (length == 2) {
146 		if (qflag)
147 			printf(" bad pkt!");
148 		else
149 			printf(" no header at all!");
150 		return;
151 	}
152 	ep = p + li;
153 	if (li > length) {
154 		if (qflag)
155 			printf(" bad pkt!");
156 		else
157 			printf(" LI(%d) > PDU size (%d)!", li, length);
158 		return;
159 	}
160 	if (li < sizeof(struct esis_hdr) + 2) {
161 		if (qflag)
162 			printf(" bad pkt!");
163 		else {
164 			printf(" too short for esis header %d:", li);
165 			while (--length != 0)
166 				printf("%02X", *p++);
167 		}
168 		return;
169 	}
170 	switch (eh->type & 0x1f) {
171 
172 	case ESIS_REDIRECT:
173 		printf(" redirect");
174 		break;
175 
176 	case ESIS_ESH:
177 		printf(" esh");
178 		break;
179 
180 	case ESIS_ISH:
181 		printf(" ish");
182 		break;
183 
184 	default:
185 		printf(" type %d", eh->type & 0x1f);
186 		break;
187 	}
188 	off[0] = eh->cksum[0];
189 	off[1] = eh->cksum[1];
190 	if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) {
191 		printf(" bad cksum (got %02x%02x want %02x%02x)",
192 		       eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]);
193 		return;
194 	}
195 	if (eh->version != 1) {
196 		printf(" unsupported version %d", eh->version);
197 		return;
198 	}
199 	p += sizeof(*eh) + 2;
200 	li -= sizeof(*eh) + 2;	/* protoid * li */
201 
202 	switch (eh->type & 0x1f) {
203 	case ESIS_REDIRECT: {
204 		const u_char *dst, *snpa, *is;
205 
206 		dst = p; p += *p + 1;
207 		if (p > snapend)
208 			return;
209 		printf(" %s", isonsap_string(dst));
210 		snpa = p; p += *p + 1;
211 		is = p;   p += *p + 1;
212 		if (p > snapend)
213 			return;
214 		if (p > ep) {
215 			printf(" [bad li]");
216 			return;
217 		}
218 		if (is[0] == 0)
219 			printf(" > %s", etheraddr_string(&snpa[1]));
220 		else
221 			printf(" > %s", isonsap_string(is));
222 		li = ep - p;
223 		break;
224 	}
225 	case ESIS_ESH: {
226 		const u_char *nsap;
227 		int i, nnsaps;
228 
229 		nnsaps = *p++;
230 
231 		/* print NSAPs */
232 		for (i = 0; i < nnsaps; i++) {
233 			nsap = p;
234 			p += *p + 1;
235 			if (p > ep) {
236 				printf(" [bad li]");
237 				return;
238 			}
239 			if (p > snapend)
240 				return;
241 			printf(" nsap %s", isonsap_string(nsap));
242 		}
243 		li = ep - p;
244 		break;
245 	}
246 	case ESIS_ISH: {
247 		const u_char *is;
248 
249 		is = p; p += *p + 1;
250 		if (p > ep) {
251 			printf(" [bad li]");
252 			return;
253 		}
254 		if (p > snapend)
255 			return;
256 		printf(" net %s", isonsap_string(is));
257 		li = ep - p;
258 		break;
259 	}
260 
261 	default:
262 		(void)printf(" len=%d", length);
263 		if (length && p < snapend) {
264 			length = snapend - p;
265 			default_print(p, length);
266 		}
267 		return;
268 	}
269 	if (vflag)
270 		while (p < ep && li) {
271 			int op, opli;
272 			const u_char *q;
273 
274 			if (snapend - p < 2)
275 				return;
276 			if (li < 2) {
277 				printf(" bad opts/li");
278 				return;
279 			}
280 			op = *p++;
281 			opli = *p++;
282 			li -= 2;
283 			if (opli > li) {
284 				printf(" opt (%d) too long", op);
285 				return;
286 			}
287 			li -= opli;
288 			q = p;
289 			p += opli;
290 			if (snapend < p)
291 				return;
292 			if (op == 198 && opli == 2) {
293 				printf(" tmo=%d", q[0] * 256 + q[1]);
294 				continue;
295 			}
296 			printf (" %d:<", op);
297 			while (--opli >= 0)
298 				printf("%02x", *q++);
299 			printf (">");
300 		}
301 }
302 
303 static int
304 osi_cksum(register const u_char *p, register u_int len,
305 	  const u_char *toff, u_char *cksum, u_char *off)
306 {
307 	const u_char *ep;
308 	int c0, c1;
309 	int n;
310 
311 	if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0)
312 		return 0;
313 
314 	n = toff - p + 1;
315 	c0 = c1 = 0;
316 	ep = p + len;
317 	for (; p < toff; p++) {
318 		c0 = (c0 + *p);
319 		c1 += c0;
320 	}
321 
322 	/* skip cksum bytes */
323 	p += 2;
324 	c1 += c0; c1 += c0;
325 
326 	for (; p < ep; p++) {
327 		c0 = (c0 + *p);
328 		c1 += c0;
329 	}
330 
331 	c1 = (((c0 * (len - n)) - c1) % 255);
332 	cksum[0] = (u_char) ((c1 < 0) ? c1 + 255 : c1);
333 	c1 = (-(int) (c1 + c0)) % 255;
334 	cksum[1] = (u_char) (c1 < 0 ? c1 + 255 : c1);
335 
336 	return (off[0] != cksum[0] || off[1] != cksum[1]);
337 }
338