2017-11-06 6:14 GMT+05:00 <selva.n...@gmail.com>:
> From: Selva Nair <selva.n...@gmail.com>
>
> Currently a route addition using IPAPI or service is skipped if the
> route gateway is reachable by multiple interfaces. This changes that
> to use the interface with lowest metric. Implemented by
>
> (i) Do not over-write the return value with TUN_ADAPTER_INDEX_INVALID in
> windows_route_find_if_index() if multiple interfaces match a route.
> (ii) Select the interface with lowest metric in adapter_index_of_ip()
> instead of the first one found when multiple interfaces match.
>
> Reported by Jan Just Keijser <janj...@nikhef.nl>
>
> v2: - A private get_interface_metric() method and better error reporting
> - Revert an unintented edit of route.c (a_index = ...)
> - Improve the commit message
>
> Signed-off-by: Selva Nair <selva.n...@gmail.com>
> ---
> src/openvpn/route.c | 1 -
> src/openvpn/tun.c | 59 ++++++++++++++++++++++++++++++
> +++++++++++++++++++++--
> 2 files changed, 57 insertions(+), 3 deletions(-)
>
> diff --git a/src/openvpn/route.c b/src/openvpn/route.c
> index 8c71e6e..66a8ae3 100644
> --- a/src/openvpn/route.c
> +++ b/src/openvpn/route.c
> @@ -2780,7 +2780,6 @@ windows_route_find_if_index(const struct route_ipv4
> *r, const struct tuntap *tt)
> msg(M_WARN, "Warning: route gateway is ambiguous: %s (%d
> matches)",
> print_in_addr_t(r->gateway, 0, &gc),
> count);
> - ret = TUN_ADAPTER_INDEX_INVALID;
> }
>
> dmsg(D_ROUTE_DEBUG, "DEBUG: route find if: on_tun=%d count=%d
> index=%d",
> diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
> index 3639718..7603133 100644
> --- a/src/openvpn/tun.c
> +++ b/src/openvpn/tun.c
> @@ -4474,6 +4474,49 @@ is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai,
> const in_addr_t ip, in_addr_t
> return ret;
> }
>
> +/**
> + * Given an interface index return the interface metric.
> + *
> + * Arguments:
> + * index : The index of the interface
> + * family : AF_INET for IPv4 or AF_INET6 for IPv6
> + * On error returns -1
> + */
> +
> +/* function signature missing in mingw iphlpapi.h */
>
that definition apparently present in mingw since 2015
https://sourceforge.net/p/mingw-w64/mingw-w64/ci/ea95d55e3387353e453d6ae8fc5cb8f7503947c2/tree/mingw-w64-headers/include/netioapi.h
> +VOID NETIOAPI_API_
> +InitializeIpInterfaceEntry(PMIB_IPINTERFACE_ROW Row);
> +
> +static int
> +get_interface_metric(NET_IFINDEX index, ADDRESS_FAMILY family)
> +{
> + DWORD err;
> + int msglevel = D_ROUTE|M_WARN;
> + MIB_IPINTERFACE_ROW ipiface;
> +
> + InitializeIpInterfaceEntry(&ipiface);
> + ipiface.Family = family;
> + ipiface.InterfaceIndex = index;
> +
> + err = GetIpInterfaceEntry(&ipiface);
> + if (err == NO_ERROR)
> + {
> + return ipiface.Metric;
> + }
> + else if (err == ERROR_NOT_FOUND)
> + {
> + /*
> + * This happens if the address family is not enabled for the
> + * interface, which is benign -- display only at a debug level
> + */
> + msglevel = D_ROUTE_DEBUG;
> + }
> + msg(msglevel, "Note: failed to determine metric of interface "
> + "<%lu> for %s : (error code = %lu)",
> + index, (family == AF_INET)? "ipv4" : "ipv6", err);
> + return -1;
> +}
> +
> DWORD
> adapter_index_of_ip(const IP_ADAPTER_INFO *list,
> const in_addr_t ip,
> @@ -4483,6 +4526,7 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list,
> struct gc_arena gc = gc_new();
> DWORD ret = TUN_ADAPTER_INDEX_INVALID;
> in_addr_t highest_netmask = 0;
> + int lowest_metric = INT_MAX;
> bool first = true;
>
> if (count)
> @@ -4496,9 +4540,14 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list,
>
> if (is_ip_in_adapter_subnet(list, ip, &hn))
> {
> + int metric = get_interface_metric(list->Index, AF_INET);
> if (first || hn > highest_netmask)
> {
> highest_netmask = hn;
> + if (metric >= 0)
> + {
> + lowest_metric = metric;
> + }
> if (count)
> {
> *count = 1;
> @@ -4512,16 +4561,22 @@ adapter_index_of_ip(const IP_ADAPTER_INFO *list,
> {
> ++*count;
> }
> + if (metric >= 0 && metric < lowest_metric)
> + {
> + ret = list->Index;
> + lowest_metric = metric;
> + }
> }
> }
> list = list->Next;
> }
>
> - dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d",
> + dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d
> metric=%d",
> print_in_addr_t(ip, 0, &gc),
> print_in_addr_t(highest_netmask, 0, &gc),
> (int)ret,
> - count ? *count : -1);
> + count ? *count : -1,
> + lowest_metric);
>
> if (ret == TUN_ADAPTER_INDEX_INVALID && count)
> {
> --
> 2.1.4
>
>
> ------------------------------------------------------------
> ------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel