Rename 'struct interface' to 'struct interface_olsr'
[olsrd.git] / src / win32 / net.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon (olsrd)
4  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
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 #ifdef _WIN32
43
44 #if defined WINCE
45 #include <sys/types.h>          // for time_t
46 #endif /* defined WINCE */
47
48 #define WIN32_LEAN_AND_MEAN
49 #include <windows.h>
50 #include <winsock2.h>
51 #include <ws2tcpip.h>
52 #include <iphlpapi.h>
53 #undef interface
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include "defs.h"
58 #include "net_os.h"
59 #include "net_olsr.h"
60 #include "ipcalc.h"
61
62 #if defined WINCE
63 #define WIDE_STRING(s) L##s
64 #else /* defined WINCE */
65 #define WIDE_STRING(s) TEXT(s)
66 #endif /* defined WINCE */
67
68 void WinSockPError(const char *Str);
69 void PError(const char *);
70
71 void DisableIcmpRedirects(void);
72
73 int
74 gethemusocket(struct sockaddr_in *pin)
75 {
76   int sock;
77
78   OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
79
80   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
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     printf("FAILED\n");
88     fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
89     printf("connection refused\n");
90     closesocket(sock);
91     return (-1);
92   }
93
94   printf("OK\n");
95
96   /* Keep TCP socket blocking */
97   return (sock);
98 }
99
100 int
101 getsocket(int bufspace, struct interface_olsr *ifp __attribute__ ((unused)))
102 {
103   struct sockaddr_in Addr;
104   int On = 1;
105   unsigned long Len;
106   int Sock = socket(AF_INET, SOCK_DGRAM, 0);
107   if (Sock < 0) {
108     WinSockPError("getsocket/socket()");
109     return -1;
110   }
111
112   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
113     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
114     closesocket(Sock);
115     return -1;
116   }
117
118   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
119     WinSockPError("getsocket/setsockopt(SO_REUSEADDR)");
120     closesocket(Sock);
121     return -1;
122   }
123
124   while (bufspace > 8192) {
125     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufspace, sizeof(bufspace)) == 0)
126       break;
127
128     bufspace -= 1024;
129   }
130
131   if (bufspace <= 8192) {
132     OLSR_PRINTF(1, "Cannot set IPv4 socket receive buffer.\n");
133   }
134   memset(&Addr, 0, sizeof(Addr));
135   Addr.sin_family = AF_INET;
136   Addr.sin_port = htons(olsr_cnf->olsrport);
137
138   if(bufspace <= 0) {
139     Addr.sin_addr.s_addr = ifp->int_addr.sin_addr.s_addr;
140   }
141
142   if (bind(Sock, (struct sockaddr *)&Addr, sizeof(Addr)) < 0) {
143     WinSockPError("getsocket/bind()");
144     closesocket(Sock);
145     return -1;
146   }
147
148   if (WSAIoctl(Sock, FIONBIO, &On, sizeof(On), NULL, 0, &Len, NULL, NULL) < 0) {
149     WinSockPError("WSAIoctl");
150     closesocket(Sock);
151     return -1;
152   }
153
154   return Sock;
155 }
156
157 int
158 getsocket6(int bufspace, struct interface_olsr *ifp __attribute__ ((unused)))
159 {
160   struct sockaddr_in6 Addr6;
161   int On = 1;
162   int Sock = socket(AF_INET6, SOCK_DGRAM, 0);
163   if (Sock < 0) {
164     WinSockPError("getsocket6/socket()");
165     return -1;
166   }
167
168   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
169     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
170     closesocket(Sock);
171     return -1;
172   }
173
174   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
175     WinSockPError("getsocket6/setsockopt(SO_REUSEADDR)");
176     closesocket(Sock);
177     return -1;
178   }
179
180   while (bufspace > 8192) {
181     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufspace, sizeof(bufspace)) == 0)
182       break;
183
184     bufspace -= 1024;
185   }
186
187   if (bufspace <= 8192)
188     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
189
190   memset(&Addr6, 0, sizeof(Addr6));
191   Addr6.sin6_family = AF_INET6;
192   Addr6.sin6_port = htons(olsr_cnf->olsrport);
193
194   if(bufspace <= 0) {
195     memcpy(&Addr6.sin6_addr, &ifp->int6_addr.sin6_addr, sizeof(struct in6_addr));
196   }
197
198   if (bind(Sock, (struct sockaddr *)&Addr6, sizeof(Addr6)) < 0) {
199     WinSockPError("getsocket6/bind()");
200     closesocket(Sock);
201     return -1;
202   }
203
204   return Sock;
205 }
206
207 static OVERLAPPED RouterOver;
208
209 void net_os_set_global_ifoptions(void)
210 {
211   HMODULE Lib;
212   unsigned int __stdcall(*enable_router)(HANDLE *, OVERLAPPED *);
213   HANDLE Hand;
214
215   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
216
217   if (Lib == NULL)
218     return;
219
220   enable_router = (unsigned int __stdcall(*)(HANDLE *, OVERLAPPED *))GetProcAddress(Lib, WIDE_STRING("EnableRouter"));
221
222   if (enable_router == NULL)
223     return;
224
225   memset(&RouterOver, 0, sizeof(OVERLAPPED));
226
227   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
228
229   if (RouterOver.hEvent == NULL) {
230     PError("CreateEvent()");
231     return;
232   }
233
234   if (enable_router(&Hand, &RouterOver) != ERROR_IO_PENDING) {
235     PError("EnableRouter()");
236     return;
237   }
238
239   OLSR_PRINTF(3, "Routing enabled.\n");
240
241   return;
242 }
243
244 static int
245 disable_ip_forwarding(int Ver)
246 {
247   HMODULE Lib;
248   unsigned int __stdcall(*unenable_router)(OVERLAPPED *, unsigned int *);
249   unsigned int Count;
250
251   Ver = Ver;
252
253   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
254
255   if (Lib == NULL)
256     return 0;
257
258   unenable_router = (unsigned int __stdcall(*)(OVERLAPPED *, unsigned int *))GetProcAddress(Lib, WIDE_STRING("UnenableRouter"));
259
260   if (unenable_router == NULL)
261     return 0;
262
263   if (unenable_router(&RouterOver, &Count) != NO_ERROR) {
264     PError("UnenableRouter()");
265     return -1;
266   }
267
268   OLSR_PRINTF(3, "Routing disabled, count = %u.\n", Count);
269
270   return 0;
271 }
272
273
274 int
275 net_os_restore_ifoptions(void)
276 {
277   disable_ip_forwarding(olsr_cnf->ip_version);
278
279   return 0;
280 }
281
282 static int
283 SetEnableRedirKey(unsigned long New)
284 {
285 #if !defined WINCE
286   HKEY Key;
287   unsigned long Type;
288   unsigned long Len;
289   unsigned long Old;
290
291   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ | KEY_WRITE, &Key) !=
292       ERROR_SUCCESS)
293     return -1;
294
295   Len = sizeof(Old);
296
297   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type, (unsigned char *)&Old, &Len) != ERROR_SUCCESS || Type != REG_DWORD)
298     Old = 1;
299
300   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD, (unsigned char *)&New, sizeof(New))) {
301     RegCloseKey(Key);
302     return -1;
303   }
304
305   RegCloseKey(Key);
306   return Old;
307 #else /* !defined WINCE */
308   return 0;
309 #endif /* !defined WINCE */
310 }
311
312 void
313 DisableIcmpRedirects(void)
314 {
315   int Res;
316
317   Res = SetEnableRedirKey(0);
318
319   if (Res != 1)
320     return;
321
322   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
323
324   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
325   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
326
327   exit(0);
328 }
329
330 int
331 join_mcast(struct interface_olsr *Nic, int Sock)
332 {
333   /* See linux/in6.h */
334   struct ipaddr_str buf;
335   struct ipv6_mreq McastReq;
336
337   McastReq.ipv6mr_multiaddr = Nic->int6_multaddr.sin6_addr;
338   McastReq.ipv6mr_interface = Nic->if_index;
339
340   OLSR_PRINTF(3, "Interface %s joining multicast %s...", Nic->int_name,
341               olsr_ip_to_string(&buf, (union olsr_ip_addr *)&Nic->int6_multaddr.sin6_addr));
342   /* Send multicast */
343   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0) {
344     perror("Join multicast");
345     return -1;
346   }
347
348   /* Old libc fix */
349 #ifdef IPV6_JOIN_GROUP
350   /* Join receiver group */
351   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0)
352 #else /* IPV6_JOIN_GROUP */
353   /* Join receiver group */
354   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0)
355 #endif /* IPV6_JOIN_GROUP */
356   {
357     perror("Join multicast send");
358     return -1;
359   }
360
361   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&McastReq.ipv6mr_interface, sizeof(McastReq.ipv6mr_interface)) < 0) {
362     perror("Set multicast if");
363     return -1;
364   }
365
366   OLSR_PRINTF(3, "OK\n");
367   return 0;
368 }
369
370 /**
371  * Wrapper for sendto(2)
372  */
373
374 ssize_t
375 olsr_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr * to, socklen_t tolen)
376 {
377   return sendto(s, buf, len, flags, to, tolen);
378 }
379
380 /**
381  * Wrapper for recvfrom(2)
382  */
383
384 ssize_t
385 olsr_recvfrom(int s, void *buf, size_t len, int flags __attribute__ ((unused)), struct sockaddr * from, socklen_t * fromlen)
386 {
387   return recvfrom(s, buf, len, 0, from, fromlen);
388 }
389
390 /**
391  * Wrapper for select(2)
392  */
393
394 int
395 olsr_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
396 {
397 #ifdef _WIN32
398   if (nfds == 0) {
399     if (timeout) {
400       Sleep(timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
401     }
402     return 0;
403   }
404   else {
405     return select(nfds, readfds, writefds, exceptfds, timeout);
406   }
407 #else /* _WIN32 */
408   return select(nfds, readfds, writefds, exceptfds, timeout);
409 #endif /* _WIN32 */
410 }
411
412 #endif /* _WIN32 */
413
414 /*
415  * Local Variables:
416  * c-basic-offset: 2
417  * indent-tabs-mode: nil
418  * End:
419  */