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