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