From: Emil Mikulic Date: Sat, 7 Jul 2012 06:33:47 +0000 (+1000) Subject: Clean up decode module. X-Git-Tag: 3.0.716~20 X-Git-Url: https://unix4lyfe.org/gitweb/darkstat/commitdiff_plain/5a823d7f30a6f2da6f75a2729bb930e407d57924 Clean up decode module. - cap calls into decode, then acct. - Decode functions can return 0 on failure. --- diff --git a/Makefile.in b/Makefile.in index 58cf4d6..fbd871f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -124,15 +124,15 @@ acct.o: acct.c acct.h decode.h addr.h conv.h daylog.h graph_db.h err.h \ cdefs.h hosts_db.h localip.h now.h opt.h addr.o: addr.c addr.h bsd.o: bsd.c bsd.h config.h cdefs.h -cap.o: cap.c cdefs.h cap.h config.h conv.h decode.h addr.h hosts_db.h \ - localip.h opt.h err.h +cap.o: cap.c acct.h cdefs.h cap.h config.h conv.h decode.h addr.h err.h \ + hosts_db.h localip.h opt.h conv.o: conv.c conv.h err.h cdefs.h darkstat.o: darkstat.c acct.h cap.h cdefs.h config.h conv.h daylog.h \ graph_db.h db.h dns.h err.h http.h hosts_db.h addr.h localip.h ncache.h \ pidfile.h now.h daylog.o: daylog.c err.h cdefs.h daylog.h graph_db.h str.h now.h db.o: db.c cdefs.h err.h hosts_db.h addr.h graph_db.h db.h -decode.o: decode.c cdefs.h acct.h cap.h decode.h addr.h err.h opt.h +decode.o: decode.c cdefs.h decode.h addr.h err.h opt.h dns.o: dns.c cdefs.h conv.h decode.h addr.h dns.h err.h hosts_db.h \ queue.h str.h tree.h bsd.h config.h err.o: err.c cdefs.h err.h opt.h pidfile.h bsd.h config.h diff --git a/cap.c b/cap.c index 1686ae9..d649d5d 100644 --- a/cap.c +++ b/cap.c @@ -7,11 +7,13 @@ * GNU General Public License version 2. (see COPYING.GPL) */ +#include "acct.h" #include "cdefs.h" #include "cap.h" #include "config.h" #include "conv.h" #include "decode.h" +#include "err.h" #include "hosts_db.h" #include "localip.h" #include "opt.h" @@ -24,7 +26,7 @@ # include /* Solaris' FIONBIO hides here */ #endif #include -#include "err.h" +#include #include #include #include @@ -89,8 +91,8 @@ cap_init(const char *device, const char *filter, int promisc) linkhdr = getlinkhdr(linktype); if (linkhdr == NULL) errx(1, "unknown linktype %d", linktype); - if (linkhdr->handler == NULL) - errx(1, "no handler for linktype %d", linktype); + if (linkhdr->decoder == NULL) + errx(1, "no decoder for linktype %d", linktype); snaplen = getsnaplen(linkhdr); if (opt_want_pppoe) { snaplen += PPPOE_HDR_LEN; @@ -251,10 +253,9 @@ hexdump(const u_char *buf, const uint32_t len) if (col == 0) printf(" "); printf("%02x", buf[i]); if (i+1 == linkhdr->hdrlen) - printf("["); - else if (i+1 == linkhdr->hdrlen + IP_HDR_LEN) - printf("]"); - else printf(" "); + printf("|"); /* marks end of link headers (e.g. ethernet) */ + else + printf(" "); col += 3; if (col >= 72) { printf("\n"); @@ -265,15 +266,20 @@ hexdump(const u_char *buf, const uint32_t len) printf("\n"); } -/* - * Callback function for pcap_dispatch() which chains to the decoder specified +/* Callback function for pcap_dispatch() which chains to the decoder specified * in linkhdr struct. */ -static void -callback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) -{ - if (opt_want_hexdump) hexdump(bytes, h->caplen); - linkhdr->handler(user, h, bytes); +static void callback(u_char *user _unused_, + const struct pcap_pkthdr *pheader, + const u_char *pdata) { + struct pktsummary sm; + + if (opt_want_hexdump) + hexdump(pdata, pheader->caplen); + memset(&sm, 0, sizeof(sm)); + sm.time = pheader->ts.tv_sec; + if (linkhdr->decoder(pheader, pdata, &sm)) + acct_for(&sm); } /* @@ -374,8 +380,8 @@ cap_from_file(const char *capfile, const char *filter) linkhdr = getlinkhdr(linktype); if (linkhdr == NULL) errx(1, "unknown linktype %d", linktype); - if (linkhdr->handler == NULL) - errx(1, "no handler for linktype %d", linktype); + if (linkhdr->decoder == NULL) + errx(1, "no decoder for linktype %d", linktype); if (linktype == DLT_EN10MB) /* FIXME: impossible with capfile? */ hosts_db_show_macs = 1; diff --git a/decode.c b/decode.c index 9d88807..e8e5f35 100644 --- a/decode.c +++ b/decode.c @@ -11,8 +11,6 @@ */ #include "cdefs.h" -#include "acct.h" -#include "cap.h" #include "decode.h" #include "err.h" #include "opt.h" @@ -63,36 +61,42 @@ #include /* struct tcphdr */ #include /* struct udphdr */ +#define PPP_HDR_LEN 4 +#define FDDI_HDR_LEN 21 +#define IP_HDR_LEN sizeof(struct ip) +#define IPV6_HDR_LEN sizeof(struct ip6_hdr) +#define TCP_HDR_LEN sizeof(struct tcphdr) +#define UDP_HDR_LEN sizeof(struct udphdr) +#define NULL_HDR_LEN 4 +#define SLL_HDR_LEN 16 +#define RAW_HDR_LEN 0 + #ifndef IPV6_VERSION -#define IPV6_VERSION 0x60 +# define IPV6_VERSION 0x60 #endif #ifndef IPV6_VERSION_MASK -#define IPV6_VERSION_MASK 0xf0 +# define IPV6_VERSION_MASK 0xF0 #endif -static void decode_ether(u_char *, const struct pcap_pkthdr *, - const u_char *); -static void decode_loop(u_char *, const struct pcap_pkthdr *, - const u_char *); -static void decode_null(u_char *, const struct pcap_pkthdr *, - const u_char *); -static void decode_ppp(u_char *, const struct pcap_pkthdr *, - const u_char *); -static void decode_pppoe(u_char *, const struct pcap_pkthdr *, - const u_char *); -static void decode_pppoe_real(const u_char *pdata, const uint32_t len, - struct pktsummary *sm); +static int decode_ether(DECODER_ARGS); +static int decode_loop(DECODER_ARGS); +static int decode_null(DECODER_ARGS); +static int decode_ppp(DECODER_ARGS); +static int decode_pppoe(DECODER_ARGS); #ifdef DLT_LINUX_SLL -static void decode_linux_sll(u_char *, const struct pcap_pkthdr *, - const u_char *); +static int decode_linux_sll(DECODER_ARGS); #endif -static void decode_raw(u_char *, const struct pcap_pkthdr *, - const u_char *); -static int decode_ip(const u_char *pdata, const uint32_t len, - struct pktsummary *sm); -static int decode_ipv6(const u_char *pdata, const uint32_t len, - struct pktsummary *sm); +static int decode_raw(DECODER_ARGS); + +#define HELPER_ARGS const u_char *pdata, \ + const uint32_t len, \ + struct pktsummary *sm + +static int helper_pppoe(HELPER_ARGS); +static int helper_ip(HELPER_ARGS); +static int helper_ipv6(HELPER_ARGS); +static void helper_ip_deeper(HELPER_ARGS); /* protocols like TCP/UDP */ /* Link-type header information */ static const struct linkhdr linkhdrs[] = { @@ -113,218 +117,130 @@ static const struct linkhdr linkhdrs[] = { { -1, 0, NULL } }; -/* - * Returns a pointer to the linkhdr record matching the given linktype, or +/* Returns a pointer to the linkhdr record matching the given linktype, or * NULL if no matching entry found. */ -const struct linkhdr * -getlinkhdr(const int linktype) -{ +const struct linkhdr *getlinkhdr(const int linktype) { size_t i; for (i=0; linkhdrs[i].linktype != -1; i++) if (linkhdrs[i].linktype == linktype) return (&(linkhdrs[i])); - return (NULL); + return NULL; } -/* - * Returns the minimum snaplen needed to decode everything up to the TCP/UDP - * packet headers. The IPv6 header is normative. The argument lh is not - * allowed to be NULL. +/* Returns the minimum snaplen needed to decode everything up to and including + * the TCP/UDP packet headers. */ -int -getsnaplen(const struct linkhdr *lh) -{ +int getsnaplen(const struct linkhdr *lh) { return (int)(lh->hdrlen + IPV6_HDR_LEN + MAX(TCP_HDR_LEN, UDP_HDR_LEN)); } -/* Decoding functions. */ -static void -decode_ether(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ +static int decode_ether(DECODER_ARGS) { u_short type; const struct ether_header *hdr = (const struct ether_header *)pdata; - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; if (pheader->caplen < ETHER_HDR_LEN) { verbosef("ether: packet too short (%u bytes)", pheader->caplen); - return; + return 0; } - #ifdef __sun - memcpy(sm.src_mac, hdr->ether_shost.ether_addr_octet, sizeof(sm.src_mac)); - memcpy(sm.dst_mac, hdr->ether_dhost.ether_addr_octet, sizeof(sm.dst_mac)); + memcpy(sm->src_mac, hdr->ether_shost.ether_addr_octet, sizeof(sm->src_mac)); + memcpy(sm->dst_mac, hdr->ether_dhost.ether_addr_octet, sizeof(sm->dst_mac)); #else - memcpy(sm.src_mac, hdr->ether_shost, sizeof(sm.src_mac)); - memcpy(sm.dst_mac, hdr->ether_dhost, sizeof(sm.dst_mac)); + memcpy(sm->src_mac, hdr->ether_shost, sizeof(sm->src_mac)); + memcpy(sm->dst_mac, hdr->ether_dhost, sizeof(sm->dst_mac)); #endif - - type = ntohs( hdr->ether_type ); + type = ntohs(hdr->ether_type); switch (type) { - case ETHERTYPE_IP: - case ETHERTYPE_IPV6: - if (!opt_want_pppoe) { - if (decode_ip(pdata + ETHER_HDR_LEN, - pheader->caplen - ETHER_HDR_LEN, &sm)) { - acct_for(&sm); - } - } else + case ETHERTYPE_IP: + case ETHERTYPE_IPV6: + if (!opt_want_pppoe) + return helper_ip(pdata + ETHER_HDR_LEN, + pheader->caplen - ETHER_HDR_LEN, + sm); verbosef("ether: discarded IP packet, expecting PPPoE instead"); - break; - case ETHERTYPE_ARP: - /* known protocol, don't complain about it. */ - break; - case ETHERTYPE_PPPOE: - if (opt_want_pppoe) - decode_pppoe_real(pdata + ETHER_HDR_LEN, - pheader->caplen - ETHER_HDR_LEN, &sm); - else + return 0; + case ETHERTYPE_PPPOE: + if (opt_want_pppoe) + return helper_pppoe(pdata + ETHER_HDR_LEN, + pheader->caplen - ETHER_HDR_LEN, + sm); verbosef("ether: got PPPoE frame: maybe you want --pppoe"); - break; - default: - verbosef("ether: unknown protocol (0x%04x)", type); + return 0; + case ETHERTYPE_ARP: + /* known protocol, don't complain about it. */ + return 0; + default: + verbosef("ether: unknown protocol (0x%04x)", type); + return 0; } } /* Very similar to decode_null, except on OpenBSD we need to think * about family endianness. */ -static void -decode_loop(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ +static int decode_loop(DECODER_ARGS) { uint32_t family; - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; if (pheader->caplen < NULL_HDR_LEN) { verbosef("loop: packet too short (%u bytes)", pheader->caplen); - return; + return 0; } family = *(const uint32_t *)pdata; #ifdef __OpenBSD__ family = ntohl(family); #endif - if (family == AF_INET) { - if (decode_ip(pdata + NULL_HDR_LEN, - pheader->caplen - NULL_HDR_LEN, &sm)) { - acct_for(&sm); - } - } - else if (family == AF_INET6) { - if (decode_ipv6(pdata + NULL_HDR_LEN, - pheader->caplen - NULL_HDR_LEN, &sm)) { - acct_for(&sm); - } - } - else - verbosef("loop: unknown family (%x)", family); + if (family == AF_INET) + return helper_ip(pdata + NULL_HDR_LEN, + pheader->caplen - NULL_HDR_LEN, sm); + if (family == AF_INET6) + return helper_ipv6(pdata + NULL_HDR_LEN, + pheader->caplen - NULL_HDR_LEN, sm); + verbosef("loop: unknown family (0x%04x)", family); + return 0; } -static void -decode_null(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ +static int decode_null(DECODER_ARGS) { uint32_t family; - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; if (pheader->caplen < NULL_HDR_LEN) { verbosef("null: packet too short (%u bytes)", pheader->caplen); - return; + return 0; } family = *(const uint32_t *)pdata; - if (family == AF_INET) { - if (decode_ip(pdata + NULL_HDR_LEN, - pheader->caplen - NULL_HDR_LEN, &sm)) { - acct_for(&sm); - } - } - else if (family == AF_INET6) { - if (decode_ipv6(pdata + NULL_HDR_LEN, - pheader->caplen - NULL_HDR_LEN, &sm)) { - acct_for(&sm); - } - } - else - verbosef("null: unknown family (%x)", family); + if (family == AF_INET) + return helper_ip(pdata + NULL_HDR_LEN, + pheader->caplen - NULL_HDR_LEN, + sm); + if (family == AF_INET6) + return helper_ipv6(pdata + NULL_HDR_LEN, + pheader->caplen - NULL_HDR_LEN, + sm); + verbosef("null: unknown family (0x%04x)", family); + return 0; } -static void -decode_ppp(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; - +static int decode_ppp(DECODER_ARGS) { if (pheader->caplen < PPPOE_HDR_LEN) { verbosef("ppp: packet too short (%u bytes)", pheader->caplen); - return; + return 0; } - - if (pdata[2] == 0x00 && pdata[3] == 0x21) { - if (decode_ip(pdata + PPP_HDR_LEN, pheader->caplen - PPP_HDR_LEN, &sm)) { - acct_for(&sm); - } - } else - verbosef("non-IP PPP packet; ignoring."); -} - -static void -decode_pppoe(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; - decode_pppoe_real(pdata, pheader->caplen, &sm); + if (pdata[2] == 0x00 && pdata[3] == 0x21) + return helper_ip(pdata + PPP_HDR_LEN, + pheader->caplen - PPP_HDR_LEN, + sm); + verbosef("ppp: non-IP PPP packet; ignoring."); + return 0; } -static void -decode_pppoe_real(const u_char *pdata, const uint32_t len, - struct pktsummary *sm) -{ - if (len < PPPOE_HDR_LEN) { - verbosef("pppoe: packet too short (%u bytes)", len); - return; - } - - if (pdata[1] != 0x00) { - verbosef("pppoe: code = 0x%02x, expecting 0; ignoring.", pdata[1]); - return; - } - - if ((pdata[6] == 0xc0) && (pdata[7] == 0x21)) return; /* LCP */ - if ((pdata[6] == 0xc0) && (pdata[7] == 0x25)) return; /* LQR */ - - if ((pdata[6] == 0x00) && (pdata[7] == 0x21)) { - if (decode_ip(pdata + PPPOE_HDR_LEN, len - PPPOE_HDR_LEN, sm)) { - acct_for(sm); - } - } else - verbosef("pppoe: non-IP PPPoE packet (0x%02x%02x); ignoring.", - pdata[6], pdata[7]); +static int decode_pppoe(DECODER_ARGS) { + return helper_pppoe(pdata, pheader->caplen, sm); } #ifdef DLT_LINUX_SLL /* very similar to decode_ether ... */ -static void -decode_linux_sll(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ +static int decode_linux_sll(DECODER_ARGS) { const struct sll_header { uint16_t packet_type; uint16_t device_type; @@ -334,61 +250,64 @@ decode_linux_sll(u_char *user _unused_, uint16_t ether_type; } *hdr = (const struct sll_header *)pdata; u_short type; - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; if (pheader->caplen < SLL_HDR_LEN) { verbosef("linux_sll: packet too short (%u bytes)", pheader->caplen); - return; + return 0; } - type = ntohs(hdr->ether_type); switch (type) { case ETHERTYPE_IP: case ETHERTYPE_IPV6: - if (decode_ip(pdata + SLL_HDR_LEN, pheader->caplen - SLL_HDR_LEN, &sm)) { - acct_for(&sm); - } - break; + return helper_ip(pdata + SLL_HDR_LEN, + pheader->caplen - SLL_HDR_LEN, + sm); case ETHERTYPE_ARP: /* known protocol, don't complain about it. */ - break; + return 0; default: - verbosef("linux_sll: unknown protocol (%04x)", type); + verbosef("linux_sll: unknown protocol (0x%04x)", type); + return 0; } } -#endif +#endif /* DLT_LINUX_SLL */ -static void -decode_raw(u_char *user _unused_, - const struct pcap_pkthdr *pheader, - const u_char *pdata) -{ - struct pktsummary sm; - memset(&sm, 0, sizeof(sm)); - sm.time = pheader->ts.tv_sec; - - if (decode_ip(pdata, pheader->caplen, &sm)) - acct_for(&sm); +static int decode_raw(DECODER_ARGS) { + return helper_ip(pdata, pheader->caplen, sm); } -static void decode_ip_payload(const u_char *pdata, const uint32_t len, - struct pktsummary *sm); +static int helper_pppoe(HELPER_ARGS) { + if (len < PPPOE_HDR_LEN) { + verbosef("pppoe: packet too short (%u bytes)", len); + return 0; + } + + if (pdata[1] != 0x00) { + verbosef("pppoe: code = 0x%02x, expecting 0; ignoring.", pdata[1]); + return 0; + } + + if ((pdata[6] == 0xc0) && (pdata[7] == 0x21)) return 0; /* LCP */ + if ((pdata[6] == 0xc0) && (pdata[7] == 0x25)) return 0; /* LQR */ -static int -decode_ip(const u_char *pdata, const uint32_t len, struct pktsummary *sm) -{ + if ((pdata[6] == 0x00) && (pdata[7] == 0x21)) + return helper_ip(pdata + PPPOE_HDR_LEN, len - PPPOE_HDR_LEN, sm); + + verbosef("pppoe: ignoring non-IP PPPoE packet (0x%02x%02x)", + pdata[6], pdata[7]); + return 0; +} + +static int helper_ip(HELPER_ARGS) { const struct ip *hdr = (const struct ip *)pdata; - if (hdr->ip_v == 6) { - /* Redirect parsing of IPv6 packets. */ - return decode_ipv6(pdata, len, sm); - } if (len < IP_HDR_LEN) { verbosef("ip: packet too short (%u bytes)", len); return 0; } + if (hdr->ip_v == 6) { + return helper_ipv6(pdata, len, sm); + } if (hdr->ip_v != 4) { verbosef("ip: version %d (expecting 4 or 6)", hdr->ip_v); return 0; @@ -403,37 +322,34 @@ decode_ip(const u_char *pdata, const uint32_t len, struct pktsummary *sm) sm->dst.family = IPv4; sm->dst.ip.v4 = hdr->ip_dst.s_addr; - decode_ip_payload(pdata + IP_HDR_LEN, len - IP_HDR_LEN, sm); + helper_ip_deeper(pdata + IP_HDR_LEN, len - IP_HDR_LEN, sm); return 1; } -static int -decode_ipv6(const u_char *pdata, const uint32_t len, struct pktsummary *sm) -{ +static int helper_ipv6(HELPER_ARGS) { const struct ip6_hdr *hdr = (const struct ip6_hdr *)pdata; if (len < IPV6_HDR_LEN) { verbosef("ipv6: packet too short (%u bytes)", len); return 0; } - if ((hdr->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { verbosef("ipv6: bad version (%02x, expecting %02x)", - hdr->ip6_vfc & IPV6_VERSION_MASK, - IPV6_VERSION); + hdr->ip6_vfc & IPV6_VERSION_MASK, IPV6_VERSION); return 0; } + /* IPv4 has "total length," but IPv6 has "payload length" which doesn't + * count the header bytes. + */ sm->len = ntohs(hdr->ip6_plen) + IPV6_HDR_LEN; sm->proto = hdr->ip6_nxt; - sm->src.family = IPv6; memcpy(&sm->src.ip.v6, &hdr->ip6_src, sizeof(sm->src.ip.v6)); - sm->dst.family = IPv6; memcpy(&sm->dst.ip.v6, &hdr->ip6_dst, sizeof(sm->dst.ip.v6)); - /* Ignore this packet if it uses extension headers. */ + /* Don't do proto accounting if this packet uses extension headers. */ switch (sm->proto) { case 0: /* Hop-by-Hop Options */ case IPPROTO_NONE: @@ -443,19 +359,20 @@ decode_ipv6(const u_char *pdata, const uint32_t len, struct pktsummary *sm) case IPPROTO_AH: case IPPROTO_ESP: case 135: /* Mobility */ - sm->proto = IPPROTO_INVALID; /* don't do proto accounting! */ + sm->proto = IPPROTO_INVALID; return 1; /* but we have addresses, so host accounting is ok */ default: - decode_ip_payload(pdata + IPV6_HDR_LEN, len - IPV6_HDR_LEN, sm); + helper_ip_deeper(pdata + IPV6_HDR_LEN, len - IPV6_HDR_LEN, sm); return 1; } } -static void -decode_ip_payload(const u_char *pdata, const uint32_t len, - struct pktsummary *sm) -{ +static void helper_ip_deeper(HELPER_ARGS) { + /* At this stage we have IP addresses so we can do host accounting. + * If proto decode fails, we set IPPROTO_INVALID to skip proto accounting. + * We don't need to "return 0" like other helpers. + */ switch (sm->proto) { case IPPROTO_TCP: { const struct tcphdr *thdr = (const struct tcphdr *)pdata; @@ -468,7 +385,7 @@ decode_ip_payload(const u_char *pdata, const uint32_t len, sm->dst_port = ntohs(thdr->th_dport); sm->tcp_flags = thdr->th_flags & (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG); - break; + return; } case IPPROTO_UDP: { @@ -480,7 +397,7 @@ decode_ip_payload(const u_char *pdata, const uint32_t len, } sm->src_port = ntohs(uhdr->uh_sport); sm->dst_port = ntohs(uhdr->uh_dport); - break; + return; } case IPPROTO_ICMP: @@ -492,7 +409,7 @@ decode_ip_payload(const u_char *pdata, const uint32_t len, break; default: - verbosef("ip_payload: unknown protocol %d", sm->proto); + verbosef("ip_deeper: unknown protocol 0x%02x", sm->proto); } } diff --git a/decode.h b/decode.h index 35cb42a..30a409d 100644 --- a/decode.h +++ b/decode.h @@ -9,55 +9,50 @@ #ifndef __DARKSTAT_DECODE_H #define __DARKSTAT_DECODE_H -#include -#include /* n_time */ -#define __USE_GNU 1 -#include /* for */ -#include /* struct ip */ - #include "addr.h" -#define PPP_HDR_LEN 4 -#define FDDI_HDR_LEN 21 -#define IP_HDR_LEN sizeof(struct ip) -#define IPV6_HDR_LEN sizeof(struct ip6_hdr) -#define TCP_HDR_LEN sizeof(struct tcphdr) -#define UDP_HDR_LEN sizeof(struct udphdr) -#define NULL_HDR_LEN 4 -#define PPPOE_HDR_LEN 8 -#define SLL_HDR_LEN 16 -#define RAW_HDR_LEN 0 - #ifndef ETHER_ADDR_LEN -#define ETHER_ADDR_LEN 6 +# define ETHER_ADDR_LEN 6 #endif +#define IPPROTO_INVALID 254 /* special: means don't do proto accounting */ + #ifndef IPPROTO_OSPF -#define IPPROTO_OSPF 89 +# define IPPROTO_OSPF 89 #endif -#define IPPROTO_INVALID 254 /* don't do proto accounting */ - -struct linkhdr { - int linktype; - unsigned int hdrlen; - pcap_handler handler; -}; - -const struct linkhdr *getlinkhdr(const int linktype); -int getsnaplen(const struct linkhdr *lh); +#define PPPOE_HDR_LEN 8 +/* Decoding creates a summary which is passed to accounting. */ struct pktsummary { /* Fields are in host byte order (except IPs) */ struct addr src, dst; time_t time; uint16_t len; - uint8_t proto; /* IPPROTO_{TCP, UDP, ICMP} */ + uint8_t proto; /* IPPROTO_INVALID means don't do proto accounting */ uint8_t tcp_flags; /* only for TCP */ uint16_t src_port, dst_port; /* only for TCP, UDP */ - uint8_t src_mac[ETHER_ADDR_LEN], + uint8_t src_mac[ETHER_ADDR_LEN], /* only for Ethernet */ dst_mac[ETHER_ADDR_LEN]; /* only for Ethernet */ }; +struct pcap_pkthdr; /* from pcap.h */ + +#define DECODER_ARGS const struct pcap_pkthdr *pheader, \ + const u_char *pdata, \ + struct pktsummary *sm + +/* Returns 0 on decode failure (meaning accounting should not be performed) */ +typedef int (decoder_fn)(DECODER_ARGS); + +struct linkhdr { + int linktype; + unsigned int hdrlen; + decoder_fn *decoder; +}; + +const struct linkhdr *getlinkhdr(const int linktype); +int getsnaplen(const struct linkhdr *lh); + #endif /* __DARKSTAT_DECODE_H */ /* vim:set ts=3 sw=3 tw=78 expandtab: */