From 3a86b5ae34fe754e02fa7fed000dde9775c5da45 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Jul 2011 15:28:35 -0500 Subject: [PATCH] core: move address checking functionality into separate file Start to consolidate netlink stuff so we can eventually keep all the API changes for libnl1 vs. libnl3 in fewer places. --- src/Makefile.am | 2 + src/nm-device-ethernet.c | 86 ++++++---------------------- src/nm-netlink-utils.c | 119 +++++++++++++++++++++++++++++++++++++++ src/nm-netlink-utils.h | 31 ++++++++++ 4 files changed, 168 insertions(+), 70 deletions(-) create mode 100644 src/nm-netlink-utils.c create mode 100644 src/nm-netlink-utils.h diff --git a/src/Makefile.am b/src/Makefile.am index 94e1a8c0c1..11529a7b96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -159,6 +159,8 @@ NetworkManager_SOURCES = \ nm-manager-auth.h \ nm-netlink-monitor.c \ nm-netlink-monitor.h \ + nm-netlink-utils.c \ + nm-netlink-utils.h \ nm-activation-request.c \ nm-activation-request.h \ nm-properties-changed-signal.c \ diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 4de0d76b98..8556c5bd5c 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -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" @@ -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; } diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c new file mode 100644 index 0000000000..a0e998315b --- /dev/null +++ b/src/nm-netlink-utils.c @@ -0,0 +1,119 @@ +/* -*- 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-netlink-utils.h" +#include "nm-netlink-monitor.h" + +#include +#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_handle *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) { + cache = rtnl_addr_alloc_cache (nlh); + if (cache) { + nl_cache_mngt_provide (cache); + nl_cache_foreach (cache, find_one_address, &info); + nl_cache_free (cache); + } + } + return info.found; +} + diff --git a/src/nm-netlink-utils.h b/src/nm-netlink-utils.h new file mode 100644 index 0000000000..0e74470b6a --- /dev/null +++ b/src/nm-netlink-utils.h @@ -0,0 +1,31 @@ +/* -*- 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_); + +#endif /* NM_NETLINK_MONITOR_H */