Namespace cleanup of scheduler, remove "polling" sockets
[olsrd.git] / src / olsr.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  * All these functions are global
44  */
45
46 #include "defs.h"
47 #include "olsr.h"
48 #include "link_set.h"
49 #include "tc_set.h"
50 #include "duplicate_set.h"
51 #include "mid_set.h"
52 #include "lq_mpr.h"
53 #include "olsr_spf.h"
54 #include "scheduler.h"
55 #include "neighbor_table.h"
56 #include "lq_packet.h"
57 #include "common/avl.h"
58 #include "net_olsr.h"
59 #include "lq_plugin.h"
60 #include "olsr_logging.h"
61 #include "os_system.h"
62 #include "os_apm.h"
63
64 #include <assert.h>
65 #include <stdarg.h>
66 #include <unistd.h>
67 #include <stdlib.h>
68
69 static void olsr_update_willingness(void *);
70 static void olsr_trigger_forced_update(void *);
71
72 bool changes_topology;
73 bool changes_neighborhood;
74 bool changes_hna;
75 bool changes_force;
76
77 /**
78  * Process changes functions
79  */
80
81 struct pcf {
82   int (*function) (int, int, int);
83   struct pcf *next;
84 };
85
86 static struct pcf *pcf_list;
87
88 static uint16_t message_seqno;
89
90 /**
91  *Initialize the message sequence number as a random value
92  */
93 void
94 init_msg_seqno(void)
95 {
96   message_seqno = random() & 0xFFFF;
97   OLSR_DEBUG(LOG_MAIN, "Settings initial message sequence number to %u\n", message_seqno);
98 }
99
100 /**
101  * Get and increment the message sequence number
102  *
103  *@return the seqno
104  */
105 uint16_t
106 get_msg_seqno(void)
107 {
108   return message_seqno++;
109 }
110
111
112 void
113 register_pcf(int (*f) (int, int, int))
114 {
115   struct pcf *new_pcf;
116
117   OLSR_DEBUG(LOG_MAIN, "Registering pcf function\n");
118
119   new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
120
121   new_pcf->function = f;
122   new_pcf->next = pcf_list;
123   pcf_list = new_pcf;
124
125 }
126
127
128 /**
129  *Process changes in neighborhood or/and topology.
130  *Re-calculates the neighborhood/topology if there
131  *are any updates - then calls the right functions to
132  *update the routing table.
133  *@return 0
134  */
135 void
136 olsr_process_changes(void)
137 {
138   struct pcf *tmp_pc_list;
139
140   if (changes_neighborhood)
141     OLSR_DEBUG(LOG_MAIN, "CHANGES IN NEIGHBORHOOD\n");
142   if (changes_topology)
143     OLSR_DEBUG(LOG_MAIN, "CHANGES IN TOPOLOGY\n");
144   if (changes_hna)
145     OLSR_DEBUG(LOG_MAIN, "CHANGES IN HNA\n");
146
147   if (!changes_force && 0 >= olsr_cnf->lq_dlimit)
148     return;
149
150   if (!changes_neighborhood && !changes_topology && !changes_hna)
151     return;
152
153   if (olsr_cnf->log_target_stderr && olsr_cnf->clear_screen && isatty(STDOUT_FILENO)) {
154     os_clear_console();
155     printf("       *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host);
156   }
157
158   if (changes_neighborhood) {
159     olsr_calculate_lq_mpr();
160   }
161
162   /* calculate the routing table */
163   if (changes_neighborhood || changes_topology || changes_hna) {
164     olsr_calculate_routing_table(false);
165   }
166
167   olsr_print_link_set();
168   olsr_print_neighbor_table();
169   olsr_print_tc_table();
170   olsr_print_mid_set();
171   olsr_print_duplicate_table();
172   olsr_print_hna_set();
173
174   for (tmp_pc_list = pcf_list; tmp_pc_list != NULL; tmp_pc_list = tmp_pc_list->next) {
175     tmp_pc_list->function(changes_neighborhood, changes_topology, changes_hna);
176   }
177
178   changes_neighborhood = false;
179   changes_topology = false;
180   changes_hna = false;
181   changes_force = false;
182 }
183
184 /*
185  * Callback for the periodic route calculation.
186  */
187 static void
188 olsr_trigger_forced_update(void *unused __attribute__ ((unused)))
189 {
190
191   changes_force = true;
192   changes_neighborhood = true;
193   changes_topology = true;
194   changes_hna = true;
195
196   olsr_process_changes();
197 }
198
199 /**
200  *Initialize all the tables used(neighbor,
201  *topology, MID,  HNA, MPR, dup).
202  *Also initalizes other variables
203  */
204 void
205 olsr_init_tables(void)
206 {
207   /* Some cookies for stats keeping */
208   static struct olsr_timer_info *periodic_spf_timer_info = NULL;
209
210   changes_topology = false;
211   changes_neighborhood = false;
212   changes_hna = false;
213
214   /* Initialize link set */
215   olsr_init_link_set();
216
217   /* Initialize duplicate table */
218   olsr_init_duplicate_set();
219
220   /* Initialize neighbor table */
221   olsr_init_neighbor_table();
222
223   /* Initialize routing table */
224   olsr_init_routing_table();
225
226   /* Initialize topology */
227   olsr_init_tc();
228
229   /* Initialize MID set */
230   olsr_init_mid_set();
231
232   /* Initialize HNA set */
233   olsr_init_hna_set();
234
235   /* Start periodic SPF and RIB recalculation */
236   if (olsr_cnf->lq_dinter > 0) {
237     periodic_spf_timer_info = olsr_timer_add("Periodic SPF", &olsr_trigger_forced_update, true);
238     olsr_timer_start(olsr_cnf->lq_dinter, 5,
239                      NULL, periodic_spf_timer_info);
240   }
241 }
242
243 /**
244  * Shared code to write the message header
245  */
246 uint8_t *olsr_put_msg_hdr(uint8_t **curr, struct olsr_message *msg)
247 {
248   uint8_t *sizeptr;
249
250   assert(msg);
251   assert(curr);
252
253   pkt_put_u8(curr, msg->type);
254   pkt_put_reltime(curr, msg->vtime);
255   sizeptr = *curr;
256   pkt_put_u16(curr, msg->size);
257   pkt_put_ipaddress(curr, &msg->originator);
258   pkt_put_u8(curr, msg->ttl);
259   pkt_put_u8(curr, msg->hopcnt);
260   pkt_put_u16(curr, msg->seqno);
261
262   return sizeptr;
263 }
264
265 /**
266  *Check if a message is to be forwarded and forward
267  *it if necessary.
268  *
269  *@param m the OLSR message recieved
270  *
271  *@returns positive if forwarded
272  */
273 int
274 olsr_forward_message(struct olsr_message *msg, uint8_t *binary, struct interface *in_if, union olsr_ip_addr *from_addr)
275 {
276   union olsr_ip_addr *src;
277   struct nbr_entry *neighbor;
278   struct interface *ifn, *iterator;
279   uint8_t *tmp;
280 #if !defined REMOVE_LOG_DEBUG
281   struct ipaddr_str buf;
282 #endif
283
284   /* Lookup sender address */
285   src = olsr_lookup_main_addr_by_alias(from_addr);
286   if (!src)
287     src = from_addr;
288
289   neighbor = olsr_lookup_nbr_entry(src, true);
290   if (!neighbor) {
291     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because no nbr entry found for %s\n",
292         msg->type, olsr_ip_to_string(&buf, src));
293     return 0;
294   }
295   if (!neighbor->is_sym) {
296     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because received by non-symmetric neighbor %s\n",
297         msg->type, olsr_ip_to_string(&buf, src));
298     return 0;
299   }
300
301   /* Check MPR */
302   if (neighbor->mprs_count == 0) {
303     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because we are no MPR for %s\n",
304         msg->type, olsr_ip_to_string(&buf, src));
305     /* don't forward packages if not a MPR */
306     return 0;
307   }
308
309   /* check if we already forwarded this message */
310   if (olsr_is_duplicate_message(msg, true, NULL)) {
311     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because we already forwarded it.\n",
312         msg->type, olsr_ip_to_string(&buf, src));
313     return 0;                   /* it's a duplicate, forget about it */
314   }
315
316   /* Treat TTL hopcnt */
317   msg->hopcnt++;
318   msg->ttl--;
319   tmp = binary;
320   olsr_put_msg_hdr(&tmp, msg);
321
322   if (msg->ttl == 0) {
323     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because TTL is 0.\n",
324         msg->type, olsr_ip_to_string(&buf, src));
325     return 0;                   /* TTL 0, forget about it */
326   }
327   OLSR_DEBUG(LOG_PACKET_PARSING, "Forwarding message type %d from %s.\n",
328       msg->type, olsr_ip_to_string(&buf, src));
329
330   /* looping trough interfaces */
331   OLSR_FOR_ALL_INTERFACES(ifn, iterator) {
332     if (net_output_pending(ifn)) {
333       /* dont forward to incoming interface if interface is mode ether */
334       if (in_if->mode == IF_MODE_ETHER && ifn == in_if)
335         continue;
336
337       /*
338        * Check if message is to big to be piggybacked
339        */
340       if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
341         /* Send */
342         net_output(ifn);
343         /* Buffer message */
344         set_buffer_timer(ifn);
345
346         if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
347           OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
348         }
349       }
350     } else {
351       /* No forwarding pending */
352       set_buffer_timer(ifn);
353
354       if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
355         OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
356       }
357     }
358   }
359
360   return 1;
361 }
362
363 static void
364 olsr_update_willingness(void *foo __attribute__ ((unused)))
365 {
366   int tmp_will = olsr_cnf->willingness;
367
368   /* Re-calculate willingness */
369   olsr_calculate_willingness();
370
371   if (tmp_will != olsr_cnf->willingness) {
372     OLSR_INFO(LOG_MAIN, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
373   }
374 }
375
376 void
377 olsr_init_willingness(void)
378 {
379   /* Some cookies for stats keeping */
380   static struct olsr_timer_info *willingness_timer_info = NULL;
381
382   if (olsr_cnf->willingness_auto) {
383     OLSR_INFO(LOG_MAIN, "Initialize automatic willingness...\n");
384     /* Run it first and then periodic. */
385     olsr_update_willingness(NULL);
386
387     willingness_timer_info = olsr_timer_add("Update Willingness", &olsr_update_willingness, true);
388     olsr_timer_start(olsr_cnf->will_int, 5, NULL, willingness_timer_info);
389   }
390 }
391
392 /**
393  *Calculate this nodes willingness to act as a MPR
394  *based on either a fixed value or the power status
395  *of the node using APM
396  *
397  *@return a 8bit value from 0-7 representing the willingness
398  */
399
400 void
401 olsr_calculate_willingness(void)
402 {
403   struct olsr_apm_info ainfo;
404 #if !defined(REMOVE_LOG_INFO)
405   struct millitxt_buf tbuf;
406 #endif
407
408   /* If fixed willingness */
409   if (!olsr_cnf->willingness_auto)
410     return;
411
412   if (os_apm_read(&ainfo) < 1) {
413     olsr_cnf->willingness = WILL_DEFAULT;
414     olsr_cnf->willingness_auto = false;
415     OLSR_WARN(LOG_MAIN, "Cannot read APM info, setting willingness to default value (%d)", olsr_cnf->willingness);
416     return;
417   }
418
419   os_apm_printinfo(&ainfo);
420
421   /* If AC powered */
422   if (ainfo.ac_line_status == OLSR_AC_POWERED) {
423     olsr_cnf->willingness = 6;
424   }
425   else {
426   /* If battery powered
427    *
428    * juice > 78% will: 3
429    * 78% > juice > 26% will: 2
430    * 26% > juice will: 1
431    */
432     olsr_cnf->willingness = (ainfo.battery_percentage / 26);
433   }
434   OLSR_INFO(LOG_MAIN, "Willingness set to %d - next update in %s secs\n",
435       olsr_cnf->willingness, olsr_milli_to_txt(&tbuf, olsr_cnf->will_int));
436 }
437
438 const char *
439 olsr_msgtype_to_string(uint8_t msgtype)
440 {
441   static char type[20];
442
443   switch (msgtype) {
444   case (HELLO_MESSAGE):
445     return "HELLO";
446   case (TC_MESSAGE):
447     return "TC";
448   case (MID_MESSAGE):
449     return "MID";
450   case (HNA_MESSAGE):
451     return "HNA";
452   case (LQ_HELLO_MESSAGE):
453     return ("LQ-HELLO");
454   case (LQ_TC_MESSAGE):
455     return ("LQ-TC");
456   default:
457     break;
458   }
459
460   snprintf(type, sizeof(type), "UNKNOWN(%d)", msgtype);
461   return type;
462 }
463
464
465 const char *
466 olsr_link_to_string(uint8_t linktype)
467 {
468   static char type[20];
469
470   switch (linktype) {
471   case (UNSPEC_LINK):
472     return "UNSPEC";
473   case (ASYM_LINK):
474     return "ASYM";
475   case (SYM_LINK):
476     return "SYM";
477   case (LOST_LINK):
478     return "LOST";
479   default:
480     break;
481   }
482
483   snprintf(type, sizeof(type), "UNKNOWN(%d)", linktype);
484   return type;
485 }
486
487
488 const char *
489 olsr_status_to_string(uint8_t status)
490 {
491   static char type[20];
492
493   switch (status) {
494   case (NOT_NEIGH):
495     return "NOT NEIGH";
496   case (SYM_NEIGH):
497     return "NEIGHBOR";
498   case (MPR_NEIGH):
499     return "MPR";
500   default:
501     break;
502   }
503
504   snprintf(type, sizeof(type), "UNKNOWN(%d)", status);
505   return type;
506 }
507
508
509 /**
510  *Termination function to be called whenever a error occures
511  *that requires the daemon to terminate
512  *
513  *@param val the exit code for OLSR
514  */
515
516 void
517 olsr_exit(int val)
518 {
519   fflush(stdout);
520   olsr_cnf->exit_value = val;
521   if (app_state == STATE_INIT) {
522     os_exit(val);
523   }
524   app_state = STATE_SHUTDOWN;
525 }
526
527
528 /**
529  * Wrapper for malloc(3) that does error-checking
530  *
531  * @param size the number of bytes to allocalte
532  * @param caller a string identifying the caller for
533  * use in error messaging
534  *
535  * @return a void pointer to the memory allocated
536  */
537 void *
538 olsr_malloc(size_t size, const char *id __attribute__ ((unused)))
539 {
540   void *ptr;
541
542   /*
543    * Not all the callers do a proper cleaning of memory.
544    * Clean it on behalf of those.
545    */
546   ptr = calloc(1, size);
547
548   if (!ptr) {
549     OLSR_ERROR(LOG_MAIN, "Out of memory for id '%s': %s\n", id, strerror(errno));
550     olsr_exit(EXIT_FAILURE);
551   }
552   return ptr;
553 }
554
555 /*
556  * Same as strdup but works with olsr_malloc
557  */
558 char *
559 olsr_strdup(const char *s)
560 {
561   char *ret = olsr_malloc(1 + strlen(s), "olsr_strdup");
562   strcpy(ret, s);
563   return ret;
564 }
565
566 /*
567  * Same as strndup but works with olsr_malloc
568  */
569 char *
570 olsr_strndup(const char *s, size_t n)
571 {
572   size_t len = n < strlen(s) ? n : strlen(s);
573   char *ret = olsr_malloc(1 + len, "olsr_strndup");
574   strncpy(ret, s, len);
575   ret[len] = 0;
576   return ret;
577 }
578
579 /*
580  * Local Variables:
581  * c-basic-offset: 2
582  * indent-tabs-mode: nil
583  * End:
584  */