diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-10-22 08:55:37 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-10-22 08:55:37 +0000 |
commit | dd081a991d1a319bc9c7ae5c270519dfe1201257 (patch) | |
tree | c6f4a12ccc04ac2f88ebd073bcd0689c288a884d | |
parent | 5431ccf5c6c657c441be44fe802c7780974aaebc (diff) | |
download | vyos-strongswan-dd081a991d1a319bc9c7ae5c270519dfe1201257.tar.gz vyos-strongswan-dd081a991d1a319bc9c7ae5c270519dfe1201257.zip |
Use patch from Astaro instead to read routes via netlink.
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | src/starter/interfaces.c | 249 |
2 files changed, 115 insertions, 138 deletions
diff --git a/debian/changelog b/debian/changelog index c68746ca4..5f78bd4e6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,10 @@ strongswan (4.3.4-1) unstable; urgency=low * Patched starter to also look at routing table "default" when table "main" doesn't have a default entry. This makes dealing with "%defaulroute" in ipsec.conf more flexible. + Update: It seems Astaro was quicker then me sending a patch with + exactly that aim to upstream. Now applied this one, which will be + part of future upstream releases and uses netlink to read routing + tables. -- Rene Mayrhofer <rmayr@debian.org> Wed, 21 Oct 2009 11:14:56 +0000 diff --git a/src/starter/interfaces.c b/src/starter/interfaces.c index 1721b869c..d12bf0bdf 100644 --- a/src/starter/interfaces.c +++ b/src/starter/interfaces.c @@ -1,5 +1,6 @@ /* strongSwan IPsec interfaces management * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security + * 2009 Heiko Hund - Astaro AG * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -14,7 +15,7 @@ #include <sys/socket.h> #include <sys/ioctl.h> -#include <sys/types.h> +#include <linux/rtnetlink.h> #ifdef HAVE_SYS_SOCKIO_H #include <sys/sockio.h> #endif @@ -34,171 +35,143 @@ #include "exec.h" #include "files.h" -const char* IP_ROUTE = "ip route show table default 0.0.0.0/0"; - /* - * discover the default route via /proc/net/route + * Get the default route information via rtnetlink */ void get_defaultroute(defaultroute_t *defaultroute) { - FILE *fd; - char line[BUF_LEN]; - bool first = TRUE; - - memset(defaultroute, 0, sizeof(defaultroute_t)); + union { + struct { + struct nlmsghdr nh; + struct rtmsg rt; + } m; + char buf[4096]; + } rtu; + + struct nlmsghdr *nh; + uint32_t best_metric = ~0; + ssize_t msglen; + int fd; + + bzero(&rtu, sizeof(rtu)); + rtu.m.nh.nlmsg_len = NLMSG_LENGTH(sizeof(rtu.m.rt)); + rtu.m.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + rtu.m.nh.nlmsg_type = RTM_GETROUTE; + rtu.m.rt.rtm_family = AF_INET; + rtu.m.rt.rtm_table = RT_TABLE_UNSPEC; + rtu.m.rt.rtm_protocol = RTPROT_UNSPEC; + rtu.m.rt.rtm_type = RTN_UNICAST; + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd == -1) + { + plog("could not create rtnetlink socket"); + return; + } - fd = fopen("/proc/net/route", "r"); + if (send(fd, &rtu, rtu.m.nh.nlmsg_len, 0) == -1) + { + plog("could not write to rtnetlink socket"); + close(fd); + return; + } - if (!fd) + msglen = recv(fd, &rtu, sizeof(rtu), MSG_WAITALL); + if (msglen == -1) { - plog("could not open 'proc/net/route'"); + plog("could not read from rtnetlink socket"); + close(fd); return; } - while (fgets(line, sizeof(line), fd) != 0) + close(fd); + + for (nh = &rtu.m.nh; NLMSG_OK(nh, msglen); nh = NLMSG_NEXT(nh, msglen)) { - char iface[11]; - char destination[9]; - char gateway[11]; - char flags[5]; - char mask[9]; - - int refcnt; - int use; - int metric; - int items; - - /* proc/net/route returns IP addresses in host order */ - strcpy(gateway, "0h"); - - /* skip the header line */ - if (first) + struct rtmsg *rt; + struct rtattr *rta; + uint32_t rtalen, metric = 0; + struct in_addr gw = { .s_addr = INADDR_ANY }; + int iface_idx = -1; + + if (nh->nlmsg_type == NLMSG_ERROR) { - first = FALSE; - continue; + plog("error from rtnetlink"); + return; } - /* parsing a single line of proc/net/route */ - items = sscanf(line, "%10s\t%8s\t%8s\t%5s\t%d\t%d\t%d\t%8s\t" - , iface, destination, gateway+2, flags, &refcnt, &use, &metric, mask); - if (items < 8) - { - plog("parsing error while scanning /proc/net/route"); + if (nh->nlmsg_type == NLMSG_DONE) + break; + + rt = NLMSG_DATA(nh); + if ( rt->rtm_dst_len != 0 + || (rt->rtm_table != RT_TABLE_MAIN + && rt->rtm_table != RT_TABLE_DEFAULT) ) continue; - } - /* check for defaultroute (destination 0.0.0.0 and mask 0.0.0.0) */ - if (streq(destination, "00000000") && streq(mask, "00000000")) + rta = RTM_RTA(rt); + rtalen = RTM_PAYLOAD(nh); + while ( RTA_OK(rta, rtalen) ) { - if (defaultroute->defined) + switch (rta->rta_type) { - plog("multiple default routes - cannot cope with %%defaultroute!!!"); - defaultroute->defined = FALSE; - fclose(fd); - return; + case RTA_GATEWAY: + gw = *(struct in_addr *) RTA_DATA(rta); + break; + case RTA_OIF: + iface_idx = *(int *) RTA_DATA(rta); + break; + case RTA_PRIORITY: + metric = *(uint32_t *) RTA_DATA(rta); + break; } - ttoaddr(gateway, strlen(gateway), AF_INET, &defaultroute->nexthop); - strncpy(defaultroute->iface, iface, IFNAMSIZ); - defaultroute->defined = TRUE; + rta = RTA_NEXT(rta, rtalen); } - } - fclose(fd); - - /* If there is no default route in the "main" table, also look at the "default" one. */ - if (!defaultroute->defined) - { - plog("no default route in table 'main', checking table 'default' instead"); - - fd = (FILE*) popen(IP_ROUTE, "r"); - if (!fd) + if (metric < best_metric + && gw.s_addr != INADDR_ANY + && iface_idx != -1) { - plog("could not execute '%s'", IP_ROUTE); - return; - } - - /* parse the output - it should only be one line */ - while (fgets(line, sizeof(line), fd) != 0) - { - char destination[19]; - char buf1[4], buf2[4]; - char gateway[16]; - char iface[11]; - int items; - - /* parsing a single line of the output */ - items = sscanf(line, "%s %s %s %s %s", - destination, buf1, gateway, buf2, iface); - if (items < 5) - { - plog("parsing error while scanning 'ip route' output"); - continue; - } - - if (streq(destination, "default")) + struct ifreq req; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { - if (defaultroute->defined) - { - plog("multiple default routes in table 'default' - cannot cope with %%defaultroute!!!"); - defaultroute->defined = FALSE; - pclose(fd); - return; - } - - ttoaddr(gateway, strlen(gateway), AF_INET, &defaultroute->nexthop); - strncpy(defaultroute->iface, iface, IFNAMSIZ); - defaultroute->defined = TRUE; + plog("could not open AF_INET socket"); + defaultroute->defined = FALSE; + break; } + bzero(&req, sizeof(req)); + req.ifr_ifindex = iface_idx; + ioctl(fd, SIOCGIFNAME, &req); + ioctl(fd, SIOCGIFADDR, &req); + close(fd); + + strncpy(defaultroute->iface, req.ifr_name, IFNAMSIZ); + defaultroute->addr.u.v4 = *((struct sockaddr_in *) &req.ifr_addr); + defaultroute->nexthop.u.v4.sin_family = AF_INET; + defaultroute->nexthop.u.v4.sin_addr = gw; + + DBG(DBG_CONTROL, + char addr[20]; + char nexthop[20]; + addrtot(&defaultroute->addr, 0, addr, sizeof(addr)); + addrtot(&defaultroute->nexthop, 0, nexthop, sizeof(nexthop)); + + DBG_log( + ( !defaultroute->defined + ? "Default route found: iface=%s, addr=%s, nexthop=%s" + : "Better default route: iface=%s, addr=%s, nexthop=%s" + ), defaultroute->iface, addr, nexthop + ) + ); + + best_metric = metric; + defaultroute->defined = TRUE; } - pclose(fd); } if (!defaultroute->defined) - { plog("no default route - cannot cope with %%defaultroute!!!"); - } - else - { - char addr_buf[20], nexthop_buf[20]; - struct ifreq physreq; - - int sock = socket(AF_INET, SOCK_DGRAM, 0); - - /* determine IP address of iface */ - if (sock < 0) - { - plog("could not open SOCK_DGRAM socket"); - defaultroute->defined = FALSE; - return; - } - memset ((void*)&physreq, 0, sizeof(physreq)); - strncpy(physreq.ifr_name, defaultroute->iface, IFNAMSIZ); - ioctl(sock, SIOCGIFADDR, &physreq); - close(sock); - defaultroute->addr.u.v4 = *((struct sockaddr_in *)&physreq.ifr_addr); - - addrtot(&defaultroute->addr, 0, addr_buf, sizeof(addr_buf)); - addrtot(&defaultroute->nexthop, 0, nexthop_buf, sizeof(nexthop_buf)); - - DBG(DBG_CONTROL, - DBG_log("Default route found: iface=%s, addr=%s, nexthop=%s" - , defaultroute->iface, addr_buf, nexthop_buf) - ) - - /* for backwards-compatibility with the awk shell scripts - * store the defaultroute in /var/run/ipsec.info - */ - fd = fopen(INFO_FILE, "w"); - - if (fd) - { - fprintf(fd, "defaultroutephys=%s\n", defaultroute->iface ); - fprintf(fd, "defaultroutevirt=ipsec0\n"); - fprintf(fd, "defaultrouteaddr=%s\n", addr_buf); - fprintf(fd, "defaultroutenexthop=%s\n", nexthop_buf); - fclose(fd); - } - } - return; } |