Remove old routes before adding new routes on any OS but Linux. Always
[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.15 2004/12/03 18:43:34 tlopatic Exp $
40  */
41
42
43 #include "defs.h"
44 #include "olsr.h"
45 #include "kernel_routes.h"
46
47 #ifdef WIN32
48 #undef strerror
49 #define strerror(x) StrError(x)
50 #endif
51
52
53
54 int
55 olsr_init_old_table()
56 {
57   int index;
58
59   for(index=0;index<HASHSIZE;index++)
60     {
61       old_routes[index].next = &old_routes[index];
62       old_routes[index].prev = &old_routes[index];
63       old_hna[index].next = &old_hna[index];
64       old_hna[index].prev = &old_hna[index];
65     }
66
67   return 1;
68 }
69
70 /**
71  *Checks if there exists a route to a given host
72  *in a given hash table.
73  *
74  *@param dst the host to check for
75  *@param table the table to check
76  *
77  *@return 1 if the host exists in the table, 0 if not
78  */
79 int
80 olsr_find_up_route(struct rt_entry *dst, struct rt_entry *table)
81
82   struct rt_entry *destination;
83   olsr_u32_t      hash;
84  
85   hash = olsr_hashing(&dst->rt_dst);
86
87   for(destination = table[hash].next;
88       destination != &table[hash];
89       destination = destination->next)
90     {
91       //printf("Checking %s hc: %d ", olsr_ip_to_string(&dst->rt_dst), dst->rt_metric);
92       //printf("vs %s hc: %d ... ", olsr_ip_to_string(&destination->rt_dst), destination->rt_metric);      
93       if (COMP_IP(&destination->rt_dst, &dst->rt_dst) &&
94           COMP_IP(&destination->rt_router, &dst->rt_router) &&
95           (destination->rt_if->if_nr == dst->rt_if->if_nr))
96         {
97           if(destination->rt_metric == dst->rt_metric)
98             {
99               return 1;
100             }
101           else
102             {
103               return 0;
104             }
105         }
106     }
107
108   return 0;
109
110 }
111
112
113 /**
114  *Create a list containing the entries in in_table
115  *that does not exist in from_table
116  *
117  *@param from_table the table to use
118  *@param in_table the routes already added
119  *
120  *@return a poiter to a linked list of routes to add
121  */
122 struct destination_n *
123 olsr_build_update_list(struct rt_entry *from_table,struct rt_entry *in_table)
124 {
125   struct destination_n *kernel_route_list = NULL;
126   struct destination_n *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               
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   //#warning deletion and addition of routes swapped in 0.4.7 - TEST!
219 #if !defined linux
220   olsr_delete_routes_from_kernel(delete_kernel_list);
221   olsr_add_routes_in_kernel(add_kernel_list);
222 #else
223   olsr_add_routes_in_kernel(add_kernel_list);
224   olsr_delete_routes_from_kernel(delete_kernel_list);
225 #endif
226 }
227
228
229
230 /**
231  *Perform all neccessary actions for an update of the 
232  *HNA routes in the kernel.
233  *
234  *@return nada
235  */
236 void
237 olsr_update_kernel_hna_routes()
238 {
239   struct destination_n *delete_kernel_list = NULL;
240   //struct destination_n *delete_kernel_list2;
241   struct destination_n *add_kernel_list = NULL;
242
243   olsr_printf(3, "Updating kernel HNA routes...\n");
244
245
246   delete_kernel_list = olsr_build_update_list(old_hna, hna_routes);
247   add_kernel_list = olsr_build_update_list(hna_routes, old_hna);
248
249   olsr_delete_routes_from_kernel(delete_kernel_list);
250   olsr_add_routes_in_kernel(add_kernel_list);
251 }
252
253
254 /**
255  *Create a copy of the routing table and
256  *clear the current table
257  *
258  *@param original the table to move from
259  *@param the table to move to
260  *
261  *@return nada
262  */
263 void
264 olsr_move_route_table(struct rt_entry *original, struct rt_entry *new)
265 {
266   olsr_16_t index;
267
268   for(index=0;index<HASHSIZE;index++)
269     {
270       if(original[index].next == &original[index])
271         {
272           new[index].next = &new[index];
273           new[index].prev = &new[index];
274         }
275       else
276         {
277           /* Copy to old */
278           new[index].next = original[index].next;
279           new[index].next->prev = &new[index];
280           new[index].prev = original[index].prev;
281           new[index].prev->next = &new[index];
282
283           /* Clear original */
284           original[index].next = &original[index];
285           original[index].prev = &original[index];
286         }
287     }
288 }
289
290
291 /**
292  *Delete a linked list of routes from the kernel.
293  *
294  *@param delete_kernel_list the list to delete
295  *
296  *@return nada
297  */
298 void 
299 olsr_delete_routes_from_kernel(struct destination_n *delete_kernel_list)
300 {
301   struct destination_n *destination_kernel;
302   olsr_16_t error;
303
304   while(delete_kernel_list!=NULL)
305     {
306       if(olsr_cnf->ip_version == AF_INET)
307         {
308           /* IPv4 */
309           error = olsr_ioctl_del_route(delete_kernel_list->destination);
310         }
311       else
312         {
313           /* IPv6 */
314           error = olsr_ioctl_del_route6(delete_kernel_list->destination);
315         }
316
317
318       if(error < 0)
319         {
320           olsr_printf(1, "Delete route:%s\n", strerror(errno));
321           olsr_syslog(OLSR_LOG_ERR, "Delete route:%m");
322         }
323
324       destination_kernel=delete_kernel_list;
325       delete_kernel_list=delete_kernel_list->next;
326       
327       free(destination_kernel);
328     }
329
330
331   
332 }
333
334 /**
335  *Add a list of routes to the kernel. Adding
336  *is done by hopcount to be sure a route
337  *to the nexthop is added.
338  *
339  *@param add_kernel_list the linked list of routes to add
340  *
341  *@return nada
342  */
343 void 
344 olsr_add_routes_in_kernel(struct destination_n *add_kernel_list)
345 {
346   struct destination_n *destination_kernel = NULL;
347   struct destination_n *previous_node = add_kernel_list;
348   olsr_16_t error;
349   int metric_counter = 0, first_run = 1;
350   //char str[46];
351   
352   //printf("Calculating routes\n");
353   
354   while(add_kernel_list != NULL)
355     {
356       //searching for all the items with metric equal to n
357       for(destination_kernel = add_kernel_list; destination_kernel != NULL; )
358         {
359           if((destination_kernel->destination->rt_metric == metric_counter) &&
360              ((first_run && 
361                COMP_IP(&destination_kernel->destination->rt_dst, &destination_kernel->destination->rt_router)) || !first_run))
362             {
363               /* First add all 1-hop routes that has themselves as GW */
364
365               if(olsr_cnf->ip_version == AF_INET)
366                 error=olsr_ioctl_add_route(destination_kernel->destination);
367               else
368                 error=olsr_ioctl_add_route6(destination_kernel->destination);
369                     
370               if(error < 0) //print the error msg
371                 {
372                   olsr_printf(1, "Add route(%s): %s\n", olsr_ip_to_string(&destination_kernel->destination->rt_dst), strerror(errno));
373                   olsr_syslog(OLSR_LOG_ERR, "Add route:%m");
374                 }
375                     
376               //getting rid of this node and hooking up the broken point
377               if(destination_kernel == add_kernel_list) 
378                 {
379                   destination_kernel = add_kernel_list->next;
380                   free(add_kernel_list);
381                   add_kernel_list = destination_kernel;
382                   previous_node=add_kernel_list;
383                 }
384               else 
385                 {
386                   previous_node->next = destination_kernel->next;
387                   free(destination_kernel);
388                   destination_kernel = previous_node->next;
389                 }
390             }
391           else 
392             {
393               previous_node = destination_kernel;
394               destination_kernel = destination_kernel->next;
395             }
396                 
397         }
398       if(first_run)
399         first_run = 0;
400       else
401         ++metric_counter;
402     }
403         
404 }
405
406
407