5420ba1f1aba0142d0888bcef7f42f7b4bb007ab
[olsrd.git] / src / unix / ifnet.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41
42 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
43 #define ifr_netmask ifr_addr
44 #endif
45
46 #include "ifnet.h"
47 #include "ipcalc.h"
48 #include "interfaces.h"
49 #include "defs.h"
50 #include "olsr.h"
51 #include "net_os.h"
52 #include "net_olsr.h"
53 #include "socket_parser.h"
54 #include "parser.h"
55 #include "scheduler.h"
56 #include "generate_msg.h"
57 #include "mantissa.h"
58 #include "lq_packet.h"
59 #include "log.h"
60 #include "link_set.h"
61 #include "../common/string.h"
62
63 #include <signal.h>
64 #include <sys/types.h>
65 #include <net/if.h>
66 #include <net/if_arp.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 #include <arpa/inet.h>
70 #include <netdb.h>
71 #include <unistd.h>
72 #include <errno.h>
73
74 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
75
76 int
77 set_flag(char *ifname, short flag __attribute__((unused)))
78 {
79   struct ifreq ifr;
80
81   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
82
83   /* Get flags */
84   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
85     {
86       fprintf(stderr,"ioctl (get interface flags)");
87       return -1;
88     }
89
90   strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
91   
92   //printf("Setting flags for if \"%s\"\n", ifr.ifr_name);
93
94   if(!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING)))
95     {
96       /* Add UP */
97       ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
98       /* Set flags + UP */
99       if(ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0)
100         {
101           fprintf(stderr, "ERROR(%s): %s\n", ifr.ifr_name, strerror(errno));
102           return -1;
103         }
104     }
105   return 1;
106
107 }
108
109
110
111
112 void
113 check_interface_updates(void *foo __attribute__((unused)))
114 {
115   struct olsr_if *tmp_if;
116
117 #ifdef DEBUG
118   OLSR_PRINTF(3, "Checking for updates in the interface set\n");
119 #endif
120
121   for(tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next)
122     {
123       if(tmp_if->host_emul)
124         continue;
125       
126       if(olsr_cnf->host_emul) /* XXX: TEMPORARY! */
127         continue;
128
129       if(!tmp_if->cnf->autodetect_chg) 
130         {
131 #ifdef DEBUG
132           /* Don't check this interface */
133           OLSR_PRINTF(3, "Not checking interface %s\n", tmp_if->name);
134 #endif
135           continue;
136         }
137
138       if(tmp_if->configured)
139         {
140           chk_if_changed(tmp_if);
141         }
142       else
143         {
144           chk_if_up(tmp_if, 3);
145         }
146     }
147
148   return;
149 }
150
151 /**
152  * Checks if an initialized interface is changed
153  * that is if it has been set down or the address
154  * has been changed.
155  *
156  *@param iface the olsr_if struct describing the interface
157  */
158 int
159 chk_if_changed(struct olsr_if *iface)
160 {
161   struct interface *ifp, *tmp_ifp;
162   struct ifreq ifr;
163   struct sockaddr_in6 tmp_saddr6;
164   int if_changes;
165   if_changes = 0;
166
167 #ifdef DEBUG
168   OLSR_PRINTF(3, "Checking if %s is set down or changed\n", iface->name);
169 #endif
170
171   if(iface->host_emul)
172     return -1;
173
174   ifp = iface->interf;
175
176   if(ifp == NULL)
177     {
178       /* Should not happen */
179       iface->configured = 0;
180       return 0;
181     }
182
183   memset(&ifr, 0, sizeof(struct ifreq));
184   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
185
186
187   /* Get flags (and check if interface exists) */
188   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
189     {
190       OLSR_PRINTF(3, "No such interface: %s\n", iface->name);
191       goto remove_interface;
192     }
193
194   ifp->int_flags = ifr.ifr_flags;
195
196   /*
197    * First check if the interface is set DOWN
198    */
199
200   if ((ifp->int_flags & IFF_UP) == 0)
201     {
202       OLSR_PRINTF(1, "\tInterface %s not up - removing it...\n", iface->name);
203       goto remove_interface;
204     }
205
206   /*
207    * We do all the interface type checks over.
208    * This is because the interface might be a PCMCIA card. Therefore
209    * It might not be the same physical interface as we configured earlier.
210    */
211
212   /* Check broadcast */
213   if ((olsr_cnf->ip_version == AF_INET) && 
214       !iface->cnf->ipv4_broadcast.v4.s_addr && /* Skip if fixed bcast */ 
215       (!(ifp->int_flags & IFF_BROADCAST))) 
216     {
217       OLSR_PRINTF(3, "\tNo broadcast - removing\n");
218       goto remove_interface;
219     }
220
221   if (ifp->int_flags & IFF_LOOPBACK)
222     {
223       OLSR_PRINTF(3, "\tThis is a loopback interface - removing it...\n");
224       goto remove_interface;
225     }
226
227   ifp->is_hcif = OLSR_FALSE;
228
229   /* trying to detect if interface is wireless. */
230   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
231
232   /* Set interface metric */
233   if(iface->cnf->weight.fixed)
234     ifp->int_metric = iface->cnf->weight.value;
235   else
236     ifp->int_metric = calculate_if_metric(ifr.ifr_name);
237
238   /* Get MTU */
239   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
240     ifp->int_mtu = 0;
241   else
242     {
243       ifr.ifr_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
244
245       if(ifp->int_mtu != ifr.ifr_mtu)
246         {
247           ifp->int_mtu = ifr.ifr_mtu;
248           /* Create new outputbuffer */
249           net_remove_buffer(ifp); /* Remove old */
250           net_add_buffer(ifp);
251         }
252     }
253
254
255   /* Get interface index */
256   ifp->if_index = if_nametoindex(ifr.ifr_name);
257
258   /*
259    * Now check if the IP has changed
260    */
261   
262   /* IP version 6 */
263   if(olsr_cnf->ip_version == AF_INET6)
264     {
265 #ifdef DEBUG
266       struct ipaddr_str buf;
267 #endif
268       /* Get interface address */
269       
270       if(get_ipv6_address(ifr.ifr_name, &tmp_saddr6, iface->cnf->ipv6_addrtype) <= 0)
271         {
272           if(iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL)
273             OLSR_PRINTF(3, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
274           else
275             OLSR_PRINTF(3, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
276           
277           
278           goto remove_interface;
279         }
280       
281 #ifdef DEBUG
282       OLSR_PRINTF(3, "\tAddress: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
283 #endif
284
285       if(memcmp(&tmp_saddr6.sin6_addr, &ifp->int6_addr.sin6_addr, olsr_cnf->ipsize) != 0)
286         {
287           struct ipaddr_str buf;
288           OLSR_PRINTF(1, "New IP address for %s:\n", ifr.ifr_name);
289           OLSR_PRINTF(1, "\tOld: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
290           OLSR_PRINTF(1, "\tNew: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
291
292           /* Check main addr */
293           if(memcmp(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize) == 0)
294             {
295               /* Update main addr */
296               memcpy(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
297             }
298
299           /* Update address */
300           memcpy(&ifp->int6_addr.sin6_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
301           memcpy(&ifp->ip_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
302
303           run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
304
305           return 1;               
306         }
307       return 0;
308
309     }
310   else
311   /* IP version 4 */
312     {
313       struct ipaddr_str buf;
314       /* Check interface address (IPv4)*/
315       if(ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) 
316         {
317           OLSR_PRINTF(1, "\tCould not get address of interface - removing it\n");
318           goto remove_interface;
319         }
320
321 #ifdef DEBUG
322       OLSR_PRINTF(3, "\tAddress:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
323 #endif
324
325       if(memcmp(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr,
326                 &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
327                 olsr_cnf->ipsize) != 0)
328         {
329           /* New address */
330           OLSR_PRINTF(1, "IPv4 address changed for %s\n", ifr.ifr_name);
331           OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
332           OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
333
334           ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
335
336           if(memcmp(&olsr_cnf->main_addr, 
337                     &ifp->ip_addr,
338                     olsr_cnf->ipsize) == 0)
339             {
340               OLSR_PRINTF(1, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
341               olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
342               memcpy(&olsr_cnf->main_addr, 
343                      &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
344                      olsr_cnf->ipsize);
345             }
346
347           memcpy(&ifp->ip_addr, 
348                  &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
349                  olsr_cnf->ipsize);
350
351           if_changes = 1;
352         }
353
354       /* Check netmask */
355       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) 
356         {
357           olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
358           goto remove_interface;
359         }
360
361 #ifdef DEBUG
362       OLSR_PRINTF(3, "\tNetmask:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
363 #endif
364
365       if(memcmp(&((struct sockaddr_in *)&ifp->int_netmask)->sin_addr.s_addr,
366                 &((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr, 
367                 olsr_cnf->ipsize) != 0)
368         {
369           struct ipaddr_str buf;
370           /* New address */
371           OLSR_PRINTF(1, "IPv4 netmask changed for %s\n", ifr.ifr_name);
372           OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
373           OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
374
375           ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
376
377           if_changes = 1;
378         }
379       
380       if(!iface->cnf->ipv4_broadcast.v4.s_addr)
381         {
382           /* Check broadcast address */      
383           if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) 
384             {
385               olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
386               goto remove_interface;
387             }
388           
389 #ifdef DEBUG
390           OLSR_PRINTF(3, "\tBroadcast address:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
391 #endif
392           
393           if(ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr)
394             {
395               struct ipaddr_str buf;
396               /* New address */
397               OLSR_PRINTF(1, "IPv4 broadcast changed for %s\n", ifr.ifr_name);
398               OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
399               OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
400               
401               ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
402               if_changes = 1;
403             }            
404         }
405     }
406
407   if(if_changes)
408     run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
409
410   return if_changes;
411
412
413  remove_interface:
414   OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
415   olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
416
417   olsr_delete_link_entry_by_ip(&ifp->ip_addr);
418
419   /*
420    *Call possible ifchange functions registered by plugins  
421    */
422   run_ifchg_cbs(ifp, IFCHG_IF_REMOVE);
423   
424   /* Dequeue */
425   if(ifp == ifnet)
426     {
427       ifnet = ifp->int_next;
428     }
429   else
430     {
431       tmp_ifp = ifnet;
432       while(tmp_ifp->int_next != ifp)
433         {
434           tmp_ifp = tmp_ifp->int_next;
435         }
436       tmp_ifp->int_next = ifp->int_next;
437     }
438
439
440   /* Remove output buffer */
441   net_remove_buffer(ifp);
442
443   /* Check main addr */
444   if(ipequal(&olsr_cnf->main_addr, &ifp->ip_addr))
445     {
446       if(ifnet == NULL)
447         {
448           /* No more interfaces */
449           memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize);
450           OLSR_PRINTF(1, "No more interfaces...\n");
451         }
452       else
453         {
454           struct ipaddr_str buf;
455           olsr_cnf->main_addr = ifnet->ip_addr;
456           OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
457           olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
458         }
459     }
460
461   /*
462    * Deregister functions for periodic message generation 
463    */
464   olsr_stop_timer(ifp->hello_gen_timer);
465   olsr_stop_timer(ifp->tc_gen_timer);
466   olsr_stop_timer(ifp->mid_gen_timer);
467   olsr_stop_timer(ifp->hna_gen_timer);
468
469   iface->configured = 0;
470   iface->interf = NULL;
471   /* Close olsr socket */
472   close(ifp->olsr_socket);
473   remove_olsr_socket(ifp->olsr_socket, &olsr_input);
474
475   /* Free memory */
476   free(ifp->int_name);
477   free(ifp);
478
479   if((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces))
480     {
481       OLSR_PRINTF(1, "No more active interfaces - exiting.\n");
482       olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n");
483       olsr_cnf->exit_value = EXIT_FAILURE;
484       kill(getpid(), SIGINT);
485     }
486
487   return 0;
488
489 }
490
491 /**
492  * Initializes the special interface used in
493  * host-client emulation
494  */
495 int
496 add_hemu_if(struct olsr_if *iface)
497 {
498   struct interface *ifp;
499   union olsr_ip_addr null_addr;
500   olsr_u32_t addr[4];
501   struct ipaddr_str buf;
502   size_t name_size;
503
504   if(!iface->host_emul)
505     return -1;
506
507   ifp = olsr_malloc(sizeof (struct interface), "Interface update 2");
508
509   memset(ifp, 0, sizeof (struct interface));
510
511   iface->configured = OLSR_TRUE;
512   iface->interf = ifp;
513
514   name_size = strlen("hcif01") + 1;
515   ifp->is_hcif = OLSR_TRUE;
516   ifp->int_name = olsr_malloc(name_size, "Interface update 3");
517   ifp->int_metric = 0;
518
519   strscpy(ifp->int_name, "hcif01", name_size);
520
521   OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
522
523   OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
524
525   OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
526
527   ifp->int_next = ifnet;
528   ifnet = ifp;
529
530   memset(&null_addr, 0, olsr_cnf->ipsize);
531   if(ipequal(&null_addr, &olsr_cnf->main_addr))
532     {
533       olsr_cnf->main_addr = iface->hemu_ip;
534       OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
535         olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
536     }
537
538   ifp->int_mtu = OLSR_DEFAULT_MTU;
539
540   ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
541
542   /* Set up buffer */
543   net_add_buffer(ifp);
544
545
546   if(olsr_cnf->ip_version == AF_INET)
547     {
548       struct sockaddr_in sin;
549
550       memset(&sin, 0, sizeof(sin));
551
552       sin.sin_family = AF_INET;
553       sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
554       sin.sin_port = htons(10150);
555  
556      /* IP version 4 */
557       ifp->ip_addr.v4 = iface->hemu_ip.v4;
558
559       memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
560       
561       /*
562        *We create one socket for each interface and bind
563        *the socket to it. This to ensure that we can control
564        *on what interface the message is transmitted
565        */
566       
567       ifp->olsr_socket = gethemusocket(&sin);
568       
569       if (ifp->olsr_socket < 0)
570         {
571           fprintf(stderr, "Could not initialize socket... exiting!\n\n");
572           olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
573           olsr_cnf->exit_value = EXIT_FAILURE;
574           kill(getpid(), SIGINT);
575         }
576
577     }
578   else
579     {
580       /* IP version 6 */
581       memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
582
583 #if 0      
584       /*
585        *We create one socket for each interface and bind
586        *the socket to it. This to ensure that we can control
587        *on what interface the message is transmitted
588        */
589       
590       ifp->olsr_socket = gethcsocket6(&addrsock6, BUFSPACE, ifp->int_name);
591       
592       join_mcast(ifp, ifp->olsr_socket);
593       
594       if (ifp->olsr_socket < 0)
595         {
596           fprintf(stderr, "Could not initialize socket... exiting!\n\n");
597           olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
598           olsr_cnf->exit_value = EXIT_FAILURE;
599           kill(getpid(), SIGINT);
600         }
601       
602 #endif
603     }
604
605   /* Send IP as first 4/16 bytes on socket */
606   memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
607   addr[0] = htonl(addr[0]);
608   addr[1] = htonl(addr[1]);
609   addr[2] = htonl(addr[2]);
610   addr[3] = htonl(addr[3]);
611
612   if(send(ifp->olsr_socket, addr , olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize)
613     {
614       fprintf(stderr, "Error sending IP!");
615     }  
616   
617   /* Register socket */
618   add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu);
619
620
621   /*
622    * Register functions for periodic message generation 
623    */
624   
625   ifp->hello_gen_timer =
626     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
627                      HELLO_JITTER, OLSR_TIMER_PERIODIC,
628                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
629                      ifp, hello_gen_timer_cookie->ci_id);
630   ifp->tc_gen_timer =
631     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
632                      TC_JITTER, OLSR_TIMER_PERIODIC,
633                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
634                      ifp, tc_gen_timer_cookie->ci_id);
635   ifp->mid_gen_timer =
636     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
637                      MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
638                      mid_gen_timer_cookie->ci_id);
639   ifp->hna_gen_timer =
640     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
641                      HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
642                      hna_gen_timer_cookie->ci_id);
643
644   /* Recalculate max topology hold time */
645   if(olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
646     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
647
648   ifp->hello_etime = (olsr_reltime)(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
649   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
650   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
651   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
652   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
653
654   return 1;
655 }
656
657 static char basenamestr[32];
658 static const char* if_basename(const char* name);
659 static const char* if_basename(const char* name)
660 {
661         char *p = strchr(name, ':');
662         if (NULL == p || p - name >= (int)(sizeof(basenamestr) / sizeof(basenamestr[0]) - 1)) {
663                 return name;
664         }
665         memcpy(basenamestr, name, p - name);
666         basenamestr[p - name] = 0;
667         return basenamestr;
668 }
669
670 /**
671  * Initializes a interface described by iface,
672  * if it is set up and is of the correct type.
673  *
674  *@param iface the olsr_if struct describing the interface
675  *@param so the socket to use for ioctls
676  *
677  */
678 int
679 chk_if_up(struct olsr_if *iface, int debuglvl __attribute__((unused)))
680 {
681   struct interface ifs, *ifp;
682   struct ifreq ifr;
683   union olsr_ip_addr null_addr;
684   size_t name_size;
685 #ifdef linux
686   int precedence = IPTOS_PREC(olsr_cnf->tos);
687   int tos_bits = IPTOS_TOS(olsr_cnf->tos);
688 #endif
689
690   if(iface->host_emul)
691     return -1;
692
693   memset(&ifr, 0, sizeof(struct ifreq));
694   memset(&ifs, 0, sizeof(struct interface));
695   strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
696
697   OLSR_PRINTF(debuglvl, "Checking %s:\n", ifr.ifr_name);
698
699   /* Get flags (and check if interface exists) */
700   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
701     {
702       OLSR_PRINTF(debuglvl, "\tNo such interface!\n");
703       return 0;
704     }
705
706   ifs.int_flags = ifr.ifr_flags;      
707
708
709   if ((ifs.int_flags & IFF_UP) == 0)
710     {
711       OLSR_PRINTF(debuglvl, "\tInterface not up - skipping it...\n");
712       return 0;
713     }
714
715   /* Check broadcast */
716   if ((olsr_cnf->ip_version == AF_INET) &&
717       !iface->cnf->ipv4_broadcast.v4.s_addr && /* Skip if fixed bcast */ 
718       (!(ifs.int_flags & IFF_BROADCAST))) 
719     {
720       OLSR_PRINTF(debuglvl, "\tNo broadcast - skipping\n");
721       return 0;
722     }
723
724
725   if (ifs.int_flags & IFF_LOOPBACK)
726     {
727       OLSR_PRINTF(debuglvl, "\tThis is a loopback interface - skipping it...\n");
728       return 0;
729     }
730
731   ifs.is_hcif = OLSR_FALSE;
732
733   /* trying to detect if interface is wireless. */
734   ifs.is_wireless = check_wireless_interface(ifr.ifr_name);
735
736   if(ifs.is_wireless)
737     OLSR_PRINTF(debuglvl, "\tWireless interface detected\n");
738   else
739     OLSR_PRINTF(debuglvl, "\tNot a wireless interface\n");
740
741   
742   /* IP version 6 */
743   if(olsr_cnf->ip_version == AF_INET6)
744     {
745       /* Get interface address */
746       struct ipaddr_str buf;
747       if(get_ipv6_address(ifr.ifr_name, &ifs.int6_addr, iface->cnf->ipv6_addrtype) <= 0)
748         {
749           if(iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL)
750             OLSR_PRINTF(debuglvl, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
751           else
752             OLSR_PRINTF(debuglvl, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
753           
754           return 0;
755         }
756       
757       OLSR_PRINTF(debuglvl, "\tAddress: %s\n", ip6_to_string(&buf, &ifs.int6_addr.sin6_addr));
758       
759       /* Multicast */
760       memset (&ifs.int6_multaddr, 0, sizeof (ifs.int6_multaddr));
761       ifs.int6_multaddr.sin6_family   = AF_INET6;
762       ifs.int6_multaddr.sin6_flowinfo = htonl(0);
763       ifs.int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
764       ifs.int6_multaddr.sin6_port     = htons(OLSRPORT);
765       ifs.int6_multaddr.sin6_addr = (iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL) ? 
766         iface->cnf->ipv6_multi_site.v6 :
767         iface->cnf->ipv6_multi_glbl.v6;
768       
769 #ifdef __MacOSX__
770       ifs.int6_multaddr.sin6_scope_id = 0;
771 #endif
772
773       OLSR_PRINTF(debuglvl, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
774       
775     }
776   /* IP version 4 */
777   else
778     {
779       /* Get interface address (IPv4)*/
780       if(ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) 
781         {
782           OLSR_PRINTF(debuglvl, "\tCould not get address of interface - skipping it\n");
783           return 0;
784         }
785       
786       ifs.int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
787       
788       /* Find netmask */
789       
790       if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) 
791         {
792           olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get netmask)", ifr.ifr_name);
793           return 0;
794         }
795       
796       ifs.int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
797       
798       /* Find broadcast address */
799       if(iface->cnf->ipv4_broadcast.v4.s_addr)
800         {
801           /* Specified broadcast */
802           memcpy(&((struct sockaddr_in *)&ifs.int_broadaddr)->sin_addr.s_addr, 
803                  &iface->cnf->ipv4_broadcast.v4, 
804                  sizeof(olsr_u32_t));
805         }
806       else
807         {
808           /* Autodetect */
809           if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) 
810             {
811               olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
812               return 0;
813             }
814           
815           ifs.int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
816         }
817       
818       /* Deactivate IP spoof filter */
819       deactivate_spoof(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version);
820       
821       /* Disable ICMP redirects */
822       disable_redirects(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version);
823       
824     }
825   
826   
827   /* Get interface index */
828   
829   ifs.if_index = if_nametoindex(ifr.ifr_name);
830   
831   /* Set interface metric */
832   if(iface->cnf->weight.fixed)
833     ifs.int_metric = iface->cnf->weight.value;
834   else
835     ifs.int_metric = calculate_if_metric(ifr.ifr_name);
836   OLSR_PRINTF(1, "\tMetric: %d\n", ifs.int_metric);
837
838   /* Get MTU */
839   if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
840     ifs.int_mtu = OLSR_DEFAULT_MTU;
841   else
842     ifs.int_mtu = ifr.ifr_mtu;
843
844   ifs.int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
845
846   ifs.ttl_index = -32; /* For the first 32 TC's, fish-eye is disabled */
847
848   /* Set up buffer */
849   net_add_buffer(&ifs);
850                
851   OLSR_PRINTF(1, "\tMTU - IPhdr: %d\n", ifs.int_mtu);
852
853   olsr_syslog(OLSR_LOG_INFO, "Adding interface %s\n", iface->name);
854   OLSR_PRINTF(1, "\tIndex %d\n", ifs.if_index);
855
856   if(olsr_cnf->ip_version == AF_INET)
857     {
858       struct ipaddr_str buf;
859       OLSR_PRINTF(1, "\tAddress:%s\n", ip4_to_string(&buf, ifs.int_addr.sin_addr));
860       OLSR_PRINTF(1, "\tNetmask:%s\n", ip4_to_string(&buf, ifs.int_netmask.sin_addr));
861       OLSR_PRINTF(1, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifs.int_broadaddr.sin_addr));
862     }
863   else
864     {
865       struct ipaddr_str buf;
866       OLSR_PRINTF(1, "\tAddress: %s\n", ip6_to_string(&buf, &ifs.int6_addr.sin6_addr));
867       OLSR_PRINTF(1, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
868     }
869   
870   ifp = olsr_malloc(sizeof (struct interface), "Interface update 2");
871   
872   iface->configured = 1;
873   iface->interf = ifp;
874
875   /* XXX bad code */
876   memcpy(ifp, &ifs, sizeof(struct interface));
877   
878   ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
879   if (olsr_cnf->max_jitter == 0)
880   {
881     /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
882     olsr_cnf->max_jitter = ifp->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
883   }
884
885   name_size = strlen(if_basename(ifr.ifr_name)) + 1;
886   ifp->gen_properties = NULL;
887   ifp->int_name = olsr_malloc(name_size, "Interface update 3");
888   strscpy(ifp->int_name, if_basename(ifr.ifr_name), name_size);
889   ifp->int_next = ifnet;
890   ifnet = ifp;
891
892   if(olsr_cnf->ip_version == AF_INET)
893     {
894       /* IP version 4 */
895       ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
896       /*
897        *We create one socket for each interface and bind
898        *the socket to it. This to ensure that we can control
899        *on what interface the message is transmitted
900        */
901       
902       ifp->olsr_socket = getsocket(BUFSPACE, ifp->int_name);
903       
904       if (ifp->olsr_socket < 0)
905         {
906           fprintf(stderr, "Could not initialize socket... exiting!\n\n");
907           olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
908           olsr_cnf->exit_value = EXIT_FAILURE;
909           kill(getpid(), SIGINT);
910         }
911
912     }
913   else
914     {
915       /* IP version 6 */
916       ifp->ip_addr.v6 =  ifp->int6_addr.sin6_addr;
917       
918       /*
919        *We create one socket for each interface and bind
920        *the socket to it. This to ensure that we can control
921        *on what interface the message is transmitted
922        */
923       
924       ifp->olsr_socket = getsocket6(BUFSPACE, ifp->int_name);
925       
926       join_mcast(ifp, ifp->olsr_socket);
927       
928       if (ifp->olsr_socket < 0)
929         {
930           fprintf(stderr, "Could not initialize socket... exiting!\n\n");
931           olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
932           olsr_cnf->exit_value = EXIT_FAILURE;
933           kill(getpid(), SIGINT);
934         }
935       
936     }
937
938   set_buffer_timer(ifp);
939
940   /* Register socket */
941   add_olsr_socket(ifp->olsr_socket, &olsr_input);
942   
943 #ifdef linux 
944   /* Set TOS */
945   
946   if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char*)&precedence, sizeof(precedence)) < 0)
947     {
948       perror("setsockopt(SO_PRIORITY)");
949       olsr_syslog(OLSR_LOG_ERR, "OLSRD: setsockopt(SO_PRIORITY) error %m");
950     }
951   if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char*)&tos_bits, sizeof(tos_bits)) < 0)    
952     {
953       perror("setsockopt(IP_TOS)");
954       olsr_syslog(OLSR_LOG_ERR, "setsockopt(IP_TOS) error %m");
955     }
956 #endif
957   
958   /*
959    *Initialize sequencenumber as a random 16bit value
960    */
961   ifp->olsr_seqnum = random() & 0xFFFF;
962
963   /*
964    * Set main address if this is the only interface
965    */
966   memset(&null_addr, 0, olsr_cnf->ipsize);
967   if(ipequal(&null_addr, &olsr_cnf->main_addr))
968     {
969       struct ipaddr_str buf;
970       olsr_cnf->main_addr = ifp->ip_addr;
971       OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
972       olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
973     }
974   
975   /*
976    * Register functions for periodic message generation 
977    */
978   ifp->hello_gen_timer =
979     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
980                      HELLO_JITTER, OLSR_TIMER_PERIODIC,
981                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
982                      ifp, hello_gen_timer_cookie->ci_id);
983   ifp->tc_gen_timer =
984     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
985                      TC_JITTER, OLSR_TIMER_PERIODIC,
986                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
987                      ifp, tc_gen_timer_cookie->ci_id);
988   ifp->mid_gen_timer =
989     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
990                      MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
991                      mid_gen_timer_cookie->ci_id);
992   ifp->hna_gen_timer =
993     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
994                      HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
995                      hna_gen_timer_cookie->ci_id);
996
997   /* Recalculate max topology hold time */
998   if(olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval) {
999     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
1000   }
1001   ifp->hello_etime = (olsr_reltime)(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
1002   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
1003   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
1004   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
1005   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
1006
1007
1008   /*
1009    *Call possible ifchange functions registered by plugins  
1010    */
1011   run_ifchg_cbs(ifp, IFCHG_IF_ADD);
1012
1013   return 1;
1014 }
1015
1016 /*
1017  * Local Variables:
1018  * c-basic-offset: 2
1019  * End:
1020  */