1 /* $OpenBSD: print-gre.c,v 1.2 2000/10/03 14:31:57 ho Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms are permitted 8 * provided that the above copyright notice and this paragraph are 9 * duplicated in all such forms and that any documentation, 10 * advertising materials, and other materials related to such 11 * distribution and use acknowledge that the software was developed 12 * by the University of California, Lawrence Berkeley Laboratory, 13 * Berkeley, CA. The name of the University may not be used to 14 * endorse or promote products derived from this software without 15 * specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * Initial contribution from John Hawkinson <jhawk@bbnplanet.com> 21 * 22 * This module implements support for decoding GRE (Generic Routing 23 * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702. 24 * This code only supports the IP encapsulation thereof. 25 */ 26 27 #ifndef lint 28 static const char rcsid[] = 29 "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-gre.c,v 1.2 2000/10/03 14:31:57 ho Exp $"; 30 #endif 31 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/uio.h> 35 #include <sys/socket.h> 36 37 #include <netinet/in.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.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 #define GREPROTO_IP 0x0800 82 83 84 /* 85 * Deencapsulate and print a GRE-tunneled IP datagram 86 */ 87 void 88 gre_print(const u_char *bp, u_int length) 89 { 90 const u_char *cp = bp + 4; 91 const struct gre *gre; 92 u_short flags, proto; 93 94 gre = (const struct gre *)bp; 95 96 if (length < GRE_SIZE) { 97 goto trunc; 98 } 99 flags = EXTRACT_16BITS(&gre->flags); 100 proto = EXTRACT_16BITS(&gre->proto); 101 102 if (vflag) { 103 /* Decode the flags */ 104 putchar('['); 105 if (flags & GRE_CP) 106 putchar('C'); 107 if (flags & GRE_RP) 108 putchar('R'); 109 if (flags & GRE_KP) 110 putchar('K'); 111 if (flags & GRE_SP) 112 putchar('S'); 113 fputs("] ", stdout); 114 } 115 /* Checksum & Offset are present */ 116 if ((flags & GRE_CP) | (flags & GRE_RP)) 117 cp += 4; 118 119 /* We don't support routing fields (variable length) now. Punt. */ 120 if (flags & GRE_RP) 121 return; 122 123 if (flags & GRE_KP) 124 cp += 4; 125 if (flags & GRE_SP) 126 cp += 4; 127 128 switch (proto) { 129 130 case GREPROTO_IP: 131 ip_print(cp, length - ((cp - bp) / sizeof(u_char))); 132 break; 133 134 default: 135 printf("gre-proto-0x%04X", proto); 136 break; 137 } 138 return; 139 140 trunc: 141 fputs("[|gre]", stdout); 142 143 } 144