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