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