af3f63996fec602f8eba1b5ec957c1e9ed7510ca
[olsrd.git] / src / process_routes.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas Tønnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: process_routes.c,v 1.11 2004/11/05 02:06:14 tlopatic Exp $
23  *
24  */
25
26
27 #include "defs.h"
28 #include "olsr.h"
29 #include "kernel_routes.h"
30
31 #ifdef linux
32 #include "linux/tunnel.h"
33 #elif defined WIN32
34 #include "win32/tunnel.h"
35 #undef strerror
36 #define strerror(x) StrError(x)
37 #elif defined __FreeBSD__
38 #else
39 #       error "Unsupported system"
40 #endif
41
42
43
44 int
45 olsr_init_old_table()
46 {
47   int index;
48
49   for(index=0;index<HASHSIZE;index++)
50     {
51       old_routes[index].next = &old_routes[index];
52       old_routes[index].prev = &old_routes[index];
53       old_hna[index].next = &old_hna[index];
54       old_hna[index].prev = &old_hna[index];
55     }
56
57   return 1;
58 }
59
60 /**
61  *Checks if there exists a route to a given host
62  *in a given hash table.
63  *
64  *@param dst the host to check for
65  *@param table the table to check
66  *
67  *@return 1 if the host exists in the table, 0 if not
68  */
69 int
70 olsr_find_up_route(struct rt_entry *dst, struct rt_entry *table)
71
72   struct rt_entry *destination;
73   olsr_u32_t      hash;
74  
75   hash = olsr_hashing(&dst->rt_dst);
76
77   for(destination = table[hash].next;
78       destination != &table[hash];
79       destination = destination->next)
80     {
81       //printf("Checking %s hc: %d ", olsr_ip_to_string(&dst->rt_dst), dst->rt_metric);
82       //printf("vs %s hc: %d ... ", olsr_ip_to_string(&destination->rt_dst), destination->rt_metric);      
83       if (COMP_IP(&destination->rt_dst, &dst->rt_dst) &&
84           COMP_IP(&destination->rt_router, &dst->rt_router) &&
85           (destination->rt_if->if_nr == dst->rt_if->if_nr))
86         {
87           if(destination->rt_metric == dst->rt_metric)
88             {
89               return 1;
90             }
91           else
92             {
93               return 0;
94             }
95         }
96     }
97
98   return 0;
99
100 }
101
102
103 /**
104  *Create a list containing the entries in in_table
105  *that does not exist in from_table
106  *
107  *@param from_table the table to use
108  *@param in_table the routes already added
109  *
110  *@return a poiter to a linked list of routes to add
111  */
112 struct destination_n *
113 olsr_build_update_list(struct rt_entry *from_table,struct rt_entry *in_table)
114 {
115   struct destination_n *kernel_route_list = NULL;
116   struct destination_n *route_list = NULL;
117   struct rt_entry      *destination;
118   olsr_u8_t            index;
119   
120   for(index=0;index<HASHSIZE;index++)
121     {
122       for(destination = from_table[index].next;
123           destination != &from_table[index];
124           destination = destination->next)
125         {
126           if (!olsr_find_up_route(destination, in_table))
127             {
128               
129               route_list = olsr_malloc(sizeof(struct destination_n), "create route tmp list");
130               
131               route_list->destination = destination;
132               
133               route_list->next = kernel_route_list;
134               kernel_route_list = route_list;
135             }
136         }   
137     }
138   
139   return (kernel_route_list);
140 }
141
142
143
144
145
146 /**
147  *Deletes all OLSR routes
148  *
149  *
150  *@return 1
151  */
152 int
153 olsr_delete_all_kernel_routes()
154
155   struct destination_n *delete_kernel_list=NULL;
156   struct destination_n *tmp=NULL;
157   union olsr_ip_addr *tmp_addr;
158 #ifndef __FreeBSD__
159   olsr_u32_t tmp_tnl_addr;
160 #endif
161
162   olsr_printf(1, "Deleting all routes...\n");
163
164 #ifndef __FreeBSD__
165   if(use_tunnel)
166     {
167       /* Delete Internet GW tunnel */
168       delete_tunnel_route();
169       /* Take down tunnel */
170       del_ip_tunnel(&ipt);
171       tmp_tnl_addr = 0;
172       set_up_gw_tunnel((union olsr_ip_addr *)&tmp_tnl_addr);
173     }
174 #endif
175
176   delete_kernel_list = olsr_build_update_list(hna_routes, old_hna);
177
178   tmp = delete_kernel_list;
179
180   olsr_printf(1, "HNA list:\n");
181   while(tmp)
182     {
183       tmp_addr = &tmp->destination->rt_dst;
184       olsr_printf(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr));
185       tmp = tmp->next;
186     }
187
188   olsr_delete_routes_from_kernel(delete_kernel_list);
189
190   delete_kernel_list = olsr_build_update_list(routingtable,old_routes);
191
192   tmp = delete_kernel_list;
193
194   olsr_printf(1, "Route list:\n");
195   while(tmp)
196     {
197       tmp_addr = &tmp->destination->rt_dst;
198       olsr_printf(1, "Dest: %s\n", olsr_ip_to_string(tmp_addr));
199       tmp = tmp->next;
200     }
201
202   olsr_delete_routes_from_kernel(delete_kernel_list);
203
204   return 1;
205 }
206
207
208 /**
209  *Perform all neccessary actions for an update of the 
210  *routes in the kernel.
211  *
212  *@return nada
213  */
214 void
215 olsr_update_kernel_routes()
216 {
217   struct destination_n *delete_kernel_list = NULL;
218   struct destination_n *add_kernel_list = NULL;
219   
220   olsr_printf(3, "Updating kernel routes...\n");
221   delete_kernel_list = olsr_build_update_list(old_routes, routingtable);
222   add_kernel_list = olsr_build_update_list(routingtable, old_routes);
223   //#warning deletion and addition of routes swapped in 0.4.7 - TEST!
224   olsr_add_routes_in_kernel(add_kernel_list);
225   olsr_delete_routes_from_kernel(delete_kernel_list);
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\n",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