Use two sockets, one for input and one for output bound to the outgoing IP.
[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 #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 #include "ipcalc.h"
59
60 #if defined WINCE
61 #define WIDE_STRING(s) L##s
62 #else
63 #define WIDE_STRING(s) TEXT(s)
64 #endif
65
66 void WinSockPError(const char *Str);
67 void PError(const char *);
68
69 void DisableIcmpRedirects(void);
70 int disable_ip_forwarding(int Ver);
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     perror("hcsocket");
81     return (-1);
82   }
83
84   /* connect to PORT on HOST */
85   if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) {
86     printf("FAILED\n");
87     fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
88     printf("connection refused\n");
89     closesocket(sock);
90     return (-1);
91   }
92
93   printf("OK\n");
94
95   /* Keep TCP socket blocking */
96   return (sock);
97 }
98
99 int
100 getsocket(int BuffSize, struct interface *ifp __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     WinSockPError("getsocket/socket()");
108     return -1;
109   }
110
111   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
112     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
113     closesocket(Sock);
114     return -1;
115   }
116
117   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
118     WinSockPError("getsocket/setsockopt(SO_REUSEADDR)");
119     closesocket(Sock);
120     return -1;
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     fprintf(stderr, "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(olsr_cnf->olsrport);
136
137   if(bufspace <= 0) {
138     sin.sin_addr.s_addr = ifp->int_addr.sin_addr.s_addr;
139   }
140
141   if (bind(Sock, (struct sockaddr *)&Addr, sizeof(Addr)) < 0) {
142     WinSockPError("getsocket/bind()");
143     closesocket(Sock);
144     return -1;
145   }
146
147   if (WSAIoctl(Sock, FIONBIO, &On, sizeof(On), NULL, 0, &Len, NULL, NULL) < 0) {
148     WinSockPError("WSAIoctl");
149     closesocket(Sock);
150     return -1;
151   }
152
153   return Sock;
154 }
155
156 int
157 getsocket6(int BuffSize, struct interface *ifp __attribute__ ((unused)))
158 {
159   struct sockaddr_in6 Addr6;
160   int On = 1;
161   int Sock = socket(AF_INET6, SOCK_DGRAM, 0);
162   if (Sock < 0) {
163     WinSockPError("getsocket6/socket()");
164     return -1;
165   }
166
167   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char *)&On, sizeof(On)) < 0) {
168     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
169     closesocket(Sock);
170     return -1;
171   }
172
173   if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char *)&On, sizeof(On)) < 0) {
174     WinSockPError("getsocket6/setsockopt(SO_REUSEADDR)");
175     closesocket(Sock);
176     return -1;
177   }
178
179   while (BuffSize > 8192) {
180     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize, sizeof(BuffSize)) == 0)
181       break;
182
183     BuffSize -= 1024;
184   }
185
186   if (BuffSize <= 8192)
187     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
188
189   memset(&Addr6, 0, sizeof(Addr6));
190   Addr6.sin6_family = AF_INET6;
191   Addr6.sin6_port = htons(olsr_cnf->olsrport);
192
193   if(bufspace <= 0) {
194     memcpy(&Addr6.sin6_addr, &ifp->int6_addr.sin6_addr, sizeof(struct in6_addr));
195   }
196
197   if (bind(Sock, (struct sockaddr *)&Addr6, sizeof(Addr6)) < 0) {
198     WinSockPError("getsocket6/bind()");
199     closesocket(Sock);
200     return -1;
201   }
202
203   return Sock;
204 }
205
206 static OVERLAPPED RouterOver;
207
208 int
209 enable_ip_forwarding(int Ver)
210 {
211   HMODULE Lib;
212   unsigned int __stdcall(*enable_router)(HANDLE *, OVERLAPPED *);
213   HANDLE Hand;
214
215   Ver = Ver;
216
217   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
218
219   if (Lib == NULL)
220     return 0;
221
222   enable_router = (unsigned int __stdcall(*)(HANDLE *, OVERLAPPED *))GetProcAddress(Lib, WIDE_STRING("EnableRouter"));
223
224   if (enable_router == NULL)
225     return 0;
226
227   memset(&RouterOver, 0, sizeof(OVERLAPPED));
228
229   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
230
231   if (RouterOver.hEvent == NULL) {
232     PError("CreateEvent()");
233     return -1;
234   }
235
236   if (enable_router(&Hand, &RouterOver) != ERROR_IO_PENDING) {
237     PError("EnableRouter()");
238     return -1;
239   }
240
241   OLSR_PRINTF(3, "Routing enabled.\n");
242
243   return 0;
244 }
245
246 int
247 disable_ip_forwarding(int Ver)
248 {
249   HMODULE Lib;
250   unsigned int __stdcall(*unenable_router)(OVERLAPPED *, unsigned int *);
251   unsigned int Count;
252
253   Ver = Ver;
254
255   Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
256
257   if (Lib == NULL)
258     return 0;
259
260   unenable_router = (unsigned int __stdcall(*)(OVERLAPPED *, unsigned int *))GetProcAddress(Lib, WIDE_STRING("UnenableRouter"));
261
262   if (unenable_router == NULL)
263     return 0;
264
265   if (unenable_router(&RouterOver, &Count) != NO_ERROR) {
266     PError("UnenableRouter()");
267     return -1;
268   }
269
270   OLSR_PRINTF(3, "Routing disabled, count = %u.\n", Count);
271
272   return 0;
273 }
274
275 int
276 restore_settings(int Ver)
277 {
278   disable_ip_forwarding(Ver);
279
280   return 0;
281 }
282
283 static int
284 SetEnableRedirKey(unsigned long New)
285 {
286 #if !defined WINCE
287   HKEY Key;
288   unsigned long Type;
289   unsigned long Len;
290   unsigned long Old;
291
292   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ | KEY_WRITE, &Key) !=
293       ERROR_SUCCESS)
294     return -1;
295
296   Len = sizeof(Old);
297
298   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type, (unsigned char *)&Old, &Len) != ERROR_SUCCESS || Type != REG_DWORD)
299     Old = 1;
300
301   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD, (unsigned char *)&New, sizeof(New))) {
302     RegCloseKey(Key);
303     return -1;
304   }
305
306   RegCloseKey(Key);
307   return Old;
308 #else
309   return 0;
310 #endif
311 }
312
313 void
314 DisableIcmpRedirects(void)
315 {
316   int Res;
317
318   Res = SetEnableRedirKey(0);
319
320   if (Res != 1)
321     return;
322
323   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
324
325 #if 0
326   if (Res < 0) {
327     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
328     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
329     Sleep(3000);
330
331     return;
332   }
333 #endif
334
335   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
336   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
337
338   exit(0);
339 }
340
341 int
342 join_mcast(struct interface *Nic, int Sock)
343 {
344   /* See linux/in6.h */
345   struct ipaddr_str buf;
346   struct ipv6_mreq McastReq;
347
348   McastReq.ipv6mr_multiaddr = Nic->int6_multaddr.sin6_addr;
349   McastReq.ipv6mr_interface = Nic->if_index;
350
351   OLSR_PRINTF(3, "Interface %s joining multicast %s...", Nic->int_name,
352               olsr_ip_to_string(&buf, (union olsr_ip_addr *)&Nic->int6_multaddr.sin6_addr));
353   /* Send multicast */
354   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0) {
355     perror("Join multicast");
356     return -1;
357   }
358
359   /* Old libc fix */
360 #ifdef IPV6_JOIN_GROUP
361   /* Join reciever group */
362   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0)
363 #else
364   /* Join reciever group */
365   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&McastReq, sizeof(struct ipv6_mreq)) < 0)
366 #endif
367   {
368     perror("Join multicast send");
369     return -1;
370   }
371
372   if (setsockopt(Sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&McastReq.ipv6mr_interface, sizeof(McastReq.ipv6mr_interface)) < 0) {
373     perror("Set multicast if");
374     return -1;
375   }
376
377   OLSR_PRINTF(3, "OK\n");
378   return 0;
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  * Wrapper for recvfrom(2)
393  */
394
395 ssize_t
396 olsr_recvfrom(int s, void *buf, size_t len, int flags __attribute__ ((unused)), struct sockaddr * from, socklen_t * fromlen)
397 {
398   return recvfrom(s, buf, len, 0, from, fromlen);
399 }
400
401 /**
402  * Wrapper for select(2)
403  */
404
405 int
406 olsr_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
407 {
408   return select(nfds, readfds, writefds, exceptfds, timeout);
409 }
410
411 /*
412  * Local Variables:
413  * c-basic-offset: 2
414  * indent-tabs-mode: nil
415  * End:
416  */