1 /*
2 * The olsr.org Optimized Link-State Routing daemon (olsrd)
3 *
4 * (c) by the OLSR project
5 *
6 * See our Git repository to find out who worked on this file
7 * and thus is a copyright holder on it.
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 * Visit http://www.olsr.org for more information.
39 *
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
43 *
44 */
45
46 /**
47 * All these functions are global
48 */
49
50 #include "defs.h"
51 #include "builddata.h"
52 #include "olsr.h"
53 #include "link_set.h"
54 #include "two_hop_neighbor_table.h"
55 #include "tc_set.h"
56 #include "duplicate_set.h"
57 #include "mpr_selector_set.h"
58 #include "mid_set.h"
59 #include "mpr.h"
60 #include "lq_mpr.h"
61 #include "olsr_spf.h"
62 #include "scheduler.h"
63 #include "apm.h"
64 #include "misc.h"
65 #include "neighbor_table.h"
66 #include "log.h"
67 #include "lq_packet.h"
68 #include "common/avl.h"
69 #include "net_olsr.h"
70 #include "lq_plugin.h"
71 #include "gateway.h"
72 #include "duplicate_handler.h"
73 #include "olsr_random.h"
74
75 #include <stdarg.h>
76 #include <signal.h>
77 #include <unistd.h>
78
79 bool changes_topology;
80 bool changes_neighborhood;
81 bool changes_hna;
82 bool changes_force;
83
84 /*COLLECT startup sleeps caused by warnings*/
85
86 #ifdef OLSR_COLLECT_STARTUP_SLEEP
87 static int max_startup_sleep = 0;
88 #endif /* OLSR_COLLECT_STARTUP_SLEEP */
89 static int sum_startup_sleep = 0;
90
olsr_startup_sleep(int s)91 void olsr_startup_sleep(int s)
92 {
93 sum_startup_sleep += s;
94 #ifdef OLSR_COLLECT_STARTUP_SLEEP
95 if (s > max_startup_sleep) max_startup_sleep=s;
96 #else /* OLSR_COLLECT_STARTUP_SLEEP */
97 sleep(s);
98 #endif /* OLSR_COLLECT_STARTUP_SLEEP */
99 }
100
olsr_do_startup_sleep(void)101 void olsr_do_startup_sleep(void)
102 {
103 #ifdef OLSR_COLLECT_STARTUP_SLEEP
104 if (sum_startup_sleep > max_startup_sleep)
105 printf("OLSR encountered multiple problems on startup, which should delay startup by %i seconds.\nAs this is quite much time, OLSR will sleep only %i seconds.\nBUT YOU SHOULD FIX ABOVE PROBLEMS!\n",
106 sum_startup_sleep,max_startup_sleep);
107 sleep(max_startup_sleep);
108 #else /* OLSR_COLLECT_STARTUP_SLEEP */
109 if (sum_startup_sleep > 0)
110 printf("olsrd startup was delayed %i seconds due to various nasty error messages.\nYOU SHOULD REALLY FIX ABOVE PROBLEMS!\n",
111 sum_startup_sleep);
112 #endif /* OLSR_COLLECT_STARTUP_SLEEP */
113 }
114
115 /**
116 * Process changes functions
117 */
118
119 struct pcf {
120 int (*function) (int, int, int);
121 struct pcf *next;
122 };
123
124 static struct pcf *pcf_list;
125
126 static uint16_t message_seqno;
127 union olsr_ip_addr all_zero;
128
129 /**
130 *Initialize the message sequence number as a random value
131 */
132 void
init_msg_seqno(void)133 init_msg_seqno(void)
134 {
135 message_seqno = olsr_random() & 0xFFFF;
136 }
137
138 /**
139 * Get and increment the message sequence number
140 *
141 *@return the seqno
142 */
143 uint16_t
get_msg_seqno(void)144 get_msg_seqno(void)
145 {
146 return message_seqno++;
147 }
148
149 bool
olsr_is_bad_duplicate_msg_seqno(uint16_t seqno)150 olsr_is_bad_duplicate_msg_seqno(uint16_t seqno) {
151 int32_t diff = (int32_t) seqno - (int32_t) message_seqno;
152
153 if (diff < -32768) {
154 diff += 65536;
155 }
156 else if (diff > 32767) {
157 diff -= 65536;
158 }
159 return diff > 0;
160 }
161
162 void
register_pcf(int (* f)(int,int,int))163 register_pcf(int (*f) (int, int, int))
164 {
165 struct pcf *new_pcf;
166
167 OLSR_PRINTF(1, "Registering pcf function\n");
168
169 new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
170
171 new_pcf->function = f;
172 new_pcf->next = pcf_list;
173 pcf_list = new_pcf;
174
175 }
176
177 /**
178 *Process changes in neighborhood or/and topology.
179 *Re-calculates the neighborhood/topology if there
180 *are any updates - then calls the right functions to
181 *update the routing table.
182 *@return 0
183 */
184 void
olsr_process_changes(void)185 olsr_process_changes(void)
186 {
187 struct pcf *tmp_pc_list;
188
189 #ifdef DEBUG
190 if (changes_neighborhood)
191 OLSR_PRINTF(3, "CHANGES IN NEIGHBORHOOD\n");
192 if (changes_topology)
193 OLSR_PRINTF(3, "CHANGES IN TOPOLOGY\n");
194 if (changes_hna)
195 OLSR_PRINTF(3, "CHANGES IN HNA\n");
196 #endif /* DEBUG */
197
198 if (!changes_neighborhood && !changes_topology && !changes_hna)
199 return;
200
201 if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1)) {
202 clear_console();
203 printf(" *** %s ***\n", olsrd_version);
204 }
205
206 if (changes_neighborhood) {
207 if (olsr_cnf->lq_level < 1) {
208 olsr_calculate_mpr();
209 } else {
210 olsr_calculate_lq_mpr();
211 }
212 }
213
214 /* calculate the routing table */
215 if (changes_neighborhood || changes_topology || changes_hna) {
216 olsr_calculate_routing_table(false);
217 }
218
219 if (olsr_cnf->debug_level > 0) {
220 if (olsr_cnf->debug_level > 2) {
221 olsr_print_mid_set();
222 #ifdef __linux__
223 olsr_print_gateway_entries();
224 #endif /* __linux__ */
225
226 if (olsr_cnf->debug_level > 3) {
227 if (olsr_cnf->debug_level > 8) {
228 olsr_print_duplicate_table();
229 }
230 olsr_print_hna_set();
231 }
232 }
233 olsr_print_link_set();
234 olsr_print_neighbor_table();
235 olsr_print_two_hop_neighbor_table();
236 if (olsr_cnf->debug_level > 3) {
237 olsr_print_tc_table();
238 }
239 }
240
241 for (tmp_pc_list = pcf_list; tmp_pc_list != NULL; tmp_pc_list = tmp_pc_list->next) {
242 tmp_pc_list->function(changes_neighborhood, changes_topology, changes_hna);
243 }
244
245 changes_neighborhood = false;
246 changes_topology = false;
247 changes_hna = false;
248 changes_force = false;
249 }
250
251 /**
252 *Initialize all the tables used(neighbor,
253 *topology, MID, HNA, MPR, dup).
254 *Also initalizes other variables
255 */
256 void
olsr_init_tables(void)257 olsr_init_tables(void)
258 {
259 changes_topology = false;
260 changes_neighborhood = false;
261 changes_hna = false;
262
263 /* Set avl tree comparator */
264 if (olsr_cnf->ipsize == 4) {
265 avl_comp_default = avl_comp_ipv4;
266 avl_comp_prefix_default = avl_comp_ipv4_prefix;
267 } else {
268 avl_comp_default = avl_comp_ipv6;
269 avl_comp_prefix_default = avl_comp_ipv6_prefix;
270 }
271
272 /* Initialize lq plugin set */
273 init_lq_handler_tree();
274
275 /* Initialize link set */
276 olsr_init_link_set();
277
278 /* Initialize duplicate table */
279 olsr_init_duplicate_set();
280
281 /* Initialize neighbor table */
282 olsr_init_neighbor_table();
283
284 /* Initialize routing table */
285 olsr_init_routing_table();
286
287 /* Initialize two hop table */
288 olsr_init_two_hop_table();
289
290 /* Initialize topology */
291 olsr_init_tc();
292
293 /* Initialize mpr selector table */
294 olsr_init_mprs_set();
295
296 /* Initialize MID set */
297 olsr_init_mid_set();
298
299 /* Initialize HNA set */
300 olsr_init_hna_set();
301
302 /* Initialize duplicate handler */
303 #ifndef NO_DUPLICATE_DETECTION_HANDLER
304 olsr_duplicate_handler_init();
305 #endif /* NO_DUPLICATE_DETECTION_HANDLER */
306 }
307
308 /**
309 *Check if a message is to be forwarded and forward
310 *it if necessary.
311 *
312 *@param m the OLSR message to be forwarded
313 *@param in_if the incoming interface
314 *@param from_addr neighbour we received message from
315 *
316 *@returns positive if forwarded
317 */
318 int
olsr_forward_message(union olsr_message * m,struct interface_olsr * in_if,union olsr_ip_addr * from_addr)319 olsr_forward_message(union olsr_message *m, struct interface_olsr *in_if, union olsr_ip_addr *from_addr)
320 {
321 union olsr_ip_addr *src;
322 struct neighbor_entry *neighbor;
323 int msgsize;
324 struct interface_olsr *ifn;
325 bool is_ttl_1 = false;
326
327 /*
328 * Sven-Ola: We should not flood the mesh with overdue messages. Because
329 * of a bug in parser.c:parse_packet, we have a lot of messages because
330 * all older olsrd's have lq_fish enabled.
331 */
332 if (AF_INET == olsr_cnf->ip_version) {
333 if (m->v4.ttl < 2 || 255 < (int)m->v4.hopcnt + (int)m->v4.ttl)
334 is_ttl_1 = true;
335 } else {
336 if (m->v6.ttl < 2 || 255 < (int)m->v6.hopcnt + (int)m->v6.ttl)
337 is_ttl_1 = true;
338 }
339
340 /* Lookup sender address */
341 src = mid_lookup_main_addr(from_addr);
342 if (!src)
343 src = from_addr;
344
345 neighbor = olsr_lookup_neighbor_table(src);
346 if (!neighbor)
347 return 0;
348
349 if (neighbor->status != SYM)
350 return 0;
351
352 /* Check MPR */
353 if (olsr_lookup_mprs_set(src) == NULL) {
354 #ifdef DEBUG
355 struct ipaddr_str buf;
356 OLSR_PRINTF(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(&buf, src));
357 #endif /* DEBUG */
358 return 0;
359 }
360
361 if (olsr_message_is_duplicate(m)) {
362 return 0;
363 }
364
365 /* Treat TTL hopcnt except for ethernet link */
366 if (!is_ttl_1) {
367 if (olsr_cnf->ip_version == AF_INET) {
368 /* IPv4 */
369 m->v4.hopcnt++;
370 m->v4.ttl--;
371 } else {
372 /* IPv6 */
373 m->v6.hopcnt++;
374 m->v6.ttl--;
375 }
376 }
377
378 /* Update packet data */
379 msgsize = ntohs(m->v4.olsr_msgsize);
380
381 /* looping trough interfaces */
382 for (ifn = ifnet; ifn; ifn = ifn->int_next) {
383 /* do not retransmit out through a interface if it has mode == silent */
384 if (ifn->mode == IF_MODE_SILENT) continue;
385
386 /* do not retransmit out through the same interface if it has mode == ether */
387 if (ifn == in_if && ifn->mode == IF_MODE_ETHER) continue;
388
389 /* do not forward TTL 1 messages to non-ether interfaces */
390 if (is_ttl_1 && ifn->mode != IF_MODE_ETHER) continue;
391
392 if (net_output_pending(ifn)) {
393 /*
394 * Check if message is to big to be piggybacked
395 */
396 if (net_outbuffer_push(ifn, m, msgsize) != msgsize) {
397 /* Send */
398 net_output(ifn);
399 /* Buffer message */
400 set_buffer_timer(ifn);
401
402 if (net_outbuffer_push(ifn, m, msgsize) != msgsize) {
403 OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
404 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
405 }
406 }
407 } else {
408 /* No forwarding pending */
409 set_buffer_timer(ifn);
410
411 if (net_outbuffer_push(ifn, m, msgsize) != msgsize) {
412 OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
413 olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
414 }
415 }
416 }
417 return 1;
418 }
419
420 void
set_buffer_timer(struct interface_olsr * ifn)421 set_buffer_timer(struct interface_olsr *ifn)
422 {
423 /* Set timer */
424 ifn->fwdtimer = GET_TIMESTAMP(olsr_random() * olsr_cnf->max_jitter * MSEC_PER_SEC / OLSR_RANDOM_MAX);
425 }
426
427 void
olsr_init_willingness(void)428 olsr_init_willingness(void)
429 {
430 if (olsr_cnf->willingness_auto) {
431
432 /* Run it first and then periodic. */
433 olsr_update_willingness(NULL);
434
435 olsr_start_timer((unsigned int)olsr_cnf->will_int * MSEC_PER_SEC, 5, OLSR_TIMER_PERIODIC, &olsr_update_willingness, NULL, 0);
436 }
437 }
438
439 void
olsr_update_willingness(void * foo)440 olsr_update_willingness(void *foo __attribute__ ((unused)))
441 {
442 int tmp_will = olsr_cnf->willingness;
443
444 /* Re-calculate willingness */
445 olsr_cnf->willingness = olsr_calculate_willingness();
446
447 if (tmp_will != olsr_cnf->willingness) {
448 OLSR_PRINTF(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
449 }
450 }
451
452 /**
453 *Calculate this nodes willingness to act as a MPR
454 *based on either a fixed value or the power status
455 *of the node using APM
456 *
457 *@return a 8bit value from 0-7 representing the willingness
458 */
459
460 uint8_t
olsr_calculate_willingness(void)461 olsr_calculate_willingness(void)
462 {
463 struct olsr_apm_info ainfo;
464
465 /* If fixed willingness */
466 if (!olsr_cnf->willingness_auto)
467 return olsr_cnf->willingness;
468
469 if (apm_read(&ainfo) < 1)
470 return WILL_DEFAULT;
471
472 apm_printinfo(&ainfo);
473
474 /* If AC powered */
475 if (ainfo.ac_line_status == OLSR_AC_POWERED)
476 return 6;
477
478 /* If battery powered
479 *
480 * juice > 78% will: 3
481 * 78% > juice > 26% will: 2
482 * 26% > juice will: 1
483 */
484 return (ainfo.battery_percentage / 26);
485 }
486
487 const char *
olsr_msgtype_to_string(uint8_t msgtype)488 olsr_msgtype_to_string(uint8_t msgtype)
489 {
490 static char type[20];
491
492 switch (msgtype) {
493 case (HELLO_MESSAGE):
494 return "HELLO";
495 case (TC_MESSAGE):
496 return "TC";
497 case (MID_MESSAGE):
498 return "MID";
499 case (HNA_MESSAGE):
500 return "HNA";
501 case (LQ_HELLO_MESSAGE):
502 return ("LQ-HELLO");
503 case (LQ_TC_MESSAGE):
504 return ("LQ-TC");
505 default:
506 break;
507 }
508
509 snprintf(type, sizeof(type), "UNKNOWN(%d)", msgtype);
510 return type;
511 }
512
513 const char *
olsr_link_to_string(uint8_t linktype)514 olsr_link_to_string(uint8_t linktype)
515 {
516 static char type[20];
517
518 switch (linktype) {
519 case (UNSPEC_LINK):
520 return "UNSPEC";
521 case (ASYM_LINK):
522 return "ASYM";
523 case (SYM_LINK):
524 return "SYM";
525 case (LOST_LINK):
526 return "LOST";
527 case (HIDE_LINK):
528 return "HIDE";
529 default:
530 break;
531 }
532
533 snprintf(type, sizeof(type), "UNKNOWN(%d)", linktype);
534 return type;
535 }
536
537 const char *
olsr_status_to_string(uint8_t status)538 olsr_status_to_string(uint8_t status)
539 {
540 static char type[20];
541
542 switch (status) {
543 case (NOT_NEIGH):
544 return "NOT NEIGH";
545 case (SYM_NEIGH):
546 return "NEIGHBOR";
547 case (MPR_NEIGH):
548 return "MPR";
549 default:
550 break;
551 }
552
553 snprintf(type, sizeof(type), "UNKNOWN(%d)", status);
554 return type;
555 }
556
557 /**
558 *Termination function to be called whenever a error occures
559 *that requires the daemon to terminate
560 *
561 *@param msg the message to write to the syslog and possibly stdout
562 *@param val the exit code
563 */
564
565 void
olsr_exit(const char * msg,int val)566 olsr_exit(const char *msg, int val)
567 {
568 if (msg) {
569 OLSR_PRINTF(1, "OLSR EXIT: %s\n", msg);
570 olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
571 }
572 fflush(stdout);
573 fflush(stderr);
574
575 if (olsr_cnf) {
576 olsr_cnf->exit_value = val;
577 }
578
579 raise(SIGTERM);
580
581 /* in case the signal handler was not setup yet */
582 exit(val);
583 }
584
585 /**
586 * Wrapper for malloc(3) that does error-checking
587 *
588 * @param size the number of bytes to allocate
589 * @param id a string identifying the caller for
590 * use in error messaging
591 *
592 * @return a void pointer to the memory allocated
593 */
594 void *
olsr_malloc(size_t size,const char * id)595 olsr_malloc(size_t size, const char *id)
596 {
597 void *ptr;
598
599 /*
600 * Not all the callers do a proper cleaning of memory.
601 * Clean it on behalf of those.
602 */
603 ptr = calloc(1, size);
604
605 if (!ptr) {
606 char buf[1024];
607 snprintf(buf, sizeof(buf), "%s: out of memory!: %s\n", id, strerror(errno));
608 olsr_exit(buf, EXIT_FAILURE);
609 }
610
611 return ptr;
612 }
613
614 /**
615 * Wrapper for realloc(3) that does error-checking
616 *
617 * @param ptr pointer to the buffer
618 * @param size the number of bytes to (re)allocate
619 * @param id a string identifying the caller for
620 * use in error messaging
621 *
622 * @return a void pointer to the memory allocated
623 */
624 void *
olsr_realloc(void * ptr,size_t size,const char * id)625 olsr_realloc(void * ptr, size_t size, const char *id)
626 {
627 ptr = realloc(ptr, size);
628 if (!ptr) {
629 char buf[1024];
630 snprintf(buf, sizeof(buf), "%s: out of memory!: %s\n", id, strerror(errno));
631 olsr_exit(buf, EXIT_FAILURE);
632 }
633
634 return ptr;
635 }
636
637 /**
638 *Wrapper for printf that prints to a specific
639 *debuglevel upper limit
640 *
641 */
642
643 int
olsr_printf(int loglevel,const char * format,...)644 olsr_printf(int loglevel, const char *format, ...)
645 {
646 if ((loglevel <= olsr_cnf->debug_level) && debug_handle) {
647 va_list arglist;
648 va_start(arglist, format);
649 vfprintf(debug_handle, format, arglist);
650 va_end(arglist);
651 }
652 return 0;
653 }
654
655 /*
656 * Local Variables:
657 * c-basic-offset: 2
658 * indent-tabs-mode: nil
659 * End:
660 */
661