* applied patches from the most recent FreiFunkFirmware (and fixed compile errors...
[olsrd.git] / src / linux / kernel_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: kernel_routes.c,v 1.20 2007/01/31 12:36:50 bernd67 Exp $
40  */
41
42
43
44 #include "kernel_routes.h"
45 #include "link_set.h"
46 #include "olsr.h"
47 #include "log.h"
48 #include <net/if.h>
49 #include <sys/ioctl.h>
50 #include <unistd.h>
51
52
53
54 static struct sockaddr_in6 null_addr6; /* Address used as Originator Address IPv6 */
55
56 /**
57  *Insert a route in the kernel routing table
58  *
59  *@param destination the route to add
60  *
61  *@return negative on error
62  */
63 int
64 olsr_ioctl_add_route(struct rt_entry *destination)
65 {
66   struct rtentry kernel_route;
67   int tmp;
68   char dst_str[16], mask_str[16], router_str[16];
69
70   inet_ntop(AF_INET, &destination->rt_dst.v4, dst_str, 16);
71   inet_ntop(AF_INET, &destination->rt_mask.v4, mask_str, 16);
72   inet_ntop(AF_INET, &destination->rt_router.v4, router_str, 16);
73
74   OLSR_PRINTF(1, "(ioctl)Adding route with metric %d to %s/%s via %s/%s.\n",
75               destination->rt_metric, dst_str, mask_str, router_str,
76               destination->rt_if->int_name)
77   
78   memset(&kernel_route, 0, sizeof(struct rtentry));
79
80   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
81   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
82   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
83
84   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
85   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
86
87   if(destination->rt_dst.v4 != destination->rt_router.v4)
88     {
89       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr=destination->rt_router.v4;
90     }
91
92   kernel_route.rt_flags = destination->rt_flags;
93   
94   kernel_route.rt_metric = destination->rt_metric + 1;
95
96   if((olsr_cnf->del_gws) &&
97      (destination->rt_dst.v4 == INADDR_ANY) &&
98      (destination->rt_dst.v4 == INADDR_ANY))
99     {
100       delete_all_inet_gws();
101       olsr_cnf->del_gws = OLSR_FALSE;
102     }
103
104   /*
105    * Set interface
106    */
107   if((kernel_route.rt_dev = malloc(strlen(destination->rt_if->int_name) + 1)) == 0)
108     {
109       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
110       olsr_exit(__func__, EXIT_FAILURE);
111     }
112
113   strcpy(kernel_route.rt_dev, destination->rt_if->int_name);
114
115   
116   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
117   
118   /*
119   printf("Adding route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
120   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
121   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
122   printf("\tmetric: %d\n", destination->rt_metric);    
123   */
124
125   //printf("\tiface: %s\n", kernel_route.rt_dev);    
126   
127   tmp = ioctl(olsr_cnf->ioctl_s,SIOCADDRT,&kernel_route);
128   /*  kernel_route.rt_dev=*/
129
130   /*
131    *Send IPC route update message
132    */
133   
134   if(olsr_cnf->open_ipc)
135       {
136         ipc_route_send_rtentry(&destination->rt_dst, 
137                                &destination->rt_router, 
138                                destination->rt_metric, 
139                                1,
140                                destination->rt_if->int_name); /* Send interface name */
141       }
142   
143   
144   if (ifnet && kernel_route.rt_dev)
145     {
146       free(kernel_route.rt_dev);
147     }
148   
149   
150   return tmp;
151 }
152
153
154
155
156 /**
157  *Insert a route in the kernel routing table
158  *
159  *@param destination the route to add
160  *
161  *@return negative on error
162  */
163 int
164 olsr_ioctl_add_route6(struct rt_entry *destination)
165 {
166
167   struct in6_rtmsg kernel_route;
168   int tmp;
169   struct in6_addr zeroaddr;
170
171   OLSR_PRINTF(2, "(ioctl)Adding route: %s(hopc %d)\n", 
172               olsr_ip_to_string(&destination->rt_dst), 
173               destination->rt_metric + 1)
174   
175
176   memset(&zeroaddr, 0, olsr_cnf->ipsize); /* Use for comparision */
177
178
179   memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
180
181   COPY_IP(&kernel_route.rtmsg_dst, &destination->rt_dst);
182
183   kernel_route.rtmsg_flags = destination->rt_flags;
184   kernel_route.rtmsg_metric = destination->rt_metric;
185   
186   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
187
188   if(memcmp(&destination->rt_dst, &destination->rt_router, olsr_cnf->ipsize) != 0)
189     {
190       COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_router);
191     }
192   else
193     {
194       COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_dst);
195     }
196
197       /*
198        * set interface
199        */
200   kernel_route.rtmsg_ifindex = destination->rt_if->if_index;
201
202
203   
204   //OLSR_PRINTF(3, "Adding route to %s using gw ", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_dst))
205   //OLSR_PRINTF(3, "%s\n", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_gateway))
206
207   if((tmp = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0)
208     {
209       if(olsr_cnf->open_ipc)
210         {
211           if(memcmp(&destination->rt_router, &null_addr6, olsr_cnf->ipsize) != 0)
212             ipc_route_send_rtentry(&destination->rt_dst, 
213                                    &destination->rt_router, 
214                                    destination->rt_metric, 
215                                    1,
216                                    destination->rt_if->int_name); /* Send interface name */
217
218         }
219     }
220     return(tmp);
221 }
222
223
224
225 /**
226  *Remove a route from the kernel
227  *
228  *@param destination the route to remove
229  *
230  *@return negative on error
231  */
232 int
233 olsr_ioctl_del_route(struct rt_entry *destination)
234 {
235   struct rtentry kernel_route;
236   int tmp;
237   char dst_str[16], mask_str[16], router_str[16];
238
239   inet_ntop(AF_INET, &destination->rt_dst.v4, dst_str, 16);
240   inet_ntop(AF_INET, &destination->rt_mask.v4, mask_str, 16);
241   inet_ntop(AF_INET, &destination->rt_router.v4, router_str, 16);
242
243   OLSR_PRINTF(1, "(ioctl)Deleting route with metric %d to %s/%s via %s.\n",
244               destination->rt_metric, dst_str, mask_str, router_str)
245   
246   memset(&kernel_route,0,sizeof(struct rtentry));
247
248   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
249   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
250   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
251
252   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
253   if(destination->rt_dst.v4 != destination->rt_router.v4)
254     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = destination->rt_router.v4;
255   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
256
257
258   kernel_route.rt_dev = NULL;
259
260   kernel_route.rt_flags = destination->rt_flags;
261   
262   kernel_route.rt_metric = destination->rt_metric + 1;
263
264   /*
265   printf("Deleteing route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
266   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
267   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
268   printf("\tmetric: %d\n", destination->rt_metric);    
269   //printf("\tiface: %s\n", kernel_route.rt_dev);    
270   */
271
272   tmp = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route);
273
274
275     /*
276      *Send IPC route update message
277      */
278
279   if(olsr_cnf->open_ipc)
280     ipc_route_send_rtentry(&destination->rt_dst, 
281                            NULL, 
282                            destination->rt_metric, 
283                            0,
284                            NULL); /* Send interface name */
285
286   return tmp;
287 }
288
289
290
291
292
293
294 /**
295  *Remove a route from the kernel
296  *
297  *@param destination the route to remove
298  *
299  *@return negative on error
300  */
301 int
302 olsr_ioctl_del_route6(struct rt_entry *destination)
303 {
304
305   struct in6_rtmsg kernel_route;
306   int tmp;
307
308   union olsr_ip_addr tmp_addr = destination->rt_dst;
309
310   OLSR_PRINTF(2, "(ioctl)Deleting route: %s(hopc %d)\n", 
311               olsr_ip_to_string(&destination->rt_dst), 
312               destination->rt_metric)
313
314
315   OLSR_PRINTF(1, "Deleting route: %s\n", olsr_ip_to_string(&tmp_addr))
316
317   memset(&kernel_route,0,sizeof(struct in6_rtmsg));
318
319   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
320
321   memcpy(&kernel_route.rtmsg_dst, &destination->rt_dst, olsr_cnf->ipsize);
322
323   memcpy(&kernel_route.rtmsg_gateway, &destination->rt_router, olsr_cnf->ipsize);
324
325   kernel_route.rtmsg_flags = destination->rt_flags;
326   kernel_route.rtmsg_metric = destination->rt_metric;
327
328
329   tmp = ioctl(olsr_cnf->ioctl_s, SIOCDELRT,&kernel_route);
330
331
332     /*
333      *Send IPC route update message
334      */
335
336   if(olsr_cnf->open_ipc)
337     ipc_route_send_rtentry(&destination->rt_dst, 
338                            NULL, 
339                            destination->rt_metric, 
340                            0,
341                            NULL); /* Send interface name */
342
343   return tmp;
344 }
345
346
347
348 int
349 delete_all_inet_gws()
350 {
351   struct rtentry kernel_route;
352   
353   int s;
354   char buf[BUFSIZ], *cp, *cplim;
355   struct ifconf ifc;
356   struct ifreq *ifr;
357   
358   OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n")
359   
360   /* Get a socket */
361   if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
362     {
363       olsr_syslog(OLSR_LOG_ERR, "socket: %m");
364       close(s);
365       return -1;
366     }
367   
368   ifc.ifc_len = sizeof (buf);
369   ifc.ifc_buf = buf;
370   if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 
371     {
372       olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
373       close(s);
374       return -1;
375     }
376
377   ifr = ifc.ifc_req;
378 #define size(p) (sizeof (p))
379   cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
380   for (cp = buf; cp < cplim;cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) 
381     {
382       ifr = (struct ifreq *)cp;
383       
384       
385       if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)
386         {
387           OLSR_PRINTF(1, "Skipping loopback...\n")
388           continue;
389         }
390
391       OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name)
392       
393       
394       memset(&kernel_route,0,sizeof(struct rtentry));
395       
396       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
397       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
398       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
399       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
400
401       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
402       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
403       
404       //memcpy(&kernel_route.rt_gateway, gw, olsr_cnf->ipsize);
405       
406            
407            
408       kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
409            
410            
411       if((kernel_route.rt_dev = malloc(6)) == 0)
412         {
413           fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
414           olsr_exit(__func__, EXIT_FAILURE);
415         }
416            
417       strncpy(kernel_route.rt_dev, ifr->ifr_ifrn.ifrn_name, 6);
418
419   
420       //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
421       
422       if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
423         OLSR_PRINTF(1, "NO\n")
424       else
425         OLSR_PRINTF(1, "YES\n")
426
427
428       free(kernel_route.rt_dev);
429       
430     }
431   
432   close(s);
433   
434   return 0;
435        
436 }