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