1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * (c) by the OLSR project
5  *
6  * See our Git repository to find out who worked on this file
7  * and thus is a copyright holder on it.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  *   notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above copyright
18  *   notice, this list of conditions and the following disclaimer in
19  *   the documentation and/or other materials provided with the
20  *   distribution.
21  * * Neither the name of olsr.org, olsrd nor the names of its
22  *   contributors may be used to endorse or promote products derived
23  *   from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Visit http://www.olsr.org for more information.
39  *
40  * If you find this software useful feel free to make a donation
41  * to the project. For more information see the website or contact
42  * the copyright holders.
43  *
44  */
45 
46 #include "ipcalc.h"
47 #include "defs.h"
48 #include "two_hop_neighbor_table.h"
49 #include "mid_set.h"
50 #include "mpr.h"
51 #include "neighbor_table.h"
52 #include "olsr.h"
53 #include "scheduler.h"
54 #include "link_set.h"
55 #include "mpr_selector_set.h"
56 #include "net_olsr.h"
57 
58 struct neighbor_entry neighbortable[HASHSIZE];
59 
60 void
olsr_init_neighbor_table(void)61 olsr_init_neighbor_table(void)
62 {
63   int i;
64 
65   for (i = 0; i < HASHSIZE; i++) {
66     neighbortable[i].next = &neighbortable[i];
67     neighbortable[i].prev = &neighbortable[i];
68   }
69 }
70 
71 /**
72  * Unlink, delete and free a nbr2_list entry.
73  */
74 static void
olsr_del_nbr2_list(struct neighbor_2_list_entry * nbr2_list)75 olsr_del_nbr2_list(struct neighbor_2_list_entry *nbr2_list)
76 {
77   struct neighbor_2_entry *nbr2;
78 
79   nbr2 = nbr2_list->neighbor_2;
80 
81   if (nbr2->neighbor_2_pointer < 1) {
82     DEQUEUE_ELEM(nbr2);
83     free(nbr2);
84   }
85 
86   /*
87    * Kill running timers.
88    */
89   olsr_stop_timer(nbr2_list->nbr2_list_timer);
90   nbr2_list->nbr2_list_timer = NULL;
91 
92   /* Dequeue */
93   DEQUEUE_ELEM(nbr2_list);
94 
95   free(nbr2_list);
96 
97   /* Set flags to recalculate the MPR set and the routing table */
98   changes_neighborhood = true;
99   changes_topology = true;
100 }
101 
102 /**
103  * Delete a two hop neighbor from a neighbors two hop neighbor list.
104  *
105  * @param neighbor the neighbor to delete the two hop neighbor from.
106  * @param neigh2 the IP address of the two hop neighbor to delete.
107  *
108  * @return positive if entry deleted
109  */
110 int
olsr_delete_neighbor_2_pointer(struct neighbor_entry * neighbor,struct neighbor_2_entry * neigh2)111 olsr_delete_neighbor_2_pointer(struct neighbor_entry *neighbor, struct neighbor_2_entry *neigh2)
112 {
113   struct neighbor_2_list_entry *nbr2_list;
114 
115   nbr2_list = neighbor->neighbor_2_list.next;
116 
117   while (nbr2_list != &neighbor->neighbor_2_list) {
118     if (nbr2_list->neighbor_2 == neigh2) {
119       olsr_del_nbr2_list(nbr2_list);
120       return 1;
121     }
122     nbr2_list = nbr2_list->next;
123   }
124   return 0;
125 }
126 
127 /**
128  *Check if a two hop neighbor is reachable via a given
129  *neighbor.
130  *
131  *@param neighbor neighbor-entry to check via
132  *@param neighbor_main_address the addres of the two hop neighbor
133  *to find.
134  *
135  *@return a pointer to the neighbor_2_list_entry struct
136  *representing the two hop neighbor if found. NULL if not found.
137  */
138 struct neighbor_2_list_entry *
olsr_lookup_my_neighbors(const struct neighbor_entry * neighbor,const union olsr_ip_addr * neighbor_main_address)139 olsr_lookup_my_neighbors(const struct neighbor_entry *neighbor, const union olsr_ip_addr *neighbor_main_address)
140 {
141   struct neighbor_2_list_entry *entry;
142 
143   for (entry = neighbor->neighbor_2_list.next; entry != &neighbor->neighbor_2_list; entry = entry->next) {
144 
145     if (ipequal(&entry->neighbor_2->neighbor_2_addr, neighbor_main_address))
146       return entry;
147 
148   }
149   return NULL;
150 }
151 
152 /**
153  * Update a neighbours main_addr inlcuding hash
154 */
155 
156 void
olsr_update_neighbor_main_addr(struct neighbor_entry * entry,const union olsr_ip_addr * new_main_addr)157 olsr_update_neighbor_main_addr(struct neighbor_entry *entry, const union olsr_ip_addr *new_main_addr)
158 {
159   /*remove from old pos*/
160   DEQUEUE_ELEM(entry);
161 
162   /*update main addr*/
163   entry->neighbor_main_addr = *new_main_addr;
164 
165   /*insert it again*/
166   QUEUE_ELEM(neighbortable[olsr_ip_hashing(new_main_addr)], entry);
167 
168 }
169 
170 /**
171  *Delete a neighbr table entry.
172  *
173  *Remember: Deleting a neighbor entry results
174  *the deletion of its 2 hop neighbors list!!!
175  *@param neighbor_addr the neighbor entry to delete
176  *
177  *@return always 1
178  */
179 
180 int
olsr_delete_neighbor_table(const union olsr_ip_addr * neighbor_addr)181 olsr_delete_neighbor_table(const union olsr_ip_addr *neighbor_addr)
182 {
183   struct neighbor_2_list_entry *two_hop_list, *two_hop_to_delete;
184   uint32_t hash;
185   struct neighbor_entry *entry;
186 
187   //printf("inserting neighbor\n");
188 
189   hash = olsr_ip_hashing(neighbor_addr);
190 
191   entry = neighbortable[hash].next;
192 
193   /*
194    * Find neighbor entry
195    */
196   while (entry != &neighbortable[hash]) {
197     if (ipequal(&entry->neighbor_main_addr, neighbor_addr))
198       break;
199 
200     entry = entry->next;
201   }
202 
203   if (entry == &neighbortable[hash])
204     return 0;
205 
206   two_hop_list = entry->neighbor_2_list.next;
207 
208   while (two_hop_list != &entry->neighbor_2_list) {
209     two_hop_to_delete = two_hop_list;
210     two_hop_list = two_hop_list->next;
211 
212     two_hop_to_delete->neighbor_2->neighbor_2_pointer--;
213     olsr_delete_neighbor_pointer(two_hop_to_delete->neighbor_2, entry);
214 
215     olsr_del_nbr2_list(two_hop_to_delete);
216   }
217 
218   /* Dequeue */
219   DEQUEUE_ELEM(entry);
220 
221   free(entry);
222 
223   changes_neighborhood = true;
224   signal_link_changes(true);
225   return 1;
226 
227 }
228 
229 /**
230  *Insert a neighbor entry in the neighbor table
231  *
232  *@param main_addr the main address of the new node
233  *
234  *@return 0 if neighbor already exists 1 if inserted
235  */
236 struct neighbor_entry *
olsr_insert_neighbor_table(const union olsr_ip_addr * main_addr)237 olsr_insert_neighbor_table(const union olsr_ip_addr *main_addr)
238 {
239   uint32_t hash;
240   struct neighbor_entry *new_neigh;
241 
242   hash = olsr_ip_hashing(main_addr);
243 
244   /* Check if entry exists */
245 
246   for (new_neigh = neighbortable[hash].next; new_neigh != &neighbortable[hash]; new_neigh = new_neigh->next) {
247     if (ipequal(&new_neigh->neighbor_main_addr, main_addr))
248       return new_neigh;
249   }
250 
251   //printf("inserting neighbor\n");
252 
253   new_neigh = olsr_malloc(sizeof(struct neighbor_entry), "New neighbor entry");
254 
255   /* Set address, willingness and status */
256   new_neigh->neighbor_main_addr = *main_addr;
257   new_neigh->willingness = WILL_NEVER;
258   new_neigh->status = NOT_SYM;
259 
260   new_neigh->neighbor_2_list.next = &new_neigh->neighbor_2_list;
261   new_neigh->neighbor_2_list.prev = &new_neigh->neighbor_2_list;
262 
263   new_neigh->linkcount = 0;
264   new_neigh->is_mpr = false;
265   new_neigh->was_mpr = false;
266 
267   /* Queue */
268   QUEUE_ELEM(neighbortable[hash], new_neigh);
269 
270   return new_neigh;
271 }
272 
273 /**
274  *Lookup a neighbor entry in the neighbortable based on an address.
275  *
276  *@param dst the IP address of the neighbor to look up
277  *
278  *@return a pointer to the neighbor struct registered on the given
279  *address. NULL if not found.
280  */
281 struct neighbor_entry *
olsr_lookup_neighbor_table(const union olsr_ip_addr * dst)282 olsr_lookup_neighbor_table(const union olsr_ip_addr *dst)
283 {
284   /*
285    *Find main address of node
286    */
287   union olsr_ip_addr *tmp_ip = mid_lookup_main_addr(dst);
288   if (tmp_ip != NULL)
289     dst = tmp_ip;
290   return olsr_lookup_neighbor_table_alias(dst);
291 }
292 
293 /**
294  *Lookup a neighbor entry in the neighbortable based on an address.
295  *
296  *@param dst the IP address of the neighbor to look up
297  *
298  *@return a pointer to the neighbor struct registered on the given
299  *address. NULL if not found.
300  */
301 struct neighbor_entry *
olsr_lookup_neighbor_table_alias(const union olsr_ip_addr * dst)302 olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *dst)
303 {
304   struct neighbor_entry *entry;
305   uint32_t hash = olsr_ip_hashing(dst);
306 
307   //printf("\nLookup %s\n", olsr_ip_to_string(&buf, dst));
308   for (entry = neighbortable[hash].next; entry != &neighbortable[hash]; entry = entry->next) {
309     //printf("Checking %s\n", olsr_ip_to_string(&buf, &entry->neighbor_main_addr));
310     if (ipequal(&entry->neighbor_main_addr, dst))
311       return entry;
312 
313   }
314   //printf("NOPE\n\n");
315 
316   return NULL;
317 
318 }
319 
320 int
update_neighbor_status(struct neighbor_entry * entry,int lnk)321 update_neighbor_status(struct neighbor_entry *entry, int lnk)
322 {
323   /*
324    * Update neighbor entry
325    */
326 
327   if (lnk == SYM_LINK) {
328     /* N_status is set to SYM */
329     if (entry->status == NOT_SYM) {
330       struct neighbor_2_entry *two_hop_neighbor;
331 
332       /* Delete posible 2 hop entry on this neighbor */
333       if ((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&entry->neighbor_main_addr)) != NULL) {
334         olsr_delete_two_hop_neighbor_table(two_hop_neighbor);
335       }
336 
337       changes_neighborhood = true;
338       changes_topology = true;
339       if (olsr_cnf->tc_redundancy > 1)
340         signal_link_changes(true);
341     }
342     entry->status = SYM;
343   } else {
344     if (entry->status == SYM) {
345       changes_neighborhood = true;
346       changes_topology = true;
347       if (olsr_cnf->tc_redundancy > 1)
348         signal_link_changes(true);
349     }
350     /* else N_status is set to NOT_SYM */
351     entry->status = NOT_SYM;
352     /* remove neighbor from routing list */
353   }
354 
355   return entry->status;
356 }
357 
358 /**
359  * Callback for the nbr2_list timer.
360  */
361 void
olsr_expire_nbr2_list(void * context)362 olsr_expire_nbr2_list(void *context)
363 {
364   struct neighbor_2_list_entry *nbr2_list;
365   struct neighbor_entry *nbr;
366   struct neighbor_2_entry *nbr2;
367 
368   nbr2_list = (struct neighbor_2_list_entry *)context;
369   nbr2_list->nbr2_list_timer = NULL;
370 
371   nbr = nbr2_list->nbr2_nbr;
372   nbr2 = nbr2_list->neighbor_2;
373 
374   nbr2->neighbor_2_pointer--;
375   olsr_delete_neighbor_pointer(nbr2, nbr);
376 
377   olsr_del_nbr2_list(nbr2_list);
378 }
379 
380 /**
381  *Prints the registered neighbors and two hop neighbors
382  *to STDOUT.
383  *
384  *@return nada
385  */
386 #ifndef NODEBUG
387 void
olsr_print_neighbor_table(void)388 olsr_print_neighbor_table(void)
389 {
390   /* The whole function doesn't do anything else. */
391   const int iplen = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
392   int idx;
393 
394   OLSR_PRINTF(1,
395               "\n--- %s ------------------------------------------------ NEIGHBORS\n\n"
396               "%*s\tHyst\tLQ\tETX\tSYM   MPR   MPRS  will\n", olsr_wallclock_string(),
397               iplen, "IP address");
398 
399   for (idx = 0; idx < HASHSIZE; idx++) {
400     struct neighbor_entry *neigh;
401     for (neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) {
402       struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
403       if (lnk) {
404         struct ipaddr_str buf;
405         struct lqtextbuffer lqbuffer1, lqbuffer2;
406 
407         OLSR_PRINTF(1, "%-*s\t%5.3f\t%s\t%s\t%s  %s  %s  %d\n", iplen, olsr_ip_to_string(&buf, &neigh->neighbor_main_addr),
408                     (double)lnk->L_link_quality,
409                     get_link_entry_text(lnk, '/', &lqbuffer1),
410                     get_linkcost_text(lnk->linkcost,false, &lqbuffer2),
411                     neigh->status == SYM ? "YES " : "NO  ",
412                     neigh->is_mpr ? "YES " : "NO  ",
413                     olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO  " : "YES ",
414                     neigh->willingness);
415       }
416     }
417   }
418 }
419 #endif /* NODEBUG */
420 
421 /*
422  * Local Variables:
423  * c-basic-offset: 2
424  * indent-tabs-mode: nil
425  * End:
426  */
427