/* * Copyright (c) 1999 * RISS-Telecom Networking Center. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may 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 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #if __STDC__ struct mbuf; struct rtentry; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ethertype.h" #include "interface.h" #include "addrtoname.h" const u_char *packetp; const u_char *snapend; struct printer { pcap_handler f; int type; }; static struct printer printers[] = { { ether_if_print, DLT_EN10MB }, { sl_if_print, DLT_SLIP }, { sl_bsdos_if_print, DLT_SLIP_BSDOS }, { ppp_if_print, DLT_PPP }, { ppp_bsdos_if_print, DLT_PPP_BSDOS }, { null_if_print, DLT_NULL }, { raw_if_print, DLT_RAW }, { NULL, 0 }, }; pcap_handler lookup_printer(int type) { struct printer *p; for (p = printers; p->f; p++) if (type == p->type) return p->f; error("unknown data link type 0x%x", type); /* NOREACHED */ } /* * This is the top level routine of the printer. 'p' is the points * to the ether header of the packet, 'tvp' is the timestamp, * 'length' is the length of the packet off the wire, and 'caplen' * is the number of bytes actually captured. */ void ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; struct ether_header *ep; if (caplen < sizeof(struct ether_header)) return; packetp = p; snapend = p + caplen; length -= sizeof(struct ether_header); caplen -= sizeof(struct ether_header); ep = (struct ether_header *)p; p += sizeof(struct ether_header); if(ntohs(ep->ether_type) == ETHERTYPE_IP) processing_ip(p, length); } /* * The DLT_NULL packet header is 4 bytes long. It contains a network * order 32 bit integer that specifies the family, e.g. AF_INET */ #define NULL_HDRLEN 4 void null_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { u_int family; u_int length = h->len; u_int caplen = h->caplen; memcpy((char *)&family, (char *)p, sizeof(family)); packetp = p; snapend = p + caplen; length -= NULL_HDRLEN; if (family == AF_INET) processing_ip(p + NULL_HDRLEN, length); } void ppp_if_print(u_char *user, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; if (caplen < PPP_HDRLEN) { return; } /* * Some printers want to get back at the link level addresses, * and/or check that they're not walking off the end of the packet. * Rather than pass them all the way down, we set these globals. */ packetp = p; snapend = p + caplen; length -= PPP_HDRLEN; if(PPP_PROTOCOL(p) == PPP_IP || PPP_PROTOCOL(p) == ETHERTYPE_IP) { processing_ip((const u_char *)(p + PPP_HDRLEN), length); } } #define PPP_BSDI_HDRLEN 24 #define PPP_BSDI_ADDRESS 0xff #define PPP_BSDI_CONTROL 0x03 /* BSD/OS specific PPP printer */ void ppp_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; register int hdrlength; u_short ptype; if (caplen < PPP_BSDI_HDRLEN) { return; } /* * Some printers want to get back at the link level addresses, * and/or check that they're not walking off the end of the packet. * Rather than pass them all the way down, we set these globals. */ packetp = p; snapend = p + caplen; hdrlength = 0; if (p[0] == PPP_BSDI_ADDRESS && p[1] == PPP_BSDI_CONTROL) { p += 2; hdrlength = 2; } /* Retrieve the protocol type */ if (*p & 01) { /* Compressed protocol field */ ptype = *p++; hdrlength++; } else { /* Un-compressed protocol field */ ptype = ntohs(*(u_short *)p); p += 2; hdrlength += 2; } length -= hdrlength; if (ptype == PPP_IP) processing_ip(p, length); } /* * The DLT_RAW packet has no header. It contains a raw IP packet. */ void raw_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; /* * Some printers want to get back at the link level addresses, * and/or check that they're not walking off the end of the packet. * Rather than pass them all the way down, we set these globals. */ packetp = p; snapend = p + caplen; processing_ip(p, length); } /* XXX BSD/OS 2.1 compatibility */ #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR) #define SLIP_HDRLEN SLC_BPFHDR #define SLX_DIR 0 #define SLX_CHDR (SLC_BPFHDRLEN - 1) #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN) #endif /* XXX needs more hacking to work right */ void sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { register u_int caplen = h->caplen; register u_int length = h->len; if (caplen < SLIP_HDRLEN) { return; } /* * Some printers want to get back at the link level addresses, * and/or check that they're not walking off the end of the packet. * Rather than pass them all the way down, we set these globals. */ packetp = p; snapend = p + caplen; length -= SLIP_HDRLEN; processing_ip((p + SLIP_HDRLEN), length); } void sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { register u_int caplen = h->caplen; register u_int length = h->len; if (caplen < SLIP_HDRLEN) { return; } /* * Some printers want to get back at the link level addresses, * and/or check that they're not walking off the end of the packet. * Rather than pass them all the way down, we set these globals. */ packetp = p; snapend = p + caplen; length -= SLIP_HDRLEN; processing_ip(p + SLIP_HDRLEN, length); }