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