1 /* 2 * Copyright (c) 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Lawrence Berkeley Laboratory, 11 * Berkeley, CA. The name of the University may not be used to 12 * endorse or promote products derived from this software without 13 * specific prior written permission. 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 * 18 * Initial contribution from John Hawkinson <jhawk@bbnplanet.com> 19 * 20 * This module implements support for decoding GRE (Generic Routing 21 * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702. 22 * This code only supports the IP encapsulation thereof. 23 */ 24 25 #ifndef lint 26 static const char rcsid[] = 27 "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.13 2001/06/15 22:17:31 fenner Exp $"; 28 #endif 29 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <sys/param.h> 35 #include <sys/time.h> 36 #include <sys/uio.h> 37 #include <sys/socket.h> 38 39 #include <netinet/in.h> 40 41 #include <netdb.h> 42 #include <stdio.h> 43 44 #include "interface.h" 45 #include "addrtoname.h" 46 #include "extract.h" /* must come after interface.h */ 47 48 struct gre { 49 u_int16_t flags; 50 u_int16_t proto; 51 }; 52 53 /* RFC 2784 - GRE */ 54 #define GRE_CP 0x8000 /* Checksum Present */ 55 #define GRE_VER_MASK 0x0007 /* Version */ 56 57 /* RFC 2890 - Key and Sequence extensions to GRE */ 58 #define GRE_KP 0x2000 /* Key Present */ 59 #define GRE_SP 0x1000 /* Sequence Present */ 60 61 /* Legacy from RFC 1700 */ 62 #define GRE_RP 0x4000 /* Routing Present */ 63 #define GRE_sP 0x0800 /* strict source route present */ 64 #define GRE_RECUR_MASK 0x0700 /* Recursion Control */ 65 #define GRE_RECUR_SHIFT 8 66 67 #define GRE_COP (GRE_RP|GRE_CP) /* Checksum & Offset Present */ 68 69 /* "Enhanced GRE" from RFC2637 - PPTP */ 70 #define GRE_AP 0x0080 /* Ack present */ 71 72 #define GRE_MBZ_MASK 0x0078 /* not defined */ 73 74 /* 75 * Deencapsulate and print a GRE-tunneled IP datagram 76 */ 77 void 78 gre_print(const u_char *bp, u_int length) 79 { 80 const u_char *cp = bp + 4; 81 const struct gre *gre; 82 u_int16_t flags, proto; 83 u_short ver=0; 84 u_short extracted_ethertype; 85 86 gre = (const struct gre *)bp; 87 88 TCHECK(gre->proto); 89 flags = EXTRACT_16BITS(&gre->flags); 90 proto = EXTRACT_16BITS(&gre->proto); 91 (void)printf("gre "); 92 93 if (flags) { 94 /* Decode the flags */ 95 putchar('['); 96 if (flags & GRE_CP) 97 putchar('C'); 98 if (flags & GRE_RP) 99 putchar('R'); 100 if (flags & GRE_KP) 101 putchar('K'); 102 if (flags & GRE_SP) 103 putchar('S'); 104 if (flags & GRE_sP) 105 putchar('s'); 106 if (flags & GRE_AP) 107 putchar('A'); 108 if (flags & GRE_RECUR_MASK) 109 printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT); 110 ver = flags & GRE_VER_MASK; 111 printf("v%u", ver); 112 113 if (flags & GRE_MBZ_MASK) 114 printf("!%x", flags & GRE_MBZ_MASK); 115 fputs("] ", stdout); 116 } 117 118 if (flags & GRE_COP) { 119 int checksum, offset; 120 121 TCHECK2(*cp, 4); 122 checksum = EXTRACT_16BITS(cp); 123 offset = EXTRACT_16BITS(cp + 2); 124 125 if (flags & GRE_CP) { 126 /* Checksum present */ 127 128 /* todo: check checksum */ 129 if (vflag > 1) 130 printf("C:%04x ", checksum); 131 } 132 if (flags & GRE_RP) { 133 /* Offset present */ 134 135 if (vflag > 1) 136 printf("O:%04x ", offset); 137 } 138 cp += 4; /* skip checksum and offset */ 139 } 140 if (flags & GRE_KP) { 141 TCHECK2(*cp, 4); 142 if (ver == 1) { /* PPTP */ 143 if (vflag > 1) 144 printf("PL:%u ", EXTRACT_16BITS(cp)); 145 printf("ID:%04x ", EXTRACT_16BITS(cp+2)); 146 } 147 else 148 printf("K:%08x ", EXTRACT_32BITS(cp)); 149 cp += 4; /* skip key */ 150 } 151 if (flags & GRE_SP) { 152 TCHECK2(*cp, 4); 153 printf("S:%u ", EXTRACT_32BITS(cp)); 154 cp += 4; /* skip seq */ 155 } 156 if (flags & GRE_AP && ver >= 1) { 157 TCHECK2(*cp, 4); 158 printf("A:%u ", EXTRACT_32BITS(cp)); 159 cp += 4; /* skip ack */ 160 } 161 /* We don't support routing fields (variable length) now. Punt. */ 162 if (flags & GRE_RP) 163 return; 164 165 TCHECK(cp[0]); 166 167 length -= cp - bp; 168 if (ether_encap_print(proto, cp, length, length, 169 &extracted_ethertype) == 0) 170 printf("gre-proto-0x%04X", proto); 171 return; 172 173 trunc: 174 fputs("[|gre]", stdout); 175 176 } 177