* killed the MAX_IFS variable and another statically sized array
[olsrd.git] / src / linux / net.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
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.32 2007/02/04 23:36:35 bernd67 Exp $
40  */
41
42
43 /*
44  * Linux spesific code
45  */
46
47 #include "net.h"
48 #include "../defs.h"
49 #include "../net_os.h"
50 #include "../parser.h"
51
52
53 /*
54  *Wireless definitions for ioctl calls
55  *(from linux/wireless.h)
56  */
57 #define SIOCGIWNAME     0x8B01          /* get name == wireless protocol */
58 #define SIOCGIWRATE     0x8B21          /* get default bit rate (bps) */
59
60 /* The original state of the IP forwarding proc entry */
61 static char orig_fwd_state;
62 static char orig_global_redirect_state;
63
64 /**
65  *Bind a socket to a device
66  *
67  *@param sock the socket to bind
68  *@param dev_name name of the device
69  *
70  *@return negative if error
71  */
72
73 int
74 bind_socket_to_device(int sock, char *dev_name)
75 {
76   /*
77    *Bind to device using the SO_BINDTODEVICE flag
78    */
79   OLSR_PRINTF(3, "Binding socket %d to device %s\n", sock, dev_name)
80   return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name)+1);
81
82 }
83
84
85 /**
86  *Enable IP forwarding.
87  *Just writing "1" to the /proc/sys/net/ipv4/ip_forward
88  *if using IPv4 or /proc/sys/net/ipv6/conf/all/forwarding
89  *if using IPv6.
90  *Could probably drop the check for
91  *"0" here and write "1" anyways.
92  *
93  *@param version IP version.
94  *
95  *@return 1 on sucess 0 on failiure
96  */ 
97 int
98 enable_ip_forwarding(int version)
99 {
100   FILE *proc_fwd;
101   char procfile[FILENAME_MAX];
102
103   if(version == AF_INET)
104     {
105       strncpy(procfile, "/proc/sys/net/ipv4/ip_forward", FILENAME_MAX);
106     }
107   else
108     if(version == AF_INET6)
109       {
110         strncpy(procfile, "/proc/sys/net/ipv6/conf/all/forwarding", FILENAME_MAX);
111       }
112     else
113       return -1;
114
115
116   if ((proc_fwd=fopen(procfile, "r"))==NULL)
117     {
118       /* IPv4 */
119       if(version == AF_INET)
120         fprintf(stderr, "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n", procfile);
121       /* IPv6 */
122       else
123         fprintf(stderr, "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv6?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n", procfile);
124       
125       sleep(3);
126       return 0;
127     }
128   
129   else
130     {
131       orig_fwd_state = fgetc(proc_fwd);
132       fclose(proc_fwd);
133       if(orig_fwd_state == '1')
134         {
135           OLSR_PRINTF(3, "\nIP forwarding is enabled on this system\n")
136         }
137       else
138         {
139           if ((proc_fwd=fopen(procfile, "w"))==NULL)
140             {
141               fprintf(stderr, "Could not open %s for writing!\n", procfile);
142               fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n");
143               sleep(3);
144               return 0;
145             }
146           else
147             {
148               syslog(LOG_INFO, "Writing \"1\" to %s\n", procfile);
149               fputs("1", proc_fwd);
150             }
151           fclose(proc_fwd);
152
153         }
154     }
155   return 1;
156       
157 }
158
159
160 int
161 disable_redirects_global(int version)
162 {
163   FILE *proc_redirect;
164   char procfile[FILENAME_MAX];
165
166   if(version == AF_INET6)
167     return -1;
168
169   strcpy(procfile, "/proc/sys/net/ipv4/conf/all/send_redirects");
170
171   if((proc_redirect = fopen(procfile, "r")) == NULL)
172     {
173       fprintf(stderr, "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", procfile);
174       
175       sleep(3);
176       return -1;
177     }
178   else
179     {
180       orig_global_redirect_state = fgetc(proc_redirect);
181       fclose(proc_redirect);
182     }
183
184   if(orig_global_redirect_state == '0')
185     {
186       return 0;
187     }
188
189   if ((proc_redirect = fopen(procfile, "w"))==NULL)
190     {
191       fprintf(stderr, "Could not open %s for writing!\n", procfile);
192       fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
193       sleep(3);
194       return 0;
195     }
196   else
197     {
198       syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
199       fputs("0", proc_redirect);
200     }
201   fclose(proc_redirect);
202   
203   return 1;
204 }
205
206
207 /**
208  *
209  *@return 1 on sucess 0 on failiure
210  */ 
211 int
212 disable_redirects(const char *if_name, struct interface *iface, int version)
213 {
214   FILE *proc_redirect;
215   char procfile[FILENAME_MAX];
216
217   if(version == AF_INET6)
218     return -1;
219
220   /* Generate the procfile name */
221   sprintf(procfile, REDIRECT_PROC, if_name);
222
223
224   if((proc_redirect = fopen(procfile, "r")) == NULL)
225     {
226       fprintf(stderr, "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", procfile);
227       
228       sleep(3);
229       return 0;
230     }
231   else
232     {
233       iface->nic_state.redirect = fgetc(proc_redirect);
234       fclose(proc_redirect);
235       
236     }
237
238   if ((proc_redirect = fopen(procfile, "w"))==NULL)
239     {
240       fprintf(stderr, "Could not open %s for writing!\n", procfile);
241       fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
242       sleep(3);
243       return 0;
244     }
245   else
246     {
247       syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
248       fputs("0", proc_redirect);
249     }
250   fclose(proc_redirect);
251
252   return 1;
253 }
254
255
256
257 /**
258  *
259  *@return 1 on sucess 0 on failiure
260  */ 
261 int
262 deactivate_spoof(const char *if_name, struct interface *iface, int version)
263 {
264   FILE *proc_spoof;
265   char procfile[FILENAME_MAX];
266
267   if(version == AF_INET6)
268     return -1;
269
270
271   /* Generate the procfile name */
272   sprintf(procfile, SPOOF_PROC, if_name);
273
274
275   if((proc_spoof = fopen(procfile, "r")) == NULL)
276     {
277       fprintf(stderr, "WARNING! Could not open the %s file to check/disable the IP spoof filter!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabled!\n\n", procfile);
278       
279       sleep(3);
280       return 0;
281     }
282   else
283     {
284       iface->nic_state.spoof = fgetc(proc_spoof);
285       fclose(proc_spoof);
286       
287     }
288
289   if ((proc_spoof = fopen(procfile, "w")) == NULL)
290     {
291       fprintf(stderr, "Could not open %s for writing!\n", procfile);
292       fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabeled!\n\n");
293       sleep(3);
294       return 0;
295     }
296   else
297     {
298       syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
299       fputs("0", proc_spoof);
300     }
301   fclose(proc_spoof);
302
303   return 1;
304 }
305
306
307
308 /**
309  *Resets the spoof filter and ICMP redirect settings
310  */
311
312 int
313 restore_settings(int version)
314 {
315   FILE *proc_fd;
316   char procfile[FILENAME_MAX];
317   struct interface *ifs;
318
319   OLSR_PRINTF(1, "Restoring network state\n")
320
321   /* Restore IP forwarding to "off" */
322   if(orig_fwd_state == '0')
323     {
324       if(version == AF_INET)
325         {
326           strcpy(procfile, "/proc/sys/net/ipv4/ip_forward");
327         }
328       else if(version == AF_INET6)
329         {
330           strcpy(procfile, "/proc/sys/net/ipv6/conf/all/forwarding");
331         }
332
333       if ((proc_fd = fopen(procfile, "w")) == NULL)
334         {
335           fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
336         }
337       else
338         {
339           syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_fwd_state);
340           fputc(orig_fwd_state, proc_fd);
341           fclose(proc_fd);
342         }
343
344     }
345
346   /* Restore global ICMP redirect setting */
347   if(orig_global_redirect_state != '0')
348     {
349       if(version == AF_INET)
350         {
351           strcpy(procfile, "/proc/sys/net/ipv4/conf/all/send_redirects");
352
353           if ((proc_fd = fopen(procfile, "w")) == NULL)
354             {
355               fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
356             }
357           else
358             {
359               syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_global_redirect_state);
360               fputc(orig_global_redirect_state, proc_fd);
361               fclose(proc_fd);
362             }
363         }
364     }
365
366
367   if(version == AF_INET6)
368     return 0;
369
370   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
371     {
372       /* Discard host-emulation interfaces */
373       if(ifs->is_hcif)
374         continue;
375       /* ICMP redirects */
376       
377       /* Generate the procfile name */
378       sprintf(procfile, REDIRECT_PROC, ifs->int_name);
379       
380       if ((proc_fd = fopen(procfile, "w")) == NULL)
381         {
382           fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
383         }
384       else
385         {
386           syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.redirect);
387
388           fputc(ifs->nic_state.redirect, proc_fd);
389           fclose(proc_fd);
390         }
391
392       
393       /* Spoof filter */
394       
395       /* Generate the procfile name */
396       sprintf(procfile, SPOOF_PROC, ifs->int_name);
397
398       if ((proc_fd = fopen(procfile, "w")) == NULL)
399         {
400           fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
401         }
402       else
403         {
404           syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.spoof);
405
406           fputc(ifs->nic_state.spoof, proc_fd);
407           fclose(proc_fd);
408         }
409
410     }
411   return 1;
412
413 }
414
415
416 /**
417  *Creates a nonblocking broadcast socket.
418  *@param sa sockaddr struct. Used for bind(2).
419  *@return the FD of the socket or -1 on error.
420  */
421 int
422 gethemusocket(struct sockaddr_in *pin)
423 {
424   int sock, on = 1;
425
426   OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
427
428
429   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
430     {
431       perror("hcsocket");
432       syslog(LOG_ERR, "hcsocket: %m");
433       return (-1);
434     }
435
436   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
437     {
438       perror("SO_REUSEADDR failed");
439       close(sock);
440       return (-1);
441     }
442   /* connect to PORT on HOST */
443   if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
444     {
445       printf("FAILED\n");
446       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
447       printf("connection refused\n");
448       close(sock);
449       return (-1);
450     }
451
452   printf("OK\n");
453
454   /* Keep TCP socket blocking */  
455   return (sock);
456 }
457
458
459 /**
460  *Creates a nonblocking broadcast socket.
461  *@param sa sockaddr struct. Used for bind(2).
462  *@return the FD of the socket or -1 on error.
463  */
464 int
465 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
466 {
467   struct sockaddr_in *sin=(struct sockaddr_in *)sa;
468   int sock, on = 1;
469
470
471
472   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
473     {
474       perror("socket");
475       syslog(LOG_ERR, "socket: %m");
476       return (-1);
477     }
478
479
480
481 #ifdef SO_BROADCAST
482   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
483     {
484       perror("setsockopt");
485       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
486       close(sock);
487       return (-1);
488     }
489 #endif
490
491   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
492     {
493       perror("SO_REUSEADDR failed");
494       close(sock);
495       return (-1);
496     }
497
498
499
500 #ifdef SO_RCVBUF
501
502   for (on = bufspace; ; on -= 1024) 
503     {
504       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
505                      &on, sizeof (on)) == 0)
506         break;
507       if (on <= 8*1024) 
508         {
509           perror("setsockopt");
510           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
511           break;
512         }
513     }
514
515
516 #endif
517
518
519   /*
520    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
521    */
522
523   /* Bind to device */
524   if(bind_socket_to_device(sock, int_name) < 0)
525     {
526       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
527       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
528       close(sock);
529       return -1;
530     }
531
532
533   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
534     {
535       perror("bind");
536       syslog(LOG_ERR, "bind: %m");
537       close(sock);
538       return (-1);
539     }
540
541   /*
542    *One should probably fetch the flags first
543    *using F_GETFL....
544    */
545   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
546     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
547
548   return (sock);
549 }
550
551
552 /**
553  *Creates a nonblocking IPv6 socket
554  *@param sin sockaddr_in6 struct. Used for bind(2).
555  *@return the FD of the socket or -1 on error.
556  */
557 int
558 getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
559 {
560   int sock, on = 1;
561
562
563
564   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
565     {
566       perror("socket");
567       syslog(LOG_ERR, "socket: %m");
568       return (-1);
569     }
570
571 #ifdef IPV6_V6ONLY
572   if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) 
573     {
574       perror("setsockopt(IPV6_V6ONLY)");
575       syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
576     }
577 #endif
578
579
580   //#ifdef SO_BROADCAST
581   /*
582   if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0)
583     {
584       perror("setsockopt");
585       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
586       close(sock);
587       return (-1);
588     }
589   */
590   //#endif
591
592
593
594
595 #ifdef SO_RCVBUF
596   for (on = bufspace; ; on -= 1024) 
597     {
598       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
599                      &on, sizeof (on)) == 0)
600         break;
601       if (on <= 8*1024) 
602         {
603           perror("setsockopt");
604           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
605           break;
606         }
607     }
608
609
610 #endif
611
612   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
613     {
614       perror("SO_REUSEADDR failed");
615       close(sock);
616       return (-1);
617     }
618
619
620   /*
621    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
622    */
623
624   /* Bind to device */
625   if(bind_socket_to_device(sock, int_name) < 0)
626     {
627       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
628       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
629       close(sock);
630       return -1;
631     }
632
633
634   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
635     {
636       perror("bind");
637       syslog(LOG_ERR, "bind: %m");
638       close(sock);
639       return (-1);
640     }
641
642   /*
643    *One should probably fetch the flags first
644    *using F_GETFL....
645    */
646   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
647     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
648
649
650
651   return (sock);
652 }
653
654
655 int
656 join_mcast(struct interface *ifs, int sock)
657 {
658   /* See linux/in6.h */
659
660   struct ipv6_mreq mcastreq;
661
662   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
663   mcastreq.ipv6mr_interface = ifs->if_index;
664
665 #if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__
666   OLSR_PRINTF(3, "Interface %s joining multicast %s...",        ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr))
667   /* Send multicast */
668   if(setsockopt(sock, 
669                 IPPROTO_IPV6, 
670                 IPV6_ADD_MEMBERSHIP, 
671                 (char *)&mcastreq, 
672                 sizeof(struct ipv6_mreq)) 
673      < 0)
674     {
675       perror("Join multicast");
676       return -1;
677     }
678 #else
679 #warning implement IPV6_ADD_MEMBERSHIP
680 #endif
681
682   /* Old libc fix */
683 #ifdef IPV6_JOIN_GROUP
684   /* Join reciever group */
685   if(setsockopt(sock, 
686                 IPPROTO_IPV6, 
687                 IPV6_JOIN_GROUP, 
688                 (char *)&mcastreq, 
689                 sizeof(struct ipv6_mreq)) 
690      < 0)
691 #else
692   /* Join reciever group */
693   if(setsockopt(sock, 
694                 IPPROTO_IPV6, 
695                 IPV6_ADD_MEMBERSHIP, 
696                 (char *)&mcastreq, 
697                 sizeof(struct ipv6_mreq)) 
698      < 0)
699 #endif 
700     {
701       perror("Join multicast send");
702       return -1;
703     }
704
705   
706   if(setsockopt(sock, 
707                 IPPROTO_IPV6, 
708                 IPV6_MULTICAST_IF, 
709                 (char *)&mcastreq.ipv6mr_interface, 
710                 sizeof(mcastreq.ipv6mr_interface)) 
711      < 0)
712     {
713       perror("Set multicast if");
714       return -1;
715     }
716
717
718   OLSR_PRINTF(3, "OK\n")
719   return 0;
720 }
721
722
723
724 /*
725  *From net-tools lib/interface.c
726  *
727  */
728
729 int
730 get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
731 {
732   char addr6[40], devname[IFNAMSIZ];
733   char addr6p[8][5];
734   int plen, scope, dad_status, if_idx;
735   FILE *f;
736   struct sockaddr_in6 tmp_sockaddr6;
737
738   if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) 
739     {
740       while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
741                     addr6p[0], addr6p[1], addr6p[2], addr6p[3],
742                     addr6p[4], addr6p[5], addr6p[6], addr6p[7],
743                     &if_idx, &plen, &scope, &dad_status, devname) != EOF) 
744         {
745           if (!strcmp(devname, ifname)) 
746             {
747               sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
748                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
749                       addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
750               OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6)
751               OLSR_PRINTF(5, "\tScope: %d\n", scope)
752               if(scope == scope_in)
753                 {
754                   OLSR_PRINTF(4, "Found addr: %s:%s:%s:%s:%s:%s:%s:%s\n",
755                               addr6p[0], addr6p[1], addr6p[2], addr6p[3],
756                               addr6p[4], addr6p[5], addr6p[6], addr6p[7])
757                   inet_pton(AF_INET6,addr6,&tmp_sockaddr6);
758                   memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr));    
759                   fclose(f);
760                   return 1;
761                 }
762             }
763         }
764       fclose(f);
765     }
766   
767   return 0;
768 }
769
770
771 /**
772  * Wrapper for sendto(2)
773  */
774
775 ssize_t
776 olsr_sendto(int s, 
777             const void *buf, 
778             size_t len, 
779             int flags, 
780             const struct sockaddr *to, 
781             socklen_t tolen)
782 {
783   return sendto(s, buf, len, flags, to, tolen);
784 }
785
786 /**
787  * Wrapper for recvfrom(2)
788  */
789
790 ssize_t  
791 olsr_recvfrom(int  s, 
792               void *buf, 
793               size_t len, 
794               int flags, 
795               struct sockaddr *from,
796               socklen_t *fromlen)
797 {
798   return recvfrom(s, 
799                   buf, 
800                   len, 
801                   flags, 
802                   from, 
803                   fromlen);
804 }
805
806 /**
807  * Wrapper for select(2)
808  */
809
810 int
811 olsr_select(int nfds,
812             fd_set *readfds,
813             fd_set *writefds,
814             fd_set *exceptfds,
815             struct timeval *timeout)
816 {
817   return select(nfds,
818                 readfds,
819                 writefds,
820                 exceptfds,
821                 timeout);
822 }
823
824 int
825 check_wireless_interface(char *ifname)
826 {
827   struct ifreq ifr;
828
829   memset(&ifr, 0, sizeof(ifr));
830   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
831
832   return (ioctl(olsr_cnf->ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
833 }
834
835 #if 0
836
837 #include <linux/sockios.h>
838 #include <linux/types.h>
839
840 /* This data structure is used for all the MII ioctl's */
841 struct mii_data {
842     __u16       phy_id;
843     __u16       reg_num;
844     __u16       val_in;
845     __u16       val_out;
846 };
847
848
849 /* Basic Mode Control Register */
850 #define MII_BMCR                0x00
851 #define  MII_BMCR_RESET         0x8000
852 #define  MII_BMCR_LOOPBACK      0x4000
853 #define  MII_BMCR_100MBIT       0x2000
854 #define  MII_BMCR_AN_ENA        0x1000
855 #define  MII_BMCR_ISOLATE       0x0400
856 #define  MII_BMCR_RESTART       0x0200
857 #define  MII_BMCR_DUPLEX        0x0100
858 #define  MII_BMCR_COLTEST       0x0080
859
860 /* Basic Mode Status Register */
861 #define MII_BMSR                0x01
862 #define  MII_BMSR_CAP_MASK      0xf800
863 #define  MII_BMSR_100BASET4     0x8000
864 #define  MII_BMSR_100BASETX_FD  0x4000
865 #define  MII_BMSR_100BASETX_HD  0x2000
866 #define  MII_BMSR_10BASET_FD    0x1000
867 #define  MII_BMSR_10BASET_HD    0x0800
868 #define  MII_BMSR_NO_PREAMBLE   0x0040
869 #define  MII_BMSR_AN_COMPLETE   0x0020
870 #define  MII_BMSR_REMOTE_FAULT  0x0010
871 #define  MII_BMSR_AN_ABLE       0x0008
872 #define  MII_BMSR_LINK_VALID    0x0004
873 #define  MII_BMSR_JABBER        0x0002
874 #define  MII_BMSR_EXT_CAP       0x0001
875
876 int
877 calculate_if_metric(char *ifname)
878 {
879   if(check_wireless_interface(ifname))
880     {
881       struct ifreq ifr;
882       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
883       
884       /* Get bit rate */
885       if(ioctl(olsr_cnf->ioctl_s, SIOCGIWRATE, &ifr) < 0)
886         {
887           OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname)
888           return WEIGHT_WLAN_11MB;
889         }
890       
891       OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue)
892
893       //WEIGHT_WLAN_LOW,          /* <11Mb WLAN     */
894       //WEIGHT_WLAN_11MB,         /* 11Mb 802.11b   */
895       //WEIGHT_WLAN_54MB,         /* 54Mb 802.11g   */
896       return WEIGHT_WLAN_LOW;
897     }
898   else
899     {
900       /* Ethernet */
901       /* Mii wizardry */
902       struct ifreq ifr;
903       struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
904       int bmcr;
905       memset(&ifr, 0, sizeof(ifr));
906       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
907
908       if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
909         if (errno != ENODEV)
910           OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
911                       ifr.ifr_name, strerror(errno))
912         return WEIGHT_ETHERNET_DEFAULT;
913       }
914
915       mii->reg_num = MII_BMCR;
916       if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
917         OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
918                     strerror(errno))
919         return WEIGHT_ETHERNET_DEFAULT;
920       }
921       bmcr = mii->val_out;
922
923
924       OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
925       OLSR_PRINTF(1, "%s Mbit, %s duplex\n",
926                   (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
927                   (bmcr & MII_BMCR_DUPLEX) ? "full" : "half")
928     
929       is_if_link_up(ifname);
930
931       if(mii->val_out & MII_BMCR_100MBIT)
932         return WEIGHT_ETHERNET_100MB;
933       else
934         return WEIGHT_ETHERNET_10MB;
935       //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
936
937     }
938 }
939
940
941 olsr_bool
942 is_if_link_up(char *ifname)
943 {
944   if(check_wireless_interface(ifname))
945     {
946       /* No link checking on wireless devices */
947       return OLSR_TRUE;
948     }
949   else
950     {
951       /* Mii wizardry */
952       struct ifreq ifr;
953       struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
954       int bmsr;
955       memset(&ifr, 0, sizeof(ifr));
956       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
957
958       if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
959         if (errno != ENODEV)
960           OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
961                       ifr.ifr_name, strerror(errno))
962         return WEIGHT_ETHERNET_DEFAULT;
963       }
964       mii->reg_num = MII_BMSR;
965       if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
966         OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
967                     strerror(errno))
968         return WEIGHT_ETHERNET_DEFAULT;
969       }
970       bmsr = mii->val_out;
971
972       OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
973       OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link ")
974     
975       return (bmsr & MII_BMSR_LINK_VALID);
976
977     }
978 }
979
980 #else
981 int
982 calculate_if_metric(char *ifname)
983 {
984   return check_wireless_interface(ifname);
985 }
986 #endif
987