633a7887171fd5f35085cdcca5febf7eb20ad408
[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 "generate_msg.h"
57 #include "olsr_time.h"
58 #include "lq_packet.h"
59 #include "log.h"
60 #include "link_set.h"
61 #include "../common/string.h"
62 #include "../valgrind/valgrind.h"
63
64 #include <signal.h>
65 #include <sys/types.h>
66 #include <net/if.h>
67 #include <net/if_arp.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/ip.h>
70 #include <arpa/inet.h>
71 #include <netdb.h>
72 #include <unistd.h>
73 #include <errno.h>
74
75 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
76
77 #if 0
78 int
79 set_flag(char *ifname, short flag __attribute__ ((unused)))
80 {
81   struct ifreq ifr;
82
83   /* Get flags */
84   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
85   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
86     fprintf(stderr, "ioctl (get interface flags)");
87     return -1;
88   }
89
90   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
91   //printf("Setting flags for if \"%s\"\n", ifr.ifr_name);
92   if ((ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) == 0) {
93     /* Add UP */
94     ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
95     /* Set flags + UP */
96     if (ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0) {
97       fprintf(stderr, "ERROR(%s): %s\n", ifr.ifr_name, strerror(errno));
98       return -1;
99     }
100   }
101   return 1;
102 }
103 #endif
104
105 /**
106  * Checks if an initialized interface is changed
107  * that is if it has been set down or the address
108  * has been changed.
109  *
110  *@param iface the olsr_if_config struct describing the interface
111  */
112 int
113 chk_if_changed(struct olsr_if_config *iface)
114 {
115 #if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_INFO
116   struct ipaddr_str buf;
117 #endif
118   struct interface *ifp;
119   struct ifreq ifr;
120   int if_changes = 0;
121
122   OLSR_DEBUG(LOG_INTERFACE, "Checking if %s is set down or changed\n", iface->name);
123
124   ifp = iface->interf;
125   if (!ifp) {
126     return 0;
127   }
128
129   memset(&ifr, 0, sizeof(ifr));
130   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
131   /* Get flags (and check if interface exists) */
132   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
133     OLSR_WARN(LOG_INTERFACE, "No such interface: %s\n", iface->name);
134     remove_interface(&iface->interf);
135     return 0;
136   }
137   ifp->int_flags = ifr.ifr_flags;
138
139   /*
140    * First check if the interface is set DOWN
141    */
142   if ((ifp->int_flags & IFF_UP) == 0) {
143     OLSR_DEBUG(LOG_INTERFACE, "\tInterface %s not up - removing it...\n", iface->name);
144     remove_interface(&iface->interf);
145     return 0;
146   }
147
148   /*
149    * We do all the interface type checks over.
150    * This is because the interface might be a PCMCIA card. Therefore
151    * it might not be the same physical interface as we configured earlier.
152    */
153
154   /* Check broadcast */
155   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
156       ((ifp->int_flags & IFF_BROADCAST)) == 0) {
157     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - removing\n");
158     remove_interface(&iface->interf);
159     return 0;
160   }
161
162   if (ifp->int_flags & IFF_LOOPBACK) {
163     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - removing it...\n");
164     remove_interface(&iface->interf);
165     return 0;
166   }
167
168   /* trying to detect if interface is wireless. */
169   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
170
171   /* Set interface metric */
172   ifp->int_metric = iface->cnf->weight.fixed ? iface->cnf->weight.value : calculate_if_metric(ifr.ifr_name);
173
174   /* Get MTU */
175   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
176     ifp->int_mtu = 0;
177   } else {
178     ifr.ifr_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
179     if (ifp->int_mtu != ifr.ifr_mtu) {
180       ifp->int_mtu = ifr.ifr_mtu;
181       /* Create new outputbuffer */
182       net_remove_buffer(ifp);   /* Remove old */
183       net_add_buffer(ifp);
184     }
185   }
186
187   /* Get interface index */
188   ifp->if_index = if_nametoindex(ifr.ifr_name);
189
190   /*
191    * Now check if the IP has changed
192    */
193
194   /* IP version 6 */
195   if (olsr_cnf->ip_version == AF_INET6) {
196     struct sockaddr_in6 tmp_saddr6;
197
198     /* Get interface address */
199     if (get_ipv6_address(ifr.ifr_name, &tmp_saddr6, iface->cnf->ipv6_addrtype) <= 0) {
200       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
201         OLSR_WARN(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
202       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
203         OLSR_WARN(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
204       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
205         OLSR_WARN(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
206       else
207         OLSR_WARN(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
208       remove_interface(&iface->interf);
209       return 0;
210     }
211
212     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
213
214     if (ip6cmp(&tmp_saddr6.sin6_addr, &ifp->int6_addr.sin6_addr) != 0) {
215       OLSR_DEBUG(LOG_INTERFACE, "New IP address for %s:\n"
216                  "\tOld: %s\n\tNew: %s\n",
217                  ifr.ifr_name, ip6_to_string(&buf, &ifp->int6_addr.sin6_addr), ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
218
219       /* Check main addr */
220       if (!olsr_cnf->fixed_origaddr && ip6cmp(&olsr_cnf->router_id.v6, &tmp_saddr6.sin6_addr) != 0) {
221         /* Update main addr */
222         olsr_cnf->router_id.v6 = tmp_saddr6.sin6_addr;
223       }
224
225       /* Update address */
226       ifp->int6_addr.sin6_addr = tmp_saddr6.sin6_addr;
227       ifp->ip_addr.v6 = tmp_saddr6.sin6_addr;
228
229       if_changes = 1;
230     }
231   } else {
232     /* IP version 4 */
233     const struct sockaddr_in *tmp_saddr4 = (struct sockaddr_in *)&ifr.ifr_addr;
234
235     /* Check interface address (IPv4) */
236     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
237       OLSR_DEBUG(LOG_INTERFACE, "\tCould not get address of interface - removing it\n");
238       remove_interface(&iface->interf);
239       return 0;
240     }
241
242     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
243
244     if (ip4cmp(&ifp->int_addr.sin_addr, &tmp_saddr4->sin_addr) != 0) {
245       /* New address */
246       OLSR_DEBUG(LOG_INTERFACE, "IPv4 address changed for %s\n"
247                  "\tOld:%s\n\tNew:%s\n",
248                  ifr.ifr_name, ip4_to_string(&buf, ifp->int_addr.sin_addr), ip4_to_string(&buf, tmp_saddr4->sin_addr));
249
250       ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
251       if (!olsr_cnf->fixed_origaddr && ip4cmp(&olsr_cnf->router_id.v4, &ifp->ip_addr.v4) == 0) {
252         OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", ip4_to_string(&buf, tmp_saddr4->sin_addr));
253         olsr_cnf->router_id.v4 = tmp_saddr4->sin_addr;
254       }
255
256       ifp->ip_addr.v4 = tmp_saddr4->sin_addr;
257
258       if_changes = 1;
259     }
260
261     /* Check netmask */
262     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
263       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
264       remove_interface(&iface->interf);
265       return 0;
266     }
267
268     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr));
269
270     if (ip4cmp(&ifp->int_netmask.sin_addr, &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr) != 0) {
271       /* New address */
272       OLSR_DEBUG(LOG_INTERFACE, "IPv4 netmask changed for %s\n"
273                  "\tOld:%s\n\tNew:%s\n",
274                  ifr.ifr_name,
275                  ip4_to_string(&buf, ifp->int_netmask.sin_addr),
276                  ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr));
277
278       ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
279
280       if_changes = 1;
281     }
282
283     if (!iface->cnf->ipv4_broadcast.v4.s_addr) {
284       /* Check broadcast address */
285       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
286         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
287         return 0;
288       }
289
290       OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n",
291                  ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));
292
293       if (ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr) {
294         /* New address */
295         OLSR_DEBUG(LOG_INTERFACE, "IPv4 broadcast changed for %s\n"
296                    "\tOld:%s\n\tNew:%s\n",
297                    ifr.ifr_name,
298                    ip4_to_string(&buf, ifp->int_broadaddr.sin_addr),
299                    ip4_to_string(&buf, ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));
300
301         ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
302         if_changes = 1;
303       }
304     }
305   }
306   if (if_changes) {
307     run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
308   }
309   return if_changes;
310 }
311
312 static char basenamestr[32];
313 static const char *if_basename(const char *name);
314 static const char *
315 if_basename(const char *name)
316 {
317   const char *p = strchr(name, ':');
318   if (NULL == p || p - name >= (int)(ARRAYSIZE(basenamestr) - 1)) {
319     return name;
320   }
321   memcpy(basenamestr, name, p - name);
322   basenamestr[p - name] = 0;
323   return basenamestr;
324 }
325
326 /**
327  * Initializes a interface described by iface,
328  * if it is set up and is of the correct type.
329  *
330  *@param iface the olsr_if_config struct describing the interface
331  *@param so the socket to use for ioctls
332  *
333  */
334 int
335 chk_if_up(struct olsr_if_config *iface)
336 {
337   struct interface *ifp;
338   struct ifreq ifr;
339   const char *ifr_basename;
340 #if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_INFO
341   struct ipaddr_str buf;
342 #endif
343
344   /*
345    * Sanity check.
346    */
347   if (iface->interf) {
348     return -1;
349   }
350   ifp = olsr_cookie_malloc(interface_mem_cookie);
351
352    /*
353    * Setup query block.
354    */
355   memset(&ifr, 0, sizeof(ifr));
356   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
357
358   OLSR_DEBUG(LOG_INTERFACE, "Checking %s:\n", ifr.ifr_name);
359
360   /* Get flags (and check if interface exists) */
361   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
362     OLSR_DEBUG(LOG_INTERFACE, "\tNo such interface!\n");
363     goto cleanup;
364   }
365
366   ifp->int_flags = ifr.ifr_flags;
367   if ((ifp->int_flags & IFF_UP) == 0) {
368     OLSR_DEBUG(LOG_INTERFACE, "\tInterface not up - skipping it...\n");
369     goto cleanup;
370   }
371
372   /* Check broadcast */
373   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
374       (ifp->int_flags & IFF_BROADCAST) == 0) {
375     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - skipping\n");
376     goto cleanup;
377   }
378
379   if (ifp->int_flags & IFF_LOOPBACK) {
380     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - skipping it...\n");
381     goto cleanup;
382   }
383
384   /* trying to detect if interface is wireless. */
385   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
386   OLSR_DEBUG(LOG_INTERFACE, ifp->is_wireless ? "\tWireless interface detected\n" : "\tNot a wireless interface\n");
387
388   ifr_basename = if_basename(ifr.ifr_name);
389
390   /* IP version 6 */
391   if (olsr_cnf->ip_version == AF_INET6) {
392     /* Get interface address */
393     int result;
394
395     if (iface->cnf->ipv6_addrtype == OLSR_IP6T_AUTO) {
396       if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_SITELOCAL)) > 0) {
397         iface->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
398       } else {
399         if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_UNIQUELOCAL)) > 0) {
400           iface->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
401         } else {
402           if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_GLOBAL)) > 0) {
403             iface->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
404           }
405         }
406       }
407     } else {
408       result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, iface->cnf->ipv6_addrtype);
409     }
410
411     if (result <= 0) {
412       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
413         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
414       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
415         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
416       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
417         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
418       else
419         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
420       goto cleanup;
421     }
422
423     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
424
425     /* Multicast */
426     memset(&ifp->int6_multaddr, 0, sizeof(ifp->int6_multaddr));
427     ifp->int6_multaddr.sin6_family = AF_INET6;
428     ifp->int6_multaddr.sin6_flowinfo = htonl(0);
429     ifp->int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
430     ifp->int6_multaddr.sin6_port = htons(olsr_cnf->olsr_port);
431     ifp->int6_multaddr.sin6_addr = iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL
432       ? iface->cnf->ipv6_multi_site.v6 : iface->cnf->ipv6_multi_glbl.v6;
433
434 #ifdef __MacOSX__
435     ifp->int6_multaddr.sin6_scope_id = 0;
436 #endif
437
438     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
439
440     ifp->ip_addr.v6 = ifp->int6_addr.sin6_addr;
441   } else {
442     /* IP version 4 */
443
444     /* Get interface address (IPv4) */
445     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
446       OLSR_WARN(LOG_INTERFACE, "\tCould not get address of interface - skipping it\n");
447       goto cleanup;
448     }
449
450     ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
451
452     /* Find netmask */
453     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
454       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get netmask) failed", ifr.ifr_name);
455       goto cleanup;
456     }
457     ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
458
459     /* Find broadcast address */
460     if (iface->cnf->ipv4_broadcast.v4.s_addr) {
461       /* Specified broadcast */
462       ifp->int_broadaddr.sin_addr = iface->cnf->ipv4_broadcast.v4;
463     } else {
464       /* Autodetect */
465       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
466         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
467         goto cleanup;
468       }
469
470       ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
471     }
472
473     /* Deactivate IP spoof filter */
474     deactivate_spoof(ifr_basename, ifp, olsr_cnf->ip_version);
475
476     /* Disable ICMP redirects */
477     disable_redirects(ifr_basename, ifp, olsr_cnf->ip_version);
478
479     ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
480   }
481
482   /* check if interface with this IP already exists */
483   if (if_ifwithaddr(&ifp->ip_addr)) {
484     OLSR_ERROR(LOG_INTERFACE, "Warning, multiple interfaces with the same IP are deprecated. Use 'OriginatorAddress'"
485                " option if you fear a changing main address. Future versions of OLSR might block using multiple"
486                " interfaces with the same IP\n");
487   }
488
489   /* Get interface index */
490   ifp->if_index = if_nametoindex(ifr.ifr_name);
491
492   /* Set interface metric */
493   ifp->int_metric = iface->cnf->weight.fixed ? iface->cnf->weight.value : calculate_if_metric(ifr.ifr_name);
494   OLSR_DEBUG(LOG_INTERFACE, "\tMetric: %d\n", ifp->int_metric);
495
496   /* Get MTU */
497   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
498     ifp->int_mtu = OLSR_DEFAULT_MTU;
499   } else {
500     ifp->int_mtu = ifr.ifr_mtu;
501   }
502   ifp->int_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
503
504   ifp->ttl_index = -32;         /* For the first 32 TC's, fish-eye is disabled */
505
506   /* Set up buffer */
507   net_add_buffer(ifp);
508
509   OLSR_DEBUG(LOG_INTERFACE, "\tMTU - IPhdr: %d\n", ifp->int_mtu);
510
511   OLSR_INFO(LOG_INTERFACE, "Adding interface %s\n", iface->name);
512   OLSR_DEBUG(LOG_INTERFACE, "\tIndex %d\n", ifp->if_index);
513
514   if (olsr_cnf->ip_version == AF_INET) {
515     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
516     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
517     OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
518   } else {
519     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
520     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
521   }
522
523   /*
524    * Clone interface name.
525    */
526   ifp->int_name = olsr_strdup(ifr_basename);
527
528   ifp->immediate_send_tc = olsr_cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval;
529 #if 0
530   ifp->gen_properties = NULL;
531 #endif
532
533   if (olsr_cnf->ip_version == AF_INET) {
534     /* IP version 4 */
535     /*
536      * We create one socket for each interface and bind
537      * the socket to it. This to ensure that we can control
538      * on what interface the message is transmitted
539      */
540     ifp->olsr_socket = getsocket(BUFSPACE, ifp->int_name);
541     if (ifp->olsr_socket < 0) {
542       OLSR_ERROR(LOG_INTERFACE, "Could not initialize socket... exiting!\n\n");
543       olsr_exit(EXIT_FAILURE);
544     }
545   } else {
546     /* IP version 6 */
547
548     /*
549      * We create one socket for each interface and bind
550      * the socket to it. This to ensure that we can control
551      * on what interface the message is transmitted
552      */
553     ifp->olsr_socket = getsocket6(BUFSPACE, ifp->int_name);
554     join_mcast(ifp, ifp->olsr_socket);
555   }
556
557   set_buffer_timer(ifp);
558
559   /* Register socket */
560   add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
561
562 #ifdef linux
563   {
564     /* Set TOS */
565     int data = IPTOS_PREC(olsr_cnf->tos);
566     if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char *)&data, sizeof(data)) < 0) {
567       OLSR_WARN(LOG_INTERFACE, "setsockopt(SO_PRIORITY) error %s", strerror(errno));
568     }
569     data = IPTOS_TOS(olsr_cnf->tos);
570     if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char *)&data, sizeof(data)) < 0) {
571       OLSR_WARN(LOG_INTERFACE, "setsockopt(IP_TOS) error %s", strerror(errno));
572     }
573   }
574 #endif
575
576   /*
577    *Initialize sequencenumber as a random 16bit value
578    */
579   ifp->olsr_seqnum = random() & 0xFFFF;
580
581   /*
582    * Set main address if this is the only interface
583    */
584   if (!olsr_cnf->fixed_origaddr && olsr_ipcmp(&all_zero, &olsr_cnf->router_id) == 0) {
585     olsr_cnf->router_id = ifp->ip_addr;
586     OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
587   }
588
589   /*
590    * Register functions for periodic message generation
591    */
592   ifp->hello_gen_timer =
593     olsr_start_timer(iface->cnf->hello_params.emission_interval,
594                      HELLO_JITTER, OLSR_TIMER_PERIODIC, &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
595   ifp->tc_gen_timer =
596     olsr_start_timer(olsr_cnf->tc_params.emission_interval,
597                      TC_JITTER, OLSR_TIMER_PERIODIC, &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
598   ifp->mid_gen_timer =
599     olsr_start_timer(olsr_cnf->mid_params.emission_interval,
600                      MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp, mid_gen_timer_cookie);
601   ifp->hna_gen_timer =
602     olsr_start_timer(olsr_cnf->hna_params.emission_interval,
603                      HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp, hna_gen_timer_cookie);
604
605   ifp->hello_interval = iface->cnf->hello_params.emission_interval;
606   ifp->hello_validity = iface->cnf->hello_params.validity_time;
607
608   ifp->mode = iface->cnf->mode;
609
610   /*
611    * Call possible ifchange functions registered by plugins
612    */
613   run_ifchg_cbs(ifp, IFCHG_IF_ADD);
614
615   /*
616    * The interface is ready, lock it.
617    */
618   lock_interface(ifp);
619
620   /*
621    * Link to config.
622    */
623   iface->interf = ifp;
624   lock_interface(iface->interf);
625
626   /* Queue */
627   list_node_init(&ifp->int_node);
628   list_add_before(&interface_head, &ifp->int_node);
629
630   return 1;
631
632 cleanup:
633   olsr_cookie_free(interface_mem_cookie, ifp);
634   return 0;
635 }
636
637 /*
638  * Local Variables:
639  * c-basic-offset: 2
640  * indent-tabs-mode: nil
641  * End:
642  */