Licence change... man that was boring work...
[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.14 2004/11/21 11:28:56 kattemat 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   olsr_add_routes_in_kernel(add_kernel_list);
220   olsr_delete_routes_from_kernel(delete_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_kernel;
297   olsr_16_t error;
298
299   while(delete_kernel_list!=NULL)
300     {
301       if(olsr_cnf->ip_version == AF_INET)
302         {
303           /* IPv4 */
304           error = olsr_ioctl_del_route(delete_kernel_list->destination);
305         }
306       else
307         {
308           /* IPv6 */
309           error = olsr_ioctl_del_route6(delete_kernel_list->destination);
310         }
311
312
313       if(error < 0)
314         {
315           olsr_printf(1, "Delete route:%s\n", strerror(errno));
316           olsr_syslog(OLSR_LOG_ERR, "Delete route:%m");
317         }
318
319       destination_kernel=delete_kernel_list;
320       delete_kernel_list=delete_kernel_list->next;
321       
322       free(destination_kernel);
323     }
324
325
326   
327 }
328
329 /**
330  *Add a list of routes to the kernel. Adding
331  *is done by hopcount to be sure a route
332  *to the nexthop is added.
333  *
334  *@param add_kernel_list the linked list of routes to add
335  *
336  *@return nada
337  */
338 void 
339 olsr_add_routes_in_kernel(struct destination_n *add_kernel_list)
340 {
341   struct destination_n *destination_kernel = NULL;
342   struct destination_n *previous_node = add_kernel_list;
343   olsr_16_t error;
344   int metric_counter = 0, first_run = 1;
345   //char str[46];
346   
347   //printf("Calculating routes\n");
348   
349   while(add_kernel_list != NULL)
350     {
351       //searching for all the items with metric equal to n
352       for(destination_kernel = add_kernel_list; destination_kernel != NULL; )
353         {
354           if((destination_kernel->destination->rt_metric == metric_counter) &&
355              ((first_run && 
356                COMP_IP(&destination_kernel->destination->rt_dst, &destination_kernel->destination->rt_router)) || !first_run))
357             {
358               /* First add all 1-hop routes that has themselves as GW */
359
360               if(olsr_cnf->ip_version == AF_INET)
361                 error=olsr_ioctl_add_route(destination_kernel->destination);
362               else
363                 error=olsr_ioctl_add_route6(destination_kernel->destination);
364                     
365               if(error < 0) //print the error msg
366                 {
367                   olsr_printf(1, "Add route(%s): %s\n", olsr_ip_to_string(&destination_kernel->destination->rt_dst), strerror(errno));
368                   olsr_syslog(OLSR_LOG_ERR, "Add route:%m");
369                 }
370                     
371               //getting rid of this node and hooking up the broken point
372               if(destination_kernel == add_kernel_list) 
373                 {
374                   destination_kernel = add_kernel_list->next;
375                   free(add_kernel_list);
376                   add_kernel_list = destination_kernel;
377                   previous_node=add_kernel_list;
378                 }
379               else 
380                 {
381                   previous_node->next = destination_kernel->next;
382                   free(destination_kernel);
383                   destination_kernel = previous_node->next;
384                 }
385             }
386           else 
387             {
388               previous_node = destination_kernel;
389               destination_kernel = destination_kernel->next;
390             }
391                 
392         }
393       if(first_run)
394         first_run = 0;
395       else
396         ++metric_counter;
397     }
398         
399 }
400
401
402