Removed preprocessor warnings for release
[olsrd.git] / src / olsr.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of olsrd-unik.
6  *
7  * UniK olsrd is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * UniK olsrd is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsrd-unik; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "defs.h"
24 #include "olsr.h"
25 #include "link_set.h"
26 #include "two_hop_neighbor_table.h"
27 #include "tc_set.h"
28 #include "duplicate_set.h"
29 #include "mpr_selector_set.h"
30 #include "mid_set.h"
31 #include "mpr.h"
32 #include "scheduler.h"
33 #include "generate_msg.h"
34 #include "apm.h"
35
36 #include <stdarg.h>
37 #include <signal.h>
38
39
40 /**
41  *Checks if a timer has timed out.
42  */
43
44
45 /**
46  *Initiates a "timer", wich is a timeval structure,
47  *with the value given in time_value.
48  *@param time_value the value to initialize the timer with
49  *@param hold_timer the timer itself
50  *@return nada
51  */
52 inline void
53 olsr_init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
54
55   olsr_u16_t  time_value_sec;
56   olsr_u16_t  time_value_msec;
57
58   time_value_sec = time_value/1000;
59   time_value_msec = time_value-(time_value_sec*1000);
60
61   hold_timer->tv_sec = time_value_sec;
62   hold_timer->tv_usec = time_value_msec*1000;   
63 }
64
65
66
67
68
69 /**
70  *Generaties a timestamp a certain number of milliseconds
71  *into the future.
72  *
73  *@param time_value how many milliseconds from now
74  *@param hold_timer the timer itself
75  *@return nada
76  */
77 inline void
78 olsr_get_timestamp(olsr_u32_t delay, struct timeval *hold_timer)
79
80   hold_timer->tv_sec = now.tv_sec + delay / 1000;
81   hold_timer->tv_usec = now.tv_usec + (delay % 1000) * 1000;
82   
83   if (hold_timer->tv_usec > 1000000)
84     {
85       hold_timer->tv_sec++;
86       hold_timer->tv_usec -= 1000000;
87     }
88 }
89
90
91
92 /**
93  *Initialize the message sequence number as a random value
94  */
95 void
96 init_msg_seqno()
97 {
98   message_seqno = random() & 0xFFFF;
99 }
100
101 /**
102  * Get and increment the message sequence number
103  *
104  *@return the seqno
105  */
106 inline olsr_u16_t
107 get_msg_seqno()
108 {
109   return message_seqno++;
110 }
111
112
113 void
114 register_pcf(int (*f)(int, int, int))
115 {
116   struct pcf *new_pcf;
117
118   olsr_printf(1, "Registering pcf function\n");
119
120   new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
121
122   new_pcf->function = f;
123   new_pcf->next = pcf_list;
124   pcf_list = new_pcf;
125
126 }
127
128
129 /**
130  *Process changes in neighborhood or/and topology.
131  *Re-calculates the neighborhooh/topology if there
132  *are any updates - then calls the right functions to
133  *update the routing table.
134  *@return 0
135  */
136 inline void
137 olsr_process_changes()
138 {
139
140   struct pcf *tmp_pc_list;
141
142 #ifdef DEBUG
143   if(changes_neighborhood)
144     olsr_printf(3, "CHANGES IN NEIGHBORHOOD\n");
145   if(changes_topology)
146     olsr_printf(3, "CHANGES IN TOPOLOGY\n");
147   if(changes_hna)
148     olsr_printf(3, "CHANGES IN HNA\n");  
149 #endif
150
151   if(!changes_neighborhood &&
152      !changes_topology &&
153      !changes_hna)
154     return;
155
156   if(changes_neighborhood)
157     {
158       /* Calculate new mprs, HNA and routing table */
159       olsr_calculate_mpr();
160       olsr_calculate_routing_table();
161       olsr_calculate_hna_routes();
162
163       goto process_pcf;  
164     }
165   
166   if(changes_topology)
167     {
168       /* calculate the routing table and HNA */
169       olsr_calculate_routing_table();
170       olsr_calculate_hna_routes();
171
172       goto process_pcf;  
173     }
174
175   if(changes_hna)
176     {
177       /* Update HNA routes */
178       olsr_calculate_hna_routes();
179
180       goto process_pcf;
181     }
182   
183  process_pcf:
184
185   for(tmp_pc_list = pcf_list; 
186       tmp_pc_list != NULL;
187       tmp_pc_list = tmp_pc_list->next)
188     {
189       tmp_pc_list->function(changes_neighborhood,
190                             changes_topology,
191                             changes_hna);
192     }
193
194   changes_neighborhood = DOWN;
195   changes_topology = DOWN;
196   changes_hna = DOWN;
197
198
199   return;
200 }
201
202
203
204
205
206 /**
207  *Initialize all the tables used(neighbor,
208  *topology, MID,  HNA, MPR, dup).
209  *Also initalizes other variables
210  */
211 void
212 olsr_init_tables()
213 {
214   
215   changes_topology = DOWN;
216   changes_neighborhood = DOWN;
217   changes_hna = DOWN;
218
219   /* Initialize link set */
220   olsr_init_link_set();
221
222   /* Initialize duplicate table */
223   olsr_init_duplicate_table();
224
225   /* Initialize neighbor table */
226   olsr_init_neighbor_table();
227
228   /* Initialize routing table */
229   olsr_init_routing_table();
230
231   /* Initialize two hop table */
232   olsr_init_two_hop_table();
233
234   /* Initialize old route table */
235   olsr_init_old_table();
236
237   /* Initialize topology */
238   olsr_init_tc();
239
240   /* Initialize mpr selector table */
241   olsr_init_mprs_set();
242
243   /* Initialize MID set */
244   olsr_init_mid_set();
245
246   /* Initialize HNA set */
247   olsr_init_hna_set();
248
249   /* Initialize ProcessChanges list */
250   ptf_list = NULL;
251   
252 }
253
254
255
256
257
258
259 /**
260  *Check if a message is to be forwarded and forward
261  *it if necessary.
262  *
263  *@param m the OLSR message recieved
264  *@param originator the originator of this message
265  *@param seqno the seqno of the message
266  *
267  *@returns positive if forwarded
268  */
269 int
270 olsr_forward_message(union olsr_message *m, 
271                      union olsr_ip_addr *originator, 
272                      olsr_u16_t seqno,
273                      struct interface *in_if, 
274                      union olsr_ip_addr *from_addr)
275 {
276   union olsr_message *om;
277   union olsr_ip_addr *src;
278   struct neighbor_entry *neighbor;
279   int msgsize;
280
281
282   if(!olsr_check_dup_table_fwd(originator, seqno, &in_if->ip_addr))
283     {
284 #ifdef DEBUG
285       olsr_printf(3, "Message already forwarded!\n");
286 #endif
287       return 0;
288     }
289
290   /* Lookup sender address */
291   if(!(src = mid_lookup_main_addr(from_addr)))
292     src = from_addr;
293
294
295   if(NULL == (neighbor=olsr_lookup_neighbor_table(src)))
296     return 0;
297
298   if(neighbor->status != SYM)
299     return 0;
300
301   /* Update duplicate table interface */
302   olsr_update_dup_entry(originator, seqno, &in_if->ip_addr);
303
304   
305   /* Check MPR */
306   if(olsr_lookup_mprs_set(src) == NULL)
307     {
308 #ifdef DEBUG
309       olsr_printf(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(src));
310 #endif
311       return 0;
312     }
313
314
315   /* Treat TTL hopcnt */
316   if(ipversion == AF_INET)
317     {
318       /* IPv4 */
319       m->v4.hopcnt++;
320       m->v4.ttl--; 
321     }
322   else
323     {
324       /* IPv6 */
325       m->v6.hopcnt++;
326       m->v6.ttl--; 
327     }
328
329
330
331   /* Update dup forwarded */
332   olsr_set_dup_forward(originator, seqno);
333
334   /* Update packet data */
335
336
337   msgsize = ntohs(m->v4.olsr_msgsize);
338
339   if(fwdsize)
340     {
341       /*
342        * Check if message is to big to be piggybacked
343        */
344       if((fwdsize + msgsize) > maxmessagesize)
345         {
346           olsr_printf(1, "Forwardbuffer full(%d + %d) - flushing!\n", fwdsize, msgsize);
347
348           /* Send */
349           net_forward();
350
351           /* Buffer message */
352           buffer_forward(m);
353         }
354       else
355         {
356 #ifdef DEBUG
357           olsr_printf(3, "Piggybacking message - buffer: %d msg: %d\n", fwdsize, msgsize);
358 #endif
359           /* piggyback message to outputbuffer */
360           om =  (union olsr_message *)((char*)fwdmsg + fwdsize);
361
362           memcpy(om, m, msgsize);
363           fwdsize += msgsize;
364           /* Set messagesize  - same for IPv4 and IPv6 */
365           fwdmsg->v4.olsr_packlen = htons(fwdsize);
366         }
367     }
368
369   else
370     {
371       /* No forwarding pending */
372       buffer_forward(m);
373     }
374
375   return 1;
376
377 }
378
379
380
381 int
382 buffer_forward(union olsr_message *m)
383 {
384   float jitter;
385   struct timeval jittertimer;
386   int msgsize;
387
388   msgsize = ntohs(m->v4.olsr_msgsize);  
389       
390   /* Set timer */
391   jitter = (float) random()/RAND_MAX;
392   jitter *= max_jitter;
393
394   olsr_init_timer((olsr_u32_t) (jitter*1000), &jittertimer);
395   
396   timeradd(&now, &jittertimer, &fwdtimer);
397   
398   /* Add header and message */
399   fwdsize = sizeof(olsr_u16_t) + sizeof(olsr_u16_t) + msgsize;
400   
401   /* Set messagesize  - same for IPv4 and IPv6 */
402   fwdmsg->v4.olsr_packlen = htons(fwdsize);
403   
404 #ifdef DEBUG
405   olsr_printf(3, "Adding jitter for forwarding: %f size: %d\n", jitter, fwdsize);
406 #endif
407
408   /* Copy message to outputbuffer */
409   memcpy(fwdmsg->v4.olsr_msg, m, msgsize);
410
411   return 1;
412 }
413
414
415
416 void
417 olsr_init_willingness()
418 {
419   if(!willingness_set)
420     olsr_register_scheduler_event(&olsr_update_willingness, will_int, will_int, NULL);
421 }
422
423 void
424 olsr_update_willingness()
425 {
426   int tmp_will;
427
428   tmp_will = my_willingness;
429
430   /* Re-calculate willingness */
431   my_willingness = olsr_calculate_willingness();
432
433   if(tmp_will != my_willingness)
434     {
435       olsr_printf(1, "Local willingness updated: old %d new %d\n", tmp_will, my_willingness);
436     }
437 }
438
439
440 /**
441  *Calculate this nodes willingness to act as a MPR
442  *based on either a fixed value or the power status
443  *of the node using APM
444  *
445  *@return a 8bit value from 0-7 representing the willingness
446  */
447
448 olsr_u8_t
449 olsr_calculate_willingness()
450 {
451   struct olsr_apm_info ainfo;
452
453   /* If fixed willingness */
454   if(willingness_set)
455     return my_willingness;
456
457
458   if(apm_read(&ainfo) < 0)
459     return WILL_DEFAULT;
460
461   apm_printinfo(&ainfo);
462
463   /* If AC powered */
464   if(ainfo.ac_line_status)
465     return 6;
466
467   /* If battery powered 
468    *
469    * juice > 78% will: 3
470    * 78% > juice > 26% will: 2
471    * 26% > juice will: 1
472    */
473   return (ainfo.battery_percentage / 26);
474 }
475
476
477
478 /**
479  *Termination function to be called whenever a error occures
480  *that requires the daemon to terminate
481  *
482  *@param msg the message to write to the syslog and possibly stdout
483  */
484
485 void
486 olsr_exit(const char *msg, int val)
487 {
488   olsr_printf(1, "OLSR EXIT: %s\n", msg);
489   syslog(LOG_ERR, "olsrd exit: %s\n", msg);
490   fflush(stdout);
491   exit_value = val;
492
493   raise(SIGTERM);
494 }
495
496
497 /**
498  *Wrapper for malloc(3) that does error-checking
499  *
500  *@param size the number of bytes to allocalte
501  *@param caller a string identifying the caller for
502  *use in error messaging
503  *
504  *@return a void pointer to the memory allocated
505  */
506 void *
507 olsr_malloc(size_t size, const char *id)
508 {
509   void *ptr;
510
511   if((ptr = malloc(size)) == 0) 
512     {
513       olsr_printf(1, "OUT OF MEMORY: %s\n", strerror(errno));
514       syslog(LOG_ERR, "olsrd: out of memory!: %m\n");
515       olsr_exit((char *)id, EXIT_FAILURE);
516     }
517   return ptr;
518 }
519
520
521 /**
522  *Wrapper for printf that prints to a specific
523  *debuglevel upper limit
524  *
525  */
526
527 inline int
528 olsr_printf(int loglevel, char *format, ...)
529 {
530   va_list arglist;
531
532   va_start(arglist, format);
533
534   if(loglevel <= debug_level)
535     {
536       vprintf(format, arglist);
537     }
538
539   va_end(arglist);
540
541   return 0;
542 }