add a cookie for HNA networks to ease troubleshooting
[olsrd.git] / src / hna_set.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "ipcalc.h"
42 #include "defs.h"
43 #include "olsr.h"
44 #include "scheduler.h"
45 #include "net_olsr.h"
46 #include "tc_set.h"
47
48
49 struct hna_entry hna_set[HASHSIZE];
50 struct olsr_cookie_info *hna_net_timer_cookie = NULL;
51
52 /**
53  * Initialize the HNA set
54  */
55 int
56 olsr_init_hna_set(void)
57 {
58   int idx;
59
60   for(idx=0;idx<HASHSIZE;idx++) {
61     hna_set[idx].next = &hna_set[idx];
62     hna_set[idx].prev = &hna_set[idx];
63   }
64
65   hna_net_timer_cookie =
66     olsr_alloc_cookie("HNA Network", OLSR_COOKIE_TYPE_TIMER);
67
68   return 1;
69 }
70
71 /**
72  *Lookup a network entry in a networkentry list
73  *
74  *@param nets the network list to look in
75  *@param net the network to look for
76  *@param mask the netmask to look for
77  *
78  *@return the localted entry or NULL of not found
79  */
80 struct hna_net *
81 olsr_lookup_hna_net(const struct hna_net *nets, const union olsr_ip_addr *net,
82                     olsr_u8_t prefixlen)
83 {
84   struct hna_net *tmp;
85   /* Loop trough entrys */
86   for (tmp = nets->next; tmp != nets; tmp = tmp->next) { 
87     if (tmp->prefixlen == prefixlen && ipequal(&tmp->A_network_addr, net)) {
88       return tmp;
89     }
90   }
91   /* Not found */
92   return NULL;
93 }
94
95
96 /**
97  * Lookup a gateway entry
98  *
99  * @param gw the address of the gateway
100  * @return the located entry or NULL if not found
101  */
102 struct hna_entry *
103 olsr_lookup_hna_gw(const union olsr_ip_addr *gw)
104 {
105   struct hna_entry *tmp_hna;
106   olsr_u32_t hash = olsr_ip_hashing(gw);
107
108 #if 0
109   OLSR_PRINTF(5, "HNA: lookup entry\n");
110 #endif
111     /* Check for registered entry */
112
113   for(tmp_hna = hna_set[hash].next;
114       tmp_hna != &hna_set[hash];
115       tmp_hna = tmp_hna->next) {
116     if(ipequal(&tmp_hna->A_gateway_addr, gw)) {
117       return tmp_hna;
118     }
119   }
120   
121   /* Not found */
122   return NULL;
123 }
124
125
126
127 /**
128  *Add a gatewayentry to the HNA set
129  *
130  *@param addr the address of the gateway
131  *
132  *@return the created entry
133  */
134 struct hna_entry *
135 olsr_add_hna_entry(const union olsr_ip_addr *addr)
136 {
137   struct hna_entry *new_entry;
138   olsr_u32_t hash;
139
140   new_entry = olsr_malloc(sizeof(struct hna_entry), "New HNA entry");
141
142   /* Fill struct */
143   new_entry->A_gateway_addr = *addr;
144
145   /* Link nets */
146   new_entry->networks.next = &new_entry->networks;
147   new_entry->networks.prev = &new_entry->networks;
148
149   /* queue */
150   hash = olsr_ip_hashing(addr);
151   
152   hna_set[hash].next->prev = new_entry;
153   new_entry->next = hna_set[hash].next;
154   hna_set[hash].next = new_entry;
155   new_entry->prev = &hna_set[hash];
156
157   return new_entry;
158
159 }
160
161
162
163 /**
164  *Adds a ntework entry to a HNA gateway
165  *
166  *@param hna_gw the gateway entry to add the
167  *network to
168  *@param net the networkaddress to add
169  *@param mask the netmask
170  *
171  *@return the newly created entry
172  */
173 struct hna_net *
174 olsr_add_hna_net(struct hna_entry *hna_gw, const union olsr_ip_addr *net, olsr_u8_t prefixlen)
175 {
176   /* Add the net */
177   struct hna_net *new_net = olsr_malloc(sizeof(struct hna_net), "Add HNA net");
178   
179   /* Fill struct */
180   memset(new_net, 0, sizeof(struct hna_net));
181   new_net->A_network_addr = *net;
182   new_net->prefixlen = prefixlen;
183
184   /* Set backpointer */
185   new_net->hna_gw = hna_gw;
186
187   /* Queue */
188   hna_gw->networks.next->prev = new_net;
189   new_net->next = hna_gw->networks.next;
190   hna_gw->networks.next = new_net;
191   new_net->prev = &hna_gw->networks;
192
193   /*
194    * Add the rt_path for the entry.
195    */
196   olsr_insert_routing_table(&new_net->A_network_addr,
197                             new_net->prefixlen,
198                             &hna_gw->A_gateway_addr,
199                             OLSR_RT_ORIGIN_HNA);
200
201   return new_net;
202 }
203
204 /**
205  * Callback for the hna_net timer.
206  */
207 static void
208 olsr_expire_hna_net_entry(void *context)
209 {
210 #if !defined(NODEBUG) && defined(DEBUG)
211   struct ipaddr_str buf1, buf2;
212 #endif
213   struct hna_net *net_to_delete;
214   struct hna_entry *hna_gw;
215
216   net_to_delete = (struct hna_net *)context;
217   net_to_delete->hna_net_timer = NULL; /* be pedandic */
218   hna_gw = net_to_delete->hna_gw;
219
220 #ifdef DEBUG
221   OLSR_PRINTF(5, "HNA: timeout %s/%u via hna-gw %s\n", 
222               olsr_ip_to_string(&buf1, &net_to_delete->A_network_addr),
223               net_to_delete->prefixlen,
224               olsr_ip_to_string(&buf2, &hna_gw->A_gateway_addr));
225 #endif
226
227   /*
228    * Delete the rt_path for the entry.
229    */
230   olsr_delete_routing_table(&net_to_delete->A_network_addr,
231                             net_to_delete->prefixlen,
232                             &hna_gw->A_gateway_addr);
233
234
235   /* Delete hna_gw if empty */
236   if (hna_gw->networks.next == &hna_gw->networks) {
237     DEQUEUE_ELEM(hna_gw);
238     free(hna_gw);
239   }
240 }
241
242 /**
243  * Update a HNA entry. If it does not exist it
244  * is created.
245  * This is the only function that should be called 
246  * from outside concerning creation of HNA entries.
247  *
248  *@param gw address of the gateway
249  *@param net address of the network
250  *@param mask the netmask
251  *@param vtime the validitytime of the entry
252  *
253  *@return nada
254  */
255 void
256 olsr_update_hna_entry(const union olsr_ip_addr *gw, const union olsr_ip_addr *net,
257                       olsr_u8_t prefixlen, olsr_reltime vtime)
258 {
259   struct hna_entry *gw_entry;
260   struct hna_net *net_entry;
261
262   gw_entry = olsr_lookup_hna_gw(gw);
263   if (!gw_entry) {
264
265     /* Need to add the entry */
266     gw_entry = olsr_add_hna_entry(gw);
267   }
268
269   net_entry = olsr_lookup_hna_net(&gw_entry->networks, net, prefixlen);
270   if (net_entry == NULL)  {
271
272     /* Need to add the net */
273     net_entry = olsr_add_hna_net(gw_entry, net, prefixlen);
274     changes_hna = OLSR_TRUE;
275   }
276
277   olsr_set_timer(&net_entry->hna_net_timer, vtime,
278                  OLSR_HNA_NET_JITTER, OLSR_TIMER_ONESHOT,
279                  &olsr_expire_hna_net_entry, net_entry,
280                  hna_net_timer_cookie);
281 }
282
283
284 /**
285  * Print all HNA entries.
286  *
287  *@return nada
288  */
289 void
290 olsr_print_hna_set(void)
291 {
292 #ifdef NODEBUG
293   /* The whole function doesn't do anything else. */
294   int idx;
295
296   OLSR_PRINTF(1, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- HNA SET\n\n",
297               nowtm->tm_hour,
298               nowtm->tm_min,
299               nowtm->tm_sec,
300               (int)now.tv_usec/10000);
301   
302   if(olsr_cnf->ip_version == AF_INET)
303     OLSR_PRINTF(1, "IP net          netmask         GW IP\n");
304   else
305     OLSR_PRINTF(1, "IP net/prefixlen               GW IP\n");
306
307   for(idx=0;idx<HASHSIZE;idx++)
308     {
309       struct hna_entry *tmp_hna = hna_set[idx].next;
310       /* Check all entrys */
311       while(tmp_hna != &hna_set[idx])
312         {
313           /* Check all networks */
314           struct hna_net *tmp_net = tmp_hna->networks.next;
315
316           while(tmp_net != &tmp_hna->networks)
317             {
318               if(olsr_cnf->ip_version == AF_INET)
319                 {
320 #ifndef NODEBUG
321                   struct ipaddr_str buf;
322 #endif
323                   OLSR_PRINTF(1, "%-15s ", olsr_ip_to_string(&buf, &tmp_net->A_network_addr));
324                   OLSR_PRINTF(1, "%-15d ", tmp_net->prefix_len);
325                   OLSR_PRINTF(1, "%-15s\n", olsr_ip_to_string(&buf, &tmp_hna->A_gateway_addr));
326                 }
327               else
328                 {
329 #ifndef NODEBUG
330                   struct ipaddr_str buf;
331 #endif
332                   OLSR_PRINTF(1, "%-27s/%d", olsr_ip_to_string(&buf, &tmp_net->A_network_addr), tmp_net->A_netmask.v6);
333                   OLSR_PRINTF(1, "%s\n", olsr_ip_to_string(&buf, &tmp_hna->A_gateway_addr));
334                 }
335
336               tmp_net = tmp_net->next;
337             }
338           tmp_hna = tmp_hna->next;
339         }
340     }
341 #endif
342 }
343
344 /*
345  * Local Variables:
346  * c-basic-offset: 2
347  * End:
348  */