neighbor table: fix crash in olsr_print_neighbor_table on MinGW
[olsrd.git] / src / neighbor_table.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 "two_hop_neighbor_table.h"
45 #include "mid_set.h"
46 #include "mpr.h"
47 #include "neighbor_table.h"
48 #include "olsr.h"
49 #include "scheduler.h"
50 #include "link_set.h"
51 #include "mpr_selector_set.h"
52 #include "net_olsr.h"
53
54 struct neighbor_entry neighbortable[HASHSIZE];
55
56 void
57 olsr_init_neighbor_table(void)
58 {
59   int i;
60
61   for (i = 0; i < HASHSIZE; i++) {
62     neighbortable[i].next = &neighbortable[i];
63     neighbortable[i].prev = &neighbortable[i];
64   }
65 }
66
67 /**
68  * Unlink, delete and free a nbr2_list entry.
69  */
70 static void
71 olsr_del_nbr2_list(struct neighbor_2_list_entry *nbr2_list)
72 {
73   struct neighbor_2_entry *nbr2;
74
75   nbr2 = nbr2_list->neighbor_2;
76
77   if (nbr2->neighbor_2_pointer < 1) {
78     DEQUEUE_ELEM(nbr2);
79     free(nbr2);
80   }
81
82   /*
83    * Kill running timers.
84    */
85   olsr_stop_timer(nbr2_list->nbr2_list_timer);
86   nbr2_list->nbr2_list_timer = NULL;
87
88   /* Dequeue */
89   DEQUEUE_ELEM(nbr2_list);
90
91   free(nbr2_list);
92
93   /* Set flags to recalculate the MPR set and the routing table */
94   changes_neighborhood = true;
95   changes_topology = true;
96 }
97
98 /**
99  * Delete a two hop neighbor from a neighbors two hop neighbor list.
100  *
101  * @param neighbor the neighbor to delete the two hop neighbor from.
102  * @param neigh2 the IP address of the two hop neighbor to delete.
103  *
104  * @return positive if entry deleted
105  */
106 int
107 olsr_delete_neighbor_2_pointer(struct neighbor_entry *neighbor, struct neighbor_2_entry *neigh2)
108 {
109   struct neighbor_2_list_entry *nbr2_list;
110
111   nbr2_list = neighbor->neighbor_2_list.next;
112
113   while (nbr2_list != &neighbor->neighbor_2_list) {
114     if (nbr2_list->neighbor_2 == neigh2) {
115       olsr_del_nbr2_list(nbr2_list);
116       return 1;
117     }
118     nbr2_list = nbr2_list->next;
119   }
120   return 0;
121 }
122
123 /**
124  *Check if a two hop neighbor is reachable via a given
125  *neighbor.
126  *
127  *@param neighbor neighbor-entry to check via
128  *@param neighbor_main_address the addres of the two hop neighbor
129  *to find.
130  *
131  *@return a pointer to the neighbor_2_list_entry struct
132  *representing the two hop neighbor if found. NULL if not found.
133  */
134 struct neighbor_2_list_entry *
135 olsr_lookup_my_neighbors(const struct neighbor_entry *neighbor, const union olsr_ip_addr *neighbor_main_address)
136 {
137   struct neighbor_2_list_entry *entry;
138
139   for (entry = neighbor->neighbor_2_list.next; entry != &neighbor->neighbor_2_list; entry = entry->next) {
140
141     if (ipequal(&entry->neighbor_2->neighbor_2_addr, neighbor_main_address))
142       return entry;
143
144   }
145   return NULL;
146 }
147
148 /**
149  * Update a neighbours main_addr inlcuding hash
150 */
151
152 void
153 olsr_update_neighbor_main_addr(struct neighbor_entry *entry, const union olsr_ip_addr *new_main_addr)
154 {
155   /*remove from old pos*/
156   DEQUEUE_ELEM(entry);
157
158   /*update main addr*/
159   entry->neighbor_main_addr = *new_main_addr;
160
161   /*insert it again*/
162   QUEUE_ELEM(neighbortable[olsr_ip_hashing(new_main_addr)], entry);
163
164 }
165
166 /**
167  *Delete a neighbr table entry.
168  *
169  *Remember: Deleting a neighbor entry results
170  *the deletion of its 2 hop neighbors list!!!
171  *@param neighbor_addr the neighbor entry to delete
172  *
173  *@return always 1
174  */
175
176 int
177 olsr_delete_neighbor_table(const union olsr_ip_addr *neighbor_addr)
178 {
179   struct neighbor_2_list_entry *two_hop_list, *two_hop_to_delete;
180   uint32_t hash;
181   struct neighbor_entry *entry;
182
183   //printf("inserting neighbor\n");
184
185   hash = olsr_ip_hashing(neighbor_addr);
186
187   entry = neighbortable[hash].next;
188
189   /*
190    * Find neighbor entry
191    */
192   while (entry != &neighbortable[hash]) {
193     if (ipequal(&entry->neighbor_main_addr, neighbor_addr))
194       break;
195
196     entry = entry->next;
197   }
198
199   if (entry == &neighbortable[hash])
200     return 0;
201
202   two_hop_list = entry->neighbor_2_list.next;
203
204   while (two_hop_list != &entry->neighbor_2_list) {
205     two_hop_to_delete = two_hop_list;
206     two_hop_list = two_hop_list->next;
207
208     two_hop_to_delete->neighbor_2->neighbor_2_pointer--;
209     olsr_delete_neighbor_pointer(two_hop_to_delete->neighbor_2, entry);
210
211     olsr_del_nbr2_list(two_hop_to_delete);
212   }
213
214   /* Dequeue */
215   DEQUEUE_ELEM(entry);
216
217   free(entry);
218
219   changes_neighborhood = true;
220   return 1;
221
222 }
223
224 /**
225  *Insert a neighbor entry in the neighbor table
226  *
227  *@param main_addr the main address of the new node
228  *
229  *@return 0 if neighbor already exists 1 if inserted
230  */
231 struct neighbor_entry *
232 olsr_insert_neighbor_table(const union olsr_ip_addr *main_addr)
233 {
234   uint32_t hash;
235   struct neighbor_entry *new_neigh;
236
237   hash = olsr_ip_hashing(main_addr);
238
239   /* Check if entry exists */
240
241   for (new_neigh = neighbortable[hash].next; new_neigh != &neighbortable[hash]; new_neigh = new_neigh->next) {
242     if (ipequal(&new_neigh->neighbor_main_addr, main_addr))
243       return new_neigh;
244   }
245
246   //printf("inserting neighbor\n");
247
248   new_neigh = olsr_malloc(sizeof(struct neighbor_entry), "New neighbor entry");
249
250   /* Set address, willingness and status */
251   new_neigh->neighbor_main_addr = *main_addr;
252   new_neigh->willingness = WILL_NEVER;
253   new_neigh->status = NOT_SYM;
254
255   new_neigh->neighbor_2_list.next = &new_neigh->neighbor_2_list;
256   new_neigh->neighbor_2_list.prev = &new_neigh->neighbor_2_list;
257
258   new_neigh->linkcount = 0;
259   new_neigh->is_mpr = false;
260   new_neigh->was_mpr = false;
261
262   /* Queue */
263   QUEUE_ELEM(neighbortable[hash], new_neigh);
264
265   return new_neigh;
266 }
267
268 /**
269  *Lookup a neighbor entry in the neighbortable based on an address.
270  *
271  *@param dst the IP address of the neighbor to look up
272  *
273  *@return a pointer to the neighbor struct registered on the given
274  *address. NULL if not found.
275  */
276 struct neighbor_entry *
277 olsr_lookup_neighbor_table(const union olsr_ip_addr *dst)
278 {
279   /*
280    *Find main address of node
281    */
282   union olsr_ip_addr *tmp_ip = mid_lookup_main_addr(dst);
283   if (tmp_ip != NULL)
284     dst = tmp_ip;
285   return olsr_lookup_neighbor_table_alias(dst);
286 }
287
288 /**
289  *Lookup a neighbor entry in the neighbortable based on an address.
290  *
291  *@param dst the IP address of the neighbor to look up
292  *
293  *@return a pointer to the neighbor struct registered on the given
294  *address. NULL if not found.
295  */
296 struct neighbor_entry *
297 olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *dst)
298 {
299   struct neighbor_entry *entry;
300   uint32_t hash = olsr_ip_hashing(dst);
301
302   //printf("\nLookup %s\n", olsr_ip_to_string(&buf, dst));
303   for (entry = neighbortable[hash].next; entry != &neighbortable[hash]; entry = entry->next) {
304     //printf("Checking %s\n", olsr_ip_to_string(&buf, &entry->neighbor_main_addr));
305     if (ipequal(&entry->neighbor_main_addr, dst))
306       return entry;
307
308   }
309   //printf("NOPE\n\n");
310
311   return NULL;
312
313 }
314
315 int
316 update_neighbor_status(struct neighbor_entry *entry, int lnk)
317 {
318   /*
319    * Update neighbor entry
320    */
321
322   if (lnk == SYM_LINK) {
323     /* N_status is set to SYM */
324     if (entry->status == NOT_SYM) {
325       struct neighbor_2_entry *two_hop_neighbor;
326
327       /* Delete posible 2 hop entry on this neighbor */
328       if ((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&entry->neighbor_main_addr)) != NULL) {
329         olsr_delete_two_hop_neighbor_table(two_hop_neighbor);
330       }
331
332       changes_neighborhood = true;
333       changes_topology = true;
334       if (olsr_cnf->tc_redundancy > 1)
335         signal_link_changes(true);
336     }
337     entry->status = SYM;
338   } else {
339     if (entry->status == SYM) {
340       changes_neighborhood = true;
341       changes_topology = true;
342       if (olsr_cnf->tc_redundancy > 1)
343         signal_link_changes(true);
344     }
345     /* else N_status is set to NOT_SYM */
346     entry->status = NOT_SYM;
347     /* remove neighbor from routing list */
348   }
349
350   return entry->status;
351 }
352
353 /**
354  * Callback for the nbr2_list timer.
355  */
356 void
357 olsr_expire_nbr2_list(void *context)
358 {
359   struct neighbor_2_list_entry *nbr2_list;
360   struct neighbor_entry *nbr;
361   struct neighbor_2_entry *nbr2;
362
363   nbr2_list = (struct neighbor_2_list_entry *)context;
364   nbr2_list->nbr2_list_timer = NULL;
365
366   nbr = nbr2_list->nbr2_nbr;
367   nbr2 = nbr2_list->neighbor_2;
368
369   nbr2->neighbor_2_pointer--;
370   olsr_delete_neighbor_pointer(nbr2, nbr);
371
372   olsr_del_nbr2_list(nbr2_list);
373 }
374
375 /**
376  *Prints the registered neighbors and two hop neighbors
377  *to STDOUT.
378  *
379  *@return nada
380  */
381 #ifndef NODEBUG
382 void
383 olsr_print_neighbor_table(void)
384 {
385   /* The whole function doesn't do anything else. */
386   const int iplen = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
387   int idx;
388
389   OLSR_PRINTF(1,
390               "\n--- %s ------------------------------------------------ NEIGHBORS\n\n"
391               "%*s  LQ     NLQ    SYM   MPR   MPRS  will\n", olsr_wallclock_string(),
392               iplen, "IP address");
393
394   for (idx = 0; idx < HASHSIZE; idx++) {
395     struct neighbor_entry *neigh;
396     for (neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) {
397       struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
398       if (lnk) {
399         struct ipaddr_str buf;
400         OLSR_PRINTF(1, "%-*s  %5.3f  %s  %s  %s  %d\n", iplen, olsr_ip_to_string(&buf, &neigh->neighbor_main_addr),
401                     (double)lnk->L_link_quality, neigh->status == SYM ? "YES " : "NO  ",
402                     neigh->is_mpr ? "YES " : "NO  ", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO  " : "YES ",
403                     neigh->willingness);
404       }
405     }
406   }
407 }
408 #endif /* NODEBUG */
409
410 /*
411  * Local Variables:
412  * c-basic-offset: 2
413  * indent-tabs-mode: nil
414  * End:
415  */