Annotation of embedaddon/strongswan/src/libcharon/plugins/farp/farp_spoofer.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2010 Martin Willi
        !             3:  * Copyright (C) 2010 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "farp_spoofer.h"
        !            17: 
        !            18: #include <errno.h>
        !            19: #include <unistd.h>
        !            20: #include <sys/socket.h>
        !            21: #include <linux/if_arp.h>
        !            22: #include <linux/if_ether.h>
        !            23: #include <linux/filter.h>
        !            24: #include <sys/ioctl.h>
        !            25: 
        !            26: #include <daemon.h>
        !            27: #include <threading/thread.h>
        !            28: #include <processing/jobs/callback_job.h>
        !            29: 
        !            30: typedef struct private_farp_spoofer_t private_farp_spoofer_t;
        !            31: 
        !            32: /**
        !            33:  * Private data of an farp_spoofer_t object.
        !            34:  */
        !            35: struct private_farp_spoofer_t {
        !            36: 
        !            37:        /**
        !            38:         * Public farp_spoofer_t interface.
        !            39:         */
        !            40:        farp_spoofer_t public;
        !            41: 
        !            42:        /**
        !            43:         * Listener that knows active addresses
        !            44:         */
        !            45:        farp_listener_t *listener;
        !            46: 
        !            47:        /**
        !            48:         * RAW socket for ARP requests
        !            49:         */
        !            50:        int skt;
        !            51: };
        !            52: 
        !            53: /**
        !            54:  * IP over Ethernet ARP message
        !            55:  */
        !            56: typedef struct __attribute__((packed)) {
        !            57:        uint16_t hardware_type;
        !            58:        uint16_t protocol_type;
        !            59:        uint8_t hardware_size;
        !            60:        uint8_t protocol_size;
        !            61:        uint16_t opcode;
        !            62:        uint8_t sender_mac[6];
        !            63:        uint8_t sender_ip[4];
        !            64:        uint8_t target_mac[6];
        !            65:        uint8_t target_ip[4];
        !            66: } arp_t;
        !            67: 
        !            68: /**
        !            69:  * Send faked ARP response
        !            70:  */
        !            71: static void send_arp(private_farp_spoofer_t *this,
        !            72:                                         arp_t *arp, struct sockaddr_ll *addr)
        !            73: {
        !            74:        struct ifreq req;
        !            75:        char tmp[4];
        !            76: 
        !            77:        req.ifr_ifindex = addr->sll_ifindex;
        !            78:        if (ioctl(this->skt, SIOCGIFNAME, &req) == 0 &&
        !            79:                ioctl(this->skt, SIOCGIFHWADDR, &req) == 0 &&
        !            80:                req.ifr_hwaddr.sa_family == ARPHRD_ETHER)
        !            81:        {
        !            82:                memcpy(arp->target_mac, arp->sender_mac, 6);
        !            83:                memcpy(arp->sender_mac, req.ifr_hwaddr.sa_data, 6);
        !            84: 
        !            85:                memcpy(tmp, arp->sender_ip, 4);
        !            86:                memcpy(arp->sender_ip, arp->target_ip, 4);
        !            87:                memcpy(arp->target_ip, tmp, 4);
        !            88: 
        !            89:                arp->opcode = htons(ARPOP_REPLY);
        !            90: 
        !            91:                sendto(this->skt, arp, sizeof(*arp), 0,
        !            92:                           (struct sockaddr*)addr, sizeof(*addr));
        !            93:        }
        !            94: }
        !            95: 
        !            96: /**
        !            97:  * ARP request receiving
        !            98:  */
        !            99: static bool receive_arp(private_farp_spoofer_t *this)
        !           100: {
        !           101:        struct sockaddr_ll addr;
        !           102:        socklen_t addr_len = sizeof(addr);
        !           103:        arp_t arp;
        !           104:        ssize_t len;
        !           105:        host_t *local, *remote;
        !           106: 
        !           107:        len = recvfrom(this->skt, &arp, sizeof(arp), MSG_DONTWAIT,
        !           108:                                   (struct sockaddr*)&addr, &addr_len);
        !           109:        if (len == sizeof(arp))
        !           110:        {
        !           111:                local = host_create_from_chunk(AF_INET,
        !           112:                                                                        chunk_create((char*)&arp.sender_ip, 4), 0);
        !           113:                remote = host_create_from_chunk(AF_INET,
        !           114:                                                                        chunk_create((char*)&arp.target_ip, 4), 0);
        !           115:                if (this->listener->has_tunnel(this->listener, local, remote))
        !           116:                {
        !           117:                        send_arp(this, &arp, &addr);
        !           118:                }
        !           119:                local->destroy(local);
        !           120:                remote->destroy(remote);
        !           121:        }
        !           122: 
        !           123:        return TRUE;
        !           124: }
        !           125: 
        !           126: METHOD(farp_spoofer_t, destroy, void,
        !           127:        private_farp_spoofer_t *this)
        !           128: {
        !           129:        lib->watcher->remove(lib->watcher, this->skt);
        !           130:        close(this->skt);
        !           131:        free(this);
        !           132: }
        !           133: 
        !           134: /**
        !           135:  * See header
        !           136:  */
        !           137: farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
        !           138: {
        !           139:        private_farp_spoofer_t *this;
        !           140:        struct sock_filter arp_request_filter_code[] = {
        !           141:                BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, protocol_type)),
        !           142:                BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_P_IP, 0, 9),
        !           143:                BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, hardware_size)),
        !           144:                BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 7),
        !           145:                BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, protocol_size)),
        !           146:                BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 5),
        !           147:                BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)),
        !           148:                BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3),
        !           149:                BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
        !           150:                BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, sizeof(arp_t), 0, 1),
        !           151:                BPF_STMT(BPF_RET+BPF_K, sizeof(arp_t)),
        !           152:                BPF_STMT(BPF_RET+BPF_K, 0),
        !           153:        };
        !           154:        struct sock_fprog arp_request_filter = {
        !           155:                sizeof(arp_request_filter_code) / sizeof(struct sock_filter),
        !           156:                arp_request_filter_code,
        !           157:        };
        !           158: 
        !           159:        INIT(this,
        !           160:                .public = {
        !           161:                        .destroy = _destroy,
        !           162:                },
        !           163:                .listener = listener,
        !           164:        );
        !           165: 
        !           166:        this->skt = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
        !           167:        if (this->skt == -1)
        !           168:        {
        !           169:                DBG1(DBG_NET, "opening ARP packet socket failed: %s", strerror(errno));
        !           170:                free(this);
        !           171:                return NULL;
        !           172:        }
        !           173: 
        !           174:        if (setsockopt(this->skt, SOL_SOCKET, SO_ATTACH_FILTER,
        !           175:                                   &arp_request_filter, sizeof(arp_request_filter)) < 0)
        !           176:        {
        !           177:                DBG1(DBG_NET, "installing ARP packet filter failed: %s", strerror(errno));
        !           178:                close(this->skt);
        !           179:                free(this);
        !           180:                return NULL;
        !           181:        }
        !           182: 
        !           183:        lib->watcher->add(lib->watcher, this->skt, WATCHER_READ,
        !           184:                                          (watcher_cb_t)receive_arp, this);
        !           185: 
        !           186:        return &this->public;
        !           187: }

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