7587044a7c9c218b8ce39a61323cf2c46848fa15
[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       /* Update address */
221       ifp->int6_addr.sin6_addr = tmp_saddr6.sin6_addr;
222       ifp->ip_addr.v6 = tmp_saddr6.sin6_addr;
223
224       if_changes = 1;
225     }
226   } else {
227     /* IP version 4 */
228     const struct sockaddr_in *tmp_saddr4 = (struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_addr;
229
230     /* Check interface address (IPv4) */
231     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
232       OLSR_DEBUG(LOG_INTERFACE, "\tCould not get address of interface - removing it\n");
233       remove_interface(&iface->interf);
234       return 0;
235     }
236
237     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
238
239     if (ip4cmp(&ifp->int_addr.sin_addr, &tmp_saddr4->sin_addr) != 0) {
240       /* New address */
241       OLSR_DEBUG(LOG_INTERFACE, "IPv4 address changed for %s\n"
242                  "\tOld:%s\n\tNew:%s\n",
243                  ifr.ifr_name, ip4_to_string(&buf, ifp->int_addr.sin_addr), ip4_to_string(&buf, tmp_saddr4->sin_addr));
244
245       ifp->int_addr = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_addr;
246       ifp->ip_addr.v4 = tmp_saddr4->sin_addr;
247
248       if_changes = 1;
249     }
250
251     /* Check netmask */
252     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
253       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
254       remove_interface(&iface->interf);
255       return 0;
256     }
257
258     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_netmask)->sin_addr));
259
260     if (ip4cmp(&ifp->int_netmask.sin_addr, &((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_netmask)->sin_addr) != 0) {
261       /* New address */
262       OLSR_DEBUG(LOG_INTERFACE, "IPv4 netmask changed for %s\n"
263                  "\tOld:%s\n\tNew:%s\n",
264                  ifr.ifr_name,
265                  ip4_to_string(&buf, ifp->int_netmask.sin_addr),
266                  ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_netmask)->sin_addr));
267
268       ifp->int_netmask = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_netmask;
269
270       if_changes = 1;
271     }
272
273     if (!iface->cnf->ipv4_broadcast.v4.s_addr) {
274       /* Check broadcast address */
275       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
276         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
277         return 0;
278       }
279
280       OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n",
281                  ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_broadaddr)->sin_addr));
282
283       if (ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_broadaddr)->sin_addr.s_addr) {
284         /* New address */
285         OLSR_DEBUG(LOG_INTERFACE, "IPv4 broadcast changed for %s\n"
286                    "\tOld:%s\n\tNew:%s\n",
287                    ifr.ifr_name,
288                    ip4_to_string(&buf, ifp->int_broadaddr.sin_addr),
289                    ip4_to_string(&buf, ((struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_broadaddr)->sin_addr));
290
291         ifp->int_broadaddr = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_broadaddr;
292         if_changes = 1;
293       }
294     }
295   }
296   if (if_changes) {
297     run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
298   }
299   return if_changes;
300 }
301
302 static char basenamestr[32];
303 static const char *if_basename(const char *name);
304 static const char *
305 if_basename(const char *name)
306 {
307   const char *p = strchr(name, ':');
308   if (NULL == p || p - name >= (int)(ARRAYSIZE(basenamestr) - 1)) {
309     return name;
310   }
311   memcpy(basenamestr, name, p - name);
312   basenamestr[p - name] = 0;
313   return basenamestr;
314 }
315
316 /**
317  * Initializes a interface described by iface,
318  * if it is set up and is of the correct type.
319  *
320  *@param iface the olsr_if_config struct describing the interface
321  *@param so the socket to use for ioctls
322  *
323  */
324 int
325 chk_if_up(struct olsr_if_config *iface)
326 {
327   struct interface *ifp;
328   struct ifreq ifr;
329   const char *ifr_basename;
330 #if !defined REMOVE_LOG_DEBUG || !defined REMOVE_LOG_INFO
331   struct ipaddr_str buf;
332 #endif
333
334   /*
335    * Sanity check.
336    */
337   if (iface->interf) {
338     return -1;
339   }
340   ifp = olsr_cookie_malloc(interface_mem_cookie);
341
342    /*
343    * Setup query block.
344    */
345   memset(&ifr, 0, sizeof(ifr));
346   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
347
348   OLSR_DEBUG(LOG_INTERFACE, "Checking %s:\n", ifr.ifr_name);
349
350   /* Get flags (and check if interface exists) */
351   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
352     OLSR_DEBUG(LOG_INTERFACE, "\tNo such interface!\n");
353     goto cleanup;
354   }
355
356   ifp->int_flags = ifr.ifr_flags;
357   if ((ifp->int_flags & IFF_UP) == 0) {
358     OLSR_DEBUG(LOG_INTERFACE, "\tInterface not up - skipping it...\n");
359     goto cleanup;
360   }
361
362   /* Check broadcast */
363   if (olsr_cnf->ip_version == AF_INET && !iface->cnf->ipv4_broadcast.v4.s_addr &&       /* Skip if fixed bcast */
364       (ifp->int_flags & IFF_BROADCAST) == 0) {
365     OLSR_DEBUG(LOG_INTERFACE, "\tNo broadcast - skipping\n");
366     goto cleanup;
367   }
368
369   if (ifp->int_flags & IFF_LOOPBACK) {
370     OLSR_DEBUG(LOG_INTERFACE, "\tThis is a loopback interface - skipping it...\n");
371     goto cleanup;
372   }
373
374   /* trying to detect if interface is wireless. */
375   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
376   OLSR_DEBUG(LOG_INTERFACE, ifp->is_wireless ? "\tWireless interface detected\n" : "\tNot a wireless interface\n");
377
378   ifr_basename = if_basename(ifr.ifr_name);
379
380   /* IP version 6 */
381   if (olsr_cnf->ip_version == AF_INET6) {
382     /* Get interface address */
383     int result;
384
385     if (iface->cnf->ipv6_addrtype == OLSR_IP6T_AUTO) {
386       if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_SITELOCAL)) > 0) {
387         iface->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
388       } else {
389         if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_UNIQUELOCAL)) > 0) {
390           iface->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
391         } else {
392           if ((result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, OLSR_IP6T_GLOBAL)) > 0) {
393             iface->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
394           }
395         }
396       }
397     } else {
398       result = get_ipv6_address(ifr.ifr_name, &ifp->int6_addr, iface->cnf->ipv6_addrtype);
399     }
400
401     if (result <= 0) {
402       if (iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL)
403         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
404       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_UNIQUELOCAL)
405         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find unique-local IPv6 address for %s\n", ifr.ifr_name);
406       else if (iface->cnf->ipv6_addrtype == OLSR_IP6T_GLOBAL)
407         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
408       else
409         OLSR_DEBUG(LOG_INTERFACE, "\tCould not find an IPv6 address for %s\n", ifr.ifr_name);
410       goto cleanup;
411     }
412
413     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
414
415     /* Multicast */
416     memset(&ifp->int6_multaddr, 0, sizeof(ifp->int6_multaddr));
417     ifp->int6_multaddr.sin6_family = AF_INET6;
418     ifp->int6_multaddr.sin6_flowinfo = htonl(0);
419     ifp->int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
420     ifp->int6_multaddr.sin6_port = htons(olsr_cnf->olsr_port);
421     ifp->int6_multaddr.sin6_addr = iface->cnf->ipv6_addrtype == OLSR_IP6T_SITELOCAL
422       ? iface->cnf->ipv6_multi_site.v6 : iface->cnf->ipv6_multi_glbl.v6;
423
424 #ifdef __MacOSX__
425     ifp->int6_multaddr.sin6_scope_id = 0;
426 #endif
427
428     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
429
430     ifp->ip_addr.v6 = ifp->int6_addr.sin6_addr;
431   } else {
432     /* IP version 4 */
433
434     /* Get interface address (IPv4) */
435     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) {
436       OLSR_WARN(LOG_INTERFACE, "\tCould not get address of interface - skipping it\n");
437       goto cleanup;
438     }
439
440     ifp->int_addr = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_addr;
441
442     /* Find netmask */
443     if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) {
444       OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get netmask) failed", ifr.ifr_name);
445       goto cleanup;
446     }
447     ifp->int_netmask = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_netmask;
448
449     /* Find broadcast address */
450     if (iface->cnf->ipv4_broadcast.v4.s_addr) {
451       /* Specified broadcast */
452       ifp->int_broadaddr.sin_addr = iface->cnf->ipv4_broadcast.v4;
453     } else {
454       /* Autodetect */
455       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) {
456         OLSR_WARN(LOG_INTERFACE, "%s: ioctl (get broadaddr) failed", ifr.ifr_name);
457         goto cleanup;
458       }
459
460       ifp->int_broadaddr = *(struct sockaddr_in *)(ARM_NOWARN_ALIGN)&ifr.ifr_broadaddr;
461     }
462
463     /* Deactivate IP spoof filter */
464     deactivate_spoof(ifr_basename, ifp, olsr_cnf->ip_version);
465
466     /* Disable ICMP redirects */
467     disable_redirects(ifr_basename, ifp, olsr_cnf->ip_version);
468
469     ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
470   }
471
472   /* check if interface with this IP already exists */
473   if (if_ifwithaddr(&ifp->ip_addr)) {
474     OLSR_ERROR(LOG_INTERFACE, "Warning, multiple interfaces with the same IP are deprecated. Use 'OriginatorAddress'"
475                " option if you fear a changing main address. Future versions of OLSR might block using multiple"
476                " interfaces with the same IP\n");
477   }
478
479   /* Get interface index */
480   ifp->if_index = if_nametoindex(ifr.ifr_name);
481
482   /* Set interface metric */
483   ifp->int_metric = iface->cnf->weight.fixed ? iface->cnf->weight.value : calculate_if_metric(ifr.ifr_name);
484   OLSR_DEBUG(LOG_INTERFACE, "\tMetric: %d\n", ifp->int_metric);
485
486   /* Get MTU */
487   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0) {
488     ifp->int_mtu = OLSR_DEFAULT_MTU;
489   } else {
490     ifp->int_mtu = ifr.ifr_mtu;
491   }
492   ifp->int_mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
493
494   /* Set up buffer */
495   net_add_buffer(ifp);
496
497   OLSR_DEBUG(LOG_INTERFACE, "\tMTU - IPhdr: %d\n", ifp->int_mtu);
498
499   OLSR_INFO(LOG_INTERFACE, "Adding interface %s\n", iface->name);
500   OLSR_DEBUG(LOG_INTERFACE, "\tIndex %d\n", ifp->if_index);
501
502   if (olsr_cnf->ip_version == AF_INET) {
503     OLSR_DEBUG(LOG_INTERFACE, "\tAddress:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
504     OLSR_DEBUG(LOG_INTERFACE, "\tNetmask:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
505     OLSR_DEBUG(LOG_INTERFACE, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
506   } else {
507     OLSR_DEBUG(LOG_INTERFACE, "\tAddress: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
508     OLSR_DEBUG(LOG_INTERFACE, "\tMulticast: %s\n", ip6_to_string(&buf, &ifp->int6_multaddr.sin6_addr));
509   }
510
511   /*
512    * Clone interface name.
513    */
514   ifp->int_name = olsr_strdup(ifr_basename);
515
516 #if 0
517   ifp->gen_properties = NULL;
518 #endif
519
520   if (olsr_cnf->ip_version == AF_INET) {
521     /* IP version 4 */
522     /*
523      * We create one socket for each interface and bind
524      * the socket to it. This to ensure that we can control
525      * on what interface the message is transmitted
526      */
527     ifp->olsr_socket = getsocket(BUFSPACE, ifp);
528     ifp->send_socket = getsocket(0, ifp);
529
530     if (ifp->olsr_socket < 0) {
531       OLSR_ERROR(LOG_INTERFACE, "Could not initialize socket... exiting!\n\n");
532       olsr_exit(EXIT_FAILURE);
533     }
534   } else {
535     /* IP version 6 */
536
537     /*
538      * We create one socket for each interface and bind
539      * the socket to it. This to ensure that we can control
540      * on what interface the message is transmitted
541      */
542     ifp->olsr_socket = getsocket6(BUFSPACE, ifp);
543     ifp->send_socket = getsocket6(0, ifp);
544
545     join_mcast(ifp, ifp->olsr_socket);
546   }
547
548   set_buffer_timer(ifp);
549
550   /* Register socket */
551   add_olsr_socket(ifp->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
552
553 #ifdef linux
554   {
555     /* Set TOS */
556     int data = IPTOS_PREC(olsr_cnf->tos);
557     if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char *)&data, sizeof(data)) < 0) {
558       OLSR_WARN(LOG_INTERFACE, "setsockopt(SO_PRIORITY) error %s", strerror(errno));
559     }
560     data = IPTOS_TOS(olsr_cnf->tos);
561     if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char *)&data, sizeof(data)) < 0) {
562       OLSR_WARN(LOG_INTERFACE, "setsockopt(IP_TOS) error %s", strerror(errno));
563     }
564   }
565 #endif
566
567   /*
568    *Initialize sequencenumber as a random 16bit value
569    */
570   ifp->olsr_seqnum = random() & 0xFFFF;
571
572   /*
573    * Set main address if it's not set
574    */
575   if (olsr_ipcmp(&all_zero, &olsr_cnf->router_id) == 0) {
576     olsr_cnf->router_id = ifp->ip_addr;
577     OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
578
579     /* initialize representation of this node in tc_set */
580     olsr_change_myself_tc();
581   }
582
583   /*
584    * Register functions for periodic message generation
585    */
586   ifp->hello_gen_timer =
587     olsr_start_timer(iface->cnf->hello_params.emission_interval,
588                      HELLO_JITTER, OLSR_TIMER_PERIODIC, &generate_hello, ifp, hello_gen_timer_cookie);
589   ifp->hello_interval = iface->cnf->hello_params.emission_interval;
590   ifp->hello_validity = iface->cnf->hello_params.validity_time;
591
592   ifp->mode = iface->cnf->mode;
593
594   /*
595    * Call possible ifchange functions registered by plugins
596    */
597   run_ifchg_cbs(ifp, IFCHG_IF_ADD);
598
599   /*
600    * The interface is ready, lock it.
601    */
602   lock_interface(ifp);
603
604   /*
605    * Link to config.
606    */
607   iface->interf = ifp;
608   lock_interface(iface->interf);
609
610   /* Queue */
611   list_add_before(&interface_head, &ifp->int_node);
612
613   return 1;
614
615 cleanup:
616   olsr_cookie_free(interface_mem_cookie, ifp);
617   return 0;
618 }
619
620 /*
621  * Local Variables:
622  * c-basic-offset: 2
623  * indent-tabs-mode: nil
624  * End:
625  */