Fixed IPv6 addrtpe initialization
[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.29 2005/09/17 20:48:50 kattemat 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       return (-1);
438     }
439   /* connect to PORT on HOST */
440   if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
441     {
442       printf("FAILED\n");
443       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
444       printf("connection refused\n");
445       return (-1);
446     }
447
448   printf("OK\n");
449
450   /* Keep TCP socket blocking */  
451   return (sock);
452 }
453
454
455 /**
456  *Creates a nonblocking broadcast socket.
457  *@param sa sockaddr struct. Used for bind(2).
458  *@return the FD of the socket or -1 on error.
459  */
460 int
461 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
462 {
463   struct sockaddr_in *sin=(struct sockaddr_in *)sa;
464   int sock, on = 1;
465
466
467
468   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
469     {
470       perror("socket");
471       syslog(LOG_ERR, "socket: %m");
472       return (-1);
473     }
474
475
476
477 #ifdef SO_BROADCAST
478   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
479     {
480       perror("setsockopt");
481       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
482       close(sock);
483       return (-1);
484     }
485 #endif
486
487   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
488     {
489       perror("SO_REUSEADDR failed");
490       return (-1);
491     }
492
493
494
495 #ifdef SO_RCVBUF
496
497   for (on = bufspace; ; on -= 1024) 
498     {
499       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
500                      &on, sizeof (on)) == 0)
501         break;
502       if (on <= 8*1024) 
503         {
504           perror("setsockopt");
505           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
506           break;
507         }
508     }
509
510
511 #endif
512
513
514   /*
515    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
516    */
517
518   /* Bind to device */
519   if(bind_socket_to_device(sock, int_name) < 0)
520     {
521       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
522       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
523       return -1;
524     }
525
526
527   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
528     {
529       perror("bind");
530       syslog(LOG_ERR, "bind: %m");
531       close(sock);
532       return (-1);
533     }
534
535   /*
536    *One should probably fetch the flags first
537    *using F_GETFL....
538    */
539   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
540     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
541
542   return (sock);
543 }
544
545
546 /**
547  *Creates a nonblocking IPv6 socket
548  *@param sin sockaddr_in6 struct. Used for bind(2).
549  *@return the FD of the socket or -1 on error.
550  */
551 int
552 getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
553 {
554   int sock, on = 1;
555
556
557
558   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
559     {
560       perror("socket");
561       syslog(LOG_ERR, "socket: %m");
562       return (-1);
563     }
564
565 #ifdef IPV6_V6ONLY
566   if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) 
567     {
568       perror("setsockopt(IPV6_V6ONLY)");
569       syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
570     }
571 #endif
572
573
574   //#ifdef SO_BROADCAST
575   /*
576   if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0)
577     {
578       perror("setsockopt");
579       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
580       close(sock);
581       return (-1);
582     }
583   */
584   //#endif
585
586
587
588
589 #ifdef SO_RCVBUF
590   for (on = bufspace; ; on -= 1024) 
591     {
592       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
593                      &on, sizeof (on)) == 0)
594         break;
595       if (on <= 8*1024) 
596         {
597           perror("setsockopt");
598           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
599           break;
600         }
601     }
602
603
604 #endif
605
606   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
607     {
608       perror("SO_REUSEADDR failed");
609       return (-1);
610     }
611
612
613   /*
614    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
615    */
616
617   /* Bind to device */
618   if(bind_socket_to_device(sock, int_name) < 0)
619     {
620       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
621       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
622       return -1;
623     }
624
625
626   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
627     {
628       perror("bind");
629       syslog(LOG_ERR, "bind: %m");
630       close(sock);
631       return (-1);
632     }
633
634   /*
635    *One should probably fetch the flags first
636    *using F_GETFL....
637    */
638   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
639     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
640
641
642
643   return (sock);
644 }
645
646
647 int
648 join_mcast(struct interface *ifs, int sock)
649 {
650   /* See linux/in6.h */
651
652   struct ipv6_mreq mcastreq;
653
654   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
655   mcastreq.ipv6mr_interface = ifs->if_index;
656
657 #if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__
658   OLSR_PRINTF(3, "Interface %s joining multicast %s...",        ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr))
659   /* Send multicast */
660   if(setsockopt(sock, 
661                 IPPROTO_IPV6, 
662                 IPV6_ADD_MEMBERSHIP, 
663                 (char *)&mcastreq, 
664                 sizeof(struct ipv6_mreq)) 
665      < 0)
666     {
667       perror("Join multicast");
668       return -1;
669     }
670 #else
671 #warning implement IPV6_ADD_MEMBERSHIP
672 #endif
673
674   /* Old libc fix */
675 #ifdef IPV6_JOIN_GROUP
676   /* Join reciever group */
677   if(setsockopt(sock, 
678                 IPPROTO_IPV6, 
679                 IPV6_JOIN_GROUP, 
680                 (char *)&mcastreq, 
681                 sizeof(struct ipv6_mreq)) 
682      < 0)
683 #else
684   /* Join reciever group */
685   if(setsockopt(sock, 
686                 IPPROTO_IPV6, 
687                 IPV6_ADD_MEMBERSHIP, 
688                 (char *)&mcastreq, 
689                 sizeof(struct ipv6_mreq)) 
690      < 0)
691 #endif 
692     {
693       perror("Join multicast send");
694       return -1;
695     }
696
697   
698   if(setsockopt(sock, 
699                 IPPROTO_IPV6, 
700                 IPV6_MULTICAST_IF, 
701                 (char *)&mcastreq.ipv6mr_interface, 
702                 sizeof(mcastreq.ipv6mr_interface)) 
703      < 0)
704     {
705       perror("Set multicast if");
706       return -1;
707     }
708
709
710   OLSR_PRINTF(3, "OK\n")
711   return 0;
712 }
713
714
715
716 /*
717  *From net-tools lib/interface.c
718  *
719  */
720
721 int
722 get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
723 {
724   char addr6[40], devname[IFNAMSIZ];
725   char addr6p[8][5];
726   int plen, scope, dad_status, if_idx;
727   FILE *f;
728   struct sockaddr_in6 tmp_sockaddr6;
729
730   if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) 
731     {
732       while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
733                     addr6p[0], addr6p[1], addr6p[2], addr6p[3],
734                     addr6p[4], addr6p[5], addr6p[6], addr6p[7],
735                     &if_idx, &plen, &scope, &dad_status, devname) != EOF) 
736         {
737           if (!strcmp(devname, ifname)) 
738             {
739               sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
740                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
741                       addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
742               OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6)
743               OLSR_PRINTF(5, "\tScope: %d\n", scope)
744               if(scope == scope_in)
745                 {
746                   OLSR_PRINTF(4, "Found addr: %s:%s:%s:%s:%s:%s:%s:%s\n",
747                               addr6p[0], addr6p[1], addr6p[2], addr6p[3],
748                               addr6p[4], addr6p[5], addr6p[6], addr6p[7])
749                   inet_pton(AF_INET6,addr6,&tmp_sockaddr6);
750                   memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr));    
751                   fclose(f);
752                   return 1;
753                 }
754             }
755         }
756       fclose(f);
757     }
758   
759   return 0;
760 }
761
762
763 /**
764  * Wrapper for sendto(2)
765  */
766
767 ssize_t
768 olsr_sendto(int s, 
769             const void *buf, 
770             size_t len, 
771             int flags, 
772             const struct sockaddr *to, 
773             socklen_t tolen)
774 {
775   return sendto(s, buf, len, flags, to, tolen);
776 }
777
778 /**
779  * Wrapper for recvfrom(2)
780  */
781
782 ssize_t  
783 olsr_recvfrom(int  s, 
784               void *buf, 
785               size_t len, 
786               int flags, 
787               struct sockaddr *from,
788               socklen_t *fromlen)
789 {
790   return recvfrom(s, 
791                   buf, 
792                   len, 
793                   flags, 
794                   from, 
795                   fromlen);
796 }
797
798 /**
799  * Wrapper for select(2)
800  */
801
802 int
803 olsr_select(int nfds,
804             fd_set *readfds,
805             fd_set *writefds,
806             fd_set *exceptfds,
807             struct timeval *timeout)
808 {
809   return select(nfds,
810                 readfds,
811                 writefds,
812                 exceptfds,
813                 timeout);
814 }
815
816 int
817 check_wireless_interface(char *ifname)
818 {
819   struct ifreq ifr;
820
821   memset(&ifr, 0, sizeof(ifr));
822   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
823
824   return (ioctl(ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
825 }
826
827 #if 0
828
829 #include <linux/sockios.h>
830 #include <linux/types.h>
831
832 /* This data structure is used for all the MII ioctl's */
833 struct mii_data {
834     __u16       phy_id;
835     __u16       reg_num;
836     __u16       val_in;
837     __u16       val_out;
838 };
839
840
841 /* Basic Mode Control Register */
842 #define MII_BMCR                0x00
843 #define  MII_BMCR_RESET         0x8000
844 #define  MII_BMCR_LOOPBACK      0x4000
845 #define  MII_BMCR_100MBIT       0x2000
846 #define  MII_BMCR_AN_ENA        0x1000
847 #define  MII_BMCR_ISOLATE       0x0400
848 #define  MII_BMCR_RESTART       0x0200
849 #define  MII_BMCR_DUPLEX        0x0100
850 #define  MII_BMCR_COLTEST       0x0080
851
852 /* Basic Mode Status Register */
853 #define MII_BMSR                0x01
854 #define  MII_BMSR_CAP_MASK      0xf800
855 #define  MII_BMSR_100BASET4     0x8000
856 #define  MII_BMSR_100BASETX_FD  0x4000
857 #define  MII_BMSR_100BASETX_HD  0x2000
858 #define  MII_BMSR_10BASET_FD    0x1000
859 #define  MII_BMSR_10BASET_HD    0x0800
860 #define  MII_BMSR_NO_PREAMBLE   0x0040
861 #define  MII_BMSR_AN_COMPLETE   0x0020
862 #define  MII_BMSR_REMOTE_FAULT  0x0010
863 #define  MII_BMSR_AN_ABLE       0x0008
864 #define  MII_BMSR_LINK_VALID    0x0004
865 #define  MII_BMSR_JABBER        0x0002
866 #define  MII_BMSR_EXT_CAP       0x0001
867
868 int
869 calculate_if_metric(char *ifname)
870 {
871   if(check_wireless_interface(ifname))
872     {
873       struct ifreq ifr;
874       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
875       
876       /* Get bit rate */
877       if(ioctl(ioctl_s, SIOCGIWRATE, &ifr) < 0)
878         {
879           OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname)
880           return WEIGHT_WLAN_11MB;
881         }
882       
883       OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue)
884
885       //WEIGHT_WLAN_LOW,          /* <11Mb WLAN     */
886       //WEIGHT_WLAN_11MB,         /* 11Mb 802.11b   */
887       //WEIGHT_WLAN_54MB,         /* 54Mb 802.11g   */
888       return WEIGHT_WLAN_LOW;
889     }
890   else
891     {
892       /* Ethernet */
893       /* Mii wizardry */
894       struct ifreq ifr;
895       struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
896       int bmcr;
897       memset(&ifr, 0, sizeof(ifr));
898       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
899
900       if (ioctl(ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
901         if (errno != ENODEV)
902           OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
903                       ifr.ifr_name, strerror(errno))
904         return WEIGHT_ETHERNET_DEFAULT;
905       }
906
907       mii->reg_num = MII_BMCR;
908       if (ioctl(ioctl_s, SIOCGMIIREG, &ifr) < 0) {
909         OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
910                     strerror(errno))
911         return WEIGHT_ETHERNET_DEFAULT;
912       }
913       bmcr = mii->val_out;
914
915
916       OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
917       OLSR_PRINTF(1, "%s Mbit, %s duplex\n",
918                   (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
919                   (bmcr & MII_BMCR_DUPLEX) ? "full" : "half")
920     
921       is_if_link_up(ifname);
922
923       if(mii->val_out & MII_BMCR_100MBIT)
924         return WEIGHT_ETHERNET_100MB;
925       else
926         return WEIGHT_ETHERNET_10MB;
927       //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
928
929     }
930 }
931
932
933 olsr_bool
934 is_if_link_up(char *ifname)
935 {
936   if(check_wireless_interface(ifname))
937     {
938       /* No link checking on wireless devices */
939       return OLSR_TRUE;
940     }
941   else
942     {
943       /* Mii wizardry */
944       struct ifreq ifr;
945       struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
946       int bmsr;
947       memset(&ifr, 0, sizeof(ifr));
948       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
949
950       if (ioctl(ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
951         if (errno != ENODEV)
952           OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
953                       ifr.ifr_name, strerror(errno))
954         return WEIGHT_ETHERNET_DEFAULT;
955       }
956       mii->reg_num = MII_BMSR;
957       if (ioctl(ioctl_s, SIOCGMIIREG, &ifr) < 0) {
958         OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
959                     strerror(errno))
960         return WEIGHT_ETHERNET_DEFAULT;
961       }
962       bmsr = mii->val_out;
963
964       OLSR_PRINTF(1, "%s: ", ifr.ifr_name)
965       OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link ")
966     
967       return (bmsr & MII_BMSR_LINK_VALID);
968
969     }
970 }
971
972 #else
973 int
974 calculate_if_metric(char *ifname)
975 {
976   return check_wireless_interface(ifname);
977 }
978 #endif
979