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