Various headerfile inclusion cleanups
[olsrd.git] / src / process_routes.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  * $Id: process_routes.c,v 1.22 2005/02/27 18:39:43 kattemat Exp $
40  */
41
42
43 #include "defs.h"
44 #include "olsr.h"
45 #include "log.h"
46 #include "kernel_routes.h"
47
48 #ifdef WIN32
49 #undef strerror
50 #define strerror(x) StrError(x)
51 #endif
52
53
54
55 int
56 olsr_init_old_table()
57 {
58   int index;
59
60   for(index=0;index<HASHSIZE;index++)
61     {
62       old_routes[index].next = &old_routes[index];
63       old_routes[index].prev = &old_routes[index];
64       old_hna[index].next = &old_hna[index];
65       old_hna[index].prev = &old_hna[index];
66     }
67
68   return 1;
69 }
70
71 /**
72  *Checks if there exists a route to a given host
73  *in a given hash table.
74  *
75  *@param dst the host to check for
76  *@param table the table to check
77  *
78  *@return 1 if the host exists in the table, 0 if not
79  */
80 int
81 olsr_find_up_route(struct rt_entry *dst, struct rt_entry *table)
82
83   struct rt_entry *destination;
84   olsr_u32_t      hash;
85  
86   hash = olsr_hashing(&dst->rt_dst);
87
88   for(destination = table[hash].next;
89       destination != &table[hash];
90       destination = destination->next)
91     {
92       //printf("Checking %s hc: %d ", olsr_ip_to_string(&dst->rt_dst), dst->rt_metric);
93       //printf("vs %s hc: %d ... ", olsr_ip_to_string(&destination->rt_dst), destination->rt_metric);      
94       if (COMP_IP(&destination->rt_dst, &dst->rt_dst) &&
95           COMP_IP(&destination->rt_router, &dst->rt_router) &&
96           (destination->rt_if->if_nr == dst->rt_if->if_nr))
97         {
98           if(destination->rt_metric == dst->rt_metric)
99             {
100               return 1;
101             }
102           else
103             {
104               return 0;
105             }
106         }
107     }
108
109   return 0;
110
111 }
112
113
114 /**
115  *Create a list containing the entries in in_table
116  *that does not exist in from_table
117  *
118  *@param from_table the table to use
119  *@param in_table the routes already added
120  *
121  *@return a poiter to a linked list of routes to add
122  */
123 struct destination_n *
124 olsr_build_update_list(struct rt_entry *from_table,struct rt_entry *in_table)
125 {
126   struct destination_n *kernel_route_list = NULL;
127   struct rt_entry      *destination;
128   olsr_u8_t            index;
129   
130   for(index=0;index<HASHSIZE;index++)
131     {
132       for(destination = from_table[index].next;
133           destination != &from_table[index];
134           destination = destination->next)
135         {
136           if (!olsr_find_up_route(destination, in_table))
137             {
138               struct destination_n *route_list;
139               route_list = olsr_malloc(sizeof(struct destination_n), "create route tmp list");
140               
141               route_list->destination = destination;
142               
143               route_list->next = kernel_route_list;
144               kernel_route_list = route_list;
145             }
146         }   
147     }
148   
149   return (kernel_route_list);
150 }
151
152
153
154
155
156 /**
157  *Deletes all OLSR routes
158  *
159  *
160  *@return 1
161  */
162 int
163 olsr_delete_all_kernel_routes()
164
165   struct destination_n *delete_kernel_list = NULL;
166   struct destination_n *tmp = NULL;
167   union olsr_ip_addr *tmp_addr;
168
169   OLSR_PRINTF(1, "Deleting all routes...\n")
170
171   delete_kernel_list = olsr_build_update_list(hna_routes, old_hna);
172
173   tmp = delete_kernel_list;
174
175   OLSR_PRINTF(1, "HNA list:\n")
176   while(tmp)
177     {
178       tmp_addr = &tmp->destination->rt_dst;
179       OLSR_PRINTF(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr))
180       tmp = tmp->next;
181     }
182
183   olsr_delete_routes_from_kernel(delete_kernel_list);
184
185   delete_kernel_list = olsr_build_update_list(routingtable,old_routes);
186
187   tmp = delete_kernel_list;
188
189   OLSR_PRINTF(1, "Route list:\n")
190   while(tmp)
191     {
192       tmp_addr = &tmp->destination->rt_dst;
193       OLSR_PRINTF(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr))
194       tmp = tmp->next;
195     }
196
197   olsr_delete_routes_from_kernel(delete_kernel_list);
198
199   return 1;
200 }
201
202
203 /**
204  *Perform all neccessary actions for an update of the 
205  *routes in the kernel.
206  *
207  *@return nada
208  */
209 void
210 olsr_update_kernel_routes()
211 {
212   struct destination_n *delete_kernel_list = NULL;
213   struct destination_n *add_kernel_list = NULL;
214   
215   OLSR_PRINTF(3, "Updating kernel routes...\n")
216   delete_kernel_list = olsr_build_update_list(old_routes, routingtable);
217   add_kernel_list = olsr_build_update_list(routingtable, old_routes);
218
219   olsr_delete_routes_from_kernel(delete_kernel_list);
220   olsr_add_routes_in_kernel(add_kernel_list);
221 }
222
223
224
225 /**
226  *Perform all neccessary actions for an update of the 
227  *HNA routes in the kernel.
228  *
229  *@return nada
230  */
231 void
232 olsr_update_kernel_hna_routes()
233 {
234   struct destination_n *delete_kernel_list = NULL;
235   //struct destination_n *delete_kernel_list2;
236   struct destination_n *add_kernel_list = NULL;
237
238   OLSR_PRINTF(3, "Updating kernel HNA routes...\n")
239
240
241   delete_kernel_list = olsr_build_update_list(old_hna, hna_routes);
242   add_kernel_list = olsr_build_update_list(hna_routes, old_hna);
243
244   olsr_delete_routes_from_kernel(delete_kernel_list);
245   olsr_add_routes_in_kernel(add_kernel_list);
246 }
247
248
249 /**
250  *Create a copy of the routing table and
251  *clear the current table
252  *
253  *@param original the table to move from
254  *@param the table to move to
255  *
256  *@return nada
257  */
258 void
259 olsr_move_route_table(struct rt_entry *original, struct rt_entry *new)
260 {
261   olsr_16_t index;
262
263   for(index=0;index<HASHSIZE;index++)
264     {
265       if(original[index].next == &original[index])
266         {
267           new[index].next = &new[index];
268           new[index].prev = &new[index];
269         }
270       else
271         {
272           /* Copy to old */
273           new[index].next = original[index].next;
274           new[index].next->prev = &new[index];
275           new[index].prev = original[index].prev;
276           new[index].prev->next = &new[index];
277
278           /* Clear original */
279           original[index].next = &original[index];
280           original[index].prev = &original[index];
281         }
282     }
283 }
284
285
286 /**
287  *Delete a linked list of routes from the kernel.
288  *
289  *@param delete_kernel_list the list to delete
290  *
291  *@return nada
292  */
293 void 
294 olsr_delete_routes_from_kernel(struct destination_n *delete_kernel_list)
295 {
296   struct destination_n *destination_ptr;
297   int metric_counter = 1;
298   olsr_bool last_run = OLSR_FALSE;
299
300   /* Find highest metric */
301   for(destination_ptr = delete_kernel_list;
302       destination_ptr != NULL;
303       destination_ptr = destination_ptr->next)
304     {
305       if(destination_ptr->destination->rt_metric > metric_counter)
306         metric_counter = destination_ptr->destination->rt_metric;
307     }
308 #ifdef DEBUG
309   OLSR_PRINTF(3, "%s highest metric %d\n",
310               __func__, metric_counter)
311 #endif
312  
313   while(delete_kernel_list!=NULL)
314     {
315       struct destination_n *previous_node = delete_kernel_list;
316
317       /* searching for all the items with metric equal to n */
318       for(destination_ptr = delete_kernel_list; destination_ptr != NULL; )
319         {
320
321           if((destination_ptr->destination->rt_metric == metric_counter) &&
322              ((last_run || 
323                !COMP_IP(&destination_ptr->destination->rt_dst, 
324                         &destination_ptr->destination->rt_router))))
325             {
326               olsr_16_t error;
327 #ifdef DEBUG
328               OLSR_PRINTF(3, "Deleting route to %s hopcount %d\n",
329                           olsr_ip_to_string(&destination_ptr->destination->rt_dst),
330                           destination_ptr->destination->rt_metric)
331 #endif
332               
333               if(olsr_cnf->ip_version == AF_INET)
334                 error = olsr_ioctl_del_route(destination_ptr->destination);
335               else
336                 error = olsr_ioctl_del_route6(destination_ptr->destination);
337               
338               if(error < 0)
339                 {
340                   OLSR_PRINTF(1, "Delete route(%s):%s\n", olsr_ip_to_string(&destination_ptr->destination->rt_dst), strerror(errno))
341                   olsr_syslog(OLSR_LOG_ERR, "Delete route:%m");
342                 }
343               
344               /* Getting rid of this node and hooking up the broken point */
345               if(destination_ptr == delete_kernel_list) 
346                 {
347                   destination_ptr = delete_kernel_list->next;
348                   free(delete_kernel_list);
349                   delete_kernel_list = destination_ptr;
350                   previous_node = delete_kernel_list;
351                 }
352               else 
353                 {
354                   previous_node->next = destination_ptr->next;
355                   free(destination_ptr);
356                   destination_ptr = previous_node->next;
357                 }
358             }
359           else 
360             {
361               previous_node = destination_ptr;
362               destination_ptr = destination_ptr->next;
363             }
364                 
365         }
366       if((metric_counter == 1) && !last_run)
367         last_run = OLSR_TRUE;
368       else
369         metric_counter--;
370       
371     }
372  
373 }
374
375 /**
376  *Add a list of routes to the kernel. Adding
377  *is done by hopcount to be sure a route
378  *to the nexthop is added.
379  *
380  *@param add_kernel_list the linked list of routes to add
381  *
382  *@return nada
383  */
384 void 
385 olsr_add_routes_in_kernel(struct destination_n *add_kernel_list)
386 {
387   int metric_counter = 1;
388   olsr_bool first_run = OLSR_TRUE;
389   
390   while(add_kernel_list != NULL)
391     {
392       struct destination_n *destination_kernel = NULL;
393       struct destination_n *previous_node = add_kernel_list;
394
395       /* searching for all the items with metric equal to n */
396       for(destination_kernel = add_kernel_list; destination_kernel != NULL; )
397         {
398           if((destination_kernel->destination->rt_metric == metric_counter) &&
399              (!first_run || 
400               COMP_IP(&destination_kernel->destination->rt_dst,
401                       &destination_kernel->destination->rt_router)))
402             {
403               olsr_16_t error;
404               /* First add all 1-hop routes that has themselves as GW */
405
406 #ifdef DEBUG
407               OLSR_PRINTF(3, "Adding route to %s hopcount %d\n",
408                           olsr_ip_to_string(&destination_kernel->destination->rt_dst),
409                           destination_kernel->destination->rt_metric)
410 #endif
411                           
412               if(olsr_cnf->ip_version == AF_INET)
413                 error=olsr_ioctl_add_route(destination_kernel->destination);
414               else
415                 error=olsr_ioctl_add_route6(destination_kernel->destination);
416               
417               if(error < 0)
418                 {
419                   OLSR_PRINTF(1, "Add route(%s): %s\n", olsr_ip_to_string(&destination_kernel->destination->rt_dst), strerror(errno))
420                   olsr_syslog(OLSR_LOG_ERR, "Add route:%m");
421                 }
422               
423               /* Getting rid of this node and hooking up the broken point */
424               if(destination_kernel == add_kernel_list) 
425                 {
426                   destination_kernel = add_kernel_list->next;
427                   free(add_kernel_list);
428                   add_kernel_list = destination_kernel;
429                   previous_node=add_kernel_list;
430                 }
431               else 
432                 {
433                   previous_node->next = destination_kernel->next;
434                   free(destination_kernel);
435                   destination_kernel = previous_node->next;
436                 }
437             }
438           else 
439             {
440               previous_node = destination_kernel;
441               destination_kernel = destination_kernel->next;
442             }
443                 
444         }
445       if(first_run)
446         first_run = OLSR_FALSE;
447       else
448         metric_counter++;
449     }
450         
451 }
452
453
454