xref: /openbsd-src/usr.sbin/tcpdump/print-isoclns.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: print-isoclns.c,v 1.11 2007/10/07 16:41:05 deraadt 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     "@(#) $Id: print-isoclns.c,v 1.11 2007/10/07 16:41:05 deraadt Exp $ (LBL)";
29 #endif
30 
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 
35 struct mbuf;
36 struct rtentry;
37 #include <net/if.h>
38 
39 #include <netinet/in.h>
40 #include <netinet/if_ether.h>
41 
42 #include <stdio.h>
43 
44 #include "interface.h"
45 #include "addrtoname.h"
46 #include "ethertype.h"
47 
48 #define	CLNS	129
49 #define	ESIS	130
50 #define	ISIS	131
51 #define	NULLNS	0
52 
53 static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *);
54 static void esis_print(const u_char *, u_int);
55 
56 void
57 isoclns_print(const u_char *p, u_int length, u_int caplen,
58 	      const u_char *esrc, const u_char *edst)
59 {
60 	if (caplen < 1) {
61 		printf("[|iso-clns] ");
62 		if (!eflag)
63 			printf("%s > %s",
64 			       etheraddr_string(esrc),
65 			       etheraddr_string(edst));
66 		return;
67 	}
68 
69 	switch (*p) {
70 
71 	case CLNS:
72 		/* esis_print(&p, &length); */
73 		printf("iso-clns");
74 		if (!eflag)
75 			(void)printf(" %s > %s",
76 				     etheraddr_string(esrc),
77 				     etheraddr_string(edst));
78 		break;
79 
80 	case ESIS:
81 		printf("iso-esis");
82 		if (!eflag)
83 			(void)printf(" %s > %s",
84 				     etheraddr_string(esrc),
85 				     etheraddr_string(edst));
86 		esis_print(p, length);
87 		return;
88 
89 	case ISIS:
90 		printf("iso-isis");
91 		if (!eflag)
92 			(void)printf(" %s > %s",
93 				     etheraddr_string(esrc),
94 				     etheraddr_string(edst));
95 		/* isis_print(&p, &length); */
96 		(void)printf(" len=%d ", length);
97 		if (caplen > 1)
98 			default_print_unaligned(p, caplen);
99 		break;
100 
101 	case NULLNS:
102 		printf("iso-nullns");
103 		if (!eflag)
104 			(void)printf(" %s > %s",
105 				     etheraddr_string(esrc),
106 				     etheraddr_string(edst));
107 		break;
108 
109 	default:
110 		printf("iso-clns %02x", p[0]);
111 		if (!eflag)
112 			(void)printf(" %s > %s",
113 				     etheraddr_string(esrc),
114 				     etheraddr_string(edst));
115 		(void)printf(" len=%d ", length);
116 		if (caplen > 1)
117 			default_print_unaligned(p, caplen);
118 		break;
119 	}
120 }
121 
122 #define	ESIS_REDIRECT	6
123 #define	ESIS_ESH	2
124 #define	ESIS_ISH	4
125 
126 struct esis_hdr {
127 	u_char version;
128 	u_char reserved;
129 	u_char type;
130 	u_char tmo[2];
131 	u_char cksum[2];
132 };
133 
134 static void
135 esis_print(const u_char *p, u_int length)
136 {
137 	const u_char *ep;
138 	int li = p[1];
139 	const struct esis_hdr *eh = (const struct esis_hdr *) &p[2];
140 	u_char cksum[2];
141 	u_char off[2];
142 
143 	if (length == 2) {
144 		if (qflag)
145 			printf(" bad pkt!");
146 		else
147 			printf(" no header at all!");
148 		return;
149 	}
150 	ep = p + li;
151 	if (li > length) {
152 		if (qflag)
153 			printf(" bad pkt!");
154 		else
155 			printf(" LI(%d) > PDU size (%d)!", li, length);
156 		return;
157 	}
158 	if (li < sizeof(struct esis_hdr) + 2) {
159 		if (qflag)
160 			printf(" bad pkt!");
161 		else {
162 			printf(" too short for esis header %d:", li);
163 			while (--length != 0)
164 				printf("%02X", *p++);
165 		}
166 		return;
167 	}
168 	switch (eh->type & 0x1f) {
169 
170 	case ESIS_REDIRECT:
171 		printf(" redirect");
172 		break;
173 
174 	case ESIS_ESH:
175 		printf(" esh");
176 		break;
177 
178 	case ESIS_ISH:
179 		printf(" ish");
180 		break;
181 
182 	default:
183 		printf(" type %d", eh->type & 0x1f);
184 		break;
185 	}
186 	off[0] = eh->cksum[0];
187 	off[1] = eh->cksum[1];
188 	if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) {
189 		printf(" bad cksum (got %02x%02x want %02x%02x)",
190 		       eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]);
191 		return;
192 	}
193 	if (eh->version != 1) {
194 		printf(" unsupported version %d", eh->version);
195 		return;
196 	}
197 	p += sizeof(*eh) + 2;
198 	li -= sizeof(*eh) + 2;	/* protoid * li */
199 
200 	switch (eh->type & 0x1f) {
201 	case ESIS_REDIRECT: {
202 		const u_char *dst, *snpa, *is;
203 
204 		dst = p; p += *p + 1;
205 		if (p > snapend)
206 			return;
207 		printf(" %s", isonsap_string(dst));
208 		snpa = p; p += *p + 1;
209 		is = p;   p += *p + 1;
210 		if (p > snapend)
211 			return;
212 		if (p > ep) {
213 			printf(" [bad li]");
214 			return;
215 		}
216 		if (is[0] == 0)
217 			printf(" > %s", etheraddr_string(&snpa[1]));
218 		else
219 			printf(" > %s", isonsap_string(is));
220 		li = ep - p;
221 		break;
222 	}
223 	case ESIS_ESH: {
224 		const u_char *nsap;
225 		int i, nnsaps;
226 
227 		nnsaps = *p++;
228 
229 		/* print NSAPs */
230 		for (i = 0; i < nnsaps; i++) {
231 			nsap = p;
232 			p += *p + 1;
233 			if (p > ep) {
234 				printf(" [bad li]");
235 				return;
236 			}
237 			if (p > snapend)
238 				return;
239 			printf(" nsap %s", isonsap_string(nsap));
240 		}
241 		li = ep - p;
242 		break;
243 	}
244 	case ESIS_ISH: {
245 		const u_char *is;
246 
247 		is = p; p += *p + 1;
248 		if (p > ep) {
249 			printf(" [bad li]");
250 			return;
251 		}
252 		if (p > snapend)
253 			return;
254 		printf(" net %s", isonsap_string(is));
255 		li = ep - p;
256 		break;
257 	}
258 
259 	default:
260 		(void)printf(" len=%d", length);
261 		if (length && p < snapend) {
262 			length = snapend - p;
263 			default_print(p, length);
264 		}
265 		return;
266 	}
267 	if (vflag)
268 		while (p < ep && li) {
269 			int op, opli;
270 			const u_char *q;
271 
272 			if (snapend - p < 2)
273 				return;
274 			if (li < 2) {
275 				printf(" bad opts/li");
276 				return;
277 			}
278 			op = *p++;
279 			opli = *p++;
280 			li -= 2;
281 			if (opli > li) {
282 				printf(" opt (%d) too long", op);
283 				return;
284 			}
285 			li -= opli;
286 			q = p;
287 			p += opli;
288 			if (snapend < p)
289 				return;
290 			if (op == 198 && opli == 2) {
291 				printf(" tmo=%d", q[0] * 256 + q[1]);
292 				continue;
293 			}
294 			printf (" %d:<", op);
295 			while (--opli >= 0)
296 				printf("%02x", *q++);
297 			printf (">");
298 		}
299 }
300 
301 static int
302 osi_cksum(register const u_char *p, register u_int len,
303 	  const u_char *toff, u_char *cksum, u_char *off)
304 {
305 	const u_char *ep;
306 	int c0, c1;
307 	int n;
308 
309 	if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0)
310 		return 0;
311 
312 	n = toff - p + 1;
313 	c0 = c1 = 0;
314 	ep = p + len;
315 	for (; p < toff; p++) {
316 		c0 = (c0 + *p);
317 		c1 += c0;
318 	}
319 
320 	/* skip cksum bytes */
321 	p += 2;
322 	c1 += c0; c1 += c0;
323 
324 	for (; p < ep; p++) {
325 		c0 = (c0 + *p);
326 		c1 += c0;
327 	}
328 
329 	c1 = (((c0 * (len - n)) - c1) % 255);
330 	cksum[0] = (u_char) ((c1 < 0) ? c1 + 255 : c1);
331 	c1 = (-(int) (c1 + c0)) % 255;
332 	cksum[1] = (u_char) (c1 < 0 ? c1 + 255 : c1);
333 
334 	return (off[0] != cksum[0] || off[1] != cksum[1]);
335 }
336