unify HNA generation and put it into hna_set.c
[olsrd.git] / src / unix / ifnet.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42
43 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
44 #define ifr_netmask ifr_addr
45 #endif
46
47 #include "ifnet.h"
48 #include "ipcalc.h"
49 #include "interfaces.h"
50 #include "defs.h"
51 #include "olsr.h"
52 #include "net_os.h"
53 #include "net_olsr.h"
54 #include "parser.h"
55 #include "scheduler.h"
56 #include "olsr_time.h"
57 #include "lq_packet.h"
58 #include "log.h"
59 #include "link_set.h"
60 #include "mid_set.h"
61 #include "hna_set.h"
62 #include "../common/string.h"
63 #include "../valgrind/valgrind.h"
64
65 #include <signal.h>
66 #include <sys/types.h>
67 #include <net/if.h>
68 #include <net/if_arp.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/ip.h>
71 #include <arpa/inet.h>
72 #include <netdb.h>
73 #include <unistd.h>
74 #include <errno.h>
75
76 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
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 /**
107  * Checks if an initialized interface is changed
108  * that is if it has been set down or the address
109  * has been changed.
110  *
111  *@param iface the olsr_if_config struct describing the interface
112  */
113 int
114 chk_if_changed(struct olsr_if_config *iface)
115 {
116 #if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_INFO
117   struct ipaddr_str buf;
118 #endif
119   struct interface *ifp;
120   struct ifreq ifr;
121   int if_changes = 0;
122
123   OLSR_DEBUG(LOG_INTERFACE, "Checking if %s is set down or changed\n", iface->name);
124
125   ifp = iface->interf;
126   if (!ifp) {
127     return 0;
128   }
129
130   memset(&ifr, 0, sizeof(ifr));
131   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
132   /* Get flags (and check if interface exists) */
133   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
134     OLSR_WARN(LOG_INTERFACE, "No such interface: %s\n", iface->name);
135     remove_interface(&iface->interf);
136     return 0;
137   }
138   ifp->int_flags = ifr.ifr_flags;
139
140   /*
141    * First check if the interface is set DOWN
142    */
143   if ((ifp->int_flags & IFF_UP) == 0) {
144     OLSR_DEBUG(LOG_INTERFACE, "\tInterface %s not up - removing it...\n", iface->name);
145     remove_interface(&iface->interf);
146     return 0;
147   }
148
149   /*
150    * We do all the interface type checks over.
151    * This is because the interface might be a PCMCIA card. Therefore
152    * it might not be the same physical interface as we configured earlier.
153    */
154
155   /* Check broadcast */
156   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
157       ((ifp->int_flags & IFF_BROADCAST)) == 0) {
158     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - removing\n");
159     remove_interface(&iface->interf);
160     return 0;
161   }
162
163   if (ifp->int_flags & IFF_LOOPBACK) {
164     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - removing it...\n");
165     remove_interface(&iface->interf);
166     return 0;
167   }
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_WARN(LOG_INTERFACE, "\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_WARN(LOG_INTERFACE, "\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_WARN(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
207       else
208         OLSR_WARN(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
209       remove_interface(&iface->interf);
210       return 0;
211     }
212
213     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
214
215     if (ip6cmp(&tmp_saddr6.sin6_addr, &ifp->int6_addr.sin6_addr) != 0) {
216       OLSR_DEBUG(LOG_INTERFACE, "New IP address for %s:\n"
217                  "\tOld: %s\n\tNew: %s\n",
218                  ifr.ifr_name, ip6_to_string(&buf, &ifp->int6_addr.sin6_addr), ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
219
220       /* Check main addr */
221       if (!olsr_cnf->fixed_origaddr && ip6cmp(&olsr_cnf->router_id.v6, &tmp_saddr6.sin6_addr) != 0) {
222         /* Update main addr */
223         olsr_cnf->router_id.v6 = tmp_saddr6.sin6_addr;
224       }
225
226       /* Update address */
227       ifp->int6_addr.sin6_addr = tmp_saddr6.sin6_addr;
228       ifp->ip_addr.v6 = tmp_saddr6.sin6_addr;
229
230       if_changes = 1;
231     }
232   } else {
233     /* IP version 4 */
234     const struct sockaddr_in *tmp_saddr4 = (struct sockaddr_in *)&ifr.ifr_addr;
235
236     /* Check interface address (IPv4) */
237     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
238       OLSR_DEBUG(LOG_INTERFACE, "\tCould not get address of interface - removing it\n");
239       remove_interface(&iface->interf);
240       return 0;
241     }
242
243     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
244
245     if (ip4cmp(&ifp->int_addr.sin_addr, &tmp_saddr4->sin_addr) != 0) {
246       /* New address */
247       OLSR_DEBUG(LOG_INTERFACE, "IPv4 address changed for %s\n"
248                  "\tOld:%s\n\tNew:%s\n",
249                  ifr.ifr_name, ip4_to_string(&buf, ifp->int_addr.sin_addr), ip4_to_string(&buf, tmp_saddr4->sin_addr));
250
251       ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
252       if (!olsr_cnf->fixed_origaddr && ip4cmp(&olsr_cnf->router_id.v4, &ifp->ip_addr.v4) == 0) {
253         OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", ip4_to_string(&buf, tmp_saddr4->sin_addr));
254         olsr_cnf->router_id.v4 = tmp_saddr4->sin_addr;
255       }
256
257       ifp->ip_addr.v4 = tmp_saddr4->sin_addr;
258
259       if_changes = 1;
260     }
261
262     /* Check netmask */
263     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
264       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
265       remove_interface(&iface->interf);
266       return 0;
267     }
268
269     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr));
270
271     if (ip4cmp(&ifp->int_netmask.sin_addr, &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr) != 0) {
272       /* New address */
273       OLSR_DEBUG(LOG_INTERFACE, "IPv4 netmask changed for %s\n"
274                  "\tOld:%s\n\tNew:%s\n",
275                  ifr.ifr_name,
276                  ip4_to_string(&buf, ifp->int_netmask.sin_addr),
277                  ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr));
278
279       ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
280
281       if_changes = 1;
282     }
283
284     if (!iface->cnf->ipv4_broadcast.v4.s_addr) {
285       /* Check broadcast address */
286       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
287         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
288         return 0;
289       }
290
291       OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n",
292                  ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));
293
294       if (ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr) {
295         /* New address */
296         OLSR_DEBUG(LOG_INTERFACE, "IPv4 broadcast changed for %s\n"
297                    "\tOld:%s\n\tNew:%s\n",
298                    ifr.ifr_name,
299                    ip4_to_string(&buf, ifp->int_broadaddr.sin_addr),
300                    ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));
301
302         ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
303         if_changes = 1;
304       }
305     }
306   }
307   if (if_changes) {
308     run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
309   }
310   return if_changes;
311 }
312
313 static char basenamestr[32];
314 static const char *if_basename(const char *name);
315 static const char *
316 if_basename(const char *name)
317 {
318   const char *p = strchr(name, ':');
319   if (NULL == p || p - name >= (int)(ARRAYSIZE(basenamestr) - 1)) {
320     return name;
321   }
322   memcpy(basenamestr, name, p - name);
323   basenamestr[p - name] = 0;
324   return basenamestr;
325 }
326
327 /**
328  * Initializes a interface described by iface,
329  * if it is set up and is of the correct type.
330  *
331  *@param iface the olsr_if_config struct describing the interface
332  *@param so the socket to use for ioctls
333  *
334  */
335 int
336 chk_if_up(struct olsr_if_config *iface)
337 {
338   struct interface *ifp;
339   struct ifreq ifr;
340   const char *ifr_basename;
341 #if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_INFO
342   struct ipaddr_str buf;
343 #endif
344
345   /*
346    * Sanity check.
347    */
348   if (iface->interf) {
349     return -1;
350   }
351   ifp = olsr_cookie_malloc(interface_mem_cookie);
352
353    /*
354    * Setup query block.
355    */
356   memset(&ifr, 0, sizeof(ifr));
357   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
358
359   OLSR_DEBUG(LOG_INTERFACE, "Checking %s:\n", ifr.ifr_name);
360
361   /* Get flags (and check if interface exists) */
362   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
363     OLSR_DEBUG(LOG_INTERFACE, "\tNo such interface!\n");
364     goto cleanup;
365   }
366
367   ifp->int_flags = ifr.ifr_flags;
368   if ((ifp->int_flags & IFF_UP) == 0) {
369     OLSR_DEBUG(LOG_INTERFACE, "\tInterface not up - skipping it...\n");
370     goto cleanup;
371   }
372
373   /* Check broadcast */
374   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
375       (ifp->int_flags & IFF_BROADCAST) == 0) {
376     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - skipping\n");
377     goto cleanup;
378   }
379
380   if (ifp->int_flags & IFF_LOOPBACK) {
381     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - skipping it...\n");
382     goto cleanup;
383   }
384
385   /* trying to detect if interface is wireless. */
386   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
387   OLSR_DEBUG(LOG_INTERFACE, ifp->is_wireless ? "\tWireless interface detected\n" : "\tNot a wireless interface\n");
388
389   ifr_basename = if_basename(ifr.ifr_name);
390
391   /* IP version 6 */
392   if (olsr_cnf->ip_version == AF_INET6) {
393     /* Get interface address */
394     int result;
395
396     if (iface->cnf->ipv6_addrtype == OLSR_IP6T_AUTO) {
397       if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_SITELOCAL)) > 0) {
398         iface->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
399       } else {
400         if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_UNIQUELOCAL)) > 0) {
401           iface->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
402         } else {
403           if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_GLOBAL)) > 0) {
404             iface->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
405           }
406         }
407       }
408     } else {
409       result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, iface->cnf->ipv6_addrtype);
410     }
411
412     if (result <= 0) {
413       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
414         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
415       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
416         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
417       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
418         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
419       else
420         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
421       goto cleanup;
422     }
423
424     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
425
426     /* Multicast */
427     memset(&ifp->int6_multaddr, 0, sizeof(ifp->int6_multaddr));
428     ifp->int6_multaddr.sin6_family = AF_INET6;
429     ifp->int6_multaddr.sin6_flowinfo = htonl(0);
430     ifp->int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
431     ifp->int6_multaddr.sin6_port = htons(olsr_cnf->olsr_port);
432     ifp->int6_multaddr.sin6_addr = iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL
433       ? iface->cnf->ipv6_multi_site.v6 : iface->cnf->ipv6_multi_glbl.v6;
434
435 #ifdef __MacOSX__
436     ifp->int6_multaddr.sin6_scope_id = 0;
437 #endif
438
439     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
440
441     ifp->ip_addr.v6 = ifp->int6_addr.sin6_addr;
442   } else {
443     /* IP version 4 */
444
445     /* Get interface address (IPv4) */
446     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
447       OLSR_WARN(LOG_INTERFACE, "\tCould not get address of interface - skipping it\n");
448       goto cleanup;
449     }
450
451     ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
452
453     /* Find netmask */
454     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
455       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get netmask) failed", ifr.ifr_name);
456       goto cleanup;
457     }
458     ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
459
460     /* Find broadcast address */
461     if (iface->cnf->ipv4_broadcast.v4.s_addr) {
462       /* Specified broadcast */
463       ifp->int_broadaddr.sin_addr = iface->cnf->ipv4_broadcast.v4;
464     } else {
465       /* Autodetect */
466       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
467         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
468         goto cleanup;
469       }
470
471       ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
472     }
473
474     /* Deactivate IP spoof filter */
475     deactivate_spoof(ifr_basename, ifp, olsr_cnf->ip_version);
476
477     /* Disable ICMP redirects */
478     disable_redirects(ifr_basename, ifp, olsr_cnf->ip_version);
479
480     ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
481   }
482
483   /* check if interface with this IP already exists */
484   if (if_ifwithaddr(&ifp->ip_addr)) {
485     OLSR_ERROR(LOG_INTERFACE, "Warning, multiple interfaces with the same IP are deprecated. Use 'OriginatorAddress'"
486                " option if you fear a changing main address. Future versions of OLSR might block using multiple"
487                " interfaces with the same IP\n");
488   }
489
490   /* Get interface index */
491   ifp->if_index = if_nametoindex(ifr.ifr_name);
492
493   /* Set interface metric */
494   ifp->int_metric = iface->cnf->weight.fixed ? iface->cnf->weight.value : calculate_if_metric(ifr.ifr_name);
495   OLSR_DEBUG(LOG_INTERFACE, "\tMetric: %d\n", ifp->int_metric);
496
497   /* Get MTU */
498   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
499     ifp->int_mtu = OLSR_DEFAULT_MTU;
500   } else {
501     ifp->int_mtu = ifr.ifr_mtu;
502   }
503   ifp->int_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
504
505   ifp->ttl_index = -32;         /* For the first 32 TC's, fish-eye is disabled */
506
507   /* Set up buffer */
508   net_add_buffer(ifp);
509
510   OLSR_DEBUG(LOG_INTERFACE, "\tMTU - IPhdr: %d\n", ifp->int_mtu);
511
512   OLSR_INFO(LOG_INTERFACE, "Adding interface %s\n", iface->name);
513   OLSR_DEBUG(LOG_INTERFACE, "\tIndex %d\n", ifp->if_index);
514
515   if (olsr_cnf->ip_version == AF_INET) {
516     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
517     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
518     OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
519   } else {
520     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
521     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
522   }
523
524   /*
525    * Clone interface name.
526    */
527   ifp->int_name = olsr_strdup(ifr_basename);
528
529   ifp->immediate_send_tc = olsr_cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval;
530 #if 0
531   ifp->gen_properties = NULL;
532 #endif
533
534   if (olsr_cnf->ip_version == AF_INET) {
535     /* IP version 4 */
536     /*
537      * We create one socket for each interface and bind
538      * the socket to it. This to ensure that we can control
539      * on what interface the message is transmitted
540      */
541     ifp->olsr_socket = getsocket(BUFSPACE, ifp->int_name);
542     if (ifp->olsr_socket < 0) {
543       OLSR_ERROR(LOG_INTERFACE, "Could not initialize socket... exiting!\n\n");
544       olsr_exit(EXIT_FAILURE);
545     }
546   } else {
547     /* IP version 6 */
548
549     /*
550      * We create one socket for each interface and bind
551      * the socket to it. This to ensure that we can control
552      * on what interface the message is transmitted
553      */
554     ifp->olsr_socket = getsocket6(BUFSPACE, ifp->int_name);
555     join_mcast(ifp, ifp->olsr_socket);
556   }
557
558   set_buffer_timer(ifp);
559
560   /* Register socket */
561   add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
562
563 #ifdef linux
564   {
565     /* Set TOS */
566     int data = IPTOS_PREC(olsr_cnf->tos);
567     if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char *)&data, sizeof(data)) < 0) {
568       OLSR_WARN(LOG_INTERFACE, "setsockopt(SO_PRIORITY) error %s", strerror(errno));
569     }
570     data = IPTOS_TOS(olsr_cnf->tos);
571     if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char *)&data, sizeof(data)) < 0) {
572       OLSR_WARN(LOG_INTERFACE, "setsockopt(IP_TOS) error %s", strerror(errno));
573     }
574   }
575 #endif
576
577   /*
578    *Initialize sequencenumber as a random 16bit value
579    */
580   ifp->olsr_seqnum = random() & 0xFFFF;
581
582   /*
583    * Set main address if this is the only interface
584    */
585   if (!olsr_cnf->fixed_origaddr && olsr_ipcmp(&all_zero, &olsr_cnf->router_id) == 0) {
586     olsr_cnf->router_id = ifp->ip_addr;
587     OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
588   }
589
590   /*
591    * Register functions for periodic message generation
592    */
593   ifp->hello_gen_timer =
594     olsr_start_timer(iface->cnf->hello_params.emission_interval,
595                      HELLO_JITTER, OLSR_TIMER_PERIODIC, &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
596   ifp->tc_gen_timer =
597     olsr_start_timer(olsr_cnf->tc_params.emission_interval,
598                      TC_JITTER, OLSR_TIMER_PERIODIC, &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
599   ifp->mid_gen_timer =
600     olsr_start_timer(olsr_cnf->mid_params.emission_interval,
601                      MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp, mid_gen_timer_cookie);
602   ifp->hna_gen_timer =
603     olsr_start_timer(olsr_cnf->hna_params.emission_interval,
604                      HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp, hna_gen_timer_cookie);
605
606   ifp->hello_interval = iface->cnf->hello_params.emission_interval;
607   ifp->hello_validity = iface->cnf->hello_params.validity_time;
608
609   ifp->mode = iface->cnf->mode;
610
611   /*
612    * Call possible ifchange functions registered by plugins
613    */
614   run_ifchg_cbs(ifp, IFCHG_IF_ADD);
615
616   /*
617    * The interface is ready, lock it.
618    */
619   lock_interface(ifp);
620
621   /*
622    * Link to config.
623    */
624   iface->interf = ifp;
625   lock_interface(iface->interf);
626
627   /* Queue */
628   list_node_init(&ifp->int_node);
629   list_add_before(&interface_head, &ifp->int_node);
630
631   return 1;
632
633 cleanup:
634   olsr_cookie_free(interface_mem_cookie, ifp);
635   return 0;
636 }
637
638 /*
639  * Local Variables:
640  * c-basic-offset: 2
641  * indent-tabs-mode: nil
642  * End:
643  */