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 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 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 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