4c1ddfa487e235b42f897ea67e39c80b7db034f6
[olsrd.git] / src / win32 / net.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: net.c,v 1.12 2005/02/12 23:07:02 spoggle Exp $
40  */
41
42 #define WIN32_LEAN_AND_MEAN
43 #include <windows.h>
44 #include <winsock2.h>
45 #include <ws2tcpip.h>
46 #include <iphlpapi.h>
47 #undef interface
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include "../defs.h"
52 #include "../net_os.h"
53
54 void WinSockPError(char *Str);
55 void PError(char *);
56
57 int olsr_printf(int, char *, ...);
58
59 void DisableIcmpRedirects(void);
60 int disable_ip_forwarding(int Ver);
61
62 int getsocket(struct sockaddr *Addr, int BuffSize, char *Int)
63 {
64   int Sock;
65   int On = 1;
66   unsigned long Len;
67
68   Sock = socket(AF_INET, SOCK_DGRAM, 0);
69
70   if (Sock < 0)
71   {
72     WinSockPError("getsocket/socket()");
73     return -1;
74   }
75
76   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
77                  (char *)&On, sizeof (On)) < 0)
78   {
79     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
80     closesocket(Sock);
81     return -1;
82   }
83
84   while (BuffSize > 8192)
85   {
86     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
87                    sizeof (BuffSize)) == 0)
88       break;
89
90     BuffSize -= 1024;
91   }
92
93   if (BuffSize <= 8192) 
94     fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
95
96   if (bind(Sock, Addr, sizeof (struct sockaddr_in)) < 0)
97   {
98     WinSockPError("getsocket/bind()");
99     closesocket(Sock);
100     return -1;
101   }
102
103   if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
104   {
105     WinSockPError("WSAIoctl");
106     closesocket(Sock);
107     return -1;
108   }
109
110   return Sock;
111 }
112
113 int getsocket6(struct sockaddr_in6 *Addr, int BuffSize, char *Int)
114 {
115   int Sock;
116   int On = 1;
117
118   Sock = socket(AF_INET6, SOCK_DGRAM, 0);
119
120   if (Sock < 0)
121   {
122     WinSockPError("getsocket6/socket()");
123     return -1;
124   }
125
126   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
127                  (char *)&On, sizeof (On)) < 0)
128   {
129     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
130     closesocket(Sock);
131     return -1;
132   }
133
134   while (BuffSize > 8192)
135   {
136     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
137                    sizeof (BuffSize)) == 0)
138       break;
139
140     BuffSize -= 1024;
141   }
142
143   if (BuffSize <= 8192) 
144     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
145
146   if (bind(Sock, (struct sockaddr *)Addr, sizeof (struct sockaddr_in6)) < 0)
147   {
148     WinSockPError("getsocket6/bind()");
149     closesocket(Sock);
150     return -1;
151   }
152
153   return Sock;
154 }
155
156 static OVERLAPPED RouterOver;
157
158 int enable_ip_forwarding(int Ver)
159 {
160   HMODULE Lib;
161   unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
162   HANDLE Hand;
163
164   Ver = Ver;
165   
166   Lib = LoadLibrary("iphlpapi.dll");
167
168   if (Lib == NULL)
169     return 0;
170
171   EnableRouter = (unsigned int _stdcall (*)(HANDLE *, OVERLAPPED *))
172     GetProcAddress(Lib, "EnableRouter");
173
174   if (EnableRouter == NULL)
175     return 0;
176
177   memset(&RouterOver, 0, sizeof (OVERLAPPED));
178
179   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
180
181   if (RouterOver.hEvent == NULL)
182   {
183     PError("CreateEvent()");
184     return -1;
185   }
186   
187   if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
188   {
189     PError("EnableRouter()");
190     return -1;
191   }
192
193   olsr_printf(3, "Routing enabled.\n");
194
195   return 0;
196 }
197
198 int disable_ip_forwarding(int Ver)
199 {
200   HMODULE Lib;
201   unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
202                                             unsigned int *Count);
203   unsigned int Count;
204
205   Ver = Ver;
206   
207   Lib = LoadLibrary("iphlpapi.dll");
208
209   if (Lib == NULL)
210     return 0;
211
212   UnenableRouter = (unsigned int _stdcall (*)(OVERLAPPED *, unsigned int *))
213     GetProcAddress(Lib, "UnenableRouter");
214
215   if (UnenableRouter == NULL)
216     return 0;
217
218   if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
219   {
220     PError("UnenableRouter()");
221     return -1;
222   }
223
224   olsr_printf(3, "Routing disabled, count = %u.\n", Count);
225
226   return 0;
227 }
228
229 int restore_settings(int Ver)
230 {
231   disable_ip_forwarding(Ver);
232
233   return 0;
234 }
235
236 static int SetEnableRedirKey(unsigned long New)
237 {
238   HKEY Key;
239   unsigned long Type;
240   unsigned long Len;
241   unsigned long Old;
242
243   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
244                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
245                    0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
246     return -1;
247
248   Len = sizeof (Old);
249
250   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
251                       (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
252       Type != REG_DWORD)
253     Old = 1;
254
255   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
256                     (unsigned char *)&New, sizeof (New)))
257   {
258     RegCloseKey(Key);
259     return -1;
260   }
261
262   RegCloseKey(Key);
263   return Old;
264 }
265
266 void DisableIcmpRedirects(void)
267 {
268   int Res;
269
270   Res = SetEnableRedirKey(0);
271
272   if (Res != 1)
273     return;
274
275   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
276
277 #if 0
278   if (Res < 0)
279   {
280     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
281     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
282     Sleep(3000);
283
284     return;
285   }
286 #endif
287
288   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
289   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
290
291   exit(0);
292 }
293
294 /* ======== moved from above ======== */
295
296 extern struct olsr_netbuf *netbufs[];
297
298 /**
299  *Sends a packet on a given interface.
300  *
301  *@param ifp the interface to send on.
302  *
303  *@return negative on error
304  */
305 int
306 net_output(struct interface *ifp)
307 {
308   struct sockaddr_in *sin;  
309   struct sockaddr_in dst;
310   struct sockaddr_in6 *sin6;  
311   struct sockaddr_in6 dst6;
312   struct ptf *tmp_ptf_list;
313   int i, x;
314   union olsr_packet *outmsg;
315
316   sin = NULL;
317   sin6 = NULL;
318
319   if(!netbufs[ifp->if_nr])
320     return -1;
321
322   if(!netbufs[ifp->if_nr]->pending)
323     return 0;
324
325   netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
326
327   outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
328   /* Add the Packet seqno */
329   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
330   /* Set the packetlength */
331   outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
332
333   if(olsr_cnf->ip_version == AF_INET)
334     {
335       /* IP version 4 */
336       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
337
338       /* Copy sin */
339       dst = *sin;
340       sin = &dst;
341
342       if (sin->sin_port == 0)
343         sin->sin_port = olsr_udp_port;
344     }
345   else
346     {
347       /* IP version 6 */
348       sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
349       /* Copy sin */
350       dst6 = *sin6;
351       sin6 = &dst6;
352     }
353
354   /*
355    *Call possible packet transform functions registered by plugins  
356    */
357   tmp_ptf_list = ptf_list;
358   while(tmp_ptf_list != NULL)
359     {
360       tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
361       tmp_ptf_list = tmp_ptf_list->next;
362     }
363
364   /*
365    *if the '-disp- option was given
366    *we print her decimal contetnt of the packets
367    */
368   if(disp_pack_out)
369     {
370       switch(netbufs[ifp->if_nr]->buff[4])
371         {
372         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
373         case(TC_MESSAGE):printf("\n\tTC ");break;
374         case(MID_MESSAGE):printf("\n\tMID ");break;
375         case(HNA_MESSAGE):printf("\n\tHNA ");break;
376         default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
377         }
378       if(olsr_cnf->ip_version == AF_INET)
379         printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
380       else
381         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
382
383       x = 0;
384
385       for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
386         {
387           if(x == 4)
388             {
389               x = 0;
390               printf("\n\t");
391             }
392           x++;
393           if(olsr_cnf->ip_version == AF_INET)
394             printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
395           else
396             printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
397         }
398       
399       printf("\n");
400     }
401   
402   if(olsr_cnf->ip_version == AF_INET)
403     {
404       /* IP version 4 */
405       if(sendto(ifp->olsr_socket, 
406                 netbufs[ifp->if_nr]->buff, 
407                 netbufs[ifp->if_nr]->pending, 
408                 MSG_DONTROUTE, 
409                 (struct sockaddr *)sin, 
410                 sizeof (*sin)) 
411          < 0)
412         {
413           perror("sendto(v4)");
414           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
415           netbufs[ifp->if_nr]->pending = 0;
416           return -1;
417         }
418     }
419   else
420     {
421       /* IP version 6 */
422       if(sendto(ifp->olsr_socket, 
423                 netbufs[ifp->if_nr]->buff,
424                 netbufs[ifp->if_nr]->pending, 
425                 MSG_DONTROUTE, 
426                 (struct sockaddr *)sin6, 
427                 sizeof (*sin6)) 
428          < 0)
429         {
430           perror("sendto(v6)");
431           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
432           fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
433           fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), (int)sizeof(*sin6));
434           fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
435           netbufs[ifp->if_nr]->pending = 0;
436           return -1;
437         }
438     }
439   
440   netbufs[ifp->if_nr]->pending = 0;
441
442   return 1;
443 }
444
445 /* The outputbuffer on neighbornodes
446  * will never exceed MAXMESSAGESIZE
447  */
448 static char inbuf[MAXMESSAGESIZE+1];
449
450 /**
451  *Processing OLSR data from socket. Reading data, setting 
452  *wich interface recieved the message, Sends IPC(if used) 
453  *and passes the packet on to parse_packet().
454  *
455  *@param fd the filedescriptor that data should be read from.
456  *@return nada
457  */
458 void
459 olsr_input(int fd)
460 {
461   /* sockaddr_in6 is bigger than sockaddr !!!! */
462   struct sockaddr_storage from;
463   size_t fromlen;
464   int cc;
465   struct interface *olsr_in_if;
466   union olsr_ip_addr from_addr;
467
468
469   for (;;) 
470     {
471       fromlen = sizeof(struct sockaddr_storage);
472
473       cc = recvfrom(fd, 
474                     inbuf, 
475                     sizeof (inbuf), 
476                     0, 
477                     (struct sockaddr *)&from, 
478                     &fromlen);
479
480       if (cc <= 0) 
481         {
482           if (cc < 0 && errno != EWOULDBLOCK)
483             {
484               olsr_printf(1, "error recvfrom: %s", strerror(errno));
485               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
486             }
487           break;
488         }
489
490       if(olsr_cnf->ip_version == AF_INET)
491         {
492           /* IPv4 sender address */
493           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
494         }
495       else
496         {
497           /* IPv6 sender address */
498           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
499         }
500
501       /* are we talking to ourselves? */
502       if(if_ifwithaddr(&from_addr) != NULL)
503         return;
504
505 #ifdef DEBUG
506       olsr_printf(5, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
507 #endif
508       //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
509       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
510         break;
511       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
512         break;
513
514       //printf("Recieved data on socket %d\n", socknr);
515
516
517       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
518         {
519           olsr_printf(1, "Could not find input interface for message from %s size %d\n",
520                       olsr_ip_to_string(&from_addr),
521                       cc);
522           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
523                  olsr_ip_to_string(&from_addr),
524                  cc);
525           return ;
526         }
527
528       /*
529        * &from - sender
530        * &inbuf.olsr 
531        * cc - bytes read
532        */
533       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
534     
535     }
536 }
537
538