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