OpenVPN on Linux (iproute2+ifconfig), FreeBSD and MacOS X (Darwin)
normally points routes directly towards the "tun" interface, obviating
the need for a gateway. For "tap" interfaces, now add gateway spec to
linux route command, and replace "-iface <dev>" with gateway spec (both
together do not work) on FreeBSD and MacOS X.
Also adapt "route delete" appropriately, otherwise route will not be found.
All other platforms already use the gateway address for tun and tap,
because there's no way to install a route "towards an interface" there.
Remove warning about missing IPv6 route gateway handling.
Signed-off-by: Gert Doering <gert@greenie.muc.de>
Acked-by: David Sommerseth <davids@redhat.com>
Message-Id: 1339342891-28443-5-git-send-email-gert@greenie.muc.de
URL: http://article.gmane.org/gmane.network.openvpn.devel/6712
Signed-off-by: David Sommerseth <davids@redhat.com>
... | ... |
@@ -1251,9 +1251,6 @@ do_init_route_ipv6_list (const struct options *options, |
1251 | 1251 |
int dev = dev_type_enum (options->dev, options->dev_type); |
1252 | 1252 |
int metric = -1; /* no metric set */ |
1253 | 1253 |
|
1254 |
- if (dev != DEV_TYPE_TUN ) |
|
1255 |
- msg( M_WARN, "IPv6 routes on TAP devices are going to fail on some platforms (need gateway spec)" ); /* TODO-GERT */ |
|
1256 |
- |
|
1257 | 1254 |
gw = options->ifconfig_ipv6_remote; /* default GW = remote end */ |
1258 | 1255 |
#if 0 /* not yet done for IPv6 - TODO!*/ |
1259 | 1256 |
if ( options->route_ipv6_default_gateway ) /* override? */ |
... | ... |
@@ -1550,6 +1550,8 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1550 | 1550 |
bool status = false; |
1551 | 1551 |
const char *device = tt->actual_name; |
1552 | 1552 |
|
1553 |
+ bool gateway_needed = false; |
|
1554 |
+ |
|
1553 | 1555 |
if (!r6->defined) |
1554 | 1556 |
return; |
1555 | 1557 |
|
... | ... |
@@ -1574,6 +1576,18 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1574 | 1574 |
* (not currently done for IPv6) |
1575 | 1575 |
*/ |
1576 | 1576 |
|
1577 |
+ /* On "tun" interface, we never set a gateway if the operating system |
|
1578 |
+ * can do "route to interface" - it does not add value, as the target |
|
1579 |
+ * dev already fully qualifies the route destination on point-to-point |
|
1580 |
+ * interfaces. OTOH, on "tap" interface, we must always set the |
|
1581 |
+ * gateway unless the route is to be an on-link network |
|
1582 |
+ */ |
|
1583 |
+ if ( tt->type == DEV_TYPE_TAP && |
|
1584 |
+ !(r6->metric_defined && r6->metric == 0 ) ) |
|
1585 |
+ { |
|
1586 |
+ gateway_needed = true; |
|
1587 |
+ } |
|
1588 |
+ |
|
1577 | 1589 |
#if defined(TARGET_LINUX) |
1578 | 1590 |
#ifdef ENABLE_IPROUTE |
1579 | 1591 |
argv_printf (&argv, "%s -6 route add %s/%d dev %s", |
... | ... |
@@ -1581,6 +1595,8 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1581 | 1581 |
network, |
1582 | 1582 |
r6->netbits, |
1583 | 1583 |
device); |
1584 |
+ if (gateway_needed) |
|
1585 |
+ argv_printf_cat (&argv, "via %s", gateway); |
|
1584 | 1586 |
if (r6->metric_defined && r6->metric > 0 ) |
1585 | 1587 |
argv_printf_cat (&argv, " metric %d", r6->metric); |
1586 | 1588 |
|
... | ... |
@@ -1590,6 +1606,8 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1590 | 1590 |
network, |
1591 | 1591 |
r6->netbits, |
1592 | 1592 |
device); |
1593 |
+ if (gateway_needed) |
|
1594 |
+ argv_printf_cat (&argv, "gw %s", gateway); |
|
1593 | 1595 |
if (r6->metric_defined && r6->metric > 0 ) |
1594 | 1596 |
argv_printf_cat (&argv, " metric %d", r6->metric); |
1595 | 1597 |
#endif /*ENABLE_IPROUTE*/ |
... | ... |
@@ -1652,20 +1670,29 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla |
1652 | 1652 |
|
1653 | 1653 |
#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) |
1654 | 1654 |
|
1655 |
- argv_printf (&argv, "%s add -inet6 %s/%d -iface %s", |
|
1655 |
+ argv_printf (&argv, "%s add -inet6 %s/%d", |
|
1656 | 1656 |
ROUTE_PATH, |
1657 | 1657 |
network, |
1658 |
- r6->netbits, |
|
1659 |
- device ); |
|
1658 |
+ r6->netbits); |
|
1659 |
+ |
|
1660 |
+ if (gateway_needed) |
|
1661 |
+ argv_printf_cat (&argv, "%s", gateway); |
|
1662 |
+ else |
|
1663 |
+ argv_printf_cat (&argv, "-iface %s", device); |
|
1660 | 1664 |
|
1661 | 1665 |
argv_msg (D_ROUTE, &argv); |
1662 | 1666 |
status = openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route add -inet6 command failed"); |
1663 | 1667 |
|
1664 | 1668 |
#elif defined(TARGET_DARWIN) |
1665 | 1669 |
|
1666 |
- argv_printf (&argv, "%s add -inet6 %s -prefixlen %d -iface %s", |
|
1670 |
+ argv_printf (&argv, "%s add -inet6 %s -prefixlen %d", |
|
1667 | 1671 |
ROUTE_PATH, |
1668 |
- network, r6->netbits, device ); |
|
1672 |
+ network, r6->netbits ); |
|
1673 |
+ |
|
1674 |
+ if (gateway_needed) |
|
1675 |
+ argv_printf_cat (&argv, "%s", gateway); |
|
1676 |
+ else |
|
1677 |
+ argv_printf_cat (&argv, "-iface %s", device); |
|
1669 | 1678 |
|
1670 | 1679 |
argv_msg (D_ROUTE, &argv); |
1671 | 1680 |
status = openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route add -inet6 command failed"); |
... | ... |
@@ -1865,6 +1892,7 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne |
1865 | 1865 |
const char *network; |
1866 | 1866 |
const char *gateway; |
1867 | 1867 |
const char *device = tt->actual_name; |
1868 |
+ bool gateway_needed = false; |
|
1868 | 1869 |
|
1869 | 1870 |
if (!r6->defined) |
1870 | 1871 |
return; |
... | ... |
@@ -1884,6 +1912,16 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne |
1884 | 1884 |
|
1885 | 1885 |
msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits ); |
1886 | 1886 |
|
1887 |
+ /* if we used a gateway on "add route", we also need to specify it on |
|
1888 |
+ * delete, otherwise some OSes will refuse to delete the route |
|
1889 |
+ */ |
|
1890 |
+ if ( tt->type == DEV_TYPE_TAP && |
|
1891 |
+ !(r6->metric_defined && r6->metric == 0 ) ) |
|
1892 |
+ { |
|
1893 |
+ gateway_needed = true; |
|
1894 |
+ } |
|
1895 |
+ |
|
1896 |
+ |
|
1887 | 1897 |
#if defined(TARGET_LINUX) |
1888 | 1898 |
#ifdef ENABLE_IPROUTE |
1889 | 1899 |
argv_printf (&argv, "%s -6 route del %s/%d dev %s", |
... | ... |
@@ -1891,12 +1929,18 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne |
1891 | 1891 |
network, |
1892 | 1892 |
r6->netbits, |
1893 | 1893 |
device); |
1894 |
+ if (gateway_needed) |
|
1895 |
+ argv_printf_cat (&argv, "via %s", gateway); |
|
1894 | 1896 |
#else |
1895 | 1897 |
argv_printf (&argv, "%s -A inet6 del %s/%d dev %s", |
1896 | 1898 |
ROUTE_PATH, |
1897 | 1899 |
network, |
1898 | 1900 |
r6->netbits, |
1899 | 1901 |
device); |
1902 |
+ if (gateway_needed) |
|
1903 |
+ argv_printf_cat (&argv, "gw %s", gateway); |
|
1904 |
+ if (r6->metric_defined && r6->metric > 0 ) |
|
1905 |
+ argv_printf_cat (&argv, " metric %d", r6->metric); |
|
1900 | 1906 |
#endif /*ENABLE_IPROUTE*/ |
1901 | 1907 |
argv_msg (D_ROUTE, &argv); |
1902 | 1908 |
openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 del command failed"); |
... | ... |
@@ -1949,23 +1993,32 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne |
1949 | 1949 |
|
1950 | 1950 |
#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) |
1951 | 1951 |
|
1952 |
- argv_printf (&argv, "%s delete -inet6 %s/%d -iface %s", |
|
1952 |
+ argv_printf (&argv, "%s delete -inet6 %s/%d", |
|
1953 | 1953 |
ROUTE_PATH, |
1954 | 1954 |
network, |
1955 |
- r6->netbits, |
|
1956 |
- device ); |
|
1955 |
+ r6->netbits ); |
|
1956 |
+ |
|
1957 |
+ if (gateway_needed) |
|
1958 |
+ argv_printf_cat (&argv, "%s", gateway); |
|
1959 |
+ else |
|
1960 |
+ argv_printf_cat (&argv, "-iface %s", device); |
|
1957 | 1961 |
|
1958 | 1962 |
argv_msg (D_ROUTE, &argv); |
1959 | 1963 |
openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed"); |
1960 | 1964 |
|
1961 | 1965 |
#elif defined(TARGET_DARWIN) |
1962 | 1966 |
|
1963 |
- argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d -iface %s", |
|
1967 |
+ argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d", |
|
1964 | 1968 |
ROUTE_PATH, |
1965 |
- network, r6->netbits, device ); |
|
1969 |
+ network, r6->netbits ); |
|
1970 |
+ |
|
1971 |
+ if (gateway_needed) |
|
1972 |
+ argv_printf_cat (&argv, "%s", gateway); |
|
1973 |
+ else |
|
1974 |
+ argv_printf_cat (&argv, "-iface %s", device); |
|
1966 | 1975 |
|
1967 | 1976 |
argv_msg (D_ROUTE, &argv); |
1968 |
- openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed"); |
|
1977 |
+ openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route delete -inet6 command failed"); |
|
1969 | 1978 |
|
1970 | 1979 |
#elif defined(TARGET_OPENBSD) |
1971 | 1980 |
|