Return to farp_spoofer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / farp |
1.1 misho 1: /* 1.1.1.2 ! misho 2: * Copyright (C) 2021 Tobias Brunner ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * 1.1 misho 5: * Copyright (C) 2010 Martin Willi 6: * Copyright (C) 2010 revosec AG 7: * 8: * This program is free software; you can redistribute it and/or modify it 9: * under the terms of the GNU General Public License as published by the 10: * Free Software Foundation; either version 2 of the License, or (at your 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 12: * 13: * This program is distributed in the hope that it will be useful, but 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16: * for more details. 17: */ 18: 1.1.1.2 ! misho 19: /* ! 20: * For the Apple BPF implementation. ! 21: * ! 22: * Copyright (C) 2020 Dan James <sddj@me.com> ! 23: * ! 24: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 25: * of this software and associated documentation files (the "Software"), to deal ! 26: * in the Software without restriction, including without limitation the rights ! 27: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 28: * copies of the Software, and to permit persons to whom the Software is ! 29: * furnished to do so, subject to the following conditions: ! 30: * ! 31: * The above copyright notice and this permission notice shall be included in ! 32: * all copies or substantial portions of the Software. ! 33: * ! 34: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 35: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 36: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ! 37: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 38: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 39: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 40: * THE SOFTWARE. ! 41: */ ! 42: 1.1 misho 43: #include "farp_spoofer.h" 44: 45: #include <errno.h> 46: #include <unistd.h> 1.1.1.2 ! misho 47: #include <sys/ioctl.h> ! 48: ! 49: #if !defined(__APPLE__) && !defined(__FreeBSD__) 1.1 misho 50: #include <sys/socket.h> 51: #include <linux/if_arp.h> 52: #include <linux/if_ether.h> 53: #include <linux/filter.h> 1.1.1.2 ! misho 54: #else ! 55: #include <fcntl.h> ! 56: #include <ifaddrs.h> ! 57: #include <net/bpf.h> ! 58: #include <net/ethernet.h> ! 59: #include <net/if.h> ! 60: #include <net/if_arp.h> ! 61: #include <net/if_dl.h> ! 62: #endif /* !defined(__APPLE__) && !defined(__FreeBSD__) */ 1.1 misho 63: 64: #include <daemon.h> 65: #include <threading/thread.h> 66: #include <processing/jobs/callback_job.h> 67: 68: typedef struct private_farp_spoofer_t private_farp_spoofer_t; 69: 70: /** 71: * Private data of an farp_spoofer_t object. 72: */ 73: struct private_farp_spoofer_t { 74: 75: /** 76: * Public farp_spoofer_t interface. 77: */ 78: farp_spoofer_t public; 79: 80: /** 81: * Listener that knows active addresses 82: */ 83: farp_listener_t *listener; 84: 1.1.1.2 ! misho 85: #if !defined(__APPLE__) && !defined(__FreeBSD__) 1.1 misho 86: /** 87: * RAW socket for ARP requests 88: */ 89: int skt; 1.1.1.2 ! misho 90: #else ! 91: /** ! 92: * Linked list of interface handlers ! 93: */ ! 94: linked_list_t *handlers; ! 95: #endif /* !defined(__APPLE__) && !defined(__FreeBSD__) */ 1.1 misho 96: }; 97: 98: /** 99: * IP over Ethernet ARP message 100: */ 101: typedef struct __attribute__((packed)) { 102: uint16_t hardware_type; 103: uint16_t protocol_type; 104: uint8_t hardware_size; 105: uint8_t protocol_size; 106: uint16_t opcode; 107: uint8_t sender_mac[6]; 108: uint8_t sender_ip[4]; 109: uint8_t target_mac[6]; 110: uint8_t target_ip[4]; 111: } arp_t; 112: 1.1.1.2 ! misho 113: #if !defined(__APPLE__) && !defined(__FreeBSD__) 1.1 misho 114: /** 115: * Send faked ARP response 116: */ 117: static void send_arp(private_farp_spoofer_t *this, 118: arp_t *arp, struct sockaddr_ll *addr) 119: { 120: struct ifreq req; 121: char tmp[4]; 122: 123: req.ifr_ifindex = addr->sll_ifindex; 124: if (ioctl(this->skt, SIOCGIFNAME, &req) == 0 && 125: ioctl(this->skt, SIOCGIFHWADDR, &req) == 0 && 126: req.ifr_hwaddr.sa_family == ARPHRD_ETHER) 127: { 128: memcpy(arp->target_mac, arp->sender_mac, 6); 129: memcpy(arp->sender_mac, req.ifr_hwaddr.sa_data, 6); 130: 131: memcpy(tmp, arp->sender_ip, 4); 132: memcpy(arp->sender_ip, arp->target_ip, 4); 133: memcpy(arp->target_ip, tmp, 4); 134: 135: arp->opcode = htons(ARPOP_REPLY); 136: 137: sendto(this->skt, arp, sizeof(*arp), 0, 138: (struct sockaddr*)addr, sizeof(*addr)); 139: } 140: } 141: 142: /** 143: * ARP request receiving 144: */ 145: static bool receive_arp(private_farp_spoofer_t *this) 146: { 147: struct sockaddr_ll addr; 148: socklen_t addr_len = sizeof(addr); 149: arp_t arp; 150: ssize_t len; 151: host_t *local, *remote; 152: 153: len = recvfrom(this->skt, &arp, sizeof(arp), MSG_DONTWAIT, 154: (struct sockaddr*)&addr, &addr_len); 155: if (len == sizeof(arp)) 156: { 157: local = host_create_from_chunk(AF_INET, 158: chunk_create((char*)&arp.sender_ip, 4), 0); 159: remote = host_create_from_chunk(AF_INET, 160: chunk_create((char*)&arp.target_ip, 4), 0); 161: if (this->listener->has_tunnel(this->listener, local, remote)) 162: { 163: send_arp(this, &arp, &addr); 164: } 165: local->destroy(local); 166: remote->destroy(remote); 167: } 168: 169: return TRUE; 170: } 171: 172: METHOD(farp_spoofer_t, destroy, void, 173: private_farp_spoofer_t *this) 174: { 175: lib->watcher->remove(lib->watcher, this->skt); 176: close(this->skt); 177: free(this); 178: } 179: 180: /** 181: * See header 182: */ 183: farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener) 184: { 185: private_farp_spoofer_t *this; 186: struct sock_filter arp_request_filter_code[] = { 187: BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, protocol_type)), 188: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_P_IP, 0, 9), 189: BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, hardware_size)), 190: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 7), 191: BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, protocol_size)), 192: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 5), 193: BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)), 194: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3), 195: BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0), 196: BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, sizeof(arp_t), 0, 1), 197: BPF_STMT(BPF_RET+BPF_K, sizeof(arp_t)), 198: BPF_STMT(BPF_RET+BPF_K, 0), 199: }; 200: struct sock_fprog arp_request_filter = { 201: sizeof(arp_request_filter_code) / sizeof(struct sock_filter), 202: arp_request_filter_code, 203: }; 204: 205: INIT(this, 206: .public = { 207: .destroy = _destroy, 208: }, 209: .listener = listener, 210: ); 211: 212: this->skt = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)); 213: if (this->skt == -1) 214: { 215: DBG1(DBG_NET, "opening ARP packet socket failed: %s", strerror(errno)); 216: free(this); 217: return NULL; 218: } 219: 220: if (setsockopt(this->skt, SOL_SOCKET, SO_ATTACH_FILTER, 221: &arp_request_filter, sizeof(arp_request_filter)) < 0) 222: { 1.1.1.2 ! misho 223: DBG1(DBG_NET, "installing ARP packet filter failed: %s", ! 224: strerror(errno)); 1.1 misho 225: close(this->skt); 226: free(this); 227: return NULL; 228: } 229: 230: lib->watcher->add(lib->watcher, this->skt, WATCHER_READ, 231: (watcher_cb_t)receive_arp, this); 232: 233: return &this->public; 234: } 1.1.1.2 ! misho 235: ! 236: #else /* !defined(__APPLE__) && !defined(__FreeBSD__) */ ! 237: ! 238: /** ! 239: * A handler is required for each interface. ! 240: */ ! 241: struct farp_handler_t { ! 242: ! 243: /** ! 244: * Reference to the private farp spoofer. ! 245: */ ! 246: private_farp_spoofer_t *this; ! 247: ! 248: /** ! 249: * The name of the interface to be handled. ! 250: */ ! 251: char *name; ! 252: ! 253: /** ! 254: * The IPv4 address of this interface. ! 255: */ ! 256: host_t *ipv4; ! 257: ! 258: /** ! 259: * The Ethernet MAC address of this interface. ! 260: */ ! 261: chunk_t mac; ! 262: ! 263: /** ! 264: * The BPF file descriptor for this interface. ! 265: */ ! 266: int fd; ! 267: ! 268: /** ! 269: * The BPF packet buffer length as read from the BPF fd. ! 270: */ ! 271: size_t buflen; ! 272: ! 273: /** ! 274: * An allocated buffer for receiving packets from BPF. ! 275: */ ! 276: uint8_t *bufdat; ! 277: }; ! 278: ! 279: typedef struct farp_handler_t farp_handler_t; ! 280: ! 281: /** ! 282: * An Ethernet frame for an ARP packet. ! 283: */ ! 284: struct frame_t { ! 285: struct ether_header e; ! 286: arp_t a; ! 287: }; ! 288: ! 289: typedef struct frame_t frame_t; ! 290: ! 291: /** ! 292: * Find and open an available BPF device. ! 293: */ ! 294: static int bpf_open() ! 295: { ! 296: static int no_cloning_bpf = 0; ! 297: /* enough space for: /dev/bpf000\0 */ ! 298: char device[12]; ! 299: int n = no_cloning_bpf ? 0 : -1; ! 300: int fd; ! 301: ! 302: do ! 303: { ! 304: if (n < 0) ! 305: { ! 306: snprintf(device, sizeof(device), "/dev/bpf"); ! 307: } ! 308: else ! 309: { ! 310: snprintf(device, sizeof(device), "/dev/bpf%d", n); ! 311: } ! 312: ! 313: fd = open(device, O_RDWR); ! 314: ! 315: if (n++ < 0 && fd < 0 && errno == ENOENT) ! 316: { ! 317: no_cloning_bpf = 1; ! 318: errno = EBUSY; ! 319: } ! 320: } ! 321: while (fd < 0 && errno == EBUSY && n < 1000); ! 322: ! 323: return fd; ! 324: } ! 325: ! 326: /** ! 327: * Free resources used by a handler. ! 328: */ ! 329: static void handler_destroy(farp_handler_t *handler) ! 330: { ! 331: if (handler->fd >= 0) ! 332: { ! 333: lib->watcher->remove(lib->watcher, handler->fd); ! 334: close(handler->fd); ! 335: } ! 336: DESTROY_IF(handler->ipv4); ! 337: chunk_free(&handler->mac); ! 338: free(handler->bufdat); ! 339: free(handler->name); ! 340: free(handler); ! 341: } ! 342: ! 343: /** ! 344: * Find the handler for the named interface, creating one if needed. ! 345: */ ! 346: static farp_handler_t *get_handler(private_farp_spoofer_t* this, ! 347: char *interface_name) ! 348: { ! 349: farp_handler_t *handler, *found = NULL; ! 350: enumerator_t *enumerator; ! 351: ! 352: enumerator = this->handlers->create_enumerator(this->handlers); ! 353: while (enumerator->enumerate(enumerator, &handler)) ! 354: { ! 355: if (streq(handler->name, interface_name)) ! 356: { ! 357: found = handler; ! 358: break; ! 359: } ! 360: } ! 361: enumerator->destroy(enumerator); ! 362: ! 363: if (!found) ! 364: { ! 365: INIT(found, ! 366: .this = this, ! 367: .name = strdup(interface_name), ! 368: .fd = -1, ! 369: ); ! 370: this->handlers->insert_last(this->handlers, found); ! 371: } ! 372: return found; ! 373: } ! 374: ! 375: /** ! 376: * Send an ARP response for the given ARP request. ! 377: */ ! 378: static void handler_send(farp_handler_t *handler, arp_t *arpreq, host_t *lcl, ! 379: host_t *rmt) ! 380: { ! 381: frame_t frame; ! 382: chunk_t mac; ! 383: ssize_t n; ! 384: ! 385: memcpy(frame.e.ether_dhost, arpreq->sender_mac, ETHER_ADDR_LEN); ! 386: mac = chunk_create(frame.e.ether_dhost, ETHER_ADDR_LEN); ! 387: memcpy(frame.e.ether_shost, handler->mac.ptr, ETHER_ADDR_LEN); ! 388: frame.e.ether_type = htons(ETHERTYPE_ARP); ! 389: ! 390: frame.a.hardware_type = htons(1); ! 391: frame.a.protocol_type = htons(ETHERTYPE_IP); ! 392: frame.a.hardware_size = arpreq->hardware_size; ! 393: frame.a.protocol_size = arpreq->protocol_size; ! 394: frame.a.opcode = htons(ARPOP_REPLY); ! 395: memcpy(frame.a.sender_mac, handler->mac.ptr, ETHER_ADDR_LEN); ! 396: memcpy(frame.a.sender_ip, arpreq->target_ip, sizeof(arpreq->target_ip)); ! 397: memcpy(frame.a.target_mac, arpreq->sender_mac, sizeof(arpreq->sender_mac)); ! 398: memcpy(frame.a.target_ip, arpreq->sender_ip, sizeof(arpreq->sender_ip)); ! 399: ! 400: DBG2(DBG_NET, "replying to ARP request for %H from %H (%#B) on %s", ! 401: rmt, lcl, &mac, handler->name); ! 402: ! 403: n = write(handler->fd, &frame, sizeof(frame)); ! 404: if (n != sizeof(frame)) ! 405: { ! 406: DBG1(DBG_NET, "sending ARP reply failed: %s", strerror(errno)); ! 407: } ! 408: } ! 409: ! 410: /** ! 411: * Receive and examine the available ARP requests. If a tunnel exists, send an ! 412: * ARP response back out the same interface. ! 413: */ ! 414: CALLBACK(handler_onarp, bool, ! 415: farp_handler_t *handler, int fd, watcher_event_t event) ! 416: { ! 417: struct bpf_hdr *bh; ! 418: struct ether_header *eh; ! 419: arp_t *a; ! 420: host_t *lcl, *rmt; ! 421: uint8_t *p = handler->bufdat; ! 422: ssize_t n; ! 423: ! 424: n = read(handler->fd, handler->bufdat, handler->buflen); ! 425: if (n <= 0) ! 426: { ! 427: DBG1(DBG_NET, "reading ARP request from %s failed: %s", handler->name, ! 428: strerror(errno)); ! 429: return FALSE; ! 430: } ! 431: ! 432: while (p < handler->bufdat + n) ! 433: { ! 434: bh = (struct bpf_hdr*)p; ! 435: eh = (struct ether_header*)(p + bh->bh_hdrlen); ! 436: a = (arp_t*)(p + bh->bh_hdrlen + sizeof(struct ether_header)); ! 437: ! 438: lcl = host_create_from_chunk(AF_INET, chunk_create(a->sender_ip, 4), 0); ! 439: rmt = host_create_from_chunk(AF_INET, chunk_create(a->target_ip, 4), 0); ! 440: if (lcl && rmt && ! 441: handler->this->listener->has_tunnel(handler->this->listener, ! 442: lcl, rmt)) ! 443: { ! 444: handler_send(handler, a, lcl, rmt); ! 445: } ! 446: DESTROY_IF(rmt); ! 447: DESTROY_IF(lcl); ! 448: ! 449: p += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); ! 450: } ! 451: return TRUE; ! 452: } ! 453: ! 454: /** ! 455: * Create an initialize a BPF handler for the interface specified in the farp ! 456: * handler. This entails opening a BPF device, binding it to the interface, ! 457: * setting the packet filter, and allocating a buffer for receiving packets. ! 458: */ ! 459: static bool setup_handler(private_farp_spoofer_t *this, farp_handler_t *handler) ! 460: { ! 461: struct bpf_insn instructions[] = { ! 462: BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0), ! 463: BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, ! 464: sizeof(struct ether_header) + sizeof(arp_t), 0, 11), ! 465: BPF_STMT(BPF_LD+BPF_H+BPF_ABS, ! 466: offsetof(struct ether_header, ether_type)), ! 467: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 9), ! 468: BPF_STMT(BPF_LD+BPF_H+BPF_ABS, ! 469: sizeof(struct ether_header) + offsetof(arp_t, protocol_type)), ! 470: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 7), ! 471: BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ! 472: sizeof(struct ether_header) + offsetof(arp_t, hardware_size)), ! 473: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 5), ! 474: BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ! 475: sizeof(struct ether_header) + offsetof(arp_t, protocol_size)), ! 476: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 3), ! 477: BPF_STMT(BPF_LD+BPF_H+BPF_ABS, ! 478: sizeof(struct ether_header) + offsetof(arp_t, opcode)), ! 479: BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 1), ! 480: BPF_STMT(BPF_RET+BPF_K, 14 + sizeof(arp_t)), ! 481: BPF_STMT(BPF_RET+BPF_K, 0) ! 482: }; ! 483: struct bpf_program program; ! 484: struct ifreq req; ! 485: uint32_t disable = 1; ! 486: uint32_t enable = 1; ! 487: uint32_t dlt = 0; ! 488: ! 489: snprintf(req.ifr_name, sizeof(req.ifr_name), "%s", handler->name); ! 490: ! 491: if ((handler->fd = bpf_open()) < 0) ! 492: { ! 493: DBG1(DBG_NET, "bpf_open(%s): %s", handler->name, strerror(errno)); ! 494: return FALSE; ! 495: } ! 496: ! 497: if (ioctl(handler->fd, BIOCSETIF, &req) < 0) ! 498: { ! 499: DBG1(DBG_NET, "BIOCSETIF(%s): %s", handler->name, strerror(errno)); ! 500: return FALSE; ! 501: } ! 502: ! 503: if (ioctl(handler->fd, BIOCSHDRCMPLT, &enable) < 0) ! 504: { ! 505: DBG1(DBG_NET, "BIOCSHDRCMPLT(%s): %s", handler->name, strerror(errno)); ! 506: return FALSE; ! 507: } ! 508: ! 509: if (ioctl(handler->fd, BIOCSSEESENT, &disable) < 0) ! 510: { ! 511: DBG1(DBG_NET, "BIOCSSEESENT(%s): %s", handler->name, strerror(errno)); ! 512: return FALSE; ! 513: } ! 514: ! 515: if (ioctl(handler->fd, BIOCIMMEDIATE, &enable) < 0) ! 516: { ! 517: DBG1(DBG_NET, "BIOCIMMEDIATE(%s): %s", handler->name, strerror(errno)); ! 518: return FALSE; ! 519: } ! 520: ! 521: if (ioctl(handler->fd, BIOCGDLT, &dlt) < 0) ! 522: { ! 523: DBG1(DBG_NET, "BIOCGDLT(%s): %s", handler->name, strerror(errno)); ! 524: return FALSE; ! 525: } ! 526: else if (dlt != DLT_EN10MB) ! 527: { ! 528: return FALSE; ! 529: } ! 530: ! 531: program.bf_len = sizeof(instructions) / sizeof(struct bpf_insn); ! 532: program.bf_insns = &instructions[0]; ! 533: ! 534: if (ioctl(handler->fd, BIOCSETF, &program) < 0) ! 535: { ! 536: DBG1(DBG_NET, "BIOCSETF(%s): %s", handler->name, strerror(errno)); ! 537: return FALSE; ! 538: } ! 539: ! 540: if (ioctl(handler->fd, BIOCGBLEN, &handler->buflen) < 0) ! 541: { ! 542: DBG1(DBG_NET, "BIOCGBLEN(%s): %s", handler->name, strerror(errno)); ! 543: return FALSE; ! 544: } ! 545: handler->bufdat = malloc(handler->buflen); ! 546: ! 547: lib->watcher->add(lib->watcher, handler->fd, WATCHER_READ, ! 548: handler_onarp, handler); ! 549: return TRUE; ! 550: } ! 551: ! 552: /** ! 553: * Create a handler for each BPF capable interface. The interface must have an ! 554: * Ethernet MAC address, an IPv4 address, and use an Ethernet data link layer. ! 555: */ ! 556: static bool setup_handlers(private_farp_spoofer_t *this) ! 557: { ! 558: struct ifaddrs *ifas; ! 559: struct ifaddrs *ifa; ! 560: struct sockaddr_dl *dl; ! 561: farp_handler_t* handler; ! 562: enumerator_t *enumerator; ! 563: host_t *ipv4; ! 564: ! 565: if (getifaddrs(&ifas) < 0) ! 566: { ! 567: DBG1(DBG_NET, "farp cannot find interfaces: %s", strerror(errno)); ! 568: return FALSE; ! 569: } ! 570: for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) ! 571: { ! 572: switch (ifa->ifa_addr->sa_family) ! 573: { ! 574: case AF_LINK: ! 575: dl = (struct sockaddr_dl*)ifa->ifa_addr; ! 576: if (dl->sdl_alen == ETHER_ADDR_LEN) ! 577: { ! 578: handler = get_handler(this, ifa->ifa_name); ! 579: handler->mac = chunk_clone(chunk_create(LLADDR(dl), ! 580: dl->sdl_alen)); ! 581: } ! 582: break; ! 583: case AF_INET: ! 584: ipv4 = host_create_from_sockaddr(ifa->ifa_addr); ! 585: if (ipv4 && !ipv4->is_anyaddr(ipv4)) ! 586: { ! 587: handler = get_handler(this, ifa->ifa_name); ! 588: if (!handler->ipv4) ! 589: { ! 590: handler->ipv4 = ipv4->clone(ipv4); ! 591: } ! 592: } ! 593: DESTROY_IF(ipv4); ! 594: break; ! 595: default: ! 596: break; ! 597: } ! 598: } ! 599: freeifaddrs(ifas); ! 600: ! 601: enumerator = this->handlers->create_enumerator(this->handlers); ! 602: while (enumerator->enumerate(enumerator, &handler)) ! 603: { ! 604: if (handler->mac.ptr && handler->ipv4 && ! 605: setup_handler(this, handler)) ! 606: { ! 607: DBG1(DBG_NET, "listening for ARP requests on %s (%H, %#B)", ! 608: handler->name, handler->ipv4, &handler->mac); ! 609: } ! 610: else ! 611: { ! 612: this->handlers->remove_at(this->handlers, enumerator); ! 613: handler_destroy(handler); ! 614: } ! 615: } ! 616: enumerator->destroy(enumerator); ! 617: ! 618: return this->handlers->get_count(this->handlers) > 0; ! 619: } ! 620: ! 621: /** ! 622: * Cleanup the handlers used by this plugin. ! 623: */ ! 624: METHOD(farp_spoofer_t, destroy, void, private_farp_spoofer_t *this) ! 625: { ! 626: enumerator_t *enumerator; ! 627: farp_handler_t *handler; ! 628: ! 629: enumerator = this->handlers->create_enumerator(this->handlers); ! 630: while (enumerator->enumerate(enumerator, &handler)) ! 631: { ! 632: handler_destroy(handler); ! 633: } ! 634: enumerator->destroy(enumerator); ! 635: this->handlers->destroy(this->handlers); ! 636: free(this); ! 637: } ! 638: ! 639: /** ! 640: * See header ! 641: */ ! 642: farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener) ! 643: { ! 644: private_farp_spoofer_t *this; ! 645: ! 646: INIT(this, ! 647: .public = { ! 648: .destroy = _destroy, ! 649: }, ! 650: .listener = listener, ! 651: .handlers = linked_list_create(), ! 652: ); ! 653: ! 654: if (!setup_handlers(this)) ! 655: { ! 656: destroy(this); ! 657: return NULL; ! 658: } ! 659: return &this->public; ! 660: } ! 661: ! 662: #endif /* !defined(__APPLE__) && !defined(__FreeBSD__) */