Annotation of embedaddon/strongswan/src/libcharon/plugins/farp/farp_spoofer.c, revision 1.1.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>