f7c53aa378c5aeaaa3d0b6773f34a7c347fcd652
[olsrd.git] / src / packet.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: packet.c,v 1.21 2006/01/07 08:16:20 kattemat Exp $
40  */
41
42
43 #include "defs.h"
44 #include "link_set.h"
45 #include "mpr_selector_set.h"
46 #include "mpr.h"
47 #include "olsr.h"
48 #include "neighbor_table.h"
49 #include "build_msg.h"
50
51 static olsr_bool sending_tc = OLSR_FALSE;
52
53 /**
54  *Free the memory allocated for a HELLO packet.
55  *
56  *@param message the pointer to the packet to erase
57  *
58  *@return nada
59  */
60 void
61 olsr_free_hello_packet(struct hello_message *message)
62 {
63   struct hello_neighbor *nb, *prev_nb;
64
65   if(!message)
66     return;
67   
68   nb = message->neighbors;
69   
70   while (nb)
71     {
72       prev_nb = nb;
73       nb = nb->next;
74       free(prev_nb);
75     }
76 }
77
78 /**
79  *Build an internal HELLO package for this
80  *node. This MUST be done for each interface.
81  *
82  *@param message the hello_message struct to fill with info
83  *@param outif the interface to send the message on - messages
84  *are created individually for each interface!
85  *@return 0
86  */
87 int
88 olsr_build_hello_packet(struct hello_message *message, struct interface *outif)
89 {
90   struct hello_neighbor   *message_neighbor, *tmp_neigh;
91   struct link_entry       *links;
92   struct neighbor_entry   *neighbor;
93   olsr_u16_t              index;
94   int                     link;
95
96 #ifdef DEBUG
97   OLSR_PRINTF(3, "\tBuilding HELLO on interface %d\n", outif->if_nr)
98 #endif
99
100   message->neighbors=NULL;
101   message->packet_seq_number=0;
102   
103   //message->mpr_seq_number=neighbortable.neighbor_mpr_seq;
104
105   /* Set willingness */
106
107   message->willingness = olsr_cnf->willingness;
108 #ifdef DEBUG
109   OLSR_PRINTF(3, "Willingness: %d\n", olsr_cnf->willingness)
110 #endif
111
112   /* Set TTL */
113
114   message->ttl = 1;  
115   COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
116
117 #ifdef DEBUG
118       OLSR_PRINTF(5, "On link:\n")
119 #endif
120
121   /* Get the links of this interface */
122   links = get_link_set();
123
124   while(links != NULL)
125     {      
126       
127       link = lookup_link_status(links);
128       /* Update the status */
129       
130       /* Check if this link tuple is registered on the outgoing interface */
131       if(!COMP_IP(&links->local_iface_addr, &outif->ip_addr))
132         {
133           links = links->next;
134           continue;
135         }
136
137       message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO");
138       
139
140       /* Find the link status */
141       message_neighbor->link = link;
142
143       /*
144        * Calculate neighbor status
145        */
146       /* 
147        * 2.1  If the main address, corresponding to
148        *      L_neighbor_iface_addr, is included in the MPR set:
149        *
150        *            Neighbor Type = MPR_NEIGH
151        */
152       if(links->neighbor->is_mpr)
153         {
154           message_neighbor->status = MPR_NEIGH;
155         }
156       /*
157        *  2.2  Otherwise, if the main address, corresponding to
158        *       L_neighbor_iface_addr, is included in the neighbor set:
159        */
160       
161       /* NOTE:
162        * It is garanteed to be included when come this far
163        * due to the extentions made in the link sensing
164        * regarding main addresses.
165        */
166       else
167         {
168           /*
169            *   2.2.1
170            *        if N_status == SYM
171            *
172            *             Neighbor Type = SYM_NEIGH
173            */
174           if(links->neighbor->status == SYM)
175             {
176               message_neighbor->status = SYM_NEIGH;
177             }
178           /*
179            *   2.2.2
180            *        Otherwise, if N_status == NOT_SYM
181            *             Neighbor Type = NOT_NEIGH
182            */
183           else
184             if(links->neighbor->status == NOT_SYM)
185               {
186                 message_neighbor->status = NOT_NEIGH;
187               }
188         }
189   
190       /* Set the remote interface address */
191       COPY_IP(&message_neighbor->address, &links->neighbor_iface_addr);
192       
193       /* Set the main address */
194       COPY_IP(&message_neighbor->main_address, &links->neighbor->neighbor_main_addr);
195 #ifdef DEBUG
196       OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address))
197       OLSR_PRINTF(5, " status %d\n", message_neighbor->status)
198 #endif
199       message_neighbor->next=message->neighbors;
200       message->neighbors=message_neighbor;          
201       
202       links = links->next;
203     }
204   
205   /* Add the links */
206
207
208
209 #ifdef DEBUG
210       OLSR_PRINTF(5, "Not on link:\n")
211 #endif
212
213   /* Add the rest of the neighbors if running on multiple interfaces */
214   
215   if(ifnet != NULL && ifnet->int_next != NULL)
216     for(index=0;index<HASHSIZE;index++)
217       {       
218         for(neighbor = neighbortable[index].next;
219             neighbor != &neighbortable[index];
220             neighbor=neighbor->next)
221           {
222             /* Check that the neighbor is not added yet */
223             tmp_neigh = message->neighbors;
224             //printf("Checking that the neighbor is not yet added\n");
225             while(tmp_neigh)
226               {
227                 if(COMP_IP(&tmp_neigh->main_address, &neighbor->neighbor_main_addr))
228                   {
229                     //printf("Not adding duplicate neighbor %s\n", olsr_ip_to_string(&neighbor->neighbor_main_addr));
230                     break;
231                   }
232                 tmp_neigh = tmp_neigh->next;
233               }
234
235             if(tmp_neigh)
236               continue;
237             
238             message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO 2");
239             
240             message_neighbor->link = UNSPEC_LINK;
241             
242             /*
243              * Calculate neighbor status
244              */
245             /* 
246              * 2.1  If the main address, corresponding to
247              *      L_neighbor_iface_addr, is included in the MPR set:
248              *
249              *            Neighbor Type = MPR_NEIGH
250              */
251             if(neighbor->is_mpr)
252               {
253                 message_neighbor->status = MPR_NEIGH;
254               }
255             /*
256              *  2.2  Otherwise, if the main address, corresponding to
257              *       L_neighbor_iface_addr, is included in the neighbor set:
258              */
259             
260             /* NOTE:
261              * It is garanteed to be included when come this far
262              * due to the extentions made in the link sensing
263              * regarding main addresses.
264              */
265             else
266               {
267                 /*
268                  *   2.2.1
269                  *        if N_status == SYM
270                  *
271                  *             Neighbor Type = SYM_NEIGH
272                  */
273                 if(neighbor->status == SYM)
274                   {
275                     message_neighbor->status = SYM_NEIGH;
276                   }
277                 /*
278                  *   2.2.2
279                  *        Otherwise, if N_status == NOT_SYM
280                  *             Neighbor Type = NOT_NEIGH
281                  */
282                 else
283                   if(neighbor->status == NOT_SYM)
284                     {
285                       message_neighbor->status = NOT_NEIGH;                   
286                     }
287               }
288             
289
290             COPY_IP(&message_neighbor->address, &neighbor->neighbor_main_addr);
291
292             COPY_IP(&message_neighbor->main_address, &neighbor->neighbor_main_addr);
293 #ifdef DEBUG
294             OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address))
295             OLSR_PRINTF(5, " status  %d\n", message_neighbor->status)
296 #endif
297             message_neighbor->next=message->neighbors;
298             message->neighbors=message_neighbor;            
299           }
300       }
301   
302
303   return 0;
304 }
305
306
307 /**
308  *Free the memory allocated for a TC packet.
309  *
310  *@param message the pointer to the packet to erase
311  *
312  *@return nada
313  */
314 void 
315 olsr_free_tc_packet(struct tc_message *message)
316 {
317   struct tc_mpr_addr *mprs, *prev_mprs;
318
319   if(!message)
320     return;
321
322   mprs = message->multipoint_relay_selector_address;
323   
324   while (mprs)
325     {
326       prev_mprs = mprs;
327       mprs = mprs->next;
328       free(prev_mprs);
329     }
330 }
331
332 /**
333  *Build an internal TC package for this
334  *node.
335  *
336  *@param message the tc_message struct to fill with info
337  *@return 0
338  */
339 int
340 olsr_build_tc_packet(struct tc_message *message)
341 {
342   struct tc_mpr_addr        *message_mpr;
343   //struct mpr_selector       *mprs;
344   olsr_u8_t              index;
345   struct neighbor_entry  *entry;
346   //struct mpr_selector_hash  *mprs_hash;
347   //olsr_u16_t          index;
348   olsr_bool entry_added = OLSR_FALSE;
349
350   message->multipoint_relay_selector_address=NULL;
351   message->packet_seq_number=0;
352  
353   message->hop_count = 0;
354   message->ttl = MAX_TTL;
355   message->ansn = get_local_ansn();
356
357   COPY_IP(&message->originator, &olsr_cnf->main_addr);
358   COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
359   
360
361   /* Loop trough all neighbors */  
362   for(index=0;index<HASHSIZE;index++)
363     {
364       for(entry = neighbortable[index].next;
365           entry != &neighbortable[index];
366           entry = entry->next)
367         {
368           if(entry->status != SYM)
369             continue;
370
371           switch(olsr_cnf->tc_redundancy)
372             {
373             case(2):
374               {
375                 /* 2 = Add all neighbors */
376                 //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
377                 message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC");
378                 
379                 COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
380                 message_mpr->next = message->multipoint_relay_selector_address;
381                 message->multipoint_relay_selector_address = message_mpr;
382                 entry_added = OLSR_TRUE;
383                 
384                 break;
385               }
386             case(1):
387               {
388                 /* 1 = Add all MPR selectors and selected MPRs */
389                 if((entry->is_mpr) ||
390                    (olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL))
391                   {
392                     //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
393                     message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 2");
394                     
395                     COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
396                     message_mpr->next = message->multipoint_relay_selector_address;
397                     message->multipoint_relay_selector_address = message_mpr;
398                     entry_added = OLSR_TRUE;
399                   }
400                 break;
401               }
402             default:
403               {
404                 /* 0 = Add only MPR selectors(default) */
405                 if(olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL)
406                   {
407                     //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
408                     message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 3");
409                     
410                     COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
411                     message_mpr->next = message->multipoint_relay_selector_address;
412                     message->multipoint_relay_selector_address = message_mpr;
413                     entry_added = OLSR_TRUE;
414                   }
415                 break;
416               }         
417           
418             } /* Switch */
419         } /* For */
420     } /* For index */
421
422   if(entry_added)
423     {
424       sending_tc = OLSR_TRUE;
425     }
426   else
427     {
428       if(sending_tc)
429         {
430           /* Send empty TC */
431           OLSR_PRINTF(3, "No more MPR selectors - will send empty TCs\n")
432           set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime*3)*1000));
433
434           sending_tc = OLSR_FALSE;
435         }
436     }
437
438
439   return 0;
440 }
441
442
443 /**
444  *Free the memory allocated for a HNA packet.
445  *
446  *@param message the pointer to the packet to erase
447  *
448  *@return nada
449  */
450
451 void
452 olsr_free_hna_packet(struct hna_message *message)
453 {
454   struct hna_net_addr  *hna_tmp, *hna_tmp2;
455
456   hna_tmp = message->hna_net;
457
458   while(hna_tmp)
459     {
460       hna_tmp2 = hna_tmp;
461       hna_tmp = hna_tmp->next;
462       free(hna_tmp2);
463     }
464 }
465
466
467
468 /**
469  *Free the memory allocated for a MID packet.
470  *
471  *@param message the pointer to the packet to erase
472  *
473  *@return nada
474  */
475
476 void
477 olsr_free_mid_packet(struct mid_message *message)
478 {
479   struct mid_alias *tmp_adr, *tmp_adr2;
480
481   tmp_adr = message->mid_addr;
482
483   while(tmp_adr)
484     {
485       tmp_adr2 = tmp_adr;
486       tmp_adr = tmp_adr->next;
487       free(tmp_adr2);
488     }
489 }