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