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