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