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