* killed the MAX_IFS variable and another statically sized array
[olsrd.git] / src / bsd / 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.30 2007/02/04 23:36:35 bernd67 Exp $
40  */
41
42 #include "defs.h"
43 #include "net_os.h"
44 #include "parser.h" /* dnc: needed for call to packet_parser() */
45 #include "net.h"
46
47 #include <net/if.h>
48
49 #ifdef __NetBSD__
50 #include <sys/param.h>
51 #include <net/if_ether.h>
52 #endif
53
54 #ifdef __OpenBSD__
55 #include <netinet/if_ether.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/ip_icmp.h>
59 #include <netinet/icmp_var.h>
60 #include <netinet/icmp6.h>
61 #endif
62
63 #ifdef __FreeBSD__
64 #include <ifaddrs.h>
65 #include <net/if_var.h>
66 #include <net/ethernet.h>
67 #include <netinet/in_var.h>
68 #ifndef FBSD_NO_80211
69 #include <net80211/ieee80211.h>
70 #include <net80211/ieee80211_ioctl.h>
71 #include <dev/wi/if_wavelan_ieee.h>
72 #include <dev/wi/if_wireg.h>
73 #endif
74 #endif
75
76 #include <net/if_dl.h>
77 #ifdef SPOOF
78 #include <libnet.h>
79 #endif /* SPOOF */
80
81 //#define       SIOCGIFGENERIC  _IOWR('i', 58, struct ifreq)    /* generic IF get op */
82 //#define SIOCGWAVELAN SIOCGIFGENERIC
83
84 #include <sys/sysctl.h>
85
86 static int ignore_redir;
87 static int send_redir;
88 static int gateway;
89
90 static int set_sysctl_int(char *name, int new)
91 {
92   int old;
93   unsigned int len = sizeof (old);
94
95 #ifdef __OpenBSD__
96   int mib[4];
97
98   /* Set net.inet.ip.forwarding by default. */
99   mib[0] = CTL_NET;
100   mib[1] = PF_INET;
101   mib[2] = IPPROTO_IP;
102   mib[3] = IPCTL_FORWARDING;
103
104   if (!strcmp(name, "net.inet6.ip6.forwarding"))
105   {
106     mib[1] = PF_INET6;
107     mib[2] = IPPROTO_IPV6;
108   }
109   else if (!strcmp(name, "net.inet.icmp.rediraccept"))
110   {
111     mib[2] = IPPROTO_ICMP;
112     mib[3] = ICMPCTL_REDIRACCEPT;
113   }
114   else if (!strcmp(name, "net.inet6.icmp6.rediraccept"))
115   {
116     mib[2] = IPPROTO_ICMPV6;
117     mib[3] = ICMPV6CTL_REDIRACCEPT;
118   }
119   else if (!strcmp(name, "net.inet.ip.redirect"))
120   {
121     mib[3] = IPCTL_SENDREDIRECTS;
122   }
123   else if (!strcmp(name, "net.inet6.ip6.redirect"))
124   {
125     mib[1] = PF_INET6;
126     mib[2] = IPPROTO_IPV6;
127     mib[3] = IPCTL_SENDREDIRECTS;
128   }
129
130   if (sysctl(mib, 4, &old, &len, &new, sizeof (new)) < 0)
131     return -1;
132 #else
133
134   if (sysctlbyname(name, &old, &len, &new, sizeof (new)) < 0)
135     return -1;
136 #endif
137
138   return old;
139 }
140
141 int enable_ip_forwarding(int version)
142 {
143   char *name;
144
145   if (olsr_cnf->ip_version == AF_INET)
146     name = "net.inet.ip.forwarding";
147
148   else
149     name = "net.inet6.ip6.forwarding";
150
151   gateway = set_sysctl_int(name, 1);
152
153   if (gateway < 0)
154     {
155       fprintf(stderr, "Cannot enable IP forwarding. Please enable IP forwarding manually. Continuing in 3 seconds...\n");
156       sleep(3);
157     }
158
159   return 1;
160 }
161
162 int
163 disable_redirects_global(int version)
164 {
165   char *name;
166
167   // do not accept ICMP redirects
168
169 #ifdef __OpenBSD__
170   if (olsr_cnf->ip_version == AF_INET)
171     name = "net.inet.icmp.rediraccept";
172
173   else
174     name = "net.inet6.icmp6.rediraccept";
175
176   ignore_redir = set_sysctl_int(name, 0);
177 #elif defined __FreeBSD__
178   if (olsr_cnf->ip_version == AF_INET)
179   {
180     name = "net.inet.icmp.drop_redirect";
181     ignore_redir = set_sysctl_int(name, 1);
182   }
183   else
184   {
185     name = "net.inet6.icmp6.rediraccept";
186     ignore_redir = set_sysctl_int(name, 0);
187   }
188 #else
189   if (olsr_cnf->ip_version == AF_INET)
190     name = "net.inet.icmp.drop_redirect";
191
192   else
193     name = "net.inet6.icmp6.drop_redirect";
194
195   ignore_redir = set_sysctl_int(name, 1);
196 #endif
197
198   if (ignore_redir < 0)
199     {
200       fprintf(stderr, "Cannot disable incoming ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
201       sleep(3);
202     }
203
204   // do not send ICMP redirects
205
206   if (olsr_cnf->ip_version == AF_INET)
207     name = "net.inet.ip.redirect";
208
209   else
210     name = "net.inet6.ip6.redirect";
211
212   send_redir = set_sysctl_int(name, 0);
213
214   if (send_redir < 0)
215     {
216       fprintf(stderr, "Cannot disable outgoing ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
217       sleep(3);
218     }
219
220   return 1;
221 }
222
223 int disable_redirects(char *if_name, struct interface *iface, int version)
224 {
225   // this function gets called for each interface olsrd uses; however,
226   // FreeBSD can only globally control ICMP redirects, and not on a
227   // per-interface basis; hence, only disable ICMP redirects in the "global"
228   // function
229   return 1;
230 }
231
232 int deactivate_spoof(char *if_name, struct interface *iface, int version)
233 {
234   return 1;
235 }
236
237 int restore_settings(int version)
238 {
239   char *name;
240
241   // reset IP forwarding
242
243   if (olsr_cnf->ip_version == AF_INET)
244     name = "net.inet.ip.forwarding";
245
246   else
247     name = "net.inet6.ip6.forwarding";
248
249   set_sysctl_int(name, gateway);
250
251   // reset incoming ICMP redirects
252
253 #ifdef __OpenBSD__
254   if (olsr_cnf->ip_version == AF_INET)
255     name = "net.inet.icmp.rediraccept";
256   else
257     name = "net.inet6.icmp6.rediraccept";
258
259 #elif defined __FreeBSD__
260   if (olsr_cnf->ip_version == AF_INET)
261     name = "net.inet.icmp.drop_redirect";
262
263   else
264     name = "net.inet6.icmp6.rediraccept";
265 #else
266   if (olsr_cnf->ip_version == AF_INET)
267     name = "net.inet.icmp.drop_redirect";
268
269   else
270     name = "net.inet6.icmp6.drop_redirect";
271 #endif
272
273   set_sysctl_int(name, ignore_redir);
274
275   // reset outgoing ICMP redirects
276
277   if (olsr_cnf->ip_version == AF_INET)
278     name = "net.inet.ip.redirect";
279
280   else
281     name = "net.inet6.ip6.redirect";
282
283   set_sysctl_int(name, send_redir);
284
285   return 1;
286 }
287
288
289 /**
290  *Creates a nonblocking broadcast socket.
291  *@param sa sockaddr struct. Used for bind(2).
292  *@return the FD of the socket or -1 on error.
293  */
294 int
295 gethemusocket(struct sockaddr_in *pin)
296 {
297   int sock, on = 1;
298
299   OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
300
301
302   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
303     {
304       perror("hcsocket");
305       syslog(LOG_ERR, "hcsocket: %m");
306       return (-1);
307     }
308
309   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
310     {
311       perror("SO_REUSEADDR failed");
312       close(sock);
313       return (-1);
314     }
315   /* connect to PORT on HOST */
316   if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
317     {
318       printf("FAILED\n");
319       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
320       printf("connection refused\n");
321       close(sock);
322       return (-1);
323     }
324
325   printf("OK\n");
326
327   /* Keep TCP socket blocking */  
328   return (sock);
329 }
330
331
332 int
333 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
334 {
335   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
336   int sock, on = 1;
337
338   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
339     {
340       perror("socket");
341       syslog(LOG_ERR, "socket: %m");
342       return (-1);
343     }
344
345   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
346     {
347       perror("setsockopt");
348       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
349       close(sock);
350       return (-1);
351     }
352
353   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
354     {
355       perror("SO_REUSEADDR failed");
356       close(sock);
357       return (-1);
358     }
359
360   if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 
361     {
362       perror("SO_REUSEPORT failed");
363       close(sock);
364       return (-1);
365     }
366
367   if (setsockopt(sock, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0) 
368     {
369       perror("IP_RECVIF failed");
370       close(sock);
371       return (-1);
372     }
373
374   for (on = bufspace; ; on -= 1024) 
375     {
376       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
377                      &on, sizeof (on)) == 0)
378         break;
379       if (on <= 8*1024) 
380         {
381           perror("setsockopt");
382           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
383           break;
384         }
385     }
386
387   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
388     {
389       perror("bind");
390       syslog(LOG_ERR, "bind: %m");
391       close(sock);
392       return (-1);
393     }
394
395   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
396     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
397
398   return (sock);
399 }
400
401 int getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
402 {
403   int sock, on = 1;
404
405   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
406     {
407       perror("socket");
408       syslog(LOG_ERR, "socket: %m");
409       return (-1);
410     }
411
412   for (on = bufspace; ; on -= 1024) 
413     {
414       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
415                      &on, sizeof (on)) == 0)
416         break;
417       if (on <= 8*1024) 
418         {
419           perror("setsockopt");
420           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
421           break;
422         }
423     }
424
425   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
426     {
427       perror("SO_REUSEADDR failed");
428       close(sock);
429       return (-1);
430     }
431
432   if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 
433     {
434       perror("SO_REUSEPORT failed");
435       return (-1);
436     }
437
438   if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
439     {
440       perror("IPV6_RECVPKTINFO failed");
441       return (-1);
442     }
443
444   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
445     {
446       perror("bind");
447       syslog(LOG_ERR, "bind: %m");
448       close(sock);
449       return (-1);
450     }
451
452   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
453     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
454
455   return (sock);
456 }
457
458
459
460 int
461 join_mcast(struct interface *ifs, int sock)
462 {
463   /* See netinet6/in6.h */
464
465   struct ipv6_mreq mcastreq;
466
467   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
468   mcastreq.ipv6mr_interface = ifs->if_index;
469
470   OLSR_PRINTF(3, "Interface %s joining multicast %s...",        ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr))
471
472   /* rfc 3493 */
473 #ifdef IPV6_JOIN_GROUP
474   /* Join reciever group */
475   if(setsockopt(sock, 
476                 IPPROTO_IPV6, 
477                 IPV6_JOIN_GROUP, 
478                 (char *)&mcastreq, 
479                 sizeof(struct ipv6_mreq)) 
480      < 0)
481 #else /* rfc 2133, obsoleted */
482   /* Join receiver group */
483   if(setsockopt(sock, 
484                 IPPROTO_IPV6, 
485                 IPV6_ADD_MEMBERSHIP, 
486                 (char *)&mcastreq, 
487                 sizeof(struct ipv6_mreq)) 
488      < 0)
489 #endif 
490     {
491       perror("Join multicast send");
492       return -1;
493     }
494
495   
496   if(setsockopt(sock, 
497                 IPPROTO_IPV6, 
498                 IPV6_MULTICAST_IF, 
499                 (char *)&mcastreq.ipv6mr_interface, 
500                 sizeof(mcastreq.ipv6mr_interface)) 
501      < 0)
502     {
503       perror("Set multicast if");
504       return -1;
505     }
506
507
508   OLSR_PRINTF(3, "OK\n")
509   return 0;
510 }
511
512
513
514
515 int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
516 {
517   struct ifaddrs *ifap, *ifa;
518   const struct sockaddr_in6 *sin6 = NULL;
519   struct in6_ifreq ifr6;
520   int found = 0;
521   int s6;
522   u_int32_t flags6;
523
524   if (getifaddrs(&ifap) != 0)
525     {
526       OLSR_PRINTF(3, "get_ipv6_address: getifaddrs() failed.\n")
527       return 0;
528     }
529
530   for (ifa = ifap; ifa; ifa = ifa->ifa_next)
531     {
532       if (ifa->ifa_addr->sa_family == AF_INET6 &&
533           strcmp(ifa->ifa_name, ifname) == 0)
534         {
535           sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
536           if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
537             continue;
538           strncpy(ifr6.ifr_name, ifname, sizeof(ifname));
539           if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
540             {
541               OLSR_PRINTF(3, "socket(AF_INET6,SOCK_DGRAM)");
542               break;
543             }
544           ifr6.ifr_addr = *sin6;
545           if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0)
546             {
547               OLSR_PRINTF(3, "ioctl(SIOCGIFAFLAG_IN6)");
548               close(s6);
549               break;
550             }
551           close(s6);
552           flags6 = ifr6.ifr_ifru.ifru_flags6;
553           if ((flags6 & IN6_IFF_ANYCAST) != 0)
554             continue;
555           if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
556             {
557               if (scope_in)
558                 {
559                   memcpy(&saddr6->sin6_addr, &sin6->sin6_addr,
560                          sizeof(struct in6_addr));
561                   found = 1;
562                   break;
563                 }
564             }
565           else
566             {
567               if (scope_in == 0)
568                 {
569                   memcpy(&saddr6->sin6_addr, &sin6->sin6_addr,
570                          sizeof(struct in6_addr));
571                   found = 1;
572                   break;
573                 }
574             }
575         }
576     }
577   freeifaddrs(ifap);
578   if (found)
579     return 1;
580
581   return 0;
582 }
583
584
585
586
587 /**
588  * Wrapper for sendto(2)
589  */
590
591 #ifdef SPOOF
592 static u_int16_t ip_id = 0;
593 #endif /* SPOOF */
594
595 ssize_t
596 olsr_sendto(int s, 
597             const void *buf, 
598             size_t len, 
599             int flags, 
600             const struct sockaddr *to, 
601             socklen_t tolen)
602 {
603 #ifdef SPOOF
604   /* IPv4 for now! */
605
606   libnet_t *context;
607   char errbuf[LIBNET_ERRBUF_SIZE];
608   libnet_ptag_t udp_tag, ip_tag, ether_tag;
609   unsigned char enet_broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
610   int status;
611   struct sockaddr_in *to_in = (struct sockaddr_in *) to;
612   u_int32_t destip;
613   struct interface *iface;
614
615   udp_tag = ip_tag = ether_tag = 0;
616   destip = to_in->sin_addr.s_addr;
617   iface = if_ifwithsock (s);
618
619   /* initialize libnet */
620   context = libnet_init(LIBNET_LINK, iface->int_name, errbuf);
621   if (context == NULL)
622     {
623       OLSR_PRINTF (1, "libnet init: %s\n", libnet_geterror (context))
624       return (0);
625     }
626
627   /* initialize IP ID field if necessary */
628   if (ip_id == 0)
629     {
630       ip_id = (u_int16_t) (arc4random () & 0xffff);
631     }
632
633   udp_tag = libnet_build_udp (698,                              /* src port */
634                               698,                              /* dest port */
635                               LIBNET_UDP_H + len,               /* length */
636                               0,                                /* checksum */
637                               buf,                              /* payload */
638                               len,                              /* payload size */
639                               context,                          /* context */
640                               udp_tag);                         /* pblock */
641   if (udp_tag == -1)
642     {
643       OLSR_PRINTF (1, "libnet UDP header: %s\n", libnet_geterror (context))
644         return (0);
645     }
646
647   ip_tag = libnet_build_ipv4 (LIBNET_IPV4_H + LIBNET_UDP_H + len, /* len */
648                               0,                                /* TOS */
649                               ip_id++,                          /* IP id */
650                               0,                                /* IP frag */
651                               1,                                /* IP TTL */
652                               IPPROTO_UDP,                      /* protocol */
653                               0,                                /* checksum */
654                               libnet_get_ipaddr4 (context),     /* src IP */
655                               destip,                           /* dest IP */
656                               NULL,                             /* payload */
657                               0,                                /* payload len */
658                               context,                          /* context */
659                               ip_tag);                          /* pblock */
660   if (ip_tag == -1)
661     {
662       OLSR_PRINTF (1, "libnet IP header: %s\n", libnet_geterror (context))
663       return (0);
664     }
665
666   ether_tag = libnet_build_ethernet (enet_broadcast,            /* ethernet dest */
667                                      libnet_get_hwaddr (context), /* ethernet source */
668                                      ETHERTYPE_IP,              /* protocol type */
669                                      NULL,                      /* payload */
670                                      0,                         /* payload size */
671                                      context,                   /* libnet handle */
672                                      ether_tag);                /* pblock tag */
673   if (ether_tag == -1)
674     {
675       OLSR_PRINTF (1, "libnet ethernet header: %s\n", libnet_geterror (context))
676       return (0);
677     }
678  
679   status = libnet_write (context);
680   if (status == -1)
681     {
682       OLSR_PRINTF (1, "libnet packet write: %s\n", libnet_geterror (context))
683       return (0);
684     }
685
686   libnet_destroy (context);
687
688   return (len);
689
690 #else
691   return sendto(s, buf, len, flags, to, tolen);
692 #endif
693 }
694
695
696 /**
697  * Wrapper for recvfrom(2)
698  */
699
700 ssize_t  
701 olsr_recvfrom(int  s, 
702               void *buf, 
703               size_t len, 
704               int flags, 
705               struct sockaddr *from,
706               socklen_t *fromlen)
707 {
708   struct msghdr mhdr;
709   struct iovec iov;
710   struct cmsghdr *cm;
711   struct sockaddr_dl *sdl;
712   struct sockaddr_in *sin = (struct sockaddr_in *) from; //XXX
713   struct sockaddr_in6 *sin6;
714   struct in6_addr *iaddr6;
715   struct in6_pktinfo *pkti;
716   struct interface *ifc;
717   char addrstr[INET6_ADDRSTRLEN];
718   char iname[IFNAMSIZ];
719   unsigned char chdr[4096];
720   int count;
721
722   bzero(&mhdr, sizeof(mhdr));
723   bzero(&iov, sizeof(iov));
724
725   mhdr.msg_name = (caddr_t) from;
726   mhdr.msg_namelen = *fromlen;
727   mhdr.msg_iov = &iov;
728   mhdr.msg_iovlen = 1;
729   mhdr.msg_control = (caddr_t) chdr;
730   mhdr.msg_controllen = sizeof (chdr);
731
732   iov.iov_len = MAXMESSAGESIZE;
733   iov.iov_base = buf;
734
735   count = recvmsg (s, &mhdr, MSG_DONTWAIT);
736   if (count <= 0)
737     {
738       return (count);
739     }
740
741   /* this needs to get communicated back to caller */
742   *fromlen = mhdr.msg_namelen;
743   if (olsr_cnf->ip_version == AF_INET6)
744     {
745       for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&mhdr); cm;
746            cm = (struct cmsghdr *)CMSG_NXTHDR(&mhdr, cm))
747         {
748           if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
749             {
750               pkti = (struct in6_pktinfo *) CMSG_DATA(cm);
751               iaddr6 = &pkti->ipi6_addr;
752               if_indextoname(pkti->ipi6_ifindex, iname);
753             }
754         }
755     }
756   else
757     {
758       cm = (struct cmsghdr *) chdr;
759       sdl = (struct sockaddr_dl *) CMSG_DATA (cm);
760       bzero (iname, sizeof (iname));
761       memcpy (iname, sdl->sdl_data, sdl->sdl_nlen);
762     }
763
764   ifc = if_ifwithsock (s);
765
766   sin6 = (struct sockaddr_in6 *)from;
767   OLSR_PRINTF (4, "%d bytes from %s, socket associated %s really received on %s\n",
768                count,
769                (olsr_cnf->ip_version == AF_INET6) ?
770                  inet_ntop(AF_INET6, (char *)&sin6->sin6_addr, addrstr,
771                                      INET6_ADDRSTRLEN):
772                  inet_ntoa (sin->sin_addr),
773                ifc->int_name,
774                iname);
775
776   if (strcmp (ifc->int_name, iname) != 0)
777     {
778       return (0);
779     }
780
781   return (count);
782 }
783
784 /**
785  * Wrapper for select(2)
786  */
787
788 int
789 olsr_select(int nfds,
790             fd_set *readfds,
791             fd_set *writefds,
792             fd_set *exceptfds,
793             struct timeval *timeout)
794 {
795   return select(nfds,
796                 readfds,
797                 writefds,
798                 exceptfds,
799                 timeout);
800 }
801
802
803 int 
804 check_wireless_interface(char *ifname)
805 {
806 #if defined __FreeBSD__ &&  !defined FBSD_NO_80211
807   struct wi_req wreq;
808   struct ifreq ifr;
809
810   memset((char *)&wreq, 0, sizeof(wreq));
811   memset((char *)&ifr, 0, sizeof(ifr));
812
813   wreq.wi_len = WI_MAX_DATALEN;
814   wreq.wi_type = WI_RID_IFACE_STATS;
815
816   strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
817   ifr.ifr_data = (caddr_t)&wreq;
818
819   return (ioctl(olsr_cnf->ioctl_s, SIOCGWAVELAN, &ifr) >= 0) ? 1 : 0;
820 #else
821   return 0;
822 #endif
823 }
824
825 #include <sys/sockio.h>
826
827 int
828 calculate_if_metric(char *ifname)
829 {
830   if(check_wireless_interface(ifname))
831     {
832       /* Wireless */
833       return 1;
834     }
835   else
836     {
837       /* Ethernet */
838 #if 0
839       /* Andreas: Perhaps SIOCGIFMEDIA is the way to do this? */
840       struct ifmediareq ifm;
841
842       memset(&ifm, 0, sizeof(ifm));
843       strlcpy(ifm.ifm_name, ifname, sizeof(ifm.ifm_name));
844
845       if(ioctl(olsr_cnf->ioctl_s, SIOCGIFMEDIA, &ifm) < 0)
846         {
847           OLSR_PRINTF(1, "Error SIOCGIFMEDIA(%s)\n", ifm.ifm_name)
848           return WEIGHT_ETHERNET_DEFAULT;
849         }
850
851       OLSR_PRINTF(1, "%s: STATUS 0x%08x\n", ifm.ifm_name, ifm.ifm_status)
852 #endif
853       return WEIGHT_ETHERNET_DEFAULT;
854     }
855 }