Normalize olsr_clock namespace
[olsrd.git] / src / interfaces.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 #include "defs.h"
43 #include "interfaces.h"
44 #include "olsr_timer.h"
45 #include "olsr_socket.h"
46 #include "olsr.h"
47 #include "parser.h"
48 #include "net_olsr.h"
49 #include "ipcalc.h"
50 #include "common/string.h"
51 #include "common/avl.h"
52 #include "olsr_logging.h"
53 #include "os_net.h"
54
55 #include <signal.h>
56 #include <unistd.h>
57 #include <assert.h>
58
59 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
60
61 /* The interface list head */
62 struct list_entity interface_head;
63
64 /* tree of lost interface IPs */
65 struct avl_tree interface_lost_tree;
66
67 /* Ifchange functions */
68 struct ifchgf {
69   ifchg_cb_func function;
70   struct ifchgf *next;
71 };
72
73 static struct ifchgf *ifchgf_list = NULL;
74
75
76 /* Some cookies for stats keeping */
77 static struct olsr_memcookie_info *interface_mem_cookie = NULL;
78 static struct olsr_memcookie_info *interface_lost_mem_cookie = NULL;
79
80 static struct olsr_timer_info *interface_poll_timerinfo = NULL;
81 static struct olsr_timer_info *hello_gen_timerinfo = NULL;
82
83 static void check_interface_updates(void *);
84
85 /**
86  * Do initialization of various data needed for network interface management.
87  * This function also tries to set up the given interfaces.
88  *
89  * @return if more than zero interfaces were configured
90  */
91 bool
92 init_interfaces(void)
93 {
94   struct olsr_if_config *tmp_if;
95
96   /* Initial values */
97   list_init_head(&interface_head);
98   avl_init(&interface_lost_tree, avl_comp_default, false, NULL);
99
100   /*
101    * Get some cookies for getting stats to ease troubleshooting.
102    */
103   interface_mem_cookie = olsr_memcookie_add("Interface", sizeof(struct interface));
104
105   interface_lost_mem_cookie = olsr_memcookie_add("Interface lost", sizeof(struct interface_lost));
106
107   interface_poll_timerinfo = olsr_timer_add("Interface Polling", &check_interface_updates, true);
108   hello_gen_timerinfo = olsr_timer_add("Hello Generation", &generate_hello, true);
109
110   OLSR_INFO(LOG_INTERFACE, "\n ---- Interface configuration ---- \n\n");
111
112   /* Run trough all interfaces immediately */
113   for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
114     add_interface(tmp_if);
115   }
116
117   /* Kick a periodic timer for the network interface update function */
118   olsr_timer_start(olsr_cnf->nic_chgs_pollrate, 5,
119                    NULL, interface_poll_timerinfo);
120
121   return (!list_is_empty(&interface_head));
122 }
123
124 static void remove_lost_interface_ip(struct interface_lost *lost) {
125 #if !defined(REMOVE_LOG_DEBUG)
126   struct ipaddr_str buf;
127 #endif
128
129   OLSR_DEBUG(LOG_INTERFACE, "Remove %s from lost interface list\n",
130       olsr_ip_to_string(&buf, &lost->ip));
131   avl_delete(&interface_lost_tree, &lost->node);
132   olsr_memcookie_free(interface_lost_mem_cookie, lost);
133 }
134
135 static void add_lost_interface_ip(union olsr_ip_addr *ip, uint32_t hello_timeout) {
136   struct interface_lost *lost;
137 #if !defined(REMOVE_LOG_DEBUG)
138   struct ipaddr_str buf;
139 #endif
140
141   lost = olsr_memcookie_malloc(interface_lost_mem_cookie);
142   lost->node.key = &lost->ip;
143   lost->ip = *ip;
144   lost->valid_until = olsr_clock_getAbsolute(hello_timeout * 2);
145   avl_insert(&interface_lost_tree, &lost->node);
146
147   OLSR_DEBUG(LOG_INTERFACE, "Added %s to lost interface list for %d ms\n",
148       olsr_ip_to_string(&buf, ip), hello_timeout*2);
149 }
150
151 static struct interface_lost *get_lost_interface_ip(union olsr_ip_addr *ip) {
152   struct interface_lost *lost;
153   assert(ip);
154   lost = avl_find_element(&interface_lost_tree, ip, lost, node);
155   return lost;
156 }
157
158 bool
159 is_lost_interface_ip(union olsr_ip_addr *ip) {
160   assert(ip);
161   return get_lost_interface_ip(ip) != NULL;
162 }
163
164 void destroy_interfaces(void) {
165   struct interface *iface, *iface_iterator;
166   struct interface_lost *lost, *lost_iterator;
167
168   OLSR_FOR_ALL_INTERFACES(iface, iface_iterator) {
169     remove_interface(iface);
170   }
171
172   OLSR_FOR_ALL_LOSTIF_ENTRIES(lost, lost_iterator) {
173     remove_lost_interface_ip(lost);
174   }
175 }
176
177 struct interface *
178 add_interface(struct olsr_if_config *iface) {
179   struct interface *ifp;
180   int sock_rcv, sock_send;
181
182   ifp = olsr_memcookie_malloc(interface_mem_cookie);
183   ifp->int_name = iface->name;
184
185   if ((os_init_interface(ifp, iface))) {
186     olsr_memcookie_free(interface_mem_cookie, ifp);
187     return NULL;
188   }
189
190   sock_rcv = os_getsocket46(olsr_cnf->ip_version, ifp->int_name, olsr_cnf->olsr_port, BUFSPACE, NULL);
191   sock_send = os_getsocket46(olsr_cnf->ip_version, ifp->int_name, olsr_cnf->olsr_port, BUFSPACE, &ifp->int_multicast);
192   if (sock_rcv < 0 || sock_send < 0) {
193     OLSR_ERROR(LOG_INTERFACE, "Could not initialize socket... exiting!\n\n");
194     olsr_exit(EXIT_FAILURE);
195   }
196
197   set_buffer_timer(ifp);
198
199   /* Register sockets */
200   ifp->olsr_socket = olsr_socket_add(sock_rcv, &olsr_input, NULL, OLSR_SOCKET_READ);
201   ifp->send_socket = olsr_socket_add(sock_send, &olsr_input, NULL, OLSR_SOCKET_READ);
202
203   os_socket_set_olsr_options(ifp, ifp->olsr_socket->fd, &ifp->int_multicast);
204   os_socket_set_olsr_options(ifp, ifp->send_socket->fd, &ifp->int_multicast);
205
206   /*
207    *Initialize packet sequencenumber as a random 16bit value
208    */
209   ifp->olsr_seqnum = random() & 0xFFFF;
210
211   /*
212    * Set main address if it's not set
213    */
214   if (olsr_ipcmp(&all_zero, &olsr_cnf->router_id) == 0) {
215 #if !defined(REMOVE_LOG_INFO)
216     struct ipaddr_str buf;
217 #endif
218     olsr_cnf->router_id = ifp->ip_addr;
219     OLSR_INFO(LOG_INTERFACE, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
220
221     /* initialize representation of this node in tc_set */
222     olsr_change_myself_tc();
223   }
224
225   /* Set up buffer */
226   net_add_buffer(ifp);
227
228   /*
229    * Register functions for periodic message generation
230    */
231   ifp->hello_gen_timer =
232     olsr_timer_start(iface->cnf->hello_params.emission_interval,
233                      HELLO_JITTER, ifp, hello_gen_timerinfo);
234   ifp->hello_interval = iface->cnf->hello_params.emission_interval;
235   ifp->hello_validity = iface->cnf->hello_params.validity_time;
236
237   ifp->mode = iface->cnf->mode;
238
239   /*
240    * Call possible ifchange functions registered by plugins
241    */
242   run_ifchg_cbs(ifp, IFCHG_IF_ADD);
243
244   /*
245    * The interface is ready, lock it.
246    */
247   lock_interface(ifp);
248
249   /*
250    * Link to config.
251    */
252   iface->interf = ifp;
253   lock_interface(iface->interf);
254
255   /* Queue */
256   list_add_before(&interface_head, &ifp->int_node);
257
258   return ifp;
259 }
260
261 /**
262  * Callback function for periodic check of interface parameters.
263  */
264 static void
265 check_interface_updates(void *foo __attribute__ ((unused)))
266 {
267   struct olsr_if_config *tmp_if;
268   struct interface_lost *lost, *iterator;
269
270   OLSR_DEBUG(LOG_INTERFACE, "Checking for updates in the interface set\n");
271
272   for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
273
274     if (!tmp_if->cnf->autodetect_chg) {
275       /* Don't check this interface */
276       OLSR_DEBUG(LOG_INTERFACE, "Not checking interface %s\n", tmp_if->name);
277       continue;
278     }
279
280     if (tmp_if->interf) {
281       chk_if_changed(tmp_if);
282     } else {
283       if (add_interface(tmp_if)) {
284         lost = get_lost_interface_ip(&tmp_if->interf->ip_addr);
285         if (lost) {
286           remove_lost_interface_ip(lost);
287         }
288       }
289     }
290   }
291
292   /* clean up lost interface tree */
293   OLSR_FOR_ALL_LOSTIF_ENTRIES(lost, iterator) {
294     if (olsr_clock_isPast(lost->valid_until)) {
295       remove_lost_interface_ip(lost);
296     }
297   }
298 }
299
300 /**
301  * Remove and cleanup a physical interface.
302  */
303 void
304 remove_interface(struct interface *ifp)
305 {
306   if (!ifp) {
307     return;
308   }
309
310   OLSR_INFO(LOG_INTERFACE, "Removing interface %s\n", ifp->int_name);
311
312   os_cleanup_interface(ifp);
313
314   olsr_delete_link_entry_by_if(ifp);
315
316   /*
317    * Call possible ifchange functions registered by plugins
318    */
319   run_ifchg_cbs(ifp, IFCHG_IF_REMOVE);
320
321   /* Dequeue */
322   list_remove(&ifp->int_node);
323
324   /* Remove output buffer */
325   net_remove_buffer(ifp);
326
327   /*
328    * Deregister functions for periodic message generation
329    */
330   olsr_timer_stop(ifp->hello_gen_timer);
331   ifp->hello_gen_timer = NULL;
332
333   /*
334    * Stop interface pacing.
335    */
336   olsr_timer_stop(ifp->buffer_hold_timer);
337   ifp->buffer_hold_timer = NULL;
338
339   /*
340    * remember the IP for some time
341    */
342   add_lost_interface_ip(&ifp->ip_addr, ifp->hello_validity);
343
344   /*
345    * Unlink from config.
346    */
347   unlock_interface(ifp);
348
349   /* Close olsr socket */
350   os_close(ifp->olsr_socket->fd);
351   os_close(ifp->send_socket->fd);
352
353   olsr_socket_remove(ifp->olsr_socket);
354   olsr_socket_remove(ifp->send_socket);
355
356   ifp->int_name = NULL;
357   unlock_interface(ifp);
358
359   if (list_is_empty(&interface_head) && !olsr_cnf->allow_no_interfaces) {
360     OLSR_ERROR(LOG_INTERFACE, "No more active interfaces - exiting.\n");
361     olsr_exit(EXIT_FAILURE);
362   }
363 }
364
365 void
366 run_ifchg_cbs(struct interface *ifp, int flag)
367 {
368   struct ifchgf *tmp;
369   for (tmp = ifchgf_list; tmp != NULL; tmp = tmp->next) {
370     tmp->function(ifp, flag);
371   }
372 }
373
374 /**
375  * Find the local interface with a given address.
376  *
377  * @param addr the address to check.
378  * @return the interface struct representing the interface
379  * that matched the address.
380  */
381 struct interface *
382 if_ifwithaddr(const union olsr_ip_addr *addr)
383 {
384   struct interface *ifp, *iterator;
385   if (!addr) {
386     return NULL;
387   }
388
389   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
390     if (olsr_ipcmp(&ifp->ip_addr, addr) == 0) {
391       return ifp;
392     }
393   }
394   return NULL;
395 }
396
397 /**
398  * Find the interface with a given number.
399  *
400  * @param nr the number of the interface to find.
401  * @return return the interface struct representing the interface
402  * that matched the number.
403  */
404 struct interface *
405 if_ifwithsock(int fd)
406 {
407   struct interface *ifp, *iterator;
408
409   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
410     if (ifp->olsr_socket->fd == fd) {
411       return ifp;
412     }
413     if (ifp->send_socket->fd == fd) {
414       return ifp;
415     }
416   }
417
418   return NULL;
419 }
420
421
422 /**
423  * Find the interface with a given label.
424  *
425  * @param if_name the label of the interface to find.
426  * @return return the interface struct representing the interface
427  * that matched the label.
428  */
429 struct interface *
430 if_ifwithname(const char *if_name)
431 {
432   struct interface *ifp, *iterator;
433
434   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
435     /* good ol' strcmp should be sufficient here */
436     if (strcmp(ifp->int_name, if_name) == 0) {
437       return ifp;
438     }
439   }
440
441   return NULL;
442 }
443
444 /**
445  * Find the interface with a given interface index.
446  *
447  * @param iif_index of the interface to find.
448  * @return return the interface struct representing the interface
449  * that matched the iif_index.
450  */
451 struct interface *
452 if_ifwithindex(const int if_index)
453 {
454   struct interface *ifp, *iterator;
455   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
456     if (ifp->if_index == if_index) {
457       return ifp;
458     }
459   }
460
461   return NULL;
462 }
463
464 /**
465  * Get an interface name for a given interface index
466  *
467  * @param iif_index of the interface to find.
468  * @return "" or interface name.
469  */
470 const char *
471 if_ifwithindex_name(const int if_index)
472 {
473   const struct interface *const ifp = if_ifwithindex(if_index);
474   return ifp == NULL ? "void" : ifp->int_name;
475 }
476
477 /**
478  * Lock an interface.
479  */
480 void
481 lock_interface(struct interface *ifp)
482 {
483   assert(ifp);
484
485   ifp->refcount++;
486 }
487
488 /**
489  * Unlock an interface and free it if the refcount went down to zero.
490  */
491 void
492 unlock_interface(struct interface *ifp)
493 {
494   /* Node must have a positive refcount balance */
495   assert(ifp->refcount);
496
497   if (--ifp->refcount) {
498     return;
499   }
500
501   /* Node must be dequeued at this point */
502   assert(!list_node_added(&ifp->int_node));
503
504   /* Free memory */
505   free(ifp->int_name);
506   olsr_memcookie_free(interface_mem_cookie, ifp);
507 }
508
509
510 /**
511  * Add an ifchange function. These functions are called on all (non-initial)
512  * changes in the interface set.
513  */
514 void
515 add_ifchgf(ifchg_cb_func f)
516 {
517   struct ifchgf *tmp = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
518
519   tmp->function = f;
520   tmp->next = ifchgf_list;
521   ifchgf_list = tmp;
522 }
523
524 #if 0
525
526 /*
527  * Remove an ifchange function
528  */
529 int
530 del_ifchgf(ifchg_cb_func f)
531 {
532   struct ifchgf *tmp, *prev;
533
534   for (tmp = ifchgf_list, prev = NULL; tmp != NULL; prev = tmp, tmp = tmp->next) {
535     if (tmp->function == f) {
536       /* Remove entry */
537       if (prev == NULL) {
538         ifchgf_list = tmp->next;
539       } else {
540         prev->next = tmp->next;
541       }
542       free(tmp);
543       return 1;
544     }
545   }
546   return 0;
547 }
548 #endif
549
550 /*
551  * Local Variables:
552  * c-basic-offset: 2
553  * indent-tabs-mode: nil
554  * End:
555  */