3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
47 #include "olsr_timer.h"
48 #include "olsr_socket.h"
51 #include "olsr_ip_prefix_list.h"
52 #include "olsr_logging.h"
54 /* Some cookies for stats keeping */
55 static struct olsr_timer_info *hna_net_timer_info = NULL;
56 static struct olsr_memcookie_info *hna_net_mem_cookie = NULL;
58 static void olsr_expire_hna_net_entry(void *context);
61 * Initialize the HNA set
64 olsr_init_hna_set(void)
66 OLSR_INFO(LOG_HNA, "Initialize HNA set...\n");
68 hna_net_timer_info = olsr_timer_add("HNA Network", &olsr_expire_hna_net_entry, false);
70 hna_net_mem_cookie = olsr_memcookie_add("hna_net", sizeof(struct hna_net));
74 * Lookup a network entry in the HNA subtree.
76 * @param tc the HNA hookup point
77 * @param prefic the prefix to look for
79 * @return the localized entry or NULL of not found
81 static struct hna_net *
82 olsr_lookup_hna_net(struct tc_entry *tc, const struct olsr_ip_prefix *prefix)
86 hna = avl_find_element(&tc->hna_tree, prefix, hna, hna_tc_node);
91 * Adds a network entry to a HNA gateway.
93 * @param tc the gateway entry to add the network to
94 * @param net the nework prefix to add
95 * @param prefixlen the prefix length
97 * @return the newly created entry
99 static struct hna_net *
100 olsr_add_hna_net(struct tc_entry *tc, const struct olsr_ip_prefix *prefix)
103 struct hna_net *new_net = olsr_memcookie_malloc(hna_net_mem_cookie);
106 new_net->hna_prefix = *prefix;
108 /* Set backpointer */
109 new_net->hna_tc = tc;
112 * Insert into the per-tc hna subtree.
114 new_net->hna_tc_node.key = &new_net->hna_prefix;
115 avl_insert(&tc->hna_tree, &new_net->hna_tc_node);
121 * Delete a single HNA network.
123 * @param hna_net the hna_net to delete.
126 olsr_delete_hna_net(struct hna_net *hna_net)
128 struct tc_entry *tc = hna_net->hna_tc;
131 * Delete the rt_path for the hna_net.
133 olsr_delete_routing_table(&hna_net->hna_prefix.prefix, hna_net->hna_prefix.prefix_len, &tc->addr, OLSR_RT_ORIGIN_HNA);
136 * Remove from the per-tc tree.
138 avl_delete(&tc->hna_tree, &hna_net->hna_tc_node);
140 if (hna_net->hna_net_timer) {
141 olsr_timer_stop(hna_net->hna_net_timer);
142 hna_net->hna_net_timer = NULL;
147 olsr_memcookie_free(hna_net_mem_cookie, hna_net);
151 * Delete all the HNA nets hanging off a tc entry.
153 * @param entry the tc entry holding the HNA networks.
156 olsr_flush_hna_nets(struct tc_entry *tc)
158 struct hna_net *hna_net, *iterator;
160 #if !defined REMOVE_LOG_DEBUG
161 struct ipaddr_str buf;
164 OLSR_DEBUG(LOG_TC, "flush hna nets of '%s' (%u)\n", olsr_ip_to_string(&buf, &tc->addr), tc->edge_tree.count);
165 OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna_net, iterator) {
166 olsr_delete_hna_net(hna_net);
171 * Callback for the hna_net timer.
174 olsr_expire_hna_net_entry(void *context)
176 struct hna_net *hna_net = context;
177 #if !defined REMOVE_LOG_DEBUG
178 struct ipaddr_str buf;
179 struct ipprefix_str prefixstr;
182 OLSR_DEBUG(5, "HNA: timeout %s via hna-gw %s\n",
183 olsr_ip_prefix_to_string(&prefixstr, &hna_net->hna_prefix), olsr_ip_to_string(&buf, &hna_net->hna_tc->addr));
185 hna_net->hna_net_timer = NULL; /* be pedandic */
187 olsr_delete_hna_net(hna_net);
191 * Update a HNA entry. If it does not exist it
193 * This is the only function that should be called
194 * from outside concerning creation of HNA entries.
196 *@param gw address of the gateway
197 *@param net address of the network
198 *@param mask the netmask
199 *@param vtime the validitytime of the entry
204 olsr_update_hna_entry(const union olsr_ip_addr *gw, const struct olsr_ip_prefix *prefix, uint32_t vtime,
207 struct tc_entry *tc = olsr_locate_tc_entry(gw);
208 struct hna_net *net_entry = olsr_lookup_hna_net(tc, prefix);
210 if (net_entry == NULL) {
211 /* Need to add the net */
212 net_entry = olsr_add_hna_net(tc, prefix);
216 net_entry->tc_entry_seqno = msg_seq;
219 * Add the rt_path for the entry.
221 olsr_insert_routing_table(&net_entry->hna_prefix.prefix, net_entry->hna_prefix.prefix_len, &tc->addr, OLSR_RT_ORIGIN_HNA);
224 * Start, or refresh the timer, whatever is appropriate.
226 olsr_timer_set(&net_entry->hna_net_timer, vtime,
227 OLSR_HNA_NET_JITTER, net_entry, hna_net_timer_info);
231 * Print all HNA entries.
236 olsr_print_hna_set(void)
238 /* The whole function doesn't do anything else. */
239 #if !defined REMOVE_LOG_INFO
240 struct tc_entry *tc, *tc_iterator;
241 struct ipaddr_str buf;
242 struct ipprefix_str prefixstr;
243 struct timeval_buf timebuf;
244 struct hna_net *hna_net, *hna_iterator;
246 OLSR_INFO(LOG_HNA, "\n--- %s ------------------------------------------------- HNA\n\n",
247 olsr_timer_getWallclockString(&timebuf));
249 OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
250 OLSR_INFO_NH(LOG_HNA, "HNA-gw %s:\n", olsr_ip_to_string(&buf, &tc->addr));
252 OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna_net, hna_iterator) {
253 OLSR_INFO_NH(LOG_HNA, "\t%-27s\n", olsr_ip_prefix_to_string(&prefixstr, &hna_net->hna_prefix));
260 olsr_prune_hna_entries(struct tc_entry *tc)
262 struct hna_net *hna_net, *iterator;
264 OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna_net, iterator) {
265 if (hna_net->tc_entry_seqno != tc->hna_seq) {
266 olsr_delete_hna_net(hna_net);
272 * Process incoming HNA message.
273 * Forwards the message if that is to be done.
276 olsr_input_hna(struct olsr_message *msg,
277 struct interface *in_if __attribute__ ((unused)),
278 union olsr_ip_addr *from_addr, enum duplicate_status status)
281 struct olsr_ip_prefix prefix;
283 #if !defined REMOVE_LOG_DEBUG
284 struct ipaddr_str buf;
288 /* We are only interested in MID message types. */
289 if (msg->type != HNA_MESSAGE) {
294 * If the sender interface (NB: not originator) of this message
295 * is not in the symmetric 1-hop neighborhood of this node, the
296 * message MUST be discarded.
298 if (check_neighbor_link(from_addr) != SYM_LINK) {
299 OLSR_DEBUG(LOG_HNA, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
303 tc = olsr_locate_tc_entry(&msg->originator);
304 if (status != RESET_SEQNO_OLSR_MESSAGE && tc->hna_seq != -1 && olsr_seqno_diff(msg->seqno, tc->hna_seq) <= 0) {
305 /* this HNA is too old, discard it */
308 tc->hna_seq = msg->seqno;
310 OLSR_DEBUG(LOG_HNA, "Processing HNA from %s, seq 0x%04x\n", olsr_ip_to_string(&buf, &msg->originator), msg->seqno);
313 * Now walk the list of HNA advertisements.
316 while (curr + 2*olsr_cnf->ipsize <= msg->end) {
317 pkt_get_ipaddress(&curr, &prefix.prefix);
318 pkt_get_prefixlen(&curr, &prefix.prefix_len);
320 if (!ip_prefix_list_find(&olsr_cnf->hna_entries, &prefix.prefix, prefix.prefix_len, olsr_cnf->ip_version)) {
322 * Only update if it's not from us.
324 olsr_update_hna_entry(&msg->originator, &prefix, msg->vtime, msg->seqno);
329 * Prune the HNAs that did not get refreshed by this advertisment.
331 olsr_prune_hna_entries(tc);
335 generate_hna(void *p __attribute__ ((unused))) {
336 struct interface *ifp, *ifp_iterator;
337 struct ip_prefix_entry *h, *h_iterator;
338 uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE] __attribute__ ((aligned));
339 uint8_t *curr = msg_buffer;
340 uint8_t *length_field, *last;
341 bool sendHNA = false;
343 OLSR_INFO(LOG_PACKET_CREATION, "Building HNA\n-------------------\n");
345 pkt_put_u8(&curr, HNA_MESSAGE);
346 pkt_put_reltime(&curr, olsr_cnf->hna_params.validity_time);
349 pkt_put_u16(&curr, 0); /* put in real messagesize later */
351 pkt_put_ipaddress(&curr, &olsr_cnf->router_id);
353 pkt_put_u8(&curr, 255);
354 pkt_put_u8(&curr, 0);
355 pkt_put_u16(&curr, get_msg_seqno());
357 last = msg_buffer + sizeof(msg_buffer) - olsr_cnf->ipsize;
358 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, h, h_iterator) {
359 union olsr_ip_addr subnet;
361 olsr_prefix_to_netmask(&subnet, h->net.prefix_len);
363 pkt_put_ipaddress(&curr, &h->net.prefix);
364 pkt_put_ipaddress(&curr, &subnet);
371 pkt_put_u16(&length_field, curr - msg_buffer);
373 OLSR_FOR_ALL_INTERFACES(ifp, ifp_iterator) {
374 if (net_outbuffer_bytes_left(ifp) < curr - msg_buffer) {
376 set_buffer_timer(ifp);
378 net_outbuffer_push(ifp, msg_buffer, curr - msg_buffer);
385 * indent-tabs-mode: nil