mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-04 01:40:16 +01:00
Merge branch 'libnl3'
This commit is contained in:
commit
0fe8c80fae
22 changed files with 1335 additions and 786 deletions
39
configure.ac
39
configure.ac
|
|
@ -312,10 +312,43 @@ else
|
|||
fi
|
||||
AC_DEFINE_UNQUOTED(NO_CONSOLEKIT, $no_ck, [Define to disable use of ConsoleKit])
|
||||
|
||||
PKG_CHECK_MODULES(LIBNL, libnl-1 >= 1.0-pre8)
|
||||
have_libnl="no"
|
||||
PKG_CHECK_MODULES(LIBNL1, libnl-1 >= 1.0-pre8, [have_libnl1=yes], [have_libnl1=no])
|
||||
if (test "${have_libnl1}" = "yes"); then
|
||||
AC_DEFINE(HAVE_LIBNL1, 1, [Define if you require libnl-1 legacy support])
|
||||
LIBNL_CFLAGS="$LIBNL1_CFLAGS"
|
||||
LIBNL_LIBS="$LIBNL1_LIBS"
|
||||
libnl_version="1"
|
||||
have_libnl="yes"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(LIBNL2, libnl-2.0, [have_libnl2=yes], [have_libnl2=no])
|
||||
if (test "${have_libnl2}" = "yes"); then
|
||||
AC_DEFINE(HAVE_LIBNL2, 1, [Define if you require specific libnl-2 support])
|
||||
LIBNL_CFLAGS="$LIBNL2_CFLAGS"
|
||||
LIBNL_LIBS="$LIBNL2_LIBS"
|
||||
libnl_version="2"
|
||||
have_libnl="yes"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [have_libnl2=yes], [have_libnl2=no])
|
||||
if (test "${have_libnl2}" = "yes"); then
|
||||
AC_DEFINE(HAVE_LIBNL3, 1, [Define if you require specific libnl-3 support])
|
||||
LIBNL_CFLAGS="$LIBNL3_CFLAGS"
|
||||
LIBNL_LIBS="$LIBNL3_LIBS"
|
||||
libnl_version="3"
|
||||
have_libnl="yes"
|
||||
fi
|
||||
|
||||
if (test "${have_libnl}" = "no"); then
|
||||
AC_MSG_ERROR([libnl development header are required])
|
||||
fi
|
||||
AC_SUBST(LIBNL_CFLAGS)
|
||||
AC_SUBST(LIBNL_LIBS)
|
||||
NM_LIBNL_CHECK
|
||||
|
||||
if (test "${libnl_version}" = "1"); then
|
||||
NM_LIBNL_CHECK
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(UUID, uuid)
|
||||
AC_SUBST(UUID_CFLAGS)
|
||||
|
|
@ -738,6 +771,8 @@ else
|
|||
echo PPP support: no
|
||||
fi
|
||||
|
||||
echo libnl version: ${libnl_version}
|
||||
|
||||
echo
|
||||
echo Building documentation: ${with_docs}
|
||||
echo Building tests: ${with_tests}
|
||||
|
|
|
|||
|
|
@ -159,6 +159,10 @@ NetworkManager_SOURCES = \
|
|||
nm-manager-auth.h \
|
||||
nm-netlink-monitor.c \
|
||||
nm-netlink-monitor.h \
|
||||
nm-netlink-utils.c \
|
||||
nm-netlink-utils.h \
|
||||
nm-netlink-compat.h \
|
||||
nm-netlink-compat.c \
|
||||
nm-activation-request.c \
|
||||
nm-activation-request.h \
|
||||
nm-properties-changed-signal.c \
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-utils.h"
|
||||
|
|
@ -43,9 +44,6 @@
|
|||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-manager-auth.h"
|
||||
|
||||
#include <netlink/addr.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
/*
|
||||
* nm_ethernet_address_is_valid
|
||||
*
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@
|
|||
#include "nm-system.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-netlink-compat.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
|
||||
/* Because of a bug in libnl, rtnl.h should be included before route.h */
|
||||
#include <netlink/route/rtnl.h>
|
||||
|
|
@ -50,15 +52,13 @@
|
|||
*/
|
||||
void nm_generic_enable_loopback (void)
|
||||
{
|
||||
struct nl_handle * nlh = NULL;
|
||||
struct nl_sock * nlh = NULL;
|
||||
struct rtnl_addr * addr = NULL;
|
||||
struct nl_addr * nl_addr = NULL;
|
||||
guint32 binaddr = 0;
|
||||
int iface_idx = -1;
|
||||
int err;
|
||||
|
||||
nm_system_device_set_up_down_with_iface ("lo", TRUE, NULL);
|
||||
|
||||
nlh = nm_netlink_get_default_handle ();
|
||||
if (!nlh)
|
||||
return;
|
||||
|
|
@ -67,6 +67,8 @@ void nm_generic_enable_loopback (void)
|
|||
if (iface_idx < 0)
|
||||
return;
|
||||
|
||||
nm_system_iface_set_up (iface_idx, TRUE, NULL);
|
||||
|
||||
addr = rtnl_addr_alloc ();
|
||||
if (!addr)
|
||||
return;
|
||||
|
|
@ -90,10 +92,10 @@ void nm_generic_enable_loopback (void)
|
|||
rtnl_addr_set_scope (addr, RT_SCOPE_HOST);
|
||||
rtnl_addr_set_label (addr, "lo");
|
||||
|
||||
if ((err = rtnl_addr_add (nlh, addr, 0)) < 0) {
|
||||
if (err != -EEXIST) {
|
||||
nm_log_warn (LOGD_CORE, "error %d returned from rtnl_addr_add():\n%s", err, nl_geterror());
|
||||
}
|
||||
err = rtnl_addr_add (nlh, addr, 0);
|
||||
if (err && (err != -NLE_EXIST)) {
|
||||
nm_log_warn (LOGD_CORE, "error setting loopback address: (%d) %s",
|
||||
err, nl_geterror (err));
|
||||
}
|
||||
out:
|
||||
if (addr)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "nm-ip6-manager.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
#include "nm-netlink-compat.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-marshal.h"
|
||||
#include "nm-logging.h"
|
||||
|
|
@ -44,7 +46,7 @@ typedef struct {
|
|||
NMNetlinkMonitor *monitor;
|
||||
GHashTable *devices;
|
||||
|
||||
struct nl_handle *nlh;
|
||||
struct nl_sock *nlh;
|
||||
struct nl_cache *addr_cache, *route_cache;
|
||||
|
||||
guint netlink_id;
|
||||
|
|
@ -553,7 +555,7 @@ process_addr (NMIP6Manager *manager, struct nl_msg *msg)
|
|||
}
|
||||
|
||||
old_size = nl_cache_nitems (priv->addr_cache);
|
||||
nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL);
|
||||
nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL);
|
||||
rtnl_addr_put (rtnladdr);
|
||||
|
||||
/* The kernel will re-notify us of automatically-added addresses
|
||||
|
|
@ -593,7 +595,7 @@ process_route (NMIP6Manager *manager, struct nl_msg *msg)
|
|||
}
|
||||
|
||||
old_size = nl_cache_nitems (priv->route_cache);
|
||||
nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL);
|
||||
nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL);
|
||||
rtnl_route_put (rtnlroute);
|
||||
|
||||
/* As above in process_addr */
|
||||
|
|
@ -1248,7 +1250,7 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
|
|||
nm_ip6_route_set_dest (ip6route, dest);
|
||||
nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute));
|
||||
nm_ip6_route_set_next_hop (ip6route, gateway);
|
||||
metric = rtnl_route_get_metric (rtnlroute, 1);
|
||||
rtnl_route_get_metric(rtnlroute, 1, &metric);
|
||||
if (metric != UINT_MAX)
|
||||
nm_ip6_route_set_metric (ip6route, metric);
|
||||
nm_ip6_config_take_route (config, ip6route);
|
||||
|
|
@ -1344,8 +1346,10 @@ nm_ip6_manager_init (NMIP6Manager *manager)
|
|||
G_CALLBACK (netlink_notification), manager);
|
||||
|
||||
priv->nlh = nm_netlink_get_default_handle ();
|
||||
priv->addr_cache = rtnl_addr_alloc_cache (priv->nlh);
|
||||
priv->route_cache = rtnl_route_alloc_cache (priv->nlh);
|
||||
rtnl_addr_alloc_cache (priv->nlh, &priv->addr_cache);
|
||||
g_warn_if_fail (priv->addr_cache != NULL);
|
||||
rtnl_route_alloc_cache (priv->nlh, NETLINK_ROUTE, NL_AUTO_PROVIDE, &priv->route_cache);
|
||||
g_warn_if_fail (priv->route_cache != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ static void
|
|||
real_deactivate (NMModem *self, NMDevice *device)
|
||||
{
|
||||
NMModemPrivate *priv;
|
||||
const char *iface;
|
||||
int ifindex;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (NM_IS_MODEM (self));
|
||||
|
|
@ -679,11 +679,11 @@ real_deactivate (NMModem *self, NMDevice *device)
|
|||
break;
|
||||
case MM_MODEM_IP_METHOD_STATIC:
|
||||
case MM_MODEM_IP_METHOD_DHCP:
|
||||
iface = nm_device_get_ip_iface (device);
|
||||
ifindex = nm_device_get_ip_ifindex (device);
|
||||
/* FIXME: use AF_UNSPEC here when we have IPv6 support */
|
||||
nm_system_device_flush_routes_with_iface (iface, AF_INET);
|
||||
nm_system_device_flush_addresses_with_iface (iface);
|
||||
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL);
|
||||
nm_system_iface_flush_routes (ifindex, AF_INET);
|
||||
nm_system_iface_flush_addresses (ifindex, AF_UNSPEC);
|
||||
nm_system_iface_set_up (ifindex, FALSE, NULL);
|
||||
break;
|
||||
default:
|
||||
nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method);
|
||||
|
|
@ -775,7 +775,7 @@ nm_modem_hw_is_up (NMModem *self, NMDevice *device)
|
|||
|
||||
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
|
||||
if (priv->pending_ip4_config || _state_is_active (state))
|
||||
return nm_system_device_is_up (device);
|
||||
return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -792,7 +792,7 @@ nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware)
|
|||
|
||||
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
|
||||
if (priv->pending_ip4_config || _state_is_active (state))
|
||||
return nm_system_device_set_up_down (device, TRUE, no_firmware);
|
||||
return nm_system_iface_set_up (nm_device_get_ip_ifindex (device), TRUE, no_firmware);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include "nm-logging.h"
|
||||
#include "nm-properties-changed-signal.h"
|
||||
#include "nm-dhcp-manager.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
|
||||
#include "nm-device-ethernet-glue.h"
|
||||
|
||||
|
|
@ -546,19 +547,19 @@ real_take_down (NMDevice *dev)
|
|||
static gboolean
|
||||
real_hw_is_up (NMDevice *device)
|
||||
{
|
||||
return nm_system_device_is_up (device);
|
||||
return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
|
||||
{
|
||||
return nm_system_device_set_up_down (dev, TRUE, no_firmware);
|
||||
return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
|
||||
}
|
||||
|
||||
static void
|
||||
real_hw_take_down (NMDevice *dev)
|
||||
{
|
||||
nm_system_device_set_up_down (dev, FALSE, NULL);
|
||||
nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
|
|
@ -677,7 +678,7 @@ _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
|
|||
/* Can't change MAC address while device is up */
|
||||
real_hw_take_down (dev);
|
||||
|
||||
success = nm_system_device_set_mac (iface, (struct ether_addr *) addr);
|
||||
success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr);
|
||||
if (success) {
|
||||
/* MAC address succesfully changed; update the current MAC to match */
|
||||
_update_hw_addr (self, addr);
|
||||
|
|
@ -1796,73 +1797,19 @@ wired_match_config (NMDevice *self, NMConnection *connection)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int ifindex;
|
||||
NMIP4Address *addr;
|
||||
gboolean found;
|
||||
} AddrData;
|
||||
|
||||
static void
|
||||
check_one_address (struct nl_object *object, void *user_data)
|
||||
{
|
||||
AddrData *data = user_data;
|
||||
struct rtnl_addr *addr = (struct rtnl_addr *) object;
|
||||
struct nl_addr *local;
|
||||
struct in_addr tmp;
|
||||
|
||||
if (rtnl_addr_get_ifindex (addr) != data->ifindex)
|
||||
return;
|
||||
if (rtnl_addr_get_family (addr) != AF_INET)
|
||||
return;
|
||||
|
||||
if (nm_ip4_address_get_prefix (data->addr) != rtnl_addr_get_prefixlen (addr))
|
||||
return;
|
||||
|
||||
local = rtnl_addr_get_local (addr);
|
||||
if (nl_addr_get_family (local) != AF_INET)
|
||||
return;
|
||||
if (nl_addr_get_len (local) != sizeof (struct in_addr))
|
||||
return;
|
||||
if (!nl_addr_get_binary_addr (local))
|
||||
return;
|
||||
|
||||
memcpy (&tmp, nl_addr_get_binary_addr (local), nl_addr_get_len (local));
|
||||
if (tmp.s_addr != nm_ip4_address_get_address (data->addr))
|
||||
return;
|
||||
|
||||
/* Yay, found it */
|
||||
data->found = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_match_config (NMDevice *self, NMConnection *connection)
|
||||
{
|
||||
NMSettingIP4Config *s_ip4;
|
||||
struct nl_handle *nlh = NULL;
|
||||
struct nl_cache *addr_cache = NULL;
|
||||
int i, num;
|
||||
GSList *leases, *iter;
|
||||
NMDHCPManager *dhcp_mgr;
|
||||
const char *method;
|
||||
int ifindex;
|
||||
AddrData check_data;
|
||||
|
||||
ifindex = nm_device_get_ifindex (self);
|
||||
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (!s_ip4)
|
||||
return FALSE;
|
||||
|
||||
/* Read all the device's IP addresses */
|
||||
nlh = nm_netlink_get_default_handle ();
|
||||
if (!nlh)
|
||||
return FALSE;
|
||||
|
||||
addr_cache = rtnl_addr_alloc_cache (nlh);
|
||||
if (!addr_cache)
|
||||
return FALSE;
|
||||
nl_cache_mngt_provide (addr_cache);
|
||||
|
||||
/* Get any saved leases that apply to this connection */
|
||||
dhcp_mgr = nm_dhcp_manager_get ();
|
||||
leases = nm_dhcp_manager_get_lease_config (dhcp_mgr,
|
||||
|
|
@ -1876,15 +1823,14 @@ ip4_match_config (NMDevice *self, NMConnection *connection)
|
|||
|
||||
/* Find at least one lease's address on the device */
|
||||
for (iter = leases; iter; iter = g_slist_next (iter)) {
|
||||
NMIP4Config *addr = iter->data;
|
||||
NMIP4Config *ip4_config = iter->data;
|
||||
NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0);
|
||||
struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
|
||||
|
||||
memset (&check_data, 0, sizeof (check_data));
|
||||
check_data.ifindex = ifindex;
|
||||
check_data.found = FALSE;
|
||||
check_data.addr = nm_ip4_config_get_address (addr, 0);
|
||||
|
||||
nl_cache_foreach (addr_cache, check_one_address, &check_data);
|
||||
if (check_data.found) {
|
||||
if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self),
|
||||
AF_INET,
|
||||
&tmp,
|
||||
nm_ip4_address_get_prefix (addr))) {
|
||||
found = TRUE; /* Yay, device has same address as a lease */
|
||||
break;
|
||||
}
|
||||
|
|
@ -1908,16 +1854,16 @@ ip4_match_config (NMDevice *self, NMConnection *connection)
|
|||
|
||||
/* Everything below for static addressing */
|
||||
|
||||
/* Find all IP4 addresses of this connection in the device's address list */
|
||||
/* Find all IP4 addresses of this connection on the device */
|
||||
num = nm_setting_ip4_config_get_num_addresses (s_ip4);
|
||||
for (i = 0; i < num; i++) {
|
||||
memset (&check_data, 0, sizeof (check_data));
|
||||
check_data.ifindex = ifindex;
|
||||
check_data.found = FALSE;
|
||||
check_data.addr = nm_setting_ip4_config_get_address (s_ip4, i);
|
||||
NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i);
|
||||
struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
|
||||
|
||||
nl_cache_foreach (addr_cache, check_one_address, &check_data);
|
||||
if (!check_data.found)
|
||||
if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self),
|
||||
AF_INET,
|
||||
&tmp,
|
||||
nm_ip4_address_get_prefix (addr)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -271,19 +271,19 @@ error:
|
|||
static gboolean
|
||||
real_hw_is_up (NMDevice *device)
|
||||
{
|
||||
return nm_system_device_is_up (device);
|
||||
return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
|
||||
{
|
||||
return nm_system_device_set_up_down (dev, TRUE, no_firmware);
|
||||
return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
|
||||
}
|
||||
|
||||
static void
|
||||
real_hw_take_down (NMDevice *dev)
|
||||
{
|
||||
nm_system_device_set_up_down (dev, FALSE, NULL);
|
||||
nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -1133,7 +1133,7 @@ out:
|
|||
static gboolean
|
||||
real_hw_is_up (NMDevice *device)
|
||||
{
|
||||
return nm_system_device_is_up (device);
|
||||
return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1142,13 +1142,13 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
|
|||
if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled)
|
||||
return FALSE;
|
||||
|
||||
return nm_system_device_set_up_down (device, TRUE, no_firmware);
|
||||
return nm_system_iface_set_up (nm_device_get_ip_ifindex (device), TRUE, no_firmware);
|
||||
}
|
||||
|
||||
static void
|
||||
real_hw_take_down (NMDevice *dev)
|
||||
real_hw_take_down (NMDevice *device)
|
||||
{
|
||||
nm_system_device_set_up_down (dev, FALSE, NULL);
|
||||
nm_system_iface_set_up (nm_device_get_ip_ifindex (device), FALSE, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1209,7 +1209,7 @@ _set_hw_addr (NMDeviceWifi *self, const guint8 *addr, const char *detail)
|
|||
/* Can't change MAC address while device is up */
|
||||
real_hw_take_down (dev);
|
||||
|
||||
success = nm_system_device_set_mac (iface, (struct ether_addr *) addr);
|
||||
success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr);
|
||||
if (success) {
|
||||
/* MAC address succesfully changed; update the current MAC to match */
|
||||
_update_hw_addr (self, addr);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#include "nm-utils.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
#include "nm-netlink-compat.h"
|
||||
#include "nm-setting-ip4-config.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "nm-setting-connection.h"
|
||||
|
|
@ -1591,16 +1593,15 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
|
|||
NMSettingIP4Config *s_ip4;
|
||||
NMActRequest *req;
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
const char *ip_iface, *method = NULL;
|
||||
const char *method = NULL;
|
||||
int ifindex;
|
||||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
/* Use the IP interface (not the control interface) for IP stuff */
|
||||
ip_iface = nm_device_get_ip_iface (self);
|
||||
|
||||
/* Make sure the interface is up before trying to do anything with it */
|
||||
if (!nm_system_device_is_up_with_iface (ip_iface))
|
||||
nm_system_device_set_up_down_with_iface (ip_iface, TRUE, NULL);
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (!nm_system_iface_is_up (ifindex))
|
||||
nm_system_iface_set_up (ifindex, TRUE, NULL);
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
connection = nm_act_request_get_connection (req);
|
||||
|
|
@ -1680,10 +1681,10 @@ dhcp6_start (NMDevice *self,
|
|||
*/
|
||||
err = nm_system_set_ip6_route (priv->ip_iface ? priv->ip_ifindex : priv->ifindex,
|
||||
&dest, 8, NULL, 256, 0, RTPROT_BOOT, RT_TABLE_LOCAL, NULL);
|
||||
if (err && (nl_get_errno () != EEXIST)) {
|
||||
if (err && (err != -NLE_EXIST)) {
|
||||
nm_log_err (LOGD_DEVICE | LOGD_IP6,
|
||||
"(%s): failed to add IPv6 multicast route: %s",
|
||||
priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror ());
|
||||
priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror (err));
|
||||
}
|
||||
|
||||
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
|
|
@ -2820,6 +2821,7 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
||||
gboolean tried_ipv6 = FALSE;
|
||||
int ifindex, family;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
|
|
@ -2857,8 +2859,10 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
|
|||
clear_act_request (self);
|
||||
|
||||
/* Take out any entries in the routing table and any IP address the device had. */
|
||||
nm_system_device_flush_routes (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
|
||||
nm_system_device_flush_addresses (self, tried_ipv6 ? AF_UNSPEC : AF_INET);
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
family = tried_ipv6 ? AF_UNSPEC : AF_INET;
|
||||
nm_system_iface_flush_routes (ifindex, family);
|
||||
nm_system_iface_flush_addresses (ifindex, family);
|
||||
nm_device_update_ip4_address (self);
|
||||
|
||||
/* Clean up nameservers and addresses */
|
||||
|
|
@ -3009,6 +3013,7 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||
gboolean success = TRUE;
|
||||
NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL;
|
||||
NMDnsManager *dns_mgr;
|
||||
int ip_ifindex;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
g_return_val_if_fail (reason != NULL, FALSE);
|
||||
|
|
@ -3039,8 +3044,10 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||
/* Don't touch the device's actual IP config if the connection is
|
||||
* assumed when NM starts.
|
||||
*/
|
||||
if (!assumed)
|
||||
success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff);
|
||||
if (!assumed) {
|
||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
||||
success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self), diff);
|
||||
}
|
||||
|
||||
if (success || assumed) {
|
||||
/* Export over D-Bus */
|
||||
|
|
@ -3112,12 +3119,14 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
gboolean success = TRUE;
|
||||
NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL;
|
||||
NMDnsManager *dns_mgr;
|
||||
int ip_ifindex;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
g_return_val_if_fail (reason != NULL, FALSE);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
ip_iface = nm_device_get_ip_iface (self);
|
||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
||||
|
||||
old_config = priv->ip6_config;
|
||||
|
||||
|
|
@ -3143,7 +3152,7 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
* assumed when NM starts.
|
||||
*/
|
||||
if (!assumed)
|
||||
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
|
||||
success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff);
|
||||
|
||||
if (success || assumed) {
|
||||
/* Export over D-Bus */
|
||||
|
|
|
|||
105
src/nm-netlink-compat.c
Normal file
105
src/nm-netlink-compat.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- 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 Caixa Magica Software.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "nm-netlink-compat.h"
|
||||
|
||||
#ifndef HAVE_LIBNL1
|
||||
struct rtnl_nexthop *
|
||||
nm_netlink_get_nh (struct rtnl_route * route)
|
||||
{
|
||||
int hops;
|
||||
|
||||
hops = rtnl_route_get_nnexthops (route);
|
||||
g_return_val_if_fail(hops > 0, NULL);
|
||||
return rtnl_route_nexthop_n (route, 0);
|
||||
}
|
||||
|
||||
int
|
||||
rtnl_route_get_oif (struct rtnl_route * route)
|
||||
{
|
||||
struct rtnl_nexthop * nh;
|
||||
|
||||
nh = nm_netlink_get_nh(route);
|
||||
g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND);
|
||||
return rtnl_route_nh_get_ifindex (nh);
|
||||
}
|
||||
|
||||
int
|
||||
rtnl_route_set_oif (struct rtnl_route * route, int ifindex)
|
||||
{
|
||||
struct rtnl_nexthop * nh;
|
||||
|
||||
nh = rtnl_route_nh_alloc();
|
||||
rtnl_route_nh_set_ifindex(nh, ifindex);
|
||||
rtnl_route_add_nexthop(route, nh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nl_addr *
|
||||
rtnl_route_get_gateway (struct rtnl_route * route)
|
||||
{
|
||||
struct rtnl_nexthop * nh;
|
||||
|
||||
nh = nm_netlink_get_nh(route);
|
||||
g_return_val_if_fail(nh, NULL);
|
||||
return rtnl_route_nh_get_gateway(nh);
|
||||
}
|
||||
|
||||
int
|
||||
rtnl_route_set_gateway (struct rtnl_route * route, struct nl_addr * gw_addr)
|
||||
{
|
||||
struct rtnl_nexthop * nh;
|
||||
|
||||
nh = nm_netlink_get_nh(route);
|
||||
g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND);
|
||||
|
||||
rtnl_route_nh_set_gateway(nh, gw_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rtnl_route_get_dst_len(struct rtnl_route * rtnlroute)
|
||||
{
|
||||
struct nl_addr * dst;
|
||||
|
||||
dst = rtnl_route_get_dst(rtnlroute);
|
||||
return nl_addr_get_prefixlen(dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNL1
|
||||
int
|
||||
nl_compat_error (int err)
|
||||
{
|
||||
err = abs (err);
|
||||
|
||||
if (err == EEXIST)
|
||||
err = NLE_EXIST;
|
||||
else if (err == ENOENT || err == ESRCH)
|
||||
err = NLE_OBJ_NOTFOUND;
|
||||
else if (err == ERANGE)
|
||||
err = NLE_RANGE;
|
||||
|
||||
return -err;
|
||||
}
|
||||
#endif
|
||||
197
src/nm-netlink-compat.h
Normal file
197
src/nm-netlink-compat.h
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/* -*- 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 Caixa Magica Software.
|
||||
*/
|
||||
|
||||
#ifndef NM_NETLINK_COMPAT_H
|
||||
#define NM_NETLINK_COMPAT_H
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/addr.h>
|
||||
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/nexthop.h>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* libnl-1 API compatibility for libnl-2/3*/
|
||||
#ifndef HAVE_LIBNL1
|
||||
|
||||
struct rtnl_nexthop * nm_netlink_get_nh(struct rtnl_route *);
|
||||
int rtnl_route_get_oif(struct rtnl_route *);
|
||||
int rtnl_route_set_oif(struct rtnl_route *, int);
|
||||
int rtnl_route_set_gateway(struct rtnl_route *, struct nl_addr *);
|
||||
int rtnl_route_get_dst_len(struct rtnl_route *);
|
||||
struct nl_addr * rtnl_route_get_gateway(struct rtnl_route *);
|
||||
#endif
|
||||
|
||||
/* libnl-2 API compatibility for libnl-3 */
|
||||
#ifdef HAVE_LIBNL3
|
||||
static inline int
|
||||
__rtnl_link_alloc_cache (struct nl_sock *h, struct nl_cache **cache)
|
||||
{
|
||||
return rtnl_link_alloc_cache (h, AF_UNSPEC, cache);
|
||||
}
|
||||
#define rtnl_link_alloc_cache __rtnl_link_alloc_cache
|
||||
#endif
|
||||
|
||||
/* libnl-1.0 compat functions */
|
||||
#ifdef HAVE_LIBNL1
|
||||
|
||||
#define nl_sock nl_handle
|
||||
|
||||
/* libnl-1.0 functions with similar prototypes */
|
||||
#define nl_socket_alloc nl_handle_alloc
|
||||
#define nl_socket_alloc_cb nl_handle_alloc_cb
|
||||
#define nl_socket_free nl_handle_destroy
|
||||
#define nl_socket_set_passcred nl_set_passcred
|
||||
#define nl_socket_disable_seq_check nl_disable_sequence_check
|
||||
#define rtnl_route_set_priority rtnl_route_set_prio
|
||||
|
||||
/* auxiliary functions */
|
||||
int nl_compat_error (int);
|
||||
|
||||
/* libnl-1.0 functions with modified prototypes in libnl-2/3*/
|
||||
static inline const char *
|
||||
__nl_geterror (int err)
|
||||
{
|
||||
/* err is set, can be parsed */
|
||||
return nl_geterror ();
|
||||
}
|
||||
#define nl_geterror __nl_geterror
|
||||
|
||||
static inline int
|
||||
__rtnl_addr_alloc_cache (struct nl_sock *h, struct nl_cache **cache)
|
||||
{
|
||||
g_return_val_if_fail (cache != NULL, -EINVAL);
|
||||
|
||||
*cache = rtnl_addr_alloc_cache (h);
|
||||
return *cache ? 0 : -ENOMEM;
|
||||
}
|
||||
#define rtnl_addr_alloc_cache __rtnl_addr_alloc_cache
|
||||
|
||||
static inline int
|
||||
__rtnl_route_alloc_cache (struct nl_sock *h, int family, int flags, struct nl_cache **cache)
|
||||
{
|
||||
g_return_val_if_fail (cache != NULL, -EINVAL);
|
||||
|
||||
*cache = rtnl_route_alloc_cache (h);
|
||||
return *cache ? 0 : -ENOMEM;
|
||||
}
|
||||
#define rtnl_route_alloc_cache __rtnl_route_alloc_cache
|
||||
|
||||
static inline int
|
||||
__rtnl_link_alloc_cache (struct nl_sock *h, struct nl_cache **cache)
|
||||
{
|
||||
g_return_val_if_fail (cache != NULL, -EINVAL);
|
||||
|
||||
*cache = rtnl_link_alloc_cache (h);
|
||||
return *cache ? 0 : -ENOMEM;
|
||||
}
|
||||
#define rtnl_link_alloc_cache __rtnl_link_alloc_cache
|
||||
|
||||
static inline int
|
||||
__rtnl_route_get_metric (struct rtnl_route *route, int metric, unsigned int *value)
|
||||
{
|
||||
g_return_val_if_fail (value != NULL, -EINVAL);
|
||||
|
||||
*value = rtnl_route_get_metric (route, metric);
|
||||
return 0;
|
||||
}
|
||||
#define rtnl_route_get_metric __rtnl_route_get_metric
|
||||
|
||||
static inline int
|
||||
__rtnl_addr_add (struct nl_sock *h, struct rtnl_addr *addr, int flags)
|
||||
{
|
||||
return nl_compat_error (rtnl_addr_add (h, addr, flags));
|
||||
}
|
||||
#define rtnl_addr_add __rtnl_addr_add
|
||||
|
||||
static inline int
|
||||
__rtnl_route_add (struct nl_sock *sk, struct rtnl_route *route, int flags)
|
||||
{
|
||||
return nl_compat_error (rtnl_route_add (sk, route, flags));
|
||||
}
|
||||
#define rtnl_route_add __rtnl_route_add
|
||||
|
||||
static inline int
|
||||
rtnl_route_delete (struct nl_sock *h, struct rtnl_route *route, int flags)
|
||||
{
|
||||
return nl_compat_error (rtnl_route_del (h, route, flags));
|
||||
}
|
||||
#define rtnl_route_del rtnl_route_delete
|
||||
|
||||
static inline int
|
||||
__rtnl_link_change (struct nl_sock *h, struct rtnl_link *old, struct rtnl_link *tmpl, int flags)
|
||||
{
|
||||
return nl_compat_error (rtnl_link_change (h, old, tmpl,flags));
|
||||
}
|
||||
#define rtnl_link_change __rtnl_link_change
|
||||
|
||||
static inline int
|
||||
__nl_cache_include (struct nl_cache *cache, struct nl_object *obj, change_func_t cb, void *data)
|
||||
{
|
||||
return nl_cache_include (cache, obj, cb);
|
||||
}
|
||||
#define nl_cache_include __nl_cache_include
|
||||
|
||||
#define NLE_SUCCESS 0
|
||||
#define NLE_FAILURE 1
|
||||
#define NLE_INTR 2
|
||||
#define NLE_BAD_SOCK 3
|
||||
#define NLE_AGAIN 4
|
||||
#define NLE_NOMEM 5
|
||||
#define NLE_EXIST 6
|
||||
#define NLE_INVAL 7
|
||||
#define NLE_RANGE 8
|
||||
#define NLE_MSGSIZE 9
|
||||
#define NLE_OPNOTSUPP 10
|
||||
#define NLE_AF_NOSUPPORT 11
|
||||
#define NLE_OBJ_NOTFOUND 12
|
||||
#define NLE_NOATTR 13
|
||||
#define NLE_MISSING_ATTR 14
|
||||
#define NLE_AF_MISMATCH 15
|
||||
#define NLE_SEQ_MISMATCH 16
|
||||
#define NLE_MSG_OVERFLOW 17
|
||||
#define NLE_MSG_TRUNC 18
|
||||
#define NLE_NOADDR 19
|
||||
#define NLE_SRCRT_NOSUPPORT 20
|
||||
#define NLE_MSG_TOOSHORT 21
|
||||
#define NLE_MSGTYPE_NOSUPPORT 22
|
||||
#define NLE_OBJ_MISMATCH 23
|
||||
#define NLE_NOCACHE 24
|
||||
#define NLE_BUSY 25
|
||||
#define NLE_PROTO_MISMATCH 26
|
||||
#define NLE_NOACCESS 27
|
||||
#define NLE_PERM 28
|
||||
#define NLE_PKTLOC_FILE 29
|
||||
#endif
|
||||
|
||||
#endif /* NM_NETLINK_COMPAT_H */
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "nm-netlink-compat.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
|
|
@ -58,12 +59,12 @@
|
|||
|
||||
typedef struct {
|
||||
/* Async event listener connection */
|
||||
struct nl_handle *nlh_event;
|
||||
struct nl_sock *nlh_event;
|
||||
GIOChannel * io_channel;
|
||||
guint event_id;
|
||||
|
||||
/* Sync/blocking request/response connection */
|
||||
struct nl_handle *nlh_sync;
|
||||
struct nl_sock *nlh_sync;
|
||||
struct nl_cache * link_cache;
|
||||
|
||||
guint request_status_id;
|
||||
|
|
@ -98,7 +99,7 @@ link_msg_handler (struct nl_object *obj, void *arg)
|
|||
error = g_error_new (NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (ENOMEM));
|
||||
g_signal_emit (self, signals[ERROR], 0, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
|
|
@ -130,7 +131,7 @@ link_msg_handler (struct nl_object *obj, void *arg)
|
|||
static int
|
||||
event_msg_recv (struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nl_handle *nlh = arg;
|
||||
struct nl_sock *nlh = arg;
|
||||
struct nlmsghdr *hdr = nlmsg_hdr (msg);
|
||||
struct ucred *creds = nlmsg_get_creds (msg);
|
||||
const struct sockaddr_nl *snl;
|
||||
|
|
@ -195,6 +196,7 @@ event_handler (GIOChannel *channel,
|
|||
NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data;
|
||||
NMNetlinkMonitorPrivate *priv;
|
||||
GError *error = NULL;
|
||||
int err;
|
||||
|
||||
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE);
|
||||
|
||||
|
|
@ -225,11 +227,12 @@ event_handler (GIOChannel *channel,
|
|||
g_return_val_if_fail (!(io_condition & ~EVENT_CONDITIONS), FALSE);
|
||||
|
||||
/* Process the netlink messages */
|
||||
if (nl_recvmsgs_default (priv->nlh_event) < 0) {
|
||||
err = nl_recvmsgs_default (priv->nlh_event);
|
||||
if (err < 0) {
|
||||
error = g_error_new (NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
g_signal_emit (self, signals[ERROR], 0, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
|
@ -238,32 +241,35 @@ event_handler (GIOChannel *channel,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
nlh_setup (struct nl_handle *nlh,
|
||||
nlh_setup (struct nl_sock *nlh,
|
||||
nl_recvmsg_msg_cb_t valid_func,
|
||||
gpointer cb_data,
|
||||
GError **error)
|
||||
{
|
||||
int err;
|
||||
|
||||
nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data);
|
||||
|
||||
if (valid_func)
|
||||
nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data);
|
||||
|
||||
if (nl_connect (nlh, NETLINK_ROUTE) < 0) {
|
||||
err = nl_connect (nlh, NETLINK_ROUTE);
|
||||
if (err < 0) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT,
|
||||
_("unable to connect to netlink for monitoring link status: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Enable unix socket peer credentials which we use for verifying that the
|
||||
* sender of the message is actually the kernel.
|
||||
*/
|
||||
if (nl_set_passcred (nlh, 1) < 0) {
|
||||
if (nl_socket_set_passcred (nlh, 1) < 0) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT,
|
||||
_("unable to enable netlink handle credential passing: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -283,20 +289,20 @@ event_connection_setup (NMNetlinkMonitor *self, GError **error)
|
|||
|
||||
/* Set up the event listener connection */
|
||||
cb = nl_cb_alloc (NL_CB_DEFAULT);
|
||||
priv->nlh_event = nl_handle_alloc_cb (cb);
|
||||
priv->nlh_event = nl_socket_alloc_cb (cb);
|
||||
nl_cb_put (cb);
|
||||
if (!priv->nlh_event) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE,
|
||||
_("unable to allocate netlink handle for monitoring link status: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (ENOMEM));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!nlh_setup (priv->nlh_event, event_msg_ready, self, error))
|
||||
goto error;
|
||||
|
||||
nl_disable_sequence_check (priv->nlh_event);
|
||||
nl_socket_disable_seq_check (priv->nlh_event);
|
||||
|
||||
/* Subscribe to the LINK group for internal carrier signals */
|
||||
if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error))
|
||||
|
|
@ -327,7 +333,7 @@ error:
|
|||
nm_netlink_monitor_close_connection (self);
|
||||
|
||||
if (priv->nlh_event) {
|
||||
nl_handle_destroy (priv->nlh_event);
|
||||
nl_socket_free (priv->nlh_event);
|
||||
priv->nlh_event = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -342,16 +348,17 @@ sync_connection_setup (NMNetlinkMonitor *self, GError **error)
|
|||
#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
|
||||
struct nl_cache *addr_cache;
|
||||
#endif
|
||||
int err;
|
||||
|
||||
/* Set up the event listener connection */
|
||||
cb = nl_cb_alloc (NL_CB_DEFAULT);
|
||||
priv->nlh_sync = nl_handle_alloc_cb (cb);
|
||||
priv->nlh_sync = nl_socket_alloc_cb (cb);
|
||||
nl_cb_put (cb);
|
||||
if (!priv->nlh_sync) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE,
|
||||
_("unable to allocate netlink handle for monitoring link status: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (ENOMEM));
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -365,16 +372,18 @@ sync_connection_setup (NMNetlinkMonitor *self, GError **error)
|
|||
* result, most addresses will not compare as equal even to
|
||||
* themselves, busting caching.
|
||||
*/
|
||||
addr_cache = rtnl_addr_alloc_cache (priv->nlh_sync);
|
||||
rtnl_addr_alloc_cache (priv->nlh_sync, &addr_cache);
|
||||
g_warn_if_fail (addr_cache != NULL);
|
||||
nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80;
|
||||
nl_cache_free (addr_cache);
|
||||
#endif
|
||||
|
||||
if ((priv->link_cache = rtnl_link_alloc_cache (priv->nlh_sync)) == NULL) {
|
||||
err = rtnl_link_alloc_cache (priv->nlh_sync, &priv->link_cache);
|
||||
if (err < 0) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE,
|
||||
_("unable to allocate netlink link cache for monitoring link status: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
goto error;
|
||||
}
|
||||
nl_cache_mngt_provide (priv->link_cache);
|
||||
|
|
@ -388,7 +397,7 @@ error:
|
|||
}
|
||||
|
||||
if (priv->nlh_sync) {
|
||||
nl_handle_destroy (priv->nlh_sync);
|
||||
nl_socket_free (priv->nlh_sync);
|
||||
priv->nlh_sync = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -483,7 +492,7 @@ gboolean
|
|||
nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error)
|
||||
{
|
||||
NMNetlinkMonitorPrivate *priv;
|
||||
int subs;
|
||||
int subs, err;
|
||||
|
||||
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);
|
||||
|
||||
|
|
@ -496,11 +505,12 @@ nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error)
|
|||
|
||||
subs = get_subs (self, group) + 1;
|
||||
if (subs == 1) {
|
||||
if (nl_socket_add_membership (priv->nlh_event, group) < 0) {
|
||||
err = nl_socket_add_membership (priv->nlh_event, group);
|
||||
if (err < 0) {
|
||||
g_set_error (error, NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP,
|
||||
_("unable to join netlink group: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -558,15 +568,17 @@ deferred_emit_carrier_state (gpointer user_data)
|
|||
{
|
||||
NMNetlinkMonitor *self = NM_NETLINK_MONITOR (user_data);
|
||||
NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||
int err;
|
||||
|
||||
priv->request_status_id = 0;
|
||||
|
||||
/* Update the link cache with latest state, and if there are no errors
|
||||
* emit the link states for all the interfaces in the cache.
|
||||
*/
|
||||
if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) {
|
||||
nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror ());
|
||||
} else
|
||||
err = nl_cache_refill (priv->nlh_sync, priv->link_cache);
|
||||
if (err < 0)
|
||||
nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror (err));
|
||||
else
|
||||
nl_cache_foreach_filter (priv->link_cache, NULL, link_msg_handler, self);
|
||||
|
||||
return FALSE;
|
||||
|
|
@ -614,6 +626,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
|
|||
NMNetlinkMonitorPrivate *priv;
|
||||
GetFlagsInfo info;
|
||||
struct rtnl_link *filter;
|
||||
int err;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);
|
||||
|
|
@ -622,12 +635,13 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
|
|||
priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||
|
||||
/* Update the link cache with the latest information */
|
||||
if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) {
|
||||
err = nl_cache_refill (priv->nlh_sync, priv->link_cache);
|
||||
if (err < 0) {
|
||||
g_set_error (error,
|
||||
NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE,
|
||||
_("error updating link cache: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -640,7 +654,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
|
|||
NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE,
|
||||
_("error updating link cache: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +665,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
|
|||
NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror ());
|
||||
nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
rtnl_link_set_ifindex (filter, ifindex);
|
||||
|
|
@ -678,11 +692,11 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self,
|
|||
|
||||
/***************************************************************/
|
||||
|
||||
struct nl_handle *
|
||||
struct nl_sock *
|
||||
nm_netlink_get_default_handle (void)
|
||||
{
|
||||
NMNetlinkMonitor *self;
|
||||
struct nl_handle *nlh;
|
||||
struct nl_sock *nlh;
|
||||
|
||||
self = nm_netlink_monitor_get ();
|
||||
nlh = NM_NETLINK_MONITOR_GET_PRIVATE (self)->nlh_sync;
|
||||
|
|
@ -796,12 +810,12 @@ finalize (GObject *object)
|
|||
}
|
||||
|
||||
if (priv->nlh_event) {
|
||||
nl_handle_destroy (priv->nlh_event);
|
||||
nl_socket_free (priv->nlh_event);
|
||||
priv->nlh_event = NULL;
|
||||
}
|
||||
|
||||
if (priv->nlh_sync) {
|
||||
nl_handle_destroy (priv->nlh_sync);
|
||||
nl_socket_free (priv->nlh_sync);
|
||||
priv->nlh_sync = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,10 +90,12 @@ gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor
|
|||
guint32 *ifflags,
|
||||
GError **error);
|
||||
|
||||
#include "nm-netlink-compat.h"
|
||||
|
||||
/* Generic utility functions */
|
||||
int nm_netlink_iface_to_index (const char *iface);
|
||||
char * nm_netlink_index_to_iface (int idx);
|
||||
struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx);
|
||||
struct nl_handle *nm_netlink_get_default_handle (void);
|
||||
struct nl_sock * nm_netlink_get_default_handle (void);
|
||||
|
||||
#endif /* NM_NETLINK_MONITOR_H */
|
||||
|
|
|
|||
423
src/nm-netlink-utils.c
Normal file
423
src/nm-netlink-utils.c
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
/* -*- 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 "logging/nm-logging.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-netlink-compat.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/addr.h>
|
||||
#include <netlink/route/addr.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
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;
|
||||
NmNlProp prop = NMNL_PROP_INVALID;
|
||||
int value;
|
||||
|
||||
route = rtnl_route_alloc ();
|
||||
g_return_val_if_fail (route != NULL, NULL);
|
||||
|
||||
if (ifindex >= 0)
|
||||
rtnl_route_set_oif (route, ifindex);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_netlink_route_add:
|
||||
* @route: the route to add
|
||||
*
|
||||
* Returns: zero if succeeded or the netlink error otherwise.
|
||||
**/
|
||||
int nm_netlink_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);
|
||||
rtnl_route_set_gateway (route, gw_addr);
|
||||
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, 0);
|
||||
|
||||
/* LIBNL Bug: Aliased ESRCH */
|
||||
if (err == -NLE_FAILURE)
|
||||
err = -NLE_OBJ_NOTFOUND;
|
||||
|
||||
if (err)
|
||||
nm_log_warn (LOGD_DEVICE | log,
|
||||
"Failed to add route %s",
|
||||
nl_geterror(err));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_get_oif (route),
|
||||
sf, family,
|
||||
strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : "<unknown>"),
|
||||
prefixlen);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int ifindex;
|
||||
int family;
|
||||
int scope;
|
||||
gboolean ignore_inet6_ll_mc;
|
||||
const 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;
|
||||
|
||||
if (nm_logging_level_enabled (LOGL_DEBUG))
|
||||
dump_route (route);
|
||||
|
||||
if ( info->ifindex >= 0
|
||||
&& rtnl_route_get_oif (route) != 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 = nm_netlink_index_to_iface (ifindex);
|
||||
|
||||
rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, NL_AUTO_PROVIDE, &cache);
|
||||
g_return_val_if_fail (cache != NULL, NULL);
|
||||
nl_cache_foreach (cache, foreach_route_cb, &info);
|
||||
nl_cache_free (cache);
|
||||
return info.out_route;
|
||||
}
|
||||
|
||||
|
||||
80
src/nm-netlink-utils.h
Normal file
80
src/nm-netlink-utils.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* -*- 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 <glib.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/route.h>
|
||||
|
||||
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_route_add (struct rtnl_route *route,
|
||||
int family,
|
||||
const void * dst, /* struct in_addr or struct in6_addr */
|
||||
int prefix,
|
||||
const void * gw, /* struct in_addr or struct in6_addr */
|
||||
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_MONITOR_H */
|
||||
|
||||
|
|
@ -425,6 +425,7 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
|||
NMConnection *connection = NULL;
|
||||
NMSettingConnection *s_con = NULL;
|
||||
const char *connection_id;
|
||||
int ip_ifindex = 0;
|
||||
|
||||
best = get_best_ip4_device (policy->manager, &best_req);
|
||||
if (!best)
|
||||
|
|
@ -461,17 +462,18 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
|||
NMDevice *parent;
|
||||
|
||||
ip_iface = nm_vpn_connection_get_ip_iface (candidate);
|
||||
ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate);
|
||||
connection = nm_vpn_connection_get_connection (candidate);
|
||||
addr = nm_ip4_config_get_address (ip4_config, 0);
|
||||
|
||||
parent = nm_vpn_connection_get_parent_device (candidate);
|
||||
parent_ip4 = nm_device_get_ip4_config (parent);
|
||||
|
||||
nm_system_replace_default_ip4_route_vpn (ip_iface,
|
||||
nm_system_replace_default_ip4_route_vpn (ip_ifindex,
|
||||
nm_ip4_address_get_gateway (addr),
|
||||
nm_vpn_connection_get_ip4_internal_gateway (candidate),
|
||||
nm_ip4_config_get_mss (ip4_config),
|
||||
nm_device_get_ip_iface (parent),
|
||||
nm_device_get_ip_ifindex (parent),
|
||||
nm_ip4_config_get_mss (parent_ip4));
|
||||
|
||||
dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
|
||||
|
|
@ -483,12 +485,14 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
|||
if (!ip_iface || !ip4_config) {
|
||||
connection = nm_act_request_get_connection (best_req);
|
||||
ip_iface = nm_device_get_ip_iface (best);
|
||||
ip_ifindex = nm_device_get_ip_ifindex (best);
|
||||
ip4_config = nm_device_get_ip4_config (best);
|
||||
g_assert (ip4_config);
|
||||
addr = nm_ip4_config_get_address (ip4_config, 0);
|
||||
|
||||
nm_system_replace_default_ip4_route (ip_iface, nm_ip4_address_get_gateway (addr), nm_ip4_config_get_mss (ip4_config));
|
||||
|
||||
nm_system_replace_default_ip4_route (ip_ifindex,
|
||||
nm_ip4_address_get_gateway (addr),
|
||||
nm_ip4_config_get_mss (ip4_config));
|
||||
dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
|
||||
}
|
||||
|
||||
|
|
@ -551,6 +555,7 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
|||
NMIP6Config *ip6_config = NULL;
|
||||
NMIP6Address *addr;
|
||||
const char *ip_iface = NULL;
|
||||
int ip_ifindex = -1;
|
||||
NMConnection *connection = NULL;
|
||||
NMSettingConnection *s_con = NULL;
|
||||
const char *connection_id;
|
||||
|
|
@ -608,11 +613,12 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
|||
if (!ip_iface || !ip6_config) {
|
||||
connection = nm_act_request_get_connection (best_req);
|
||||
ip_iface = nm_device_get_ip_iface (best);
|
||||
ip_ifindex = nm_device_get_ip_ifindex (best);
|
||||
ip6_config = nm_device_get_ip6_config (best);
|
||||
g_assert (ip6_config);
|
||||
addr = nm_ip6_config_get_address (ip6_config, 0);
|
||||
|
||||
nm_system_replace_default_ip6_route (ip_iface, nm_ip6_address_get_gateway (addr));
|
||||
nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr));
|
||||
|
||||
dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
|
||||
}
|
||||
|
|
|
|||
898
src/nm-system.c
898
src/nm-system.c
File diff suppressed because it is too large
Load diff
|
|
@ -35,33 +35,31 @@
|
|||
* implemented in the backend files in backends/ directory
|
||||
*/
|
||||
|
||||
void nm_system_device_flush_routes (NMDevice *dev, int family);
|
||||
void nm_system_device_flush_routes_with_iface (const char *iface, int family);
|
||||
gboolean nm_system_iface_flush_routes (int ifindex, int family);
|
||||
|
||||
gboolean nm_system_replace_default_ip4_route (const char *iface,
|
||||
gboolean nm_system_replace_default_ip4_route (int ifindex,
|
||||
guint32 gw,
|
||||
guint32 mss);
|
||||
|
||||
gboolean nm_system_replace_default_ip6_route (const char *iface,
|
||||
gboolean nm_system_replace_default_ip6_route (int ifindex,
|
||||
const struct in6_addr *gw);
|
||||
|
||||
gboolean nm_system_replace_default_ip4_route_vpn (const char *iface,
|
||||
gboolean nm_system_replace_default_ip4_route_vpn (int ifindex,
|
||||
guint32 ext_gw,
|
||||
guint32 int_gw,
|
||||
guint32 mss,
|
||||
const char *parent_iface,
|
||||
int parent_ifindex,
|
||||
guint32 parent_mss);
|
||||
|
||||
struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config);
|
||||
|
||||
|
||||
void nm_system_device_flush_addresses (NMDevice *dev, int family);
|
||||
void nm_system_device_flush_addresses_with_iface (const char *iface);
|
||||
gboolean nm_system_iface_flush_addresses (int ifindex, int family);
|
||||
|
||||
void nm_system_enable_loopback (void);
|
||||
void nm_system_update_dns (void);
|
||||
|
||||
gboolean nm_system_apply_ip4_config (const char *iface,
|
||||
gboolean nm_system_apply_ip4_config (int ifindex,
|
||||
NMIP4Config *config,
|
||||
int priority,
|
||||
NMIP4ConfigCompareFlags flags);
|
||||
|
|
@ -76,22 +74,19 @@ int nm_system_set_ip6_route (int ifindex,
|
|||
int table,
|
||||
struct rtnl_route **out_route);
|
||||
|
||||
gboolean nm_system_apply_ip6_config (const char *iface,
|
||||
gboolean nm_system_apply_ip6_config (int ifindex,
|
||||
NMIP6Config *config,
|
||||
int priority,
|
||||
NMIP6ConfigCompareFlags flags);
|
||||
|
||||
gboolean nm_system_device_set_up_down (NMDevice *dev,
|
||||
gboolean up,
|
||||
gboolean *no_firmware);
|
||||
gboolean nm_system_device_set_up_down_with_iface (const char *iface,
|
||||
gboolean up,
|
||||
gboolean *no_firmware);
|
||||
gboolean nm_system_iface_set_up (int ifindex,
|
||||
gboolean up,
|
||||
gboolean *no_firmware);
|
||||
|
||||
gboolean nm_system_device_is_up (NMDevice *device);
|
||||
gboolean nm_system_device_is_up_with_iface (const char *iface);
|
||||
gboolean nm_system_iface_is_up (int ifindex);
|
||||
|
||||
gboolean nm_system_device_set_mtu (const char *iface, guint32 mtu);
|
||||
gboolean nm_system_device_set_mac (const char *iface, const struct ether_addr *mac);
|
||||
gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu);
|
||||
|
||||
gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-dns-manager.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-netlink-utils.h"
|
||||
#include "nm-glib-compat.h"
|
||||
#include "settings/nm-settings-connection.h"
|
||||
|
||||
|
|
@ -86,6 +87,7 @@ typedef struct {
|
|||
NMIP4Config *ip4_config;
|
||||
guint32 ip4_internal_gw;
|
||||
char *ip_iface;
|
||||
int ip_ifindex;
|
||||
char *banner;
|
||||
|
||||
struct rtnl_route *gw_route;
|
||||
|
|
@ -424,6 +426,13 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* Grab the interface index for address/routing operations */
|
||||
priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface);
|
||||
if (!priv->ip_ifindex) {
|
||||
nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface);
|
||||
goto error;
|
||||
}
|
||||
|
||||
addr = nm_ip4_address_new ();
|
||||
nm_ip4_address_set_prefix (addr, 24); /* default to class C */
|
||||
|
||||
|
|
@ -529,9 +538,9 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
|
|||
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_IP4_CONFIG));
|
||||
nm_utils_merge_ip4_config (config, s_ip4);
|
||||
|
||||
nm_system_device_set_up_down_with_iface (priv->ip_iface, TRUE, NULL);
|
||||
nm_system_iface_set_up (priv->ip_ifindex, TRUE, NULL);
|
||||
|
||||
if (nm_system_apply_ip4_config (priv->ip_iface, config, 0, NM_IP4_COMPARE_FLAG_ALL)) {
|
||||
if (nm_system_apply_ip4_config (priv->ip_ifindex, config, 0, NM_IP4_COMPARE_FLAG_ALL)) {
|
||||
NMDnsManager *dns_mgr;
|
||||
|
||||
/* Add any explicit route to the VPN gateway through the parent device */
|
||||
|
|
@ -765,6 +774,14 @@ nm_vpn_connection_get_ip_iface (NMVPNConnection *connection)
|
|||
return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_iface;
|
||||
}
|
||||
|
||||
int
|
||||
nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), -1);
|
||||
|
||||
return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_ifindex;
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
nm_vpn_connection_get_parent_device (NMVPNConnection *connection)
|
||||
{
|
||||
|
|
@ -940,11 +957,11 @@ vpn_cleanup (NMVPNConnection *connection)
|
|||
{
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
|
||||
|
||||
if (priv->ip_iface) {
|
||||
nm_system_device_set_up_down_with_iface (priv->ip_iface, FALSE, NULL);
|
||||
if (priv->ip_ifindex) {
|
||||
nm_system_iface_set_up (priv->ip_ifindex, FALSE, NULL);
|
||||
/* FIXME: use AF_UNSPEC here when we have IPv6 support */
|
||||
nm_system_device_flush_routes_with_iface (priv->ip_iface, AF_INET);
|
||||
nm_system_device_flush_addresses_with_iface (priv->ip_iface);
|
||||
nm_system_iface_flush_routes (priv->ip_ifindex, AF_INET);
|
||||
nm_system_iface_flush_addresses (priv->ip_ifindex, AF_UNSPEC);
|
||||
}
|
||||
|
||||
if (priv->ip4_config) {
|
||||
|
|
@ -958,12 +975,12 @@ vpn_cleanup (NMVPNConnection *connection)
|
|||
|
||||
/* Remove any previously added VPN gateway host route */
|
||||
if (priv->gw_route)
|
||||
rtnl_route_del (nm_netlink_get_default_handle (), priv->gw_route, 0);
|
||||
nm_netlink_route_delete (priv->gw_route);
|
||||
|
||||
/* Reset routes and addresses of the currently active device */
|
||||
parent_config = nm_device_get_ip4_config (priv->parent_dev);
|
||||
if (parent_config) {
|
||||
if (!nm_system_apply_ip4_config (nm_device_get_ip_iface (priv->parent_dev),
|
||||
if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (priv->parent_dev),
|
||||
nm_device_get_ip4_config (priv->parent_dev),
|
||||
nm_device_get_priority (priv->parent_dev),
|
||||
NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) {
|
||||
|
|
@ -982,6 +999,7 @@ vpn_cleanup (NMVPNConnection *connection)
|
|||
|
||||
g_free (priv->ip_iface);
|
||||
priv->ip_iface = NULL;
|
||||
priv->ip_ifindex = 0;
|
||||
|
||||
/* Clear out connection secrets to ensure that the settings service
|
||||
* gets asked for them next time the connection is activated.
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ void nm_vpn_connection_disconnect (NMVPNConnection *connect
|
|||
NMVPNConnectionStateReason reason);
|
||||
NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection);
|
||||
const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection);
|
||||
int nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection);
|
||||
NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection);
|
||||
guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection);
|
||||
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ real_take_down (NMDevice *device)
|
|||
static gboolean
|
||||
real_hw_is_up (NMDevice *device)
|
||||
{
|
||||
return nm_system_device_is_up (device);
|
||||
return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -401,13 +401,13 @@ real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
|
|||
if (!priv->enabled || !priv->wimaxd_enabled)
|
||||
return FALSE;
|
||||
|
||||
return nm_system_device_set_up_down (dev, TRUE, no_firmware);
|
||||
return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
|
||||
}
|
||||
|
||||
static void
|
||||
real_hw_take_down (NMDevice *dev)
|
||||
{
|
||||
nm_system_device_set_up_down (dev, FALSE, NULL);
|
||||
nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue