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