1127668Sbms/* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */ 2127668Sbms 326180Sfenner/* 4127668Sbms * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5127668Sbms * All rights reserved. 626180Sfenner * 7127668Sbms * Redistribution and use in source and binary forms, with or without 8127668Sbms * modification, are permitted provided that the following conditions 9127668Sbms * are met: 10127668Sbms * 1. Redistributions of source code must retain the above copyright 11127668Sbms * notice, this list of conditions and the following disclaimer. 12127668Sbms * 2. Redistributions in binary form must reproduce the above copyright 13127668Sbms * notice, this list of conditions and the following disclaimer in the 14127668Sbms * documentation and/or other materials provided with the distribution. 15127668Sbms * 3. All advertising materials mentioning features or use of this software 16127668Sbms * must display the following acknowledgement: 17127668Sbms * This product includes software developed by Jason L. Wright 18127668Sbms * 4. The name of the author may not be used to endorse or promote products 19127668Sbms * derived from this software without specific prior written permission. 2026180Sfenner * 21127668Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22127668Sbms * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23127668Sbms * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24127668Sbms * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25127668Sbms * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26127668Sbms * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27127668Sbms * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28127668Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29127668Sbms * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30127668Sbms * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31127668Sbms * POSSIBILITY OF SUCH DAMAGE. 3226180Sfenner */ 3326180Sfenner 34127668Sbms/* 35127668Sbms * tcpdump filter for GRE - Generic Routing Encapsulation 36127668Sbms * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE) 37127668Sbms */ 38127668Sbms 3926180Sfenner#ifndef lint 40127668Sbmsstatic const char rcsid[] _U_ = 41190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.28 2005-04-06 21:32:39 mcr Exp $ (LBL)"; 4226180Sfenner#endif 4326180Sfenner 4456893Sfenner#ifdef HAVE_CONFIG_H 4556893Sfenner#include "config.h" 4656893Sfenner#endif 4756893Sfenner 48127668Sbms#include <tcpdump-stdinc.h> 4926180Sfenner 5026180Sfenner#include <stdio.h> 51127668Sbms#include <string.h> 5226180Sfenner 5326180Sfenner#include "interface.h" 5426180Sfenner#include "addrtoname.h" 55127668Sbms#include "extract.h" 5626180Sfenner 57127668Sbms#include "ip.h" 58146773Ssam#include "ethertype.h" 5926180Sfenner 60127668Sbms#define GRE_CP 0x8000 /* checksum present */ 61127668Sbms#define GRE_RP 0x4000 /* routing present */ 62127668Sbms#define GRE_KP 0x2000 /* key present */ 63127668Sbms#define GRE_SP 0x1000 /* sequence# present */ 64127668Sbms#define GRE_sP 0x0800 /* source routing */ 65127668Sbms#define GRE_RECRS 0x0700 /* recursion count */ 66127668Sbms#define GRE_AP 0x0080 /* acknowledgment# present */ 6798524Sfenner 68146773Ssamstruct tok gre_flag_values[] = { 69146773Ssam { GRE_CP, "checksum present"}, 70146773Ssam { GRE_RP, "routing present"}, 71146773Ssam { GRE_KP, "key present"}, 72146773Ssam { GRE_SP, "sequence# present"}, 73146773Ssam { GRE_sP, "source routing present"}, 74146773Ssam { GRE_RECRS, "recursion count"}, 75146773Ssam { GRE_AP, "ack present"}, 76146773Ssam { 0, NULL } 77146773Ssam}; 7826180Sfenner 79146773Ssam#define GRE_VERS_MASK 0x0007 /* protocol version */ 80146773Ssam 81127668Sbms/* source route entry types */ 82127668Sbms#define GRESRE_IP 0x0800 /* IP */ 83127668Sbms#define GRESRE_ASN 0xfffe /* ASN */ 8426180Sfenner 85127668Sbmsvoid gre_print_0(const u_char *, u_int); 86127668Sbmsvoid gre_print_1(const u_char *, u_int); 87127668Sbmsvoid gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int); 88127668Sbmsvoid gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); 89127668Sbmsvoid gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); 9098524Sfenner 91127668Sbmsvoid 92127668Sbmsgre_print(const u_char *bp, u_int length) 93127668Sbms{ 94127668Sbms u_int len = length, vers; 9598524Sfenner 96127668Sbms if (len < 2) { 97127668Sbms printf("[|gre]"); 98127668Sbms return; 99127668Sbms } 100146773Ssam vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK; 101146773Ssam printf("GREv%u",vers); 10298524Sfenner 103146773Ssam switch(vers) { 104146773Ssam case 0: 105146773Ssam gre_print_0(bp, len); 106146773Ssam break; 107146773Ssam case 1: 108146773Ssam gre_print_1(bp, len); 109146773Ssam break; 110146773Ssam default: 111146773Ssam printf(" ERROR: unknown-version"); 112146773Ssam break; 113146773Ssam } 114127668Sbms return; 115127668Sbms 116127668Sbms} 117127668Sbms 11826180Sfennervoid 119127668Sbmsgre_print_0(const u_char *bp, u_int length) 12026180Sfenner{ 121127668Sbms u_int len = length; 122127668Sbms u_int16_t flags, prot; 12326180Sfenner 124127668Sbms flags = EXTRACT_16BITS(bp); 125146773Ssam if (vflag) 126146773Ssam printf(", Flags [%s]", 127146773Ssam bittok2str(gre_flag_values,"none",flags)); 12826180Sfenner 129127668Sbms len -= 2; 130127668Sbms bp += 2; 13126180Sfenner 132127668Sbms if (len < 2) 133127668Sbms goto trunc; 134127668Sbms prot = EXTRACT_16BITS(bp); 135127668Sbms len -= 2; 136127668Sbms bp += 2; 137127668Sbms 138127668Sbms if ((flags & GRE_CP) | (flags & GRE_RP)) { 139127668Sbms if (len < 2) 140127668Sbms goto trunc; 141127668Sbms if (vflag) 142146773Ssam printf(", sum 0x%x", EXTRACT_16BITS(bp)); 143127668Sbms bp += 2; 144127668Sbms len -= 2; 145127668Sbms 146127668Sbms if (len < 2) 147127668Sbms goto trunc; 148146773Ssam printf(", off 0x%x", EXTRACT_16BITS(bp)); 149127668Sbms bp += 2; 150127668Sbms len -= 2; 15126180Sfenner } 15226180Sfenner 153127668Sbms if (flags & GRE_KP) { 154127668Sbms if (len < 4) 155127668Sbms goto trunc; 156146773Ssam printf(", key=0x%x", EXTRACT_32BITS(bp)); 157127668Sbms bp += 4; 158127668Sbms len -= 4; 159127668Sbms } 16098524Sfenner 161127668Sbms if (flags & GRE_SP) { 162127668Sbms if (len < 4) 163127668Sbms goto trunc; 164146773Ssam printf(", seq %u", EXTRACT_32BITS(bp)); 165127668Sbms bp += 4; 166127668Sbms len -= 4; 167127668Sbms } 16898524Sfenner 169127668Sbms if (flags & GRE_RP) { 170127668Sbms for (;;) { 171127668Sbms u_int16_t af; 172127668Sbms u_int8_t sreoff; 173127668Sbms u_int8_t srelen; 17498524Sfenner 175127668Sbms if (len < 4) 176127668Sbms goto trunc; 177127668Sbms af = EXTRACT_16BITS(bp); 178127668Sbms sreoff = *(bp + 2); 179127668Sbms srelen = *(bp + 3); 180127668Sbms bp += 4; 181127668Sbms len -= 4; 18298524Sfenner 183127668Sbms if (af == 0 && srelen == 0) 184127668Sbms break; 185127668Sbms 186127668Sbms gre_sre_print(af, sreoff, srelen, bp, len); 187127668Sbms 188127668Sbms if (len < srelen) 189127668Sbms goto trunc; 190127668Sbms bp += srelen; 191127668Sbms len -= srelen; 19298524Sfenner } 19398524Sfenner } 194127668Sbms 195146773Ssam if (eflag) 196146773Ssam printf(", proto %s (0x%04x)", 197146773Ssam tok2str(ethertype_values,"unknown",prot), 198146773Ssam prot); 199146773Ssam 200146773Ssam printf(", length %u",length); 201146773Ssam 202146773Ssam if (vflag < 1) 203146773Ssam printf(": "); /* put in a colon as protocol demarc */ 204146773Ssam else 205146773Ssam printf("\n\t"); /* if verbose go multiline */ 206146773Ssam 207127668Sbms switch (prot) { 208146773Ssam case ETHERTYPE_IP: 209146773Ssam ip_print(gndo, bp, len); 210127668Sbms break; 211146773Ssam#ifdef INET6 212146773Ssam case ETHERTYPE_IPV6: 213235530Sdelphij ip6_print(gndo, bp, len); 214146773Ssam break; 215146773Ssam#endif 216146773Ssam case ETHERTYPE_MPLS: 217146773Ssam mpls_print(bp, len); 218146773Ssam break; 219146773Ssam case ETHERTYPE_IPX: 220146773Ssam ipx_print(bp, len); 221146773Ssam break; 222146773Ssam case ETHERTYPE_ATALK: 223146773Ssam atalk_print(bp, len); 224146773Ssam break; 225146773Ssam case ETHERTYPE_GRE_ISO: 226127668Sbms isoclns_print(bp, len, len); 227127668Sbms break; 228214478Srpaulo case ETHERTYPE_TEB: 229235530Sdelphij ether_print(gndo, bp, len, len, NULL, NULL); 230214478Srpaulo break; 231127668Sbms default: 232127668Sbms printf("gre-proto-0x%x", prot); 233127668Sbms } 234127668Sbms return; 235127668Sbms 236127668Sbmstrunc: 237127668Sbms printf("[|gre]"); 238127668Sbms} 239127668Sbms 240127668Sbmsvoid 241127668Sbmsgre_print_1(const u_char *bp, u_int length) 242127668Sbms{ 243127668Sbms u_int len = length; 244127668Sbms u_int16_t flags, prot; 245127668Sbms 246127668Sbms flags = EXTRACT_16BITS(bp); 247127668Sbms len -= 2; 248127668Sbms bp += 2; 249127668Sbms 250146773Ssam if (vflag) 251146773Ssam printf(", Flags [%s]", 252146773Ssam bittok2str(gre_flag_values,"none",flags)); 253127668Sbms 254127668Sbms if (len < 2) 255127668Sbms goto trunc; 256127668Sbms prot = EXTRACT_16BITS(bp); 257127668Sbms len -= 2; 258127668Sbms bp += 2; 259127668Sbms 260127668Sbms 26198524Sfenner if (flags & GRE_KP) { 262127668Sbms u_int32_t k; 263127668Sbms 264127668Sbms if (len < 4) 265127668Sbms goto trunc; 266127668Sbms k = EXTRACT_32BITS(bp); 267146773Ssam printf(", call %d", k & 0xffff); 268127668Sbms len -= 4; 269127668Sbms bp += 4; 27098524Sfenner } 271127668Sbms 27298524Sfenner if (flags & GRE_SP) { 273127668Sbms if (len < 4) 274127668Sbms goto trunc; 275146773Ssam printf(", seq %u", EXTRACT_32BITS(bp)); 276127668Sbms bp += 4; 277127668Sbms len -= 4; 27898524Sfenner } 279127668Sbms 280127668Sbms if (flags & GRE_AP) { 281127668Sbms if (len < 4) 282127668Sbms goto trunc; 283146773Ssam printf(", ack %u", EXTRACT_32BITS(bp)); 284127668Sbms bp += 4; 285127668Sbms len -= 4; 28698524Sfenner } 287127668Sbms 288146773Ssam if ((flags & GRE_SP) == 0) 289146773Ssam printf(", no-payload"); 29026180Sfenner 291146773Ssam if (eflag) 292146773Ssam printf(", proto %s (0x%04x)", 293146773Ssam tok2str(ethertype_values,"unknown",prot), 294146773Ssam prot); 295146773Ssam 296146773Ssam printf(", length %u",length); 297146773Ssam 298146773Ssam if ((flags & GRE_SP) == 0) 299146773Ssam return; 300146773Ssam 301146773Ssam if (vflag < 1) 302146773Ssam printf(": "); /* put in a colon as protocol demarc */ 303146773Ssam else 304146773Ssam printf("\n\t"); /* if verbose go multiline */ 305146773Ssam 306127668Sbms switch (prot) { 307146773Ssam case ETHERTYPE_PPP: 308146773Ssam ppp_print(bp, len); 309127668Sbms break; 310127668Sbms default: 311127668Sbms printf("gre-proto-0x%x", prot); 312127668Sbms break; 313127668Sbms } 31426180Sfenner return; 31526180Sfenner 31626180Sfennertrunc: 317127668Sbms printf("[|gre]"); 318127668Sbms} 31926180Sfenner 320127668Sbmsvoid 321127668Sbmsgre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen, 322127668Sbms const u_char *bp, u_int len) 323127668Sbms{ 324127668Sbms switch (af) { 325127668Sbms case GRESRE_IP: 326146773Ssam printf(", (rtaf=ip"); 327127668Sbms gre_sre_ip_print(sreoff, srelen, bp, len); 328127668Sbms printf(") "); 329127668Sbms break; 330127668Sbms case GRESRE_ASN: 331146773Ssam printf(", (rtaf=asn"); 332127668Sbms gre_sre_asn_print(sreoff, srelen, bp, len); 333127668Sbms printf(") "); 334127668Sbms break; 335127668Sbms default: 336146773Ssam printf(", (rtaf=0x%x) ", af); 337127668Sbms } 33826180Sfenner} 339127668Sbmsvoid 340127668Sbmsgre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 341127668Sbms{ 342127668Sbms struct in_addr a; 343127668Sbms const u_char *up = bp; 344127668Sbms 345127668Sbms if (sreoff & 3) { 346146773Ssam printf(", badoffset=%u", sreoff); 347127668Sbms return; 348127668Sbms } 349127668Sbms if (srelen & 3) { 350146773Ssam printf(", badlength=%u", srelen); 351127668Sbms return; 352127668Sbms } 353127668Sbms if (sreoff >= srelen) { 354146773Ssam printf(", badoff/len=%u/%u", sreoff, srelen); 355127668Sbms return; 356127668Sbms } 357127668Sbms 358127668Sbms for (;;) { 359127668Sbms if (len < 4 || srelen == 0) 360127668Sbms return; 361127668Sbms 362127668Sbms memcpy(&a, bp, sizeof(a)); 363127668Sbms printf(" %s%s", 364127668Sbms ((bp - up) == sreoff) ? "*" : "", 365127668Sbms inet_ntoa(a)); 366127668Sbms 367127668Sbms bp += 4; 368127668Sbms len -= 4; 369127668Sbms srelen -= 4; 370127668Sbms } 371127668Sbms} 372127668Sbms 373127668Sbmsvoid 374127668Sbmsgre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 375127668Sbms{ 376127668Sbms const u_char *up = bp; 377127668Sbms 378127668Sbms if (sreoff & 1) { 379146773Ssam printf(", badoffset=%u", sreoff); 380127668Sbms return; 381127668Sbms } 382127668Sbms if (srelen & 1) { 383146773Ssam printf(", badlength=%u", srelen); 384127668Sbms return; 385127668Sbms } 386127668Sbms if (sreoff >= srelen) { 387146773Ssam printf(", badoff/len=%u/%u", sreoff, srelen); 388127668Sbms return; 389127668Sbms } 390127668Sbms 391127668Sbms for (;;) { 392127668Sbms if (len < 2 || srelen == 0) 393127668Sbms return; 394127668Sbms 395127668Sbms printf(" %s%x", 396127668Sbms ((bp - up) == sreoff) ? "*" : "", 397127668Sbms EXTRACT_16BITS(bp)); 398127668Sbms 399127668Sbms bp += 2; 400127668Sbms len -= 2; 401127668Sbms srelen -= 2; 402127668Sbms } 403127668Sbms} 404