Import of tcpdump 3.8.3
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-gre.c
1 /*      $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $     */
2
3 /*
4  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Jason L. Wright
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*
35  * tcpdump filter for GRE - Generic Routing Encapsulation
36  * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
37  */
38
39 #ifndef lint
40 static const char rcsid[] _U_ =
41     "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.22.2.2 2003/11/16 08:51:24 guy Exp $ (LBL)";
42 #endif
43
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include <tcpdump-stdinc.h>
49
50 #include <stdio.h>
51 #include <string.h>
52
53 #include "interface.h"
54 #include "addrtoname.h"
55 #include "extract.h"
56
57 #include "ip.h"
58
59 #define GRE_CP          0x8000          /* checksum present */
60 #define GRE_RP          0x4000          /* routing present */
61 #define GRE_KP          0x2000          /* key present */
62 #define GRE_SP          0x1000          /* sequence# present */
63 #define GRE_sP          0x0800          /* source routing */
64 #define GRE_RECRS       0x0700          /* recursion count */
65 #define GRE_AP          0x0080          /* acknowledgment# present */
66 #define GRE_VERS        0x0007          /* protocol version */
67
68 #define GREPROTO_IP     0x0800          /* IP */
69 #define GREPROTO_PPP    0x880b          /* PPTP */
70 #define GREPROTO_ISO    0x00fe          /* OSI */
71
72 /* source route entry types */
73 #define GRESRE_IP       0x0800          /* IP */
74 #define GRESRE_ASN      0xfffe          /* ASN */
75
76 void gre_print_0(const u_char *, u_int);
77 void gre_print_1(const u_char *, u_int);
78 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int);
79 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int);
80 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int);
81
82 void
83 gre_print(const u_char *bp, u_int length)
84 {
85         u_int len = length, vers;
86
87         if (len < 2) {
88                 printf("[|gre]");
89                 return;
90         }
91         vers = EXTRACT_16BITS(bp) & 7;
92
93         if (vers == 0)
94                 gre_print_0(bp, len);
95         else if (vers == 1)
96                 gre_print_1(bp, len);
97         else
98                 printf("gre-unknown-version=%u", vers);
99         return;
100
101 }
102
103 void
104 gre_print_0(const u_char *bp, u_int length)
105 {
106         u_int len = length;
107         u_int16_t flags, prot;
108
109         flags = EXTRACT_16BITS(bp);
110         if (vflag) {
111                 printf("[%s%s%s%s%s] ",
112                     (flags & GRE_CP) ? "C" : "",
113                     (flags & GRE_RP) ? "R" : "",
114                     (flags & GRE_KP) ? "K" : "",
115                     (flags & GRE_SP) ? "S" : "",
116                     (flags & GRE_sP) ? "s" : "");
117         }
118
119         len -= 2;
120         bp += 2;
121
122         if (len < 2)
123                 goto trunc;
124         prot = EXTRACT_16BITS(bp);
125         len -= 2;
126         bp += 2;
127
128         if ((flags & GRE_CP) | (flags & GRE_RP)) {
129                 if (len < 2)
130                         goto trunc;
131                 if (vflag)
132                         printf("sum 0x%x ", EXTRACT_16BITS(bp));
133                 bp += 2;
134                 len -= 2;
135
136                 if (len < 2)
137                         goto trunc;
138                 printf("off 0x%x ", EXTRACT_16BITS(bp));
139                 bp += 2;
140                 len -= 2;
141         }
142
143         if (flags & GRE_KP) {
144                 if (len < 4)
145                         goto trunc;
146                 printf("key=0x%x ", EXTRACT_32BITS(bp));
147                 bp += 4;
148                 len -= 4;
149         }
150
151         if (flags & GRE_SP) {
152                 if (len < 4)
153                         goto trunc;
154                 printf("seq %u ", EXTRACT_32BITS(bp));
155                 bp += 4;
156                 len -= 4;
157         }
158
159         if (flags & GRE_RP) {
160                 for (;;) {
161                         u_int16_t af;
162                         u_int8_t sreoff;
163                         u_int8_t srelen;
164
165                         if (len < 4)
166                                 goto trunc;
167                         af = EXTRACT_16BITS(bp);
168                         sreoff = *(bp + 2);
169                         srelen = *(bp + 3);
170                         bp += 4;
171                         len -= 4;
172
173                         if (af == 0 && srelen == 0)
174                                 break;
175
176                         gre_sre_print(af, sreoff, srelen, bp, len);
177
178                         if (len < srelen)
179                                 goto trunc;
180                         bp += srelen;
181                         len -= srelen;
182                 }
183         }
184
185         switch (prot) {
186         case GREPROTO_IP:
187                 ip_print(bp, len);
188                 break;
189         case GREPROTO_ISO:
190                 isoclns_print(bp, len, len);
191                 break;
192         default:
193                 printf("gre-proto-0x%x", prot);
194         }
195         return;
196
197 trunc:
198         printf("[|gre]");
199 }
200
201 void
202 gre_print_1(const u_char *bp, u_int length)
203 {
204         u_int len = length;
205         u_int16_t flags, prot;
206
207         flags = EXTRACT_16BITS(bp);
208         len -= 2;
209         bp += 2;
210
211         if (vflag) {
212                 printf("[%s%s%s%s%s%s] ",
213                     (flags & GRE_CP) ? "C" : "",
214                     (flags & GRE_RP) ? "R" : "",
215                     (flags & GRE_KP) ? "K" : "",
216                     (flags & GRE_SP) ? "S" : "",
217                     (flags & GRE_sP) ? "s" : "",
218                     (flags & GRE_AP) ? "A" : "");
219         }
220
221         if (len < 2)
222                 goto trunc;
223         prot = EXTRACT_16BITS(bp);
224         len -= 2;
225         bp += 2;
226
227         if (flags & GRE_CP) {
228                 printf("cpset!");
229                 return;
230         }
231         if (flags & GRE_RP) {
232                 printf("rpset!");
233                 return;
234         }
235         if ((flags & GRE_KP) == 0) {
236                 printf("kpunset!");
237                 return;
238         }
239         if (flags & GRE_sP) {
240                 printf("spset!");
241                 return;
242         }
243
244         if (flags & GRE_KP) {
245                 u_int32_t k;
246
247                 if (len < 4)
248                         goto trunc;
249                 k = EXTRACT_32BITS(bp);
250                 printf("call %d ", k & 0xffff);
251                 len -= 4;
252                 bp += 4;
253         }
254
255         if (flags & GRE_SP) {
256                 if (len < 4)
257                         goto trunc;
258                 printf("seq %u ", EXTRACT_32BITS(bp));
259                 bp += 4;
260                 len -= 4;
261         }
262
263         if (flags & GRE_AP) {
264                 if (len < 4)
265                         goto trunc;
266                 printf("ack %u ", EXTRACT_32BITS(bp));
267                 bp += 4;
268                 len -= 4;
269         }
270
271         if ((flags & GRE_SP) == 0) {
272                 printf("no-payload");
273                 return;
274         }
275
276         switch (prot) {
277         case GREPROTO_PPP:
278                 printf("gre-ppp-payload");
279                 break;
280         default:
281                 printf("gre-proto-0x%x", prot);
282                 break;
283         }
284         return;
285
286 trunc:
287         printf("[|gre]");
288 }
289
290 void
291 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen,
292     const u_char *bp, u_int len)
293 {
294         switch (af) {
295         case GRESRE_IP:
296                 printf("(rtaf=ip");
297                 gre_sre_ip_print(sreoff, srelen, bp, len);
298                 printf(") ");
299                 break;
300         case GRESRE_ASN:
301                 printf("(rtaf=asn");
302                 gre_sre_asn_print(sreoff, srelen, bp, len);
303                 printf(") ");
304                 break;
305         default:
306                 printf("(rtaf=0x%x) ", af);
307         }
308 }
309 void
310 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
311 {
312         struct in_addr a;
313         const u_char *up = bp;
314
315         if (sreoff & 3) {
316                 printf(" badoffset=%u", sreoff);
317                 return;
318         }
319         if (srelen & 3) {
320                 printf(" badlength=%u", srelen);
321                 return;
322         }
323         if (sreoff >= srelen) {
324                 printf(" badoff/len=%u/%u", sreoff, srelen);
325                 return;
326         }
327
328         for (;;) {
329                 if (len < 4 || srelen == 0)
330                         return;
331
332                 memcpy(&a, bp, sizeof(a));
333                 printf(" %s%s",
334                     ((bp - up) == sreoff) ? "*" : "",
335                     inet_ntoa(a));
336
337                 bp += 4;
338                 len -= 4;
339                 srelen -= 4;
340         }
341 }
342
343 void
344 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
345 {
346         const u_char *up = bp;
347
348         if (sreoff & 1) {
349                 printf(" badoffset=%u", sreoff);
350                 return;
351         }
352         if (srelen & 1) {
353                 printf(" badlength=%u", srelen);
354                 return;
355         }
356         if (sreoff >= srelen) {
357                 printf(" badoff/len=%u/%u", sreoff, srelen);
358                 return;
359         }
360
361         for (;;) {
362                 if (len < 2 || srelen == 0)
363                         return;
364
365                 printf(" %s%x",
366                     ((bp - up) == sreoff) ? "*" : "",
367                     EXTRACT_16BITS(bp));
368
369                 bp += 2;
370                 len -= 2;
371                 srelen -= 2;
372         }
373 }