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