Rename olsr_time.[ch] to olsr_clock.[ch]
[olsrd.git] / src / unix / ifnet.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 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
44 #define ifr_netmask ifr_addr
45 #endif
46
47 #include "ipcalc.h"
48 #include "interfaces.h"
49 #include "defs.h"
50 #include "olsr.h"
51 #include "os_net.h"
52 #include "net_olsr.h"
53 #include "parser.h"
54 #include "olsr_timer.h"
55 #include "olsr_socket.h"
56 #include "olsr_clock.h"
57 #include "lq_packet.h"
58 #include "link_set.h"
59 #include "mid_set.h"
60 #include "hna_set.h"
61 #include "common/string.h"
62
63 #ifdef linux
64 #include "linux/linux_net.h"
65 #endif
66
67 #include <assert.h>
68 #include <signal.h>
69 #include <sys/types.h>
70 #include <net/if.h>
71 #include <net/if_arp.h>
72 #include <netinet/in_systm.h>
73 #include <netinet/ip.h>
74 #include <arpa/inet.h>
75 #include <netdb.h>
76 #include <unistd.h>
77 #include <errno.h>
78 #include <fcntl.h>
79
80 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
81
82 /**
83  * Wrapper for closing sockets
84  * @param
85  * @param sock
86  * @return
87  */
88 int
89 os_close(int sock) {
90   return close(sock);
91 }
92
93 /**
94  * Checks if an initialized interface is changed
95  * that is if it has been set down or the address
96  * has been changed.
97  *
98  *@param iface the olsr_if_config struct describing the interface
99  */
100 int
101 chk_if_changed(struct olsr_if_config *iface)
102 {
103 #if !defined REMOVE_LOG_DEBUG
104   struct ipaddr_str buf;
105 #endif
106   struct interface *ifp;
107   struct ifreq ifr;
108   int if_changes = 0;
109   int int_flags;
110
111   OLSR_DEBUG(LOG_INTERFACE, "Checking if %s is set down or changed\n", iface->name);
112
113   ifp = iface->interf;
114   if (!ifp) {
115     return 0;
116   }
117
118   memset(&ifr, 0, sizeof(ifr));
119   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
120   /* Get flags (and check if interface exists) */
121   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
122     OLSR_WARN(LOG_INTERFACE, "No such interface: %s\n", iface->name);
123     remove_interface(iface->interf);
124     return 0;
125   }
126   int_flags = ifr.ifr_flags;
127
128   /*
129    * First check if the interface is UP & RUNNING
130    * e.g. "NO-CARRIER" == only up but not running 
131    */
132   if ( ((int_flags & IFF_UP) == 0) || ((int_flags & IFF_RUNNING) == 0) ) {
133     OLSR_DEBUG(LOG_INTERFACE, "\tInterface %s not up & running - removing it...\n", iface->name);
134     remove_interface(iface->interf);
135     return 0;
136   }
137
138   /*
139    * We do all the interface type checks over.
140    * This is because the interface might be a PCMCIA card. Therefore
141    * it might not be the same physical interface as we configured earlier.
142    */
143
144   /* Check broadcast */
145   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
146       ((int_flags & IFF_BROADCAST)) == 0) {
147     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - removing\n");
148     remove_interface(iface->interf);
149     return 0;
150   }
151
152   if (int_flags & IFF_LOOPBACK) {
153     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - removing it...\n");
154     remove_interface(iface->interf);
155     return 0;
156   }
157
158   /* Get MTU */
159   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
160     ifp->int_mtu = 0;
161   } else {
162     ifr.ifr_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
163     if (ifp->int_mtu != ifr.ifr_mtu) {
164       ifp->int_mtu = ifr.ifr_mtu;
165       /* Create new outputbuffer */
166       net_remove_buffer(ifp);   /* Remove old */
167       net_add_buffer(ifp);
168     }
169   }
170
171   /* Get interface index */
172   ifp->if_index = if_nametoindex(ifr.ifr_name);
173
174   /*
175    * Now check if the IP has changed
176    */
177
178   /* IP version 6 */
179   if (olsr_cnf->ip_version == AF_INET6) {
180     struct sockaddr_in6 tmp_saddr6;
181
182     /* Get interface address */
183     if (get_ipv6_address(ifr.ifr_name, &tmp_saddr6, iface->cnf->ipv6_addrtype) <= 0) {
184       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
185         OLSR_WARN(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
186       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
187         OLSR_WARN(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
188       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
189         OLSR_WARN(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
190       else
191         OLSR_WARN(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
192       remove_interface(iface->interf);
193       return 0;
194     }
195
196     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
197
198     if (ip6cmp(&tmp_saddr6.sin6_addr, &ifp->int_src.v6.sin6_addr) != 0) {
199       OLSR_DEBUG(LOG_INTERFACE, "New IP address for %s:\n"
200                  "\tOld: %s\n\tNew: %s\n",
201                  ifr.ifr_name, ip6_to_string(&buf, &ifp->int_src.v6.sin6_addr), ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
202
203       /* Update address */
204       ifp->int_src.v6.sin6_addr = tmp_saddr6.sin6_addr;
205       ifp->ip_addr.v6 = tmp_saddr6.sin6_addr;
206
207       if_changes = 1;
208     }
209   } else {
210     /* IP version 4 */
211     const struct sockaddr_in *tmp_saddr4 = (struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_addr));
212
213     /* Check interface address (IPv4) */
214     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
215       OLSR_DEBUG(LOG_INTERFACE, "\tCould not get address of interface - removing it\n");
216       remove_interface(iface->interf);
217       return 0;
218     }
219
220     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_src.v4.sin_addr));
221
222     if (ip4cmp(&ifp->int_src.v4.sin_addr, &tmp_saddr4->sin_addr) != 0) {
223       /* New address */
224       OLSR_DEBUG(LOG_INTERFACE, "IPv4 address changed for %s\n"
225                  "\tOld:%s\n\tNew:%s\n",
226                  ifr.ifr_name, ip4_to_string(&buf, ifp->int_src.v4.sin_addr), ip4_to_string(&buf, tmp_saddr4->sin_addr));
227
228       ifp->int_src.v4 = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_addr));
229       ifp->ip_addr.v4 = tmp_saddr4->sin_addr;
230
231       if_changes = 1;
232     }
233
234     /* Check netmask */
235     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
236       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
237       remove_interface(iface->interf);
238       return 0;
239     }
240
241     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_netmask)))->sin_addr));
242
243     if (!iface->cnf->ipv4_broadcast.v4.s_addr) {
244       /* Check broadcast address */
245       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
246         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
247         return 0;
248       }
249
250       OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n",
251                  ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr)))->sin_addr));
252
253       if (ifp->int_multicast.v4.sin_addr.s_addr != ((struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr)))->sin_addr.s_addr) {
254         /* New address */
255         OLSR_DEBUG(LOG_INTERFACE, "IPv4 broadcast changed for %s\n"
256                    "\tOld:%s\n\tNew:%s\n",
257                    ifr.ifr_name,
258                    ip4_to_string(&buf, ifp->int_multicast.v4.sin_addr),
259                    ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr)))->sin_addr));
260
261         ifp->int_multicast.v4 = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr));
262         if_changes = 1;
263       }
264     }
265   }
266   if (if_changes) {
267     run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
268   }
269   return if_changes;
270 }
271
272 static const char *
273 if_basename(const char *name)
274 {
275   static char basenamestr[32];
276   const char *p = strchr(name, ':');
277   if (NULL == p || p - name >= (int)(ARRAYSIZE(basenamestr) - 1)) {
278     return name;
279   }
280   memcpy(basenamestr, name, p - name);
281   basenamestr[p - name] = 0;
282   return basenamestr;
283 }
284
285 /**
286  * Initializes a interface described by iface,
287  * if it is set up and is of the correct type.
288  *
289  *@param iface the olsr_if_config struct describing the interface
290  *@param so the socket to use for ioctls
291  *
292  */
293 int
294 os_init_interface(struct interface *ifp, struct olsr_if_config *iface)
295 {
296   struct ifreq ifr;
297   const char *ifr_basename;
298   int int_flags;
299 #if !defined REMOVE_LOG_DEBUG
300   struct ipaddr_str buf;
301 #endif
302
303   /*
304    * Sanity check.
305    */
306   assert (iface->interf == NULL);
307   assert (ifp);
308
309    /*
310    * Setup query block.
311    */
312   memset(&ifr, 0, sizeof(ifr));
313   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
314
315   OLSR_DEBUG(LOG_INTERFACE, "Checking %s:\n", ifr.ifr_name);
316
317   /* Get flags (and check if interface exists) */
318   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
319     OLSR_DEBUG(LOG_INTERFACE, "\tNo such interface!\n");
320     return -1;
321   }
322
323   int_flags = ifr.ifr_flags;
324   if ((int_flags & IFF_UP) == 0) {
325     OLSR_DEBUG(LOG_INTERFACE, "\tInterface not up - skipping it...\n");
326     return -1;
327   }
328
329   /* Check broadcast */
330   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
331       (int_flags & IFF_BROADCAST) == 0) {
332     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - skipping\n");
333     return -1;
334   }
335
336   if (int_flags & IFF_LOOPBACK) {
337     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - skipping it...\n");
338     return -1;
339   }
340
341   ifr_basename = if_basename(ifr.ifr_name);
342
343   /* IP version 6 */
344   if (olsr_cnf->ip_version == AF_INET6) {
345     /* Get interface address */
346     int result;
347
348     memset(&ifp->int_src, 0, sizeof(ifp->int_multicast));
349     ifp->int_src.v6.sin6_family = AF_INET6;
350     ifp->int_src.v6.sin6_flowinfo = htonl(0);
351     ifp->int_src.v6.sin6_scope_id = if_nametoindex(ifr.ifr_name);
352     ifp->int_src.v6.sin6_port = htons(olsr_cnf->olsr_port);
353
354     if (iface->cnf->ipv6_addrtype == OLSR_IP6T_AUTO) {
355       if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int_src.v6, OLSR_IP6T_SITELOCAL)) > 0) {
356         iface->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
357       } else {
358         if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int_src.v6, OLSR_IP6T_UNIQUELOCAL)) > 0) {
359           iface->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
360         } else {
361           if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int_src.v6, OLSR_IP6T_GLOBAL)) > 0) {
362             iface->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
363           }
364         }
365       }
366     } else {
367       result = get_ipv6_address(ifr.ifr_name, &ifp->int_src.v6, iface->cnf->ipv6_addrtype);
368     }
369
370     if (result <= 0) {
371       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
372         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
373       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
374         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
375       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
376         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
377       else
378         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
379       return -1;
380     }
381
382     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int_src.v6.sin6_addr));
383
384     /* Multicast */
385     memset(&ifp->int_multicast, 0, sizeof(ifp->int_multicast));
386     ifp->int_multicast.v6.sin6_family = AF_INET6;
387     ifp->int_multicast.v6.sin6_flowinfo = htonl(0);
388     ifp->int_multicast.v6.sin6_scope_id = if_nametoindex(ifr.ifr_name);
389     ifp->int_multicast.v6.sin6_port = htons(olsr_cnf->olsr_port);
390     ifp->int_multicast.v6.sin6_addr = iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL
391       ? iface->cnf->ipv6_multi_site.v6 : iface->cnf->ipv6_multi_glbl.v6;
392
393 #ifdef __MacOSX__
394     ifp->int6_multaddr.sin6_scope_id = 0;
395 #endif
396
397     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int_multicast.v6.sin6_addr));
398
399     ifp->ip_addr.v6 = ifp->int_src.v6.sin6_addr;
400   } else {
401     /* IP version 4 */
402     memset(&ifp->int_src, 0, sizeof(ifp->int_src));
403     memset(&ifp->int_multicast, 0, sizeof(ifp->int_multicast));
404
405     /* Get interface address (IPv4) */
406     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
407       OLSR_WARN(LOG_INTERFACE, "\tCould not get address of interface - skipping it\n");
408       return -1;
409     }
410
411     ifp->int_src.v4 = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_addr));
412
413     /* Find broadcast address */
414     if (iface->cnf->ipv4_broadcast.v4.s_addr) {
415       /* Specified broadcast */
416       ifp->int_multicast.v4.sin_addr = iface->cnf->ipv4_broadcast.v4;
417     } else {
418       /* Autodetect */
419       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
420         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
421         return -1;
422       }
423
424       ifp->int_multicast.v4 = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr));
425     }
426
427     ifp->int_src.v4.sin_family = AF_INET;
428     ifp->int_src.v4.sin_port = htons(olsr_cnf->olsr_port);
429     ifp->int_multicast.v4.sin_family = AF_INET;
430     ifp->int_multicast.v4.sin_port = htons(olsr_cnf->olsr_port);
431
432     ifp->ip_addr.v4 = ifp->int_src.v4.sin_addr;
433   }
434
435   /* check if interface with this IP already exists */
436   if (if_ifwithaddr(&ifp->ip_addr)) {
437     OLSR_ERROR(LOG_INTERFACE, "Warning, multiple interfaces with the same IP are deprecated. Use 'OriginatorAddress'"
438                " option if you fear a changing main address. Future versions of OLSR might block using multiple"
439                " interfaces with the same IP\n");
440   }
441
442   /* Get interface index */
443   ifp->if_index = if_nametoindex(ifr.ifr_name);
444
445   /* Get MTU */
446   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
447     ifp->int_mtu = OLSR_DEFAULT_MTU;
448   } else {
449     ifp->int_mtu = ifr.ifr_mtu;
450   }
451   ifp->int_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
452
453   OLSR_DEBUG(LOG_INTERFACE, "\tMTU - IPhdr: %d\n", ifp->int_mtu);
454
455   OLSR_INFO(LOG_INTERFACE, "Adding interface %s\n", iface->name);
456   OLSR_DEBUG(LOG_INTERFACE, "\tIndex %d\n", ifp->if_index);
457
458   if (olsr_cnf->ip_version == AF_INET) {
459     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_src.v4.sin_addr));
460     OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifp->int_multicast.v4.sin_addr));
461   } else {
462     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int_src.v6.sin6_addr));
463     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int_multicast.v6.sin6_addr));
464   }
465
466   /* Set interface options */
467 #ifdef linux
468   net_os_set_ifoptions(ifr_basename, ifp);
469 #endif
470
471   return 0;
472 }
473
474 void
475 os_cleanup_interface(struct interface *ifp) {
476 #ifdef linux
477   net_os_restore_ifoption(ifp);
478 #endif
479 }
480
481 int
482 os_socket_set_nonblocking(int fd)
483 {
484   /* make the fd non-blocking */
485   int socket_flags = fcntl(fd, F_GETFL);
486   if (socket_flags < 0) {
487     OLSR_WARN(LOG_NETWORKING, "Cannot get the socket flags: %s", strerror(errno));
488     return -1;
489   }
490   if (fcntl(fd, F_SETFL, socket_flags | O_NONBLOCK) < 0) {
491     OLSR_WARN(LOG_NETWORKING, "Cannot set the socket flags: %s", strerror(errno));
492     return -1;
493   }
494   return 0;
495 }
496
497
498 /*
499  * Local Variables:
500  * c-basic-offset: 2
501  * indent-tabs-mode: nil
502  * End:
503  */