oliverschmidt | b025e43 | 2007-09-05 16:11:04 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2007, Swedish Institute of Computer Science. |
| 3 | * All rights reserved. |
| 4 | * |
| 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 | * |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * 3. Neither the name of the Institute nor the names of its contributors |
| 17 | * may be used to endorse or promote products derived from this software |
| 18 | * without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
| 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
| 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 30 | * SUCH DAMAGE. |
| 31 | * |
| 32 | * This file is part of the uIP TCP/IP stack. |
| 33 | * |
| 34 | * Author: Oliver Schmidt <ol.sc@web.de> |
| 35 | * |
| 36 | * $Id: wpcap.c,v 1.1 2007/09/05 16:11:08 oliverschmidt Exp $ |
| 37 | */ |
| 38 | |
| 39 | #define WIN32_LEAN_AND_MEAN |
| 40 | #define _WIN32_WINNT 0x0501 |
| 41 | #include <windows.h> |
| 42 | #include <winsock2.h> |
| 43 | #include <iphlpapi.h> |
| 44 | |
| 45 | #include <stdio.h> |
| 46 | #include <stdlib.h> |
| 47 | #include <malloc.h> |
| 48 | |
| 49 | #define htonl contiki_htonl /* htonl is defined in winsock2 */ |
| 50 | #define htons contiki_htons /* htons is defined in winsock2 */ |
| 51 | |
| 52 | #include "uip.h" |
| 53 | #include "uip_arp.h" |
| 54 | #include "ctk.h" |
| 55 | #include "wpcap.h" |
| 56 | |
| 57 | struct pcap; |
| 58 | |
| 59 | struct pcap_if { |
| 60 | struct pcap_if *next; |
| 61 | char *name; |
| 62 | char *description; |
| 63 | struct pcap_addr { |
| 64 | struct pcap_addr *next; |
| 65 | struct sockaddr *addr; |
| 66 | struct sockaddr *netmask; |
| 67 | struct sockaddr *broadaddr; |
| 68 | struct sockaddr *dstaddr; |
| 69 | } *addresses; |
| 70 | DWORD flags; |
| 71 | }; |
| 72 | |
| 73 | struct pcap_pkthdr { |
| 74 | struct timeval ts; |
| 75 | DWORD caplen; |
| 76 | DWORD len; |
| 77 | }; |
| 78 | |
| 79 | HMODULE wpcap; |
| 80 | |
| 81 | static struct pcap *pcap; |
| 82 | |
| 83 | static int (* pcap_findalldevs)(struct pcap_if **, char *); |
| 84 | static struct pcap *(* pcap_open_live)(char *, int, int, int, char *); |
| 85 | static int (* pcap_next_ex)(struct pcap *, struct pcap_pkthdr **, unsigned char **); |
| 86 | static int (* pcap_sendpacket)(struct pcap *, unsigned char *, int); |
| 87 | |
| 88 | #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) |
| 89 | |
| 90 | extern void debug_printf(char *format, ...); |
| 91 | |
| 92 | /*---------------------------------------------------------------------------*/ |
| 93 | static void |
| 94 | error_exit(char *message) |
| 95 | { |
| 96 | console_exit(); |
| 97 | cprintf(message); |
| 98 | exit(EXIT_FAILURE); |
| 99 | } |
| 100 | /*---------------------------------------------------------------------------*/ |
| 101 | static void |
| 102 | init_pcap(struct in_addr addr) |
| 103 | { |
| 104 | struct pcap_if *interfaces; |
| 105 | char error[256]; |
| 106 | |
| 107 | if(pcap_findalldevs(&interfaces, error) == -1) { |
| 108 | error_exit(error); |
| 109 | } |
| 110 | |
| 111 | while(interfaces != NULL) { |
| 112 | debug_printf("init_pcap: found interface: %s\n", interfaces->description); |
| 113 | |
| 114 | if(interfaces->addresses != NULL && |
| 115 | interfaces->addresses->addr != NULL && |
| 116 | interfaces->addresses->addr->sa_family == AF_INET) { |
| 117 | |
| 118 | struct in_addr interface_addr; |
| 119 | interface_addr = ((struct sockaddr_in *)interfaces->addresses->addr)->sin_addr; |
| 120 | debug_printf("init_pcap: with address: %s\n", inet_ntoa(interface_addr)); |
| 121 | |
| 122 | if(interface_addr.s_addr == addr.s_addr) { |
| 123 | break; |
| 124 | } |
| 125 | } |
| 126 | interfaces = interfaces->next; |
| 127 | } |
| 128 | |
| 129 | if(interfaces == NULL) { |
| 130 | error_exit("no interface found with ip addr specified on cmdline\n"); |
| 131 | } |
| 132 | |
| 133 | pcap = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); |
| 134 | if(pcap == NULL) { |
| 135 | error_exit(error); |
| 136 | } |
| 137 | } |
| 138 | /*---------------------------------------------------------------------------*/ |
| 139 | static void |
| 140 | set_ethaddr(struct in_addr addr) |
| 141 | { |
| 142 | PIP_ADAPTER_ADDRESSES adapters; |
| 143 | ULONG size = 0; |
| 144 | |
| 145 | if(GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST | |
| 146 | GAA_FLAG_SKIP_MULTICAST | |
| 147 | GAA_FLAG_SKIP_DNS_SERVER, |
| 148 | NULL, NULL, &size) != ERROR_BUFFER_OVERFLOW) { |
| 149 | error_exit("error on access to adapter list size\n"); |
| 150 | } |
| 151 | adapters = alloca(size); |
| 152 | if(GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST | |
| 153 | GAA_FLAG_SKIP_MULTICAST | |
| 154 | GAA_FLAG_SKIP_DNS_SERVER, |
| 155 | NULL, adapters, &size) != ERROR_SUCCESS) { |
| 156 | error_exit("error on access to adapter list\n"); |
| 157 | } |
| 158 | |
| 159 | while(adapters != NULL) { |
| 160 | |
| 161 | char buffer[256]; |
| 162 | WideCharToMultiByte(CP_ACP, 0, adapters->Description, -1, |
| 163 | buffer, sizeof(buffer), NULL, NULL); |
| 164 | debug_printf("set_ethaddr: found adapter: %s\n", buffer); |
| 165 | |
| 166 | if(adapters->FirstUnicastAddress != NULL && |
| 167 | adapters->FirstUnicastAddress->Address.lpSockaddr != NULL && |
| 168 | adapters->FirstUnicastAddress->Address.lpSockaddr->sa_family == AF_INET) { |
| 169 | |
| 170 | struct in_addr adapter_addr; |
| 171 | adapter_addr = ((struct sockaddr_in *)adapters->FirstUnicastAddress->Address.lpSockaddr)->sin_addr; |
| 172 | debug_printf("set_ethaddr: with address: %s\n", inet_ntoa(adapter_addr)); |
| 173 | |
| 174 | if(adapter_addr.s_addr == addr.s_addr) { |
| 175 | if(adapters->PhysicalAddressLength != 6) { |
| 176 | error_exit("ip addr specified on cmdline does not belong to an ethernet card\n"); |
| 177 | } |
| 178 | debug_printf("set_ethaddr: ethernetaddr: %02X-%02X-%02X-%02X-%02X-%02X\n", |
| 179 | adapters->PhysicalAddress[0], adapters->PhysicalAddress[1], |
| 180 | adapters->PhysicalAddress[2], adapters->PhysicalAddress[3], |
| 181 | adapters->PhysicalAddress[4], adapters->PhysicalAddress[5]); |
| 182 | |
| 183 | uip_setethaddr((*(struct uip_eth_addr *)adapters->PhysicalAddress)); |
| 184 | break; |
| 185 | } |
| 186 | } |
| 187 | adapters = adapters->Next; |
| 188 | } |
| 189 | |
| 190 | if(adapters == NULL) { |
| 191 | error_exit("no adapter found with ip addr specified on cmdline\n"); |
| 192 | } |
| 193 | } |
| 194 | /*---------------------------------------------------------------------------*/ |
| 195 | void |
| 196 | wpcap_init(void) |
| 197 | { |
| 198 | struct in_addr addr; |
| 199 | |
| 200 | addr.s_addr = inet_addr(__argv[1]); |
| 201 | if(addr.s_addr == INADDR_NONE) { |
| 202 | error_exit("usage: <program> <ip addr of ethernet card to share>\n"); |
| 203 | } |
| 204 | debug_printf("wpcap_init: cmdline address: %s\n", inet_ntoa(addr)); |
| 205 | |
| 206 | wpcap = LoadLibrary("wpcap.dll"); |
| 207 | (FARPROC)pcap_findalldevs = GetProcAddress(wpcap, "pcap_findalldevs"); |
| 208 | (FARPROC)pcap_open_live = GetProcAddress(wpcap, "pcap_open_live"); |
| 209 | (FARPROC)pcap_next_ex = GetProcAddress(wpcap, "pcap_next_ex"); |
| 210 | (FARPROC)pcap_sendpacket = GetProcAddress(wpcap, "pcap_sendpacket"); |
| 211 | |
| 212 | if(pcap_findalldevs == NULL || pcap_open_live == NULL || |
| 213 | pcap_next_ex == NULL || pcap_sendpacket == NULL) { |
| 214 | error_exit("error on access to winpcap library\n"); |
| 215 | } |
| 216 | |
| 217 | init_pcap(addr); |
| 218 | set_ethaddr(addr); |
| 219 | } |
| 220 | /*---------------------------------------------------------------------------*/ |
| 221 | u16_t |
| 222 | wpcap_poll(void) |
| 223 | { |
| 224 | struct pcap_pkthdr *packet_header; |
| 225 | unsigned char *packet; |
| 226 | |
| 227 | if(pcap == NULL) { |
| 228 | return 0; |
| 229 | } |
| 230 | |
| 231 | switch(pcap_next_ex(pcap, &packet_header, &packet)) { |
| 232 | case -1: |
| 233 | error_exit("error on read\n"); |
| 234 | case 0: |
| 235 | return 0; |
| 236 | } |
| 237 | |
| 238 | if(packet_header->caplen > UIP_BUFSIZE) { |
| 239 | return 0; |
| 240 | } |
| 241 | |
| 242 | CopyMemory(uip_buf, packet, packet_header->caplen); |
| 243 | return (u16_t)packet_header->caplen; |
| 244 | } |
| 245 | /*---------------------------------------------------------------------------*/ |
| 246 | void |
| 247 | wpcap_send(void) |
| 248 | { |
| 249 | if(pcap_sendpacket(pcap, uip_buf, uip_len) == -1) { |
| 250 | error_exit("error on send\n"); |
| 251 | } |
| 252 | } |
| 253 | /*---------------------------------------------------------------------------*/ |
| 254 | void |
| 255 | wpcap_exit(void) |
| 256 | { |
| 257 | FreeLibrary(wpcap); |
| 258 | pcap = NULL; |
| 259 | } |
| 260 | /*---------------------------------------------------------------------------*/ |