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>