blob: 59af00c4fd592db965a6b56005ab51d6169010b3 [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
15typedef struct {
oliverschmidted66a1d2005-02-15 21:18:33 +000016 DWORD dwAddr;
17 DWORD dwIndex;
18 DWORD dwMask;
19 DWORD dwBCastAddr;
20 DWORD dwReasmSize;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000021 unsigned short unused1;
22 unsigned short unused2;
23} MIB_IPADDRROW;
24
25typedef struct {
oliverschmidted66a1d2005-02-15 21:18:33 +000026 DWORD dwNumEntries;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000027 MIB_IPADDRROW table[0];
28} MIB_IPADDRTABLE;
29
30static DWORD (WINAPI *GetIpAddrTable)(MIB_IPADDRTABLE *, DWORD *, BOOL);
31
32static DWORD (WINAPI *CreateProxyArpEntry)(DWORD, DWORD, DWORD);
33
34static DWORD (WINAPI *DeleteProxyArpEntry)(DWORD, DWORD, DWORD);
35
36#pragma pack(pop)
37
ryohji55cd87a2007-05-02 04:06:56 +000038#define htons contiki_htons /* htons is defined in winsock2 */
oliverschmidtde98fae2004-07-31 14:47:56 +000039#include "uip.h"
ryohji55cd87a2007-05-02 04:06:56 +000040#undef htons
oliverschmidtde98fae2004-07-31 14:47:56 +000041#include "tcpip.h"
42#include "ctk.h"
ryohji55cd87a2007-05-02 04:06:56 +000043
44#define SOCKIO_(ON,CMD) sockio_(ON,CMD,"ioctlsocket("#CMD") error: %d\n")
oliverschmidtde98fae2004-07-31 14:47:56 +000045
46#define BUF ((uip_tcpip_hdr *)uip_buf)
47
oliverschmidt7f0b22b2005-01-29 23:10:43 +000048void debug_printf(char *format, ...);
49
oliverschmidte7851ab2005-01-30 20:25:28 +000050static DWORD interfaceindex;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000051static DWORD proxyaddr;
oliverschmidtde98fae2004-07-31 14:47:56 +000052static SOCKET rawsock = INVALID_SOCKET;
ryohji55cd87a2007-05-02 04:06:56 +000053static unsigned long off = 0;
54static unsigned long on = 1;
oliverschmidtde98fae2004-07-31 14:47:56 +000055
ryohji55cd87a2007-05-02 04:06:56 +000056static const int recv_filt[] = {WSAEWOULDBLOCK,WSAEMSGSIZE};
57static const int send_filt[] = {WSAEADDRNOTAVAIL,WSAEHOSTUNREACH};
58
59static void sockio_(unsigned long on, long cmd, char *cmd_err_fmt);
60static u16_t filt_err(int e, const int *head, const int *const tail);
61static void update_proxy_arp(void);
62static u16_t filter_recv(int value);
63static u16_t filter_send(int value);
64/*-----------------------------------------------------------------------------------*/
65static int match(const int x, const int *head, const int *const tail)
66{
67 for( ;tail != head; ++head)
68 {
69 if(*head == x) return 1;
70 }
71 return 0;
72}
oliverschmidtde98fae2004-07-31 14:47:56 +000073/*-----------------------------------------------------------------------------------*/
74static void
oliverschmidt7f0b22b2005-01-29 23:10:43 +000075create_proxyarp(void)
76{
oliverschmidted66a1d2005-02-15 21:18:33 +000077 DWORD retval;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000078 struct in_addr addr;
79
80 if(proxyaddr == 0) {
81 return;
82 }
83 retval = CreateProxyArpEntry(proxyaddr, 0xFFFFFFFF, interfaceindex);
84 addr.S_un.S_addr = proxyaddr;
85 debug_printf("CreateProxyArpEntry(%s): %d\n", inet_ntoa(addr), retval);
86}
87/*-----------------------------------------------------------------------------------*/
88static void
89delete_proxyarp(void)
90{
oliverschmidted66a1d2005-02-15 21:18:33 +000091 DWORD retval;
oliverschmidt7f0b22b2005-01-29 23:10:43 +000092 struct in_addr addr;
93
94 if(proxyaddr == 0) {
95 return;
96 }
97 retval = DeleteProxyArpEntry(proxyaddr, 0xFFFFFFFF, interfaceindex);
98 addr.S_un.S_addr = proxyaddr;
99 debug_printf("DeleteProxyArpEntry(%s): %d\n", inet_ntoa(addr), retval);
100}
101/*-----------------------------------------------------------------------------------*/
ryohji55cd87a2007-05-02 04:06:56 +0000102static int
oliverschmidtde98fae2004-07-31 14:47:56 +0000103error_exit(char *message, int value)
104{
105 console_exit();
106 cprintf(message, value);
107 exit(EXIT_FAILURE);
ryohji55cd87a2007-05-02 04:06:56 +0000108 return 0;
oliverschmidtde98fae2004-07-31 14:47:56 +0000109}
110/*-----------------------------------------------------------------------------------*/
111void
112rawsock_init(void)
113{
oliverschmidted66a1d2005-02-15 21:18:33 +0000114 DWORD hostaddr;
115 HMODULE iphlpapi;
116 MIB_IPADDRTABLE *addrtable;
117 DWORD addrtablesize = 0;
118 DWORD retval;
119 DWORD entry = 0;
120 WSADATA wsadata;
121 struct sockaddr_in addr;
oliverschmidtde98fae2004-07-31 14:47:56 +0000122
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000123 hostaddr = inet_addr(__argv[1]);
124 if(hostaddr == INADDR_NONE) {
125 error_exit("Parameter error: Invalid host IP address\n", 0);
126 }
127
128 iphlpapi = LoadLibrary("iphlpapi.dll");
129 if(iphlpapi == NULL) {
130 error_exit("LoadLibrary(iphlpapi.dll) error: %d\n", GetLastError());
131 }
132
133 (FARPROC)GetIpAddrTable = GetProcAddress(iphlpapi, "GetIpAddrTable");
134 if(GetIpAddrTable == NULL) {
135 error_exit("GetProcAddress(GetIpAddrTable) error: %d\n", GetLastError());
136 }
137
138 (FARPROC)CreateProxyArpEntry = GetProcAddress(iphlpapi, "CreateProxyArpEntry");
139 if(GetIpAddrTable == NULL) {
140 error_exit("GetProcAddress(CreateProxyArpEntry) error: %d\n", GetLastError());
141 }
142
143 (FARPROC)DeleteProxyArpEntry = GetProcAddress(iphlpapi, "DeleteProxyArpEntry");
144 if(GetIpAddrTable == NULL) {
145 error_exit("GetProcAddress(DeleteProxyArpEntry) error: %d\n", GetLastError());
146 }
147
148 retval = GetIpAddrTable(NULL, &addrtablesize, TRUE);
149 if(retval != ERROR_INSUFFICIENT_BUFFER) {
150 error_exit("GetIpAddrTable(NULL) error: %d\n", retval);
151 }
152
153 addrtable = alloca(addrtablesize);
154 retval = GetIpAddrTable(addrtable, &addrtablesize, TRUE);
155 if(retval != NO_ERROR) {
156 error_exit("GetIpAddrTable(ptr) error: %d\n", retval);
157 }
158
oliverschmidte7851ab2005-01-30 20:25:28 +0000159 while(1) {
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000160 if(entry == addrtable->dwNumEntries) {
161 error_exit("Parameter error: Unknown host IP address\n", 0);
162 }
163 if(addrtable->table[entry].dwAddr == hostaddr) {
164 interfaceindex = addrtable->table[entry].dwIndex;
oliverschmidte7851ab2005-01-30 20:25:28 +0000165 break;
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000166 }
167 entry++;
168 }
169
oliverschmidtde98fae2004-07-31 14:47:56 +0000170 if(WSAStartup(2, &wsadata) != 0) {
171 error_exit("WSAStartup() error\n", 0);
172 }
173
174 rawsock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
175 if(rawsock == INVALID_SOCKET) {
176 error_exit("socket() error: %d\n", WSAGetLastError());
177 }
178
179 addr.sin_family = AF_INET;
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000180 addr.sin_addr.s_addr = hostaddr;
oliverschmidtde98fae2004-07-31 14:47:56 +0000181 addr.sin_port = 0;
oliverschmidt2605c1c2004-08-02 11:36:34 +0000182 if(bind(rawsock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) {
oliverschmidtde98fae2004-07-31 14:47:56 +0000183 error_exit("bind() error: %d\n", WSAGetLastError());
184 }
185
oliverschmidtc160fca2005-01-30 13:26:05 +0000186 if(setsockopt(rawsock, SOL_SOCKET, SO_BROADCAST,
187 (char *)&on, sizeof(on)) == SOCKET_ERROR) {
188 error_exit("setsockopt(SO_BROADCAST) error: %d\n", WSAGetLastError());
189 }
190
oliverschmidtde98fae2004-07-31 14:47:56 +0000191 if(setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL,
192 (char *)&on, sizeof(on)) == SOCKET_ERROR) {
193 error_exit("setsockopt(IP_HDRINCL) error: %d\n", WSAGetLastError());
194 }
195
ryohji55cd87a2007-05-02 04:06:56 +0000196 SOCKIO_(on, SIO_RCVALL);
197 SOCKIO_(on, FIONBIO);
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000198
199 if(atexit(delete_proxyarp) != 0) {
200 error_exit("atexit() error\n", 0);
201 }
oliverschmidtde98fae2004-07-31 14:47:56 +0000202}
203/*-----------------------------------------------------------------------------------*/
204void
ryohji55cd87a2007-05-02 04:06:56 +0000205rawsock_send(u8_t *hdr, u16_t hdrlen, u8_t *data, u16_t datalen)
oliverschmidtde98fae2004-07-31 14:47:56 +0000206{
oliverschmidted66a1d2005-02-15 21:18:33 +0000207 struct sockaddr_in addr;
ryohji55cd87a2007-05-02 04:06:56 +0000208 DWORD dummy;
209 WSABUF sendbuf[2] = {{hdrlen, hdr},{datalen, data}};
oliverschmidtde98fae2004-07-31 14:47:56 +0000210
ryohji55cd87a2007-05-02 04:06:56 +0000211 SOCKIO_(off, FIONBIO); /* switch Non-blocking I/O off */
oliverschmidtde98fae2004-07-31 14:47:56 +0000212
213 addr.sin_family = AF_INET;
214 addr.sin_addr.s_addr = *(unsigned long *)BUF->destipaddr;
215 addr.sin_port = 0;
ryohji55cd87a2007-05-02 04:06:56 +0000216 filter_send(WSASendTo(rawsock, sendbuf, 2, &dummy, 0
217 , (struct sockaddr *)&addr, sizeof(addr), NULL, NULL));
oliverschmidt2605c1c2004-08-02 11:36:34 +0000218
ryohji55cd87a2007-05-02 04:06:56 +0000219 SOCKIO_(on, FIONBIO); /* switch Non-blocking I/O on */
oliverschmidtde98fae2004-07-31 14:47:56 +0000220}
221/*-----------------------------------------------------------------------------------*/
222u16_t
223rawsock_poll(void)
224{
ryohji55cd87a2007-05-02 04:06:56 +0000225 return INVALID_SOCKET == rawsock ? 0 :
226 filter_recv((update_proxy_arp(), recv(rawsock, uip_buf, UIP_BUFSIZE, 0)));
227}
228/*-----------------------------------------------------------------------------------*/
229u16_t filter_recv(int value)
230{
231 return SOCKET_ERROR == value
232 ? filt_err(WSAGetLastError(), recv_filt, recv_filt + 2) : value;
233}
234/*-----------------------------------------------------------------------------------*/
235u16_t filter_send(int value)
236{
237 return SOCKET_ERROR == value
238 ? filt_err(WSAGetLastError(), send_filt, send_filt + 2) : value;
239}
240/*-----------------------------------------------------------------------------------*/
241u16_t filt_err(int v, const int *hd, const int *const tl)
242{
243 return match(v, hd, tl) ? v : error_exit("send/recv() error: %d\n", v);
244}
245/*-----------------------------------------------------------------------------------*/
246void
247update_proxy_arp(void)
248{
oliverschmidt7f0b22b2005-01-29 23:10:43 +0000249 if(proxyaddr != *(DWORD *)uip_hostaddr) {
250 delete_proxyarp();
251 proxyaddr = *(DWORD *)uip_hostaddr;
252 create_proxyarp();
253 }
ryohji55cd87a2007-05-02 04:06:56 +0000254}
255/*-----------------------------------------------------------------------------------*/
256void
257sockio_(unsigned long on, long cmd, char *cmd_err_fmt)
258{
259 if(SOCKET_ERROR == ioctlsocket(rawsock, cmd, &on)) {
260 error_exit(cmd_err_fmt, WSAGetLastError());
oliverschmidtde98fae2004-07-31 14:47:56 +0000261 }
oliverschmidtde98fae2004-07-31 14:47:56 +0000262}
263/*-----------------------------------------------------------------------------------*/