]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
If we print something as an OAM cell, we're done with it, so just return.
[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.4 2005-01-24 03:27:26 guy 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
34 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
35 #define JUNIPER_BPF_IN 1 /* Incoming packet */
36 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
37 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
38
39 #define ATM2_PKT_TYPE_MASK 0x70
40 #define ATM2_GAP_COUNT_MASK 0x3F
41
42 int ip_heuristic_guess(register const u_char *, u_int);
43 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
44 static int juniper_parse_header (const u_char *, u_int8_t *, u_int);
45
46 /*
47 * ATM1 PIC cookie format
48 *
49 * +-----+-------------------------+-------------------------------+
50 * |fmtid| vc index | channel ID |
51 * +-----+-------------------------+-------------------------------+
52 */
53
54 u_int
55 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
56 {
57 register u_int length = h->len;
58 register u_int caplen = h->caplen;
59 u_int16_t extracted_ethertype;
60 u_int8_t direction;
61 u_int32_t cookie1;
62
63 if(juniper_parse_header(p, &direction,length) == 0)
64 return 0;
65
66 p+=4;
67 length-=4;
68 caplen-=4;
69
70 cookie1=EXTRACT_32BITS(p);
71
72 if (eflag) {
73 /* FIXME decode channel-id, vc-index, fmt-id
74 for once lets just hexdump the cookie */
75
76 printf("ATM1 cookie 0x%08x, ", EXTRACT_32BITS(p));
77 }
78
79 p+=4;
80 length-=4;
81 caplen-=4;
82
83 if (cookie1 & 0x80000000) { /* OAM cell ? */
84 /* XXX - at least some packets are mis-identified as OAM
85 cells by this test */
86 oam_print(p,length);
87 return 0;
88 }
89
90 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
91 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
92
93 if (llc_print(p, length, caplen, NULL, NULL,
94 &extracted_ethertype) != 0)
95 return 8;
96 }
97
98 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
99 isoclns_print(p + 1, length - 1, caplen - 1);
100 /* FIXME check if frame was recognized */
101 return 8;
102 }
103
104 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
105 return 0;
106
107 return (8);
108 }
109
110 /*
111 * ATM2 PIC cookie format
112 *
113 * +-------------------------------+---------+---+-----+-----------+
114 * | channel ID | reserv |AAL| CCRQ| gap cnt |
115 * +-------------------------------+---------+---+-----+-----------+
116 */
117
118 u_int
119 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
120 {
121 register u_int length = h->len;
122 register u_int caplen = h->caplen;
123 u_int16_t extracted_ethertype;
124 u_int8_t direction;
125 u_int32_t cookie1,cookie2;
126
127 if(juniper_parse_header(p, &direction,length) == 0)
128 return 0;
129
130 p+=4;
131 length-=4;
132 caplen-=4;
133
134 cookie1=EXTRACT_32BITS(p);
135 cookie2=EXTRACT_32BITS(p+4);
136
137 if (eflag) {
138 /* FIXME decode channel, fmt-id, ccrq, aal, gap cnt
139 for once lets just hexdump the cookie */
140
141 printf("ATM2 cookie 0x%08x%08x, ",
142 EXTRACT_32BITS(p),
143 EXTRACT_32BITS(p+4));
144 }
145
146 p+=8;
147 length-=8;
148 caplen-=8;
149
150 if (cookie2 & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
151 oam_print(p,length);
152 return 12;
153 }
154
155 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
156 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
157
158 if (llc_print(p, length, caplen, NULL, NULL,
159 &extracted_ethertype) != 0)
160 return 12;
161 }
162
163 if (direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
164 (cookie1 & ATM2_GAP_COUNT_MASK)) {
165 ether_print(p, length, caplen);
166 return 12;
167 }
168
169 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
170 isoclns_print(p + 1, length - 1, caplen - 1);
171 /* FIXME check if frame was recognized */
172 return 12;
173 }
174
175 if(juniper_ppp_heuristic_guess(p, length) != 0) /* PPPoA vcmux encaps ? */
176 return 12;
177
178 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
179 return 12;
180
181 return (12);
182 }
183
184
185 /* try to guess, based on all PPP protos that are supported in
186 * a juniper router if the payload data is encapsulated using PPP */
187 int
188 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
189
190 switch(EXTRACT_16BITS(p)) {
191 case PPP_IP :
192 case PPP_OSI :
193 case PPP_MPLS_UCAST :
194 case PPP_MPLS_MCAST :
195 case PPP_IPCP :
196 case PPP_OSICP :
197 case PPP_MPLSCP :
198 case PPP_LCP :
199 case PPP_PAP :
200 case PPP_CHAP :
201 case PPP_ML :
202 #ifdef INET6
203 case PPP_IPV6 :
204 case PPP_IPV6CP :
205 #endif
206 ppp_print(p, length);
207 break;
208
209 default:
210 return 0; /* did not find a ppp header */
211 break;
212 }
213 return 1; /* we printed a ppp packet */
214 }
215
216 int
217 ip_heuristic_guess(register const u_char *p, u_int length) {
218
219 switch(p[0]) {
220 case 0x45:
221 case 0x46:
222 case 0x47:
223 case 0x48:
224 case 0x49:
225 case 0x4a:
226 case 0x4b:
227 case 0x4c:
228 case 0x4d:
229 case 0x4e:
230 case 0x4f:
231 ip_print(p, length);
232 break;
233 #ifdef INET6
234 case 0x60:
235 case 0x61:
236 case 0x62:
237 case 0x63:
238 case 0x64:
239 case 0x65:
240 case 0x66:
241 case 0x67:
242 case 0x68:
243 case 0x69:
244 case 0x6a:
245 case 0x6b:
246 case 0x6c:
247 case 0x6d:
248 case 0x6e:
249 case 0x6f:
250 ip6_print(p, length);
251 break;
252 #endif
253 default:
254 return 0; /* did not find a ip header */
255 break;
256 }
257 return 1; /* we printed an v4/v6 packet */
258 }
259
260 static int
261 juniper_parse_header (const u_char *p, u_int8_t *direction, u_int length) {
262
263 *direction = p[3]&JUNIPER_BPF_PKT_IN;
264
265 if (EXTRACT_24BITS(p) != 0x4d4743) /* magic number found ? */
266 return -1;
267
268 if (*direction == JUNIPER_BPF_PKT_IN) {
269 if (eflag)
270 printf("%3s ", "In");
271 }
272 else {
273 if (eflag)
274 printf("%3s ", "Out");
275 }
276
277 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
278 if (eflag)
279 printf("no-L2-hdr, ");
280
281 /* there is no link-layer present -
282 * perform the v4/v6 heuristics
283 * to figure out what it is
284 */
285 if(ip_heuristic_guess(p+8,length-8) == 0)
286 printf("no IP-hdr found!");
287
288 return 0; /* stop parsing the output further */
289
290 }
291 return 1; /* everything went ok so far. continue parsing */
292 }