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