diff options
| -rw-r--r-- | Makefile.in | 2 | ||||
| -rw-r--r-- | interface.h | 4 | ||||
| -rw-r--r-- | ipnet.h | 13 | ||||
| -rw-r--r-- | print-ipnet.c | 132 | ||||
| -rw-r--r-- | tcpdump.c | 3 |
5 files changed, 153 insertions, 1 deletions
diff --git a/Makefile.in b/Makefile.in index 04efdcd7..ca29ce85 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,7 +77,7 @@ CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c print-eap.c print-eigrp.c\ print-esp.c print-ether.c print-fddi.c print-fr.c \ print-gre.c print-hsrp.c print-icmp.c print-igmp.c \ - print-igrp.c print-ip.c print-ipcomp.c print-ipfc.c \ + print-igrp.c print-ip.c print-ipcomp.c print-ipfc.c print-ipnet.c \ print-ipx.c print-isoclns.c print-juniper.c print-krb.c \ print-l2tp.c print-lane.c print-ldp.c print-lldp.c print-llc.c \ print-lmp.c print-lspping.c print-lwapp.c \ diff --git a/interface.h b/interface.h index 9038b433..4296823a 100644 --- a/interface.h +++ b/interface.h @@ -322,6 +322,10 @@ extern void bfd_print(const u_char *, u_int, u_int); extern void sip_print(const u_char *, u_int); extern void syslog_print(const u_char *, u_int); extern u_int bt_if_print(const struct pcap_pkthdr *, const u_char *); +extern void ipnet_print(const u_char *, u_int, u_int); +extern u_int ipnet_if_print(const struct pcap_pkthdr *, const u_char *); +extern int ipnet_encap_print(u_short, const u_char *, u_int, u_int); + extern u_int usb_linux_print(const struct pcap_pkthdr *, const u_char *); #ifdef INET6 diff --git a/ipnet.h b/ipnet.h new file mode 100644 index 00000000..ae692842 --- /dev/null +++ b/ipnet.h @@ -0,0 +1,13 @@ +typedef struct ipnet_hdr { + uint8_t iph_version; + uint8_t iph_family; + uint16_t iph_htype; + uint32_t iph_pktlen; + uint32_t iph_ifindex; + uint32_t iph_grifindex; + uint32_t iph_zsrc; + uint32_t iph_zdst; +} ipnet_hdr_t; + +#define IPH_AF_INET 2 /* Matches Solaris's AF_INET */ +#define IPH_AF_INET6 26 /* Matches Solaris's AF_INET6 */ diff --git a/print-ipnet.c b/print-ipnet.c new file mode 100644 index 00000000..56b49784 --- /dev/null +++ b/print-ipnet.c @@ -0,0 +1,132 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tcpdump-stdinc.h> + +#include <stdio.h> +#include <pcap.h> + +#include "interface.h" +#include "addrtoname.h" +#include "ipnet.h" + +#ifdef DLT_IPNET + +int ipnet_encap_print(u_short, const u_char *, u_int, u_int); + +const struct tok ipnet_values[] = { + { IPH_AF_INET, "IPv4" }, + { IPH_AF_INET6, "IPv6" }, + { 0, NULL } +}; + +static inline void +ipnet_hdr_print(register const u_char *bp, u_int length) +{ + const ipnet_hdr_t *hdr; + hdr = (const ipnet_hdr_t *)bp; + + (void)printf("%d > %d", hdr->iph_zsrc, hdr->iph_zdst); + + if (!qflag) { + (void)printf(", family %s (%d)", + tok2str(ipnet_values, "Unknown", + hdr->iph_family), + hdr->iph_family); + } else { + (void)printf(", %s", + tok2str(ipnet_values, + "Unknown Ethertype (0x%04x)", + hdr->iph_family)); + } + + (void)printf(", length %u: ", length); +} + +void +ipnet_print(const u_char *p, u_int length, u_int caplen) +{ + ipnet_hdr_t *hdr; + + if (caplen < sizeof(ipnet_hdr_t)) { + printf("[|ipnet]"); + return; + } + + if (eflag) + ipnet_hdr_print(p, length); + + length -= sizeof(ipnet_hdr_t); + caplen -= sizeof(ipnet_hdr_t); + hdr = (ipnet_hdr_t *)p; + p += sizeof(ipnet_hdr_t); + + if (ipnet_encap_print(hdr->iph_family, p, length, caplen) == 0) { + if (!eflag) + ipnet_hdr_print((u_char *)hdr, + length + sizeof(ipnet_hdr_t)); + + if (!suppress_default_print) + default_print(p, caplen); + } +} + +/* + * This is the top level routine of the printer. 'p' points + * to the ether header of the packet, 'h->ts' is the timestamp, + * 'h->len' is the length of the packet off the wire, and 'h->caplen' + * is the number of bytes actually captured. + */ +u_int +ipnet_if_print(const struct pcap_pkthdr *h, const u_char *p) +{ + ipnet_print(p, h->len, h->caplen); + + return (sizeof(ipnet_hdr_t)); +} + +/* + * Prints the packet encapsulated in an Ethernet data segment + * (or an equivalent encapsulation), given the Ethernet type code. + * + * Returns non-zero if it can do so, zero if the ethertype is unknown. + * + * The Ethernet type code is passed through a pointer; if it was + * ETHERTYPE_8021Q, it gets updated to be the Ethernet type of + * the 802.1Q payload, for the benefit of lower layers that might + * want to know what it is. + */ + +int +ipnet_encap_print(u_short family, const u_char *p, + u_int length, u_int caplen) +{ + recurse: + + switch (family) { + + case IPH_AF_INET: + ip_print(gndo, p, length); + return (1); + +#ifdef INET6 + case IPH_AF_INET6: + ip6_print(p, length); + return (1); +#endif /*INET6*/ + + default: + return(0); + } +} + + +/* + * Local Variables: + * c-style: whitesmith + * c-basic-offset: 8 + * End: + */ + +#endif /* DLT_IPNET */ @@ -282,6 +282,9 @@ static struct printer printers[] = { #if defined(HAVE_PCAP_USB_H) && defined(DLT_USB_LINUX_MMAPPED) { usb_linux_print, DLT_USB_LINUX_MMAPPED}, #endif +#ifdef DLT_IPNET + { ipnet_if_print, DLT_IPNET }, +#endif { NULL, 0 }, }; |
