2 * OLSR ad-hoc routing table management protocol
3 * Copyright (C) 2004 Andreas Tønnesen (andreto@ifi.uio.no)
5 * This file is part of olsr.org.
7 * olsr.org is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * olsr.org is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with olsr.org; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * $Id: kernel_routes.c,v 1.10 2004/11/12 22:11:54 kattemat Exp $
27 #include "../kernel_routes.h"
28 #include "../link_set.h"
31 #include <sys/ioctl.h>
35 *Insert a route in the kernel routing table
37 *@param destination the route to add
39 *@return negative on error
42 olsr_ioctl_add_route(struct rt_entry *destination)
45 struct rtentry kernel_route;
48 olsr_printf(1, "(ioctl)Adding route: %s ",
49 olsr_ip_to_string(&destination->rt_dst));
50 olsr_printf(1, "gw %s (hopc %d)\n",
51 olsr_ip_to_string(&destination->rt_router),
52 destination->rt_metric);
54 memset(&kernel_route, 0, sizeof(struct rtentry));
56 ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
57 ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
58 ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
60 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
61 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
63 if(destination->rt_dst.v4 != destination->rt_router.v4)
65 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr=destination->rt_router.v4;
68 kernel_route.rt_flags = destination->rt_flags;
70 kernel_route.rt_metric = destination->rt_metric + 1;
73 * Thales Internet GW fix
77 (destination->rt_dst.v4 == INADDR_ANY) &&
78 (destination->rt_dst.v4 == INADDR_ANY))
80 delete_all_inet_gws();
87 if((kernel_route.rt_dev = malloc(strlen(destination->rt_if->int_name) + 1)) == 0)
89 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
90 olsr_exit(__func__, EXIT_FAILURE);
93 strcpy(kernel_route.rt_dev, destination->rt_if->int_name);
96 //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
99 printf("Adding route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));
100 printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));
101 printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));
102 printf("\tmetric: %d\n", destination->rt_metric);
105 //printf("\tiface: %s\n", kernel_route.rt_dev);
107 tmp = ioctl(ioctl_s,SIOCADDRT,&kernel_route);
108 /* kernel_route.rt_dev=*/
111 *Send IPC route update message
114 if(olsr_cnf->open_ipc)
116 ipc_route_send_rtentry(&destination->rt_dst,
117 &destination->rt_router,
118 destination->rt_metric,
120 destination->rt_if->int_name); /* Send interface name */
124 if (ifnet && kernel_route.rt_dev)
126 free(kernel_route.rt_dev);
137 *Insert a route in the kernel routing table
139 *@param destination the route to add
141 *@return negative on error
144 olsr_ioctl_add_route6(struct rt_entry *destination)
147 struct in6_rtmsg kernel_route;
149 struct in6_addr zeroaddr;
151 olsr_printf(2, "(ioctl)Adding route: %s(hopc %d)\n",
152 olsr_ip_to_string(&destination->rt_dst),
153 destination->rt_metric + 1);
156 memset(&zeroaddr, 0, ipsize); /* Use for comparision */
159 memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
161 COPY_IP(&kernel_route.rtmsg_dst, &destination->rt_dst);
163 kernel_route.rtmsg_flags = destination->rt_flags;
164 kernel_route.rtmsg_metric = destination->rt_metric;
166 kernel_route.rtmsg_dst_len = kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
168 if(memcmp(&destination->rt_dst, &destination->rt_router, ipsize) != 0)
170 COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_router);
174 COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_dst);
180 kernel_route.rtmsg_ifindex = destination->rt_if->if_index;
184 //olsr_printf(3, "Adding route to %s using gw ", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_dst));
185 //olsr_printf(3, "%s\n", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_gateway));
187 if((tmp = ioctl(ioctl_s, SIOCADDRT, &kernel_route)) < 0)
189 olsr_printf(1, "Add route: %s\n", strerror(errno));
190 olsr_syslog(OLSR_LOG_ERR, "Add route:%m");
194 if(olsr_cnf->open_ipc)
196 if(memcmp(&destination->rt_router, &null_addr6, ipsize) != 0)
197 ipc_route_send_rtentry(&destination->rt_dst,
198 &destination->rt_router,
199 destination->rt_metric,
201 destination->rt_if->int_name); /* Send interface name */
211 *Remove a route from the kernel
213 *@param destination the route to remove
215 *@return negative on error
218 olsr_ioctl_del_route(struct rt_entry *destination)
221 struct rtentry kernel_route;
224 olsr_printf(1, "(ioctl)Deleting route: %s(hopc %d)\n",
225 olsr_ip_to_string(&destination->rt_dst),
226 destination->rt_metric + 1);
228 memset(&kernel_route,0,sizeof(struct rtentry));
230 ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
231 ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
232 ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
234 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
235 if(destination->rt_dst.v4 != destination->rt_router.v4)
236 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = destination->rt_router.v4;
237 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
240 kernel_route.rt_dev = NULL;
242 kernel_route.rt_flags = destination->rt_flags;
244 kernel_route.rt_metric = destination->rt_metric + 1;
247 printf("Deleteing route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));
248 printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));
249 printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));
250 printf("\tmetric: %d\n", destination->rt_metric);
251 //printf("\tiface: %s\n", kernel_route.rt_dev);
254 tmp = ioctl(ioctl_s, SIOCDELRT, &kernel_route);
258 *Send IPC route update message
261 if(olsr_cnf->open_ipc)
262 ipc_route_send_rtentry(&destination->rt_dst,
264 destination->rt_metric,
266 NULL); /* Send interface name */
277 *Remove a route from the kernel
279 *@param destination the route to remove
281 *@return negative on error
284 olsr_ioctl_del_route6(struct rt_entry *destination)
287 struct in6_rtmsg kernel_route;
290 union olsr_ip_addr tmp_addr = destination->rt_dst;
292 olsr_printf(2, "(ioctl)Deleting route: %s(hopc %d)\n",
293 olsr_ip_to_string(&destination->rt_dst),
294 destination->rt_metric + 1);
297 olsr_printf(1, "Deleting route: %s\n", olsr_ip_to_string(&tmp_addr));
299 memset(&kernel_route,0,sizeof(struct in6_rtmsg));
301 kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
303 memcpy(&kernel_route.rtmsg_dst, &destination->rt_dst, ipsize);
305 memcpy(&kernel_route.rtmsg_gateway, &destination->rt_router, ipsize);
307 kernel_route.rtmsg_flags = destination->rt_flags;
308 kernel_route.rtmsg_metric = destination->rt_metric;
311 tmp = ioctl(ioctl_s, SIOCDELRT,&kernel_route);
315 *Send IPC route update message
318 if(olsr_cnf->open_ipc)
319 ipc_route_send_rtentry(&destination->rt_dst,
321 destination->rt_metric,
323 NULL); /* Send interface name */
331 *Add a IP in IP tunnel route to a Internet gateway
332 *First add acess to the gateway node trough the tunnel
333 *then add the Internet gateway
335 *@return negative on error
339 add_tunnel_route(union olsr_ip_addr *gw)
342 struct rtentry kernel_route;
344 //olsr_u32_t adr, netmask;
346 /* Get gw netaddress */
350 netmask = IN_CLASSA_NET;
351 else if (IN_CLASSB(adr))
352 netmask = IN_CLASSB_NET;
354 netmask = IN_CLASSC_NET;
356 netmask = htonl(netmask);
360 tunl_netmask = netmask;
363 printf("Adding route to gateway trough tunnel.\n\tNode %s\n", ip_to_string(&tunl_gw));
364 printf("\tMask %s\n", ip_to_string(&netmask));
368 memset(&kernel_route,0,sizeof(struct rtentry));
370 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = tunl_gw;
371 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
372 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = netmask;
373 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
374 //((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
375 //((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
377 //memcpy(&kernel_route.rt_gateway, gw, ipsize);
379 kernel_route.rt_flags = RTF_UP;// | RTF_HOST;
381 kernel_route.rt_metric = 1;
383 if((kernel_route.rt_dev = malloc(6)) == 0)
385 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
386 olsr_exit(__func__, EXIT_FAILURE);
389 strcpy(kernel_route.rt_dev, "tunl1");
392 //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
394 if((tmp = ioctl(ioctl_s, SIOCADDRT, &kernel_route)) < 0)
395 perror("Add default Internet route net");
398 free(kernel_route.rt_dev);
404 memset(&kernel_route,0,sizeof(struct rtentry));
406 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = INADDR_ANY;
407 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
408 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = INADDR_ANY;
409 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
410 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;//tunl_gw;
411 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
414 //olsr_printf(1, "Adding kernel route for Internet router trough tunnel\n");
416 kernel_route.rt_metric = 0;
418 kernel_route.rt_flags = RTF_UP;// | RTF_GATEWAY;
420 if((kernel_route.rt_dev = malloc(6)) == 0)
422 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
423 olsr_exit(__func__, EXIT_FAILURE);
426 strcpy(kernel_route.rt_dev, "tunl1");
429 olsr_printf(1, "Inserting route entry on device %s\n\n", kernel_route.rt_dev);
431 if((tmp = ioctl(ioctl_s,SIOCADDRT,&kernel_route)) < 0)
433 olsr_printf(1, "Add tunnel route: %s\n", strerror(errno));
434 olsr_syslog(OLSR_LOG_ERR, "Add tunnel route:%m");
437 free(kernel_route.rt_dev);
447 delete_tunnel_route()
449 struct rtentry kernel_route;
455 olsr_printf(1, "Deleting tunnel GW route\n");
457 memset(&kernel_route,0,sizeof(struct rtentry));
459 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = INADDR_ANY;
460 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
461 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = INADDR_ANY;
462 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
464 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = tunl_gw;
465 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
467 kernel_route.rt_metric = 1;
469 kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
471 if((kernel_route.rt_dev = malloc(6)) == 0)
473 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
474 olsr_exit(__func__, EXIT_FAILURE);
477 strcpy(kernel_route.rt_dev, "tunl1");
480 //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
482 if((tmp = ioctl(ioctl_s,SIOCDELRT,&kernel_route)) < 0)
484 olsr_printf(1, "Del tunnel route: %s\n", strerror(errno));
485 olsr_syslog(OLSR_LOG_ERR, "Del tunnel route:%m");
488 free(kernel_route.rt_dev);
492 olsr_printf(1, "Deleting route gateway trough tunnel.\n\tNet %s\n", ip_to_string(&tunl_gw));
493 olsr_printf(1, "\tMask %s\n", ip_to_string(&tunl_netmask));
497 memset(&kernel_route,0,sizeof(struct rtentry));
499 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = tunl_gw;
500 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
501 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = tunl_netmask;
502 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
504 //memcpy(&kernel_route.rt_gateway, gw, ipsize);
508 kernel_route.rt_flags = RTF_UP | RTF_HOST;
511 if((kernel_route.rt_dev = malloc(6)) == 0)
513 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
514 olsr_exit(__func__, EXIT_FAILURE);
517 strcpy(kernel_route.rt_dev, "tunl1");
520 //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
522 if((tmp = ioctl(ioctl_s,SIOCDELRT,&kernel_route)) < 0)
524 olsr_printf(1, "Del tunnel route: %s\n", strerror(errno));
525 olsr_syslog(OLSR_LOG_ERR, "Del tunnel route:%m");
529 free(kernel_route.rt_dev);
541 delete_all_inet_gws()
543 struct rtentry kernel_route;
546 char buf[BUFSIZ], *cp, *cplim;
550 olsr_printf(1, "Internet gateway detected...\nTrying to delete default gateways\n");
553 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
555 olsr_syslog(OLSR_LOG_ERR, "socket: %m");
560 ifc.ifc_len = sizeof (buf);
562 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
564 olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
570 #define size(p) (sizeof (p))
571 cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
572 for (cp = buf; cp < cplim;cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr))
574 ifr = (struct ifreq *)cp;
577 if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)
579 olsr_printf(1, "Skipping loopback...\n");
583 olsr_printf(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
586 memset(&kernel_route,0,sizeof(struct rtentry));
588 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
589 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
590 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
591 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
593 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
594 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
596 //memcpy(&kernel_route.rt_gateway, gw, ipsize);
600 kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
603 if((kernel_route.rt_dev = malloc(6)) == 0)
605 fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
606 olsr_exit(__func__, EXIT_FAILURE);
609 strncpy(kernel_route.rt_dev, ifr->ifr_ifrn.ifrn_name, 6);
612 //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
614 if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
615 olsr_printf(1, "NO\n");
617 olsr_printf(1, "YES\n");
620 free(kernel_route.rt_dev);