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