Replaced unik-olsrd with olsr.org
[olsrd.git] / src / process_package.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of olsr.org.
6  *
7  * olsr.org 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  * olsr.org 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 olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23
24 #include "defs.h"
25 #include "process_package.h"
26 #include "hysteresis.h"
27 #include "two_hop_neighbor_table.h"
28 #include "tc_set.h"
29 #include "mpr_selector_set.h"
30 #include "mid_set.h"
31 #include "olsr.h"
32 #include "parser.h"
33 #include "duplicate_set.h"
34 #include "rebuild_packet.h"
35
36
37 #ifdef linux 
38 #include "linux/tunnel.h"
39 #elif defined WIN32
40 #include "win32/tunnel.h"
41 #endif
42
43
44 /**
45  *Initializing the parser functions we are using
46  */
47 void
48 olsr_init_package_process()
49 {
50
51   olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
52   olsr_parser_add_function(&olsr_process_received_tc, TC_MESSAGE, 1);
53   olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
54   olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
55 }
56
57 /**
58  *Processes a received HELLO message. 
59  *
60  *@param m the incoming OLSR message
61  *@return 0 on sucess
62  */
63
64 void
65 olsr_process_received_hello(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
66 {
67   struct link_entry         *link;
68   struct neighbor_entry     *neighbor;
69   struct hello_message      message;
70
71   hello_chgestruct(&message, m);
72
73   /*
74   if(COMP_IP(&message.source_addr, &main_addr))
75     {
76       olsr_destroy_hello_message(&message);
77       return;
78     }
79   */
80
81   /*
82    * Update link status
83    */
84   link = update_link_entry(&in_if->ip_addr, from_addr, &message, in_if);
85
86   neighbor = link->neighbor;
87
88   /*
89    * Hysteresis
90    */
91   if(use_hysteresis)
92     {
93       /* Update HELLO timeout */
94       //printf("MESSAGE HTIME: %f\n", message.htime);
95       olsr_update_hysteresis_hello(link, message.htime);
96     }
97
98   /* Check if we are chosen as MPR */
99   if(olsr_lookup_mpr_status(&message, in_if))
100     /* source_addr is always the main addr of a node! */
101     olsr_update_mprs_set(&message.source_addr, (float)message.vtime);
102
103
104
105   /* Check willingness */
106   if(neighbor->willingness != message.willingness)
107     {
108       olsr_printf(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
109                   olsr_ip_to_string(&neighbor->neighbor_main_addr),
110                   neighbor->willingness,
111                   message.willingness);
112       /*
113        *If willingness changed - recalculate
114        */
115       neighbor->willingness = message.willingness;
116       changes_neighborhood = UP;
117       changes_topology = UP;
118     }
119
120
121   /* Don't register neighbors of neighbors that announces WILL_NEVER */
122   if(neighbor->willingness != WILL_NEVER)
123     olsr_process_message_neighbors(neighbor, &message);
124
125   /* Process changes immedeatly in case of MPR updates */
126   olsr_process_changes();
127
128   olsr_destroy_hello_message(&message);
129
130   return;
131 }
132
133
134
135
136
137 /**
138  *Process a received TopologyControl message
139  *
140  *
141  *@param m the incoming OLSR message
142  *@return 0 on success
143  */
144 void
145 olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
146
147   struct tc_mpr_addr              *mpr;
148   struct tc_entry                 *tc_last;
149   struct tc_message               message;
150
151   tc_chgestruct(&message, m, from_addr);
152
153   /*    
154   if(COMP_IP(&message.originator, &main_addr))
155     { 
156       goto forward;
157     }
158   */
159
160   if(!olsr_check_dup_table_proc(&message.originator, 
161                                 message.packet_seq_number))
162     {
163       goto forward;
164     }
165
166   olsr_printf(3, "Processing TC from %s\n", olsr_ip_to_string(&message.originator));
167
168
169
170
171
172   /*
173    *      If the sender interface (NB: not originator) of this message
174    *      is not in the symmetric 1-hop neighborhood of this node, the
175    *      message MUST be discarded.
176    */
177
178   if(check_neighbor_link(from_addr) != SYM_LINK)
179     {
180       olsr_printf(2, "Received TC from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
181       olsr_destroy_tc_message(&message);
182       return;
183     }
184
185
186   if(debug_level > 2)
187     {
188       mpr = message.multipoint_relay_selector_address;
189       olsr_printf(3, "mpr_selector_list:[");      
190       while(mpr!=NULL)
191         {
192           olsr_printf(3, "%s:", olsr_ip_to_string(&mpr->address));
193           mpr=mpr->next;
194         }
195       olsr_printf(3, "]\n");
196     }
197
198
199
200   tc_last = olsr_lookup_tc_entry(&message.originator);
201   
202  
203   if(tc_last != NULL)
204     {
205       /* Update entry */
206
207       /* Delete destinations with lower ANSN */
208       if(olsr_tc_delete_mprs(tc_last, &message))
209         changes_topology=UP; 
210
211       /* Update destinations */
212       if(olsr_tc_update_mprs(tc_last, &message))
213         changes_topology = UP;
214
215       /* Delete possible empty TC entry */
216       if(changes_topology == UP)
217         olsr_tc_delete_entry_if_empty(tc_last);
218
219     }
220   else
221     {
222       /*if message is empty then skip it */
223       if(message.multipoint_relay_selector_address != NULL)
224         {
225           /* New entry */
226           tc_last = olsr_add_tc_entry(&message.originator);      
227           
228           /* Update destinations */
229           olsr_tc_update_mprs(tc_last, &message);
230           
231           changes_topology = UP;
232         }
233       else
234         {
235           olsr_printf(3, "Dropping empty TC from %s\n", olsr_ip_to_string(&message.originator)); 
236         }
237     }
238
239   /* Process changes */
240   //olsr_process_changes();
241
242  forward:
243
244   olsr_forward_message(m, 
245                        &message.originator, 
246                        message.packet_seq_number, 
247                        in_if,
248                        from_addr);
249   olsr_destroy_tc_message(&message);
250
251   return;
252 }
253
254
255
256
257
258
259 /**
260  *Process a received(and parsed) MID message
261  *For every address check if there is a topology node
262  *registered with it and update its addresses.
263  *
264  *@param m the OLSR message received.
265  *@return 1 on success
266  */
267
268 void
269 olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
270 {
271   struct mid_alias *tmp_adr;
272   struct mid_message message;
273
274
275   mid_chgestruct(&message, m);
276
277   /*
278   if(COMP_IP(&message.mid_origaddr, &main_addr))
279     {
280       goto forward;  
281     }
282   */
283
284   if(!olsr_check_dup_table_proc(&message.mid_origaddr, 
285                                 message.mid_seqno))
286     {
287       goto forward;
288     }
289   
290   olsr_printf(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr));
291
292   tmp_adr = message.mid_addr;
293
294
295   /*
296    *      If the sender interface (NB: not originator) of this message
297    *      is not in the symmetric 1-hop neighborhood of this node, the
298    *      message MUST be discarded.
299    */
300
301   if(check_neighbor_link(from_addr) != SYM_LINK)
302     {
303       olsr_printf(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
304       olsr_destroy_mid_message(&message);
305       return;
306     }
307
308
309
310   /* Update the timeout of the MID */
311   olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
312
313   while(tmp_adr)
314     {
315       if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
316         {
317           olsr_printf(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr));
318           olsr_printf(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr));
319           insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
320         }
321
322
323       tmp_adr = tmp_adr->next;
324     } 
325   
326   /*Update topology if neccesary*/
327   //olsr_process_changes();
328
329  forward:
330   
331   olsr_forward_message(m, 
332                        &message.mid_origaddr, 
333                        message.mid_seqno, 
334                        in_if,
335                        from_addr);
336   olsr_destroy_mid_message(&message);
337
338   return;
339 }
340
341
342
343
344
345 /**
346  *Process incoming HNA message.
347  *Forwards the message if that is to be done.
348  *
349  *@param m the incoming OLSR message
350  *the OLSR message.
351  *@return 1 on success
352  */
353
354 void
355 olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
356 {
357   struct hna_net_addr  *hna_tmp;
358   struct  hna_message message;
359
360   //printf("Processing HNA\n");
361
362   hna_chgestruct(&message, m);
363   
364
365   /* Process message */   
366   /*
367   if(COMP_IP(&message.originator, &main_addr)) 
368     {
369       goto forward;
370     }
371   */
372
373   if(!olsr_check_dup_table_proc(&message.originator, 
374                                 message.packet_seq_number))
375     {
376       goto forward;
377     }
378
379
380
381
382   hna_tmp = message.hna_net;
383
384
385
386   /*
387    *      If the sender interface (NB: not originator) of this message
388    *      is not in the symmetric 1-hop neighborhood of this node, the
389    *      message MUST be discarded.
390    */
391
392
393   if(check_neighbor_link(from_addr) != SYM_LINK)
394     {
395       olsr_printf(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
396       olsr_destroy_hna_message(&message);
397       return;
398     }
399
400   while(hna_tmp)
401     {
402       
403       /*
404        * Set up tunnel to Internet gateway
405        */
406       if((use_tunnel) && (ipversion == AF_INET) && (hna_tmp->net.v4 == 0))
407         {
408           if(inet_tnl_added || gw_tunnel)
409             {
410               hna_tmp = hna_tmp->next;
411               continue;
412             }
413           
414           olsr_printf(1, "Internet gateway discovered! Setting up tunnel:\n");
415
416           /* Set up tunnel endpoint */
417           set_up_source_tnl(&main_addr, &message.originator, in_if->if_index); 
418         }
419       else
420         {
421           olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime); 
422         }
423       
424       hna_tmp = hna_tmp->next;
425     }
426   
427   /*Update topology if neccesary*/
428   //olsr_process_changes();
429
430  forward:
431   olsr_forward_message(m, 
432                        &message.originator, 
433                        message.packet_seq_number, 
434                        in_if,
435                        from_addr);
436   olsr_destroy_hna_message(&message);
437
438   return;
439 }
440
441
442
443
444
445
446
447 /**
448  *Processes an list of neighbors from an incoming HELLO message.
449  *@param neighbor the neighbor who sendt the message.
450  *@param message the HELLO message
451  *@return nada
452  */
453 void
454 olsr_process_message_neighbors(struct neighbor_entry *neighbor,struct hello_message *message)
455 {
456   struct hello_neighbor        *message_neighbors;
457   struct neighbor_2_list_entry *two_hop_neighbor_yet;
458   struct neighbor_2_entry      *two_hop_neighbor;
459   union olsr_ip_addr           *neigh_addr;
460   
461
462   for(message_neighbors=message->neighbors;
463       message_neighbors!=NULL;
464       message_neighbors=message_neighbors->next)
465     {
466       
467       /*
468        *check all interfaces
469        *so that we don't add ourselves to the
470        *2 hop list
471        *IMPORTANT!
472        */
473       if(if_ifwithaddr(&message_neighbors->address) != NULL)
474          continue;
475
476       /* Get the main address */
477       if((neigh_addr = mid_lookup_main_addr(&message_neighbors->address)) != NULL)
478         COPY_IP(&message_neighbors->address, neigh_addr);
479       
480
481       if(((message_neighbors->status==SYM_NEIGH) || (message_neighbors->status==MPR_NEIGH)))
482         {
483           //printf("\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address));
484           
485           //printf("\tMain addr: %s\n", olsr_ip_to_string(neigh_addr));
486           
487           if((two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor, &message_neighbors->address))!=NULL)
488             {
489               
490               /* Updating the holding time for this neighbor */
491               olsr_get_timestamp((olsr_u32_t) message->vtime*1000, &two_hop_neighbor_yet->neighbor_2_timer);
492
493             }
494           else
495             {
496               
497               if((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&message_neighbors->address)) == NULL)
498                 {
499                  
500                   //printf("Adding 2 hop neighbor %s\n\n", olsr_ip_to_string(&message_neighbors->address)); 
501                   changes_neighborhood=UP;
502                   changes_topology=UP;
503                   two_hop_neighbor = olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");
504                   
505                   two_hop_neighbor->neighbor_2_nblist.next = &two_hop_neighbor->neighbor_2_nblist;
506                   two_hop_neighbor->neighbor_2_nblist.prev = &two_hop_neighbor->neighbor_2_nblist;
507                   two_hop_neighbor->neighbor_2_pointer=0;
508                   
509                   COPY_IP(&two_hop_neighbor->neighbor_2_addr,&message_neighbors->address);
510                   olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
511                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor, (float)message->vtime);
512                 }
513               else
514                 {
515                   
516                   /*
517                     linking to this two_hop_neighbor entry
518                   */    
519                   changes_neighborhood=UP;
520                   changes_topology=UP;
521                   
522                   olsr_linking_this_2_entries(neighbor, two_hop_neighbor, (float)message->vtime); 
523                 }
524             }
525         }
526       
527     }
528
529 }
530
531
532
533
534
535
536
537
538 /**
539  *Links a one-hop neighbor with a 2-hop neighbor.
540  *
541  *@param neighbor the 1-hop neighbor
542  *@param two_hop_neighbor the 2-hop neighbor
543  *@return nada
544  */
545 void
546 olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
547 {
548   struct neighbor_list_entry    *list_of_1_neighbors;
549   struct neighbor_2_list_entry  *list_of_2_neighbors;
550
551   list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
552
553   list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
554
555   list_of_1_neighbors->neighbor = neighbor;
556
557   /* Queue */
558   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
559   list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
560   two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
561   list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
562
563
564   list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
565   
566   olsr_get_timestamp((olsr_u32_t) vtime*1000, &list_of_2_neighbors->neighbor_2_timer);
567
568   /* Queue */
569   neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
570   list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
571   neighbor->neighbor_2_list.next = list_of_2_neighbors;
572   list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
573   
574   /*increment the pointer counter*/
575   two_hop_neighbor->neighbor_2_pointer++;
576 }
577
578
579
580
581
582
583 /**
584  *Check if a hello message states this node as a MPR.
585  *
586  *@param message the message to check
587  *@param n_link the buffer to put the link status in
588  *@param n_status the buffer to put the status in
589  *
590  *@return 1 if we are selected as MPR 0 if not
591  */
592 int
593 olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
594 {
595   
596   struct hello_neighbor  *neighbors;
597
598   neighbors=message->neighbors;
599   
600   while(neighbors!=NULL)
601     {  
602       //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
603       //printf("against %s\n",olsr_ip_to_string(&main_addr));
604
605
606     if(ipversion == AF_INET)
607       { 
608         /* IPv4 */  
609         if(COMP_IP(&neighbors->address, &in_if->ip_addr))
610           {
611             //printf("ok");
612             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
613               return 1;
614             
615             return 0;
616           }
617       }
618     else
619       { 
620         /* IPv6 */  
621         if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
622           {
623             //printf("ok");
624             if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
625               return 1;
626             
627             return 0;
628           }
629       }
630  
631       neighbors = neighbors->next; 
632     }
633
634   /* Not found */
635   return 0;
636 }
637