1 /* $OpenBSD: print-gre.c,v 1.12 2016/12/13 06:40:21 dlg 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * tcpdump filter for GRE - Generic Routing Encapsulation 31 * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE) 32 */ 33 34 #include <sys/time.h> 35 #include <sys/uio.h> 36 #include <sys/socket.h> 37 38 #include <netinet/in.h> 39 #include <netinet/ip.h> 40 #include <arpa/inet.h> 41 42 #include <net/ethertypes.h> 43 44 #include <stdio.h> 45 #include <string.h> 46 47 #include "interface.h" 48 #include "addrtoname.h" 49 #include "extract.h" 50 51 #define GRE_CP 0x8000 /* checksum present */ 52 #define GRE_RP 0x4000 /* routing present */ 53 #define GRE_KP 0x2000 /* key present */ 54 #define GRE_SP 0x1000 /* sequence# present */ 55 #define GRE_sP 0x0800 /* source routing */ 56 #define GRE_RECRS 0x0700 /* recursion count */ 57 #define GRE_AP 0x0080 /* acknowledgment# present */ 58 #define GRE_VERS 0x0007 /* protocol version */ 59 60 /* source route entry types */ 61 #define GRESRE_IP 0x0800 /* IP */ 62 #define GRESRE_ASN 0xfffe /* ASN */ 63 64 #define NVGRE_VSID_MASK 0xffffff00U 65 #define NVGRE_VSID_SHIFT 8 66 #define NVGRE_FLOWID_MASK 0x000000ffU 67 #define NVGRE_FLOWID_SHIFT 0 68 69 void gre_print_0(const u_char *, u_int); 70 void gre_print_1(const u_char *, u_int); 71 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int); 72 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); 73 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); 74 75 void 76 gre_print(const u_char *bp, u_int length) 77 { 78 u_int len = length, vers; 79 80 if (bp + len > snapend) 81 len = snapend - bp; 82 83 if (len < 2) { 84 printf("[|gre]"); 85 return; 86 } 87 vers = EXTRACT_16BITS(bp) & GRE_VERS; 88 89 switch (vers) { 90 case 0: 91 gre_print_0(bp, len); 92 break; 93 case 1: 94 gre_print_1(bp, len); 95 break; 96 default: 97 printf("gre-unknown-version=%u", vers); 98 break; 99 } 100 } 101 102 void 103 gre_print_0(const u_char *bp, u_int length) 104 { 105 u_int len = length; 106 u_int16_t flags, prot; 107 108 flags = EXTRACT_16BITS(bp); 109 if (vflag) { 110 printf("[%s%s%s%s%s] ", 111 (flags & GRE_CP) ? "C" : "", 112 (flags & GRE_RP) ? "R" : "", 113 (flags & GRE_KP) ? "K" : "", 114 (flags & GRE_SP) ? "S" : "", 115 (flags & GRE_sP) ? "s" : ""); 116 } 117 118 len -= 2; 119 bp += 2; 120 121 if (len < 2) 122 goto trunc; 123 prot = EXTRACT_16BITS(bp); 124 printf("%s", etherproto_string(prot)); 125 126 len -= 2; 127 bp += 2; 128 129 if ((flags & GRE_CP) | (flags & GRE_RP)) { 130 if (len < 2) 131 goto trunc; 132 if (vflag) 133 printf(" sum 0x%x", EXTRACT_16BITS(bp)); 134 bp += 2; 135 len -= 2; 136 137 if (len < 2) 138 goto trunc; 139 printf(" off 0x%x", EXTRACT_16BITS(bp)); 140 bp += 2; 141 len -= 2; 142 } 143 144 if (flags & GRE_KP) { 145 uint32_t key, vsid; 146 147 if (len < 4) 148 goto trunc; 149 key = EXTRACT_32BITS(bp); 150 151 /* maybe NVGRE? */ 152 if (flags == (GRE_KP | 0) && prot == ETHERTYPE_TRANSETHER) { 153 vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT; 154 printf(" NVGRE vsid=%u (0x%x)+flowid=0x%02x /", 155 vsid, vsid, 156 (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT); 157 } 158 printf(" key=%u (0x%x)", key, key); 159 bp += 4; 160 len -= 4; 161 } 162 163 if (flags & GRE_SP) { 164 if (len < 4) 165 goto trunc; 166 printf(" seq %u", EXTRACT_32BITS(bp)); 167 bp += 4; 168 len -= 4; 169 } 170 171 if (flags & GRE_RP) { 172 for (;;) { 173 u_int16_t af; 174 u_int8_t sreoff; 175 u_int8_t srelen; 176 177 if (len < 4) 178 goto trunc; 179 af = EXTRACT_16BITS(bp); 180 sreoff = *(bp + 2); 181 srelen = *(bp + 3); 182 bp += 4; 183 len -= 4; 184 185 if (af == 0 && srelen == 0) 186 break; 187 188 gre_sre_print(af, sreoff, srelen, bp, len); 189 190 if (len < srelen) 191 goto trunc; 192 bp += srelen; 193 len -= srelen; 194 } 195 } 196 197 printf(": "); 198 199 switch (prot) { 200 case ETHERTYPE_IP: 201 ip_print(bp, len); 202 break; 203 case ETHERTYPE_IPV6: 204 ip6_print(bp, len); 205 break; 206 case ETHERTYPE_MPLS: 207 mpls_print(bp, len); 208 break; 209 case ETHERTYPE_TRANSETHER: 210 ether_print(bp, len); 211 break; 212 default: 213 printf("gre-proto-0x%x", prot); 214 } 215 return; 216 217 trunc: 218 printf("[|gre]"); 219 } 220 221 void 222 gre_print_1(const u_char *bp, u_int length) 223 { 224 u_int len = length; 225 u_int16_t flags, prot; 226 227 flags = EXTRACT_16BITS(bp); 228 len -= 2; 229 bp += 2; 230 231 if (vflag) { 232 printf("[%s%s%s%s%s%s]", 233 (flags & GRE_CP) ? "C" : "", 234 (flags & GRE_RP) ? "R" : "", 235 (flags & GRE_KP) ? "K" : "", 236 (flags & GRE_SP) ? "S" : "", 237 (flags & GRE_sP) ? "s" : "", 238 (flags & GRE_AP) ? "A" : ""); 239 } 240 241 if (len < 2) 242 goto trunc; 243 prot = EXTRACT_16BITS(bp); 244 len -= 2; 245 bp += 2; 246 247 if (flags & GRE_CP) { 248 printf(" cpset!"); 249 return; 250 } 251 if (flags & GRE_RP) { 252 printf(" rpset!"); 253 return; 254 } 255 if ((flags & GRE_KP) == 0) { 256 printf(" kpunset!"); 257 return; 258 } 259 if (flags & GRE_sP) { 260 printf(" spset!"); 261 return; 262 } 263 264 if (flags & GRE_KP) { 265 u_int32_t k; 266 267 if (len < 4) 268 goto trunc; 269 k = EXTRACT_32BITS(bp); 270 printf(" call %d", k & 0xffff); 271 len -= 4; 272 bp += 4; 273 } 274 275 if (flags & GRE_SP) { 276 if (len < 4) 277 goto trunc; 278 printf(" seq %u", EXTRACT_32BITS(bp)); 279 bp += 4; 280 len -= 4; 281 } 282 283 if (flags & GRE_AP) { 284 if (len < 4) 285 goto trunc; 286 printf(" ack %u", EXTRACT_32BITS(bp)); 287 bp += 4; 288 len -= 4; 289 } 290 291 if ((flags & GRE_SP) == 0) { 292 printf(" no-payload"); 293 return; 294 } 295 296 printf(": "); 297 298 switch (prot) { 299 case ETHERTYPE_PPP: 300 printf("gre-ppp-payload"); 301 break; 302 default: 303 printf("gre-proto-0x%x", prot); 304 break; 305 } 306 return; 307 308 trunc: 309 printf("[|gre]"); 310 } 311 312 void 313 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen, 314 const u_char *bp, u_int len) 315 { 316 switch (af) { 317 case GRESRE_IP: 318 printf(" (rtaf=ip"); 319 gre_sre_ip_print(sreoff, srelen, bp, len); 320 printf(")"); 321 break; 322 case GRESRE_ASN: 323 printf(" (rtaf=asn"); 324 gre_sre_asn_print(sreoff, srelen, bp, len); 325 printf(")"); 326 break; 327 default: 328 printf(" (rtaf=0x%x)", af); 329 } 330 } 331 void 332 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 333 { 334 struct in_addr a; 335 const u_char *up = bp; 336 337 if (sreoff & 3) { 338 printf(" badoffset=%u", sreoff); 339 return; 340 } 341 if (srelen & 3) { 342 printf(" badlength=%u", srelen); 343 return; 344 } 345 if (sreoff >= srelen) { 346 printf(" badoff/len=%u/%u", sreoff, srelen); 347 return; 348 } 349 350 for (;;) { 351 if (len < 4 || srelen == 0) 352 return; 353 354 memcpy(&a, bp, sizeof(a)); 355 printf(" %s%s", 356 ((bp - up) == sreoff) ? "*" : "", 357 inet_ntoa(a)); 358 359 bp += 4; 360 len -= 4; 361 srelen -= 4; 362 } 363 } 364 365 void 366 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 367 { 368 const u_char *up = bp; 369 370 if (sreoff & 1) { 371 printf(" badoffset=%u", sreoff); 372 return; 373 } 374 if (srelen & 1) { 375 printf(" badlength=%u", srelen); 376 return; 377 } 378 if (sreoff >= srelen) { 379 printf(" badoff/len=%u/%u", sreoff, srelen); 380 return; 381 } 382 383 for (;;) { 384 if (len < 2 || srelen == 0) 385 return; 386 387 printf(" %s%x", 388 ((bp - up) == sreoff) ? "*" : "", 389 EXTRACT_16BITS(bp)); 390 391 bp += 2; 392 len -= 2; 393 srelen -= 2; 394 } 395 } 396