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>