2 * Copyright (c) 2007, Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * This file is part of the Contiki operating system.
31 * Author: Oliver Schmidt <ol.sc@web.de>
33 * $Id: wpcap.c,v 1.4 2009/04/29 11:56:14 adamdunkels Exp $
38 #define WIN32_LEAN_AND_MEAN
39 #define _WIN32_WINNT 0x0501
49 #else /* __CYGWIN__ */
51 #endif /* __CYGWIN__ */
58 #include <sys/types.h>
65 #include <sys/ioctl.h>
69 /* Avoid 'conflicting types' errors. */
77 static void raw_send(void *buf
, int len
);
82 struct pcap_addr
*next
;
83 struct sockaddr
*addr
;
84 struct sockaddr
*netmask
;
85 struct sockaddr
*broadaddr
;
86 struct sockaddr
*dstaddr
;
93 struct pcap_addr
*addresses
;
103 void wpcap_send(void *buf
, int len
);
107 static struct pcap
*pcap
;
109 static int (* pcap_findalldevs
)(struct pcap_if
**, char *);
110 static struct pcap
*(* pcap_open_live
)(char *, int, int, int, char *);
111 static int (* pcap_next_ex
)(struct pcap
*, struct pcap_pkthdr
**, unsigned char **);
112 static int (* pcap_sendpacket
)(struct pcap
*, unsigned char *, int);
117 #define ARP_REQUEST 1
120 #define ARP_HWTYPE_ETH 1
123 #include "net/uip_arp.h"
126 struct uip_eth_hdr ethhdr
;
136 uip_ipaddr_t srcipaddr
, destipaddr
;
141 struct uip_eth_hdr ethhdr
;
147 struct uip_eth_addr shwaddr
;
148 uip_ipaddr_t sipaddr
;
149 struct uip_eth_addr dhwaddr
;
150 uip_ipaddr_t dipaddr
;
151 } __attribute__ ((packed
));
155 struct uip_eth_addr ethaddr
;
158 static struct uip_eth_addr uip_ethaddr
= {{0,0,0,0,0,0}};
159 static const uip_ipaddr_t all_zeroes_addr
= { { 0x0, /* rest is 0 */ } };
160 static const struct uip_eth_addr broadcast_ethaddr
=
161 {{0xff,0xff,0xff,0xff,0xff,0xff}};
162 static const uip_ipaddr_t broadcast_ipaddr
= {{255,255,255,255}};
164 static struct arp_entry arp_table
[UIP_ARPTAB_SIZE
];
166 static uip_ipaddr_t ifaddr
, netaddr
, netmask
;
173 log_message(char *msg1
, char *msg2
)
176 printf("Log: %s %s\n", msg1
, msg2
);
179 /*---------------------------------------------------------------------------*/
181 error_exit(char *msg1
)
183 printf("error_exit: %s", msg1
);
186 /*---------------------------------------------------------------------------*/
188 init_pcap(struct in_addr addr
)
190 struct pcap_if
*interfaces
;
191 struct pcap_addr
*paddr
;
194 if(pcap_findalldevs(&interfaces
, error
) == -1) {
198 while(interfaces
!= NULL
) {
199 log_message("init_pcap: found interface: ", interfaces
->description
);
201 if(interfaces
->addresses
!= NULL
) {
202 for(paddr
= interfaces
->addresses
;
204 paddr
= paddr
->next
) {
205 if(paddr
->addr
!= NULL
&& paddr
->addr
->sa_family
== AF_INET
) {
207 struct in_addr interface_addr
;
208 interface_addr
= ((struct sockaddr_in
*)paddr
->addr
)->sin_addr
;
209 log_message("init_pcap: with address: ", inet_ntoa(interface_addr
));
211 if(interface_addr
.s_addr
== addr
.s_addr
) {
212 pcap
= pcap_open_live(interfaces
->name
, BUFSIZE
, 0, -1, error
);
221 interfaces
= interfaces
->next
;
224 if(interfaces
== NULL
) {
225 error_exit("no interface found with ip addr specified on cmdline\n");
228 /*---------------------------------------------------------------------------*/
230 setethaddr(struct uip_eth_addr
*a
)
232 memcpy(&uip_ethaddr
, a
, sizeof(struct uip_eth_addr
));
234 /*---------------------------------------------------------------------------*/
236 set_ethaddr(struct in_addr addr
)
238 PIP_ADAPTER_ADDRESSES adapters
;
241 if(GetAdaptersAddresses(AF_INET
, GAA_FLAG_SKIP_ANYCAST
|
242 GAA_FLAG_SKIP_MULTICAST
|
243 GAA_FLAG_SKIP_DNS_SERVER
,
244 NULL
, NULL
, &size
) != ERROR_BUFFER_OVERFLOW
) {
245 error_exit("error on access to adapter list size\n");
247 adapters
= alloca(size
);
248 if(GetAdaptersAddresses(AF_INET
, GAA_FLAG_SKIP_ANYCAST
|
249 GAA_FLAG_SKIP_MULTICAST
|
250 GAA_FLAG_SKIP_DNS_SERVER
,
251 NULL
, adapters
, &size
) != ERROR_SUCCESS
) {
252 error_exit("error on access to adapter list\n");
255 while(adapters
!= NULL
) {
258 WideCharToMultiByte(CP_ACP
, 0, adapters
->Description
, -1,
259 buffer
, sizeof(buffer
), NULL
, NULL
);
260 log_message("set_ethaddr: found adapter: ", buffer
);
262 if(adapters
->FirstUnicastAddress
!= NULL
&&
263 adapters
->FirstUnicastAddress
->Address
.lpSockaddr
!= NULL
&&
264 adapters
->FirstUnicastAddress
->Address
.lpSockaddr
->sa_family
== AF_INET
) {
266 struct in_addr adapter_addr
;
267 adapter_addr
= ((struct sockaddr_in
*)adapters
->FirstUnicastAddress
->Address
.lpSockaddr
)->sin_addr
;
268 log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr
));
270 if(adapter_addr
.s_addr
== addr
.s_addr
) {
271 printf("Using local network interface with address %s\n",
272 inet_ntoa(adapter_addr
));
273 if(adapters
->PhysicalAddressLength
!= 6) {
274 error_exit("ip addr specified on cmdline does not belong to an ethernet card\n");
276 wsprintf(buffer
, "%02X-%02X-%02X-%02X-%02X-%02X",
277 adapters
->PhysicalAddress
[0], adapters
->PhysicalAddress
[1],
278 adapters
->PhysicalAddress
[2], adapters
->PhysicalAddress
[3],
279 adapters
->PhysicalAddress
[4], adapters
->PhysicalAddress
[5]);
280 log_message("set_ethaddr: ethernetaddr: ", buffer
);
282 setethaddr((struct uip_eth_addr
*)adapters
->PhysicalAddress
);
286 adapters
= adapters
->Next
;
289 if(adapters
== NULL
) {
290 error_exit("no adapter found with ip addr specified on cmdline\n");
293 /*---------------------------------------------------------------------------*/
295 print_packet(unsigned char *buf
, int len
)
299 for(i
= 0; i
< len
; ++i
) {
300 printf("0x%02x, ", buf
[i
]);
307 /*---------------------------------------------------------------------------*/
309 uip_arp_update(uip_ipaddr_t
*ipaddr
, struct uip_eth_addr
*ethaddr
)
311 struct arp_entry
*tabptr
;
314 /* Walk through the ARP mapping table and try to find an entry to
315 update. If none is found, the IP -> MAC address mapping is
316 inserted in the ARP table. */
317 for(i
= 0; i
< UIP_ARPTAB_SIZE
; ++i
) {
319 tabptr
= &arp_table
[i
];
320 /* Only check those entries that are actually in use. */
321 if(!uip_ipaddr_cmp(&tabptr
->ipaddr
, &all_zeroes_addr
)) {
323 /* Check if the source IP address of the incoming packet matches
324 the IP address in this ARP table entry. */
325 if(uip_ipaddr_cmp(ipaddr
, &tabptr
->ipaddr
)) {
327 /* An old entry found, update this and return. */
328 memcpy(tabptr
->ethaddr
.addr
, ethaddr
->addr
, 6);
329 tabptr
->time
= arptime
;
336 /* If we get here, no existing ARP table entry was found, so we
339 /* First, we try to find an unused entry in the ARP table. */
340 for(i
= 0; i
< UIP_ARPTAB_SIZE
; ++i
) {
341 tabptr
= &arp_table
[i
];
342 if(uip_ipaddr_cmp(&tabptr
->ipaddr
, &all_zeroes_addr
)) {
347 /* If no unused entry is found, we try to find the oldest entry and
349 if(i
== UIP_ARPTAB_SIZE
) {
352 for(i
= 0; i
< UIP_ARPTAB_SIZE
; ++i
) {
353 tabptr
= &arp_table
[i
];
354 if(arptime
- tabptr
->time
> tmpage
) {
355 tmpage
= arptime
- tabptr
->time
;
360 tabptr
= &arp_table
[i
];
363 /* Now, i is the ARP table entry which we will fill with the new
365 uip_ipaddr_copy(&tabptr
->ipaddr
, ipaddr
);
366 memcpy(tabptr
->ethaddr
.addr
, ethaddr
->addr
, 6);
367 tabptr
->time
= arptime
;
369 /*---------------------------------------------------------------------------*/
371 * Prepend Ethernet header to an outbound IP packet and see if we need
372 * to send out an ARP request.
374 * This function should be called before sending out an IP packet. The
375 * function checks the destination IP address of the IP packet to see
376 * what Ethernet MAC address that should be used as a destination MAC
377 * address on the Ethernet.
379 * If the destination IP address is in the local network (determined
380 * by logical ANDing of netmask and our IP address), the function
381 * checks the ARP cache to see if an entry for the destination IP
382 * address is found. If so, an Ethernet header is prepended and the
383 * function returns. If no ARP cache entry is found for the
384 * destination IP address, the packet in the uip_buf[] is replaced by
385 * an ARP request packet for the IP address. The IP packet is dropped
386 * and it is assumed that they higher level protocols (e.g., TCP)
387 * eventually will retransmit the dropped packet.
389 * If the destination IP address is not on the local network, the IP
390 * address of the default router is used instead.
392 * When the function returns, a packet is present in the uip_buf[]
393 * buffer, and the length of the packet is in the global variable
396 /*---------------------------------------------------------------------------*/
398 arp_out(struct ethip_hdr
*iphdr
, int len
)
401 struct arp_entry
*tabptr
;
402 struct arp_hdr
*arphdr
= (struct arp_hdr
*)iphdr
;
408 /* Find the destination IP address in the ARP table and construct
409 the Ethernet header. If the destination IP addres isn't on the
410 local network, we use the default router's IP address instead.
412 If not ARP table entry is found, we overwrite the original IP
413 packet with an ARP request for the IP address. */
415 /* First check if destination is a local broadcast. */
416 if(uip_ipaddr_cmp(&iphdr
->destipaddr
, &broadcast_ipaddr
)) {
417 memcpy(iphdr
->ethhdr
.dest
.addr
, broadcast_ethaddr
.addr
, 6);
419 /* Check if the destination address is on the local network. */
421 if(!uip_ipaddr_maskcmp(&iphdr
->destipaddr
, &netaddr
, &netmask
)) {
422 /* Destination address was not on the local network, so we need to
423 use the default router's IP address instead of the destination
424 address when determining the MAC address. */
425 uip_ipaddr_copy(&ipaddr
, &ifaddr
);
430 /* Else, we use the destination IP address. */
431 uip_ipaddr_copy(&ipaddr
, &iphdr
->destipaddr
);
434 for(i
= 0; i
< UIP_ARPTAB_SIZE
; ++i
) {
435 tabptr
= &arp_table
[i
];
436 if(uip_ipaddr_cmp(&ipaddr
, &tabptr
->ipaddr
)) {
441 if(i
== UIP_ARPTAB_SIZE
) {
442 /* The destination address was not in our ARP table, so we
443 overwrite the IP packet with an ARP request. */
445 memset(arphdr
->ethhdr
.dest
.addr
, 0xff, 6);
446 memset(arphdr
->dhwaddr
.addr
, 0x00, 6);
447 memcpy(arphdr
->ethhdr
.src
.addr
, uip_ethaddr
.addr
, 6);
448 memcpy(arphdr
->shwaddr
.addr
, uip_ethaddr
.addr
, 6);
450 uip_ipaddr_copy(&arphdr
->dipaddr
, &ipaddr
);
451 uip_ipaddr_copy(&arphdr
->sipaddr
, &netaddr
);
452 arphdr
->opcode
= HTONS(ARP_REQUEST
); /* ARP request. */
453 arphdr
->hwtype
= HTONS(ARP_HWTYPE_ETH
);
454 arphdr
->protocol
= HTONS(UIP_ETHTYPE_IP
);
456 arphdr
->protolen
= 4;
457 arphdr
->ethhdr
.type
= HTONS(UIP_ETHTYPE_ARP
);
459 /* uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];*/
461 return sizeof(struct arp_hdr
);
464 /* Build an ethernet header. */
465 memcpy(iphdr
->ethhdr
.dest
.addr
, tabptr
->ethaddr
.addr
, 6);
468 memcpy(iphdr
->ethhdr
.src
.addr
, uip_ethaddr
.addr
, 6);
470 iphdr
->ethhdr
.type
= HTONS(UIP_ETHTYPE_IP
);
472 return len
+ sizeof(struct uip_eth_hdr
);
474 /*---------------------------------------------------------------------------*/
476 do_arp(void *buf
, int len
)
480 hdr
= (struct arp_hdr
*)buf
;
481 if(hdr
->ethhdr
.type
== HTONS(UIP_ETHTYPE_ARP
)) {
482 if(hdr
->opcode
== HTONS(ARP_REQUEST
)) {
483 /* Check if the ARP is for our network */
484 /* printf("ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n",
485 uip_ipaddr_to_quad(&hdr->dipaddr),
486 uip_ipaddr_to_quad(&netaddr),
487 uip_ipaddr_to_quad(&netmask));*/
488 if(uip_ipaddr_maskcmp(&hdr
->dipaddr
, &netaddr
, &netmask
)) {
489 uip_ipaddr_t tmpaddr
;
491 /* printf("ARP for us.\n");*/
492 uip_arp_update(&hdr
->sipaddr
, &hdr
->shwaddr
);
494 hdr
->opcode
= HTONS(ARP_REPLY
);
496 memcpy(&hdr
->dhwaddr
.addr
, &hdr
->shwaddr
.addr
, 6);
497 memcpy(&hdr
->shwaddr
.addr
, &uip_ethaddr
.addr
, 6);
498 memcpy(&hdr
->ethhdr
.src
.addr
, &uip_ethaddr
.addr
, 6);
499 memcpy(&hdr
->ethhdr
.dest
.addr
, &hdr
->dhwaddr
.addr
, 6);
501 uip_ipaddr_copy(&tmpaddr
, &hdr
->dipaddr
);
502 uip_ipaddr_copy(&hdr
->dipaddr
, &hdr
->sipaddr
);
503 uip_ipaddr_copy(&hdr
->sipaddr
, &tmpaddr
);
505 hdr
->ethhdr
.type
= HTONS(UIP_ETHTYPE_ARP
);
506 raw_send(hdr
, sizeof(struct arp_hdr
));
509 } else if(hdr
->opcode
== HTONS(ARP_REPLY
)) {
510 /* ARP reply. We insert or update the ARP table if it was meant
512 if(uip_ipaddr_maskcmp(&hdr
->dipaddr
, &netaddr
, &netmask
)) {
513 uip_arp_update(&hdr
->sipaddr
, &hdr
->shwaddr
);
517 if(hdr
->ethhdr
.type
== HTONS(UIP_ETHTYPE_IP
)) {
518 return &((struct ethip_hdr
*)hdr
)->vhl
;
522 /*---------------------------------------------------------------------------*/
528 snprintf(buf
, sizeof(buf
), "route delete %d.%d.%d.%d",
529 uip_ipaddr_to_quad(&ifaddr
));
534 /*---------------------------------------------------------------------------*/
541 /*---------------------------------------------------------------------------*/
543 wpcap_start(char *ethcardaddr
, char *slipnetaddr
, char *slipnetmask
, int log
)
551 addr
.s_addr
= inet_addr(ethcardaddr
);
552 tmpaddr
= inet_addr(ethcardaddr
);
553 memcpy(&ifaddr
.u16
[0], &tmpaddr
, sizeof(tmpaddr
));
554 tmpaddr
= inet_addr(slipnetaddr
);
555 memcpy(&netaddr
.u16
[0], &tmpaddr
, sizeof(tmpaddr
));
556 tmpaddr
= inet_addr(slipnetmask
);
557 memcpy(&netmask
.u16
[0], &tmpaddr
, sizeof(tmpaddr
));
559 printf("Network address %d.%d.%d.%d/%d.%d.%d.%d\n",
560 uip_ipaddr_to_quad(&netaddr
),
561 uip_ipaddr_to_quad(&netmask
));
563 snprintf(buf
, sizeof(buf
), "route add %d.%d.%d.%d mask %d.%d.%d.%d %d.%d.%d.%d",
564 uip_ipaddr_to_quad(&netaddr
),
565 uip_ipaddr_to_quad(&netmask
),
566 uip_ipaddr_to_quad(&ifaddr
));
569 signal(SIGTERM
, remove_route
);
571 log_message("wpcap_init: cmdline address: ", inet_ntoa(addr
));
574 wpcap
= LoadLibrary("wpcap.dll");
575 pcap_findalldevs
= (int (*)(struct pcap_if
**, char *))
576 GetProcAddress(wpcap
, "pcap_findalldevs");
577 pcap_open_live
= (struct pcap
*(*)(char *, int, int, int, char *))
578 GetProcAddress(wpcap
, "pcap_open_live");
579 pcap_next_ex
= (int (*)(struct pcap
*, struct pcap_pkthdr
**, unsigned char **))
580 GetProcAddress(wpcap
, "pcap_next_ex");
581 pcap_sendpacket
= (int (*)(struct pcap
*, unsigned char *, int))
582 GetProcAddress(wpcap
, "pcap_sendpacket");
584 if(pcap_findalldevs
== NULL
|| pcap_open_live
== NULL
||
585 pcap_next_ex
== NULL
|| pcap_sendpacket
== NULL
) {
586 error_exit("error on access to winpcap library\n");
597 ret
= wpcap_poll(buf
);
599 /* print_packet(buf, ret);*/
600 if(do_arp(buf
, ret
)) {
601 printf("IP packet\n");
608 /*---------------------------------------------------------------------------*/
610 wpcap_poll(char **buf
)
612 struct pcap_pkthdr
*packet_header
;
613 unsigned char *packet
;
617 switch(pcap_next_ex(pcap
, &packet_header
, &packet
)) {
619 error_exit("error on poll\n");
624 if(packet_header
->caplen
> BUFSIZE
) {
628 CopyMemory(*buf
, packet
, packet_header
->caplen
);
629 len
= packet_header
->caplen
;
630 /* printf("len %d\n", len);*/
631 buf2
= do_arp(*buf
, len
);
635 len
= len
- (buf2
- *buf
);
640 /*---------------------------------------------------------------------------*/
642 wpcap_send(void *buf
, int len
)
646 memcpy(&buf2
[sizeof(struct uip_eth_hdr
)], buf
, len
);
647 len
= arp_out((struct ethip_hdr
*)buf2
, len
);
651 /*---------------------------------------------------------------------------*/
653 raw_send(void *buf
, int len
)
655 /* printf("sending len %d\n", len);*/
656 if(pcap_sendpacket(pcap
, buf
, len
) == -1) {
657 print_packet(buf
, len
);
658 error_exit("error on send\n");
661 /*---------------------------------------------------------------------------*/
667 /*---------------------------------------------------------------------------*/