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, ð_h->ether_shost, sizeof(struct ether_addr));
! 582: memcpy(&te_addr, ð_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>