1 /* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Original code by Matt Thomas, Digital Equipment Corporation 22 */ 23 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-isoclns.c,v 1.6 1997/07/25 20:12:25 mickey Exp $ (LBL)"; 27 #endif 28 29 #include <sys/types.h> 30 #include <sys/time.h> 31 #include <sys/socket.h> 32 33 #ifdef __STDC__ 34 struct mbuf; 35 struct rtentry; 36 #endif 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 #if 0 224 case ESIS_ESH: 225 printf(" esh"); 226 break; 227 #endif 228 case ESIS_ISH: { 229 const u_char *is; 230 231 is = p; p += *p + 1; 232 if (p > ep) { 233 printf(" [bad li]"); 234 return; 235 } 236 if (p > snapend) 237 return; 238 printf(" %s", isonsap_string(is)); 239 li = ep - p; 240 break; 241 } 242 243 default: 244 (void)printf(" len=%d", length); 245 if (length && p < snapend) { 246 length = snapend - p; 247 default_print(p, length); 248 } 249 return; 250 } 251 if (vflag) 252 while (p < ep && li) { 253 int op, opli; 254 const u_char *q; 255 256 if (snapend - p < 2) 257 return; 258 if (li < 2) { 259 printf(" bad opts/li"); 260 return; 261 } 262 op = *p++; 263 opli = *p++; 264 li -= 2; 265 if (opli > li) { 266 printf(" opt (%d) too long", op); 267 return; 268 } 269 li -= opli; 270 q = p; 271 p += opli; 272 if (snapend < p) 273 return; 274 if (op == 198 && opli == 2) { 275 printf(" tmo=%d", q[0] * 256 + q[1]); 276 continue; 277 } 278 printf (" %d:<", op); 279 while (--opli >= 0) 280 printf("%02x", *q++); 281 printf (">"); 282 } 283 } 284 285 static int 286 osi_cksum(register const u_char *p, register u_int len, 287 const u_char *toff, u_char *cksum, u_char *off) 288 { 289 int x, y, f = (len - ((toff - p) + 1)); 290 int32_t c0 = 0, c1 = 0; 291 292 if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0) 293 return 0; 294 295 off[0] = off[1] = 0; 296 while (--len >= 0) { 297 c0 += *p++; 298 c1 += c0; 299 c0 %= 255; 300 c1 %= 255; 301 } 302 x = (c0 * f - c1); 303 if (x < 0) 304 x = 255 - (-x % 255); 305 else 306 x %= 255; 307 y = -1 * (x + c0); 308 if (y < 0) 309 y = 255 - (-y % 255); 310 else 311 y %= 255; 312 313 off[0] = x; 314 off[1] = y; 315 316 return (off[0] != cksum[0] || off[1] != cksum[1]); 317 } 318