Annotation of embedaddon/ipguard/packet.c, revision 1.1

1.1     ! misho       1: /*  packet.c
        !             2:  *
        !             3:  * Copyright (c) 2010 SeaD <sead at deep.perm.ru>
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  *
        !            14:  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            17:  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
        !            18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            24:  * SUCH DAMAGE.
        !            25:  *
        !            26:  *  $Id: packet.c,v 1.19 2010/07/12 03:46:36 sead Exp $
        !            27:  *
        !            28:  */
        !            29: 
        !            30: #include <sys/types.h>
        !            31: #include <sys/socket.h>
        !            32: #include <netinet/in.h>
        !            33: 
        !            34: #ifdef __OpenBSD__
        !            35: # include <net/if.h>
        !            36: # include <net/if_arp.h>
        !            37: #endif  /* __OpenBSD__ */
        !            38: 
        !            39: #ifdef __linux__
        !            40: # include <time.h>
        !            41: # include <netinet/ether.h>
        !            42: #else   /* __linux__ */
        !            43: # include <netinet/if_ether.h>
        !            44: #endif  /* __linux__ */
        !            45: 
        !            46: #include <pcap.h>
        !            47: 
        !            48: #ifndef __GLIBC__
        !            49: # define __GLIBC__      1
        !            50: # include <libnet.h>
        !            51: # undef __GLIBC__
        !            52: #else   /* __GLIBC__ */
        !            53: # include <libnet.h>
        !            54: #endif  /* __GLIBC__ */
        !            55: 
        !            56: #include "ipguard.h"
        !            57: 
        !            58: static struct ether_addr se_addr, te_addr, sh_addr, th_addr, bh_addr, zh_addr,
        !            59:     fake_addr, pfake_addr;
        !            60: static struct in_addr sp_addr, tp_addr, zp_addr;
        !            61: 
        !            62: static pcap_t *pcap = NULL;
        !            63: static libnet_t *ln = NULL;
        !            64: static char ifname[IFNAMSIZ];
        !            65: 
        !            66: static struct pair_t {
        !            67:     struct ether_addr mac;
        !            68:     struct in_addr ip;
        !            69:     struct in_addr mask;
        !            70: } *pairs = NULL;
        !            71: static int pair_num = 0;
        !            72: 
        !            73: static struct buffer_t {
        !            74:     struct ether_addr mac;
        !            75:     struct in_addr ip;
        !            76:     int num;
        !            77:     time_t last;
        !            78: } *buffer = NULL;
        !            79: 
        !            80: void buffer_init(void) {
        !            81:     if ((buffer = (struct buffer_t *) malloc(sizeof(struct buffer_t) * buffer_num)) == NULL) {
        !            82:         log_str(ERROR, "malloc():", strerror(errno));
        !            83:         exit(EXIT_FAILURE);
        !            84:     }
        !            85: }
        !            86: 
        !            87: void buffer_destroy(void) {
        !            88:     free(buffer);
        !            89: }
        !            90: 
        !            91: void buffer_add(void) {
        !            92:     struct buffer_t *p = NULL, *pn = NULL;
        !            93:     register int n;
        !            94: 
        !            95:     for (n = 0, p = buffer; n < buffer_num; n++, p++)
        !            96:         if (!memcmp(&sh_addr, &p->mac, sizeof(struct ether_addr))) {
        !            97:             memcpy(&p->ip, &sp_addr, sizeof(struct in_addr));
        !            98:             p->num++; p->last = time(&p->last); return;
        !            99:         }
        !           100: 
        !           101:     for (n = 0, p = buffer, pn = p + 1; n < buffer_num - 1; n++, p++, pn++)
        !           102:         memcpy(p, pn, sizeof(struct buffer_t));
        !           103:     memcpy(&p->mac, &sh_addr, sizeof(struct ether_addr));
        !           104:     memcpy(&p->ip, &sp_addr, sizeof(struct in_addr));
        !           105:     p->num = 1; p->last = time(&p->last);
        !           106: }
        !           107: 
        !           108: void buffer_dump(void) {
        !           109:     struct buffer_t *p = NULL;
        !           110:     register int n;
        !           111: 
        !           112:     snprintf(s, 64, "Bad MAC-IP buffer (%d pairs)", buffer_num);
        !           113:     log_str(INFO, s, "");
        !           114:     
        !           115:     for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) {
        !           116:         snprintf(s, 64, "%03d %s %-15s %2d %lu",
        !           117:             n+1, ether_ntoa(&p->mac), inet_ntoa(p->ip), p->num, (unsigned long) p->last);
        !           118:         log_str(INFO, "dump:", s);
        !           119:     }
        !           120: }
        !           121: 
        !           122: void buffer_dump2ethers(void) {
        !           123:     struct buffer_t *p = NULL;
        !           124:     register int n;
        !           125: 
        !           126:     for (n = 0, p = buffer + buffer_num - 1; n < buffer_num && p->num > 0; n++, p--) {
        !           127:         snprintf(s, 64, "%-17s       %-15s", ether_ntoa(&p->mac), inet_ntoa(p->ip));
        !           128:         log_str(INFO, s, "");
        !           129:     }
        !           130: }
        !           131: 
        !           132: uint32_t bit_2mask(int bit) {
        !           133:     uint32_t mask = 0;
        !           134:     register int n;
        !           135: 
        !           136:     for (n = 0; n < bit; n++) { mask >>= 1; mask |= 0x80000000; }
        !           137: 
        !           138:     return mask;
        !           139: }
        !           140: 
        !           141: void pair_init(void) {
        !           142:     struct libnet_ether_addr *ha = NULL;
        !           143:     uint32_t pa = 0, mask;
        !           144:     int bit = 0;
        !           145: 
        !           146:     if ((pairs = (struct pair_t *) malloc(sizeof(struct pair_t))) == NULL) {
        !           147:         log_str(ERROR, "malloc():", strerror(errno));
        !           148:         exit(EXIT_FAILURE);
        !           149:     }
        !           150:     if ((ha = libnet_get_hwaddr(ln)) == NULL) {
        !           151:         log_str(ERROR, libnet_geterror(ln), "");
        !           152:         exit(EXIT_FAILURE);
        !           153:     }
        !           154:     if (!(pa = libnet_get_ipaddr4(ln))) {
        !           155:         log_str(ERROR, libnet_geterror(ln), "");
        !           156:         exit(EXIT_FAILURE);
        !           157:     }
        !           158:     mask = htonl(bit_2mask(bit));
        !           159:     if (!nofirst) {
        !           160:         memcpy(&pairs->mac, ha, sizeof(struct ether_addr));
        !           161:         memcpy(&pairs->ip, &pa, sizeof(struct in_addr));
        !           162:         memcpy(&pairs->mask, &mask, sizeof(struct in_addr));
        !           163:         pair_num++;
        !           164: 
        !           165:         if (debug > 1)
        !           166:             fprintf(stderr, "PAIR ADD FIRST: %s %s %u\n",
        !           167:                 ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), bit);
        !           168:     }
        !           169: }
        !           170: 
        !           171: void pair_destroy(void) {
        !           172:     free(pairs);
        !           173:     pair_num = 0;
        !           174: }
        !           175: 
        !           176: void pair_add(char *mac, char *ip) {
        !           177:     struct pair_t *p = NULL;
        !           178:     struct ether_addr *fmac = NULL;
        !           179:     uint32_t fip, mask;
        !           180:     char *m;
        !           181:     int bit;
        !           182: 
        !           183:     if ((m = strchr(ip, '/'))) {
        !           184:         *m++ = '\0'; bit = atoi(m);
        !           185:         if (!bit || (bit < 0) || (bit > 32)) {
        !           186:             log_str(NOTICE, "Wrong mask", m); return;
        !           187:         }
        !           188:         if (debug > 2) fprintf(stderr, "NETWORK MASK: %s %u\n", ip, bit);
        !           189:     } else bit = 0;
        !           190: 
        !           191:     if ((fmac = ether_aton(mac)) == NULL) {
        !           192:         if (verbose) log_str(WARNING, "Invalid MAC:", mac); return;
        !           193:     }
        !           194:     if ((fip = libnet_name2addr4(ln, ip, LIBNET_RESOLVE)) == -1) {
        !           195:         if (verbose) log_str(WARNING, "Host unknown:", ip); return;
        !           196:     }
        !           197: 
        !           198:     mask = htonl(bit_2mask(bit));
        !           199:     if (mask) fip &= mask;
        !           200: 
        !           201:     if ((pairs = realloc(pairs, ++pair_num * sizeof(struct pair_t))) == NULL) {
        !           202:         log_str(ERROR, "realloc():", strerror(errno));
        !           203:         exit(EXIT_FAILURE);
        !           204:     }
        !           205:     p = pairs + pair_num - 1;
        !           206: 
        !           207:     memcpy(&p->mac, fmac, sizeof(struct ether_addr));
        !           208:     memcpy(&p->ip, &fip, sizeof(struct in_addr));
        !           209:     memcpy(&p->mask, &mask, sizeof(struct in_addr));
        !           210: 
        !           211:     if (debug > 1)
        !           212:         fprintf(stderr, "PAIR ADD: %s %s %u\n",
        !           213:             ether_ntoa(&p->mac), inet_ntoa(p->ip), bit);
        !           214: }
        !           215: 
        !           216: void pair_dump(void) {
        !           217:     struct pair_t *p = pairs;
        !           218:     char ntoasw[16];
        !           219:     register int n;
        !           220: 
        !           221:     snprintf(s, 64, "Current MAC-IP table (%d pairs)", pair_num);
        !           222:     log_str(INFO, s, "");
        !           223: 
        !           224:     for (n = 0; n < pair_num; n++, p++) {
        !           225:         strncpy(ntoasw, inet_ntoa(p->mask), 16);
        !           226:         snprintf(s, 64, "%s %s %s",
        !           227:             ether_ntoa(&p->mac), inet_ntoa(p->ip), ntoasw);
        !           228:         log_str(INFO, "dump:", s);
        !           229:     }
        !           230: }
        !           231: 
        !           232: void packet_fmacs(int op) {
        !           233:     switch (op) {
        !           234:         /* init */
        !           235:         case 1: mac_rand(fmac); strncpy(pfmac, fmac, 18); break;
        !           236:         /* regenerate */
        !           237:         case 2: strncpy(pfmac, fmac, 18); mac_regen(fmac); break;
        !           238:     }
        !           239: 
        !           240:     memcpy(&fake_addr, ether_aton(fmac), sizeof(struct ether_addr));
        !           241:     memcpy(&pfake_addr, ether_aton(pfmac), sizeof(struct ether_addr));
        !           242: }
        !           243: 
        !           244: void packet_init(char *iface) {
        !           245:     struct bpf_program arp_p;
        !           246:     char ebuf[PCAP_ERRBUF_SIZE] = "\0";
        !           247: 
        !           248:     strncpy(ifname, iface, IFNAMSIZ);
        !           249:     memset(&bh_addr, 0xff, sizeof(struct ether_addr));
        !           250:     memset(&zh_addr, 0x00, sizeof(struct ether_addr));
        !           251:     memset(&zp_addr, 0x00, sizeof(struct in_addr));
        !           252:     packet_fmacs(1);
        !           253: 
        !           254:     /* pcap init */
        !           255:     if (!(pcap = pcap_open_live(ifname, 100, promisc, 10, ebuf))) {
        !           256:         debug = 2; log_str(ERROR, "pcap_open_live():", ebuf);
        !           257:         exit(EXIT_FAILURE);
        !           258:     }
        !           259:     if (strlen(ebuf)) fprintf(stderr, "warning: %s\n", ebuf);
        !           260:     if (pcap_compile(pcap, &arp_p, pcapf, 0, -1) == -1) {
        !           261:         snprintf(s, 128, "pcap_compile(%s):", pcapf);
        !           262:         debug = 2; log_str(ERROR, s, "wrong expression");
        !           263:         exit(EXIT_FAILURE);
        !           264:     }
        !           265:     if (pcap_setfilter(pcap, &arp_p) == -1) {
        !           266:         debug = 2; log_str(ERROR, "pcap_setfilter():", "failed");
        !           267:         exit(EXIT_FAILURE);
        !           268:     }
        !           269: 
        !           270:     /* libnet init */
        !           271:     if (!(ln = libnet_init(LIBNET_LINK_ADV, ifname, ebuf))) {
        !           272:         debug = 2; log_str(ERROR, ebuf, "");
        !           273:         exit(EXIT_FAILURE);
        !           274:     }
        !           275: 
        !           276:     pair_init();
        !           277:     if (buffer_num) buffer_init();
        !           278:     ethers_init();
        !           279: 
        !           280:     snprintf(s, 128, "%s %s %s (%d pairs) fake %s%s",
        !           281:         iface, ether_ntoa(&pairs->mac), inet_ntoa(pairs->ip), pair_num, fmac,
        !           282:         (read_only ? " RO mode" : ""));
        !           283:     log_str(NOTICE, s, "");
        !           284:     if (verbose) pair_dump();
        !           285: }
        !           286: 
        !           287: void packet_destroy (void) {
        !           288:     if (buffer_num) buffer_destroy();
        !           289:     pair_destroy();
        !           290:     libnet_destroy(ln);
        !           291:     pcap_close(pcap);
        !           292: }
        !           293: 
        !           294: void packet_send(int op, int num) {
        !           295:     register int n;
        !           296: 
        !           297:     if (libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, 6, 4, op,
        !           298:             (u_char *) &sh_addr, (u_char *) &sp_addr,
        !           299:             (u_char *) &th_addr, (u_char *) &tp_addr,
        !           300:             NULL, 0, ln, 0) == -1) {
        !           301:         log_str(ERROR, libnet_geterror(ln), "");
        !           302:         exit(EXIT_FAILURE);
        !           303:     }
        !           304: 
        !           305:     if (libnet_build_ethernet(
        !           306:             (u_char *) &te_addr, (u_char *) &se_addr,
        !           307:             ETHERTYPE_ARP, NULL, 0, ln, 0) == -1) {
        !           308:         log_str(ERROR, libnet_geterror(ln), "");
        !           309:         exit(EXIT_FAILURE);
        !           310:     }
        !           311: 
        !           312:     if ((n = num)) while (1) {
        !           313:         if (debug > 1) {
        !           314:             fprintf(stderr, "SEND ARP %u: ", op);
        !           315:             fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n  ", ether_ntoa(&te_addr));
        !           316:             fprintf(stderr, "sdr %-17s %-15s  ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr));
        !           317:             fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr));
        !           318:         }
        !           319:         if (!read_only)
        !           320:             if (libnet_write(ln) == -1) {
        !           321:                 log_str(ERROR, libnet_geterror(ln), "");
        !           322:                 exit_ipguard(EXIT_FAILURE);
        !           323:             }
        !           324:         if (--n <= 0) break; else usleep(fake_time * 1000);
        !           325:     }
        !           326: 
        !           327:     libnet_clear_packet(ln);
        !           328: }
        !           329: 
        !           330: void packet_check(void) {
        !           331:     struct pair_t *p = NULL;
        !           332:     struct pair_t *se_ch = NULL, *te_ch = NULL, *sp_ch = NULL, *tp_ch = NULL;
        !           333:     uint32_t fsip, ftip, fmask, swip;
        !           334:     int bsdr = 0;
        !           335:     char ntoasw[16];
        !           336:     register int n;
        !           337: 
        !           338:     /* count mismatch MACs between ether and ARP headers */
        !           339:     if (memcmp(&se_addr, &sh_addr, sizeof(struct ether_addr))) {
        !           340:         if (debug > 1) {
        !           341:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           342:             fprintf(stderr, "MISMATCH SOURCE: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           343:         }
        !           344:         mis++;
        !           345:     }
        !           346:     /* count non-zero target MAC in ARP who-has */
        !           347:     if (memcmp(&zh_addr, &th_addr, sizeof(struct ether_addr))) {
        !           348:         if (debug > 1) {
        !           349:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           350:             fprintf(stderr, "NON-ZERO TARGET: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           351:         }
        !           352:         nzh++;
        !           353:     }
        !           354:     /* count non-bcast target ether MAC */
        !           355:     if (memcmp(&bh_addr, &te_addr, sizeof(struct ether_addr))) {
        !           356:         if (debug > 1) {
        !           357:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           358:             fprintf(stderr, "NON-BCAST WHO-HAS: %-17s %-15s %-15s\n", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           359:         }
        !           360:         nbe++;
        !           361:     }
        !           362: 
        !           363:     /* return if sdr MAC is ours */
        !           364:     if (!memcmp(&se_addr, &pairs->mac, sizeof(struct ether_addr))) {
        !           365:         if (debug > 2) fprintf(stderr, "MY MAC PASSED: %s\n", ether_ntoa(&se_addr));
        !           366:         mymac++; return;
        !           367:     }
        !           368:     /* return if sdr MAC is our fake MAC */
        !           369:     if (!memcmp(&se_addr, &fake_addr, sizeof(struct ether_addr))) {
        !           370:         if (debug > 2) fprintf(stderr, "FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr));
        !           371:         fake++; return;
        !           372:     }
        !           373:     /* return if sdr MAC is previous fake MAC */
        !           374:     if (fake_regen)
        !           375:         if (!memcmp(&se_addr, &pfake_addr, sizeof(struct ether_addr))) {
        !           376:             if (debug > 2) fprintf(stderr, "PRE FAKE MAC PASSED: %s\n", ether_ntoa(&se_addr));
        !           377:             pfake++; return;
        !           378:         }
        !           379:     /* fill weird gratuitous ARP sdr IP 0.0.0.0 (Linux/MacOS/Vista) */
        !           380:     if (!memcmp(&sp_addr, &zp_addr, sizeof(struct in_addr))) {
        !           381:         if (debug > 2) fprintf(stderr, "WEIRD GRATUITOUS FILL: %s\n", inet_ntoa(tp_addr));
        !           382:         memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr));
        !           383:         wgrat++;
        !           384:     }
        !           385: 
        !           386:     /* check if IP/MAC is listed */
        !           387:     for (n = 0, p = pairs; n < pair_num; n++, p++) {
        !           388:         memcpy(&fsip, &sp_addr, sizeof(struct in_addr));
        !           389:         memcpy(&ftip, &tp_addr, sizeof(struct in_addr));
        !           390:         memcpy(&fmask, &p->mask, sizeof(struct in_addr));
        !           391:         if (fmask) { fsip &= fmask; ftip &= fmask; }
        !           392:         if (!memcmp(&se_addr, &p->mac, sizeof(struct ether_addr))) {
        !           393:             if (!se_ch) se_ch = p;
        !           394:             if (!memcmp(&fsip, &p->ip, sizeof(struct in_addr))) se_ch = sp_ch = p;
        !           395:         }
        !           396:         if (!memcmp(&te_addr, &p->mac, sizeof(struct ether_addr))) {
        !           397:             if (!te_ch) te_ch = p;
        !           398:             if (!memcmp(&ftip, &p->ip, sizeof(struct in_addr))) te_ch = tp_ch = p;
        !           399:         }
        !           400:         if (!sp_ch && !memcmp(&fsip, &p->ip, sizeof(struct in_addr))) sp_ch = p;
        !           401:         if (!tp_ch && !memcmp(&ftip, &p->ip, sizeof(struct in_addr))) tp_ch = p;
        !           402:     }
        !           403: 
        !           404:     if (debug > 2) {
        !           405:         if (se_ch) fprintf(stderr, "MATCH MAC   SDR: %-18s -> %-18s\n", ether_ntoa(&se_ch->mac), inet_ntoa(se_ch->ip));
        !           406:         else fprintf(stderr, "UNKNOWN MAC SDR: %-18s\n", ether_ntoa(&se_addr));
        !           407:         if (te_ch) fprintf(stderr, "MATCH MAC   TRG: %-18s -> %-18s\n", ether_ntoa(&te_ch->mac), inet_ntoa(te_ch->ip));
        !           408:         else {
        !           409:             if (!memcmp(&te_addr, &bh_addr, sizeof(struct ether_addr)))
        !           410:                 fprintf(stderr, "BCAST MAC   TRG: %-18s\n", "ff:ff:ff:ff:ff:ff");
        !           411:             else
        !           412:                 fprintf(stderr, "UNKNOWN MAC TRG: %-18s\n", ether_ntoa(&te_addr));
        !           413:         }
        !           414:         if (sp_ch) fprintf(stderr, "MATCH IP    SDR: %-18s -> %-18s\n", inet_ntoa(sp_ch->ip), ether_ntoa(&sp_ch->mac));
        !           415:         else fprintf(stderr, "UNKNOWN IP  SDR: %-18s\n", inet_ntoa(sp_addr));
        !           416:         if (tp_ch) fprintf(stderr, "MATCH IP    TRG: %-18s -> %-18s\n", inet_ntoa(tp_ch->ip), ether_ntoa(&tp_ch->mac));
        !           417:         else fprintf(stderr, "UNKNOWN IP  TRG: %-18s\n", inet_ntoa(tp_addr));
        !           418:     }
        !           419: 
        !           420:     /* gratuitous ARP packets */
        !           421:     if (se_ch && (se_ch == tp_ch) &&
        !           422:         !memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) {
        !           423:         if (debug > 2) fprintf(stderr, "GOOD PASSED: grat\n");
        !           424:         grat++; return;
        !           425:     }
        !           426: 
        !           427:     /* wildcard trg MAC 00:00:00:00:00:00 */
        !           428:     if (sp_ch && !memcmp(&sp_ch->mac, &zh_addr, sizeof(struct ether_addr))) {
        !           429:         if (debug > 2) fprintf(stderr, "GOOD PASSED: zmac\n");
        !           430:         zmac++; if (!addr_nosubst) return;
        !           431:     }
        !           432:     /* wildcard sdr IP 0.0.0.0 */
        !           433:     if (se_ch && !memcmp(&se_ch->ip, &zp_addr, sizeof(struct in_addr))) {
        !           434:         if (debug > 2) fprintf(stderr, "GOOD PASSED: zip\n");
        !           435:         zip++; if (!addr_nosubst) return;
        !           436:     }
        !           437: 
        !           438:     /* correct pair - sdr MAC pos == sdr IP pos and listed trg IP pos or not duplex */
        !           439:     if (se_ch && (se_ch == sp_ch) && (tp_ch || !duplex)) {
        !           440:         if (debug > 2) fprintf(stderr, "GOOD PASSED: good\n");
        !           441:         good++; return;
        !           442:     }
        !           443: 
        !           444:     /* sdr MAC and sdr IP are both not listed - new pair */
        !           445:     if (!se_ch && (se_ch == sp_ch)) {
        !           446:         if (verbose) {
        !           447:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           448:             snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           449:             log_str(NOTICE, "bnew:", s);
        !           450:         }
        !           451:         bnew++; bsdr++; if (grant) return;
        !           452:     }
        !           453: 
        !           454:     /* sdr MAC is listed but IP is not */
        !           455:     if (se_ch && (se_ch != sp_ch)) {
        !           456:         if (verbose) {
        !           457:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           458:             snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           459:             log_str(NOTICE, "bsip:", s);
        !           460:         }
        !           461:         bsip++; bsdr++;
        !           462:     }
        !           463:     /* sdr IP is listed but MAC is not */
        !           464:     if (sp_ch && (se_ch != sp_ch)) {
        !           465:         if (verbose) {
        !           466:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           467:             snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           468:             log_str(NOTICE, "bmac:", s);
        !           469:         }
        !           470:         bmac++; bsdr++;
        !           471:     }
        !           472: 
        !           473:     /* do not block gratuitous ARP in hidden mode */
        !           474:     if (!memcmp(&sp_addr, &tp_addr, sizeof(struct in_addr))) {
        !           475:         if (verbose) {
        !           476:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           477:             snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           478:             log_str(NOTICE, "bgrt:", s);
        !           479:         }
        !           480:         bgrat++; if (hidden) return;
        !           481:     }
        !           482: 
        !           483:     /* if duplex and trg IP is not listed then block */
        !           484:     if (!tp_ch) {
        !           485:         if (verbose) {
        !           486:             strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           487:             snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           488:             log_str(NOTICE, "btip:", s);
        !           489:         }
        !           490:         btip++; if (!bsdr && !duplex) return;
        !           491:     }
        !           492: 
        !           493:     /* add pirate pair to bad buffer */
        !           494:     if (bsdr && buffer_num) buffer_add();
        !           495: 
        !           496:     strncpy(ntoasw, inet_ntoa(tp_addr), 16);
        !           497:     snprintf(s, 128, "%-17s %-15s %-15s", ether_ntoa(&sh_addr), inet_ntoa(sp_addr), ntoasw);
        !           498:     log_str(NOTICE, "xxxx:", s);
        !           499: 
        !           500:     /* block pirate
        !           501:         eth fake MAC -> pirate MAC
        !           502:         sdr fake MAC - target IP
        !           503:         trg pirate MAC - pirate IP
        !           504:     */
        !           505:     memcpy(&te_addr, &se_addr, sizeof(struct ether_addr));
        !           506:     memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr));
        !           507:     memcpy(&th_addr, &sh_addr, sizeof(struct ether_addr));
        !           508:     memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr));
        !           509:     memcpy(&swip, &tp_addr, sizeof(struct in_addr));
        !           510:     memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr));
        !           511:     memcpy(&sp_addr, &swip, sizeof(struct in_addr));
        !           512:     packet_send(ARPOP_REPLY, fake_num);
        !           513: 
        !           514:     if (bsdr) {
        !           515:         /* control headshot
        !           516:             eth fake MAC -> pirate MAC
        !           517:             sdr fake MAC - pirate IP
        !           518:             trg pirate MAC - pirate IP
        !           519:         */
        !           520:         memcpy(&sp_addr, &tp_addr, sizeof(struct in_addr));
        !           521:         packet_send(ARPOP_REPLY, 1);
        !           522:     }
        !           523: 
        !           524:     /* and fix broken ARP caches by broadcast */
        !           525:     if (bsdr && fixbc) {
        !           526:         memcpy(&te_addr, &bh_addr, sizeof(struct ether_addr));
        !           527:         memcpy(&th_addr, &zh_addr, sizeof(struct ether_addr));
        !           528:         if (sp_ch) {
        !           529:             /* sdr IP is valid
        !           530:                 eth ethers MAC -> broadcast
        !           531:                 sdr ethers MAC - ethers IP
        !           532:                 trg zero MAC - ethers IP
        !           533:             */
        !           534:             memcpy(&se_addr, &sp_ch->mac, sizeof(struct ether_addr));
        !           535:             memcpy(&sh_addr, &sp_ch->mac, sizeof(struct ether_addr));
        !           536:             memcpy(&sp_addr, &sp_ch->ip, sizeof(struct in_addr));
        !           537:         } else if (se_ch) {
        !           538:             /* sdr MAC is valid
        !           539:                 eth ethers MAC -> broadcast
        !           540:                 sdr ethers MAC - ethers IP
        !           541:                 trg zero MAC - ethers IP
        !           542:             ** disabled as probably useless **
        !           543:             memcpy(&se_addr, &se_ch->mac, sizeof(struct ether_addr));
        !           544:             memcpy(&sh_addr, &se_ch->mac, sizeof(struct ether_addr));
        !           545:             memcpy(&sp_addr, &se_ch->ip, sizeof(struct in_addr));
        !           546:             */
        !           547:         } else {
        !           548:             /* invalid sender
        !           549:                 eth fake MAC -> broadcast
        !           550:                 sdr fake MAC - pirate IP
        !           551:                 trg zero MAC - pirate IP
        !           552:             */
        !           553:             memcpy(&se_addr, &fake_addr, sizeof(struct ether_addr));
        !           554:             memcpy(&sh_addr, &fake_addr, sizeof(struct ether_addr));
        !           555:         }
        !           556:         memcpy(&tp_addr, &sp_addr, sizeof(struct in_addr));
        !           557:         packet_send(ARPOP_REQUEST, 1);
        !           558:     }
        !           559: 
        !           560:     bad++;
        !           561:     if (debug > 2)
        !           562:         fprintf(stderr, "STATS:  god %-6d  new %-6d  bmc %-6d  bip %-6d  btg %-6d  all %-6d\n",
        !           563:             good+mymac+fake+pfake+grat+wgrat+zmac+zip, bnew, bmac, bsip, btip, all);
        !           564: }
        !           565: 
        !           566: void packet_handle(char *blah, struct pcap_pkthdr *blah2, u_char *recv) {
        !           567:     struct ether_header *eth_h = NULL;
        !           568:     struct ether_arp *arp_h = NULL;
        !           569:     int op;
        !           570: 
        !           571:     sig_catch();
        !           572:     if (ethers_update) ethers_stat();
        !           573:     if (fake_regen) packet_fmacs(2);
        !           574: 
        !           575:     eth_h = (struct ether_header *) recv;
        !           576:     if (htons(eth_h->ether_type) != ETHERTYPE_ARP) {
        !           577:         snprintf(s, 8, "0x%x", eth_h->ether_type);
        !           578:         log_str(WARNING, "wrong ethertype:", s); return;
        !           579:     }
        !           580: 
        !           581:     memcpy(&se_addr, &eth_h->ether_shost, sizeof(struct ether_addr));
        !           582:     memcpy(&te_addr, &eth_h->ether_dhost, sizeof(struct ether_addr));
        !           583: 
        !           584:     arp_h = (struct ether_arp *) ((char *) eth_h + ETHER_HDR_LEN);
        !           585:     if (htons(arp_h->ea_hdr.ar_hrd) != ARPHRD_ETHER) {
        !           586:         snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_hrd);
        !           587:         log_str(WARNING, "wrong hw address:", s); return;
        !           588:     }
        !           589:     if (htons(arp_h->ea_hdr.ar_pro) != ETHERTYPE_IP) {
        !           590:         snprintf(s, 8, "0x%x", arp_h->ea_hdr.ar_pro);
        !           591:         log_str(WARNING, "wrong proto address:", s); return;
        !           592:     }
        !           593:     op = htons(arp_h->ea_hdr.ar_op);
        !           594: 
        !           595:     memcpy(&sh_addr, &arp_h->arp_sha, sizeof(struct ether_addr));
        !           596:     memcpy(&sp_addr, &arp_h->arp_spa, sizeof(struct in_addr));
        !           597:     memcpy(&th_addr, &arp_h->arp_tha, sizeof(struct ether_addr));
        !           598:     memcpy(&tp_addr, &arp_h->arp_tpa, sizeof(struct in_addr));
        !           599: 
        !           600:     if (debug > 1) {
        !           601:         fprintf(stderr, "RECV ARP %u: ", op);
        !           602:         fprintf(stderr, "%-17s -> ", ether_ntoa(&se_addr)); fprintf(stderr, "%-17s\n  ", ether_ntoa(&te_addr));
        !           603:         fprintf(stderr, "sdr %-17s %-15s  ", ether_ntoa(&sh_addr), inet_ntoa(sp_addr));
        !           604:         fprintf(stderr, "trg %-17s %-15s\n", ether_ntoa(&th_addr), inet_ntoa(tp_addr));
        !           605:     }
        !           606: 
        !           607:     if (op == ARPOP_REPLY) return;
        !           608:     if (op != ARPOP_REQUEST) {
        !           609:         snprintf(s, 8, "0x%x", op);
        !           610:         log_str(WARNING, "wrong arp op:", s);
        !           611:         return;
        !           612:     }
        !           613: 
        !           614:     all++;
        !           615:     packet_check();
        !           616: }
        !           617: 
        !           618: void packet_recv(void) {
        !           619:     if (pcap_loop(pcap, -1, (pcap_handler) packet_handle, NULL) == -1) {
        !           620:         log_str(ERROR, "pcap_loop()", "failed");
        !           621:         exit_ipguard(EXIT_FAILURE);
        !           622:     }
        !           623: }
        !           624: 
        !           625: void stat_dump(void) {
        !           626:     struct pcap_stat ps;
        !           627: 
        !           628:     snprintf(s, 64, "ARP statistics:");
        !           629:     log_str(INFO, s, "");
        !           630:     snprintf(s, 64, "Total ARP who-has packets %u", all);
        !           631:     log_str(INFO, s, "");
        !           632:     snprintf(s, 64, "Good MAC-IP pairs %u", good);
        !           633:     log_str(INFO, s, "");
        !           634:     snprintf(s, 64, "Gratuitous MAC-IP/weird %u/%u", grat, wgrat);
        !           635:     log_str(INFO, s, "");
        !           636:     snprintf(s, 64, "Zero MAC/IP %u/%u", zmac, zip);
        !           637:     log_str(INFO, s, "");
        !           638:     snprintf(s, 64, "New MAC-IP pairs %u", bnew);
        !           639:     log_str(INFO, s, "");
        !           640:     snprintf(s, 64, "Bad MAC-IP pairs %u", bad);
        !           641:     log_str(INFO, s, "");
        !           642:     snprintf(s, 64, "Bad MAC/IP %u/%u", bmac, bsip);
        !           643:     log_str(INFO, s, "");
        !           644:     if (duplex) {
        !           645:         snprintf(s, 64, "Bad target IP %u", btip);
        !           646:         log_str(INFO, s, "");
        !           647:     }
        !           648:     snprintf(s, 64, "Bad gratuitous MAC-IP %u", bgrat);
        !           649:     log_str(INFO, s, "");
        !           650:     snprintf(s, 64, "My/Fake/PreFake MAC %u/%u/%u", mymac, fake, pfake);
        !           651:     log_str(INFO, s, "");
        !           652:     snprintf(s, 64, "Mismatch sender Ether/ARP MAC %u", mis);
        !           653:     log_str(INFO, s, "");
        !           654:     snprintf(s, 64, "Non-zero target ARP MAC %u", nzh);
        !           655:     log_str(INFO, s, "");
        !           656:     snprintf(s, 64, "Non-bcast target Ether MAC %u", nbe);
        !           657:     log_str(INFO, s, "");
        !           658: 
        !           659:     if (pcap_stats(pcap, &ps) == -1) {
        !           660:         log_str(WARNING, "pcap_stat()", "failed"); return;
        !           661:     }
        !           662:     snprintf(s, 64, "PCAP statistics:");
        !           663:     log_str(INFO, s, "");
        !           664:     snprintf(s, 64, "Received/Dropped packets %u/%u", ps.ps_recv, ps.ps_drop);
        !           665:     log_str(INFO, s, "");
        !           666: }
        !           667: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>