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