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