ee7d9cd9ce03b737126fa549de9949a0d804aa95
[olsrd.git] / src / olsr.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  * $Id: olsr.c,v 1.48 2006/01/07 08:16:20 kattemat Exp $
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 "two_hop_neighbor_table.h"
50 #include "tc_set.h"
51 #include "duplicate_set.h"
52 #include "mpr_selector_set.h"
53 #include "mid_set.h"
54 #include "mpr.h"
55 #include "lq_mpr.h"
56 #include "lq_route.h"
57 #include "scheduler.h"
58 #include "apm.h"
59 #include "misc.h"
60 #include "neighbor_table.h"
61 #include "log.h"
62 #include "lq_packet.h"
63
64 #include <stdarg.h>
65 #include <signal.h>
66
67
68 olsr_bool changes_topology;
69 olsr_bool changes_neighborhood;
70 olsr_bool changes_hna;
71
72 /**
73  * Process changes functions
74  */
75
76 struct pcf
77 {
78   int (*function)(int, int, int);
79   struct pcf *next;
80 };
81
82 static struct pcf *pcf_list;
83
84 static olsr_u16_t message_seqno;
85
86 /**
87  *Initialize the message sequence number as a random value
88  */
89 void
90 init_msg_seqno()
91 {
92   message_seqno = random() & 0xFFFF;
93 }
94
95 /**
96  * Get and increment the message sequence number
97  *
98  *@return the seqno
99  */
100 inline olsr_u16_t
101 get_msg_seqno()
102 {
103   return message_seqno++;
104 }
105
106
107 void
108 register_pcf(int (*f)(int, int, int))
109 {
110   struct pcf *new_pcf;
111
112   OLSR_PRINTF(1, "Registering pcf function\n")
113
114   new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
115
116   new_pcf->function = f;
117   new_pcf->next = pcf_list;
118   pcf_list = new_pcf;
119
120 }
121
122
123 /**
124  *Process changes in neighborhood or/and topology.
125  *Re-calculates the neighborhooh/topology if there
126  *are any updates - then calls the right functions to
127  *update the routing table.
128  *@return 0
129  */
130 void
131 olsr_process_changes()
132 {
133
134   struct pcf *tmp_pc_list;
135
136 #ifdef DEBUG
137   if(changes_neighborhood)
138     OLSR_PRINTF(3, "CHANGES IN NEIGHBORHOOD\n")
139   if(changes_topology)
140     OLSR_PRINTF(3, "CHANGES IN TOPOLOGY\n")
141   if(changes_hna)
142     OLSR_PRINTF(3, "CHANGES IN HNA\n")
143 #endif
144   
145   if(!changes_neighborhood &&
146      !changes_topology &&
147      !changes_hna)
148     return;
149
150   if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1))
151   {
152       clear_console();
153       printf("%s", OLSRD_VERSION_DATE);
154   }
155
156   if (changes_neighborhood)
157     {
158       /* Calculate new mprs, HNA and routing table */
159       if (olsr_cnf->lq_level < 1)
160         {
161           olsr_calculate_mpr();
162         }
163
164       else
165         {
166           olsr_calculate_lq_mpr();
167         }
168
169       if (olsr_cnf->lq_level < 2)
170         {
171           olsr_calculate_routing_table();
172           olsr_calculate_hna_routes();
173         }
174
175       else
176         {
177           olsr_calculate_lq_routing_table();
178         }
179     }
180   
181   else if (changes_topology)
182     {
183       /* calculate the routing table and HNA */
184
185       if (olsr_cnf->lq_level < 2)
186         {
187           olsr_calculate_routing_table();
188           olsr_calculate_hna_routes();
189         }
190
191       else
192         {
193           olsr_calculate_lq_routing_table();
194         }
195     }
196
197   else if (changes_hna)
198     {
199       /* update HNA routes */
200
201       if (olsr_cnf->lq_level < 2)
202         {
203           olsr_calculate_hna_routes();
204         }
205
206       else
207         {
208           olsr_calculate_lq_routing_table();
209         }
210     }
211   
212   if (olsr_cnf->debug_level > 0)
213     {      
214       if (olsr_cnf->debug_level > 2) 
215         {
216           olsr_print_mid_set();
217           
218           if (olsr_cnf->debug_level > 3)
219             {
220               olsr_print_duplicate_table();
221               olsr_print_hna_set();
222             }
223         }
224       
225       olsr_print_link_set();
226       olsr_print_neighbor_table();
227       olsr_print_tc_table();
228     }
229
230   for(tmp_pc_list = pcf_list; 
231       tmp_pc_list != NULL;
232       tmp_pc_list = tmp_pc_list->next)
233     {
234       tmp_pc_list->function(changes_neighborhood,
235                             changes_topology,
236                             changes_hna);
237     }
238
239   changes_neighborhood = OLSR_FALSE;
240   changes_topology = OLSR_FALSE;
241   changes_hna = OLSR_FALSE;
242
243
244   return;
245 }
246
247
248
249
250
251 /**
252  *Initialize all the tables used(neighbor,
253  *topology, MID,  HNA, MPR, dup).
254  *Also initalizes other variables
255  */
256 void
257 olsr_init_tables()
258 {
259   
260   changes_topology = OLSR_FALSE;
261   changes_neighborhood = OLSR_FALSE;
262   changes_hna = OLSR_FALSE;
263
264   /* Initialize link set */
265   olsr_init_link_set();
266
267   /* Initialize duplicate table */
268   olsr_init_duplicate_table();
269
270   /* Initialize neighbor table */
271   olsr_init_neighbor_table();
272
273   /* Initialize routing table */
274   olsr_init_routing_table();
275
276   /* Initialize two hop table */
277   olsr_init_two_hop_table();
278
279   /* Initialize old route table */
280   olsr_init_old_table();
281
282   /* Initialize topology */
283   olsr_init_tc();
284
285   /* Initialize mpr selector table */
286   olsr_init_mprs_set();
287
288   /* Initialize MID set */
289   olsr_init_mid_set();
290
291   /* Initialize HNA set */
292   olsr_init_hna_set();
293   
294 }
295
296
297
298
299
300
301 /**
302  *Check if a message is to be forwarded and forward
303  *it if necessary.
304  *
305  *@param m the OLSR message recieved
306  *@param originator the originator of this message
307  *@param seqno the seqno of the message
308  *
309  *@returns positive if forwarded
310  */
311 int
312 olsr_forward_message(union olsr_message *m, 
313                      union olsr_ip_addr *originator, 
314                      olsr_u16_t seqno,
315                      struct interface *in_if, 
316                      union olsr_ip_addr *from_addr)
317 {
318   union olsr_ip_addr *src;
319   struct neighbor_entry *neighbor;
320   int msgsize;
321   struct interface *ifn;
322
323
324   if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
325     {
326 #ifdef DEBUG
327       OLSR_PRINTF(3, "Message already forwarded!\n")
328 #endif
329       return 0;
330     }
331
332   /* Lookup sender address */
333   if(!(src = mid_lookup_main_addr(from_addr)))
334     src = from_addr;
335
336
337   if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
338     return 0;
339
340   if(neighbor->status != SYM)
341     return 0;
342
343   /* Update duplicate table interface */
344   olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
345
346   
347   /* Check MPR */
348   if(olsr_lookup_mprs_set(src) == NULL)
349     {
350 #ifdef DEBUG
351       OLSR_PRINTF(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src))
352 #endif
353       return 0;
354     }
355
356
357   /* Treat TTL hopcnt */
358   if(olsr_cnf->ip_version == AF_INET)
359     {
360       /* IPv4 */
361       m->v4.hopcnt++;
362       m->v4.ttl--; 
363     }
364   else
365     {
366       /* IPv6 */
367       m->v6.hopcnt++;
368       m->v6.ttl--; 
369     }
370
371
372
373   /* Update dup forwarded */
374   olsr_set_dup_forward(originator, seqno);
375
376   /* Update packet data */
377
378
379   msgsize = ntohs(m->v4.olsr_msgsize);
380
381   /* looping trough interfaces */
382   for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
383     { 
384       if(net_output_pending(ifn))
385         {
386           /*
387            * Check if message is to big to be piggybacked
388            */
389           if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
390             {
391               /* Send */
392               net_output(ifn);
393               /* Buffer message */
394               set_buffer_timer(ifn);
395               
396               if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
397                 {
398                   OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize)
399                   olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
400                 }
401
402             }
403         }
404       
405       else
406         {
407           /* No forwarding pending */
408           set_buffer_timer(ifn);
409           
410           if(net_outbuffer_push(ifn, (olsr_u8_t *)m, msgsize) != msgsize)
411             {
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
418   return 1;
419
420 }
421
422
423 void
424 set_buffer_timer(struct interface *ifn)
425 {
426   float jitter;
427       
428   /* Set timer */
429   jitter = (float) random()/RAND_MAX;
430   jitter *= olsr_cnf->max_jitter;
431
432   ifn->fwdtimer = GET_TIMESTAMP(jitter*1000);
433
434 }
435
436
437
438 void
439 olsr_init_willingness()
440 {
441   if(olsr_cnf->willingness_auto)
442     olsr_register_scheduler_event(&olsr_update_willingness, 
443                                   NULL, olsr_cnf->will_int, olsr_cnf->will_int, NULL);
444 }
445
446 void
447 olsr_update_willingness(void *foo)
448 {
449   int tmp_will;
450
451   tmp_will = olsr_cnf->willingness;
452
453   /* Re-calculate willingness */
454   olsr_cnf->willingness = olsr_calculate_willingness();
455
456   if(tmp_will != olsr_cnf->willingness)
457     {
458       OLSR_PRINTF(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness)
459     }
460 }
461
462
463 /**
464  *Calculate this nodes willingness to act as a MPR
465  *based on either a fixed value or the power status
466  *of the node using APM
467  *
468  *@return a 8bit value from 0-7 representing the willingness
469  */
470
471 olsr_u8_t
472 olsr_calculate_willingness()
473 {
474   struct olsr_apm_info ainfo;
475
476   /* If fixed willingness */
477   if(!olsr_cnf->willingness_auto)
478     return olsr_cnf->willingness;
479
480   if(apm_read(&ainfo) < 1)
481     return WILL_DEFAULT;
482
483   apm_printinfo(&ainfo);
484
485   /* If AC powered */
486   if(ainfo.ac_line_status == OLSR_AC_POWERED)
487     return 6;
488
489   /* If battery powered 
490    *
491    * juice > 78% will: 3
492    * 78% > juice > 26% will: 2
493    * 26% > juice will: 1
494    */
495   return (ainfo.battery_percentage / 26);
496 }
497
498 const char *
499 olsr_msgtype_to_string(olsr_u8_t msgtype)
500 {
501   static char type[20];
502
503   switch(msgtype)
504     {
505     case(HELLO_MESSAGE):
506       return "HELLO";
507     case(TC_MESSAGE):
508       return "TC";
509     case(MID_MESSAGE):
510       return "MID";
511     case(HNA_MESSAGE):
512       return "HNA";
513     case(LQ_HELLO_MESSAGE):
514       return("LQ-HELLO");
515     case(LQ_TC_MESSAGE):
516       return("LQ-TC");
517     default:
518       break;
519     }
520
521   snprintf(type, 20, "UNKNOWN(%d)", msgtype);
522   return type;
523 }
524
525
526 const char *
527 olsr_link_to_string(olsr_u8_t linktype)
528 {
529   static char type[20];
530
531   switch(linktype)
532     {
533     case(UNSPEC_LINK):
534       return "UNSPEC";
535     case(ASYM_LINK):
536       return "ASYM";
537     case(SYM_LINK):
538       return "SYM";
539     case(LOST_LINK):
540       return "LOST";
541     case(HIDE_LINK):
542       return "HIDE";
543     default:
544       break;
545     }
546
547   snprintf(type, 20, "UNKNOWN(%d)", linktype);
548   return type;
549 }
550
551
552 const char *
553 olsr_status_to_string(olsr_u8_t status)
554 {
555   static char type[20];
556
557   switch(status)
558     {
559     case(NOT_NEIGH):
560       return "NOT NEIGH";
561     case(SYM_NEIGH):
562       return "NEIGHBOR";
563     case(MPR_NEIGH):
564       return "MPR";
565     default:
566       break;
567     }
568
569   snprintf(type, 20, "UNKNOWN(%d)", status);
570   return type;
571 }
572
573
574 /**
575  *Termination function to be called whenever a error occures
576  *that requires the daemon to terminate
577  *
578  *@param msg the message to write to the syslog and possibly stdout
579  */
580
581 void
582 olsr_exit(const char *msg, int val)
583 {
584   OLSR_PRINTF(1, "OLSR EXIT: %s\n", msg)
585   olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
586   fflush(stdout);
587   olsr_cnf->exit_value = val;
588
589   raise(SIGTERM);
590 }
591
592
593 /**
594  *Wrapper for malloc(3) that does error-checking
595  *
596  *@param size the number of bytes to allocalte
597  *@param caller a string identifying the caller for
598  *use in error messaging
599  *
600  *@return a void pointer to the memory allocated
601  */
602 void *
603 olsr_malloc(size_t size, const char *id)
604 {
605   void *ptr;
606
607   if((ptr = malloc(size)) == 0) 
608     {
609       OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", strerror(errno))
610       olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
611       olsr_exit((char *)id, EXIT_FAILURE);
612     }
613   return ptr;
614 }
615
616
617 /**
618  *Wrapper for printf that prints to a specific
619  *debuglevel upper limit
620  *
621  */
622
623 int
624 olsr_printf(int loglevel, char *format, ...)
625 {
626   va_list arglist;
627
628   if((loglevel <= olsr_cnf->debug_level) && debug_handle)
629     {
630       va_start(arglist, format);
631       
632       vfprintf(debug_handle, format, arglist);
633       
634       va_end(arglist);
635     }
636
637
638   return 0;
639 }