Added CVS Id to all C and haeder files
[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.8 2004/09/21 19:08:57 kattemat 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 #else
38 #       error "Unsupported system"
39 #endif
40
41
42
43 int
44 olsr_init_old_table()
45 {
46   int index;
47
48   for(index=0;index<HASHSIZE;index++)
49     {
50       old_routes[index].next = &old_routes[index];
51       old_routes[index].prev = &old_routes[index];
52       old_hna[index].next = &old_hna[index];
53       old_hna[index].prev = &old_hna[index];
54     }
55
56   return 1;
57 }
58
59 /**
60  *Checks if there exists a route to a given host
61  *in a given hash table.
62  *
63  *@param dst the host to check for
64  *@param table the table to check
65  *
66  *@return 1 if the host exists in the table, 0 if not
67  */
68 int
69 olsr_find_up_route(struct rt_entry *dst, struct rt_entry *table)
70
71   struct rt_entry *destination;
72   olsr_u32_t      hash;
73  
74   hash = olsr_hashing(&dst->rt_dst);
75
76   for(destination = table[hash].next;
77       destination != &table[hash];
78       destination = destination->next)
79     {
80       //printf("Checking %s hc: %d ", olsr_ip_to_string(&dst->rt_dst), dst->rt_metric);
81       //printf("vs %s hc: %d ... ", olsr_ip_to_string(&destination->rt_dst), destination->rt_metric);      
82       if (COMP_IP(&destination->rt_dst, &dst->rt_dst) &&
83           COMP_IP(&destination->rt_router, &dst->rt_router) &&
84           (destination->rt_if->if_nr == dst->rt_if->if_nr))
85         {
86           if(destination->rt_metric == dst->rt_metric)
87             {
88               return 1;
89             }
90           else
91             {
92               return 0;
93             }
94         }
95     }
96
97   return 0;
98
99 }
100
101
102 /**
103  *Create a list containing the entries in in_table
104  *that does not exist in from_table
105  *
106  *@param from_table the table to use
107  *@param in_table the routes already added
108  *
109  *@return a poiter to a linked list of routes to add
110  */
111 struct destination_n *
112 olsr_build_update_list(struct rt_entry *from_table,struct rt_entry *in_table)
113 {
114   struct destination_n *kernel_route_list = NULL;
115   struct destination_n *route_list = NULL;
116   struct rt_entry      *destination;
117   olsr_u8_t            index;
118   
119   for(index=0;index<HASHSIZE;index++)
120     {
121       for(destination = from_table[index].next;
122           destination != &from_table[index];
123           destination = destination->next)
124         {
125           if (!olsr_find_up_route(destination, in_table))
126             {
127               
128               route_list = olsr_malloc(sizeof(struct destination_n), "create route tmp list");
129               
130               route_list->destination = destination;
131               
132               route_list->next = kernel_route_list;
133               kernel_route_list = route_list;
134             }
135         }   
136     }
137   
138   return (kernel_route_list);
139 }
140
141
142
143
144
145 /**
146  *Deletes all OLSR routes
147  *
148  *
149  *@return 1
150  */
151 int
152 olsr_delete_all_kernel_routes()
153
154   struct destination_n *delete_kernel_list=NULL;
155   struct destination_n *tmp=NULL;
156   union olsr_ip_addr *tmp_addr;
157   olsr_u32_t tmp_tnl_addr;
158
159   olsr_printf(1, "Deleting all routes...\n");
160
161   if(use_tunnel)
162     {
163       /* Delete Internet GW tunnel */
164       delete_tunnel_route();
165       /* Take down tunnel */
166       del_ip_tunnel(&ipt);
167       tmp_tnl_addr = 0;
168       set_up_gw_tunnel(&tmp_tnl_addr);
169     }
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(ipversion == 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(ipversion == 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\n",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