More cleanup of OS-specific interface, this times with win32
[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 "apm.h"
56 #include "neighbor_table.h"
57 #include "lq_packet.h"
58 #include "common/avl.h"
59 #include "net_olsr.h"
60 #include "lq_plugin.h"
61 #include "olsr_logging.h"
62 #include "os_log.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_alloc_timerinfo("Periodic SPF", &olsr_trigger_forced_update, true);
238     olsr_start_timer(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;
279   struct list_iterator iterator;
280   uint8_t *tmp;
281 #if !defined REMOVE_LOG_DEBUG
282   struct ipaddr_str buf;
283 #endif
284
285   /* Lookup sender address */
286   src = olsr_lookup_main_addr_by_alias(from_addr);
287   if (!src)
288     src = from_addr;
289
290   neighbor = olsr_lookup_nbr_entry(src, true);
291   if (!neighbor) {
292     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because no nbr entry found for %s\n",
293         msg->type, olsr_ip_to_string(&buf, src));
294     return 0;
295   }
296   if (!neighbor->is_sym) {
297     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because received by non-symmetric neighbor %s\n",
298         msg->type, olsr_ip_to_string(&buf, src));
299     return 0;
300   }
301
302   /* Check MPR */
303   if (neighbor->mprs_count == 0) {
304     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because we are no MPR for %s\n",
305         msg->type, olsr_ip_to_string(&buf, src));
306     /* don't forward packages if not a MPR */
307     return 0;
308   }
309
310   /* check if we already forwarded this message */
311   if (olsr_is_duplicate_message(msg, true, NULL)) {
312     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because we already forwarded it.\n",
313         msg->type, olsr_ip_to_string(&buf, src));
314     return 0;                   /* it's a duplicate, forget about it */
315   }
316
317   /* Treat TTL hopcnt */
318   msg->hopcnt++;
319   msg->ttl--;
320   tmp = binary;
321   olsr_put_msg_hdr(&tmp, msg);
322
323   if (msg->ttl == 0) {
324     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because TTL is 0.\n",
325         msg->type, olsr_ip_to_string(&buf, src));
326     return 0;                   /* TTL 0, forget about it */
327   }
328   OLSR_DEBUG(LOG_PACKET_PARSING, "Forwarding message type %d from %s.\n",
329       msg->type, olsr_ip_to_string(&buf, src));
330
331   /* looping trough interfaces */
332   OLSR_FOR_ALL_INTERFACES(ifn, iterator) {
333     if (net_output_pending(ifn)) {
334       /* dont forward to incoming interface if interface is mode ether */
335       if (in_if->mode == IF_MODE_ETHER && ifn == in_if)
336         continue;
337
338       /*
339        * Check if message is to big to be piggybacked
340        */
341       if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
342         /* Send */
343         net_output(ifn);
344         /* Buffer message */
345         set_buffer_timer(ifn);
346
347         if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
348           OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
349         }
350       }
351     } else {
352       /* No forwarding pending */
353       set_buffer_timer(ifn);
354
355       if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
356         OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
357       }
358     }
359   }
360
361   return 1;
362 }
363
364 static void
365 olsr_update_willingness(void *foo __attribute__ ((unused)))
366 {
367   int tmp_will = olsr_cnf->willingness;
368
369   /* Re-calculate willingness */
370   olsr_cnf->willingness = olsr_calculate_willingness();
371
372   if (tmp_will != olsr_cnf->willingness) {
373     OLSR_INFO(LOG_MAIN, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
374   }
375 }
376
377 void
378 olsr_init_willingness(void)
379 {
380   /* Some cookies for stats keeping */
381   static struct olsr_timer_info *willingness_timer_info = NULL;
382
383   if (olsr_cnf->willingness_auto) {
384     OLSR_INFO(LOG_MAIN, "Initialize automatic willingness...\n");
385     /* Run it first and then periodic. */
386     olsr_update_willingness(NULL);
387
388     willingness_timer_info = olsr_alloc_timerinfo("Update Willingness", &olsr_update_willingness, true);
389     olsr_start_timer(olsr_cnf->will_int, 5, NULL, willingness_timer_info);
390   }
391 }
392
393 /**
394  *Calculate this nodes willingness to act as a MPR
395  *based on either a fixed value or the power status
396  *of the node using APM
397  *
398  *@return a 8bit value from 0-7 representing the willingness
399  */
400
401 uint8_t
402 olsr_calculate_willingness(void)
403 {
404   struct olsr_apm_info ainfo;
405
406   /* If fixed willingness */
407   if (!olsr_cnf->willingness_auto)
408     return olsr_cnf->willingness;
409
410   if (apm_read(&ainfo) < 1)
411     return WILL_DEFAULT;
412
413   apm_printinfo(&ainfo);
414
415   /* If AC powered */
416   if (ainfo.ac_line_status == OLSR_AC_POWERED)
417     return 6;
418
419   /* If battery powered
420    *
421    * juice > 78% will: 3
422    * 78% > juice > 26% will: 2
423    * 26% > juice will: 1
424    */
425   return (ainfo.battery_percentage / 26);
426 }
427
428 const char *
429 olsr_msgtype_to_string(uint8_t msgtype)
430 {
431   static char type[20];
432
433   switch (msgtype) {
434   case (HELLO_MESSAGE):
435     return "HELLO";
436   case (TC_MESSAGE):
437     return "TC";
438   case (MID_MESSAGE):
439     return "MID";
440   case (HNA_MESSAGE):
441     return "HNA";
442   case (LQ_HELLO_MESSAGE):
443     return ("LQ-HELLO");
444   case (LQ_TC_MESSAGE):
445     return ("LQ-TC");
446   default:
447     break;
448   }
449
450   snprintf(type, sizeof(type), "UNKNOWN(%d)", msgtype);
451   return type;
452 }
453
454
455 const char *
456 olsr_link_to_string(uint8_t linktype)
457 {
458   static char type[20];
459
460   switch (linktype) {
461   case (UNSPEC_LINK):
462     return "UNSPEC";
463   case (ASYM_LINK):
464     return "ASYM";
465   case (SYM_LINK):
466     return "SYM";
467   case (LOST_LINK):
468     return "LOST";
469   default:
470     break;
471   }
472
473   snprintf(type, sizeof(type), "UNKNOWN(%d)", linktype);
474   return type;
475 }
476
477
478 const char *
479 olsr_status_to_string(uint8_t status)
480 {
481   static char type[20];
482
483   switch (status) {
484   case (NOT_NEIGH):
485     return "NOT NEIGH";
486   case (SYM_NEIGH):
487     return "NEIGHBOR";
488   case (MPR_NEIGH):
489     return "MPR";
490   default:
491     break;
492   }
493
494   snprintf(type, sizeof(type), "UNKNOWN(%d)", status);
495   return type;
496 }
497
498
499 /**
500  *Termination function to be called whenever a error occures
501  *that requires the daemon to terminate
502  *
503  *@param val the exit code for OLSR
504  */
505
506 void
507 olsr_exit(int val)
508 {
509   fflush(stdout);
510   olsr_cnf->exit_value = val;
511   if (app_state == STATE_INIT) {
512     exit(val);
513   }
514   app_state = STATE_SHUTDOWN;
515 }
516
517
518 /**
519  * Wrapper for malloc(3) that does error-checking
520  *
521  * @param size the number of bytes to allocalte
522  * @param caller a string identifying the caller for
523  * use in error messaging
524  *
525  * @return a void pointer to the memory allocated
526  */
527 void *
528 olsr_malloc(size_t size, const char *id __attribute__ ((unused)))
529 {
530   void *ptr;
531
532   /*
533    * Not all the callers do a proper cleaning of memory.
534    * Clean it on behalf of those.
535    */
536   ptr = calloc(1, size);
537
538   if (!ptr) {
539     OLSR_ERROR(LOG_MAIN, "Out of memory for id '%s': %s\n", id, strerror(errno));
540     olsr_exit(EXIT_FAILURE);
541   }
542   return ptr;
543 }
544
545 /*
546  * Same as strdup but works with olsr_malloc
547  */
548 char *
549 olsr_strdup(const char *s)
550 {
551   char *ret = olsr_malloc(1 + strlen(s), "olsr_strdup");
552   strcpy(ret, s);
553   return ret;
554 }
555
556 /*
557  * Same as strndup but works with olsr_malloc
558  */
559 char *
560 olsr_strndup(const char *s, size_t n)
561 {
562   size_t len = n < strlen(s) ? n : strlen(s);
563   char *ret = olsr_malloc(1 + len, "olsr_strndup");
564   strncpy(ret, s, len);
565   ret[len] = 0;
566   return ret;
567 }
568
569 /*
570  * Local Variables:
571  * c-basic-offset: 2
572  * indent-tabs-mode: nil
573  * End:
574  */