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.6 1999/11/21 09:36:52 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 #include <netinet/in_systm.h> 41 #include <netinet/ip.h> 42 43 #include <netdb.h> 44 #include <stdio.h> 45 46 #include "interface.h" 47 #include "addrtoname.h" 48 #include "extract.h" /* must come after interface.h */ 49 50 #define GRE_SIZE (20) 51 52 struct gre { 53 u_short flags; 54 u_short proto; 55 union { 56 struct gre_ckof { 57 u_short cksum; 58 u_short offset; 59 } gre_ckof; 60 u_int32_t key; 61 u_int32_t seq; 62 } gre_void1; 63 union { 64 u_int32_t key; 65 u_int32_t seq; 66 u_int32_t routing; 67 } gre_void2; 68 union { 69 u_int32_t seq; 70 u_int32_t routing; 71 } gre_void3; 72 union { 73 u_int32_t routing; 74 } gre_void4; 75 }; 76 77 #define GRE_CP 0x8000 /* Checksum Present */ 78 #define GRE_RP 0x4000 /* Routing Present */ 79 #define GRE_KP 0x2000 /* Key Present */ 80 #define GRE_SP 0x1000 /* Sequence Present */ 81 82 83 /* 84 * Deencapsulate and print a GRE-tunneled IP datagram 85 */ 86 void 87 gre_print(const u_char *bp, u_int length) 88 { 89 const u_char *cp = bp + 4; 90 const struct gre *gre; 91 u_short flags, proto; 92 93 gre = (const struct gre *)bp; 94 95 if (length < GRE_SIZE) { 96 goto trunc; 97 } 98 flags = EXTRACT_16BITS(&gre->flags); 99 proto = EXTRACT_16BITS(&gre->proto); 100 101 if (vflag) { 102 /* Decode the flags */ 103 putchar('['); 104 if (flags & GRE_CP) 105 putchar('C'); 106 if (flags & GRE_RP) 107 putchar('R'); 108 if (flags & GRE_KP) 109 putchar('K'); 110 if (flags & GRE_SP) 111 putchar('S'); 112 fputs("] ", stdout); 113 } 114 /* Checksum & Offset are present */ 115 if ((flags & GRE_CP) | (flags & GRE_RP)) 116 cp += 4; 117 118 /* We don't support routing fields (variable length) now. Punt. */ 119 if (flags & GRE_RP) 120 return; 121 122 if (flags & GRE_KP) 123 cp += 4; 124 if (flags & GRE_SP) 125 cp += 4; 126 127 length -= cp - bp; 128 if (ether_encap_print(proto, cp, length, length) == 0) 129 printf("gre-proto-0x%04X", proto); 130 return; 131 132 trunc: 133 fputs("[|gre]", stdout); 134 135 } 136