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.
This commit is contained in:
Dan Williams 2011-07-22 15:28:35 -05:00
parent 2fabdbff15
commit 3a86b5ae34
4 changed files with 168 additions and 70 deletions

View file

@ -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 \

View file

@ -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;
}

119
src/nm-netlink-utils.c Normal file
View file

@ -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 <netinet/in.h>
#include <netlink/netlink.h>
#include <netlink/addr.h>
#include <netlink/route/addr.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_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;
}

31
src/nm-netlink-utils.h Normal file
View file

@ -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 <glib.h>
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 */