| /* |
| * Copyright (c) 1996 |
| * The Regents of the University of California. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms are permitted |
| * provided that the above copyright notice and this paragraph are |
| * duplicated in all such forms and that any documentation, |
| * advertising materials, and other materials related to such |
| * distribution and use acknowledge that the software was developed |
| * by the University of California, Lawrence Berkeley Laboratory, |
| * Berkeley, CA. The name of the University may not be used to |
| * endorse or promote products derived from this software without |
| * specific prior written permission. |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
| * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * Initial contribution from John Hawkinson <jhawk@bbnplanet.com> |
| * |
| * This module implements support for decoding GRE (Generic Routing |
| * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702. |
| * This code only supports the IP encapsulation thereof. |
| */ |
| |
| #ifndef lint |
| static const char rcsid[] = |
| "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.6 1999-11-21 09:36:52 fenner Exp $"; |
| #endif |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <sys/param.h> |
| #include <sys/time.h> |
| #include <sys/uio.h> |
| #include <sys/socket.h> |
| |
| #include <netinet/in.h> |
| #include <netinet/in_systm.h> |
| #include <netinet/ip.h> |
| |
| #include <netdb.h> |
| #include <stdio.h> |
| |
| #include "interface.h" |
| #include "addrtoname.h" |
| #include "extract.h" /* must come after interface.h */ |
| |
| #define GRE_SIZE (20) |
| |
| struct gre { |
| u_short flags; |
| u_short proto; |
| union { |
| struct gre_ckof { |
| u_short cksum; |
| u_short offset; |
| } gre_ckof; |
| u_int32_t key; |
| u_int32_t seq; |
| } gre_void1; |
| union { |
| u_int32_t key; |
| u_int32_t seq; |
| u_int32_t routing; |
| } gre_void2; |
| union { |
| u_int32_t seq; |
| u_int32_t routing; |
| } gre_void3; |
| union { |
| u_int32_t routing; |
| } gre_void4; |
| }; |
| |
| #define GRE_CP 0x8000 /* Checksum Present */ |
| #define GRE_RP 0x4000 /* Routing Present */ |
| #define GRE_KP 0x2000 /* Key Present */ |
| #define GRE_SP 0x1000 /* Sequence Present */ |
| |
| |
| /* |
| * Deencapsulate and print a GRE-tunneled IP datagram |
| */ |
| void |
| gre_print(const u_char *bp, u_int length) |
| { |
| const u_char *cp = bp + 4; |
| const struct gre *gre; |
| u_short flags, proto; |
| |
| gre = (const struct gre *)bp; |
| |
| if (length < GRE_SIZE) { |
| goto trunc; |
| } |
| flags = EXTRACT_16BITS(&gre->flags); |
| proto = EXTRACT_16BITS(&gre->proto); |
| |
| if (vflag) { |
| /* Decode the flags */ |
| putchar('['); |
| if (flags & GRE_CP) |
| putchar('C'); |
| if (flags & GRE_RP) |
| putchar('R'); |
| if (flags & GRE_KP) |
| putchar('K'); |
| if (flags & GRE_SP) |
| putchar('S'); |
| fputs("] ", stdout); |
| } |
| /* Checksum & Offset are present */ |
| if ((flags & GRE_CP) | (flags & GRE_RP)) |
| cp += 4; |
| |
| /* We don't support routing fields (variable length) now. Punt. */ |
| if (flags & GRE_RP) |
| return; |
| |
| if (flags & GRE_KP) |
| cp += 4; |
| if (flags & GRE_SP) |
| cp += 4; |
| |
| length -= cp - bp; |
| if (ether_encap_print(proto, cp, length, length) == 0) |
| printf("gre-proto-0x%04X", proto); |
| return; |
| |
| trunc: |
| fputs("[|gre]", stdout); |
| |
| } |