1 /* $OpenBSD: print-gre.c,v 1.34 2020/08/17 07:09:25 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 #define GRE_WCCP 0x883e 70 #define ERSPAN_II 0x88be 71 #define ERSPAN_III 0x22eb 72 73 struct wccp_redirect { 74 uint8_t flags; 75 #define WCCP_D (1 << 7) 76 #define WCCP_A (1 << 6) 77 uint8_t ServiceId; 78 uint8_t AltBucket; 79 uint8_t PriBucket; 80 }; 81 82 void gre_print_0(const u_char *, u_int); 83 void gre_print_1(const u_char *, u_int); 84 void gre_print_pptp(const u_char *, u_int, uint16_t); 85 void gre_print_eoip(const u_char *, u_int, uint16_t); 86 void gre_print_erspan(uint16_t, const u_char *, u_int); 87 void gre_print_erspan3(const u_char *, u_int); 88 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int); 89 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); 90 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); 91 92 void 93 gre_print(const u_char *p, u_int length) 94 { 95 uint16_t vers; 96 int l; 97 98 l = snapend - p; 99 100 if (l < sizeof(vers)) { 101 printf("[|gre]"); 102 return; 103 } 104 vers = EXTRACT_16BITS(p) & GRE_VERS; 105 106 switch (vers) { 107 case 0: 108 gre_print_0(p, length); 109 break; 110 case 1: 111 gre_print_1(p, length); 112 break; 113 default: 114 printf("gre-unknown-version=%u", vers); 115 break; 116 } 117 } 118 119 void 120 gre_print_0(const u_char *p, u_int length) 121 { 122 uint16_t flags, proto; 123 u_int l; 124 125 l = snapend - p; 126 127 flags = EXTRACT_16BITS(p); 128 p += sizeof(flags); 129 l -= sizeof(flags); 130 length -= sizeof(flags); 131 132 printf("gre"); 133 134 if (vflag) { 135 printf(" [%s%s%s%s%s]", 136 (flags & GRE_CP) ? "C" : "", 137 (flags & GRE_RP) ? "R" : "", 138 (flags & GRE_KP) ? "K" : "", 139 (flags & GRE_SP) ? "S" : "", 140 (flags & GRE_sP) ? "s" : ""); 141 } 142 143 if (l < sizeof(proto)) 144 goto trunc; 145 proto = EXTRACT_16BITS(p); 146 p += sizeof(proto); 147 l -= sizeof(proto); 148 length -= sizeof(proto); 149 150 if (vflag) 151 printf(" %04x", proto); 152 153 if ((flags & GRE_CP) | (flags & GRE_RP)) { 154 if (l < 2) 155 goto trunc; 156 if ((flags & GRE_CP) && vflag) 157 printf(" sum 0x%x", EXTRACT_16BITS(p)); 158 p += 2; 159 l -= 2; 160 length -= 2; 161 162 if (l < 2) 163 goto trunc; 164 if (flags & GRE_RP) 165 printf(" off 0x%x", EXTRACT_16BITS(p)); 166 p += 2; 167 l -= 2; 168 length -= 2; 169 } 170 171 if (flags & GRE_KP) { 172 uint32_t key, vsid; 173 174 if (l < sizeof(key)) 175 goto trunc; 176 key = EXTRACT_32BITS(p); 177 p += sizeof(key); 178 l -= sizeof(key); 179 length -= sizeof(key); 180 181 /* maybe NVGRE, or key entropy? */ 182 vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT; 183 printf(" key=%u|%u+%02x", key, vsid, 184 (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT); 185 } 186 187 if (flags & GRE_SP) { 188 if (l < 4) 189 goto trunc; 190 printf(" seq %u", EXTRACT_32BITS(p)); 191 p += 4; 192 l -= 4; 193 length -= 4; 194 } 195 196 if (flags & GRE_RP) { 197 for (;;) { 198 u_int16_t af; 199 u_int8_t sreoff; 200 u_int8_t srelen; 201 202 if (l < 4) 203 goto trunc; 204 af = EXTRACT_16BITS(p); 205 sreoff = *(p + 2); 206 srelen = *(p + 3); 207 p += 4; 208 l -= 4; 209 length -= 4; 210 211 if (af == 0 && srelen == 0) 212 break; 213 214 gre_sre_print(af, sreoff, srelen, p, l); 215 216 if (l < srelen) 217 goto trunc; 218 p += srelen; 219 l -= srelen; 220 length -= srelen; 221 } 222 } 223 224 printf(" "); 225 226 switch (packettype) { 227 case PT_ERSPAN: 228 gre_print_erspan(flags, p, length); 229 return; 230 default: 231 break; 232 } 233 234 switch (proto) { 235 case 0: 236 printf("keep-alive"); 237 break; 238 case GRE_WCCP: { 239 printf("wccp "); 240 241 if (l == 0) 242 return; 243 244 if (*p >> 4 != 4) { 245 struct wccp_redirect *wccp; 246 247 if (l < sizeof(*wccp)) { 248 printf("[|wccp]"); 249 return; 250 } 251 252 wccp = (struct wccp_redirect *)p; 253 254 printf("D:%c A:%c SId:%u Alt:%u Pri:%u", 255 (wccp->flags & WCCP_D) ? '1' : '0', 256 (wccp->flags & WCCP_A) ? '1' : '0', 257 wccp->ServiceId, wccp->AltBucket, wccp->PriBucket); 258 259 p += sizeof(*wccp); 260 l -= sizeof(*wccp); 261 262 printf(": "); 263 } 264 265 /* FALLTHROUGH */ 266 } 267 case ETHERTYPE_IP: 268 ip_print(p, length); 269 break; 270 case ETHERTYPE_IPV6: 271 ip6_print(p, length); 272 break; 273 case ETHERTYPE_MPLS: 274 case ETHERTYPE_MPLS_MCAST: 275 mpls_print(p, length); 276 break; 277 case ETHERTYPE_TRANSETHER: 278 ether_tryprint(p, length, 0); 279 break; 280 #ifndef ETHERTYPE_NSH 281 #define ETHERTYPE_NSH 0x894f 282 #endif 283 case ETHERTYPE_NSH: 284 nsh_print(p, length); 285 break; 286 case ERSPAN_II: 287 gre_print_erspan(flags, p, length); 288 break; 289 case 0x2000: 290 cdp_print(p, length, l, 0); 291 break; 292 #ifndef ETHERTYPE_NHRP 293 #define ETHERTYPE_NHRP 0x2001 294 #endif 295 case ETHERTYPE_NHRP: 296 nhrp_print(p, length); 297 break; 298 default: 299 printf("unknown-proto-%04x", proto); 300 } 301 return; 302 303 trunc: 304 printf("[|gre]"); 305 } 306 307 void 308 gre_print_1(const u_char *p, u_int length) 309 { 310 uint16_t flags, proto; 311 int l; 312 313 l = snapend - p; 314 315 flags = EXTRACT_16BITS(p); 316 p += sizeof(flags); 317 l -= sizeof(flags); 318 length -= sizeof(flags); 319 320 if (l < sizeof(proto)) 321 goto trunc; 322 323 proto = EXTRACT_16BITS(p); 324 p += sizeof(proto); 325 l -= sizeof(proto); 326 length -= sizeof(proto); 327 328 switch (proto) { 329 case ETHERTYPE_PPP: 330 gre_print_pptp(p, length, flags); 331 break; 332 case 0x6400: 333 /* MikroTik RouterBoard Ethernet over IP (EoIP) */ 334 gre_print_eoip(p, length, flags); 335 break; 336 default: 337 printf("unknown-gre1-proto-%04x", proto); 338 break; 339 } 340 341 return; 342 343 trunc: 344 printf("[|gre1]"); 345 } 346 347 void 348 gre_print_pptp(const u_char *p, u_int length, uint16_t flags) 349 { 350 uint16_t len; 351 int l; 352 353 l = snapend - p; 354 355 printf("pptp"); 356 357 if (vflag) { 358 printf(" [%s%s%s%s%s%s]", 359 (flags & GRE_CP) ? "C" : "", 360 (flags & GRE_RP) ? "R" : "", 361 (flags & GRE_KP) ? "K" : "", 362 (flags & GRE_SP) ? "S" : "", 363 (flags & GRE_sP) ? "s" : "", 364 (flags & GRE_AP) ? "A" : ""); 365 } 366 367 if (flags & GRE_CP) { 368 printf(" cpset!"); 369 return; 370 } 371 if (flags & GRE_RP) { 372 printf(" rpset!"); 373 return; 374 } 375 if ((flags & GRE_KP) == 0) { 376 printf(" kpunset!"); 377 return; 378 } 379 if (flags & GRE_sP) { 380 printf(" spset!"); 381 return; 382 } 383 384 /* GRE_KP */ 385 if (l < sizeof(len)) 386 goto trunc; 387 len = EXTRACT_16BITS(p); 388 p += sizeof(len); 389 l -= sizeof(len); 390 length -= sizeof(len); 391 392 if (vflag) 393 printf(" len %u", EXTRACT_16BITS(p)); 394 395 if (l < 2) 396 goto trunc; 397 printf(" callid %u", EXTRACT_16BITS(p)); 398 p += 2; 399 l -= 2; 400 length -= 2; 401 402 if (flags & GRE_SP) { 403 if (l < 4) 404 goto trunc; 405 printf(" seq %u", EXTRACT_32BITS(p)); 406 p += 4; 407 l -= 4; 408 length -= 4; 409 } 410 411 if (flags & GRE_AP) { 412 if (l < 4) 413 goto trunc; 414 printf(" ack %u", EXTRACT_32BITS(p)); 415 p += 4; 416 l -= 4; 417 length -= 4; 418 } 419 420 if ((flags & GRE_SP) == 0) 421 return; 422 423 if (length < len) { 424 printf(" truncated-pptp - %d bytes missing!", 425 len - length); 426 len = length; 427 } 428 429 printf(": "); 430 431 ppp_hdlc_print(p, len); 432 return; 433 434 trunc: 435 printf("[|pptp]"); 436 } 437 438 void 439 gre_print_eoip(const u_char *p, u_int length, uint16_t flags) 440 { 441 uint16_t len, id; 442 int l; 443 444 l = snapend - p; 445 446 printf("eoip"); 447 448 flags &= ~GRE_VERS; 449 if (flags != GRE_KP) { 450 printf(" unknown-eoip-flags-%04x!", flags); 451 return; 452 } 453 454 if (l < sizeof(len)) 455 goto trunc; 456 457 len = EXTRACT_16BITS(p); 458 p += sizeof(len); 459 l -= sizeof(len); 460 length -= sizeof(len); 461 462 if (l < sizeof(id)) 463 goto trunc; 464 465 id = EXTRACT_LE_16BITS(p); 466 p += sizeof(id); 467 l -= sizeof(id); 468 length -= sizeof(id); 469 470 if (vflag) 471 printf(" len=%u tunnel-id=%u", len, id); 472 else 473 printf(" %u", id); 474 475 if (length < len) { 476 printf(" truncated-eoip - %d bytes missing!", 477 len - length); 478 len = length; 479 } 480 481 printf(": "); 482 483 if (len == 0) 484 printf("keepalive"); 485 else 486 ether_tryprint(p, len, 0); 487 488 return; 489 490 trunc: 491 printf("[|eoip]"); 492 } 493 494 #define ERSPAN2_VER_SHIFT 28 495 #define ERSPAN2_VER_MASK (0xfU << ERSPAN2_VER_SHIFT) 496 #define ERSPAN2_VER (0x1U << ERSPAN2_VER_SHIFT) 497 #define ERSPAN2_VLAN_SHIFT 16 498 #define ERSPAN2_VLAN_MASK (0xfffU << ERSPAN2_VLAN_SHIFT) 499 #define ERSPAN2_COS_SHIFT 13 500 #define ERSPAN2_COS_MASK (0x7U << ERSPAN2_COS_SHIFT) 501 #define ERSPAN2_EN_SHIFT 11 502 #define ERSPAN2_EN_MASK (0x3U << ERSPAN2_EN_SHIFT) 503 #define ERSPAN2_EN_NONE (0x0U << ERSPAN2_EN_SHIFT) 504 #define ERSPAN2_EN_ISL (0x1U << ERSPAN2_EN_SHIFT) 505 #define ERSPAN2_EN_DOT1Q (0x2U << ERSPAN2_EN_SHIFT) 506 #define ERSPAN2_EN_VLAN (0x3U << ERSPAN2_EN_SHIFT) 507 #define ERSPAN2_T_SHIFT 10 508 #define ERSPAN2_T_MASK (0x1U << ERSPAN2_T_SHIFT) 509 #define ERSPAN2_SID_SHIFT 0 510 #define ERSPAN2_SID_MASK (0x3ffU << ERSPAN2_SID_SHIFT) 511 512 #define ERSPAN2_INDEX_SHIFT 0 513 #define ERSPAN2_INDEX_MASK (0xfffffU << ERSPAN2_INDEX_SHIFT) 514 515 void 516 gre_print_erspan(uint16_t flags, const u_char *bp, u_int len) 517 { 518 uint32_t hdr, ver, vlan, cos, en, sid, index; 519 u_int l; 520 521 printf("erspan"); 522 523 if (!(flags & GRE_SP)) { 524 printf(" I: "); 525 ether_tryprint(bp, len, 0); 526 return; 527 } 528 529 l = snapend - bp; 530 if (l < sizeof(hdr)) 531 goto trunc; 532 533 hdr = EXTRACT_32BITS(bp); 534 bp += sizeof(hdr); 535 l -= sizeof(hdr); 536 len -= sizeof(hdr); 537 538 ver = hdr & ERSPAN2_VER_MASK; 539 if (ver != ERSPAN2_VER) { 540 ver >>= ERSPAN2_VER_SHIFT; 541 printf(" erspan-unknown-version-%x", ver); 542 return; 543 } 544 545 if (vflag) 546 printf(" II"); 547 548 sid = (hdr & ERSPAN2_SID_MASK) >> ERSPAN2_SID_SHIFT; 549 printf(" session %u", sid); 550 551 en = hdr & ERSPAN2_EN_MASK; 552 vlan = (hdr & ERSPAN2_VLAN_MASK) >> ERSPAN2_VLAN_SHIFT; 553 switch (en) { 554 case ERSPAN2_EN_NONE: 555 break; 556 case ERSPAN2_EN_ISL: 557 printf(" isl %u", vlan); 558 break; 559 case ERSPAN2_EN_DOT1Q: 560 printf(" vlan %u", vlan); 561 break; 562 case ERSPAN2_EN_VLAN: 563 printf(" vlan payload"); 564 break; 565 } 566 567 if (vflag) { 568 cos = (hdr & ERSPAN2_COS_MASK) >> ERSPAN2_COS_SHIFT; 569 printf(" cos %u", cos); 570 571 if (hdr & ERSPAN2_T_MASK) 572 printf(" truncated"); 573 } 574 575 if (l < sizeof(hdr)) 576 goto trunc; 577 578 hdr = EXTRACT_32BITS(bp); 579 bp += sizeof(hdr); 580 l -= sizeof(hdr); 581 len -= sizeof(hdr); 582 583 if (vflag) { 584 index = (hdr & ERSPAN2_INDEX_MASK) >> ERSPAN2_INDEX_SHIFT; 585 printf(" index %u", index); 586 } 587 588 printf(": "); 589 ether_tryprint(bp, len, 0); 590 return; 591 592 trunc: 593 printf(" [|erspan]"); 594 } 595 596 void 597 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen, 598 const u_char *bp, u_int len) 599 { 600 switch (af) { 601 case GRESRE_IP: 602 printf(" (rtaf=ip"); 603 gre_sre_ip_print(sreoff, srelen, bp, len); 604 printf(")"); 605 break; 606 case GRESRE_ASN: 607 printf(" (rtaf=asn"); 608 gre_sre_asn_print(sreoff, srelen, bp, len); 609 printf(")"); 610 break; 611 default: 612 printf(" (rtaf=0x%x)", af); 613 } 614 } 615 void 616 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 617 { 618 struct in_addr a; 619 const u_char *up = bp; 620 621 if (sreoff & 3) { 622 printf(" badoffset=%u", sreoff); 623 return; 624 } 625 if (srelen & 3) { 626 printf(" badlength=%u", srelen); 627 return; 628 } 629 if (sreoff >= srelen) { 630 printf(" badoff/len=%u/%u", sreoff, srelen); 631 return; 632 } 633 634 for (;;) { 635 if (len < 4 || srelen == 0) 636 return; 637 638 memcpy(&a, bp, sizeof(a)); 639 printf(" %s%s", 640 ((bp - up) == sreoff) ? "*" : "", 641 inet_ntoa(a)); 642 643 bp += 4; 644 len -= 4; 645 srelen -= 4; 646 } 647 } 648 649 void 650 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 651 { 652 const u_char *up = bp; 653 654 if (sreoff & 1) { 655 printf(" badoffset=%u", sreoff); 656 return; 657 } 658 if (srelen & 1) { 659 printf(" badlength=%u", srelen); 660 return; 661 } 662 if (sreoff >= srelen) { 663 printf(" badoff/len=%u/%u", sreoff, srelen); 664 return; 665 } 666 667 for (;;) { 668 if (len < 2 || srelen == 0) 669 return; 670 671 printf(" %s%x", 672 ((bp - up) == sreoff) ? "*" : "", 673 EXTRACT_16BITS(bp)); 674 675 bp += 2; 676 len -= 2; 677 srelen -= 2; 678 } 679 } 680 681 /* 682 * - RFC 7348 Virtual eXtensible Local Area Network (VXLAN) 683 * - draft-ietf-nvo3-vxlan-gpe-08 Generic Protocol Extension for VXLAN 684 */ 685 686 struct vxlan_header { 687 uint16_t flags; 688 #define VXLAN_VER 0x3000 /* GPE */ 689 #define VXLAN_VER_0 0x0000 690 #define VXLAN_I 0x0800 /* Instance Bit */ 691 #define VXLAN_P 0x0400 /* GPE Next Protocol */ 692 #define VXLAN_B 0x0200 /* GPE BUM Traffic */ 693 #define VXLAN_O 0x0100 /* GPE OAM Flag */ 694 uint8_t reserved; 695 uint8_t next_proto; /* GPE */ 696 #define VXLAN_PROTO_RESERVED 0x00 697 #define VXLAN_PROTO_IPV4 0x01 698 #define VXLAN_PROTO_IPV6 0x02 699 #define VXLAN_PROTO_ETHERNET 0x03 700 #define VXLAN_PROTO_NSH 0x04 701 #define VXLAN_PROTO_MPLS 0x05 702 #define VXLAN_PROTO_VBNG 0x07 703 #define VXLAN_PROTO_GBP 0x80 704 #define VXLAN_PROTO_IOAM 0x82 705 uint32_t vni; 706 #define VXLAN_VNI_SHIFT 8 707 #define VXLAN_VNI_MASK (0xffffffU << VXLAN_VNI_SHIFT) 708 #define VXLAN_VNI_RESERVED (~VXLAN_VNI_MASK) 709 }; 710 711 void 712 vxlan_print(const u_char *p, u_int length) 713 { 714 const struct vxlan_header *vh; 715 uint16_t flags, ver; 716 uint8_t proto = VXLAN_PROTO_ETHERNET; 717 int l = snapend - p; 718 719 printf("VXLAN"); 720 721 if (l < sizeof(*vh)) 722 goto trunc; 723 if (length < sizeof(*vh)) { 724 printf(" ip truncated"); 725 return; 726 } 727 728 vh = (const struct vxlan_header *)p; 729 730 p += sizeof(*vh); 731 length -= sizeof(*vh); 732 733 flags = ntohs(vh->flags); 734 ver = flags & VXLAN_VER; 735 if (ver != VXLAN_VER_0) { 736 printf(" unknown version %u", ver >> 12); 737 return; 738 } 739 740 if (flags & VXLAN_I) { 741 uint32_t vni = (htonl(vh->vni) & VXLAN_VNI_MASK) >> 742 VXLAN_VNI_SHIFT; 743 printf(" vni %u", vni); 744 } 745 746 if (flags & VXLAN_P) 747 proto = vh->next_proto; 748 749 if (flags & VXLAN_B) 750 printf(" BUM"); 751 752 if (flags & VXLAN_O) { 753 printf(" OAM (proto 0x%x, len %u)", proto, length); 754 return; 755 } 756 757 printf(": "); 758 759 switch (proto) { 760 case VXLAN_PROTO_RESERVED: 761 printf("Reserved"); 762 break; 763 case VXLAN_PROTO_IPV4: 764 ip_print(p, length); 765 break; 766 case VXLAN_PROTO_IPV6: 767 ip6_print(p, length); 768 break; 769 case VXLAN_PROTO_ETHERNET: 770 ether_tryprint(p, length, 0); 771 break; 772 case VXLAN_PROTO_NSH: 773 nsh_print(p, length); 774 break; 775 case VXLAN_PROTO_MPLS: 776 mpls_print(p, length); 777 break; 778 779 default: 780 printf("Unassigned proto 0x%x", proto); 781 break; 782 } 783 784 return; 785 trunc: 786 printf(" [|vxlan]"); 787 } 788 789 /* 790 * Geneve: Generic Network Virtualization Encapsulation 791 * draft-ietf-nvo3-geneve-16 792 */ 793 794 struct geneve_header { 795 uint16_t flags; 796 #define GENEVE_VER_SHIFT 14 797 #define GENEVE_VER_MASK (0x3U << GENEVE_VER_SHIFT) 798 #define GENEVE_VER_0 (0x0U << GENEVE_VER_SHIFT) 799 #define GENEVE_OPT_LEN_SHIFT 8 800 #define GENEVE_OPT_LEN_MASK (0x3fU << GENEVE_OPT_LEN_SHIFT) 801 #define GENEVE_OPT_LEN_UNITS 4 802 #define GENEVE_O 0x0080 /* Control packet */ 803 #define GENEVE_C 0x0040 /* Critical options present */ 804 uint16_t protocol; 805 uint32_t vni; 806 #define GENEVE_VNI_SHIFT 8 807 #define GENEVE_VNI_MASK (0xffffffU << GENEVE_VNI_SHIFT) 808 #define GENEVE_VNI_RESERVED (~GENEVE_VNI_MASK) 809 }; 810 811 struct geneve_option { 812 uint16_t class; 813 uint8_t type; 814 uint8_t flags; 815 #define GENEVE_OPTION_LENGTH_SHIFT 0 816 #define GENEVE_OPTION_LENGTH_MASK (0x1fU << GENEVE_OPTION_LENGTH_SHIFT) 817 }; 818 819 static void 820 geneve_options_print(const u_char *p, u_int l) 821 { 822 if (l == 0) 823 return; 824 825 do { 826 struct geneve_option *go; 827 unsigned int len, i; 828 829 if (l < sizeof(*go)) 830 goto trunc; 831 832 go = (struct geneve_option *)p; 833 p += sizeof(*go); 834 l -= sizeof(*go); 835 836 printf("\n\toption class %u type %u", ntohs(go->class), 837 go->type); 838 839 len = (go->flags & GENEVE_OPTION_LENGTH_MASK) >> 840 GENEVE_OPTION_LENGTH_SHIFT; 841 if (len > 0) { 842 printf(":"); 843 for (i = 0; i < len; i++) { 844 uint32_t w; 845 846 if (l < sizeof(w)) 847 goto trunc; 848 849 w = EXTRACT_32BITS(p); 850 p += sizeof(w); 851 l -= sizeof(w); 852 853 printf(" %08x", w); 854 } 855 } 856 } while (l > 0); 857 858 return; 859 trunc: 860 printf("[|geneve option]"); 861 } 862 863 void 864 geneve_print(const u_char *p, u_int length) 865 { 866 const struct geneve_header *gh; 867 uint16_t flags, ver, optlen, proto; 868 uint32_t vni; 869 int l = snapend - p; 870 871 printf("geneve"); 872 873 if (l < sizeof(*gh)) 874 goto trunc; 875 if (length < sizeof(*gh)) { 876 printf(" ip truncated"); 877 return; 878 } 879 880 gh = (const struct geneve_header *)p; 881 882 p += sizeof(*gh); 883 l -= sizeof(*gh); 884 length -= sizeof(*gh); 885 886 flags = ntohs(gh->flags); 887 ver = flags & GENEVE_VER_MASK; 888 if (ver != GENEVE_VER_0) { 889 printf(" unknown version %u", ver >> GENEVE_VER_SHIFT); 890 return; 891 } 892 893 vni = (htonl(gh->vni) & GENEVE_VNI_MASK) >> GENEVE_VNI_SHIFT; 894 printf(" vni %u", vni); 895 896 if (flags & GENEVE_O) 897 printf(" Control"); 898 899 if (flags & GENEVE_C) 900 printf(" Critical"); 901 902 optlen = (flags & GENEVE_OPT_LEN_MASK) >> GENEVE_OPT_LEN_SHIFT; 903 optlen *= GENEVE_OPT_LEN_UNITS; 904 905 if (l < optlen) 906 goto trunc; 907 if (length < optlen) { 908 printf(" ip truncated"); 909 return; 910 } 911 912 if (optlen > 0) 913 geneve_options_print(p, optlen); 914 915 p += optlen; 916 length -= optlen; 917 918 printf("\n "); 919 920 proto = ntohs(gh->protocol); 921 switch (proto) { 922 case ETHERTYPE_IP: 923 ip_print(p, length); 924 break; 925 case ETHERTYPE_IPV6: 926 ip6_print(p, length); 927 break; 928 case ETHERTYPE_MPLS: 929 case ETHERTYPE_MPLS_MCAST: 930 mpls_print(p, length); 931 break; 932 case ETHERTYPE_TRANSETHER: 933 ether_tryprint(p, length, 0); 934 break; 935 936 default: 937 printf("geneve-protocol-0x%x", proto); 938 break; 939 } 940 941 return; 942 trunc: 943 printf(" [|geneve]"); 944 } 945