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