* fixed compile bugs if DEBUG is enabled
[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.24 2007/10/20 12:59:08 bernd67 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   int                     idx;
94
95 #ifdef DEBUG
96   OLSR_PRINTF(3, "\tBuilding HELLO on interface %d\n", outif->int_name);
97 #endif
98
99   message->neighbors=NULL;
100   message->packet_seq_number=0;
101   
102   //message->mpr_seq_number=neighbortable.neighbor_mpr_seq;
103
104   /* Set willingness */
105
106   message->willingness = olsr_cnf->willingness;
107 #ifdef DEBUG
108   OLSR_PRINTF(3, "Willingness: %d\n", olsr_cnf->willingness);
109 #endif
110
111   /* Set TTL */
112
113   message->ttl = 1;  
114   COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
115
116 #ifdef DEBUG
117   OLSR_PRINTF(5, "On link:\n");
118 #endif
119
120   /* Get the links of this interface */
121   links = get_link_set();
122
123   while(links != NULL)
124     {      
125       int lnk = lookup_link_status(links);
126       /* Update the status */
127       
128       /* Check if this link tuple is registered on the outgoing interface */
129       if(!COMP_IP(&links->local_iface_addr, &outif->ip_addr))
130         {
131           links = links->next;
132           continue;
133         }
134
135       message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO");
136       
137
138       /* Find the link status */
139       message_neighbor->link = lnk;
140
141       /*
142        * Calculate neighbor status
143        */
144       /* 
145        * 2.1  If the main address, corresponding to
146        *      L_neighbor_iface_addr, is included in the MPR set:
147        *
148        *            Neighbor Type = MPR_NEIGH
149        */
150       if(links->neighbor->is_mpr)
151         {
152           message_neighbor->status = MPR_NEIGH;
153         }
154       /*
155        *  2.2  Otherwise, if the main address, corresponding to
156        *       L_neighbor_iface_addr, is included in the neighbor set:
157        */
158       
159       /* NOTE:
160        * It is garanteed to be included when come this far
161        * due to the extentions made in the link sensing
162        * regarding main addresses.
163        */
164       else
165         {
166           /*
167            *   2.2.1
168            *        if N_status == SYM
169            *
170            *             Neighbor Type = SYM_NEIGH
171            */
172           if(links->neighbor->status == SYM)
173             {
174               message_neighbor->status = SYM_NEIGH;
175             }
176           /*
177            *   2.2.2
178            *        Otherwise, if N_status == NOT_SYM
179            *             Neighbor Type = NOT_NEIGH
180            */
181           else
182             if(links->neighbor->status == NOT_SYM)
183               {
184                 message_neighbor->status = NOT_NEIGH;
185               }
186         }
187   
188       /* Set the remote interface address */
189       COPY_IP(&message_neighbor->address, &links->neighbor_iface_addr);
190       
191       /* Set the main address */
192       COPY_IP(&message_neighbor->main_address, &links->neighbor->neighbor_main_addr);
193 #ifdef DEBUG
194       OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address));
195       OLSR_PRINTF(5, " status %d\n", message_neighbor->status);
196 #endif
197       message_neighbor->next=message->neighbors;
198       message->neighbors=message_neighbor;          
199       
200       links = links->next;
201     }
202   
203   /* Add the links */
204
205
206
207 #ifdef DEBUG
208     OLSR_PRINTF(5, "Not on link:\n");
209 #endif
210
211   /* Add the rest of the neighbors if running on multiple interfaces */
212   
213   if(ifnet != NULL && ifnet->int_next != NULL)
214     for(idx=0;idx<HASHSIZE;idx++)
215       {       
216         for(neighbor = neighbortable[idx].next;
217             neighbor != &neighbortable[idx];
218             neighbor=neighbor->next)
219           {
220             /* Check that the neighbor is not added yet */
221             tmp_neigh = message->neighbors;
222             //printf("Checking that the neighbor is not yet added\n");
223             while(tmp_neigh)
224               {
225                 if(COMP_IP(&tmp_neigh->main_address, &neighbor->neighbor_main_addr))
226                   {
227                     //printf("Not adding duplicate neighbor %s\n", olsr_ip_to_string(&neighbor->neighbor_main_addr));
228                     break;
229                   }
230                 tmp_neigh = tmp_neigh->next;
231               }
232
233             if(tmp_neigh)
234               continue;
235             
236             message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO 2");
237             
238             message_neighbor->link = UNSPEC_LINK;
239             
240             /*
241              * Calculate neighbor status
242              */
243             /* 
244              * 2.1  If the main address, corresponding to
245              *      L_neighbor_iface_addr, is included in the MPR set:
246              *
247              *            Neighbor Type = MPR_NEIGH
248              */
249             if(neighbor->is_mpr)
250               {
251                 message_neighbor->status = MPR_NEIGH;
252               }
253             /*
254              *  2.2  Otherwise, if the main address, corresponding to
255              *       L_neighbor_iface_addr, is included in the neighbor set:
256              */
257             
258             /* NOTE:
259              * It is garanteed to be included when come this far
260              * due to the extentions made in the link sensing
261              * regarding main addresses.
262              */
263             else
264               {
265                 /*
266                  *   2.2.1
267                  *        if N_status == SYM
268                  *
269                  *             Neighbor Type = SYM_NEIGH
270                  */
271                 if(neighbor->status == SYM)
272                   {
273                     message_neighbor->status = SYM_NEIGH;
274                   }
275                 /*
276                  *   2.2.2
277                  *        Otherwise, if N_status == NOT_SYM
278                  *             Neighbor Type = NOT_NEIGH
279                  */
280                 else
281                   if(neighbor->status == NOT_SYM)
282                     {
283                       message_neighbor->status = NOT_NEIGH;                   
284                     }
285               }
286             
287
288             COPY_IP(&message_neighbor->address, &neighbor->neighbor_main_addr);
289
290             COPY_IP(&message_neighbor->main_address, &neighbor->neighbor_main_addr);
291 #ifdef DEBUG
292             OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address));
293             OLSR_PRINTF(5, " status  %d\n", message_neighbor->status);
294 #endif
295             message_neighbor->next=message->neighbors;
296             message->neighbors=message_neighbor;            
297           }
298       }
299   
300
301   return 0;
302 }
303
304
305 /**
306  *Free the memory allocated for a TC packet.
307  *
308  *@param message the pointer to the packet to erase
309  *
310  *@return nada
311  */
312 void 
313 olsr_free_tc_packet(struct tc_message *message)
314 {
315   struct tc_mpr_addr *mprs, *prev_mprs;
316
317   if(!message)
318     return;
319
320   mprs = message->multipoint_relay_selector_address;
321   
322   while (mprs)
323     {
324       prev_mprs = mprs;
325       mprs = mprs->next;
326       free(prev_mprs);
327     }
328 }
329
330 /**
331  *Build an internal TC package for this
332  *node.
333  *
334  *@param message the tc_message struct to fill with info
335  *@return 0
336  */
337 int
338 olsr_build_tc_packet(struct tc_message *message)
339 {
340   struct tc_mpr_addr     *message_mpr;
341   //struct mpr_selector       *mprs;
342   int                     idx;
343   struct neighbor_entry  *entry;
344   //struct mpr_selector_hash  *mprs_hash;
345   olsr_bool entry_added = OLSR_FALSE;
346
347   message->multipoint_relay_selector_address=NULL;
348   message->packet_seq_number=0;
349  
350   message->hop_count = 0;
351   message->ttl = MAX_TTL;
352   message->ansn = get_local_ansn();
353
354   COPY_IP(&message->originator, &olsr_cnf->main_addr);
355   COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
356   
357
358   /* Loop trough all neighbors */  
359   for(idx=0;idx<HASHSIZE;idx++)
360     {
361       for(entry = neighbortable[idx].next;
362           entry != &neighbortable[idx];
363           entry = entry->next)
364         {
365           if(entry->status != SYM)
366             continue;
367
368           switch(olsr_cnf->tc_redundancy)
369             {
370             case(2):
371               {
372                 /* 2 = Add all neighbors */
373                 //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
374                 message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC");
375                 
376                 COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
377                 message_mpr->next = message->multipoint_relay_selector_address;
378                 message->multipoint_relay_selector_address = message_mpr;
379                 entry_added = OLSR_TRUE;
380                 
381                 break;
382               }
383             case(1):
384               {
385                 /* 1 = Add all MPR selectors and selected MPRs */
386                 if((entry->is_mpr) ||
387                    (olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL))
388                   {
389                     //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
390                     message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 2");
391                     
392                     COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
393                     message_mpr->next = message->multipoint_relay_selector_address;
394                     message->multipoint_relay_selector_address = message_mpr;
395                     entry_added = OLSR_TRUE;
396                   }
397                 break;
398               }
399             default:
400               {
401                 /* 0 = Add only MPR selectors(default) */
402                 if(olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL)
403                   {
404                     //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
405                     message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 3");
406                     
407                     COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
408                     message_mpr->next = message->multipoint_relay_selector_address;
409                     message->multipoint_relay_selector_address = message_mpr;
410                     entry_added = OLSR_TRUE;
411                   }
412                 break;
413               }         
414           
415             } /* Switch */
416         } /* For */
417     } /* For idx */
418
419   if(entry_added)
420     {
421       sending_tc = OLSR_TRUE;
422     }
423   else
424     {
425       if(sending_tc)
426         {
427           /* Send empty TC */
428           OLSR_PRINTF(3, "No more MPR selectors - will send empty TCs\n");
429           set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime*3)*1000));
430
431           sending_tc = OLSR_FALSE;
432         }
433     }
434
435
436   return 0;
437 }
438
439
440 /**
441  *Free the memory allocated for a HNA packet.
442  *
443  *@param message the pointer to the packet to erase
444  *
445  *@return nada
446  */
447
448 void
449 olsr_free_hna_packet(struct hna_message *message)
450 {
451   struct hna_net_addr  *hna_tmp, *hna_tmp2;
452
453   hna_tmp = message->hna_net;
454
455   while(hna_tmp)
456     {
457       hna_tmp2 = hna_tmp;
458       hna_tmp = hna_tmp->next;
459       free(hna_tmp2);
460     }
461 }
462
463
464
465 /**
466  *Free the memory allocated for a MID packet.
467  *
468  *@param message the pointer to the packet to erase
469  *
470  *@return nada
471  */
472
473 void
474 olsr_free_mid_packet(struct mid_message *message)
475 {
476   struct mid_alias *tmp_adr, *tmp_adr2;
477
478   tmp_adr = message->mid_addr;
479
480   while(tmp_adr)
481     {
482       tmp_adr2 = tmp_adr;
483       tmp_adr = tmp_adr->next;
484       free(tmp_adr2);
485     }
486 }