4a59ec2cbba19c94c4ded94db5147aa104d2e7c5
[olsrd.git] / src / win32 / net.c
1 /* 
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
4  *
5  * Derived from its Linux counterpart.
6  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
7  *
8  * This file is part of the olsr.org OLSR daemon.
9  *
10  * olsr.org is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * olsr.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with olsr.org; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * $Id: net.c,v 1.9 2004/11/18 21:12:29 tlopatic Exp $
25  *
26  */
27
28 #define WIN32_LEAN_AND_MEAN
29 #include <windows.h>
30 #include <winsock2.h>
31 #include <ws2tcpip.h>
32 #include <iphlpapi.h>
33 #undef interface
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include "../defs.h"
38 #include "../net_os.h"
39
40 void WinSockPError(char *Str);
41 void PError(char *);
42
43 int olsr_printf(int, char *, ...);
44
45 void DisableIcmpRedirects(void);
46 int disable_ip_forwarding(int Ver);
47
48 int getsocket(struct sockaddr *Addr, int BuffSize, char *Int)
49 {
50   int Sock;
51   int On = 1;
52   unsigned long Len;
53
54   Sock = socket(AF_INET, SOCK_DGRAM, 0);
55
56   if (Sock < 0)
57   {
58     WinSockPError("getsocket/socket()");
59     return -1;
60   }
61
62   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
63                  (char *)&On, sizeof (On)) < 0)
64   {
65     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
66     closesocket(Sock);
67     return -1;
68   }
69
70   while (BuffSize > 8192)
71   {
72     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
73                    sizeof (BuffSize)) == 0)
74       break;
75
76     BuffSize -= 1024;
77   }
78
79   if (BuffSize <= 8192) 
80     fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
81
82   if (bind(Sock, Addr, sizeof (struct sockaddr_in)) < 0)
83   {
84     WinSockPError("getsocket/bind()");
85     closesocket(Sock);
86     return -1;
87   }
88
89   if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
90   {
91     WinSockPError("WSAIoctl");
92     closesocket(Sock);
93     return -1;
94   }
95
96   return Sock;
97 }
98
99 int getsocket6(struct sockaddr_in6 *Addr, int BuffSize, char *Int)
100 {
101   int Sock;
102   int On = 1;
103
104   Sock = socket(AF_INET6, SOCK_DGRAM, 0);
105
106   if (Sock < 0)
107   {
108     WinSockPError("getsocket6/socket()");
109     return -1;
110   }
111
112   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
113                  (char *)&On, sizeof (On)) < 0)
114   {
115     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
116     closesocket(Sock);
117     return -1;
118   }
119
120   while (BuffSize > 8192)
121   {
122     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
123                    sizeof (BuffSize)) == 0)
124       break;
125
126     BuffSize -= 1024;
127   }
128
129   if (BuffSize <= 8192) 
130     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
131
132   if (bind(Sock, (struct sockaddr *)Addr, sizeof (struct sockaddr_in6)) < 0)
133   {
134     WinSockPError("getsocket6/bind()");
135     closesocket(Sock);
136     return -1;
137   }
138
139   return Sock;
140 }
141
142 static OVERLAPPED RouterOver;
143
144 int enable_ip_forwarding(int Ver)
145 {
146   HMODULE Lib;
147   unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
148   HANDLE Hand;
149
150   Ver = Ver;
151   
152   Lib = LoadLibrary("iphlpapi.dll");
153
154   if (Lib == NULL)
155     return 0;
156
157   EnableRouter = (unsigned int _stdcall (*)(HANDLE *, OVERLAPPED *))
158     GetProcAddress(Lib, "EnableRouter");
159
160   if (EnableRouter == NULL)
161     return 0;
162
163   memset(&RouterOver, 0, sizeof (OVERLAPPED));
164
165   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
166
167   if (RouterOver.hEvent == NULL)
168   {
169     PError("CreateEvent()");
170     return -1;
171   }
172   
173   if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
174   {
175     PError("EnableRouter()");
176     return -1;
177   }
178
179   olsr_printf(3, "Routing enabled.\n");
180
181   return 0;
182 }
183
184 int disable_ip_forwarding(int Ver)
185 {
186   HMODULE Lib;
187   unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
188                                             unsigned int *Count);
189   unsigned int Count;
190
191   Ver = Ver;
192   
193   Lib = LoadLibrary("iphlpapi.dll");
194
195   if (Lib == NULL)
196     return 0;
197
198   UnenableRouter = (unsigned int _stdcall (*)(OVERLAPPED *, unsigned int *))
199     GetProcAddress(Lib, "UnenableRouter");
200
201   if (UnenableRouter == NULL)
202     return 0;
203
204   if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
205   {
206     PError("UnenableRouter()");
207     return -1;
208   }
209
210   olsr_printf(3, "Routing disabled, count = %u.\n", Count);
211
212   return 0;
213 }
214
215 int restore_settings(int Ver)
216 {
217   disable_ip_forwarding(Ver);
218
219   return 0;
220 }
221
222 static int SetEnableRedirKey(unsigned long New)
223 {
224   HKEY Key;
225   unsigned long Type;
226   unsigned long Len;
227   unsigned long Old;
228
229   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
230                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
231                    0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
232     return -1;
233
234   Len = sizeof (Old);
235
236   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
237                       (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
238       Type != REG_DWORD)
239     Old = 1;
240
241   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
242                     (unsigned char *)&New, sizeof (New)))
243   {
244     RegCloseKey(Key);
245     return -1;
246   }
247
248   RegCloseKey(Key);
249   return Old;
250 }
251
252 void DisableIcmpRedirects(void)
253 {
254   int Res;
255
256   Res = SetEnableRedirKey(0);
257
258   if (Res == 0)
259     return;
260
261   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
262
263   if (Res < 0)
264   {
265     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
266     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
267     Sleep(3000);
268
269     return;
270   }
271
272   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
273   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
274
275   exit(0);
276 }