61a9ca10406f296d3b77887e010814c8c9c91732
[olsrd.git] / src / win32 / net.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #if defined WINCE
43 #include <sys/types.h>          // for time_t
44 #endif
45
46 #define WIN32_LEAN_AND_MEAN
47 #include <windows.h>
48 #include <winsock2.h>
49 #include <ws2tcpip.h>
50 #include <iphlpapi.h>
51 #undef interface
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <errno.h>
56
57 #include "defs.h"
58 #include "net_os.h"
59 #include "net_olsr.h"
60 #include "ipcalc.h"
61 #include "olsr_logging.h"
62
63 #if defined WINCE
64 #define WIDE_STRING(s) L##s
65 #else
66 #define WIDE_STRING(s) s
67 #endif
68
69 void WinSockPError(const char *Str);
70 void PError(const char *);
71
72 void DisableIcmpRedirects(void);
73 int disable_ip_forwarding(int Ver);
74
75
76 int
77 gethemusocket(struct sockaddr_in *pin)
78 {
79   int sock;
80
81   OLSR_INFO(LOG_NETWORKING, "       Connecting to switch daemon port %d\n", pin->sin_port);
82
83   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
84     OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for emulation (%s)\n", strerror(errno));
85     olsr_exit(EXIT_FAILURE);
86   }
87
88   /* connect to PORT on HOST */
89   if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) {
90     OLSR_ERROR(LOG_NETWORKING, "Cannot reuse address for socket for emulation (%s)\n", strerror(errno));
91     CLOSESOCKET(sock);
92     olsr_exit(EXIT_FAILURE);
93   }
94
95   /* Keep TCP socket blocking */
96   return (sock);
97 }
98
99 int
100 getsocket(int BuffSize, char *Int __attribute__ ((unused)))
101 {
102   struct sockaddr_in Addr;
103   int On = 1;
104   unsigned long Len;
105   int Sock = socket(AF_INET, SOCK_DGRAM, 0);
106   if (Sock < 0) {
107     OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
108     olsr_exit(EXIT_FAILURE);
109   }
110
111   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
112     OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
113     CLOSESOCKET(Sock);
114     olsr_exit(EXIT_FAILURE);
115   }
116
117   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
118     OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
119     CLOSESOCKET(Sock);
120     olsr_exit(EXIT_FAILURE);
121   }
122
123   while (BuffSize > 8192) {
124     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize, sizeof(BuffSize)) == 0)
125       break;
126
127     BuffSize -= 1024;
128   }
129
130   if (BuffSize <= 8192)
131     OLSR_WARN(LOG_NETWORKING, "Cannot set IPv4 socket receive buffer.\n");
132
133   memset(&Addr, 0, sizeof(Addr));
134   Addr.sin_family = AF_INET;
135   Addr.sin_port = htons(OLSRPORT);
136   Addr.sin_addr.s_addr = INADDR_ANY;
137   if (bind(Sock, (struct sockaddr *)&Addr, sizeof(Addr)) < 0) {
138     OLSR_ERROR(LOG_NETWORKING, "Could not bind socket for OLSR PDUs to device (%s)\n", strerror(errno));
139     CLOSESOCKET(Sock);
140     olsr_exit(EXIT_FAILURE);
141   }
142
143   if (WSAIoctl(Sock, FIONBIO, &On, sizeof(On), NULL, 0, &Len, NULL, NULL) < 0) {
144     OLSR_ERROR(LOG_NETWORKING, "WSAIoctl");
145     CLOSESOCKET(Sock);
146     olsr_exit(EXIT_FAILURE);
147   }
148
149   return Sock;
150 }
151
152 int
153 getsocket6(int BuffSize, char *Int __attribute__ ((unused)))
154 {
155   struct sockaddr_in6 Addr6;
156   int On = 1;
157   int Sock = socket(AF_INET6, SOCK_DGRAM, 0);
158   if (Sock < 0) {
159     OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
160     olsr_exit(EXIT_FAILURE);
161   }
162
163   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
164     OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
165     CLOSESOCKET(sock);
166     olsr_exit(EXIT_FAILURE);
167   }
168
169   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
170     OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
171     CLOSESOCKET(Sock);
172     olsr_exit(EXIT_FAILURE);
173   }
174
175   while (BuffSize > 8192) {
176     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize, sizeof(BuffSize)) == 0)
177       break;
178
179     BuffSize -= 1024;
180   }
181
182   if (BuffSize <= 8192)
183     OLSR_WARN(LOG_NETWORKING, "Cannot set IPv6 socket receive buffer.\n");
184
185   memset(&Addr6, 0, sizeof(Addr6));
186   Addr6.sin6_family = AF_INET6;
187   Addr6.sin6_port = htons(OLSRPORT);
188   //Addr6.sin6_addr.s_addr = IN6ADDR_ANY_INIT;
189   if (bind(Sock, (struct sockaddr *)&Addr6, sizeof(Addr6)) < 0) {
190     OLSR_ERROR(LOG_NETWORKING, "Could not bind socket for OLSR PDUs to device (%s)\n", strerror(errno));
191     CLOSESOCKET(Sock);
192     olsr_exit(EXIT_FAILURE);
193   }
194
195   return Sock;
196 }
197
198 static OVERLAPPED RouterOver;
199
200 int
201 enable_ip_forwarding(int Ver)
202 {
203   HMODULE Lib;
204   unsigned int __stdcall(*EnableRouterFunc) (HANDLE * Hand, OVERLAPPED * Over);
205   HANDLE Hand;
206
207   Ver = Ver;
208
209   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
210
211   if (Lib == NULL)
212     return 0;
213
214   EnableRouterFunc = (unsigned int __stdcall(*)(HANDLE *, OVERLAPPED *))
215     GetProcAddress(Lib, WIDE_STRING("EnableRouter"));
216
217   if (EnableRouterFunc == NULL)
218     return 0;
219
220   memset(&RouterOver, 0, sizeof(OVERLAPPED));
221
222   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
223
224   if (RouterOver.hEvent == NULL) {
225     OLSR_WARN(LOG_NETWORKING, "CreateEvent()");
226     return -1;
227   }
228
229   if (EnableRouterFunc(&Hand, &RouterOver) != ERROR_IO_PENDING) {
230     OLSR_WARN(LOG_NETWORKING, "EnableRouter()");
231     return -1;
232   }
233
234   OLSR_DEBUG(LOG_NETWORKING, "Routing enabled.\n");
235
236   return 0;
237 }
238
239 int
240 disable_ip_forwarding(int Ver)
241 {
242   HMODULE Lib;
243   unsigned int __stdcall(*UnenableRouterFunc) (OVERLAPPED * Over, unsigned int *Count);
244   unsigned int Count;
245
246   Ver = Ver;
247
248   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
249
250   if (Lib == NULL)
251     return 0;
252
253   UnenableRouterFunc = (unsigned int __stdcall(*)(OVERLAPPED *, unsigned int *))
254     GetProcAddress(Lib, WIDE_STRING("UnenableRouter"));
255
256   if (UnenableRouterFunc == NULL)
257     return 0;
258
259   if (UnenableRouterFunc(&RouterOver, &Count) != NO_ERROR) {
260     OLSR_WARN(LOG_NETWORKING, "UnenableRouter()");
261     return -1;
262   }
263
264   OLSR_DEBUG(LOG_NETWORKING, "Routing disabled, count = %u.\n", Count);
265
266   return 0;
267 }
268
269 int
270 restore_settings(int Ver)
271 {
272   disable_ip_forwarding(Ver);
273
274   return 0;
275 }
276
277 static int
278 SetEnableRedirKey(unsigned long New)
279 {
280 #if !defined WINCE
281   HKEY Key;
282   unsigned long Type;
283   unsigned long Len;
284   unsigned long Old;
285
286   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
287                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
288     return -1;
289
290   Len = sizeof(Old);
291
292   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type, (unsigned char *)&Old, &Len) != ERROR_SUCCESS || Type != REG_DWORD)
293     Old = 1;
294
295   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD, (unsigned char *)&New, sizeof(New))) {
296     RegCloseKey(Key);
297     return -1;
298   }
299
300   RegCloseKey(Key);
301   return Old;
302 #else
303   return 0;
304 #endif
305 }
306
307 void
308 DisableIcmpRedirects(void)
309 {
310   int Res;
311
312   Res = SetEnableRedirKey(0);
313
314   if (Res != 1)
315     return;
316
317   OLSR_ERROR(LOG_NETWORKING, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
318
319 #if 0
320   if (Res < 0) {
321     OLSR_ERROR(LOG_NETWORKING, "Cannot disable ICMP redirect processing in the registry.\n");
322     OLSR_ERROR(LOG_NETWORKING, "Please disable it manually. Continuing in 3 seconds...\n");
323     Sleep(3000);
324
325     return;
326   }
327 #endif
328
329   OLSR_ERROR(LOG_NETWORKING, "I have disabled ICMP redirect processing in the registry for you.\n");
330   OLSR_ERROR(LOG_NETWORKING, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
331
332   exit(0);
333 }
334
335
336 int
337 join_mcast(struct interface *Nic, int Sock)
338 {
339   /* See linux/in6.h */
340   struct ipaddr_str buf;
341   struct ipv6_mreq McastReq;
342
343   McastReq.ipv6mr_multiaddr = Nic->int6_multaddr.sin6_addr;
344   McastReq.ipv6mr_interface = Nic->if_index;
345
346   OLSR_DEBUG(LOG_NETWORKING, "Interface %s joining multicast %s...", Nic->int_name,
347              olsr_ip_to_string(&buf, (union olsr_ip_addr *)&Nic->int6_multaddr.sin6_addr));
348   /* Send multicast */
349   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq))
350       < 0) {
351     OLSR_WARN(LOG_NETWORKING, "Join multicast: %s\n", strerror(errno));
352     return -1;
353   }
354
355   /* Old libc fix */
356 #ifdef IPV6_JOIN_GROUP
357   /* Join reciever group */
358   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&McastReq, sizeof(struct ipv6_mreq))
359       < 0)
360 #else
361   /* Join reciever group */
362   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq))
363       < 0)
364 #endif
365   {
366     OLSR_WARN(LOG_NETWORKING, "Join multicast send: %s\n", strerror(errno));
367     return -1;
368   }
369
370
371   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&McastReq.ipv6mr_interface, sizeof(McastReq.ipv6mr_interface))
372       < 0) {
373     OLSR_WARN(LOG_NETWORKING, "Join multicast if: %s\n", strerror(errno));
374     return -1;
375   }
376
377   return 0;
378 }
379
380
381 /**
382  * Wrapper for sendto(2)
383  */
384
385 ssize_t
386 olsr_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr * to, socklen_t tolen)
387 {
388   return sendto(s, buf, len, flags, to, tolen);
389 }
390
391
392 /**
393  * Wrapper for recvfrom(2)
394  */
395
396 ssize_t
397 olsr_recvfrom(int s, void *buf, size_t len, int flags __attribute__ ((unused)), struct sockaddr * from, socklen_t * fromlen)
398 {
399   return recvfrom(s, buf, len, 0, from, fromlen);
400 }
401
402 /**
403  * Wrapper for select(2)
404  */
405
406 int
407 olsr_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
408 {
409   return select(nfds, readfds, writefds, exceptfds, timeout);
410 }
411
412 /*
413  * Local Variables:
414  * c-basic-offset: 2
415  * indent-tabs-mode: nil
416  * End:
417  */