blob: f36657fe6bee5a8d4f6012e1e842dc2553e98380 [file] [log] [blame]
oliverschmidtde98fae2004-07-31 14:47:56 +00001#define WIN32_LEAN_AND_MEAN
2#include <winsock2.h>
3#include <ws2tcpip.h>
4#include <stdlib.h>
oliverschmidt7f0b22b2005-01-29 23:10:43 +00005#include <malloc.h>
oliverschmidtde98fae2004-07-31 14:47:56 +00006
7/* from mstcpip.h */
oliverschmidt7f0b22b2005-01-29 23:10:43 +00008
oliverschmidtde98fae2004-07-31 14:47:56 +00009#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
10
oliverschmidt7f0b22b2005-01-29 23:10:43 +000011/* from iphlpapi.h */
12
13#pragma pack(push, 4)
14
ryohji09e3a0d2007-05-06 13:01:52 +000015typedef struct mib_ipaddrrow_t {
16 DWORD dwAddr;
17 DWORD dwIndex;
18 DWORD dwMask;
19 DWORD dwBCastAddr;
20 DWORD dwReasmSize;
21 DWORD unused;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000022} MIB_IPADDRROW;
23
ryohji09e3a0d2007-05-06 13:01:52 +000024typedef struct mib_ipaddrtable_t {
oliverschmidted66a1d2005-02-15 21:18:33 +000025 DWORD dwNumEntries;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000026 MIB_IPADDRROW table[0];
27} MIB_IPADDRTABLE;
28
oliverschmidt7f0b22b2005-01-29 23:10:43 +000029#pragma pack(pop)
30
ryohji55cd87a2007-05-02 04:06:56 +000031#define htons contiki_htons /* htons is defined in winsock2 */
oliverschmidtde98fae2004-07-31 14:47:56 +000032#include "uip.h"
ryohji55cd87a2007-05-02 04:06:56 +000033#undef htons
oliverschmidtde98fae2004-07-31 14:47:56 +000034#include "tcpip.h"
35#include "ctk.h"
ryohji55cd87a2007-05-02 04:06:56 +000036
oliverschmidtde98fae2004-07-31 14:47:56 +000037#define BUF ((uip_tcpip_hdr *)uip_buf)
38
ryohji09e3a0d2007-05-06 13:01:52 +000039typedef DWORD (WINAPI *ARPFUNC)(DWORD, DWORD, DWORD);
40
41extern void debug_printf(char *format, ...);
42
43static void error_exit(const char *message, int value);
44static void create_proxyarp(void);
45static void delete_proxyarp(void);
oliverschmidt7f0b22b2005-01-29 23:10:43 +000046
oliverschmidte7851ab2005-01-30 20:25:28 +000047static DWORD interfaceindex;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000048static DWORD proxyaddr;
oliverschmidtde98fae2004-07-31 14:47:56 +000049static SOCKET rawsock = INVALID_SOCKET;
50
ryohji55cd87a2007-05-02 04:06:56 +000051
ryohji09e3a0d2007-05-06 13:01:52 +000052#define END_OF(ARRAY) (ARRAY + sizeof(ARRAY)/sizeof(ARRAY[0]))
53#define HOSTADDR() (*(DWORD*)uip_hostaddr)
54#define NETMASK() (*(DWORD*)uip_netmask)
55
56#define DELAY_LOAD(NAME,MODULE) \
57( GetProcAddress(GetModuleHandle(MODULE), NAME) \
58 ? GetProcAddress(GetModuleHandle(MODULE), NAME) \
59 : (error_exit("GetProcAddress("#NAME") error: %d\n", GetLastError()), 0))
60
61#define SOCKCTL_(ON,CMD) \
62{ unsigned long on = ON; if (SOCKET_ERROR == \
63 ioctlsocket(rawsock, CMD, &on)) \
64 error_exit("ioctlsocket("#CMD") error: %d\n", WSAGetLastError()); }
65
66#define SOCKOPT_ON_(OPT,LAYER) \
67{ unsigned long on = 1; if (SOCKET_ERROR == \
68 setsockopt(rawsock, LAYER, OPT, (char*)&on, sizeof(on))) \
69 error_exit("setsockopt("#OPT") error: %d\n", WSAGetLastError()); }
70
71#define TRAP(ERR,HEAD,TAIL) \
72( match(ERR,HEAD,TAIL) ? ERR : (error_exit("send/recv() error: %d\n",ERR),0) )
73
ryohji55cd87a2007-05-02 04:06:56 +000074/*-----------------------------------------------------------------------------------*/
75static int match(const int x, const int *head, const int *const tail)
76{
ryohji09e3a0d2007-05-06 13:01:52 +000077 for( ;tail != head; ++head) if(*head == x) return 1;
ryohji55cd87a2007-05-02 04:06:56 +000078 return 0;
79}
oliverschmidtde98fae2004-07-31 14:47:56 +000080/*-----------------------------------------------------------------------------------*/
81static void
ryohji09e3a0d2007-05-06 13:01:52 +000082error_exit(const char *message, int value)
oliverschmidtde98fae2004-07-31 14:47:56 +000083{
84 console_exit();
85 cprintf(message, value);
86 exit(EXIT_FAILURE);
ryohji09e3a0d2007-05-06 13:01:52 +000087}
88/*-----------------------------------------------------------------------------------*/
89static DWORD
90get_interface_index_for_(DWORD ip)
91{
92 DWORD (WINAPI *Table)(MIB_IPADDRTABLE *, DWORD *, BOOL);
93 DWORD retval;
94 DWORD size = sizeof(MIB_IPADDRROW);
95 MIB_IPADDRTABLE *d = 0;
96 MIB_IPADDRROW *r;
97
98 (FARPROC)Table = DELAY_LOAD("GetIpAddrTable","iphlpapi");
99 do { d = realloc(d, size *= 2); }
100 while(ERROR_INSUFFICIENT_BUFFER == (retval = Table(d, &size, TRUE)));
101 if(NO_ERROR != retval) error_exit("GetIpAddrTable error: %d\n", retval);
102
103 for(r = d->table; r != d->table + d->dwNumEntries; ++r)
104 if(r->dwAddr == ip) return retval = r->dwIndex, realloc(d,0), retval;
105 return error_exit("Parameter error: Unknown host IP address\n", 0), 0;
106}
107/*-----------------------------------------------------------------------------------*/
108static void*
109sock_in_addr(unsigned long ipaddr, u16_t port)
110{
111 static struct sockaddr_in addr;
112 addr.sin_family = AF_INET;
113 addr.sin_port = port;
114 addr.sin_addr.s_addr = ipaddr;
115 return &addr;
oliverschmidtde98fae2004-07-31 14:47:56 +0000116}
117/*-----------------------------------------------------------------------------------*/
118void
119rawsock_init(void)
120{
oliverschmidted66a1d2005-02-15 21:18:33 +0000121 DWORD hostaddr;
oliverschmidted66a1d2005-02-15 21:18:33 +0000122 WSADATA wsadata;
ryohji09e3a0d2007-05-06 13:01:52 +0000123
124 if(WSAStartup(2, &wsadata) != 0) {
125 error_exit("WSAStartup() error\n", 0);
126 }
oliverschmidtde98fae2004-07-31 14:47:56 +0000127
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000128 hostaddr = inet_addr(__argv[1]);
129 if(hostaddr == INADDR_NONE) {
130 error_exit("Parameter error: Invalid host IP address\n", 0);
131 }
132
ryohji09e3a0d2007-05-06 13:01:52 +0000133 rawsock = socket(PF_INET, SOCK_RAW, IPPROTO_IP);
oliverschmidtde98fae2004-07-31 14:47:56 +0000134 if(rawsock == INVALID_SOCKET) {
135 error_exit("socket() error: %d\n", WSAGetLastError());
136 }
137
ryohji09e3a0d2007-05-06 13:01:52 +0000138 if(bind(rawsock, sock_in_addr(hostaddr,0), sizeof(struct sockaddr)) == SOCKET_ERROR) {
oliverschmidtde98fae2004-07-31 14:47:56 +0000139 error_exit("bind() error: %d\n", WSAGetLastError());
140 }
141
ryohji09e3a0d2007-05-06 13:01:52 +0000142 SOCKOPT_ON_(SO_BROADCAST, SOL_SOCKET);
143 SOCKOPT_ON_(IP_HDRINCL, IPPROTO_IP);
144 SOCKCTL_(1, SIO_RCVALL);
145 SOCKCTL_(1, FIONBIO);
oliverschmidtc160fca2005-01-30 13:26:05 +0000146
ryohji09e3a0d2007-05-06 13:01:52 +0000147 LoadLibrary("iphlpapi"); /* map iphlpapi.dll to process address space */
148 if(atexit(delete_proxyarp)) error_exit("atexit() error\n", 0);
149 interfaceindex = get_interface_index_for_(hostaddr);
150}
151/*-----------------------------------------------------------------------------------*/
152void
153rawsock_fini(void)
154{
155 delete_proxyarp();
156 closesocket(rawsock);
157 rawsock = INVALID_SOCKET;
158 FreeLibrary(GetModuleHandle("iphlpapi"));
159 WSACleanup();
oliverschmidtde98fae2004-07-31 14:47:56 +0000160}
161/*-----------------------------------------------------------------------------------*/
162void
ryohji55cd87a2007-05-02 04:06:56 +0000163rawsock_send(u8_t *hdr, u16_t hdrlen, u8_t *data, u16_t datalen)
oliverschmidtde98fae2004-07-31 14:47:56 +0000164{
ryohji09e3a0d2007-05-06 13:01:52 +0000165 static const int ignore[] = {WSAEADDRNOTAVAIL,WSAEHOSTUNREACH};
ryohji55cd87a2007-05-02 04:06:56 +0000166 WSABUF sendbuf[2] = {{hdrlen, hdr},{datalen, data}};
ryohji09e3a0d2007-05-06 13:01:52 +0000167 DWORD value;
oliverschmidtde98fae2004-07-31 14:47:56 +0000168
ryohji09e3a0d2007-05-06 13:01:52 +0000169 SOCKCTL_(0, FIONBIO); /* switch Non-blocking I/O off */
oliverschmidtde98fae2004-07-31 14:47:56 +0000170
ryohji09e3a0d2007-05-06 13:01:52 +0000171 value = WSASendTo(rawsock, sendbuf, 2, &value, 0
172 , sock_in_addr(*(unsigned*)BUF->destipaddr,0), sizeof(struct sockaddr_in)
173 , NULL, NULL);
174 if(SOCKET_ERROR == value) TRAP(WSAGetLastError(), ignore, END_OF(ignore));
oliverschmidt2605c1c2004-08-02 11:36:34 +0000175
ryohji09e3a0d2007-05-06 13:01:52 +0000176 SOCKCTL_(1, FIONBIO); /* switch Non-blocking I/O on */
oliverschmidtde98fae2004-07-31 14:47:56 +0000177}
178/*-----------------------------------------------------------------------------------*/
179u16_t
180rawsock_poll(void)
181{
ryohji09e3a0d2007-05-06 13:01:52 +0000182 static const int ignore[] = {WSAEWOULDBLOCK,WSAEMSGSIZE,WSANOTINITIALISED};
183 const int nr = (create_proxyarp(),recv(rawsock, uip_buf, UIP_BUFSIZE, 0));
184 return SOCKET_ERROR != nr ? nr : TRAP(WSAGetLastError(), ignore, END_OF(ignore));
ryohji55cd87a2007-05-02 04:06:56 +0000185}
186/*-----------------------------------------------------------------------------------*/
187void
ryohji09e3a0d2007-05-06 13:01:52 +0000188create_proxyarp(void)
ryohji55cd87a2007-05-02 04:06:56 +0000189{
ryohji09e3a0d2007-05-06 13:01:52 +0000190 if(proxyaddr != HOSTADDR()) {
191 FARPROC f = DELAY_LOAD("CreateProxyArpEntry","iphlpapi");
192 DWORD retval = (delete_proxyarp(),((ARPFUNC)f)(HOSTADDR(), NETMASK(), interfaceindex));
193 proxyaddr = HOSTADDR();
194 debug_printf("CreateProxyArpEntry(%s): %d\n", inet_ntoa(*(struct in_addr*)&proxyaddr), retval);
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000195 }
ryohji55cd87a2007-05-02 04:06:56 +0000196}
197/*-----------------------------------------------------------------------------------*/
198void
ryohji09e3a0d2007-05-06 13:01:52 +0000199delete_proxyarp(void)
ryohji55cd87a2007-05-02 04:06:56 +0000200{
ryohji09e3a0d2007-05-06 13:01:52 +0000201 if(proxyaddr) {
202 FARPROC f = DELAY_LOAD("DeleteProxyArpEntry","iphlpapi");
203 DWORD retval = ((ARPFUNC)f)(HOSTADDR(), NETMASK(), interfaceindex);
204 debug_printf("DeleteProxyArpEntry(%s): %d\n", inet_ntoa(*(struct in_addr*)&proxyaddr), retval);
205 proxyaddr = 0;
oliverschmidtde98fae2004-07-31 14:47:56 +0000206 }
oliverschmidtde98fae2004-07-31 14:47:56 +0000207}
208/*-----------------------------------------------------------------------------------*/