Annotation of embedaddon/strongswan/src/libcharon/plugins/farp/farp_spoofer.c, revision 1.1.1.2
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__) */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>