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