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