Adjusted Contiki download page content to the fact that there are now two disk images...
[contiki-2.x.git] / tools / wpcapslip / wpcap.c
blob28fa2468f85317aa0670a60a0930a8b9a19e8f4a
1 /*
2 * Copyright (c) 2007, Swedish Institute of Computer Science.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
27 * SUCH DAMAGE.
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
40 #include <windows.h>
41 #include <winsock2.h>
42 #include <iphlpapi.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #ifdef __CYGWIN__
48 #include <alloca.h>
49 #else /* __CYGWIN__ */
50 #include <malloc.h>
51 #endif /* __CYGWIN__ */
52 #include <signal.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <stdarg.h>
56 #include <string.h>
57 #include <time.h>
58 #include <sys/types.h>
60 #include <unistd.h>
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <signal.h>
64 #include <termios.h>
65 #include <sys/ioctl.h>
67 #include <err.h>
69 /* Avoid 'conflicting types' errors. */
70 #define htonl
71 #define htons
74 #define PROGRESS(x)
77 static void raw_send(void *buf, int len);
79 struct pcap;
81 struct pcap_addr {
82 struct pcap_addr *next;
83 struct sockaddr *addr;
84 struct sockaddr *netmask;
85 struct sockaddr *broadaddr;
86 struct sockaddr *dstaddr;
89 struct pcap_if {
90 struct pcap_if *next;
91 char *name;
92 char *description;
93 struct pcap_addr *addresses;
94 DWORD flags;
97 struct pcap_pkthdr {
98 struct timeval ts;
99 DWORD caplen;
100 DWORD len;
103 void wpcap_send(void *buf, int len);
105 HMODULE wpcap;
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);
115 #define BUFSIZE 1514
117 #define ARP_REQUEST 1
118 #define ARP_REPLY 2
120 #define ARP_HWTYPE_ETH 1
122 #include "net/uip.h"
123 #include "net/uip_arp.h"
125 struct ethip_hdr {
126 struct uip_eth_hdr ethhdr;
127 /* IP header. */
128 u8_t vhl,
129 tos,
130 len[2],
131 ipid[2],
132 ipoffset[2],
133 ttl,
134 proto;
135 u16_t ipchksum;
136 uip_ipaddr_t srcipaddr, destipaddr;
140 struct arp_hdr {
141 struct uip_eth_hdr ethhdr;
142 uint16_t hwtype;
143 uint16_t protocol;
144 uint8_t hwlen;
145 uint8_t protolen;
146 uint16_t opcode;
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));
153 struct arp_entry {
154 uip_ipaddr_t ipaddr;
155 struct uip_eth_addr ethaddr;
156 u8_t time;
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;
168 static int arptime;
170 static int logging;
172 static void
173 log_message(char *msg1, char *msg2)
175 if(logging) {
176 printf("Log: %s %s\n", msg1, msg2);
179 /*---------------------------------------------------------------------------*/
180 static void
181 error_exit(char *msg1)
183 printf("error_exit: %s", msg1);
184 exit(EXIT_FAILURE);
186 /*---------------------------------------------------------------------------*/
187 static void
188 init_pcap(struct in_addr addr)
190 struct pcap_if *interfaces;
191 struct pcap_addr *paddr;
192 char error[256];
194 if(pcap_findalldevs(&interfaces, error) == -1) {
195 error_exit(error);
198 while(interfaces != NULL) {
199 log_message("init_pcap: found interface: ", interfaces->description);
201 if(interfaces->addresses != NULL) {
202 for(paddr = interfaces->addresses;
203 paddr != NULL;
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);
213 if(pcap == NULL) {
214 error_exit(error);
216 return;
221 interfaces = interfaces->next;
224 if(interfaces == NULL) {
225 error_exit("no interface found with ip addr specified on cmdline\n");
228 /*---------------------------------------------------------------------------*/
229 static void
230 setethaddr(struct uip_eth_addr *a)
232 memcpy(&uip_ethaddr, a, sizeof(struct uip_eth_addr));
234 /*---------------------------------------------------------------------------*/
235 static void
236 set_ethaddr(struct in_addr addr)
238 PIP_ADAPTER_ADDRESSES adapters;
239 ULONG size = 0;
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) {
257 char buffer[256];
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);
283 break;
286 adapters = adapters->Next;
289 if(adapters == NULL) {
290 error_exit("no adapter found with ip addr specified on cmdline\n");
293 /*---------------------------------------------------------------------------*/
294 static void
295 print_packet(unsigned char *buf, int len)
297 int i;
299 for(i = 0; i < len; ++i) {
300 printf("0x%02x, ", buf[i]);
301 if(i % 8 == 7) {
302 printf("\n");
305 printf("\n\n");
307 /*---------------------------------------------------------------------------*/
308 static void
309 uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
311 struct arp_entry *tabptr;
312 int i, tmpage, c;
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;
331 return;
336 /* If we get here, no existing ARP table entry was found, so we
337 create one. */
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)) {
343 break;
347 /* If no unused entry is found, we try to find the oldest entry and
348 throw it away. */
349 if(i == UIP_ARPTAB_SIZE) {
350 tmpage = 0;
351 c = 0;
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;
356 c = i;
359 i = c;
360 tabptr = &arp_table[i];
363 /* Now, i is the ARP table entry which we will fill with the new
364 information. */
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
394 * uip_len.
396 /*---------------------------------------------------------------------------*/
397 static int
398 arp_out(struct ethip_hdr *iphdr, int len)
400 #if 1
401 struct arp_entry *tabptr;
402 struct arp_hdr *arphdr = (struct arp_hdr *)iphdr;
403 uip_ipaddr_t ipaddr;
404 int i;
405 #endif
407 #if 1
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);
418 } else {
419 /* Check if the destination address is on the local network. */
420 #if 1
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);
426 } else {
427 #else
429 #endif
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)) {
437 break;
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);
455 arphdr->hwlen = 6;
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);
467 #endif /* 0 */
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 /*---------------------------------------------------------------------------*/
475 void *
476 do_arp(void *buf, int len)
478 struct arp_hdr *hdr;
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));
507 return NULL;
509 } else if(hdr->opcode == HTONS(ARP_REPLY)) {
510 /* ARP reply. We insert or update the ARP table if it was meant
511 for us. */
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;
520 return NULL;
522 /*---------------------------------------------------------------------------*/
523 void
524 cleanup(void)
526 char buf[1024];
528 snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d",
529 uip_ipaddr_to_quad(&ifaddr));
530 printf("%s\n", buf);
531 system(buf);
534 /*---------------------------------------------------------------------------*/
535 static void
536 remove_route(int s)
538 cleanup();
539 _exit(0);
541 /*---------------------------------------------------------------------------*/
542 void
543 wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
545 struct in_addr addr;
546 char buf[4000];
547 uint32_t tmpaddr;
549 logging = 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));
567 printf("%s\n", buf);
568 system(buf);
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");
589 init_pcap(addr);
590 set_ethaddr(addr);
592 return;
593 #if 0
594 while(1) {
595 int ret;
597 ret = wpcap_poll(buf);
598 if(ret > 0) {
599 /* print_packet(buf, ret);*/
600 if(do_arp(buf, ret)) {
601 printf("IP packet\n");
604 sleep(1);
606 #endif
608 /*---------------------------------------------------------------------------*/
609 uint16_t
610 wpcap_poll(char **buf)
612 struct pcap_pkthdr *packet_header;
613 unsigned char *packet;
614 int len;
615 char *buf2;
617 switch(pcap_next_ex(pcap, &packet_header, &packet)) {
618 case -1:
619 error_exit("error on poll\n");
620 case 0:
621 return 0;
624 if(packet_header->caplen > BUFSIZE) {
625 return 0;
628 CopyMemory(*buf, packet, packet_header->caplen);
629 len = packet_header->caplen;
630 /* printf("len %d\n", len);*/
631 buf2 = do_arp(*buf, len);
632 if(buf2 == NULL) {
633 return 0;
634 } else {
635 len = len - (buf2 - *buf);
636 *buf = buf2;
637 return len;
640 /*---------------------------------------------------------------------------*/
641 void
642 wpcap_send(void *buf, int len)
644 char buf2[4000];
646 memcpy(&buf2[sizeof(struct uip_eth_hdr)], buf, len);
647 len = arp_out((struct ethip_hdr *)buf2, len);
649 raw_send(buf2, len);
651 /*---------------------------------------------------------------------------*/
652 static void
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 /*---------------------------------------------------------------------------*/
662 void
663 wpcap_exit(void)
665 FreeLibrary(wpcap);
667 /*---------------------------------------------------------------------------*/