Fix for glibc must be here too
[olsrd.git] / src / unix / ifnet.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
43 #define ifr_netmask ifr_addr
44 #endif
45
46 #include "ifnet.h"
47 #include "ipcalc.h"
48 #include "interfaces.h"
49 #include "defs.h"
50 #include "olsr.h"
51 #include "net_os.h"
52 #include "net_olsr.h"
53 #include "parser.h"
54 #include "scheduler.h"
55 #include "generate_msg.h"
56 #include "mantissa.h"
57 #include "lq_packet.h"
58 #include "log.h"
59 #include "link_set.h"
60
61 #include <signal.h>
62 #include <sys/types.h>
63 #include <net/if.h>
64 #include <net/if_arp.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/ip.h>
67 #include <arpa/inet.h>
68 #include <netdb.h>
69 #include <unistd.h>
70
71 /**
72  * Fix bug in GLIBC, see https://bugzilla.redhat.com/show_bug.cgi?id=635260
73  */
74 #ifdef IPTOS_CLASS
75 #undef IPTOS_CLASS
76 #endif
77 #define IPTOS_CLASS(class)    ((class) & IPTOS_CLASS_MASK)
78
79 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
80
81 int
82 set_flag(char *ifname, short flag __attribute__ ((unused)))
83 {
84   struct ifreq ifr;
85
86   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
87
88   /* Get flags */
89   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
90     fprintf(stderr, "ioctl (get interface flags)");
91     return -1;
92   }
93
94   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
95
96   //printf("Setting flags for if \"%s\"\n", ifr.ifr_name);
97
98   if (!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING))) {
99     /* Add UP */
100     ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
101     /* Set flags + UP */
102     if (ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0) {
103       fprintf(stderr, "ERROR(%s): %s\n", ifr.ifr_name, strerror(errno));
104       return -1;
105     }
106   }
107   return 1;
108
109 }
110
111 void
112 check_interface_updates(void *foo __attribute__ ((unused)))
113 {
114   struct olsr_if *tmp_if;
115
116 #ifdef DEBUG
117   OLSR_PRINTF(3, "Checking for updates in the interface set\n");
118 #endif
119
120   for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
121     if (tmp_if->host_emul)
122       continue;
123
124     if (olsr_cnf->host_emul)    /* XXX: TEMPORARY! */
125       continue;
126
127     if (!tmp_if->cnf->autodetect_chg) {
128 #ifdef DEBUG
129       /* Don't check this interface */
130       OLSR_PRINTF(3, "Not checking interface %s\n", tmp_if->name);
131 #endif
132       continue;
133     }
134
135     if (tmp_if->configured) {
136       chk_if_changed(tmp_if);
137     } else {
138       chk_if_up(tmp_if, 3);
139     }
140   }
141
142   return;
143 }
144
145 /**
146  * Checks if an initialized interface is changed
147  * that is if it has been set down or the address
148  * has been changed.
149  *
150  *@param iface the olsr_if struct describing the interface
151  */
152 int
153 chk_if_changed(struct olsr_if *iface)
154 {
155   struct interface *ifp;
156   struct ifreq ifr;
157   struct sockaddr_in6 tmp_saddr6;
158   int if_changes;
159   if_changes = 0;
160
161 #ifdef DEBUG
162   OLSR_PRINTF(3, "Checking if %s is set down or changed\n", iface->name);
163 #endif
164
165   if (iface->host_emul)
166     return -1;
167
168   ifp = iface->interf;
169
170   if (ifp == NULL) {
171     /* Should not happen */
172     iface->configured = 0;
173     return 0;
174   }
175
176   memset(&ifr, 0, sizeof(struct ifreq));
177   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
178
179   /* Get flags (and check if interface exists) */
180   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
181     OLSR_PRINTF(3, "No such interface: %s\n", iface->name);
182     goto remove_interface;
183   }
184
185   ifp->int_flags = ifr.ifr_flags;
186
187   /*
188    * First check if the interface is set DOWN
189    */
190
191   if ((ifp->int_flags & IFF_UP) == 0 || (ifp->int_flags & IFF_RUNNING) == 0) {
192     OLSR_PRINTF(1, "\tInterface %s not up and running - removing it...\n", iface->name);
193     goto remove_interface;
194   }
195
196   /*
197    * We do all the interface type checks over.
198    * This is because the interface might be a PCMCIA card. Therefore
199    * It might not be the same physical interface as we configured earlier.
200    */
201
202   /* Check broadcast */
203   if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr &&     /* Skip if fixed bcast */
204       (!(ifp->int_flags & IFF_BROADCAST))) {
205     OLSR_PRINTF(3, "\tNo broadcast - removing\n");
206     goto remove_interface;
207   }
208
209   if (ifp->int_flags & IFF_LOOPBACK) {
210     OLSR_PRINTF(3, "\tThis is a loopback interface - removing it...\n");
211     goto remove_interface;
212   }
213
214   ifp->is_hcif = false;
215
216   /* trying to detect if interface is wireless. */
217   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
218
219   /* Set interface metric */
220   if (iface->cnf->weight.fixed)
221     ifp->int_metric = iface->cnf->weight.value;
222   else
223     ifp->int_metric = calculate_if_metric(ifr.ifr_name);
224
225   /* Get MTU */
226   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
227     ifp->int_mtu = 0;
228   else {
229     ifr.ifr_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
230
231     if (ifp->int_mtu != ifr.ifr_mtu) {
232       ifp->int_mtu = ifr.ifr_mtu;
233       /* Create new outputbuffer */
234       net_remove_buffer(ifp);   /* Remove old */
235       net_add_buffer(ifp);
236     }
237   }
238
239   /* Get interface index */
240   ifp->if_index = if_nametoindex(ifr.ifr_name);
241
242   /*
243    * Now check if the IP has changed
244    */
245
246   /* IP version 6 */
247   if (olsr_cnf->ip_version == AF_INET6) {
248     struct ipaddr_str buf;
249     /* Get dst interface address */
250
251     if (0 == get_ipv6_address(iface->name, &tmp_saddr6, (iface->cnf->ipv6_src.prefix_len == 0) ? NULL : (&iface->cnf->ipv6_src))) {
252       OLSR_PRINTF(3, "\tCould not find ip address for %s with prefix %s.\n", ifr.ifr_name, olsr_ip_prefix_to_string(&iface->cnf->ipv6_src));
253       goto remove_interface;
254     }
255
256 #ifdef DEBUG
257     OLSR_PRINTF(3, "\tAddress: %s\n", ip6_to_string(&buf, &iface->cnf->ipv6_multicast.v6));
258 #endif
259
260     if (memcmp(&tmp_saddr6.sin6_addr, &ifp->int6_addr.sin6_addr, olsr_cnf->ipsize) != 0) {
261       OLSR_PRINTF(1, "New IP address for %s:\n", ifr.ifr_name);
262       OLSR_PRINTF(1, "\tOld: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
263       OLSR_PRINTF(1, "\tNew: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
264
265       /* deactivated to prevent change of originator IP */
266 #if 0
267       /* Check main addr */
268       if (memcmp(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize) == 0) {
269         /* Update main addr */
270         memcpy(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
271       }
272 #endif
273       /* Update address */
274       memcpy(&ifp->int6_addr.sin6_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
275       memcpy(&ifp->ip_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
276
277       olsr_trigger_ifchange(ifp->if_index, ifp, IFCHG_IF_UPDATE);
278
279       /* we have to make sure that olsrd uses the new source address of this interface */
280       olsr_remove_interface(iface); /* so we remove the interface completely */
281       chk_if_up(iface,3); /* and create it again to get new sockets,..*/
282     }
283     return 0;
284
285   } else
286     /* IP version 4 */
287   {
288     struct ipaddr_str buf;
289     /* Check interface address (IPv4) */
290     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
291       OLSR_PRINTF(1, "\tCould not get address of interface - removing it\n");
292       goto remove_interface;
293     }
294 #ifdef DEBUG
295     OLSR_PRINTF(3, "\tAddress:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
296 #endif
297
298     if (memcmp
299         (&((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifp->int_addr))->sin_addr.s_addr, &((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr.s_addr,
300          olsr_cnf->ipsize) != 0) {
301       /* New address */
302       OLSR_PRINTF(1, "IPv4 address changed for %s\n", ifr.ifr_name);
303       OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
304       OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
305
306       ifp->int_addr = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_addr);
307       /* deactivated to prevent change of originator IP */
308 #if 0
309       if (memcmp(&olsr_cnf->main_addr, &ifp->ip_addr, olsr_cnf->ipsize) == 0) {
310         OLSR_PRINTF(1, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
311         olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
312         memcpy(&olsr_cnf->main_addr, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, olsr_cnf->ipsize);
313       }
314 #endif
315       memcpy(&ifp->ip_addr, &((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr.s_addr, olsr_cnf->ipsize);
316
317       /* we have to make sure that olsrd uses the new source address of this interface */
318       olsr_remove_interface(iface); /* so we remove the interface completely */
319       chk_if_up(iface,3); /* and create it again to get new sockets,..*/
320       return 0;
321     }
322
323     /* Check netmask */
324     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
325       olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
326       goto remove_interface;
327     }
328 #ifdef DEBUG
329     OLSR_PRINTF(3, "\tNetmask:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
330 #endif
331
332     if (memcmp
333         (&((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifp->int_netmask))->sin_addr.s_addr, &((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_netmask))->sin_addr.s_addr,
334          olsr_cnf->ipsize) != 0) {
335       /* New address */
336       OLSR_PRINTF(1, "IPv4 netmask changed for %s\n", ifr.ifr_name);
337       OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
338       OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
339
340       ifp->int_netmask = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_netmask);
341
342       if_changes = 1;
343     }
344
345     if (!iface->cnf->ipv4_multicast.v4.s_addr) {
346       /* Check broadcast address */
347       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
348         olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
349         goto remove_interface;
350       }
351 #ifdef DEBUG
352       OLSR_PRINTF(3, "\tBroadcast address:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
353 #endif
354
355       if (ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr.s_addr) {
356         /* New address */
357         OLSR_PRINTF(1, "IPv4 broadcast changed for %s\n", ifr.ifr_name);
358         OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
359         OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
360
361         ifp->int_broadaddr = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr);
362         if_changes = 1;
363       }
364     }
365   }
366
367   if (if_changes)
368     olsr_trigger_ifchange(ifp->if_index, ifp, IFCHG_IF_UPDATE);
369
370   return if_changes;
371
372 remove_interface:
373
374   olsr_remove_interface(iface);
375   return 0;
376 }
377
378 /**
379  * Initializes the special interface used in
380  * host-client emulation
381  */
382 int
383 add_hemu_if(struct olsr_if *iface)
384 {
385   struct interface *ifp;
386   union olsr_ip_addr null_addr;
387   uint32_t addr[4];
388   struct ipaddr_str buf;
389   size_t name_size;
390
391   if (!iface->host_emul)
392     return -1;
393
394   ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
395
396   memset(ifp, 0, sizeof(struct interface));
397
398   /* initialize backpointer */
399   ifp->olsr_if = iface;
400
401   iface->configured = true;
402   iface->interf = ifp;
403
404   name_size = strlen("hcif01") + 1;
405   ifp->is_hcif = true;
406   ifp->int_name = olsr_malloc(name_size, "Interface update 3");
407   ifp->int_metric = 0;
408
409   strscpy(ifp->int_name, "hcif01", name_size);
410
411   OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
412
413   OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
414
415   OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
416
417   ifp->int_next = ifnet;
418   ifnet = ifp;
419
420   memset(&null_addr, 0, olsr_cnf->ipsize);
421   if (ipequal(&null_addr, &olsr_cnf->main_addr)) {
422     olsr_cnf->main_addr = iface->hemu_ip;
423     olsr_cnf->unicast_src_ip = iface->hemu_ip;
424     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
425     olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
426   }
427
428   ifp->int_mtu = OLSR_DEFAULT_MTU;
429
430   ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
431
432   /* Set up buffer */
433   net_add_buffer(ifp);
434
435   if (olsr_cnf->ip_version == AF_INET) {
436     struct sockaddr_in sin;
437
438     memset(&sin, 0, sizeof(sin));
439
440     sin.sin_family = AF_INET;
441     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
442     sin.sin_port = htons(10150);
443
444     /* IP version 4 */
445     ifp->ip_addr.v4 = iface->hemu_ip.v4;
446
447     memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
448
449     /*
450      *We create one socket for each interface and bind
451      *the socket to it. This to ensure that we can control
452      *on what interface the message is transmitted
453      */
454
455     ifp->olsr_socket = gethemusocket(&sin);
456
457     if (ifp->olsr_socket < 0) {
458       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
459       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
460       olsr_cnf->exit_value = EXIT_FAILURE;
461       kill(getpid(), SIGINT);
462     }
463
464   } else {
465     /* IP version 6 */
466     memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
467
468 #if 0
469     /*
470      *We create one socket for each interface and bind
471      *the socket to it. This to ensure that we can control
472      *on what interface the message is transmitted
473      */
474
475     ifp->olsr_socket = gethcsocket6(&addrsock6, BUFSPACE, ifp->int_name);
476
477     join_mcast(ifp, ifp->olsr_socket);
478
479     if (ifp->olsr_socket < 0) {
480       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
481       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
482       olsr_cnf->exit_value = EXIT_FAILURE;
483       kill(getpid(), SIGINT);
484     }
485 #endif
486   }
487
488   /* Send IP as first 4/16 bytes on socket */
489   memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
490   addr[0] = htonl(addr[0]);
491   addr[1] = htonl(addr[1]);
492   addr[2] = htonl(addr[2]);
493   addr[3] = htonl(addr[3]);
494
495   if (send(ifp->olsr_socket, addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize) {
496     fprintf(stderr, "Error sending IP!");
497   }
498
499   /* Register socket */
500   add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu, NULL, NULL, SP_PR_READ);
501
502   /*
503    * Register functions for periodic message generation
504    */
505
506   ifp->hello_gen_timer =
507     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
508                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
509   ifp->tc_gen_timer =
510     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
511                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
512   ifp->mid_gen_timer =
513     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
514                      mid_gen_timer_cookie);
515   ifp->hna_gen_timer =
516     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
517                      hna_gen_timer_cookie);
518
519   /* Recalculate max topology hold time */
520   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
521     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
522
523   ifp->hello_etime = (olsr_reltime) (iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
524   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
525   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
526   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
527   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
528
529   ifp->mode = iface->cnf->mode;
530
531   return 1;
532 }
533
534 static char basenamestr[32];
535 static const char *if_basename(const char *name);
536 static const char *
537 if_basename(const char *name)
538 {
539   char *p = strchr(name, ':');
540   if (NULL == p || p - name >= (int)(sizeof(basenamestr) / sizeof(basenamestr[0]) - 1)) {
541     return name;
542   }
543   memcpy(basenamestr, name, p - name);
544   basenamestr[p - name] = 0;
545   return basenamestr;
546 }
547
548 /**
549  * Initializes a interface described by iface,
550  * if it is set up and is of the correct type.
551  *
552  *@param iface the olsr_if struct describing the interface
553  *@param so the socket to use for ioctls
554  *
555  */
556 int
557 chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
558 {
559   struct interface ifs, *ifp;
560   struct ifreq ifr;
561   union olsr_ip_addr null_addr;
562   size_t name_size;
563 #ifdef linux
564   int precedence = IPTOS_PREC(olsr_cnf->tos);
565   int tos_bits = IPTOS_TOS(olsr_cnf->tos);
566 #endif
567
568   if (iface->host_emul)
569     return -1;
570
571   memset(&ifr, 0, sizeof(struct ifreq));
572   memset(&ifs, 0, sizeof(struct interface));
573   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
574
575   OLSR_PRINTF(debuglvl, "Checking %s:\n", ifr.ifr_name);
576
577   /* Get flags (and check if interface exists) */
578   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
579     OLSR_PRINTF(debuglvl, "\tNo such interface!\n");
580     return 0;
581   }
582
583   ifs.int_flags = ifr.ifr_flags;
584
585   if ( ( (ifs.int_flags & IFF_UP) == 0) || ( (ifs.int_flags & IFF_RUNNING) == 0) ) {
586     OLSR_PRINTF(debuglvl, "\tInterface not up & running - skipping it...\n");
587     return 0;
588   }
589
590   /* Check broadcast */
591   if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr &&     /* Skip if fixed bcast */
592       (!(ifs.int_flags & IFF_BROADCAST))) {
593     OLSR_PRINTF(debuglvl, "\tNo broadcast - skipping\n");
594     return 0;
595   }
596
597   if (ifs.int_flags & IFF_LOOPBACK) {
598     OLSR_PRINTF(debuglvl, "\tThis is a loopback interface - skipping it...\n");
599     return 0;
600   }
601
602   ifs.is_hcif = false;
603
604   /* trying to detect if interface is wireless. */
605   ifs.is_wireless = check_wireless_interface(ifr.ifr_name);
606
607   if (ifs.is_wireless)
608     OLSR_PRINTF(debuglvl, "\tWireless interface detected\n");
609   else
610     OLSR_PRINTF(debuglvl, "\tNot a wireless interface\n");
611
612   /* IP version 6 */
613   if (olsr_cnf->ip_version == AF_INET6) {
614     /* Get interface address */
615     struct ipaddr_str buf;
616
617     if (0 == get_ipv6_address(iface->name, &ifs.int6_addr, (iface->cnf->ipv6_src.prefix_len == 0) ? NULL : (&iface->cnf->ipv6_src))) {
618       OLSR_PRINTF(3, "\tCould not find ip address for %s with prefix %s.\n", ifr.ifr_name, olsr_ip_prefix_to_string(&iface->cnf->ipv6_src));
619       return 0;
620     }
621     OLSR_PRINTF(debuglvl, "\tAddress: %s\n", ip6_to_string(&buf, &iface->cnf->ipv6_multicast.v6));
622
623     /* Multicast */
624     memset(&ifs.int6_multaddr, 0, sizeof(ifs.int6_multaddr));
625     ifs.int6_multaddr.sin6_family = AF_INET6;
626     ifs.int6_multaddr.sin6_flowinfo = htonl(0);
627     ifs.int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
628     ifs.int6_multaddr.sin6_port = htons(olsr_cnf->olsrport);
629     ifs.int6_multaddr.sin6_addr =  iface->cnf->ipv6_multicast.v6;
630
631 #ifdef __MacOSX__
632     ifs.int6_multaddr.sin6_scope_id = 0;
633 #endif
634
635     OLSR_PRINTF(debuglvl, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
636
637   }
638   /* IP version 4 */
639   else {
640     /* Get interface address (IPv4) */
641     if (iface->cnf->ipv4_src.v4.s_addr) {
642       ifs.int_addr.sin_addr = iface->cnf->ipv4_src.v4;
643     }
644     else {
645       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
646         OLSR_PRINTF(debuglvl, "\tCould not get address of interface - skipping it\n");
647         return 0;
648       }
649
650       ifs.int_addr = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_addr);
651     }
652     /* Find netmask */
653     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
654       olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get netmask)", ifr.ifr_name);
655       return 0;
656     }
657
658     ifs.int_netmask = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_netmask);
659
660     /* Find broadcast address */
661     if (iface->cnf->ipv4_multicast.v4.s_addr) {
662       /* Specified broadcast */
663       memcpy(&((struct sockaddr_in *)&ifs.int_broadaddr)->sin_addr.s_addr, &iface->cnf->ipv4_multicast.v4, sizeof(uint32_t));
664     } else {
665       /* Autodetect */
666       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
667         olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
668         return 0;
669       }
670
671       ifs.int_broadaddr = *(struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr);
672     }
673
674     /* Deactivate IP spoof filter */
675     /* Disable ICMP redirects */
676     net_os_set_ifoptions(if_basename(ifr.ifr_name), &ifs);
677   }
678
679   /* Get interface index */
680
681   ifs.if_index = if_nametoindex(ifr.ifr_name);
682
683   /* Set interface metric */
684   if (iface->cnf->weight.fixed)
685     ifs.int_metric = iface->cnf->weight.value;
686   else
687     ifs.int_metric = calculate_if_metric(ifr.ifr_name);
688   OLSR_PRINTF(1, "\tMetric: %d\n", ifs.int_metric);
689
690   /* Get MTU */
691   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
692     ifs.int_mtu = OLSR_DEFAULT_MTU;
693   else
694     ifs.int_mtu = ifr.ifr_mtu;
695
696   ifs.int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
697
698   ifs.ttl_index = -32;          /* For the first 32 TC's, fish-eye is disabled */
699
700   /* Set up buffer */
701   net_add_buffer(&ifs);
702
703   OLSR_PRINTF(1, "\tMTU - IPhdr: %d\n", ifs.int_mtu);
704
705   olsr_syslog(OLSR_LOG_INFO, "Adding interface %s\n", iface->name);
706   OLSR_PRINTF(1, "\tIndex %d\n", ifs.if_index);
707
708   if (olsr_cnf->ip_version == AF_INET) {
709     struct ipaddr_str buf;
710     OLSR_PRINTF(1, "\tAddress:%s\n", ip4_to_string(&buf, ifs.int_addr.sin_addr));
711     OLSR_PRINTF(1, "\tNetmask:%s\n", ip4_to_string(&buf, ifs.int_netmask.sin_addr));
712     OLSR_PRINTF(1, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifs.int_broadaddr.sin_addr));
713   } else {
714     struct ipaddr_str buf;
715     OLSR_PRINTF(1, "\tAddress: %s\n", ip6_to_string(&buf, &ifs.int6_addr.sin6_addr));
716     OLSR_PRINTF(1, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
717   }
718
719   name_size = strlen(if_basename(ifr.ifr_name)) + 1;
720   ifs.int_name = olsr_malloc(name_size, "Interface update 3");
721   strscpy(ifs.int_name, if_basename(ifr.ifr_name), name_size);
722
723   if (olsr_cnf->ip_version == AF_INET) {
724     /* IP version 4 */
725     ifs.ip_addr.v4 = ifs.int_addr.sin_addr;
726     /*
727      *We create one socket for each interface and bind
728      *the socket to it. This to ensure that we can control
729      *on what interface the message is transmitted
730      */
731
732     ifs.olsr_socket = getsocket(BUFSPACE, &ifs);
733     ifs.send_socket = getsocket(0, &ifs);
734
735     if (ifs.olsr_socket < 0) {
736       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
737       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
738       olsr_cnf->exit_value = EXIT_FAILURE;
739       free(ifs.int_name);
740       kill(getpid(), SIGINT);
741       return 0;
742     }
743     if (ifs.send_socket < 0) {
744       OLSR_PRINTF(1, "Warning, transmission socket could not be initialized. Abort if-up.\n");
745       close (ifs.olsr_socket);
746       free(ifs.int_name);
747       return 0;
748     }
749   } else {
750     /* IP version 6 */
751     ifs.ip_addr.v6 = ifs.int6_addr.sin6_addr;
752
753     /*
754      *We create one socket for each interface and bind
755      *the socket to it. This to ensure that we can control
756      *on what interface the message is transmitted
757      */
758
759     ifs.olsr_socket = getsocket6(BUFSPACE, &ifs);
760     ifs.send_socket = getsocket6(0, &ifs);
761
762     if (ifs.olsr_socket < 0) {
763       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
764       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
765       olsr_cnf->exit_value = EXIT_FAILURE;
766       free(ifs.int_name);
767       kill(getpid(), SIGINT);
768       return 0;
769     }
770     if (ifs.send_socket < 0) {
771       OLSR_PRINTF(1, "Warning, transmission socket could not be initialized. Abort if-up.\n");
772       close (ifs.olsr_socket);
773       free(ifs.int_name);
774       return 0;
775     }
776
777     join_mcast(&ifs, ifs.olsr_socket);
778     join_mcast(&ifs, ifs.send_socket);
779   }
780
781   ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
782
783   iface->configured = 1;
784   iface->interf = ifp;
785
786   /* XXX bad code */
787   memcpy(ifp, &ifs, sizeof(struct interface));
788
789   /* initialize backpointer */
790   ifp->olsr_if = iface;
791
792   ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
793   if (olsr_cnf->max_jitter == 0) {
794     /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
795     olsr_cnf->max_jitter =
796       ifp->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
797   }
798
799   ifp->gen_properties = NULL;
800   ifp->int_next = ifnet;
801   ifnet = ifp;
802
803   set_buffer_timer(ifp);
804
805   /* Register socket */
806   add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
807   add_olsr_socket(ifp->send_socket, &olsr_input, NULL, NULL, SP_PR_READ);
808
809 #ifdef linux
810   /* Set TOS */
811
812   if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char *)&precedence, sizeof(precedence)) < 0) {
813     perror("setsockopt(SO_PRIORITY)");
814     olsr_syslog(OLSR_LOG_ERR, "OLSRD: setsockopt(SO_PRIORITY) error %m");
815   }
816   if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char *)&tos_bits, sizeof(tos_bits)) < 0) {
817     perror("setsockopt(IP_TOS)");
818     olsr_syslog(OLSR_LOG_ERR, "setsockopt(IP_TOS) error %m");
819   }
820 #endif
821
822   /*
823    *Initialize sequencenumber as a random 16bit value
824    */
825   ifp->olsr_seqnum = random() & 0xFFFF;
826
827   /*
828    * Set main address if this is the only interface
829    */
830   memset(&null_addr, 0, olsr_cnf->ipsize);
831   if (ipequal(&null_addr, &olsr_cnf->main_addr)) {
832     struct ipaddr_str buf;
833     olsr_cnf->main_addr = ifp->ip_addr;
834     olsr_cnf->unicast_src_ip = ifp->ip_addr;
835     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
836     olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
837   }
838
839   /*
840    * Register functions for periodic message generation
841    */
842   ifp->hello_gen_timer =
843     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
844                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
845   ifp->tc_gen_timer =
846     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
847                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
848   ifp->mid_gen_timer =
849     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
850                      mid_gen_timer_cookie);
851   ifp->hna_gen_timer =
852     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
853                      hna_gen_timer_cookie);
854
855   /* Recalculate max topology hold time */
856   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval) {
857     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
858   }
859   ifp->hello_etime = (olsr_reltime) (iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
860   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
861   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
862   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
863   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
864
865   ifp->mode = iface->cnf->mode;
866
867   /*
868    *Call possible ifchange functions registered by plugins
869    */
870   olsr_trigger_ifchange(ifp->if_index, ifp, IFCHG_IF_ADD);
871
872   return 1;
873 }
874
875 /*
876  * Local Variables:
877  * c-basic-offset: 2
878  * indent-tabs-mode: nil
879  * End:
880  */