Optimized get_best_link_to_neighbor(). Removed olsr_neighbor_best_link()
[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.13 2005/02/14 15:54:30 tlopatic 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 // XXX - really port I/O functions to Windows
55
56 #undef EWOULDBLOCK
57 #define EWOULDBLOCK WSAEWOULDBLOCK
58 #undef errno
59 #define errno WSAGetLastError()
60 #undef strerror
61 #define strerror(x) StrError(x)
62
63 void WinSockPError(char *Str);
64 void PError(char *);
65
66 int olsr_printf(int, char *, ...);
67
68 void DisableIcmpRedirects(void);
69 int disable_ip_forwarding(int Ver);
70
71 int getsocket(struct sockaddr *Addr, int BuffSize, char *Int)
72 {
73   int Sock;
74   int On = 1;
75   unsigned long Len;
76
77   Sock = socket(AF_INET, SOCK_DGRAM, 0);
78
79   if (Sock < 0)
80   {
81     WinSockPError("getsocket/socket()");
82     return -1;
83   }
84
85   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
86                  (char *)&On, sizeof (On)) < 0)
87   {
88     WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
89     closesocket(Sock);
90     return -1;
91   }
92
93   while (BuffSize > 8192)
94   {
95     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
96                    sizeof (BuffSize)) == 0)
97       break;
98
99     BuffSize -= 1024;
100   }
101
102   if (BuffSize <= 8192) 
103     fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
104
105   if (bind(Sock, Addr, sizeof (struct sockaddr_in)) < 0)
106   {
107     WinSockPError("getsocket/bind()");
108     closesocket(Sock);
109     return -1;
110   }
111
112   if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
113   {
114     WinSockPError("WSAIoctl");
115     closesocket(Sock);
116     return -1;
117   }
118
119   return Sock;
120 }
121
122 int getsocket6(struct sockaddr_in6 *Addr, int BuffSize, char *Int)
123 {
124   int Sock;
125   int On = 1;
126
127   Sock = socket(AF_INET6, SOCK_DGRAM, 0);
128
129   if (Sock < 0)
130   {
131     WinSockPError("getsocket6/socket()");
132     return -1;
133   }
134
135   if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
136                  (char *)&On, sizeof (On)) < 0)
137   {
138     WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
139     closesocket(Sock);
140     return -1;
141   }
142
143   while (BuffSize > 8192)
144   {
145     if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
146                    sizeof (BuffSize)) == 0)
147       break;
148
149     BuffSize -= 1024;
150   }
151
152   if (BuffSize <= 8192) 
153     fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
154
155   if (bind(Sock, (struct sockaddr *)Addr, sizeof (struct sockaddr_in6)) < 0)
156   {
157     WinSockPError("getsocket6/bind()");
158     closesocket(Sock);
159     return -1;
160   }
161
162   return Sock;
163 }
164
165 static OVERLAPPED RouterOver;
166
167 int enable_ip_forwarding(int Ver)
168 {
169   HMODULE Lib;
170   unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
171   HANDLE Hand;
172
173   Ver = Ver;
174   
175   Lib = LoadLibrary("iphlpapi.dll");
176
177   if (Lib == NULL)
178     return 0;
179
180   EnableRouter = (unsigned int _stdcall (*)(HANDLE *, OVERLAPPED *))
181     GetProcAddress(Lib, "EnableRouter");
182
183   if (EnableRouter == NULL)
184     return 0;
185
186   memset(&RouterOver, 0, sizeof (OVERLAPPED));
187
188   RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
189
190   if (RouterOver.hEvent == NULL)
191   {
192     PError("CreateEvent()");
193     return -1;
194   }
195   
196   if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
197   {
198     PError("EnableRouter()");
199     return -1;
200   }
201
202   olsr_printf(3, "Routing enabled.\n");
203
204   return 0;
205 }
206
207 int disable_ip_forwarding(int Ver)
208 {
209   HMODULE Lib;
210   unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
211                                             unsigned int *Count);
212   unsigned int Count;
213
214   Ver = Ver;
215   
216   Lib = LoadLibrary("iphlpapi.dll");
217
218   if (Lib == NULL)
219     return 0;
220
221   UnenableRouter = (unsigned int _stdcall (*)(OVERLAPPED *, unsigned int *))
222     GetProcAddress(Lib, "UnenableRouter");
223
224   if (UnenableRouter == NULL)
225     return 0;
226
227   if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
228   {
229     PError("UnenableRouter()");
230     return -1;
231   }
232
233   olsr_printf(3, "Routing disabled, count = %u.\n", Count);
234
235   return 0;
236 }
237
238 int restore_settings(int Ver)
239 {
240   disable_ip_forwarding(Ver);
241
242   return 0;
243 }
244
245 static int SetEnableRedirKey(unsigned long New)
246 {
247   HKEY Key;
248   unsigned long Type;
249   unsigned long Len;
250   unsigned long Old;
251
252   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
253                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
254                    0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
255     return -1;
256
257   Len = sizeof (Old);
258
259   if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
260                       (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
261       Type != REG_DWORD)
262     Old = 1;
263
264   if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
265                     (unsigned char *)&New, sizeof (New)))
266   {
267     RegCloseKey(Key);
268     return -1;
269   }
270
271   RegCloseKey(Key);
272   return Old;
273 }
274
275 void DisableIcmpRedirects(void)
276 {
277   int Res;
278
279   Res = SetEnableRedirKey(0);
280
281   if (Res != 1)
282     return;
283
284   fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
285
286 #if 0
287   if (Res < 0)
288   {
289     fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
290     fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
291     Sleep(3000);
292
293     return;
294   }
295 #endif
296
297   fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
298   fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
299
300   exit(0);
301 }
302
303 /* ======== moved from above ======== */
304
305 extern struct olsr_netbuf *netbufs[];
306
307 /**
308  *Sends a packet on a given interface.
309  *
310  *@param ifp the interface to send on.
311  *
312  *@return negative on error
313  */
314 int
315 net_output(struct interface *ifp)
316 {
317   struct sockaddr_in *sin;  
318   struct sockaddr_in dst;
319   struct sockaddr_in6 *sin6;  
320   struct sockaddr_in6 dst6;
321   struct ptf *tmp_ptf_list;
322   int i, x;
323   union olsr_packet *outmsg;
324
325   sin = NULL;
326   sin6 = NULL;
327
328   if(!netbufs[ifp->if_nr])
329     return -1;
330
331   if(!netbufs[ifp->if_nr]->pending)
332     return 0;
333
334   netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
335
336   outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
337   /* Add the Packet seqno */
338   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
339   /* Set the packetlength */
340   outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
341
342   if(olsr_cnf->ip_version == AF_INET)
343     {
344       /* IP version 4 */
345       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
346
347       /* Copy sin */
348       dst = *sin;
349       sin = &dst;
350
351       if (sin->sin_port == 0)
352         sin->sin_port = olsr_udp_port;
353     }
354   else
355     {
356       /* IP version 6 */
357       sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
358       /* Copy sin */
359       dst6 = *sin6;
360       sin6 = &dst6;
361     }
362
363   /*
364    *Call possible packet transform functions registered by plugins  
365    */
366   tmp_ptf_list = ptf_list;
367   while(tmp_ptf_list != NULL)
368     {
369       tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
370       tmp_ptf_list = tmp_ptf_list->next;
371     }
372
373   /*
374    *if the '-disp- option was given
375    *we print her decimal contetnt of the packets
376    */
377   if(disp_pack_out)
378     {
379       switch(netbufs[ifp->if_nr]->buff[4])
380         {
381         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
382         case(TC_MESSAGE):printf("\n\tTC ");break;
383         case(MID_MESSAGE):printf("\n\tMID ");break;
384         case(HNA_MESSAGE):printf("\n\tHNA ");break;
385         default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
386         }
387       if(olsr_cnf->ip_version == AF_INET)
388         printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
389       else
390         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
391
392       x = 0;
393
394       for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
395         {
396           if(x == 4)
397             {
398               x = 0;
399               printf("\n\t");
400             }
401           x++;
402           if(olsr_cnf->ip_version == AF_INET)
403             printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
404           else
405             printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
406         }
407       
408       printf("\n");
409     }
410   
411   if(olsr_cnf->ip_version == AF_INET)
412     {
413       /* IP version 4 */
414       if(sendto(ifp->olsr_socket, 
415                 netbufs[ifp->if_nr]->buff, 
416                 netbufs[ifp->if_nr]->pending, 
417                 MSG_DONTROUTE, 
418                 (struct sockaddr *)sin, 
419                 sizeof (*sin)) 
420          < 0)
421         {
422           perror("sendto(v4)");
423           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
424           netbufs[ifp->if_nr]->pending = 0;
425           return -1;
426         }
427     }
428   else
429     {
430       /* IP version 6 */
431       if(sendto(ifp->olsr_socket, 
432                 netbufs[ifp->if_nr]->buff,
433                 netbufs[ifp->if_nr]->pending, 
434                 MSG_DONTROUTE, 
435                 (struct sockaddr *)sin6, 
436                 sizeof (*sin6)) 
437          < 0)
438         {
439           perror("sendto(v6)");
440           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
441           fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
442           fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), (int)sizeof(*sin6));
443           fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
444           netbufs[ifp->if_nr]->pending = 0;
445           return -1;
446         }
447     }
448   
449   netbufs[ifp->if_nr]->pending = 0;
450
451   return 1;
452 }
453
454 /* The outputbuffer on neighbornodes
455  * will never exceed MAXMESSAGESIZE
456  */
457 static char inbuf[MAXMESSAGESIZE+1];
458
459 /**
460  *Processing OLSR data from socket. Reading data, setting 
461  *wich interface recieved the message, Sends IPC(if used) 
462  *and passes the packet on to parse_packet().
463  *
464  *@param fd the filedescriptor that data should be read from.
465  *@return nada
466  */
467 void
468 olsr_input(int fd)
469 {
470   /* sockaddr_in6 is bigger than sockaddr !!!! */
471   struct sockaddr_storage from;
472   size_t fromlen;
473   int cc;
474   struct interface *olsr_in_if;
475   union olsr_ip_addr from_addr;
476
477
478   for (;;) 
479     {
480       fromlen = sizeof(struct sockaddr_storage);
481
482       cc = recvfrom(fd, 
483                     inbuf, 
484                     sizeof (inbuf), 
485                     0, 
486                     (struct sockaddr *)&from, 
487                     &fromlen);
488
489       if (cc <= 0) 
490         {
491           if (cc < 0 && errno != EWOULDBLOCK)
492             {
493               olsr_printf(1, "error recvfrom: %s", strerror(errno));
494               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
495             }
496           break;
497         }
498
499       if(olsr_cnf->ip_version == AF_INET)
500         {
501           /* IPv4 sender address */
502           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
503         }
504       else
505         {
506           /* IPv6 sender address */
507           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
508         }
509
510       /* are we talking to ourselves? */
511       if(if_ifwithaddr(&from_addr) != NULL)
512         return;
513
514 #ifdef DEBUG
515       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));
516 #endif
517       //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
518       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
519         break;
520       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
521         break;
522
523       //printf("Recieved data on socket %d\n", socknr);
524
525
526       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
527         {
528           olsr_printf(1, "Could not find input interface for message from %s size %d\n",
529                       olsr_ip_to_string(&from_addr),
530                       cc);
531           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
532                  olsr_ip_to_string(&from_addr),
533                  cc);
534           return ;
535         }
536
537       /*
538        * &from - sender
539        * &inbuf.olsr 
540        * cc - bytes read
541        */
542       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
543     
544     }
545 }
546
547