BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BArpProbe.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <sys/socket.h>
34 #include <net/if.h>
35 #include <net/if_arp.h>
36 #include <sys/ioctl.h>
37 #include <linux/filter.h>
38  
39 #include <misc/debug.h>
40 #include <misc/byteorder.h>
41 #include <misc/ethernet_proto.h>
42 #include <misc/ipv4_proto.h>
43 #include <misc/udp_proto.h>
44 #include <misc/get_iface_info.h>
45 #include <base/BLog.h>
46  
47 #include "BArpProbe.h"
48  
49 #include <generated/blog_channel_BArpProbe.h>
50  
51 #define STATE_INITIAL 1
52 #define STATE_NOEXIST 2
53 #define STATE_EXIST 3
54 #define STATE_EXIST_PANIC 4
55  
56 static void dgram_handler (BArpProbe *o, int event)
57 {
58 DebugObject_Access(&o->d_obj);
59  
60 BLog(BLOG_ERROR, "packet socket error");
61  
62 // report error
63 DEBUGERROR(&o->d_err, o->handler(o->user, BARPPROBE_EVENT_ERROR));
64 return;
65 }
66  
67 static void send_request (BArpProbe *o)
68 {
69 if (o->send_sending) {
70 BLog(BLOG_ERROR, "cannot send packet while another packet is being sent!");
71 return;
72 }
73  
74 // build packet
75 struct arp_packet *arp = &o->send_packet;
76 arp->hardware_type = hton16(ARP_HARDWARE_TYPE_ETHERNET);
77 arp->protocol_type = hton16(ETHERTYPE_IPV4);
78 arp->hardware_size = hton8(6);
79 arp->protocol_size = hton8(4);
80 arp->opcode = hton16(ARP_OPCODE_REQUEST);
81 memcpy(arp->sender_mac, o->if_mac, 6);
82 arp->sender_ip = hton32(0);
83 memset(arp->target_mac, 0, sizeof(arp->target_mac));
84 arp->target_ip = o->addr;
85  
86 // send packet
87 PacketPassInterface_Sender_Send(o->send_if, (uint8_t *)&o->send_packet, sizeof(o->send_packet));
88  
89 // set sending
90 o->send_sending = 1;
91 }
92  
93 static void send_if_handler_done (BArpProbe *o)
94 {
95 DebugObject_Access(&o->d_obj);
96 ASSERT(o->send_sending)
97  
98 // set not sending
99 o->send_sending = 0;
100 }
101  
102 static void recv_if_handler_done (BArpProbe *o, int data_len)
103 {
104 DebugObject_Access(&o->d_obj);
105 ASSERT(data_len >= 0)
106 ASSERT(data_len <= sizeof(struct arp_packet))
107  
108 // receive next packet
109 PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet);
110  
111 if (data_len != sizeof(struct arp_packet)) {
112 BLog(BLOG_WARNING, "receive: wrong size");
113 return;
114 }
115  
116 struct arp_packet *arp = &o->recv_packet;
117  
118 if (ntoh16(arp->hardware_type) != ARP_HARDWARE_TYPE_ETHERNET) {
119 BLog(BLOG_WARNING, "receive: wrong hardware type");
120 return;
121 }
122  
123 if (ntoh16(arp->protocol_type) != ETHERTYPE_IPV4) {
124 BLog(BLOG_WARNING, "receive: wrong protocol type");
125 return;
126 }
127  
128 if (ntoh8(arp->hardware_size) != 6) {
129 BLog(BLOG_WARNING, "receive: wrong hardware size");
130 return;
131 }
132  
133 if (ntoh8(arp->protocol_size) != 4) {
134 BLog(BLOG_WARNING, "receive: wrong protocol size");
135 return;
136 }
137  
138 if (ntoh16(arp->opcode) != ARP_OPCODE_REPLY) {
139 return;
140 }
141  
142 if (arp->sender_ip != o->addr) {
143 return;
144 }
145  
146 int old_state = o->state;
147  
148 // set minus one missed
149 o->num_missed = -1;
150  
151 // set timer
152 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITSEND);
153  
154 // set state exist
155 o->state = STATE_EXIST;
156  
157 // report exist if needed
158 if (old_state == STATE_INITIAL || old_state == STATE_NOEXIST) {
159 o->handler(o->user, BARPPROBE_EVENT_EXIST);
160 return;
161 }
162 }
163  
164 static void timer_handler (BArpProbe *o)
165 {
166 DebugObject_Access(&o->d_obj);
167  
168 // send request
169 send_request(o);
170  
171 switch (o->state) {
172 case STATE_INITIAL: {
173 ASSERT(o->num_missed >= 0)
174 ASSERT(o->num_missed < BARPPROBE_INITIAL_NUM_ATTEMPTS)
175  
176 // increment missed
177 o->num_missed++;
178  
179 // all attempts failed?
180 if (o->num_missed == BARPPROBE_INITIAL_NUM_ATTEMPTS) {
181 // set timer
182 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
183  
184 // set state noexist
185 o->state = STATE_NOEXIST;
186  
187 // report noexist
188 o->handler(o->user, BARPPROBE_EVENT_NOEXIST);
189 return;
190 }
191  
192 // set timer
193 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV);
194 } break;
195  
196 case STATE_NOEXIST: {
197 // set timer
198 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
199 } break;
200  
201 case STATE_EXIST: {
202 ASSERT(o->num_missed >= -1)
203 ASSERT(o->num_missed < BARPPROBE_EXIST_NUM_NOREPLY)
204  
205 // increment missed
206 o->num_missed++;
207  
208 // all missed?
209 if (o->num_missed == BARPPROBE_EXIST_NUM_NOREPLY) {
210 // set timer
211 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV);
212  
213 // set zero missed
214 o->num_missed = 0;
215  
216 // set state panic
217 o->state = STATE_EXIST_PANIC;
218 return;
219 }
220  
221 // set timer
222 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_WAITRECV);
223 } break;
224  
225 case STATE_EXIST_PANIC: {
226 ASSERT(o->num_missed >= 0)
227 ASSERT(o->num_missed < BARPPROBE_EXIST_PANIC_NUM_NOREPLY)
228  
229 // increment missed
230 o->num_missed++;
231  
232 // all missed?
233 if (o->num_missed == BARPPROBE_EXIST_PANIC_NUM_NOREPLY) {
234 // set timer
235 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_NOEXIST_WAITRECV);
236  
237 // set state panic
238 o->state = STATE_NOEXIST;
239  
240 // report noexist
241 o->handler(o->user, BARPPROBE_EVENT_NOEXIST);
242 return;
243 }
244  
245 // set timer
246 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_EXIST_PANIC_WAITRECV);
247 } break;
248 }
249 }
250  
251 int BArpProbe_Init (BArpProbe *o, const char *ifname, uint32_t addr, BReactor *reactor, void *user, BArpProbe_handler handler)
252 {
253 ASSERT(ifname)
254 ASSERT(handler)
255  
256 // init arguments
257 o->addr = addr;
258 o->reactor = reactor;
259 o->user = user;
260 o->handler = handler;
261  
262 // get interface information
263 int if_mtu;
264 int if_index;
265 if (!badvpn_get_iface_info(ifname, o->if_mac, &if_mtu, &if_index)) {
266 BLog(BLOG_ERROR, "failed to get interface information");
267 goto fail0;
268 }
269  
270 uint8_t *if_mac = o->if_mac;
271 BLog(BLOG_INFO, "if_mac=%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8" if_mtu=%d if_index=%d",
272 if_mac[0], if_mac[1], if_mac[2], if_mac[3], if_mac[4], if_mac[5], if_mtu, if_index);
273  
274 // check MTU
275 if (if_mtu < sizeof(struct arp_packet)) {
276 BLog(BLOG_ERROR, "MTU is too small for ARP !?!");
277 goto fail0;
278 }
279  
280 // init dgram
281 if (!BDatagram_Init(&o->dgram, BADDR_TYPE_PACKET, o->reactor, o, (BDatagram_handler)dgram_handler)) {
282 BLog(BLOG_ERROR, "BDatagram_Init failed");
283 goto fail0;
284 }
285  
286 // bind dgram
287 BAddr bind_addr;
288 BAddr_InitPacket(&bind_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_HOST, if_mac);
289 if (!BDatagram_Bind(&o->dgram, bind_addr)) {
290 BLog(BLOG_ERROR, "BDatagram_Bind failed");
291 goto fail1;
292 }
293  
294 // set dgram send addresses
295 BAddr dest_addr;
296 uint8_t broadcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
297 BAddr_InitPacket(&dest_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_BROADCAST, broadcast_mac);
298 BIPAddr local_addr;
299 BIPAddr_InitInvalid(&local_addr);
300 BDatagram_SetSendAddrs(&o->dgram, dest_addr, local_addr);
301  
302 // init send interface
303 BDatagram_SendAsync_Init(&o->dgram, sizeof(struct arp_packet));
304 o->send_if = BDatagram_SendAsync_GetIf(&o->dgram);
305 PacketPassInterface_Sender_Init(o->send_if, (PacketPassInterface_handler_done)send_if_handler_done, o);
306  
307 // set not sending
308 o->send_sending = 0;
309  
310 // init recv interface
311 BDatagram_RecvAsync_Init(&o->dgram, sizeof(struct arp_packet));
312 o->recv_if = BDatagram_RecvAsync_GetIf(&o->dgram);
313 PacketRecvInterface_Receiver_Init(o->recv_if, (PacketRecvInterface_handler_done)recv_if_handler_done, o);
314  
315 // init timer
316 BTimer_Init(&o->timer, 0, (BTimer_handler)timer_handler, o);
317  
318 // receive first packet
319 PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet);
320  
321 // send request
322 send_request(o);
323  
324 // set timer
325 BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV);
326  
327 // set zero missed
328 o->num_missed = 0;
329  
330 // set state initial
331 o->state = STATE_INITIAL;
332  
333 DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
334 DebugObject_Init(&o->d_obj);
335 return 1;
336  
337 fail1:
338 BDatagram_Free(&o->dgram);
339 fail0:
340 return 0;
341 }
342  
343 void BArpProbe_Free (BArpProbe *o)
344 {
345 DebugObject_Free(&o->d_obj);
346 DebugError_Free(&o->d_err);
347  
348 // free timer
349 BReactor_RemoveTimer(o->reactor, &o->timer);
350  
351 // free recv interface
352 BDatagram_RecvAsync_Free(&o->dgram);
353  
354 // free send interface
355 BDatagram_SendAsync_Free(&o->dgram);
356  
357 // free dgram
358 BDatagram_Free(&o->dgram);
359 }