a5281b62e0582221b82e5a217e5497363ebc581a
[olsrd.git] / src / linux / net.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42
43 /*
44  * Linux spesific code
45  */
46
47 #include "os_net.h"
48 #include "os_misc.h"
49 #include "ipcalc.h"
50 #include "common/string.h"
51 #include "olsr_protocol.h"
52 #include "olsr_logging.h"
53 #include "olsr.h"
54
55 #include <net/if.h>
56
57 #include <sys/ioctl.h>
58
59 #include <fcntl.h>
60 #include <string.h>
61 #include <stdio.h>
62 #include <syslog.h>
63 #include <errno.h>
64 #include <unistd.h>
65 #include <assert.h>
66 #include <netinet/ip.h>
67
68 /* Redirect proc entry */
69 #define REDIRECT_PROC "/proc/sys/net/ipv4/conf/%s/send_redirects"
70
71 /* IP spoof proc entry */
72 #define SPOOF_PROC "/proc/sys/net/ipv4/conf/%s/rp_filter"
73
74 /*
75  *Wireless definitions for ioctl calls
76  *(from linux/wireless.h)
77  */
78 #define SIOCGIWNAME     0x8B01  /* get name == wireless protocol */
79 #define SIOCGIWRATE     0x8B21  /* get default bit rate (bps) */
80
81 /* The original state of the IP forwarding proc entry */
82 static char orig_fwd_state;
83 static char orig_global_redirect_state;
84
85 /**
86  *Bind a socket to a device
87  *
88  *@param sock the socket to bind
89  *@param dev_name name of the device
90  *
91  *@return negative if error
92  */
93
94 static int
95 bind_socket_to_device(int sock, char *dev_name)
96 {
97   /*
98    *Bind to device using the SO_BINDTODEVICE flag
99    */
100   OLSR_DEBUG(LOG_NETWORKING, "Binding socket %d to device %s\n", sock, dev_name);
101   return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name) + 1);
102 }
103
104
105 /**
106  *Enable IP forwarding.
107  *Just writing "1" to the /proc/sys/net/ipv4/ip_forward
108  *if using IPv4 or /proc/sys/net/ipv6/conf/all/forwarding
109  *if using IPv6.
110  *Could probably drop the check for
111  *"0" here and write "1" anyways.
112  *
113  *@param version IP version.
114  *
115  *@return 1 on sucess 0 on failiure
116  */
117 int
118 enable_ip_forwarding(int version)
119 {
120   const char *const procfile = version == AF_INET ? "/proc/sys/net/ipv4/ip_forward" : "/proc/sys/net/ipv6/conf/all/forwarding";
121   FILE *proc_fwd = fopen(procfile, "r");
122
123   if (proc_fwd == NULL) {
124     OLSR_WARN(LOG_NETWORKING,
125               "WARNING! Could not open the %s file to check/enable IP forwarding!\n"
126               "Are you using the procfile filesystem?\nDoes your system support IPv%d?\n"
127               "I will continue(in 3 sec) - but you should manually ensure that IP forwarding is enabled!\n\n",
128               procfile, version == AF_INET ? 4 : 6);
129     sleep(3);
130     return 0;
131   }
132   orig_fwd_state = fgetc(proc_fwd);
133   fclose(proc_fwd);
134
135   if (orig_fwd_state == '1') {
136     OLSR_INFO(LOG_NETWORKING, "\nIP forwarding is enabled on this system\n");
137   } else {
138     proc_fwd = fopen(procfile, "w");
139     if (proc_fwd == NULL) {
140       OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\n"
141                 "I will continue(in 3 sec) - but you should manually ensure that IP forwarding is enabeled!\n\n", procfile);
142       sleep(3);
143       return 0;
144     }
145     fputs("1", proc_fwd);
146     fclose(proc_fwd);
147   }
148   return 1;
149 }
150
151 int
152 disable_redirects_global(int version)
153 {
154   FILE *proc_redirect;
155   const char *const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
156
157   if (version == AF_INET6) {
158     return -1;
159   }
160   proc_redirect = fopen(procfile, "r");
161   if (proc_redirect == NULL) {
162     OLSR_WARN(LOG_NETWORKING,
163               "WARNING! Could not open the %s file to check/disable ICMP redirects!\n"
164               "Are you using the procfile filesystem?\n"
165               "Does your system support IPv4?\n"
166               "I will continue(in 3 sec) - but you should manually ensure that ICMP redirects are disabled!\n\n", procfile);
167     sleep(3);
168     return -1;
169   }
170   orig_global_redirect_state = fgetc(proc_redirect);
171   fclose(proc_redirect);
172
173   if (orig_global_redirect_state == '0') {
174     return 0;
175   }
176   proc_redirect = fopen(procfile, "w");
177   if (proc_redirect == NULL) {
178     OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\n"
179               "I will continue(in 3 sec) - but you should manually ensure that ICMP redirect is disabled!\n\n", procfile);
180     sleep(3);
181     return 0;
182   }
183   fputs("0", proc_redirect);
184   fclose(proc_redirect);
185   return 1;
186 }
187
188 /**
189  *
190  *@return 1 on sucess 0 on failiure
191  */
192 int
193 disable_redirects(const char *if_name, struct interface *iface, int version)
194 {
195   FILE *proc_redirect;
196   char procfile[FILENAME_MAX];
197
198   if (version == AF_INET6) {
199     return -1;
200   }
201
202   /* Generate the procfile name */
203   snprintf(procfile, sizeof(procfile), REDIRECT_PROC, if_name);
204
205   proc_redirect = fopen(procfile, "r");
206   if (proc_redirect == NULL) {
207     OLSR_WARN(LOG_NETWORKING,
208               "WARNING! Could not open the %s file to check/disable ICMP redirects!\n"
209               "Are you using the procfile filesystem?\n"
210               "Does your system support IPv4?\n"
211               "I will continue(in 3 sec) - but you should manually ensure that ICMP redirects are disabled!\n\n", procfile);
212     sleep(3);
213     return 0;
214   }
215   iface->nic_state.redirect = fgetc(proc_redirect);
216   fclose(proc_redirect);
217
218   proc_redirect = fopen(procfile, "w");
219   if (proc_redirect == NULL) {
220     OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\n"
221               "I will continue(in 3 sec) - but you should manually ensure that ICMP redirect is disabled!\n\n", procfile);
222     sleep(3);
223     return 0;
224   }
225   fputs("0", proc_redirect);
226   fclose(proc_redirect);
227   return 1;
228 }
229
230 /**
231  *
232  *@return 1 on sucess 0 on failiure
233  */
234 int
235 deactivate_spoof(const char *if_name, struct interface *iface, int version)
236 {
237   FILE *proc_spoof;
238   char procfile[FILENAME_MAX];
239
240   if (version == AF_INET6) {
241     return -1;
242   }
243
244   /* Generate the procfile name */
245   sprintf(procfile, SPOOF_PROC, if_name);
246
247   proc_spoof = fopen(procfile, "r");
248   if (proc_spoof == NULL) {
249     OLSR_WARN(LOG_NETWORKING,
250               "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
251               "Are you using the procfile filesystem?\n"
252               "Does your system support IPv4?\n"
253               "I will continue(in 3 sec) - but you should manually ensure that IP spoof filtering is disabled!\n\n", procfile);
254     sleep(3);
255     return 0;
256   }
257   iface->nic_state.spoof = fgetc(proc_spoof);
258   fclose(proc_spoof);
259
260   proc_spoof = fopen(procfile, "w");
261   if (proc_spoof == NULL) {
262     OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\n"
263               "I will continue(in 3 sec) - but you should manually ensure that IP spoof filtering is disabled!\n\n", procfile);
264     sleep(3);
265     return 0;
266   }
267   fputs("0", proc_spoof);
268   fclose(proc_spoof);
269   return 1;
270 }
271
272 /**
273  *Resets the spoof filter and ICMP redirect settings
274  */
275 int
276 restore_settings(int version)
277 {
278   struct interface *ifs;
279   struct list_iterator iterator;
280
281   OLSR_INFO(LOG_NETWORKING, "Restoring network state\n");
282
283   /* Restore IP forwarding to "off" */
284   if (orig_fwd_state == '0') {
285     const char *const procfile = version == AF_INET ? "/proc/sys/net/ipv4/ip_forward" : "/proc/sys/net/ipv6/conf/all/forwarding";
286     FILE *proc_fd = fopen(procfile, "w");
287
288     if (proc_fd == NULL) {
289       OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\nSettings not restored!\n", procfile);
290     } else {
291       fputc(orig_fwd_state, proc_fd);
292       fclose(proc_fd);
293     }
294   }
295
296   /* Restore global ICMP redirect setting */
297   if (orig_global_redirect_state != '0') {
298     if (version == AF_INET) {
299       const char *const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
300       FILE *proc_fd = fopen(procfile, "w");
301
302       if (proc_fd == NULL) {
303         OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\nSettings not restored!\n", procfile);
304       } else {
305         fputc(orig_global_redirect_state, proc_fd);
306         fclose(proc_fd);
307       }
308     }
309   }
310
311   if (version == AF_INET6) {
312     return 0;
313   }
314
315   OLSR_FOR_ALL_INTERFACES(ifs, iterator) {
316     char procfile[FILENAME_MAX];
317     FILE *proc_fd;
318     /* ICMP redirects */
319
320     /* Generate the procfile name */
321     snprintf(procfile, sizeof(procfile), REDIRECT_PROC, ifs->int_name);
322     proc_fd = fopen(procfile, "w");
323     if (proc_fd == NULL) {
324       OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\nSettings not restored!\n", procfile);
325     } else {
326       fputc(ifs->nic_state.redirect, proc_fd);
327       fclose(proc_fd);
328     }
329
330     /* Spoof filter */
331
332     /* Generate the procfile name */
333     sprintf(procfile, SPOOF_PROC, ifs->int_name);
334     proc_fd = fopen(procfile, "w");
335     if (proc_fd == NULL) {
336       OLSR_WARN(LOG_NETWORKING, "Could not open %s for writing!\nSettings not restored!\n", procfile);
337     } else {
338       fputc(ifs->nic_state.spoof, proc_fd);
339       fclose(proc_fd);
340     }
341   }
342
343   return 1;
344 }
345
346 /**
347  *Creates a nonblocking broadcast socket.
348  *@param sa sockaddr struct. Used for bind(2).
349  *@return the FD of the socket or -1 on error.
350  */
351 int
352 getsocket4(int bufspace, struct interface *ifp, bool bind_to_unicast, uint16_t port)
353 {
354   struct sockaddr_in sin4;
355   int on;
356   int sock = socket(AF_INET, SOCK_DGRAM, 0);
357   if (sock < 0) {
358     OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
359     olsr_exit(EXIT_FAILURE);
360   }
361
362   on = 1;
363 #ifdef SO_BROADCAST
364   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
365     OLSR_ERROR(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to broadcast mode (%s)\n", strerror(errno));
366     close(sock);
367     olsr_exit(EXIT_FAILURE);
368   }
369 #endif
370
371   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
372     OLSR_ERROR(LOG_NETWORKING, "Cannot reuse address for OLSR PDUs (%s)\n", strerror(errno));
373     close(sock);
374     olsr_exit(EXIT_FAILURE);
375   }
376 #ifdef SO_RCVBUF
377   if(bufspace > 0) {
378     for (on = bufspace;; on -= 1024) {
379       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0) {
380         OLSR_DEBUG(LOG_NETWORKING, "Set socket buffer space to %d\n", on);
381         break;
382       }
383       if (on <= 8 * 1024) {
384         OLSR_WARN(LOG_NETWORKING, "Could not set a socket buffer space for OLSR PDUs (%s)\n", strerror(errno));
385         break;
386       }
387     }
388   }
389 #endif
390
391   /*
392    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
393    */
394
395   /* Bind to device */
396   if (bind_socket_to_device(sock, ifp->int_name) < 0) {
397     OLSR_ERROR(LOG_NETWORKING, "Could not bind socket for OLSR PDUs to device (%s)\n", strerror(errno));
398     close(sock);
399     olsr_exit(EXIT_FAILURE);
400   }
401
402   memset(&sin4, 0, sizeof(sin4));
403   sin4.sin_family = AF_INET;
404   sin4.sin_port = htons(port);
405
406   if(bind_to_unicast) {
407     sin4.sin_addr = ifp->int_src.v4.sin_addr;
408   }
409   else {
410     assert(sin4.sin_addr.s_addr == INADDR_ANY);
411   }
412   if (bind(sock, (struct sockaddr *)&sin4, sizeof(sin4)) < 0) {
413     OLSR_ERROR(LOG_NETWORKING, "Coult not bind socket for OLSR PDUs to port (%s)\n", strerror(errno));
414     close(sock);
415     olsr_exit(EXIT_FAILURE);
416   }
417
418   set_nonblocking(sock);
419   return sock;
420 }
421
422
423 /**
424  *Creates a nonblocking IPv6 socket
425  *@param sin sockaddr_in6 struct. Used for bind(2).
426  *@return the FD of the socket or -1 on error.
427  */
428 int
429 getsocket6(int bufspace, struct interface *ifp, bool bind_to_unicast, uint16_t port)
430 {
431   struct sockaddr_in6 sin6;
432   int on;
433   int sock = socket(AF_INET6, SOCK_DGRAM, 0);
434   if (sock < 0) {
435     OLSR_ERROR(LOG_NETWORKING, "Cannot open socket for OLSR PDUs (%s)\n", strerror(errno));
436     olsr_exit(EXIT_FAILURE);
437   }
438 #ifdef IPV6_V6ONLY
439   on = 1;
440   if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
441     OLSR_WARN(LOG_NETWORKING, "Cannot set socket for OLSR PDUs to ipv6 only (%s)\n", strerror(errno));
442   }
443 #endif
444
445
446   //#ifdef SO_BROADCAST
447   /*
448      if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof(on)) < 0)
449      {
450      perror("setsockopt");
451      syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
452      close(sock);
453      return (-1);
454      }
455    */
456   //#endif
457
458 #ifdef SO_RCVBUF
459   if(bufspace > 0) {
460     for (on = bufspace;; on -= 1024) {
461       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0) {
462         OLSR_DEBUG(LOG_NETWORKING, "Set socket buffer space to %d\n", on);
463         break;
464       }
465       if (on <= 8 * 1024) {
466         OLSR_WARN(LOG_NETWORKING, "Could not set a socket buffer space for OLSR PDUs (%s)\n", strerror(errno));
467         break;
468       }
469     }
470   }
471 #endif
472
473   on = 1;
474   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
475     OLSR_ERROR(LOG_NETWORKING, "Cannot reuse address for socket for OLSR PDUs (%s)\n", strerror(errno));
476     close(sock);
477     olsr_exit(EXIT_FAILURE);
478   }
479
480   /*
481    * we are abusing "on" here. The value is 1 which is our intended
482    * hop limit value.
483    */
484   if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &on, sizeof(on)) < 0) {
485     OLSR_ERROR(LOG_NETWORKING, "Cannot set multicast hops to 1 for socket for OLSR PDUs (%s)\n", strerror(errno));
486     close(sock);
487     olsr_exit(EXIT_FAILURE);
488   }
489
490
491   /*
492    * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
493    */
494
495   /* Bind to device */
496   if (bind_socket_to_device(sock, ifp->int_name) < 0) {
497     OLSR_ERROR(LOG_NETWORKING, "Cannot bind socket for OLSR PDUs to interface %s (%s)\n", ifp->int_name, strerror(errno));
498     close(sock);
499     olsr_exit(EXIT_FAILURE);
500   }
501
502   memset(&sin6, 0, sizeof(sin6));
503   sin6.sin6_family = AF_INET6;
504   sin6.sin6_port = htons(port);
505
506   if(bind_to_unicast) {
507     memcpy(&sin6.sin6_addr, &ifp->int_src.v6.sin6_addr, sizeof(struct in6_addr));
508   }
509   else {
510     assert(0 == memcmp(&sin6.sin6_addr, &in6addr_any, sizeof(sin6.sin6_addr)));   /* == IN6ADDR_ANY_INIT */
511   }
512   if (bind(sock, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
513     OLSR_ERROR(LOG_NETWORKING, "Cannot bind socket for OLSR PDUs (%s)\n", strerror(errno));
514     close(sock);
515     olsr_exit(EXIT_FAILURE);
516   }
517
518   set_nonblocking(sock);
519   return sock;
520 }
521
522 void
523 os_set_olsr_socketoptions(int sock) {
524   /* Set TOS */
525   int data = IPTOS_PREC(olsr_cnf->tos);
526   if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (char *)&data, sizeof(data)) < 0) {
527     OLSR_WARN(LOG_INTERFACE, "setsockopt(SO_PRIORITY) error %s", strerror(errno));
528   }
529   data = IPTOS_TOS(olsr_cnf->tos);
530   if (setsockopt(sock, SOL_IP, IP_TOS, (char *)&data, sizeof(data)) < 0) {
531     OLSR_WARN(LOG_INTERFACE, "setsockopt(IP_TOS) error %s", strerror(errno));
532   }
533 }
534
535 int
536 join_mcast(struct interface *ifs, int sock)
537 {
538   /* See linux/in6.h */
539 #if !defined REMOVE_LOG_INFO
540   struct ipaddr_str buf;
541 #endif
542   struct ipv6_mreq mcastreq;
543
544   mcastreq.ipv6mr_multiaddr = ifs->int_multicast.v6.sin6_addr;
545   mcastreq.ipv6mr_interface = ifs->if_index;
546
547   OLSR_INFO(LOG_NETWORKING, "Interface %s joining multicast %s\n", ifs->int_name,
548             olsr_sockaddr_to_string(&buf, &ifs->int_multicast));
549   /* Send multicast */
550   if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq))
551       < 0) {
552     OLSR_WARN(LOG_NETWORKING, "Cannot join multicast group (%s)\n", strerror(errno));
553     return -1;
554   }
555 #if 0
556   /* Old libc fix */
557 #ifdef IPV6_JOIN_GROUP
558   /* Join reciever group */
559   if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcastreq, sizeof(struct ipv6_mreq))
560       < 0)
561 #else
562   /* Join reciever group */
563   if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq))
564       < 0)
565 #endif
566   {
567     perror("Join multicast send");
568     return -1;
569   }
570 #endif
571   if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&mcastreq.ipv6mr_interface, sizeof(mcastreq.ipv6mr_interface))
572       < 0) {
573     OLSR_WARN(LOG_NETWORKING, "Cannot set multicast interface (%s)\n", strerror(errno));
574     return -1;
575   }
576
577   return 0;
578 }
579
580 /*
581  *From net-tools lib/interface.c
582  *
583  */
584 int
585 get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int addrtype6)
586 {
587   int rv = 0;
588   FILE *f = fopen(_PATH_PROCNET_IFINET6, "r");
589   if (f != NULL) {
590     char devname[IFNAMSIZ];
591     char addr6p[8][5];
592     int plen, scope, dad_status, if_idx;
593     bool found = false;
594     while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
595                   addr6p[0], addr6p[1], addr6p[2], addr6p[3],
596                   addr6p[4], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
597       if (strcmp(devname, ifname) == 0) {
598         char addr6[40];
599         sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
600                 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
601
602         if (addrtype6 == OLSR_IP6T_SITELOCAL && scope == IPV6_ADDR_SITELOCAL)
603           found = true;
604         else if (addrtype6 == OLSR_IP6T_UNIQUELOCAL && scope == IPV6_ADDR_GLOBAL)
605           found = true;
606         else if (addrtype6 == OLSR_IP6T_GLOBAL && scope == IPV6_ADDR_GLOBAL)
607           found = true;
608
609         if (found) {
610           found = false;
611           if (addr6p[0][0] == 'F' || addr6p[0][0] == 'f') {
612             if (addr6p[0][1] == 'C' || addr6p[0][1] == 'c' || addr6p[0][1] == 'D' || addr6p[0][1] == 'd')
613               found = true;
614           }
615           if (addrtype6 == OLSR_IP6T_SITELOCAL)
616             found = true;
617           else if (addrtype6 == OLSR_IP6T_UNIQUELOCAL && found)
618             found = true;
619           else if (addrtype6 == OLSR_IP6T_GLOBAL && !found)
620             found = true;
621           else
622             found = false;
623         }
624
625         if (found) {
626           inet_pton(AF_INET6, addr6, &saddr6->sin6_addr);
627           rv = 1;
628           break;
629         }
630       }
631     }
632     fclose(f);
633   }
634   return rv;
635 }
636
637
638 /**
639  * Wrapper for sendto(2)
640  */
641 ssize_t
642 olsr_sendto(int s, const void *buf, size_t len, int flags, const union olsr_sockaddr *sockaddr)
643 {
644   return sendto(s, buf, len, flags, &sockaddr->std, sizeof(*sockaddr));
645 }
646
647 /**
648  * Wrapper for recvfrom(2)
649  */
650
651 ssize_t
652 olsr_recvfrom(int s, void *buf, size_t len, int flags,
653     union olsr_sockaddr *sockaddr, socklen_t *socklen)
654 {
655   return recvfrom(s, buf, len, flags, &sockaddr->std, socklen);
656 }
657
658 /**
659  * Wrapper for select(2)
660  */
661
662 int
663 olsr_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
664 {
665   return select(nfds, readfds, writefds, exceptfds, timeout);
666 }
667 /*
668  * Local Variables:
669  * c-basic-offset: 2
670  * indent-tabs-mode: nil
671  * End:
672  */