info: java: update workspace
[olsrd.git] / src / hna_set.c
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 "olsr.h"
49 #include "scheduler.h"
50 #include "net_olsr.h"
51 #include "tc_set.h"
52 #include "parser.h"
53 #include "gateway.h"
54 #include "duplicate_handler.h"
55
56 struct hna_entry hna_set[HASHSIZE];
57 struct olsr_cookie_info *hna_net_timer_cookie = NULL;
58 struct olsr_cookie_info *hna_entry_mem_cookie = NULL;
59 struct olsr_cookie_info *hna_net_mem_cookie = NULL;
60
61 static bool olsr_delete_hna_net_entry(struct hna_net *net_to_delete);
62
63 /**
64  * Initialize the HNA set
65  */
66 int
67 olsr_init_hna_set(void)
68 {
69   int idx;
70
71   for (idx = 0; idx < HASHSIZE; idx++) {
72     hna_set[idx].next = &hna_set[idx];
73     hna_set[idx].prev = &hna_set[idx];
74   }
75
76   hna_net_timer_cookie = olsr_alloc_cookie("HNA Network", OLSR_COOKIE_TYPE_TIMER);
77
78   hna_net_mem_cookie = olsr_alloc_cookie("hna_net", OLSR_COOKIE_TYPE_MEMORY);
79   olsr_cookie_set_memory_size(hna_net_mem_cookie, sizeof(struct hna_net));
80
81   hna_entry_mem_cookie = olsr_alloc_cookie("hna_entry", OLSR_COOKIE_TYPE_MEMORY);
82   olsr_cookie_set_memory_size(hna_entry_mem_cookie, sizeof(struct hna_entry));
83
84   return 1;
85 }
86
87 void
88 olsr_cleanup_hna(union olsr_ip_addr *orig) {
89   struct hna_entry *hna;
90
91   OLSR_FOR_ALL_HNA_ENTRIES(hna) {
92     if (hna->networks.next != &hna->networks && ipequal(&hna->A_gateway_addr, orig)) {
93       while (!olsr_delete_hna_net_entry(hna->networks.next));
94     }
95   } OLSR_FOR_ALL_HNA_ENTRIES_END(hna)
96 }
97
98 /**
99  * Lookup a network entry in a networkentry list.
100  *
101  * @param nets the network list to look in
102  * @param net the network to look for
103  * @param prefixlen the prefix length
104  *
105  * @return the localized entry or NULL of not found
106  */
107 struct hna_net *
108 olsr_lookup_hna_net(const struct hna_net *nets, const union olsr_ip_addr *net, uint8_t prefixlen)
109 {
110   struct hna_net *tmp;
111
112   /* Loop trough entrys */
113   for (tmp = nets->next; tmp != nets; tmp = tmp->next) {
114     if (tmp->hna_prefix.prefix_len == prefixlen && ipequal(&tmp->hna_prefix.prefix, net)) {
115       return tmp;
116     }
117   }
118
119   /* Not found */
120   return NULL;
121 }
122
123 /**
124  * Lookup a gateway entry
125  *
126  * @param gw the address of the gateway
127  * @return the located entry or NULL if not found
128  */
129 struct hna_entry *
130 olsr_lookup_hna_gw(const union olsr_ip_addr *gw)
131 {
132   struct hna_entry *tmp_hna;
133   uint32_t hash = olsr_ip_hashing(gw);
134
135   /* Check for registered entry */
136
137   for (tmp_hna = hna_set[hash].next; tmp_hna != &hna_set[hash]; tmp_hna = tmp_hna->next) {
138     if (ipequal(&tmp_hna->A_gateway_addr, gw)) {
139       return tmp_hna;
140     }
141   }
142
143   /* Not found */
144   return NULL;
145 }
146
147 /**
148  *Add a gatewayentry to the HNA set
149  *
150  *@param addr the address of the gateway
151  *
152  *@return the created entry
153  */
154 struct hna_entry *
155 olsr_add_hna_entry(const union olsr_ip_addr *addr)
156 {
157   struct hna_entry *new_entry;
158   uint32_t hash;
159
160   new_entry = olsr_cookie_malloc(hna_entry_mem_cookie);
161
162   /* Fill struct */
163   new_entry->A_gateway_addr = *addr;
164
165   /* Link nets */
166   new_entry->networks.next = &new_entry->networks;
167   new_entry->networks.prev = &new_entry->networks;
168
169   /* queue */
170   hash = olsr_ip_hashing(addr);
171
172   hna_set[hash].next->prev = new_entry;
173   new_entry->next = hna_set[hash].next;
174   hna_set[hash].next = new_entry;
175   new_entry->prev = &hna_set[hash];
176
177   return new_entry;
178 }
179
180 /**
181  * Adds a network entry to a HNA gateway.
182  *
183  * @param hna_gw the gateway entry to add the network to
184  * @param net the network address to add
185  * @param prefixlen the prefix length
186  *
187  * @return the newly created entry
188  */
189 struct hna_net *
190 olsr_add_hna_net(struct hna_entry *hna_gw, const union olsr_ip_addr *net, uint8_t prefixlen)
191 {
192   /* Add the net */
193   struct hna_net *new_net = olsr_cookie_malloc(hna_net_mem_cookie);
194
195   /* Fill struct */
196   memset(new_net, 0, sizeof(struct hna_net));
197   new_net->hna_prefix.prefix = *net;
198   new_net->hna_prefix.prefix_len= prefixlen;
199
200   /* Set backpointer */
201   new_net->hna_gw = hna_gw;
202
203   /* Queue */
204   hna_gw->networks.next->prev = new_net;
205   new_net->next = hna_gw->networks.next;
206   hna_gw->networks.next = new_net;
207   new_net->prev = &hna_gw->networks;
208
209   return new_net;
210 }
211
212 static bool
213 olsr_delete_hna_net_entry(struct hna_net *net_to_delete) {
214 #ifdef DEBUG
215   struct ipaddr_str buf1, buf2;
216 #endif /* DEBUG */
217   struct hna_entry *hna_gw;
218   bool removed_entry = false;
219
220 #ifdef __linux__
221   if (is_prefix_inetgw(&net_to_delete->hna_prefix)) {
222     /* modify smart gateway entry if necessary */
223     olsr_delete_gateway_entry(&net_to_delete->hna_gw->A_gateway_addr, net_to_delete->hna_prefix.prefix_len, false);
224   }
225 #endif /* __linux__ */
226
227   olsr_stop_timer(net_to_delete->hna_net_timer);
228   net_to_delete->hna_net_timer = NULL;  /* be pedandic */
229   hna_gw = net_to_delete->hna_gw;
230
231 #ifdef DEBUG
232   OLSR_PRINTF(5, "HNA: timeout %s via hna-gw %s\n",
233       olsr_ip_prefix_to_string(&net_to_delete->hna_prefix),
234               olsr_ip_to_string(&buf2, &hna_gw->A_gateway_addr));
235 #endif /* DEBUG */
236
237   /*
238    * Delete the rt_path for the entry.
239    */
240   olsr_delete_routing_table(&net_to_delete->hna_prefix.prefix,
241       net_to_delete->hna_prefix.prefix_len, &hna_gw->A_gateway_addr);
242
243   DEQUEUE_ELEM(net_to_delete);
244
245   /* Delete hna_gw if empty */
246   if (hna_gw->networks.next == &hna_gw->networks) {
247     DEQUEUE_ELEM(hna_gw);
248     olsr_cookie_free(hna_entry_mem_cookie, hna_gw);
249     removed_entry = true;
250   }
251
252   olsr_cookie_free(hna_net_mem_cookie, net_to_delete);
253   return removed_entry;
254 }
255
256 /**
257  * Callback for the hna_net timer.
258  */
259 static void
260 olsr_expire_hna_net_entry(void *context)
261 {
262   olsr_delete_hna_net_entry(context);
263 }
264
265 /**
266  * Update a HNA entry. If it does not exist it
267  * is created.
268  * This is the only function that should be called
269  * from outside concerning creation of HNA entries.
270  *
271  *@param gw address of the gateway
272  *@param net address of the network
273  *@param prefixlen the prefix length
274  *@param vtime the validitytime of the entry
275  */
276 void
277 olsr_update_hna_entry(const union olsr_ip_addr *gw, const union olsr_ip_addr *net, uint8_t prefixlen, olsr_reltime vtime)
278 {
279   struct hna_entry *gw_entry;
280   struct hna_net *net_entry;
281
282   gw_entry = olsr_lookup_hna_gw(gw);
283   if (!gw_entry) {
284
285     /* Need to add the entry */
286     gw_entry = olsr_add_hna_entry(gw);
287   }
288
289   net_entry = olsr_lookup_hna_net(&gw_entry->networks, net, prefixlen);
290   if (net_entry == NULL) {
291
292     /* Need to add the net */
293     net_entry = olsr_add_hna_net(gw_entry, net, prefixlen);
294     changes_hna = true;
295   }
296
297   /*
298    * Add the rt_path for the entry.
299    */
300   olsr_insert_routing_table(&net_entry->hna_prefix.prefix,
301       net_entry->hna_prefix.prefix_len, &gw_entry->A_gateway_addr, OLSR_RT_ORIGIN_HNA);
302
303   /*
304    * Start, or refresh the timer, whatever is appropriate.
305    */
306   olsr_set_timer(&net_entry->hna_net_timer, vtime, OLSR_HNA_NET_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_hna_net_entry, net_entry,
307                  hna_net_timer_cookie);
308 }
309
310 /**
311  * Print all HNA entries.
312  *
313  *@return nada
314  */
315 #ifndef NODEBUG
316 void
317 olsr_print_hna_set(void)
318 {
319   /* The whole function doesn't do anything else. */
320   int idx;
321   struct tm * nowtm;
322   struct timeval now;
323   const int ipwidth = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
324   const int ipwidthprefix = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN + 1 + 3 - 1);
325
326         (void)gettimeofday(&now, NULL);
327   nowtm = localtime((time_t *)&now.tv_sec);
328
329   OLSR_PRINTF(1, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- HNA SET\n\n", nowtm->tm_hour,
330               nowtm->tm_min, nowtm->tm_sec, (int)now.tv_usec / 10000);
331
332   if (olsr_cnf->ip_version == AF_INET)
333     OLSR_PRINTF(1, "IP net          netmask         GW IP\n");
334   else
335     OLSR_PRINTF(1, "IP net/prefixlen               GW IP\n");
336
337   for (idx = 0; idx < HASHSIZE; idx++) {
338     struct hna_entry *tmp_hna = hna_set[idx].next;
339     /* Check all entrys */
340     while (tmp_hna != &hna_set[idx]) {
341       /* Check all networks */
342       struct hna_net *tmp_net = tmp_hna->networks.next;
343
344       while (tmp_net != &tmp_hna->networks) {
345         struct ipaddr_str buf;
346         OLSR_PRINTF(1, "%-*s ", ipwidthprefix, olsr_ip_prefix_to_string(&tmp_net->hna_prefix));
347         OLSR_PRINTF(1, "%-*s\n", ipwidth, olsr_ip_to_string(&buf, &tmp_hna->A_gateway_addr));
348
349         tmp_net = tmp_net->next;
350       }
351       tmp_hna = tmp_hna->next;
352     }
353   }
354 }
355 #endif /* NODEBUG */
356
357 /**
358  *Process incoming HNA message.
359  *Forwards the message if that is to be done.
360  *
361  *@param m the incoming OLSR message
362  *@param in_if the incoming interface
363  *@param from_addr the originator address
364  *the OLSR message.
365  *@return 1 on success
366  */
367
368 bool
369 olsr_input_hna(union olsr_message *m, struct interface_olsr *in_if __attribute__ ((unused)), union olsr_ip_addr *from_addr)
370 {
371
372   uint8_t olsr_msgtype;
373   olsr_reltime vtime;
374   uint16_t olsr_msgsize;
375   union olsr_ip_addr originator;
376   uint8_t hop_count;
377   uint16_t msg_seq_number;
378
379   int hnasize;
380   const uint8_t *curr, *curr_end;
381
382   struct ipaddr_str buf;
383 #ifdef DEBUG
384   OLSR_PRINTF(5, "Processing HNA\n");
385 #endif /* DEBUG */
386
387   /* Check if everyting is ok */
388   if (!m) {
389     return false;
390   }
391   curr = (const uint8_t *)m;
392
393   /* olsr_msgtype */
394   pkt_get_u8(&curr, &olsr_msgtype);
395   if (olsr_msgtype != HNA_MESSAGE) {
396     OLSR_PRINTF(1, "not a HNA message!\n");
397     return false;
398   }
399   /* Get vtime */
400   pkt_get_reltime(&curr, &vtime);
401
402   /* olsr_msgsize */
403   pkt_get_u16(&curr, &olsr_msgsize);
404
405   hnasize = olsr_msgsize - 8 - olsr_cnf->ipsize;
406   curr_end = (const uint8_t *)m + olsr_msgsize;
407
408   /* validate originator */
409   pkt_get_ipaddress(&curr, &originator);
410   /*printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator)); */
411
412   /* ttl */
413   pkt_ignore_u8(&curr);
414
415   /* hopcnt */
416   pkt_get_u8(&curr, &hop_count);
417
418   /* seqno */
419   pkt_get_u16(&curr, &msg_seq_number);
420
421   if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
422     OLSR_PRINTF(1, "Illegal HNA message from %s with size %d!\n",
423         olsr_ip_to_string(&buf, &originator), olsr_msgsize);
424     return false;
425   }
426
427   /*
428    *      If the sender interface (NB: not originator) of this message
429    *      is not in the symmetric 1-hop neighborhood of this node, the
430    *      message MUST be discarded.
431    */
432   if (check_neighbor_link(from_addr) != SYM_LINK) {
433     OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
434     return false;
435   }
436   while (curr < curr_end) {
437     struct olsr_ip_prefix prefix;
438     union olsr_ip_addr mask;
439
440     struct ip_prefix_list *entry;
441     struct interface_olsr *ifs;
442     bool stop = false;
443
444     pkt_get_ipaddress(&curr, &prefix.prefix);
445     pkt_get_ipaddress(&curr, &mask);
446     prefix.prefix_len = olsr_netmask_to_prefix(&mask);
447
448 #ifdef __linux__
449     if (olsr_cnf->smart_gw_active && olsr_is_smart_gateway(&prefix, &mask)) {
450       olsr_update_gateway_entry(&originator, &mask, prefix.prefix_len, msg_seq_number, vtime);
451       continue;
452     }
453 #endif /* __linux__ */
454
455 #ifdef MAXIMUM_GATEWAY_PREFIX_LENGTH
456     if (olsr_cnf->smart_gw_active && prefix.prefix_len > 0 && prefix.prefix_len <= MAXIMUM_GATEWAY_PREFIX_LENGTH) {
457       continue;
458     }
459 #endif /* MAXIMUM_GATEWAY_PREFIX_LENGTH */
460
461 #ifndef NO_DUPLICATE_DETECTION_HANDLER
462     for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
463       if (ipequal(&ifs->ip_addr, &prefix.prefix)) {
464       /* ignore your own main IP as an incoming MID */
465         olsr_handle_hna_collision(&prefix.prefix, &originator);
466         stop = true;
467         break;
468       }
469     }
470     if (stop) {
471       continue;
472     }
473 #endif /* NO_DUPLICATE_DETECTION_HANDLER */
474     entry = ip_prefix_list_find(olsr_cnf->hna_entries, &prefix.prefix, prefix.prefix_len);
475     if (entry == NULL) {
476       /* only update if it's not from us */
477       olsr_update_hna_entry(&originator, &prefix.prefix, prefix.prefix_len, vtime);
478     }
479   }
480   /* Forward the message */
481   return true;
482 }
483
484 /*
485  * Local Variables:
486  * c-basic-offset: 2
487  * indent-tabs-mode: nil
488  * End:
489  */