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