Disable ICMP redirect processing.
[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.6 2004/11/17 16:54:41 tlopatic Exp $
25  *
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #define WIN32_LEAN_AND_MEAN
32 #include <windows.h>
33 #include <winsock2.h>
34 #include <ws2tcpip.h>
35 #include <iphlpapi.h>
36 #undef interface
37
38 void WinSockPError(char *Str);
39 void PError(char *);
40
41 int olsr_printf(int, char *, ...);
42
43 int getsocket(struct sockaddr *Addr, int BuffSize, char *Int)
44 {
45   int Sock;
46   int On = 1;
47   unsigned long Len;
48
49   Sock = socket(AF_INET, SOCK_DGRAM, 0);
50
51   if (Sock < 0)
52   {
53     WinSockPError("getsocket/socket()");
54     return -1;
55   }
56
57   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
58                  (char *)&On, sizeof (On)) < 0)
59   {
60     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
61     closesocket(Sock);
62     return -1;
63   }
64
65   while (BuffSize > 8192)
66   {
67     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
68                    sizeof (BuffSize)) == 0)
69       break;
70
71     BuffSize -= 1024;
72   }
73
74   if (BuffSize <= 8192) 
75     fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
76
77   if (bind(Sock, Addr, sizeof (struct sockaddr_in)) < 0)
78   {
79     WinSockPError("getsocket/bind()");
80     closesocket(Sock);
81     return -1;
82   }
83
84   if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
85   {
86     WinSockPError("WSAIoctl");
87     closesocket(Sock);
88     return -1;
89   }
90
91   return Sock;
92 }
93
94 int getsocket6(struct sockaddr_in6 *Addr, int BuffSize, char *Int)
95 {
96   int Sock;
97   int On = 1;
98
99   Sock = socket(AF_INET6, SOCK_DGRAM, 0);
100
101   if (Sock < 0)
102   {
103     WinSockPError("getsocket6/socket()");
104     return -1;
105   }
106
107   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
108                  (char *)&On, sizeof (On)) < 0)
109   {
110     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
111     closesocket(Sock);
112     return -1;
113   }
114
115   while (BuffSize > 8192)
116   {
117     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
118                    sizeof (BuffSize)) == 0)
119       break;
120
121     BuffSize -= 1024;
122   }
123
124   if (BuffSize <= 8192) 
125     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
126
127   if (bind(Sock, (struct sockaddr *)Addr, sizeof (struct sockaddr_in6)) < 0)
128   {
129     WinSockPError("getsocket6/bind()");
130     closesocket(Sock);
131     return -1;
132   }
133
134   return Sock;
135 }
136
137 static OVERLAPPED RouterOver;
138
139 int enable_ip_forwarding(int Ver)
140 {
141   HMODULE Lib;
142   unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
143   HANDLE Hand;
144
145   Ver = Ver;
146   
147   Lib = LoadLibrary("iphlpapi.dll");
148
149   if (Lib == NULL)
150     return 0;
151
152   EnableRouter = (unsigned int _stdcall (*)(HANDLE *, OVERLAPPED *))
153     GetProcAddress(Lib, "EnableRouter");
154
155   if (EnableRouter == NULL)
156     return 0;
157
158   memset(&RouterOver, 0, sizeof (OVERLAPPED));
159
160   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
161
162   if (RouterOver.hEvent == NULL)
163   {
164     PError("CreateEvent()");
165     return -1;
166   }
167   
168   if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
169   {
170     PError("EnableRouter()");
171     return -1;
172   }
173
174   olsr_printf(3, "Routing enabled.\n");
175
176   return 0;
177 }
178
179 int disable_ip_forwarding(int Ver)
180 {
181   HMODULE Lib;
182   unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
183                                             unsigned int *Count);
184   unsigned int Count;
185
186   Ver = Ver;
187   
188   Lib = LoadLibrary("iphlpapi.dll");
189
190   if (Lib == NULL)
191     return 0;
192
193   UnenableRouter = (unsigned int _stdcall (*)(OVERLAPPED *, unsigned int *))
194     GetProcAddress(Lib, "UnenableRouter");
195
196   if (UnenableRouter == NULL)
197     return 0;
198
199   if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
200   {
201     PError("UnenableRouter()");
202     return -1;
203   }
204
205   olsr_printf(3, "Routing disabled, count = %u.\n", Count);
206
207   return 0;
208 }
209
210 int restore_settings(int Ver)
211 {
212   disable_ip_forwarding(Ver);
213
214   return 0;
215 }
216
217 static int SetEnableRedirKey(unsigned long New)
218 {
219   HKEY Key;
220   unsigned long Type;
221   unsigned long Len;
222   unsigned long Old;
223
224   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
225                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
226                    0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
227     return -1;
228
229   Len = sizeof (Old);
230
231   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
232                       (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
233       Type != REG_DWORD)
234   {
235     RegCloseKey(Key);
236     return -1;
237   }
238
239   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
240                     (unsigned char *)&New, sizeof (New)))
241   {
242     RegCloseKey(Key);
243     return -1;
244   }
245
246   RegCloseKey(Key);
247   return Old;
248 }
249
250 void DisableIcmpRedirects(void)
251 {
252   int Res;
253
254   Res = SetEnableRedirKey(0);
255
256   if (Res == 0)
257     return;
258
259   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
260
261   if (Res < 0)
262   {
263     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
264     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
265     Sleep(3000);
266
267     return;
268   }
269
270   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
271   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
272
273   exit(0);
274 }