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 #include <sys/cdefs.h> 40 #ifndef lint 41 #if 0 42 static const char rcsid[] _U_ = 43 "@(#) Header: /tcpdump/master/tcpdump/print-gre.c,v 1.28 2005-04-06 21:32:39 mcr Exp (LBL)"; 44 #else 45 __RCSID("$NetBSD: print-gre.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 46 #endif 47 #endif 48 49 #ifdef HAVE_CONFIG_H 50 #include "config.h" 51 #endif 52 53 #include <tcpdump-stdinc.h> 54 55 #include <stdio.h> 56 #include <string.h> 57 58 #include "interface.h" 59 #include "addrtoname.h" 60 #include "extract.h" 61 62 #include "ip.h" 63 #include "ethertype.h" 64 65 #define GRE_CP 0x8000 /* checksum present */ 66 #define GRE_RP 0x4000 /* routing present */ 67 #define GRE_KP 0x2000 /* key present */ 68 #define GRE_SP 0x1000 /* sequence# present */ 69 #define GRE_sP 0x0800 /* source routing */ 70 #define GRE_RECRS 0x0700 /* recursion count */ 71 #define GRE_AP 0x0080 /* acknowledgment# present */ 72 73 struct tok gre_flag_values[] = { 74 { GRE_CP, "checksum present"}, 75 { GRE_RP, "routing present"}, 76 { GRE_KP, "key present"}, 77 { GRE_SP, "sequence# present"}, 78 { GRE_sP, "source routing present"}, 79 { GRE_RECRS, "recursion count"}, 80 { GRE_AP, "ack present"}, 81 { 0, NULL } 82 }; 83 84 #define GRE_VERS_MASK 0x0007 /* protocol version */ 85 86 /* source route entry types */ 87 #define GRESRE_IP 0x0800 /* IP */ 88 #define GRESRE_ASN 0xfffe /* ASN */ 89 90 void gre_print_0(const u_char *, u_int); 91 void gre_print_1(const u_char *, u_int); 92 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int); 93 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); 94 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); 95 96 void 97 gre_print(const u_char *bp, u_int length) 98 { 99 u_int len = length, vers; 100 101 if (len < 2) { 102 printf("[|gre]"); 103 return; 104 } 105 vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK; 106 printf("GREv%u",vers); 107 108 switch(vers) { 109 case 0: 110 gre_print_0(bp, len); 111 break; 112 case 1: 113 gre_print_1(bp, len); 114 break; 115 default: 116 printf(" ERROR: unknown-version"); 117 break; 118 } 119 return; 120 121 } 122 123 void 124 gre_print_0(const u_char *bp, u_int length) 125 { 126 u_int len = length; 127 u_int16_t flags, prot; 128 129 flags = EXTRACT_16BITS(bp); 130 if (vflag) 131 printf(", Flags [%s]", 132 bittok2str(gre_flag_values,"none",flags)); 133 134 len -= 2; 135 bp += 2; 136 137 if (len < 2) 138 goto trunc; 139 prot = EXTRACT_16BITS(bp); 140 len -= 2; 141 bp += 2; 142 143 if ((flags & GRE_CP) | (flags & GRE_RP)) { 144 if (len < 2) 145 goto trunc; 146 if (vflag) 147 printf(", sum 0x%x", EXTRACT_16BITS(bp)); 148 bp += 2; 149 len -= 2; 150 151 if (len < 2) 152 goto trunc; 153 printf(", off 0x%x", EXTRACT_16BITS(bp)); 154 bp += 2; 155 len -= 2; 156 } 157 158 if (flags & GRE_KP) { 159 if (len < 4) 160 goto trunc; 161 printf(", key=0x%x", EXTRACT_32BITS(bp)); 162 bp += 4; 163 len -= 4; 164 } 165 166 if (flags & GRE_SP) { 167 if (len < 4) 168 goto trunc; 169 printf(", seq %u", EXTRACT_32BITS(bp)); 170 bp += 4; 171 len -= 4; 172 } 173 174 if (flags & GRE_RP) { 175 for (;;) { 176 u_int16_t af; 177 u_int8_t sreoff; 178 u_int8_t srelen; 179 180 if (len < 4) 181 goto trunc; 182 af = EXTRACT_16BITS(bp); 183 sreoff = *(bp + 2); 184 srelen = *(bp + 3); 185 bp += 4; 186 len -= 4; 187 188 if (af == 0 && srelen == 0) 189 break; 190 191 gre_sre_print(af, sreoff, srelen, bp, len); 192 193 if (len < srelen) 194 goto trunc; 195 bp += srelen; 196 len -= srelen; 197 } 198 } 199 200 if (eflag) 201 printf(", proto %s (0x%04x)", 202 tok2str(ethertype_values,"unknown",prot), 203 prot); 204 205 printf(", length %u",length); 206 207 if (vflag < 1) 208 printf(": "); /* put in a colon as protocol demarc */ 209 else 210 printf("\n\t"); /* if verbose go multiline */ 211 212 switch (prot) { 213 case ETHERTYPE_IP: 214 ip_print(gndo, bp, len); 215 break; 216 #ifdef INET6 217 case ETHERTYPE_IPV6: 218 ip6_print(bp, len); 219 break; 220 #endif 221 case ETHERTYPE_MPLS: 222 mpls_print(bp, len); 223 break; 224 case ETHERTYPE_IPX: 225 ipx_print(bp, len); 226 break; 227 case ETHERTYPE_ATALK: 228 atalk_print(bp, len); 229 break; 230 case ETHERTYPE_GRE_ISO: 231 isoclns_print(bp, len, len); 232 break; 233 case ETHERTYPE_TEB: 234 ether_print(bp, len, len, NULL, NULL); 235 break; 236 default: 237 printf("gre-proto-0x%x", prot); 238 } 239 return; 240 241 trunc: 242 printf("[|gre]"); 243 } 244 245 void 246 gre_print_1(const u_char *bp, u_int length) 247 { 248 u_int len = length; 249 u_int16_t flags, prot; 250 251 flags = EXTRACT_16BITS(bp); 252 len -= 2; 253 bp += 2; 254 255 if (vflag) 256 printf(", Flags [%s]", 257 bittok2str(gre_flag_values,"none",flags)); 258 259 if (len < 2) 260 goto trunc; 261 prot = EXTRACT_16BITS(bp); 262 len -= 2; 263 bp += 2; 264 265 266 if (flags & GRE_KP) { 267 u_int32_t k; 268 269 if (len < 4) 270 goto trunc; 271 k = EXTRACT_32BITS(bp); 272 printf(", call %d", k & 0xffff); 273 len -= 4; 274 bp += 4; 275 } 276 277 if (flags & GRE_SP) { 278 if (len < 4) 279 goto trunc; 280 printf(", seq %u", EXTRACT_32BITS(bp)); 281 bp += 4; 282 len -= 4; 283 } 284 285 if (flags & GRE_AP) { 286 if (len < 4) 287 goto trunc; 288 printf(", ack %u", EXTRACT_32BITS(bp)); 289 bp += 4; 290 len -= 4; 291 } 292 293 if ((flags & GRE_SP) == 0) 294 printf(", no-payload"); 295 296 if (eflag) 297 printf(", proto %s (0x%04x)", 298 tok2str(ethertype_values,"unknown",prot), 299 prot); 300 301 printf(", length %u",length); 302 303 if ((flags & GRE_SP) == 0) 304 return; 305 306 if (vflag < 1) 307 printf(": "); /* put in a colon as protocol demarc */ 308 else 309 printf("\n\t"); /* if verbose go multiline */ 310 311 switch (prot) { 312 case ETHERTYPE_PPP: 313 ppp_print(bp, len); 314 break; 315 default: 316 printf("gre-proto-0x%x", prot); 317 break; 318 } 319 return; 320 321 trunc: 322 printf("[|gre]"); 323 } 324 325 void 326 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen, 327 const u_char *bp, u_int len) 328 { 329 switch (af) { 330 case GRESRE_IP: 331 printf(", (rtaf=ip"); 332 gre_sre_ip_print(sreoff, srelen, bp, len); 333 printf(") "); 334 break; 335 case GRESRE_ASN: 336 printf(", (rtaf=asn"); 337 gre_sre_asn_print(sreoff, srelen, bp, len); 338 printf(") "); 339 break; 340 default: 341 printf(", (rtaf=0x%x) ", af); 342 } 343 } 344 void 345 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 346 { 347 struct in_addr a; 348 const u_char *up = bp; 349 350 if (sreoff & 3) { 351 printf(", badoffset=%u", sreoff); 352 return; 353 } 354 if (srelen & 3) { 355 printf(", badlength=%u", srelen); 356 return; 357 } 358 if (sreoff >= srelen) { 359 printf(", badoff/len=%u/%u", sreoff, srelen); 360 return; 361 } 362 363 for (;;) { 364 if (len < 4 || srelen == 0) 365 return; 366 367 memcpy(&a, bp, sizeof(a)); 368 printf(" %s%s", 369 ((bp - up) == sreoff) ? "*" : "", 370 inet_ntoa(a)); 371 372 bp += 4; 373 len -= 4; 374 srelen -= 4; 375 } 376 } 377 378 void 379 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 380 { 381 const u_char *up = bp; 382 383 if (sreoff & 1) { 384 printf(", badoffset=%u", sreoff); 385 return; 386 } 387 if (srelen & 1) { 388 printf(", badlength=%u", srelen); 389 return; 390 } 391 if (sreoff >= srelen) { 392 printf(", badoff/len=%u/%u", sreoff, srelen); 393 return; 394 } 395 396 for (;;) { 397 if (len < 2 || srelen == 0) 398 return; 399 400 printf(" %s%x", 401 ((bp - up) == sreoff) ? "*" : "", 402 EXTRACT_16BITS(bp)); 403 404 bp += 2; 405 len -= 2; 406 srelen -= 2; 407 } 408 } 409