/* packet.c * * Copyright (c) 2010 SeaD * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: packet.c,v 1.1.1.1 2012/02/21 21:59:41 misho Exp $ * */ #include #include #include #ifdef __OpenBSD__ # include # include #endif /* __OpenBSD__ */ #ifdef __linux__ # include # include #else /* __linux__ */ # include #endif /* __linux__ */ #include #ifndef __GLIBC__ # define __GLIBC__ 1 # include # undef __GLIBC__ #else /* __GLIBC__ */ # include #endif /* __GLIBC__ */ #include "ipguard.h" static struct ether_addr se_addr, te_addr, sh_addr, th_addr, bh_addr, zh_addr, fake_addr, pfake_addr; static struct in_addr sp_addr, tp_addr, zp_addr; static pcap_t *pcap = NULL; static libnet_t *ln = NULL; static char ifname[IFNAMSIZ]; static struct pair_t { struct ether_addr mac; struct in_addr ip; struct in_addr mask; } *pairs = NULL; static int pair_num = 0; static struct buffer_t { struct ether_addr mac; struct in_addr ip; int num; time_t last; } *buffer = NULL; void buffer_init(void) { if ((buffer = (struct buffer_t *) malloc(sizeof(struct buffer_t) * buffer_num)) == NULL) { log_str(ERROR, "malloc():", strerror(errno)); exit(EXIT_FAILURE); } } void buffer_destroy(void) { free(buffer); } void buffer_add(void) { struct buffer_t *p = NULL, *pn = NULL; register int n; for (n = 0, p = buffer; n < buffer_num; n++, p++) if (!memcmp(&sh_addr, &p->mac, sizeof(struct ether_addr))) { memcpy(&p->ip, &sp_addr, sizeof(struct in_addr)); p->num++; p->last = time(&p->last); return; } for (n = 0, p = buffer, pn = p + 1; n < buffer_num - 1; n++, p++, pn++) memcpy(p, pn, sizeof(struct buffer_t)); memcpy(&p->mac, &sh_addr, sizeof(struct ether_addr)); memcpy(&p->ip, &sp_addr, sizeof(struct in_addr)); p->num = 1; p->last = time(&p->last); } void buffer_dump(void) { struct buffer_t *p = NULL; register int n; snprintf(s, 64, "Bad MAC-IP buffer (%d pairs)", buffer_num); log_str(INFO, s, ""); for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) { snprintf(s, 64, "%03d %s %-15s %2d %lu", n+1, ether_ntoa(&p->mac), inet_ntoa(p->ip), p->num, (unsigned long) p->last); log_str(INFO, "dump:", s); } } void buffer_dump2ethers(void) { struct buffer_t *p = NULL; register int n; for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) { snprintf(s, 64, "%-17s %-15s", ether_ntoa(&p->mac), inet_ntoa(p->ip)); log_str(INFO, s, ""); } } uint32_t bit_2mask(int bit) { uint32_t mask = 0; register int n; for (n = 0; n < bit; n++) { mask >>= 1; mask |= 0x80000000; } return mask; } void pair_init(void) { struct libnet_ether_addr *ha = NULL; uint32_t pa = 0, mask; int bit = 0; if ((pairs = (struct pair_t *) malloc(sizeof(struct pair_t))) == NULL) { log_str(ERROR, "malloc():", strerror(errno)); exit(EXIT_FAILURE); } if ((ha = libnet_get_hwaddr(ln)) == NULL) { log_str(ERROR, libnet_geterror(ln), ""); exit(EXIT_FAILURE); } if (!(pa = libnet_get_ipaddr4(ln))) { log_str(ERROR, libnet_geterror(ln), ""); exit(EXIT_FAILURE); } mask = htonl(bit_2mask(bit)); if (!nofirst) { memcpy(&pairs->mac, ha, sizeof(struct ether_addr)); memcpy(&pairs->ip, &pa, sizeof(struct in_addr)); memcpy(&pairs->mask, &mask, sizeof(struct in_addr)); pair_num++; if (debug > 1) fprintf(stderr, "PAIR ADD FIRST: %s %s %u\n", ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), bit); } } void pair_destroy(void) { free(pairs); pair_num = 0; } void pair_add(char *mac, char *ip) { struct pair_t *p = NULL; struct ether_addr *fmac = NULL; uint32_t fip, mask; char *m; int bit; if ((m = strchr(ip, '/'))) { *m++ = '\0'; bit = atoi(m); if (!bit || (bit < 0) || (bit > 32)) { log_str(NOTICE, "Wrong mask", m); return; } if (debug > 2) fprintf(stderr, "NETWORK MASK: %s %u\n", ip, bit); } else bit = 0; if ((fmac = ether_aton(mac)) == NULL) { if (verbose) log_str(WARNING, "Invalid MAC:", mac); return; } if ((fip = libnet_name2addr4(ln, ip, LIBNET_RESOLVE)) == -1) { if (verbose) log_str(WARNING, "Host unknown:", ip); return; } mask = htonl(bit_2mask(bit)); if (mask) fip &= mask; if ((pairs = realloc(pairs, ++pair_num * sizeof(struct pair_t))) == NULL) { log_str(ERROR, "realloc():", strerror(errno)); exit(EXIT_FAILURE); } p = pairs + pair_num - 1; memcpy(&p->mac, fmac, sizeof(struct ether_addr)); memcpy(&p->ip, &fip, sizeof(struct in_addr)); memcpy(&p->mask, &mask, sizeof(struct in_addr)); if (debug > 1) fprintf(stderr, "PAIR ADD: %s %s %u\n", ether_ntoa(&p->mac), inet_ntoa(p->ip), bit); } void pair_dump(void) { struct pair_t *p = pairs; char ntoasw[16]; register int n; snprintf(s, 64, "Current MAC-IP table (%d pairs)", pair_num); log_str(INFO, s, ""); for (n = 0; n < pair_num; n++, p++) { strncpy(ntoasw, inet_ntoa(p->mask), 16); snprintf(s, 64, "%s %s %s", ether_ntoa(&p->mac), inet_ntoa(p->ip), ntoasw); log_str(INFO, "dump:", s); } } void packet_fmacs(int op) { switch (op) { /* init */ case 1: mac_rand(fmac); strncpy(pfmac, fmac, 18); break; /* regenerate */ case 2: strncpy(pfmac, fmac, 18); mac_regen(fmac); break; } memcpy(&fake_addr, ether_aton(fmac), sizeof(struct ether_addr)); memcpy(&pfake_addr, ether_aton(pfmac), sizeof(struct ether_addr)); } void packet_init(char *iface) { struct bpf_program arp_p; char ebuf[PCAP_ERRBUF_SIZE] = "\0"; strncpy(ifname, iface, IFNAMSIZ); memset(&bh_addr, 0xff, sizeof(struct ether_addr)); memset(&zh_addr, 0x00, sizeof(struct ether_addr)); memset(&zp_addr, 0x00, sizeof(struct in_addr)); packet_fmacs(1); /* pcap init */ if (!(pcap = pcap_open_live(ifname, 100, promisc, 10, ebuf))) { debug = 2; log_str(ERROR, "pcap_open_live():", ebuf); exit(EXIT_FAILURE); } if (strlen(ebuf)) fprintf(stderr, "warning: %s\n", ebuf); if (pcap_compile(pcap, &arp_p, pcapf, 0, -1) == -1) { snprintf(s, 128, "pcap_compile(%s):", pcapf); debug = 2; log_str(ERROR, s, "wrong expression"); exit(EXIT_FAILURE); } if (pcap_setfilter(pcap, &arp_p) == -1) { debug = 2; log_str(ERROR, "pcap_setfilter():", "failed"); exit(EXIT_FAILURE); } /* libnet init */ if (!(ln = libnet_init(LIBNET_LINK_ADV, ifname, ebuf))) { debug = 2; log_str(ERROR, ebuf, ""); exit(EXIT_FAILURE); } pair_init(); if (buffer_num) buffer_init(); ethers_init(); snprintf(s, 128, "%s %s %s (%d pairs) fake %s%s", iface, ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), pair_num, fmac, (read_only ? " RO mode" : "")); log_str(NOTICE, s, ""); if (verbose) pair_dump(); } void packet_destroy (void) { if (buffer_num) buffer_destroy(); pair_destroy(); libnet_destroy(ln); pcap_close(pcap); } void packet_send(int op, int num) { register int n; if (libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, 6, 4, op, (u_char *) &sh_addr, (u_char *) &sp_addr, (u_char *) &th_addr, (u_char *) &tp_addr, NULL, 0, ln, 0) == -1) { log_str(ERROR, libnet_geterror(ln), ""); exit(EXIT_FAILURE); } if (libnet_build_ethernet( (u_char *) &te_addr, (u_char *) &se_addr, ETHERTYPE_ARP, NULL, 0, ln, 0) == -1) { log_str(ERROR, libnet_geterror(ln), ""); exit(EXIT_FAILURE); } if ((n = num)) while (1) { if (debug > 1) { fprintf(stderr, "SEND ARP %u: ", op); fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n ", ether_ntoa(&te_addr)); fprintf(stderr, "sdr %-17s %-15s ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr)); fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr)); } if (!read_only) if (libnet_write(ln) == -1) { log_str(ERROR, libnet_geterror(ln), ""); exit_ipguard(EXIT_FAILURE); } if (--n <= 0) break; else usleep(fake_time * 1000); } libnet_clear_packet(ln); } void packet_check(void) { struct pair_t *p = NULL; struct pair_t *se_ch = NULL, *te_ch = NULL, *sp_ch = NULL, *tp_ch = NULL; uint32_t fsip, ftip, fmask, swip; int bsdr = 0; char ntoasw[16]; register int n; /* count mismatch MACs between ether and ARP headers */ if (memcmp(&se_addr, &sh_addr, sizeof(struct ether_addr))) { if (debug > 1) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); fprintf(stderr, "MISMATCH SOURCE: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); } mis++; } /* count non-zero target MAC in ARP who-has */ if (memcmp(&zh_addr, &th_addr, sizeof(struct ether_addr))) { if (debug > 1) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); fprintf(stderr, "NON-ZERO TARGET: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); } nzh++; } /* count non-bcast target ether MAC */ if (memcmp(&bh_addr, &te_addr, sizeof(struct ether_addr))) { if (debug > 1) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); fprintf(stderr, "NON-BCAST WHO-HAS: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); } nbe++; } /* return if sdr MAC is ours */ if (!memcmp(&se_addr, &pairs->mac, sizeof(struct ether_addr))) { if (debug > 2) fprintf(stderr, "MY MAC PASSED: %s\n", ether_ntoa(&se_addr)); mymac++; return; } /* return if sdr MAC is our fake MAC */ if (!memcmp(&se_addr, &fake_addr, sizeof(struct ether_addr))) { if (debug > 2) fprintf(stderr, "FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr)); fake++; return; } /* return if sdr MAC is previous fake MAC */ if (fake_regen) if (!memcmp(&se_addr, &pfake_addr, sizeof(struct ether_addr))) { if (debug > 2) fprintf(stderr, "PRE FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr)); pfake++; return; } /* fill weird gratuitous ARP sdr IP 0.0.0.0 (Linux/MacOS/Vista) */ if (!memcmp(&sp_addr, &zp_addr, sizeof(struct in_addr))) { if (debug > 2) fprintf(stderr, "WEIRD GRATUITOUS FILL: %s\n", inet_ntoa(tp_addr)); memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr)); wgrat++; } /* check if IP/MAC is listed */ for (n = 0, p = pairs; n < pair_num; n++, p++) { memcpy(&fsip, &sp_addr, sizeof(struct in_addr)); memcpy(&ftip, &tp_addr, sizeof(struct in_addr)); memcpy(&fmask, &p->mask, sizeof(struct in_addr)); if (fmask) { fsip &= fmask; ftip &= fmask; } if (!memcmp(&se_addr, &p->mac, sizeof(struct ether_addr))) { if (!se_ch) se_ch = p; if (!memcmp(&fsip, &p->ip, sizeof(struct in_addr))) se_ch = sp_ch = p; } if (!memcmp(&te_addr, &p->mac, sizeof(struct ether_addr))) { if (!te_ch) te_ch = p; if (!memcmp(&ftip, &p->ip, sizeof(struct in_addr))) te_ch = tp_ch = p; } if (!sp_ch && !memcmp(&fsip, &p->ip, sizeof(struct in_addr))) sp_ch = p; if (!tp_ch && !memcmp(&ftip, &p->ip, sizeof(struct in_addr))) tp_ch = p; } if (debug > 2) { if (se_ch) fprintf(stderr, "MATCH MAC SDR: %-18s -> %-18s\n", ether_ntoa(&se_ch->mac), inet_ntoa(se_ch->ip)); else fprintf(stderr, "UNKNOWN MAC SDR: %-18s\n", ether_ntoa(&se_addr)); if (te_ch) fprintf(stderr, "MATCH MAC TRG: %-18s -> %-18s\n", ether_ntoa(&te_ch->mac), inet_ntoa(te_ch->ip)); else { if (!memcmp(&te_addr, &bh_addr, sizeof(struct ether_addr))) fprintf(stderr, "BCAST MAC TRG: %-18s\n", "ff:ff:ff:ff:ff:ff"); else fprintf(stderr, "UNKNOWN MAC TRG: %-18s\n", ether_ntoa(&te_addr)); } if (sp_ch) fprintf(stderr, "MATCH IP SDR: %-18s -> %-18s\n", inet_ntoa(sp_ch->ip), ether_ntoa(&sp_ch->mac)); else fprintf(stderr, "UNKNOWN IP SDR: %-18s\n", inet_ntoa(sp_addr)); if (tp_ch) fprintf(stderr, "MATCH IP TRG: %-18s -> %-18s\n", inet_ntoa(tp_ch->ip), ether_ntoa(&tp_ch->mac)); else fprintf(stderr, "UNKNOWN IP TRG: %-18s\n", inet_ntoa(tp_addr)); } /* gratuitous ARP packets */ if (se_ch && (se_ch == tp_ch) && !memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) { if (debug > 2) fprintf(stderr, "GOOD PASSED: grat\n"); grat++; return; } /* wildcard trg MAC 00:00:00:00:00:00 */ if (sp_ch && !memcmp(&sp_ch->mac, &zh_addr, sizeof(struct ether_addr))) { if (debug > 2) fprintf(stderr, "GOOD PASSED: zmac\n"); zmac++; if (!addr_nosubst) return; } /* wildcard sdr IP 0.0.0.0 */ if (se_ch && !memcmp(&se_ch->ip, &zp_addr, sizeof(struct in_addr))) { if (debug > 2) fprintf(stderr, "GOOD PASSED: zip\n"); zip++; if (!addr_nosubst) return; } /* correct pair - sdr MAC pos == sdr IP pos and listed trg IP pos or not duplex */ if (se_ch && (se_ch == sp_ch) && (tp_ch || !duplex)) { if (debug > 2) fprintf(stderr, "GOOD PASSED: good\n"); good++; return; } /* sdr MAC and sdr IP are both not listed - new pair */ if (!se_ch && (se_ch == sp_ch)) { if (verbose) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "bnew:", s); } bnew++; bsdr++; if (grant) return; } /* sdr MAC is listed but IP is not */ if (se_ch && (se_ch != sp_ch)) { if (verbose) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "bsip:", s); } bsip++; bsdr++; } /* sdr IP is listed but MAC is not */ if (sp_ch && (se_ch != sp_ch)) { if (verbose) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "bmac:", s); } bmac++; bsdr++; } /* do not block gratuitous ARP in hidden mode */ if (!memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) { if (verbose) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "bgrt:", s); } bgrat++; if (hidden) return; } /* if duplex and trg IP is not listed then block */ if (!tp_ch) { if (verbose) { strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "btip:", s); } btip++; if (!bsdr && !duplex) return; } /* add pirate pair to bad buffer */ if (bsdr && buffer_num) buffer_add(); strncpy(ntoasw, inet_ntoa(tp_addr), 16); snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw); log_str(NOTICE, "xxxx:", s); /* block pirate eth fake MAC -> pirate MAC sdr fake MAC - target IP trg pirate MAC - pirate IP */ memcpy(&te_addr, &se_addr, sizeof(struct ether_addr)); memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr)); memcpy(&th_addr, &sh_addr, sizeof(struct ether_addr)); memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr)); memcpy(&swip, &tp_addr, sizeof(struct in_addr)); memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr)); memcpy(&sp_addr, &swip, sizeof(struct in_addr)); packet_send(ARPOP_REPLY, fake_num); if (bsdr) { /* control headshot eth fake MAC -> pirate MAC sdr fake MAC - pirate IP trg pirate MAC - pirate IP */ memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr)); packet_send(ARPOP_REPLY, 1); } /* and fix broken ARP caches by broadcast */ if (bsdr && fixbc) { memcpy(&te_addr, &bh_addr, sizeof(struct ether_addr)); memcpy(&th_addr, &zh_addr, sizeof(struct ether_addr)); if (sp_ch) { /* sdr IP is valid eth ethers MAC -> broadcast sdr ethers MAC - ethers IP trg zero MAC - ethers IP */ memcpy(&se_addr, &sp_ch->mac, sizeof(struct ether_addr)); memcpy(&sh_addr, &sp_ch->mac, sizeof(struct ether_addr)); memcpy(&sp_addr, &sp_ch->ip, sizeof(struct in_addr)); } else if (se_ch) { /* sdr MAC is valid eth ethers MAC -> broadcast sdr ethers MAC - ethers IP trg zero MAC - ethers IP ** disabled as probably useless ** memcpy(&se_addr, &se_ch->mac, sizeof(struct ether_addr)); memcpy(&sh_addr, &se_ch->mac, sizeof(struct ether_addr)); memcpy(&sp_addr, &se_ch->ip, sizeof(struct in_addr)); */ } else { /* invalid sender eth fake MAC -> broadcast sdr fake MAC - pirate IP trg zero MAC - pirate IP */ memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr)); memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr)); } memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr)); packet_send(ARPOP_REQUEST, 1); } bad++; if (debug > 2) fprintf(stderr, "STATS: god %-6d new %-6d bmc %-6d bip %-6d btg %-6d all %-6d\n", good+mymac+fake+pfake+grat+wgrat+zmac+zip, bnew, bmac, bsip, btip, all); } void packet_handle(char *blah, struct pcap_pkthdr *blah2, u_char *recv) { struct ether_header *eth_h = NULL; struct ether_arp *arp_h = NULL; int op; sig_catch(); if (ethers_update) ethers_stat(); if (fake_regen) packet_fmacs(2); eth_h = (struct ether_header *) recv; if (htons(eth_h->ether_type) != ETHERTYPE_ARP) { snprintf(s, 8, "0x%x", eth_h->ether_type); log_str(WARNING, "wrong ethertype:", s); return; } memcpy(&se_addr, ð_h->ether_shost, sizeof(struct ether_addr)); memcpy(&te_addr, ð_h->ether_dhost, sizeof(struct ether_addr)); arp_h = (struct ether_arp *) ((char *) eth_h + ETHER_HDR_LEN); if (htons(arp_h->ea_hdr.ar_hrd) != ARPHRD_ETHER) { snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_hrd); log_str(WARNING, "wrong hw address:", s); return; } if (htons(arp_h->ea_hdr.ar_pro) != ETHERTYPE_IP) { snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_pro); log_str(WARNING, "wrong proto address:", s); return; } op = htons(arp_h->ea_hdr.ar_op); memcpy(&sh_addr, &arp_h->arp_sha, sizeof(struct ether_addr)); memcpy(&sp_addr, &arp_h->arp_spa, sizeof(struct in_addr)); memcpy(&th_addr, &arp_h->arp_tha, sizeof(struct ether_addr)); memcpy(&tp_addr, &arp_h->arp_tpa, sizeof(struct in_addr)); if (debug > 1) { fprintf(stderr, "RECV ARP %u: ", op); fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n ", ether_ntoa(&te_addr)); fprintf(stderr, "sdr %-17s %-15s ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr)); fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr)); } if (op == ARPOP_REPLY) return; if (op != ARPOP_REQUEST) { snprintf(s, 8, "0x%x", op); log_str(WARNING, "wrong arp op:", s); return; } all++; packet_check(); } void packet_recv(void) { if (pcap_loop(pcap, -1, (pcap_handler) packet_handle, NULL) == -1) { log_str(ERROR, "pcap_loop()", "failed"); exit_ipguard(EXIT_FAILURE); } } void stat_dump(void) { struct pcap_stat ps; snprintf(s, 64, "ARP statistics:"); log_str(INFO, s, ""); snprintf(s, 64, "Total ARP who-has packets %u", all); log_str(INFO, s, ""); snprintf(s, 64, "Good MAC-IP pairs %u", good); log_str(INFO, s, ""); snprintf(s, 64, "Gratuitous MAC-IP/weird %u/%u", grat, wgrat); log_str(INFO, s, ""); snprintf(s, 64, "Zero MAC/IP %u/%u", zmac, zip); log_str(INFO, s, ""); snprintf(s, 64, "New MAC-IP pairs %u", bnew); log_str(INFO, s, ""); snprintf(s, 64, "Bad MAC-IP pairs %u", bad); log_str(INFO, s, ""); snprintf(s, 64, "Bad MAC/IP %u/%u", bmac, bsip); log_str(INFO, s, ""); if (duplex) { snprintf(s, 64, "Bad target IP %u", btip); log_str(INFO, s, ""); } snprintf(s, 64, "Bad gratuitous MAC-IP %u", bgrat); log_str(INFO, s, ""); snprintf(s, 64, "My/Fake/PreFake MAC %u/%u/%u", mymac, fake, pfake); log_str(INFO, s, ""); snprintf(s, 64, "Mismatch sender Ether/ARP MAC %u", mis); log_str(INFO, s, ""); snprintf(s, 64, "Non-zero target ARP MAC %u", nzh); log_str(INFO, s, ""); snprintf(s, 64, "Non-bcast target Ether MAC %u", nbe); log_str(INFO, s, ""); if (pcap_stats(pcap, &ps) == -1) { log_str(WARNING, "pcap_stat()", "failed"); return; } snprintf(s, 64, "PCAP statistics:"); log_str(INFO, s, ""); snprintf(s, 64, "Received/Dropped packets %u/%u", ps.ps_recv, ps.ps_drop); log_str(INFO, s, ""); }