diff --git a/src/Makefile.am b/src/Makefile.am index f020fbd59c..e0a7125d11 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -237,8 +237,6 @@ nm_sources = \ nm-manager.h \ nm-netlink-monitor.c \ nm-netlink-monitor.h \ - nm-netlink-utils.c \ - nm-netlink-utils.h \ nm-policy-hosts.c \ nm-policy-hosts.h \ nm-policy.c \ diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c deleted file mode 100644 index c115a75aa8..0000000000 --- a/src/nm-netlink-utils.c +++ /dev/null @@ -1,476 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * 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 Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#include "nm-logging.h" -#include "nm-platform.h" -#include "nm-netlink-utils.h" -#include "nm-netlink-monitor.h" - -#include -#include -#include - -typedef struct { - int ifindex; - int family; - void *addr; - int addrlen; - int prefix; - gboolean found; -} FindAddrInfo; - -static void -find_one_address (struct nl_object *object, void *user_data) -{ - FindAddrInfo *info = user_data; - struct rtnl_addr *addr = (struct rtnl_addr *) object; - struct nl_addr *local; - void *binaddr; - - if (info->found) - return; - - if (rtnl_addr_get_ifindex (addr) != info->ifindex) - return; - if (rtnl_addr_get_family (addr) != info->family) - return; - - if (rtnl_addr_get_prefixlen (addr) != info->prefix) - return; - - local = rtnl_addr_get_local (addr); - if (nl_addr_get_family (local) != info->family) - return; - if (nl_addr_get_len (local) != info->addrlen) - return; - binaddr = nl_addr_get_binary_addr (local); - if (binaddr) { - if (memcmp (binaddr, info->addr, info->addrlen) == 0) - info->found = TRUE; /* Yay, found it */ - } -} - -/** - * nm_netlink_find_address: - * @ifindex: interface index - * @family: address family, either AF_INET or AF_INET6 - * @addr: binary address, either struct in_addr* or struct in6_addr* - * @prefix: prefix length - * - * Searches for a matching address on the given interface. - * - * Returns: %TRUE if the given address was found on the interface, %FALSE if it - * was not found or an error occurred. - **/ -gboolean -nm_netlink_find_address (int ifindex, - int family, - void *addr, /* struct in_addr or struct in6_addr */ - int prefix) -{ - struct nl_sock *nlh = NULL; - struct nl_cache *cache = NULL; - FindAddrInfo info; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); - g_return_val_if_fail (addr != NULL, FALSE); - g_return_val_if_fail (prefix >= 0, FALSE); - - memset (&info, 0, sizeof (info)); - info.ifindex = ifindex; - info.family = family; - info.prefix = prefix; - info.addr = addr; - if (family == AF_INET) - info.addrlen = sizeof (struct in_addr); - else if (family == AF_INET6) - info.addrlen = sizeof (struct in6_addr); - else - g_assert_not_reached (); - - nlh = nm_netlink_get_default_handle (); - if (nlh) { - rtnl_addr_alloc_cache(nlh, &cache); - if (cache) { - nl_cache_mngt_provide (cache); - nl_cache_foreach (cache, find_one_address, &info); - nl_cache_free (cache); - } - } - return info.found; -} - -struct rtnl_route * -nm_netlink_route_new (int ifindex, - int family, - int mss, - ...) -{ - va_list var_args; - struct rtnl_route *route; - struct rtnl_nexthop *nexthop; - NmNlProp prop = NMNL_PROP_INVALID; - int value; - - route = rtnl_route_alloc (); - g_return_val_if_fail (route != NULL, NULL); - - if (ifindex > 0) { - nexthop = rtnl_route_nh_alloc(); - rtnl_route_nh_set_ifindex (nexthop, ifindex); - rtnl_route_add_nexthop (route, nexthop); - } - if (family != AF_UNSPEC) - rtnl_route_set_family (route, family); - if (mss > 0) - rtnl_route_set_metric (route, RTAX_ADVMSS, mss); - - va_start (var_args, mss); - prop = va_arg (var_args, NmNlProp); - while (prop != NMNL_PROP_INVALID) { - value = va_arg (var_args, int); - - if (prop == NMNL_PROP_PROT && value != RTPROT_UNSPEC) - rtnl_route_set_protocol (route, value); - else if (prop == NMNL_PROP_TABLE && value != RT_TABLE_UNSPEC) - rtnl_route_set_table (route, value); - else if (prop == NMNL_PROP_SCOPE && value != RT_SCOPE_NOWHERE) - rtnl_route_set_scope (route, value); - else if (prop == NMNL_PROP_PRIO && value > 0) - rtnl_route_set_priority (route, value); - - prop = va_arg (var_args, NmNlProp); - } - va_end (var_args); - - return route; -} - -/** - * _route_add: - * @route: the route to add - * @family: address family, either %AF_INET or %AF_INET6 - * @dest: the route destination address, either a struct in_addr or a struct - * in6_addr depending on @family - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any; given as a - * struct in_addr or struct in6_addr depending on @family - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -static int -_route_add (struct rtnl_route *route, - int family, - const void *dest, /* in_addr or in6_addr */ - int dest_prefix, - const void *gateway, /* in_addr or in6_addr */ - int flags) -{ - struct nl_sock *sk; - struct nl_addr *dest_addr, *gw_addr; - void *tmp_addr; - int addrlen, err, log; - - if (family == AF_INET) { - addrlen = sizeof (struct in_addr); - log = LOGD_IP4; - } else if (family == AF_INET6) { - addrlen = sizeof (struct in6_addr); - log = LOGD_IP6; - } else - g_assert_not_reached (); - - sk = nm_netlink_get_default_handle (); - - /* Build up the destination address */ - if (dest) { - /* Copy to preserve const */ - tmp_addr = g_malloc0 (addrlen); - memcpy (tmp_addr, dest, addrlen); - - dest_addr = nl_addr_build (family, tmp_addr, addrlen); - g_free (tmp_addr); - - g_return_val_if_fail (dest_addr != NULL, -NLE_INVAL); - nl_addr_set_prefixlen (dest_addr, dest_prefix); - - rtnl_route_set_dst (route, dest_addr); - nl_addr_put (dest_addr); - } - - /* Build up the gateway address */ - if (gateway) { - tmp_addr = g_malloc0 (addrlen); - memcpy (tmp_addr, gateway, addrlen); - - gw_addr = nl_addr_build (family, tmp_addr, addrlen); - g_free (tmp_addr); - - if (gw_addr) { - nl_addr_set_prefixlen (gw_addr, 0); - if (rtnl_route_get_nnexthops (route) == 1) - rtnl_route_nh_set_gateway (rtnl_route_nexthop_n (route, 0), gw_addr); - else - nm_log_warn (LOGD_DEVICE, "Netlink didn't have exactly one nexthop."); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - nl_addr_put (gw_addr); - } else - nm_log_err (LOGD_DEVICE | log, "Invalid gateway"); - } - - err = rtnl_route_add (sk, route, flags); - - /* LIBNL Bug: Aliased ESRCH */ - if (err == -NLE_FAILURE) - err = -NLE_OBJ_NOTFOUND; - - return err; -} - -/** - * nm_netlink_route4_add: - * @route: the route to add - * @dest: the route destination address in network byte order - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any, in network byte order - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Adds an IPv4 route with the given parameters. - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -int -nm_netlink_route4_add (struct rtnl_route *route, - guint32 *dst, - int prefix, - guint32 *gw, - int flags) -{ - return _route_add (route, AF_INET, dst, prefix, gw, flags); -} - -/** - * nm_netlink_route6_add: - * @route: the route to add - * @dest: the route destination address - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Adds an IPv6 route with the given parameters. - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -int -nm_netlink_route6_add (struct rtnl_route *route, - const struct in6_addr *dst, - int prefix, - const struct in6_addr *gw, - int flags) -{ - return _route_add (route, AF_INET6, dst, prefix, gw, flags); -} - -/** - * nm_netlink_route_delete: - * @route: the route to delete - * - * Returns: %TRUE if the request was successful, %FALSE if it failed - **/ -gboolean -nm_netlink_route_delete (struct rtnl_route *route) -{ - struct nl_sock *nlh; - int err = 0; - - g_return_val_if_fail (route != NULL, FALSE); - - nlh = nm_netlink_get_default_handle (); - err = rtnl_route_delete (nlh, route, 0); - - if (err) - nm_log_dbg (LOGD_IP4 | LOGD_IP6, "%s (%d)", nl_geterror(err), err); - - /* Workaround libnl BUG: ESRCH is aliased to generic NLE_FAILURE - * See: http://git.kernel.org/?p=libs/netlink/libnl.git;a=commit;h=7e9d5f */ - if (err == -NLE_FAILURE) - err = -NLE_OBJ_NOTFOUND; - - return (err && (err != -NLE_OBJ_NOTFOUND) && (err != -NLE_RANGE) ) ? FALSE : TRUE; -} - - -static void -dump_route (struct rtnl_route *route) -{ - char buf6[INET6_ADDRSTRLEN]; - char buf4[INET_ADDRSTRLEN]; - struct nl_addr *nl; - struct in6_addr *addr6 = NULL; - struct in_addr *addr4 = NULL; - int prefixlen = 0; - const char *sf = "UNSPEC"; - int family = rtnl_route_get_family (route); - guint32 log_level = LOGD_IP4 | LOGD_IP6; - - memset (buf6, 0, sizeof (buf6)); - memset (buf4, 0, sizeof (buf4)); - nl = rtnl_route_get_dst (route); - if (nl) { - if (nl_addr_get_family (nl) == AF_INET) { - addr4 = nl_addr_get_binary_addr (nl); - if (addr4) - inet_ntop (AF_INET, addr4, &buf4[0], sizeof (buf4)); - } else if (nl_addr_get_family (nl) == AF_INET6) { - addr6 = nl_addr_get_binary_addr (nl); - if (addr6) - inet_ntop (AF_INET6, addr6, &buf6[0], sizeof (buf6)); - } - prefixlen = nl_addr_get_prefixlen (nl); - } - - if (family == AF_INET) { - sf = "INET"; - log_level = LOGD_IP4; - } else if (family == AF_INET6) { - sf = "INET6"; - log_level = LOGD_IP6; - } - - nm_log_dbg (log_level, " route idx %d family %s (%d) addr %s/%d", - rtnl_route_nh_get_ifindex (rtnl_route_nexthop_n (route, 0)), - sf, family, - strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : ""), - prefixlen); -} - - -typedef struct { - int ifindex; - int family; - int scope; - gboolean ignore_inet6_ll_mc; - char *iface; - NlRouteForeachFunc callback; - gpointer user_data; - struct rtnl_route *out_route; -} ForeachRouteInfo; - -static void -foreach_route_cb (struct nl_object *object, void *user_data) -{ - ForeachRouteInfo *info = user_data; - struct rtnl_route *route = (struct rtnl_route *) object; - struct nl_addr *dst; - - if (info->out_route) - return; - - /* Only care about single-nexthop routes */ - if (rtnl_route_get_nnexthops (route) != 1) - return; - - if (nm_logging_level_enabled (LOGL_DEBUG)) - dump_route (route); - - if ( info->ifindex > 0 - && rtnl_route_nh_get_ifindex (rtnl_route_nexthop_n (route, 0)) != info->ifindex) - return; - - if ( info->scope != RT_SCOPE_UNIVERSE - && rtnl_route_get_scope (route) != info->scope) - return; - - if ( info->family != AF_UNSPEC - && rtnl_route_get_family (route) != info->family) - return; - - dst = rtnl_route_get_dst (route); - - /* Check for IPv6 LL and MC routes that might need to be ignored */ - if ( (info->family == AF_INET6 || info->family == AF_UNSPEC) - && (rtnl_route_get_family (route) == AF_INET6)) { - struct in6_addr *addr = NULL; - - if (dst) - addr = nl_addr_get_binary_addr (dst); - if (addr) { - if ( IN6_IS_ADDR_LINKLOCAL (addr) - || IN6_IS_ADDR_MC_LINKLOCAL (addr) - || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8))) - return; - } - } - - info->out_route = info->callback (route, dst, info->iface, info->user_data); - if (info->out_route) { - /* Ref the route so it sticks around after the cache is cleared */ - rtnl_route_get (info->out_route); - } -} - -/** - * nm_netlink_foreach_route: - * @ifindex: the interface index to filter routes for - * @family: the address family to filter routes for - * @scope: route scope, eg RT_SCOPE_LINK - * @ignore_inet6_ll_mc: if %TRUE ignore IPv6 link-local and multi-cast routes - * @callback: function called when a route matches the filter - * @user_data: data passed to @callback - * - * Filters each route in the routing table against the given @ifindex and - * @family (if given) and calls @callback for each matching route. - * - * Returns: a route if @callback returned one; the caller must dispose of the - * route using rtnl_route_put() when it is no longer required. - **/ -struct rtnl_route * -nm_netlink_foreach_route (int ifindex, - int family, - int scope, - gboolean ignore_inet6_ll_mc, - NlRouteForeachFunc callback, - gpointer user_data) -{ - struct nl_cache *cache; - ForeachRouteInfo info; - - memset (&info, 0, sizeof (info)); - info.ifindex = ifindex; - info.family = family; - info.scope = scope; - info.ignore_inet6_ll_mc = ignore_inet6_ll_mc; - info.callback = callback; - info.user_data = user_data; - info.iface = g_strdup (nm_platform_link_get_name (ifindex)); - - rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, 0, &cache); - g_warn_if_fail (cache != NULL); - if (cache) { - nl_cache_foreach (cache, foreach_route_cb, &info); - nl_cache_free (cache); - } - g_free (info.iface); - return info.out_route; -} - - diff --git a/src/nm-netlink-utils.h b/src/nm-netlink-utils.h deleted file mode 100644 index 1f7c679622..0000000000 --- a/src/nm-netlink-utils.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * 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 Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef NM_NETLINK_UTILS_H -#define NM_NETLINK_UTILS_H - -#include - -gboolean nm_netlink_find_address (int ifindex, - int family, - void *addr, /* struct in_addr or struct in6_addr */ - int prefix_); - -typedef enum { - NMNL_PROP_INVALID = 0, - NMNL_PROP_PROT, - NMNL_PROP_SCOPE, - NMNL_PROP_TABLE, - NMNL_PROP_PRIO, -} NmNlProp; - -struct rtnl_route * nm_netlink_route_new (int ifindex, - int family, - int mss, - ...) __attribute__((__sentinel__)); - -int nm_netlink_route4_add (struct rtnl_route *route, - guint32 *dst, - int prefix, - guint32 *gw, - int flags); - -int nm_netlink_route6_add (struct rtnl_route *route, - const struct in6_addr *dst, - int prefix, - const struct in6_addr *gw, - int flags); - -gboolean nm_netlink_route_delete (struct rtnl_route *route); - -/** - * NlRouteForeachFunc: - * @route: the route being processed - * @dst: the route's destination address - * @iface: the interface name of the index passed to nm_netlink_foreach_route() - * @in_family: the address family passed to nm_netlink_foreach_route() - * @user_data: the user data pointer passed to nm_netlink_foreach_route() - * - * Returns: a route to return to the caller of nm_netlink_foreach_route() which - * terminates routing table iteration, or NULL to continue iterating the - * routing table. - **/ -typedef struct rtnl_route * (*NlRouteForeachFunc) (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data); - -struct rtnl_route * nm_netlink_foreach_route (int ifindex, - int family, - int scope, - gboolean ignore_inet6_ll_mc, - NlRouteForeachFunc callback, - gpointer user_data); - -#endif /* NM_NETLINK_UTILS_H */ - diff --git a/src/nm-system.c b/src/nm-system.c index 9e21a689e5..626914e84a 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -42,9 +42,6 @@ #include #include #include -#include -#include -#include #include "nm-system.h" #include "nm-platform.h" @@ -52,20 +49,6 @@ #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-logging.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" - -#include -#include -#include -#include -#include -#include -#include - -static void nm_system_device_set_priority (int ifindex, - NMIP4Config *config, - int priority); static gboolean ip4_dest_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 dest_prefix) @@ -230,61 +213,6 @@ nm_system_apply_ip4_config (int ifindex, return TRUE; } -int -nm_system_set_ip6_route (int ifindex, - const struct in6_addr *ip6_dest, - guint32 ip6_prefix, - const struct in6_addr *ip6_gateway, - guint32 metric, - int mss, - int protocol, - int table, - struct rtnl_route **out_route) -{ - struct nl_sock *nlh; - struct rtnl_route *route; - int err = 0; - - g_return_val_if_fail (ifindex > 0, -1); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -1); - - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_PROT, protocol, - NMNL_PROP_PRIO, metric, - NMNL_PROP_TABLE, table, - NULL); - g_return_val_if_fail (route != NULL, -1); - - /* Add the route */ - err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); - if (err == -NLE_OBJ_NOTFOUND && ip6_gateway) { - /* Gateway might be over a bridge; try adding a route to gateway first */ - struct rtnl_route *route2; - - route2 = nm_netlink_route_new (ifindex, AF_INET6, mss, NULL); - if (route2) { - err = nm_netlink_route6_add (route, ip6_gateway, 128, NULL, 0); - /* Add route to gateway over bridge */ - if (!err) { - /* Try adding the route again */ - err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); - if (err) - nm_netlink_route_delete (route2); - } - rtnl_route_put (route2); - } - } - - if (out_route) - *out_route = route; - else - rtnl_route_put (route); - - return err; -} - static gboolean ip6_dest_in_same_subnet (NMIP6Config *config, const struct in6_addr *dest, guint32 dest_prefix) { @@ -460,502 +388,6 @@ nm_system_apply_ip6_config (int ifindex, return TRUE; } -static struct rtnl_route * -add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) -{ - struct nl_sock *nlh; - struct rtnl_route *route = NULL; - int err; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, NULL); - - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = nm_netlink_route_new (ifindex, AF_INET, mss, - NMNL_PROP_SCOPE, RT_SCOPE_LINK, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, NULL); - - /* Add direct route to the gateway */ - err = nm_netlink_route4_add (route, &gw, 32, NULL, 0); - if (err) { - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to add IPv4 route to gateway (%d)", - nm_platform_link_get_name (ifindex), err); - goto error; - } - - return route; - -error: - rtnl_route_put (route); - return NULL; -} - -static int -replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) -{ - struct rtnl_route *route = NULL; - struct nl_sock *nlh; - int err = -1; - guint32 dst = 0; - - g_return_val_if_fail (ifindex > 0, -ENODEV); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -ENOMEM); - - route = nm_netlink_route_new (ifindex, AF_INET, mss, - NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, -ENOMEM); - - /* Add the new default route */ - err = nm_netlink_route4_add (route, &dst, 0, &gw, NLM_F_REPLACE); - if (err == -NLE_EXIST) - err = 0; - - rtnl_route_put (route); - return err; -} - -/* - * nm_system_replace_default_ip4_route_vpn - * - * Replace default IPv4 route with one via the current device - * - */ -gboolean -nm_system_replace_default_ip4_route_vpn (int ifindex, - guint32 ext_gw, - guint32 int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss) -{ - struct rtnl_route *gw_route = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - const char *iface; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - err = replace_default_ip4_route (ifindex, int_gw, mss); - if (err == 0) - return TRUE; - - iface = nm_platform_link_get_name (ifindex); - if (!iface) - goto out; - - if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, - "(%s): failed to set IPv4 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (parent_ifindex, ext_gw, parent_mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip4_route (ifindex, int_gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, - "(%s): failed to set IPv4 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - return success; -} - -/* - * nm_system_replace_default_ip4_route - * - * Replace default IPv4 route with one via the current device - * - */ -gboolean -nm_system_replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) -{ - struct rtnl_route *gw_route = NULL; - gboolean success = FALSE; - const char *iface; - int err; - - err = replace_default_ip4_route (ifindex, gw, mss); - if (err == 0) - return TRUE; - - iface = nm_platform_link_get_name (ifindex); - if (!iface) - goto out; - - if (err != -NLE_OBJ_NOTFOUND) { - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to set IPv4 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (ifindex, gw, mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip4_route (ifindex, gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to set IPv4 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - return success; -} - -static struct rtnl_route * -add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw, int mss) -{ - struct nl_sock *nlh; - struct rtnl_route *route = NULL; - int err; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, NULL); - - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_SCOPE, RT_SCOPE_LINK, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, NULL); - - /* Add direct route to the gateway */ - err = nm_netlink_route6_add (route, gw, 128, NULL, 0); - if (err) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to add IPv6 route to gateway (%d)", - nm_platform_link_get_name (ifindex), err); - - rtnl_route_put (route); - route = NULL; - } - - return route; -} - -static int -add_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) -{ - struct rtnl_route *route = NULL; - struct nl_sock *nlh; - int err = -1; - - g_return_val_if_fail (ifindex > 0, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -ENOMEM); - - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NMNL_PROP_PRIO, 1, - NULL); - g_return_val_if_fail (route != NULL, -ENOMEM); - - /* Add the new default route */ - err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_CREATE | NLM_F_REPLACE); - if (err == -NLE_EXIST) - err = 0; - - rtnl_route_put (route); - return err; -} - -static struct rtnl_route * -find_static_default_routes (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - GList **def_routes = user_data; - - if ( nl_addr_get_prefixlen (dst) == 0 - && rtnl_route_get_protocol (route) == RTPROT_STATIC) { - rtnl_route_get (route); - *def_routes = g_list_prepend (*def_routes, route); - } - - return NULL; -} - -static int -replace_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) -{ - GList *def_routes, *iter; - struct rtnl_route *route; - char gw_str[INET6_ADDRSTRLEN + 1]; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (nm_logging_level_enabled (LOGL_DEBUG)) { - if (gw) { - memset (gw_str, 0, sizeof (gw_str)); - if (inet_ntop (AF_INET6, gw, gw_str, sizeof (gw_str) - 1)) - nm_log_dbg (LOGD_IP6, "Setting IPv6 default route via %s", gw_str); - } else { - nm_log_dbg (LOGD_IP6, "Setting IPv6 default route via %s", - nm_platform_link_get_name (ifindex)); - } - } - - /* We can't just use NLM_F_REPLACE here like in the IPv4 case, because - * the kernel doesn't like it if we replace the default routes it - * creates. (See rh#785772.) So we delete any non-kernel default routes, - * and then add a new default route of our own with a lower metric than - * the kernel ones. - */ - def_routes = NULL; - nm_netlink_foreach_route (ifindex, AF_INET6, RT_SCOPE_UNIVERSE, TRUE, - find_static_default_routes, &def_routes); - for (iter = def_routes; iter; iter = iter->next) { - route = iter->data; - if (!nm_netlink_route_delete (route)) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to delete existing IPv6 default route", - nm_platform_link_get_name (ifindex)); - } - rtnl_route_put (route); - } - g_list_free (def_routes); - - return add_default_ip6_route (ifindex, gw, mss); -} - -/* - * nm_system_replace_default_ip6_route - * - * Replace default IPv6 route with one via the given gateway - * - */ -gboolean -nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw) -{ - struct rtnl_route *gw_route = NULL; - gboolean success = FALSE; - const char *iface; - int err; - - err = replace_default_ip6_route (ifindex, gw, 0); - if (err == 0 || err == -NLE_EXIST) - return TRUE; - - iface = nm_platform_link_get_name (ifindex); - if (!iface) - goto out; - - if (err != -NLE_OBJ_NOTFOUND) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to set IPv6 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (ifindex, gw, 0); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip6_route (ifindex, gw, 0); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to set IPv6 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - return success; -} - -gboolean -nm_system_replace_default_ip6_route_vpn (int ifindex, - const struct in6_addr *ext_gw, - const struct in6_addr *int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss) -{ - struct rtnl_route *gw_route = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - const char *iface; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - err = replace_default_ip6_route (ifindex, int_gw, mss); - if (err == 0) - return TRUE; - - iface = nm_platform_link_get_name (ifindex); - if (!iface) - goto out; - - if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, - "(%s): failed to set IPv6 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (parent_ifindex, ext_gw, parent_mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip6_route (ifindex, int_gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, - "(%s): failed to set IPv6 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - return success; -} - -static struct rtnl_route * -delete_one_route (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - guint32 log_level = GPOINTER_TO_UINT (user_data); - - nm_log_dbg (log_level, " deleting route"); - if (!nm_netlink_route_delete (route)) - nm_log_err (LOGD_DEVICE, "(%s): failed to delete route", iface); - - return NULL; -} - -/** - * nm_system_iface_flush_routes: - * @ifindex: interface index - * @family: address family, i.e. AF_INET, AF_INET6, or AF_UNSPEC - * - * Flush all network addresses associated with a network device. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_flush_routes (int ifindex, int family) -{ - guint32 log_level = LOGD_IP4 | LOGD_IP6; - const char *sf = "UNSPEC"; - const char *iface; - - g_return_val_if_fail (ifindex > 0, FALSE); - - iface = nm_platform_link_get_name (ifindex); - g_return_val_if_fail (iface != NULL, FALSE); - - if (family == AF_INET) { - log_level = LOGD_IP4; - sf = "INET"; - } else if (family == AF_INET6) { - log_level = LOGD_IP6; - sf = "INET6"; - } - nm_log_dbg (log_level, "(%s): flushing routes ifindex %d family %s (%d)", - iface, ifindex, sf, family); - - /* We don't want to flush IPv6 link-local routes that may exist on the - * the interface since the LL address and routes should normally stay - * assigned all the time. - */ - nm_netlink_foreach_route (ifindex, family, RT_SCOPE_UNIVERSE, TRUE, delete_one_route, GUINT_TO_POINTER (log_level)); - - return TRUE; -} - -static struct rtnl_route * -find_route (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - NMIP4Config *config = user_data; - struct in_addr *dst_addr; - int num; - int i; - - if (dst && (nl_addr_get_family (dst) != AF_INET)) - return NULL; - - /* Find the first route that handles a subnet of at least one of the - * device's IPv4 addresses. - */ - dst_addr = nl_addr_get_binary_addr (dst); - num = nm_ip4_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_ip4_config_get_address (config, i); - guint32 prefix = nm_ip4_address_get_prefix (addr); - guint32 address = nm_ip4_address_get_address (addr); - - if ( prefix == nl_addr_get_prefixlen (dst) - && (address & nm_utils_ip4_prefix_to_netmask (prefix)) == dst_addr->s_addr) - return route; - } - return NULL; -} - -static void -nm_system_device_set_priority (int ifindex, - NMIP4Config *config, - int priority) -{ - struct nl_sock *nlh; - struct rtnl_route *found; - - found = nm_netlink_foreach_route (ifindex, AF_INET, RT_SCOPE_LINK, FALSE, find_route, config); - if (found) { - nlh = nm_netlink_get_default_handle (); - nm_netlink_route_delete (found); - rtnl_route_set_priority (found, priority); - rtnl_route_add (nlh, found, 0); - rtnl_route_put (found); - } -} - static const struct { const char *option; const char *default_value; diff --git a/src/nm-system.h b/src/nm-system.h index 56b46bc3e8..3757601d8e 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -22,59 +22,21 @@ #ifndef NETWORK_MANAGER_SYSTEM_H #define NETWORK_MANAGER_SYSTEM_H -#include -#include - #include "nm-platform.h" #include "nm-device.h" #include "nm-ip4-config.h" #include "nm-setting-bond.h" -gboolean nm_system_iface_flush_routes (int ifindex, int family); - -gboolean nm_system_replace_default_ip4_route (int ifindex, - guint32 gw, - guint32 mss); - -gboolean nm_system_replace_default_ip6_route (int ifindex, - const struct in6_addr *gw); - -gboolean nm_system_replace_default_ip4_route_vpn (int ifindex, - guint32 ext_gw, - guint32 int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss); - -gboolean nm_system_replace_default_ip6_route_vpn (int ifindex, - const struct in6_addr *ext_gw, - const struct in6_addr *int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss); - NMPlatformIP4Route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw); NMPlatformIP6Route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, const struct in6_addr *vpn_gw); -gboolean nm_system_iface_flush_addresses (int ifindex, int family); - gboolean nm_system_apply_ip4_config (int ifindex, NMIP4Config *config, int priority, NMIP4ConfigCompareFlags flags); -int nm_system_set_ip6_route (int ifindex, - const struct in6_addr *ip6_dest, - guint32 ip6_prefix, - const struct in6_addr *ip6_gateway, - guint32 metric, - int mss, - int protocol, - int table, - struct rtnl_route **out_route); - gboolean nm_system_apply_ip6_config (int ifindex, NMIP6Config *config, int priority,