1 /* 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that: (1) source code 4 * distributions retain the above copyright notice and this paragraph 5 * in its entirety, and (2) distributions including binary code include 6 * the above copyright notice and this paragraph in its entirety in 7 * the documentation or other materials provided with the distribution. 8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11 * FOR A PARTICULAR PURPOSE. 12 * 13 * Original code by Hannes Gredler (hannes@juniper.net) 14 */ 15 16 #ifndef lint 17 static const char rcsid[] _U_ = 18 "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8 2005/04/06 21:32:41 mcr Exp $ (LBL)"; 19 #endif 20 21 #ifdef HAVE_CONFIG_H 22 #include "config.h" 23 #endif 24 25 #include <tcpdump-stdinc.h> 26 27 #include <pcap.h> 28 #include <stdio.h> 29 30 #include "interface.h" 31 #include "extract.h" 32 #include "ppp.h" 33 #include "llc.h" 34 #include "nlpid.h" 35 36 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */ 37 #define JUNIPER_BPF_IN 1 /* Incoming packet */ 38 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */ 39 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */ 40 41 #define LS_COOKIE_ID 0x54 42 #define LS_MLFR_LEN 4 43 #define ML_MLFR_LEN 2 44 45 #define ATM2_PKT_TYPE_MASK 0x70 46 #define ATM2_GAP_COUNT_MASK 0x3F 47 48 int ip_heuristic_guess(register const u_char *, u_int); 49 int juniper_ppp_heuristic_guess(register const u_char *, u_int); 50 static int juniper_parse_header (const u_char *, u_int8_t *, u_int); 51 52 u_int 53 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p) 54 { 55 register u_int length = h->len; 56 register u_int caplen = h->caplen; 57 u_int8_t direction,bundle,cookie_len; 58 u_int32_t cookie,proto; 59 60 if(juniper_parse_header(p, &direction,length) == 0) 61 return 0; 62 63 p+=4; 64 length-=4; 65 caplen-=4; 66 67 if (p[0] == LS_COOKIE_ID) { 68 cookie=EXTRACT_32BITS(p); 69 if (eflag) printf("LSPIC-MLPPP cookie 0x%08x, ",cookie); 70 cookie_len = LS_MLFR_LEN; 71 bundle = cookie & 0xff; 72 } else { 73 cookie=EXTRACT_16BITS(p); 74 if (eflag) printf("MLPIC-MLPPP cookie 0x%04x, ",cookie); 75 cookie_len = ML_MLFR_LEN; 76 bundle = (cookie >> 8) & 0xff; 77 } 78 79 proto = EXTRACT_16BITS(p+cookie_len); 80 p += cookie_len; 81 length-= cookie_len; 82 caplen-= cookie_len; 83 84 /* suppress Bundle-ID if frame was captured on a child-link 85 * this may be the case if the cookie looks like a proto */ 86 if (eflag && 87 cookie != PPP_OSI && 88 cookie != (PPP_ADDRESS << 8 | PPP_CONTROL)) 89 printf("Bundle-ID %u, ",bundle); 90 91 switch (cookie) { 92 case PPP_OSI: 93 ppp_print(p-2,length+2); 94 break; 95 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */ 96 default: 97 ppp_print(p,length); 98 break; 99 } 100 101 return cookie_len; 102 } 103 104 105 u_int 106 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p) 107 { 108 register u_int length = h->len; 109 register u_int caplen = h->caplen; 110 u_int8_t direction,bundle,cookie_len; 111 u_int32_t cookie,proto,frelay_len = 0; 112 113 if(juniper_parse_header(p, &direction,length) == 0) 114 return 0; 115 116 p+=4; 117 length-=4; 118 caplen-=4; 119 120 if (p[0] == LS_COOKIE_ID) { 121 cookie=EXTRACT_32BITS(p); 122 if (eflag) printf("LSPIC-MLFR cookie 0x%08x, ",cookie); 123 cookie_len = LS_MLFR_LEN; 124 bundle = cookie & 0xff; 125 } else { 126 cookie=EXTRACT_16BITS(p); 127 if (eflag) printf("MLPIC-MLFR cookie 0x%04x, ",cookie); 128 cookie_len = ML_MLFR_LEN; 129 bundle = (cookie >> 8) & 0xff; 130 } 131 132 proto = EXTRACT_16BITS(p+cookie_len); 133 p += cookie_len+2; 134 length-= cookie_len+2; 135 caplen-= cookie_len+2; 136 137 /* suppress Bundle-ID if frame was captured on a child-link */ 138 if (eflag && cookie != 1) printf("Bundle-ID %u, ",bundle); 139 140 switch (proto) { 141 case (LLC_UI): 142 case (LLC_UI<<8): 143 isoclns_print(p, length, caplen); 144 break; 145 case (LLC_UI<<8 | NLPID_Q933): 146 case (LLC_UI<<8 | NLPID_IP): 147 case (LLC_UI<<8 | NLPID_IP6): 148 isoclns_print(p-1, length+1, caplen+1); /* pass IP{4,6} to the OSI layer for proper link-layer printing */ 149 break; 150 default: 151 printf("unknown protocol 0x%04x, length %u",proto, length); 152 } 153 154 return cookie_len + frelay_len; 155 } 156 157 /* 158 * ATM1 PIC cookie format 159 * 160 * +-----+-------------------------+-------------------------------+ 161 * |fmtid| vc index | channel ID | 162 * +-----+-------------------------+-------------------------------+ 163 */ 164 165 u_int 166 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p) 167 { 168 register u_int length = h->len; 169 register u_int caplen = h->caplen; 170 u_int16_t extracted_ethertype; 171 u_int8_t direction; 172 u_int32_t cookie1; 173 174 if(juniper_parse_header(p, &direction,length) == 0) 175 return 0; 176 177 p+=4; 178 length-=4; 179 caplen-=4; 180 181 cookie1=EXTRACT_32BITS(p); 182 183 if (eflag) { 184 /* FIXME decode channel-id, vc-index, fmt-id 185 for once lets just hexdump the cookie */ 186 187 printf("ATM1 cookie 0x%08x, ", cookie1); 188 } 189 190 p+=4; 191 length-=4; 192 caplen-=4; 193 194 if ((cookie1 >> 24) == 0x80) { /* OAM cell ? */ 195 oam_print(p,length); 196 return 0; 197 } 198 199 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ 200 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ 201 202 if (llc_print(p, length, caplen, NULL, NULL, 203 &extracted_ethertype) != 0) 204 return 8; 205 } 206 207 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ 208 isoclns_print(p + 1, length - 1, caplen - 1); 209 /* FIXME check if frame was recognized */ 210 return 8; 211 } 212 213 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */ 214 return 0; 215 216 return (8); 217 } 218 219 /* 220 * ATM2 PIC cookie format 221 * 222 * +-------------------------------+---------+---+-----+-----------+ 223 * | channel ID | reserv |AAL| CCRQ| gap cnt | 224 * +-------------------------------+---------+---+-----+-----------+ 225 */ 226 227 u_int 228 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p) 229 { 230 register u_int length = h->len; 231 register u_int caplen = h->caplen; 232 u_int16_t extracted_ethertype; 233 u_int8_t direction; 234 u_int32_t cookie1,cookie2; 235 236 if(juniper_parse_header(p, &direction,length) == 0) 237 return 0; 238 239 p+=4; 240 length-=4; 241 caplen-=4; 242 243 cookie1=EXTRACT_32BITS(p); 244 cookie2=EXTRACT_32BITS(p+4); 245 246 if (eflag) { 247 /* FIXME decode channel, fmt-id, ccrq, aal, gap cnt 248 for once lets just hexdump the cookie */ 249 250 printf("ATM2 cookie 0x%08x%08x, ", 251 EXTRACT_32BITS(p), 252 EXTRACT_32BITS(p+4)); 253 } 254 255 p+=8; 256 length-=8; 257 caplen-=8; 258 259 if (cookie2 & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */ 260 oam_print(p,length); 261 return 12; 262 } 263 264 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ 265 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ 266 267 if (llc_print(p, length, caplen, NULL, NULL, 268 &extracted_ethertype) != 0) 269 return 12; 270 } 271 272 if (direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */ 273 (cookie1 & ATM2_GAP_COUNT_MASK)) { 274 ether_print(p, length, caplen); 275 return 12; 276 } 277 278 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ 279 isoclns_print(p + 1, length - 1, caplen - 1); 280 /* FIXME check if frame was recognized */ 281 return 12; 282 } 283 284 if(juniper_ppp_heuristic_guess(p, length) != 0) /* PPPoA vcmux encaps ? */ 285 return 12; 286 287 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */ 288 return 12; 289 290 return (12); 291 } 292 293 294 /* try to guess, based on all PPP protos that are supported in 295 * a juniper router if the payload data is encapsulated using PPP */ 296 int 297 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) { 298 299 switch(EXTRACT_16BITS(p)) { 300 case PPP_IP : 301 case PPP_OSI : 302 case PPP_MPLS_UCAST : 303 case PPP_MPLS_MCAST : 304 case PPP_IPCP : 305 case PPP_OSICP : 306 case PPP_MPLSCP : 307 case PPP_LCP : 308 case PPP_PAP : 309 case PPP_CHAP : 310 case PPP_ML : 311 #ifdef INET6 312 case PPP_IPV6 : 313 case PPP_IPV6CP : 314 #endif 315 ppp_print(p, length); 316 break; 317 318 default: 319 return 0; /* did not find a ppp header */ 320 break; 321 } 322 return 1; /* we printed a ppp packet */ 323 } 324 325 int 326 ip_heuristic_guess(register const u_char *p, u_int length) { 327 328 switch(p[0]) { 329 case 0x45: 330 case 0x46: 331 case 0x47: 332 case 0x48: 333 case 0x49: 334 case 0x4a: 335 case 0x4b: 336 case 0x4c: 337 case 0x4d: 338 case 0x4e: 339 case 0x4f: 340 ip_print(gndo, p, length); 341 break; 342 #ifdef INET6 343 case 0x60: 344 case 0x61: 345 case 0x62: 346 case 0x63: 347 case 0x64: 348 case 0x65: 349 case 0x66: 350 case 0x67: 351 case 0x68: 352 case 0x69: 353 case 0x6a: 354 case 0x6b: 355 case 0x6c: 356 case 0x6d: 357 case 0x6e: 358 case 0x6f: 359 ip6_print(p, length); 360 break; 361 #endif 362 default: 363 return 0; /* did not find a ip header */ 364 break; 365 } 366 return 1; /* we printed an v4/v6 packet */ 367 } 368 369 static int 370 juniper_parse_header (const u_char *p, u_int8_t *direction, u_int length) { 371 372 *direction = p[3]&JUNIPER_BPF_PKT_IN; 373 374 if (EXTRACT_24BITS(p) != 0x4d4743) /* magic number found ? */ 375 return -1; 376 377 if (*direction == JUNIPER_BPF_PKT_IN) { 378 if (eflag) 379 printf("%3s ", "In"); 380 } 381 else { 382 if (eflag) 383 printf("%3s ", "Out"); 384 } 385 386 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { 387 if (eflag) 388 printf("no-L2-hdr, "); 389 390 /* there is no link-layer present - 391 * perform the v4/v6 heuristics 392 * to figure out what it is 393 */ 394 if(ip_heuristic_guess(p+8,length-8) == 0) 395 printf("no IP-hdr found!"); 396 397 return 0; /* stop parsing the output further */ 398 399 } 400 return 1; /* everything went ok so far. continue parsing */ 401 } 402 403 404 /* 405 * Local Variables: 406 * c-style: whitesmith 407 * c-basic-offset: 8 408 * End: 409 */ 410