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