]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
Add missing af.c and af.h files.
[tcpdump] / print-juniper.c
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.30 2006-02-24 12:18:03 hannes 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 "addrtoname.h"
32 #include "extract.h"
33 #include "ppp.h"
34 #include "llc.h"
35 #include "nlpid.h"
36 #include "ethertype.h"
37 #include "atm.h"
38
39 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
40 #define JUNIPER_BPF_IN 1 /* Incoming packet */
41 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
42 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
43 #define JUNIPER_BPF_IIF 0x4 /* IIF is valid */
44 #define JUNIPER_BPF_FILTER 0x40 /* BPF filtering is supported */
45 #define JUNIPER_BPF_EXT 0x80 /* extensions present */
46 #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
47
48 #define JUNIPER_LSQ_COOKIE_RE (1 << 3)
49 #define JUNIPER_LSQ_COOKIE_DIR (1 << 2)
50 #define JUNIPER_LSQ_L3_PROTO_SHIFT 4
51 #define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
52 #define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
53 #define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
54 #define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
55 #define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
56 #define AS_PIC_COOKIE_LEN 8
57
58 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
59 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
60 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
61 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
62 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
63
64 static struct tok juniper_ipsec_type_values[] = {
65 { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
66 { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
67 { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
68 { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
69 { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
70 { 0, NULL}
71 };
72
73 static struct tok juniper_direction_values[] = {
74 { JUNIPER_BPF_IN, "In"},
75 { JUNIPER_BPF_OUT, "Out"},
76 { 0, NULL}
77 };
78
79 /* codepoints for encoding extensions to a .pcap file */
80 enum {
81 JUNIPER_EXT_TLV_IFD_IDX = 1,
82 JUNIPER_EXT_TLV_IFD_NAME = 2,
83 JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3,
84 JUNIPER_EXT_TLV_IFL_IDX = 4,
85 JUNIPER_EXT_TLV_IFL_UNIT = 5,
86 JUNIPER_EXT_TLV_IFL_ENCAPS = 6,
87 JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7,
88 JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8
89 };
90
91 /* 1 byte type and 1-byte length */
92 #define JUNIPER_EXT_TLV_OVERHEAD 2
93
94 struct tok jnx_ext_tlv_values[] = {
95 { JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" },
96 { JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" },
97 { JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" },
98 { JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" },
99 { JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" },
100 { JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" },
101 { JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" },
102 { JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" },
103 { 0, NULL }
104 };
105
106 struct tok jnx_flag_values[] = {
107 { JUNIPER_BPF_EXT, "Ext" },
108 { JUNIPER_BPF_FILTER, "Filter" },
109 { JUNIPER_BPF_IIF, "IIF" },
110 { JUNIPER_BPF_NO_L2, "no-L2" },
111 { JUNIPER_BPF_PKT_IN, "In" },
112 { 0, NULL }
113 };
114
115 struct juniper_cookie_table_t {
116 u_int32_t pictype; /* pic type */
117 u_int8_t cookie_len; /* cookie len */
118 const char *s; /* pic name */
119 };
120
121 static struct juniper_cookie_table_t juniper_cookie_table[] = {
122 #ifdef DLT_JUNIPER_ATM1
123 { DLT_JUNIPER_ATM1, 4, "ATM1"},
124 #endif
125 #ifdef DLT_JUNIPER_ATM2
126 { DLT_JUNIPER_ATM2, 8, "ATM2"},
127 #endif
128 #ifdef DLT_JUNIPER_MLPPP
129 { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
130 #endif
131 #ifdef DLT_JUNIPER_MLFR
132 { DLT_JUNIPER_MLFR, 2, "MLFR"},
133 #endif
134 #ifdef DLT_JUNIPER_MFR
135 { DLT_JUNIPER_MFR, 4, "MFR"},
136 #endif
137 #ifdef DLT_JUNIPER_PPPOE
138 { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
139 #endif
140 #ifdef DLT_JUNIPER_PPPOE_ATM
141 { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
142 #endif
143 #ifdef DLT_JUNIPER_GGSN
144 { DLT_JUNIPER_GGSN, 8, "GGSN"},
145 #endif
146 #ifdef DLT_JUNIPER_MONITOR
147 { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
148 #endif
149 #ifdef DLT_JUNIPER_SERVICES
150 { DLT_JUNIPER_SERVICES, 8, "AS"},
151 #endif
152 #ifdef DLT_JUNIPER_ES
153 { DLT_JUNIPER_ES, 0, "ES"},
154 #endif
155 { 0, 0, NULL }
156 };
157
158 struct juniper_l2info_t {
159 u_int32_t length;
160 u_int32_t caplen;
161 u_int32_t pictype;
162 u_int8_t direction;
163 u_int8_t header_len;
164 u_int8_t cookie_len;
165 u_int8_t cookie_type;
166 u_int8_t cookie[8];
167 u_int8_t bundle;
168 u_int16_t proto;
169 u_int8_t flags;
170 };
171
172 #define LS_COOKIE_ID 0x54
173 #define AS_COOKIE_ID 0x47
174 #define LS_MLFR_COOKIE_LEN 4
175 #define ML_MLFR_COOKIE_LEN 2
176 #define LS_MFR_COOKIE_LEN 6
177 #define ATM1_COOKIE_LEN 4
178 #define ATM2_COOKIE_LEN 8
179
180 #define ATM2_PKT_TYPE_MASK 0x70
181 #define ATM2_GAP_COUNT_MASK 0x3F
182
183 #define JUNIPER_PROTO_NULL 1
184 #define JUNIPER_PROTO_IPV4 2
185 #define JUNIPER_PROTO_IPV6 6
186
187 #define MFR_BE_MASK 0xc0
188
189 static struct tok juniper_protocol_values[] = {
190 { JUNIPER_PROTO_NULL, "Null" },
191 { JUNIPER_PROTO_IPV4, "IPv4" },
192 { JUNIPER_PROTO_IPV6, "IPv6" },
193 { 0, NULL}
194 };
195
196 int ip_heuristic_guess(register const u_char *, u_int);
197 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
198 int juniper_read_tlv_value(const u_char *, u_int, u_int);
199 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
200
201 #ifdef DLT_JUNIPER_GGSN
202 u_int
203 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
204 {
205 struct juniper_l2info_t l2info;
206 struct juniper_ggsn_header {
207 u_int8_t svc_id;
208 u_int8_t flags_len;
209 u_int8_t proto;
210 u_int8_t flags;
211 u_int8_t vlan_id[2];
212 u_int8_t res[2];
213 };
214 const struct juniper_ggsn_header *gh;
215
216 l2info.pictype = DLT_JUNIPER_GGSN;
217 if(juniper_parse_header(p, h, &l2info) == 0)
218 return l2info.header_len;
219
220 p+=l2info.header_len;
221 gh = (struct juniper_ggsn_header *)p;
222
223 if (eflag)
224 printf("proto %s (%u), vlan %u: ",
225 tok2str(juniper_protocol_values,"Unknown",gh->proto),
226 gh->proto,
227 EXTRACT_16BITS(&gh->vlan_id[0]));
228
229 switch (gh->proto) {
230 case JUNIPER_PROTO_IPV4:
231 ip_print(gndo, p, l2info.length);
232 break;
233 #ifdef INET6
234 case JUNIPER_PROTO_IPV6:
235 ip6_print(p, l2info.length);
236 break;
237 #endif /* INET6 */
238 default:
239 if (!eflag)
240 printf("unknown GGSN proto (%u)", gh->proto);
241 }
242
243 return l2info.header_len;
244 }
245 #endif
246
247 #ifdef DLT_JUNIPER_ES
248 u_int
249 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
250 {
251 struct juniper_l2info_t l2info;
252 struct juniper_ipsec_header {
253 u_int8_t sa_index[2];
254 u_int8_t ttl;
255 u_int8_t type;
256 u_int8_t spi[4];
257 u_int8_t src_ip[4];
258 u_int8_t dst_ip[4];
259 };
260 u_int rewrite_len,es_type_bundle;
261 const struct juniper_ipsec_header *ih;
262
263 l2info.pictype = DLT_JUNIPER_ES;
264 if(juniper_parse_header(p, h, &l2info) == 0)
265 return l2info.header_len;
266
267 p+=l2info.header_len;
268 ih = (struct juniper_ipsec_header *)p;
269
270 switch (ih->type) {
271 case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
272 case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
273 rewrite_len = 0;
274 es_type_bundle = 1;
275 break;
276 case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
277 case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
278 case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
279 rewrite_len = 16;
280 es_type_bundle = 0;
281 default:
282 printf("ES Invalid type %u, length %u",
283 ih->type,
284 l2info.length);
285 return l2info.header_len;
286 }
287
288 l2info.length-=rewrite_len;
289 p+=rewrite_len;
290
291 if (eflag) {
292 if (!es_type_bundle) {
293 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
294 EXTRACT_16BITS(&ih->sa_index),
295 ih->ttl,
296 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
297 ih->type,
298 EXTRACT_32BITS(&ih->spi),
299 ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
300 ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
301 l2info.length);
302 } else {
303 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
304 EXTRACT_16BITS(&ih->sa_index),
305 ih->ttl,
306 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
307 ih->type,
308 l2info.length);
309 }
310 }
311
312 ip_print(gndo, p, l2info.length);
313 return l2info.header_len;
314 }
315 #endif
316
317 #ifdef DLT_JUNIPER_MONITOR
318 u_int
319 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
320 {
321 struct juniper_l2info_t l2info;
322 struct juniper_monitor_header {
323 u_int8_t pkt_type;
324 u_int8_t padding;
325 u_int8_t iif[2];
326 u_int8_t service_id[4];
327 };
328 const struct juniper_monitor_header *mh;
329
330 l2info.pictype = DLT_JUNIPER_MONITOR;
331 if(juniper_parse_header(p, h, &l2info) == 0)
332 return l2info.header_len;
333
334 p+=l2info.header_len;
335 mh = (struct juniper_monitor_header *)p;
336
337 if (eflag)
338 printf("service-id %u, iif %u, pkt-type %u: ",
339 EXTRACT_32BITS(&mh->service_id),
340 EXTRACT_16BITS(&mh->iif),
341 mh->pkt_type);
342
343 /* no proto field - lets guess by first byte of IP header*/
344 ip_heuristic_guess(p, l2info.length);
345
346 return l2info.header_len;
347 }
348 #endif
349
350 #ifdef DLT_JUNIPER_SERVICES
351 u_int
352 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
353 {
354 struct juniper_l2info_t l2info;
355 struct juniper_services_header {
356 u_int8_t svc_id;
357 u_int8_t flags_len;
358 u_int8_t svc_set_id[2];
359 u_int8_t dir_iif[4];
360 };
361 const struct juniper_services_header *sh;
362
363 l2info.pictype = DLT_JUNIPER_SERVICES;
364 if(juniper_parse_header(p, h, &l2info) == 0)
365 return l2info.header_len;
366
367 p+=l2info.header_len;
368 sh = (struct juniper_services_header *)p;
369
370 if (eflag)
371 printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
372 sh->svc_id,
373 sh->flags_len,
374 EXTRACT_16BITS(&sh->svc_set_id),
375 EXTRACT_24BITS(&sh->dir_iif[1]));
376
377 /* no proto field - lets guess by first byte of IP header*/
378 ip_heuristic_guess(p, l2info.length);
379
380 return l2info.header_len;
381 }
382 #endif
383
384 #ifdef DLT_JUNIPER_PPPOE
385 u_int
386 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
387 {
388 struct juniper_l2info_t l2info;
389
390 l2info.pictype = DLT_JUNIPER_PPPOE;
391 if(juniper_parse_header(p, h, &l2info) == 0)
392 return l2info.header_len;
393
394 p+=l2info.header_len;
395 /* this DLT contains nothing but raw ethernet frames */
396 ether_print(p, l2info.length, l2info.caplen);
397 return l2info.header_len;
398 }
399 #endif
400
401 #ifdef DLT_JUNIPER_ETHER
402 u_int
403 juniper_ether_print(const struct pcap_pkthdr *h, register const u_char *p)
404 {
405 struct juniper_l2info_t l2info;
406
407 l2info.pictype = DLT_JUNIPER_ETHER;
408 if(juniper_parse_header(p, h, &l2info) == 0)
409 return l2info.header_len;
410
411 p+=l2info.header_len;
412 /* this DLT contains nothing but raw Ethernet frames */
413 ether_print(p, l2info.length, l2info.caplen);
414 return l2info.header_len;
415 }
416 #endif
417
418 #ifdef DLT_JUNIPER_PPP
419 u_int
420 juniper_ppp_print(const struct pcap_pkthdr *h, register const u_char *p)
421 {
422 struct juniper_l2info_t l2info;
423
424 l2info.pictype = DLT_JUNIPER_PPP;
425 if(juniper_parse_header(p, h, &l2info) == 0)
426 return l2info.header_len;
427
428 p+=l2info.header_len;
429 /* this DLT contains nothing but raw ppp frames */
430 ppp_print(p, l2info.length);
431 return l2info.header_len;
432 }
433 #endif
434
435 #ifdef DLT_JUNIPER_FRELAY
436 u_int
437 juniper_frelay_print(const struct pcap_pkthdr *h, register const u_char *p)
438 {
439 struct juniper_l2info_t l2info;
440
441 l2info.pictype = DLT_JUNIPER_FRELAY;
442 if(juniper_parse_header(p, h, &l2info) == 0)
443 return l2info.header_len;
444
445 p+=l2info.header_len;
446 /* this DLT contains nothing but raw frame-relay frames */
447 fr_print(p, l2info.length);
448 return l2info.header_len;
449 }
450 #endif
451
452 #ifdef DLT_JUNIPER_CHDLC
453 u_int
454 juniper_chdlc_print(const struct pcap_pkthdr *h, register const u_char *p)
455 {
456 struct juniper_l2info_t l2info;
457
458 l2info.pictype = DLT_JUNIPER_CHDLC;
459 if(juniper_parse_header(p, h, &l2info) == 0)
460 return l2info.header_len;
461
462 p+=l2info.header_len;
463 /* this DLT contains nothing but raw c-hdlc frames */
464 chdlc_print(p, l2info.length);
465 return l2info.header_len;
466 }
467 #endif
468
469 #ifdef DLT_JUNIPER_PPPOE_ATM
470 u_int
471 juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
472 {
473 struct juniper_l2info_t l2info;
474 u_int16_t extracted_ethertype;
475
476 l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
477 if(juniper_parse_header(p, h, &l2info) == 0)
478 return l2info.header_len;
479
480 p+=l2info.header_len;
481
482 extracted_ethertype = EXTRACT_16BITS(p);
483 /* this DLT contains nothing but raw PPPoE frames,
484 * prepended with a type field*/
485 if (ether_encap_print(extracted_ethertype,
486 p+ETHERTYPE_LEN,
487 l2info.length-ETHERTYPE_LEN,
488 l2info.caplen-ETHERTYPE_LEN,
489 &extracted_ethertype) == 0)
490 /* ether_type not known, probably it wasn't one */
491 printf("unknown ethertype 0x%04x", extracted_ethertype);
492
493 return l2info.header_len;
494 }
495 #endif
496
497 #ifdef DLT_JUNIPER_MLPPP
498 u_int
499 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
500 {
501 struct juniper_l2info_t l2info;
502
503 l2info.pictype = DLT_JUNIPER_MLPPP;
504 if(juniper_parse_header(p, h, &l2info) == 0)
505 return l2info.header_len;
506
507 /* suppress Bundle-ID if frame was captured on a child-link
508 * best indicator if the cookie looks like a proto */
509 if (eflag &&
510 EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
511 EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
512 printf("Bundle-ID %u: ",l2info.bundle);
513
514 p+=l2info.header_len;
515
516 /* first try the LSQ protos */
517 switch(l2info.proto) {
518 case JUNIPER_LSQ_L3_PROTO_IPV4:
519 /* IP traffic going to the RE would not have a cookie
520 * -> this must be incoming IS-IS over PPP
521 */
522 if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
523 ppp_print(p, l2info.length);
524 else
525 ip_print(gndo, p, l2info.length);
526 return l2info.header_len;
527 #ifdef INET6
528 case JUNIPER_LSQ_L3_PROTO_IPV6:
529 ip6_print(p,l2info.length);
530 return l2info.header_len;
531 #endif
532 case JUNIPER_LSQ_L3_PROTO_MPLS:
533 mpls_print(p,l2info.length);
534 return l2info.header_len;
535 case JUNIPER_LSQ_L3_PROTO_ISO:
536 isoclns_print(p,l2info.length,l2info.caplen);
537 return l2info.header_len;
538 default:
539 break;
540 }
541
542 /* zero length cookie ? */
543 switch (EXTRACT_16BITS(&l2info.cookie)) {
544 case PPP_OSI:
545 ppp_print(p-2,l2info.length+2);
546 break;
547 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
548 default:
549 ppp_print(p,l2info.length);
550 break;
551 }
552
553 return l2info.header_len;
554 }
555 #endif
556
557
558 #ifdef DLT_JUNIPER_MFR
559 u_int
560 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
561 {
562 struct juniper_l2info_t l2info;
563
564 l2info.pictype = DLT_JUNIPER_MFR;
565 if(juniper_parse_header(p, h, &l2info) == 0)
566 return l2info.header_len;
567
568 p+=l2info.header_len;
569
570 /* child-link ? */
571 if (l2info.cookie_len == 0) {
572 mfr_print(p,l2info.length);
573 return l2info.header_len;
574 }
575
576 /* first try the LSQ protos */
577 if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
578 switch(l2info.proto) {
579 case JUNIPER_LSQ_L3_PROTO_IPV4:
580 ip_print(gndo, p, l2info.length);
581 return l2info.header_len;
582 #ifdef INET6
583 case JUNIPER_LSQ_L3_PROTO_IPV6:
584 ip6_print(p,l2info.length);
585 return l2info.header_len;
586 #endif
587 case JUNIPER_LSQ_L3_PROTO_MPLS:
588 mpls_print(p,l2info.length);
589 return l2info.header_len;
590 case JUNIPER_LSQ_L3_PROTO_ISO:
591 isoclns_print(p,l2info.length,l2info.caplen);
592 return l2info.header_len;
593 default:
594 break;
595 }
596 return l2info.header_len;
597 }
598
599 /* suppress Bundle-ID if frame was captured on a child-link */
600 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
601 switch (l2info.proto) {
602 case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
603 isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
604 break;
605 case (LLC_UI<<8 | NLPID_Q933):
606 case (LLC_UI<<8 | NLPID_IP):
607 case (LLC_UI<<8 | NLPID_IP6):
608 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
609 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
610 break;
611 default:
612 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
613 }
614
615 return l2info.header_len;
616 }
617 #endif
618
619 #ifdef DLT_JUNIPER_MLFR
620 u_int
621 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
622 {
623 struct juniper_l2info_t l2info;
624
625 l2info.pictype = DLT_JUNIPER_MLFR;
626 if(juniper_parse_header(p, h, &l2info) == 0)
627 return l2info.header_len;
628
629 p+=l2info.header_len;
630
631 /* suppress Bundle-ID if frame was captured on a child-link */
632 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
633 switch (l2info.proto) {
634 case (LLC_UI):
635 case (LLC_UI<<8):
636 isoclns_print(p, l2info.length, l2info.caplen);
637 break;
638 case (LLC_UI<<8 | NLPID_Q933):
639 case (LLC_UI<<8 | NLPID_IP):
640 case (LLC_UI<<8 | NLPID_IP6):
641 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
642 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
643 break;
644 default:
645 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
646 }
647
648 return l2info.header_len;
649 }
650 #endif
651
652 /*
653 * ATM1 PIC cookie format
654 *
655 * +-----+-------------------------+-------------------------------+
656 * |fmtid| vc index | channel ID |
657 * +-----+-------------------------+-------------------------------+
658 */
659
660 #ifdef DLT_JUNIPER_ATM1
661 u_int
662 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
663 {
664 u_int16_t extracted_ethertype;
665
666 struct juniper_l2info_t l2info;
667
668 l2info.pictype = DLT_JUNIPER_ATM1;
669 if(juniper_parse_header(p, h, &l2info) == 0)
670 return l2info.header_len;
671
672 p+=l2info.header_len;
673
674 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
675 oam_print(p,l2info.length,ATM_OAM_NOHEC);
676 return l2info.header_len;
677 }
678
679 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
680 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
681
682 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
683 &extracted_ethertype) != 0)
684 return l2info.header_len;
685 }
686
687 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
688 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
689 /* FIXME check if frame was recognized */
690 return l2info.header_len;
691 }
692
693 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
694 return l2info.header_len;
695
696 return l2info.header_len;
697 }
698 #endif
699
700 /*
701 * ATM2 PIC cookie format
702 *
703 * +-------------------------------+---------+---+-----+-----------+
704 * | channel ID | reserv |AAL| CCRQ| gap cnt |
705 * +-------------------------------+---------+---+-----+-----------+
706 */
707
708 #ifdef DLT_JUNIPER_ATM2
709 u_int
710 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
711 {
712 u_int16_t extracted_ethertype;
713
714 struct juniper_l2info_t l2info;
715
716 l2info.pictype = DLT_JUNIPER_ATM2;
717 if(juniper_parse_header(p, h, &l2info) == 0)
718 return l2info.header_len;
719
720 p+=l2info.header_len;
721
722 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
723 oam_print(p,l2info.length,ATM_OAM_NOHEC);
724 return l2info.header_len;
725 }
726
727 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
728 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
729
730 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
731 &extracted_ethertype) != 0)
732 return l2info.header_len;
733 }
734
735 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
736 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
737 ether_print(p, l2info.length, l2info.caplen);
738 return l2info.header_len;
739 }
740
741 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
742 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
743 /* FIXME check if frame was recognized */
744 return l2info.header_len;
745 }
746
747 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
748 return l2info.header_len;
749
750 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
751 return l2info.header_len;
752
753 return l2info.header_len;
754 }
755 #endif
756
757
758 /* try to guess, based on all PPP protos that are supported in
759 * a juniper router if the payload data is encapsulated using PPP */
760 int
761 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
762
763 switch(EXTRACT_16BITS(p)) {
764 case PPP_IP :
765 case PPP_OSI :
766 case PPP_MPLS_UCAST :
767 case PPP_MPLS_MCAST :
768 case PPP_IPCP :
769 case PPP_OSICP :
770 case PPP_MPLSCP :
771 case PPP_LCP :
772 case PPP_PAP :
773 case PPP_CHAP :
774 case PPP_ML :
775 #ifdef INET6
776 case PPP_IPV6 :
777 case PPP_IPV6CP :
778 #endif
779 ppp_print(p, length);
780 break;
781
782 default:
783 return 0; /* did not find a ppp header */
784 break;
785 }
786 return 1; /* we printed a ppp packet */
787 }
788
789 int
790 ip_heuristic_guess(register const u_char *p, u_int length) {
791
792 switch(p[0]) {
793 case 0x45:
794 case 0x46:
795 case 0x47:
796 case 0x48:
797 case 0x49:
798 case 0x4a:
799 case 0x4b:
800 case 0x4c:
801 case 0x4d:
802 case 0x4e:
803 case 0x4f:
804 ip_print(gndo, p, length);
805 break;
806 #ifdef INET6
807 case 0x60:
808 case 0x61:
809 case 0x62:
810 case 0x63:
811 case 0x64:
812 case 0x65:
813 case 0x66:
814 case 0x67:
815 case 0x68:
816 case 0x69:
817 case 0x6a:
818 case 0x6b:
819 case 0x6c:
820 case 0x6d:
821 case 0x6e:
822 case 0x6f:
823 ip6_print(p, length);
824 break;
825 #endif
826 default:
827 return 0; /* did not find a ip header */
828 break;
829 }
830 return 1; /* we printed an v4/v6 packet */
831 }
832
833 int
834 juniper_read_tlv_value(const u_char *p, u_int tlv_type, u_int tlv_len) {
835
836 int tlv_value;
837
838 /* TLVs < 128 are little endian encoded */
839 if (tlv_type < 128) {
840 switch (tlv_len) {
841 case 1:
842 tlv_value = *p;
843 break;
844 case 2:
845 tlv_value = EXTRACT_LE_16BITS(p);
846 break;
847 case 3:
848 tlv_value = EXTRACT_LE_24BITS(p);
849 break;
850 case 4:
851 tlv_value = EXTRACT_LE_32BITS(p);
852 break;
853 default:
854 tlv_value = -1;
855 break;
856 }
857 } else {
858 /* TLVs >= 128 are big endian encoded */
859 switch (tlv_len) {
860 case 1:
861 tlv_value = *p;
862 break;
863 case 2:
864 tlv_value = EXTRACT_16BITS(p);
865 break;
866 case 3:
867 tlv_value = EXTRACT_24BITS(p);
868 break;
869 case 4:
870 tlv_value = EXTRACT_32BITS(p);
871 break;
872 default:
873 tlv_value = -1;
874 break;
875 }
876 }
877 return tlv_value;
878 }
879
880 static int
881 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
882
883 struct juniper_cookie_table_t *lp = juniper_cookie_table;
884 u_int idx, jnx_ext_len, jnx_header_len = 0;
885 u_int8_t tlv_type,tlv_len;
886 u_int32_t control_word;
887 int tlv_value;
888 const u_char *tptr;
889
890
891 l2info->header_len = 0;
892 l2info->cookie_len = 0;
893 l2info->proto = 0;
894
895
896 l2info->length = h->len;
897 l2info->caplen = h->caplen;
898 TCHECK2(p[0],4);
899 l2info->flags = p[3];
900 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
901
902 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
903 printf("no magic-number found!");
904 return 0;
905 }
906
907 if (eflag) /* print direction */
908 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
909
910 /* magic number + flags */
911 jnx_header_len = 4;
912
913 if (vflag>1)
914 printf("\n\tJuniper PCAP Flags [%s]",
915 bittok2str(jnx_flag_values, "none", l2info->flags));
916
917 /* extensions present ? - calculate how much bytes to skip */
918 if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
919
920 tptr = p+jnx_header_len;
921
922 /* ok to read extension length ? */
923 TCHECK2(tptr[0], 2);
924 jnx_ext_len = EXTRACT_16BITS(tptr);
925 jnx_header_len += 2;
926 tptr +=2;
927
928 /* nail up the total length -
929 * just in case something goes wrong
930 * with TLV parsing */
931 jnx_header_len += jnx_ext_len;
932
933 if (vflag>1)
934 printf(", PCAP Extension(s) total length %u",
935 jnx_ext_len);
936
937 TCHECK2(tptr[0], jnx_ext_len);
938 while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) {
939 tlv_type = *(tptr++);
940 tlv_len = *(tptr++);
941 tlv_value = 0;
942
943 /* sanity check */
944 if (tlv_type == 0 || tlv_len == 0)
945 break;
946
947 if (vflag>1)
948 printf("\n\t %s Extension TLV #%u, length %u, value ",
949 tok2str(jnx_ext_tlv_values,"Unknown",tlv_type),
950 tlv_type,
951 tlv_len);
952
953 tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len);
954 switch (tlv_type) {
955 case JUNIPER_EXT_TLV_IFD_NAME:
956 /* FIXME */
957 break;
958
959 case JUNIPER_EXT_TLV_IFD_MEDIATYPE: /* fall through */
960 case JUNIPER_EXT_TLV_IFL_ENCAPS:
961 case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE:
962 case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS:
963 case JUNIPER_EXT_TLV_IFL_IDX:
964 case JUNIPER_EXT_TLV_IFL_UNIT:
965 case JUNIPER_EXT_TLV_IFD_IDX:
966 default:
967 if (tlv_value != -1) {
968 if (vflag>1)
969 printf("%u",tlv_value);
970 }
971 break;
972 }
973
974 tptr+=tlv_len;
975 jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD;
976 }
977
978 if (vflag>1)
979 printf("\n\t-----original packet-----\n\t");
980 }
981
982 if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
983 if (eflag)
984 printf("no-L2-hdr, ");
985
986 /* there is no link-layer present -
987 * perform the v4/v6 heuristics
988 * to figure out what it is
989 */
990 TCHECK2(p[jnx_header_len+4],1);
991 if(ip_heuristic_guess(p+jnx_header_len+4,l2info->length-(jnx_header_len+4)) == 0)
992 printf("no IP-hdr found!");
993
994 l2info->header_len=jnx_header_len+4;
995 return 0; /* stop parsing the output further */
996
997 }
998 l2info->header_len = jnx_header_len;
999 p+=l2info->header_len;
1000 l2info->length -= l2info->header_len;
1001 l2info->caplen -= l2info->header_len;
1002
1003 /* search through the cookie table and copy values matching for our PIC type */
1004 while (lp->s != NULL) {
1005 if (lp->pictype == l2info->pictype) {
1006
1007 l2info->cookie_len += lp->cookie_len;
1008
1009 switch (p[0]) {
1010 case LS_COOKIE_ID:
1011 l2info->cookie_type = LS_COOKIE_ID;
1012 l2info->cookie_len += 2;
1013 break;
1014 case AS_COOKIE_ID:
1015 l2info->cookie_type = AS_COOKIE_ID;
1016 l2info->cookie_len = 8;
1017 break;
1018
1019 default:
1020 l2info->bundle = l2info->cookie[0];
1021 break;
1022 }
1023
1024
1025 #ifdef DLT_JUNIPER_MFR
1026 /* MFR child links don't carry cookies */
1027 if (l2info->pictype == DLT_JUNIPER_MFR &&
1028 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
1029 l2info->cookie_len = 0;
1030 }
1031 #endif
1032
1033 l2info->header_len += l2info->cookie_len;
1034 l2info->length -= l2info->cookie_len;
1035 l2info->caplen -= l2info->cookie_len;
1036
1037 if (eflag)
1038 printf("%s-PIC, cookie-len %u",
1039 lp->s,
1040 l2info->cookie_len);
1041
1042 if (l2info->cookie_len > 0) {
1043 TCHECK2(p[0],l2info->cookie_len);
1044 if (eflag)
1045 printf(", cookie 0x");
1046 for (idx = 0; idx < l2info->cookie_len; idx++) {
1047 l2info->cookie[idx] = p[idx]; /* copy cookie data */
1048 if (eflag) printf("%02x",p[idx]);
1049 }
1050 }
1051
1052 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
1053
1054
1055 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
1056 break;
1057 }
1058 ++lp;
1059 }
1060 p+=l2info->cookie_len;
1061
1062 /* DLT_ specific parsing */
1063 switch(l2info->pictype) {
1064 #ifdef DLT_JUNIPER_MLPPP
1065 case DLT_JUNIPER_MLPPP:
1066 switch (l2info->cookie_type) {
1067 case LS_COOKIE_ID:
1068 l2info->bundle = l2info->cookie[1];
1069 break;
1070 case AS_COOKIE_ID:
1071 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
1072 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
1073 break;
1074 default:
1075 l2info->bundle = l2info->cookie[0];
1076 break;
1077 }
1078 break;
1079 #endif
1080 #ifdef DLT_JUNIPER_MLFR
1081 case DLT_JUNIPER_MLFR:
1082 switch (l2info->cookie_type) {
1083 case LS_COOKIE_ID:
1084 l2info->bundle = l2info->cookie[1];
1085 l2info->proto = EXTRACT_16BITS(p);
1086 l2info->header_len += 2;
1087 l2info->length -= 2;
1088 l2info->caplen -= 2;
1089 break;
1090 case AS_COOKIE_ID:
1091 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
1092 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
1093 break;
1094 default:
1095 l2info->bundle = l2info->cookie[0];
1096 l2info->header_len += 2;
1097 l2info->length -= 2;
1098 l2info->caplen -= 2;
1099 break;
1100 }
1101 break;
1102 #endif
1103 #ifdef DLT_JUNIPER_MFR
1104 case DLT_JUNIPER_MFR:
1105 switch (l2info->cookie_type) {
1106 case LS_COOKIE_ID:
1107 l2info->bundle = l2info->cookie[1];
1108 l2info->proto = EXTRACT_16BITS(p);
1109 l2info->header_len += 2;
1110 l2info->length -= 2;
1111 l2info->caplen -= 2;
1112 break;
1113 case AS_COOKIE_ID:
1114 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
1115 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
1116 break;
1117 default:
1118 l2info->bundle = l2info->cookie[0];
1119 break;
1120 }
1121 break;
1122 #endif
1123 #ifdef DLT_JUNIPER_ATM2
1124 case DLT_JUNIPER_ATM2:
1125 TCHECK2(p[0],4);
1126 /* ATM cell relay control word present ? */
1127 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
1128 control_word = EXTRACT_32BITS(p);
1129 /* some control word heuristics */
1130 switch(control_word) {
1131 case 0: /* zero control word */
1132 case 0x08000000: /* < JUNOS 7.4 control-word */
1133 case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
1134 l2info->header_len += 4;
1135 break;
1136 default:
1137 break;
1138 }
1139
1140 if (eflag)
1141 printf("control-word 0x%08x ", control_word);
1142 }
1143 break;
1144 #endif
1145 #ifdef DLT_JUNIPER_ATM1
1146 case DLT_JUNIPER_ATM1:
1147 break;
1148 #endif
1149 #ifdef DLT_JUNIPER_PPP
1150 case DLT_JUNIPER_PPP:
1151 break;
1152 #endif
1153 #ifdef DLT_JUNIPER_CHDLC
1154 case DLT_JUNIPER_CHDLC:
1155 break;
1156 #endif
1157 #ifdef DLT_JUNIPER_ETHER
1158 case DLT_JUNIPER_ETHER:
1159 break;
1160 #endif
1161 #ifdef DLT_JUNIPER_FRELAY
1162 case DLT_JUNIPER_FRELAY:
1163 break;
1164 #endif
1165
1166 default:
1167 printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
1168 break;
1169 }
1170
1171 if (eflag > 1)
1172 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
1173
1174 return 1; /* everything went ok so far. continue parsing */
1175 trunc:
1176 printf("[|juniper_hdr], length %u",h->len);
1177 return 0;
1178 }
1179
1180
1181 /*
1182 * Local Variables:
1183 * c-style: whitesmith
1184 * c-basic-offset: 4
1185 * End:
1186 */