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