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