* and make it compile on Win32
[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  * $Id: net.c,v 1.23 2007/11/08 23:23:13 bernd67 Exp $
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 "defs.h"
56 #include "net_os.h"
57 #include "net_olsr.h"
58
59 #if defined WINCE
60 #define WIDE_STRING(s) L##s
61 #else
62 #define WIDE_STRING(s) s
63 #endif
64
65 void WinSockPError(char *Str);
66 void PError(char *);
67
68 void DisableIcmpRedirects(void);
69 int disable_ip_forwarding(int Ver);
70
71
72 int
73 gethemusocket(struct sockaddr_in *pin)
74 {
75   int sock;
76
77   OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
78
79   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
80     {
81       perror("hcsocket");
82       return (-1);
83     }
84
85   /* connect to PORT on HOST */
86   if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
87     {
88       printf("FAILED\n");
89       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
90       printf("connection refused\n");
91       closesocket(sock);
92       return (-1);
93     }
94
95   printf("OK\n");
96
97   /* Keep TCP socket blocking */  
98   return (sock);
99 }
100
101 int getsocket(struct sockaddr *Addr, int BuffSize, char *Int __attribute__((unused)))
102 {
103   int Sock;
104   int On = 1;
105   unsigned long Len;
106
107   Sock = socket(AF_INET, SOCK_DGRAM, 0);
108
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   while (BuffSize > 8192)
124   {
125     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
126                    sizeof (BuffSize)) == 0)
127       break;
128
129     BuffSize -= 1024;
130   }
131
132   if (BuffSize <= 8192) 
133     fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
134
135   if (bind(Sock, Addr, sizeof (struct sockaddr_in)) < 0)
136   {
137     WinSockPError("getsocket/bind()");
138     closesocket(Sock);
139     return -1;
140   }
141
142   if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
143   {
144     WinSockPError("WSAIoctl");
145     closesocket(Sock);
146     return -1;
147   }
148
149   return Sock;
150 }
151
152 int getsocket6(struct sockaddr_in6 *Addr, int BuffSize, char *Int __attribute__((unused)))
153 {
154   int Sock;
155   int On = 1;
156
157   Sock = socket(AF_INET6, SOCK_DGRAM, 0);
158
159   if (Sock < 0)
160   {
161     WinSockPError("getsocket6/socket()");
162     return -1;
163   }
164
165   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
166                  (char *)&On, sizeof (On)) < 0)
167   {
168     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
169     closesocket(Sock);
170     return -1;
171   }
172
173   while (BuffSize > 8192)
174   {
175     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
176                    sizeof (BuffSize)) == 0)
177       break;
178
179     BuffSize -= 1024;
180   }
181
182   if (BuffSize <= 8192) 
183     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
184
185   if (bind(Sock, (struct sockaddr *)Addr, sizeof (struct sockaddr_in6)) < 0)
186   {
187     WinSockPError("getsocket6/bind()");
188     closesocket(Sock);
189     return -1;
190   }
191
192   return Sock;
193 }
194
195 static OVERLAPPED RouterOver;
196
197 int enable_ip_forwarding(int Ver)
198 {
199   HMODULE Lib;
200   unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
201   HANDLE Hand;
202
203   Ver = Ver;
204
205   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
206
207   if (Lib == NULL)
208     return 0;
209
210   EnableRouter = (unsigned int __stdcall (*)(HANDLE *, OVERLAPPED *))
211     GetProcAddress(Lib, WIDE_STRING("EnableRouter"));
212
213   if (EnableRouter == NULL)
214     return 0;
215
216   memset(&RouterOver, 0, sizeof (OVERLAPPED));
217
218   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
219
220   if (RouterOver.hEvent == NULL)
221   {
222     PError("CreateEvent()");
223     return -1;
224   }
225   
226   if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
227   {
228     PError("EnableRouter()");
229     return -1;
230   }
231
232   OLSR_PRINTF(3, "Routing enabled.\n");
233
234   return 0;
235 }
236
237 int disable_ip_forwarding(int Ver)
238 {
239   HMODULE Lib;
240   unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
241                                             unsigned int *Count);
242   unsigned int Count;
243
244   Ver = Ver;
245   
246   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
247
248   if (Lib == NULL)
249     return 0;
250
251   UnenableRouter = (unsigned int __stdcall (*)(OVERLAPPED *, unsigned int *))
252     GetProcAddress(Lib, WIDE_STRING("UnenableRouter"));
253
254   if (UnenableRouter == NULL)
255     return 0;
256
257   if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
258   {
259     PError("UnenableRouter()");
260     return -1;
261   }
262
263   OLSR_PRINTF(3, "Routing disabled, count = %u.\n", Count);
264
265   return 0;
266 }
267
268 int restore_settings(int Ver)
269 {
270   disable_ip_forwarding(Ver);
271
272   return 0;
273 }
274
275 static int SetEnableRedirKey(unsigned long New)
276 {
277 #if !defined WINCE
278   HKEY Key;
279   unsigned long Type;
280   unsigned long Len;
281   unsigned long Old;
282
283   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
284                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
285                    0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
286     return -1;
287
288   Len = sizeof (Old);
289
290   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
291                       (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
292       Type != REG_DWORD)
293     Old = 1;
294
295   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
296                     (unsigned char *)&New, sizeof (New)))
297   {
298     RegCloseKey(Key);
299     return -1;
300   }
301
302   RegCloseKey(Key);
303   return Old;
304 #else
305   return 0;
306 #endif
307 }
308
309 void DisableIcmpRedirects(void)
310 {
311   int Res;
312
313   Res = SetEnableRedirKey(0);
314
315   if (Res != 1)
316     return;
317
318   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
319
320 #if 0
321   if (Res < 0)
322   {
323     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
324     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
325     Sleep(3000);
326
327     return;
328   }
329 #endif
330
331   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
332   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
333
334   exit(0);
335 }
336
337
338 int join_mcast(struct interface *Nic, int Sock)
339 {
340   /* See linux/in6.h */
341   struct ipaddr_str buf;
342   struct ipv6_mreq McastReq;
343
344   //COPY_IP(&McastReq.ipv6mr_multiaddr, &Nic->int6_multaddr.sin6_addr);
345   McastReq.ipv6mr_multiaddr = Nic->int6_multaddr.sin6_addr;
346   McastReq.ipv6mr_interface = Nic->if_index;
347
348   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));
349   /* Send multicast */
350   if(setsockopt(Sock, 
351                 IPPROTO_IPV6, 
352                 IPV6_ADD_MEMBERSHIP, 
353                 (char *)&McastReq, 
354                 sizeof(struct ipv6_mreq)) 
355      < 0)
356     {
357       perror("Join multicast");
358       return -1;
359     }
360
361   /* Old libc fix */
362 #ifdef IPV6_JOIN_GROUP
363   /* Join reciever group */
364   if(setsockopt(Sock, 
365                 IPPROTO_IPV6, 
366                 IPV6_JOIN_GROUP, 
367                 (char *)&McastReq, 
368                 sizeof(struct ipv6_mreq)) 
369      < 0)
370 #else
371   /* Join reciever group */
372   if(setsockopt(Sock, 
373                 IPPROTO_IPV6, 
374                 IPV6_ADD_MEMBERSHIP, 
375                 (char *)&McastReq, 
376                 sizeof(struct ipv6_mreq)) 
377      < 0)
378 #endif 
379     {
380       perror("Join multicast send");
381       return -1;
382     }
383
384   
385   if(setsockopt(Sock, 
386                 IPPROTO_IPV6, 
387                 IPV6_MULTICAST_IF, 
388                 (char *)&McastReq.ipv6mr_interface, 
389                 sizeof(McastReq.ipv6mr_interface)) 
390      < 0)
391     {
392       perror("Set multicast if");
393       return -1;
394     }
395
396
397   OLSR_PRINTF(3, "OK\n");
398   return 0;
399 }
400
401
402 /**
403  * Wrapper for sendto(2)
404  */
405
406 ssize_t
407 olsr_sendto(int s, 
408             const void *buf, 
409             size_t len, 
410             int flags, 
411             const struct sockaddr *to, 
412             socklen_t tolen)
413 {
414   return sendto(s, buf, len, flags, to, tolen);
415 }
416
417
418 /**
419  * Wrapper for recvfrom(2)
420  */
421
422 ssize_t  
423 olsr_recvfrom(int  s, 
424               void *buf, 
425               size_t len, 
426               int flags __attribute__((unused)), 
427               struct sockaddr *from,
428               socklen_t *fromlen)
429 {
430   return recvfrom(s, 
431                   buf, 
432                   len, 
433                   0, 
434                   from, 
435                   fromlen);
436 }
437
438 /**
439  * Wrapper for select(2)
440  */
441
442 int
443 olsr_select(int nfds,
444             fd_set *readfds,
445             fd_set *writefds,
446             fd_set *exceptfds,
447             struct timeval *timeout)
448 {
449   return select(nfds,
450                 readfds,
451                 writefds,
452                 exceptfds,
453                 timeout);
454 }