Merge branch 'iscsi'

This commit is contained in:
Dan Williams 2009-08-10 15:52:28 -05:00
commit 38f732a721
31 changed files with 1615 additions and 96 deletions

View file

@ -358,6 +358,9 @@ typedef enum {
/* Carrier/link changed */
NM_DEVICE_STATE_REASON_CARRIER,
/* The device's existing connection was assumed */
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
/* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason;

View file

@ -370,6 +370,11 @@
<tp:docstring>
The device's carrier/link changed.
</tp:docstring>
</tp:enumvalue>
<tp:enumvalue suffix="CONNECTION_ASSUMED" value="41">
<tp:docstring>
The device's existing connection was assumed.
</tp:docstring>
</tp:enumvalue>
</tp:enum>

View file

@ -18,6 +18,10 @@
* Copyright (C) 2005 - 2008 Red Hat, Inc.
*/
#define _XOPEN_SOURCE
#include <time.h>
#undef _XOPEN_SOURCE
#include <glib.h>
#include <glib/gi18n.h>
#include <dbus/dbus.h>
@ -74,6 +78,206 @@ get_leasefile_for_iface (const char * iface, const char *uuid)
NM_DHCP_MANAGER_LEASE_FILE_EXT);
}
static void
add_lease_option (GHashTable *hash, char *line)
{
char *spc;
spc = strchr (line, ' ');
if (!spc) {
g_warning ("%s: line '%s' did not contain a space", __func__, line);
return;
}
/* If it's an 'option' line, split at second space */
if (g_str_has_prefix (line, "option ")) {
spc = strchr (spc + 1, ' ');
if (!spc) {
g_warning ("%s: option line '%s' did not contain a second space",
__func__, line);
return;
}
}
/* Split the line at the space */
*spc = '\0';
spc++;
/* Kill the ';' at the end of the line, if any */
if (*(spc + strlen (spc) - 1) == ';')
*(spc + strlen (spc) - 1) = '\0';
/* Treat 'interface' specially */
if (g_str_has_prefix (line, "interface")) {
if (*(spc) == '"')
spc++; /* Jump past the " */
if (*(spc + strlen (spc) - 1) == '"')
*(spc + strlen (spc) - 1) = '\0'; /* Kill trailing " */
}
g_hash_table_insert (hash, g_strdup (line), g_strdup (spc));
}
GSList *
nm_dhcp_client_get_lease_ip4_config (const char *iface, const char *uuid)
{
GSList *parsed = NULL, *iter, *leases = NULL;
char *contents = NULL;
char *leasefile;
char **line, **split = NULL;
GHashTable *hash = NULL;
leasefile = get_leasefile_for_iface (iface, uuid);
if (!leasefile)
return NULL;
if (!g_file_test (leasefile, G_FILE_TEST_EXISTS))
goto out;
if (!g_file_get_contents (leasefile, &contents, NULL, NULL))
goto out;
split = g_strsplit_set (contents, "\n\r", -1);
g_free (contents);
if (!split)
goto out;
for (line = split; line && *line; line++) {
*line = g_strstrip (*line);
if (!strcmp (*line, "}")) {
/* Lease ends */
parsed = g_slist_append (parsed, hash);
hash = NULL;
} else if (!strcmp (*line, "lease {")) {
/* Beginning of a new lease */
if (hash) {
g_warning ("%s: lease file %s malformed; new lease started "
"without ending previous lease",
__func__, leasefile);
g_hash_table_destroy (hash);
}
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
} else if (strlen (*line))
add_lease_option (hash, *line);
}
g_strfreev (split);
/* Check if the last lease in the file was properly ended */
if (hash) {
g_warning ("%s: lease file %s malformed; new lease started "
"without ending previous lease",
__func__, leasefile);
g_hash_table_destroy (hash);
hash = NULL;
}
for (iter = parsed; iter; iter = g_slist_next (iter)) {
NMIP4Config *ip4;
NMIP4Address *addr;
const char *data;
struct in_addr tmp;
guint32 prefix;
struct tm expire;
hash = iter->data;
/* Make sure this lease is for the interface we want */
data = g_hash_table_lookup (hash, "interface");
if (!data || strcmp (data, iface))
continue;
data = g_hash_table_lookup (hash, "expire");
if (data) {
time_t now_tt;
struct tm *now;
/* Read lease expiration (in UTC) */
if (!strptime (data, "%w %Y/%m/%d %H:%M:%S", &expire)) {
g_warning ("%s: couldn't parse expire time '%s'",
__func__, data);
continue;
}
now_tt = time (NULL);
now = gmtime(&now_tt);
/* Ignore this lease if it's already expired */
if (expire.tm_year < now->tm_year)
continue;
else if (expire.tm_year == now->tm_year) {
if (expire.tm_mon < now->tm_mon)
continue;
else if (expire.tm_mon == now->tm_mon) {
if (expire.tm_mday < now->tm_mday)
continue;
else if (expire.tm_mday == now->tm_mday) {
if (expire.tm_hour < now->tm_hour)
continue;
else if (expire.tm_hour == now->tm_hour) {
if (expire.tm_min < now->tm_min)
continue;
else if (expire.tm_min == now->tm_min) {
if (expire.tm_sec <= now->tm_sec)
continue;
}
}
}
}
}
/* If we get this far, the lease hasn't expired */
}
data = g_hash_table_lookup (hash, "fixed-address");
if (!data)
continue;
ip4 = nm_ip4_config_new ();
addr = nm_ip4_address_new ();
/* IP4 address */
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 address '%s'", __func__, data);
goto error;
}
nm_ip4_address_set_address (addr, tmp.s_addr);
/* Netmask */
data = g_hash_table_lookup (hash, "option subnet-mask");
if (!data)
data = "255.255.255.0"; /* FIXME: assume class C? */
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 subnet mask '%s'", __func__, data);
goto error;
}
prefix = nm_utils_ip4_netmask_to_prefix (tmp.s_addr);
nm_ip4_address_set_prefix (addr, prefix);
/* Gateway */
data = g_hash_table_lookup (hash, "option routers");
if (data) {
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 gateway '%s'", __func__, data);
goto error;
}
nm_ip4_address_set_gateway (addr, tmp.s_addr);
}
nm_ip4_config_take_address (ip4, addr);
leases = g_slist_append (leases, ip4);
continue;
error:
nm_ip4_address_unref (addr);
g_object_unref (ip4);
}
out:
g_slist_foreach (parsed, (GFunc) g_hash_table_destroy, NULL);
g_free (leasefile);
return leases;
}
#define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier"

View file

@ -49,6 +49,11 @@ get_pidfile_for_iface (const char * iface)
NM_DHCP_MANAGER_PID_FILE_EXT);
}
GSList *
nm_dhcp_client_get_lease_ip4_config (const char *iface, const char *uuid)
{
return NULL;
}
static void
dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED)

View file

@ -1121,3 +1121,16 @@ nm_dhcp_manager_set_hostname_provider (NMDHCPManager *manager,
g_object_weak_ref (G_OBJECT (provider), hostname_provider_destroyed, manager);
}
}
GSList *
nm_dhcp_manager_get_lease_ip4_config (NMDHCPManager *self,
const char *iface,
const char *uuid)
{
g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (uuid != NULL, NULL);
return nm_dhcp_client_get_lease_ip4_config (iface, uuid);
}

View file

@ -107,6 +107,10 @@ gboolean nm_dhcp_manager_foreach_dhcp4_option (NMDHCPManager *self,
GHFunc func,
gpointer user_data);
GSList * nm_dhcp_manager_get_lease_ip4_config (NMDHCPManager *self,
const char *iface,
const char *uuid);
/* The following are implemented by the DHCP client backends */
GPid nm_dhcp_client_start (NMDHCPDevice *device,
const char *uuid,
@ -118,6 +122,9 @@ gboolean nm_dhcp_client_process_classless_routes (GHashTable *options,
NMIP4Config *ip4_config,
guint32 *gwaddr);
GSList * nm_dhcp_client_get_lease_ip4_config (const char *iface,
const char *uuid);
/* Test functions */
NMIP4Config *nm_dhcp_manager_options_to_ip4_config (const char *iface,
GHashTable *options);

View file

@ -76,6 +76,8 @@ typedef struct {
GSList *share_rules;
char *ac_path;
gboolean assumed;
} NMActRequestPrivate;
enum {
@ -136,6 +138,7 @@ NMActRequest *
nm_act_request_new (NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
gpointer *device)
{
GObject *object;
@ -160,6 +163,7 @@ nm_act_request_new (NMConnection *connection,
NM_ACT_REQUEST (object));
priv->user_requested = user_requested;
priv->assumed = assumed;
return NM_ACT_REQUEST (object);
}
@ -643,3 +647,11 @@ nm_act_request_get_device (NMActRequest *req)
return G_OBJECT (NM_ACT_REQUEST_GET_PRIVATE (req)->device);
}
gboolean
nm_act_request_get_assumed (NMActRequest *req)
{
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
}

View file

@ -59,6 +59,7 @@ GType nm_act_request_get_type (void);
NMActRequest *nm_act_request_new (NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
gpointer *device); /* An NMDevice */
NMConnection *nm_act_request_get_connection (NMActRequest *req);
@ -85,6 +86,8 @@ void nm_act_request_add_share_rule (NMActRequest *req,
GObject * nm_act_request_get_device (NMActRequest *req);
gboolean nm_act_request_get_assumed (NMActRequest *req);
gboolean nm_act_request_get_secrets (NMActRequest *req,
const char *setting_name,
gboolean request_new,

View file

@ -53,6 +53,7 @@
#include "ppp-manager/nm-ppp-manager.h"
#include "nm-utils.h"
#include "nm-properties-changed-signal.h"
#include "nm-dhcp-manager.h"
#include "nm-device-ethernet-glue.h"
@ -280,8 +281,8 @@ constructor (GType type,
guint32 caps;
object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
n_construct_params,
construct_params);
n_construct_params,
construct_params);
if (!object)
return NULL;
@ -1472,6 +1473,196 @@ spec_match_list (NMDevice *device, const GSList *specs)
return matched;
}
static gboolean
wired_match_config (NMDevice *self, NMConnection *connection)
{
NMSettingWired *s_wired;
struct ether_addr ether;
const GByteArray *s_ether;
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired)
return FALSE;
/* MAC address check */
s_ether = nm_setting_wired_get_mac_address (s_wired);
if (s_ether) {
nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (self), &ether);
if (memcmp (s_ether->data, ether.ether_addr_octet, ETH_ALEN))
return FALSE;
}
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;
NMSettingConnection *s_con;
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_ethernet_get_ifindex (NM_DEVICE_ETHERNET (self));
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
g_assert (nm_setting_connection_get_uuid (s_con));
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
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_ip4_config (dhcp_mgr,
nm_device_get_iface (self),
nm_setting_connection_get_uuid (s_con));
g_object_unref (dhcp_mgr);
method = nm_setting_ip4_config_get_method (s_ip4);
if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
gboolean found = FALSE;
/* Find at least one lease's address on the device */
for (iter = leases; iter; iter = g_slist_next (iter)) {
NMIP4Config *addr = iter->data;
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) {
found = TRUE; /* Yay, device has same address as a lease */
break;
}
}
g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
g_slist_free (leases);
return found;
} else {
/* Maybe the connection used to be DHCP and there are stale leases; ignore them */
g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
g_slist_free (leases);
}
/* 'shared' and 'link-local' aren't supported methods because 'shared'
* requires too much iptables and dnsmasq state to be reclaimed, and
* avahi-autoipd isn't smart enough to allow the link-local address to be
* determined at any point other than when it was first assigned.
*/
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
return FALSE;
/* Everything below for static addressing */
/* Find all IP4 addresses of this connection in the device's address list */
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);
nl_cache_foreach (addr_cache, check_one_address, &check_data);
if (!check_data.found)
return FALSE;
}
/* Success; all the connection's static IP addresses are assigned to the device */
return TRUE;
}
static NMConnection *
connection_match_config (NMDevice *self, const GSList *connections)
{
GSList *iter;
NMSettingConnection *s_con;
for (iter = (GSList *) connections; iter; iter = g_slist_next (iter)) {
NMConnection *candidate = NM_CONNECTION (iter->data);
s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRED_SETTING_NAME))
continue;
/* Can't assume 802.1x or PPPoE connections; they have too much state
* that's impossible to get on-the-fly from PPPoE or the supplicant.
*/
if ( nm_connection_get_setting (candidate, NM_TYPE_SETTING_802_1X)
|| nm_connection_get_setting (candidate, NM_TYPE_SETTING_PPPOE))
continue;
if (!wired_match_config (self, candidate))
continue;
if (!ip4_match_config (self, candidate))
continue;
return candidate;
}
return NULL;
}
static void
dispose (GObject *object)
{
@ -1587,6 +1778,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->spec_match_list = spec_match_list;
parent_class->connection_match_config = connection_match_config;
/* properties */
g_object_class_install_property

View file

@ -291,8 +291,29 @@ gboolean
nm_device_interface_spec_match_list (NMDeviceInterface *device,
const GSList *specs)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE);
if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->spec_match_list)
return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->spec_match_list (device, specs);
return FALSE;
}
NMConnection *
nm_device_interface_connection_match_config (NMDeviceInterface *device,
const GSList *connections)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), NULL);
if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config)
return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config (device, connections);
return NULL;
}
gboolean
nm_device_interface_can_assume_connection (NMDeviceInterface *device)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE);
return !!NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config;
}

View file

@ -90,6 +90,8 @@ struct _NMDeviceInterface {
gboolean (*spec_match_list) (NMDeviceInterface *device, const GSList *specs);
NMConnection * (*connection_match_config) (NMDeviceInterface *device, const GSList *specs);
/* Signals */
void (*state_changed) (NMDeviceInterface *device,
NMDeviceState new_state,
@ -117,4 +119,9 @@ NMDeviceState nm_device_interface_get_state (NMDeviceInterface *device);
gboolean nm_device_interface_spec_match_list (NMDeviceInterface *device,
const GSList *specs);
NMConnection * nm_device_interface_connection_match_config (NMDeviceInterface *device,
const GSList *connections);
gboolean nm_device_interface_can_assume_connection (NMDeviceInterface *device);
#endif /* NM_DEVICE_INTERFACE_H */

View file

@ -130,7 +130,8 @@ static gboolean nm_device_activate (NMDeviceInterface *device,
NMActRequest *req,
GError **error);
static void nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason);
static gboolean nm_device_spec_match_list (NMDeviceInterface *device, const GSList *specs);
static gboolean spec_match_list (NMDeviceInterface *device, const GSList *specs);
static NMConnection *connection_match_config (NMDeviceInterface *device, const GSList *connections);
static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self, int family);
@ -139,8 +140,14 @@ static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReas
static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware);
static gboolean nm_device_is_up (NMDevice *self);
static gboolean nm_device_set_ip4_config (NMDevice *dev, NMIP4Config *config, NMDeviceStateReason *reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev, NMIP6Config *config, NMDeviceStateReason *reason);
static gboolean nm_device_set_ip4_config (NMDevice *dev,
NMIP4Config *config,
gboolean assumed,
NMDeviceStateReason *reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev,
NMIP6Config *config,
gboolean assumed,
NMDeviceStateReason *reason);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
@ -149,7 +156,8 @@ device_interface_init (NMDeviceInterface *device_interface_class)
device_interface_class->check_connection_compatible = check_connection_compatible;
device_interface_class->activate = nm_device_activate;
device_interface_class->deactivate = nm_device_deactivate;
device_interface_class->spec_match_list = nm_device_spec_match_list;
device_interface_class->spec_match_list = spec_match_list;
device_interface_class->connection_match_config = connection_match_config;
}
@ -772,7 +780,7 @@ handle_autoip_change (NMDevice *self, NMDeviceStateReason *reason)
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
if (!nm_device_set_ip4_config (self, config, reason)) {
if (!nm_device_set_ip4_config (self, config, FALSE, reason)) {
nm_warning ("(%s): failed to update IP4 config in response to autoip event.",
nm_device_get_iface (self));
return FALSE;
@ -1722,19 +1730,20 @@ static gboolean
nm_device_activate_stage5_ip_config_commit (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMIP4Config *ip4_config = NULL;
NMIP6Config *ip6_config = NULL;
const char *iface, *method = NULL;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
gboolean assumed;
ip4_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG);
g_assert (ip4_config);
ip6_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG);
/* FIXME g_assert (ip6_config); */
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE, 0);
@ -1743,12 +1752,14 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...",
iface);
if (!nm_device_set_ip4_config (self, ip4_config, &reason)) {
assumed = nm_act_request_get_assumed (priv->act_request);
if (!nm_device_set_ip4_config (self, ip4_config, assumed, &reason)) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
if (!nm_device_set_ip6_config (self, ip6_config, &reason)) {
if (ip6_config && !nm_device_set_ip6_config (self, ip6_config, assumed, &reason)) {
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) IPv6 failed",
iface);
}
@ -1774,7 +1785,8 @@ out:
/* Balance IP config creation; device takes ownership in set_ip*_config() */
g_object_unref (ip4_config);
g_object_unref (ip6_config);
if (ip6_config)
g_object_unref (ip6_config);
return FALSE;
}
@ -1918,8 +1930,8 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
nm_device_deactivate_quickly (self);
/* Clean up nameservers and addresses */
nm_device_set_ip4_config (self, NULL, &ignored);
nm_device_set_ip6_config (self, NULL, &ignored);
nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
nm_device_set_ip6_config (self, NULL, FALSE, &ignored);
/* Take out any entries in the routing table and any IP address the device had. */
nm_system_device_flush_routes (self);
@ -2020,13 +2032,22 @@ nm_device_activate (NMDeviceInterface *device,
G_CALLBACK (connection_secrets_failed_cb),
device);
/* HACK: update the state a bit early to avoid a race between the
* scheduled stage1 handler and nm_policy_device_change_check() thinking
* that the activation request isn't deferred because the deferred bit
* gets cleared a bit too early, when the connection becomes valid.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage1_device_prepare (self);
if (!nm_act_request_get_assumed (req)) {
/* HACK: update the state a bit early to avoid a race between the
* scheduled stage1 handler and nm_policy_device_change_check() thinking
* that the activation request isn't deferred because the deferred bit
* gets cleared a bit too early, when the connection becomes valid.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage1_device_prepare (self);
} else {
/* If it's an assumed connection, let the device subclass short-circuit
* the normal connection process and just copy its IP configs from the
* interface.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage3_ip_config_start (self);
}
return TRUE;
}
@ -2091,6 +2112,7 @@ handle_dhcp_lease_change (NMDevice *device)
NMActRequest *req;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
const char *ip_iface;
gboolean assumed;
if (!nm_device_get_use_dhcp (device)) {
nm_warning ("got DHCP rebind for device that wasn't using DHCP.");
@ -2116,7 +2138,8 @@ handle_dhcp_lease_change (NMDevice *device)
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
if (nm_device_set_ip4_config (device, config, &reason)) {
assumed = nm_act_request_get_assumed (req);
if (nm_device_set_ip4_config (device, config, assumed, &reason)) {
nm_dhcp4_config_reset (priv->dhcp4_config);
nm_dhcp_manager_foreach_dhcp4_option (priv->dhcp_manager,
ip_iface,
@ -2274,6 +2297,7 @@ nm_device_get_ip4_config (NMDevice *self)
static gboolean
nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *new_config,
gboolean assumed,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
@ -2309,8 +2333,13 @@ nm_device_set_ip4_config (NMDevice *self,
if (new_config) {
priv->ip4_config = g_object_ref (new_config);
success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success) {
/* 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 (success || assumed) {
/* Export over D-Bus */
if (!nm_ip4_config_get_dbus_path (new_config))
nm_ip4_config_export (new_config);
@ -2371,6 +2400,7 @@ nm_device_update_ip4_address (NMDevice *self)
static gboolean
nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *new_config,
gboolean assumed,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
@ -2406,8 +2436,13 @@ nm_device_set_ip6_config (NMDevice *self,
if (new_config) {
priv->ip6_config = g_object_ref (new_config);
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success) {
/* Don't touch the device's actual IP config if the connection is
* assumed when NM starts.
*/
if (!assumed)
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success || assumed) {
/* Export over D-Bus */
if (!nm_ip6_config_get_dbus_path (new_config))
nm_ip6_config_export (new_config);
@ -2543,29 +2578,49 @@ dispose (GObject *object)
{
NMDevice *self = NM_DEVICE (object);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean take_down = TRUE;
if (priv->disposed || !priv->initialized)
goto out;
priv->disposed = TRUE;
/* Don't down can-assume-connection capable devices that are activated with
* a connection that can be assumed.
*/
if (nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (self))
&& (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED)) {
NMConnection *connection;
NMSettingIP4Config *s_ip4;
const char *method = NULL;
/* Only system connections can be left up */
connection = nm_act_request_get_connection (priv->act_request);
if ( connection
&& (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM)) {
/* Only static or DHCP connections can be left up */
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
g_assert (s_ip4);
method = nm_setting_ip4_config_get_method (s_ip4);
if ( !method
|| !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)
|| !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
take_down = FALSE;
}
}
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
priv->failed_to_disconnected_id = 0;
}
/*
* In dispose, you are supposed to free all types referenced from this
* object which might themselves hold a reference to self. Generally,
* the most simple solution is to unref all members on which you own a
* reference.
*/
if (priv->managed) {
if (priv->managed && take_down) {
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
nm_device_take_down (self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
nm_device_set_ip4_config (self, NULL, &ignored);
nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
}
clear_act_request (self);
@ -2573,7 +2628,8 @@ dispose (GObject *object)
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
nm_device_set_use_dhcp (self, FALSE);
if (!take_down)
nm_device_set_use_dhcp (self, FALSE);
if (priv->dnsmasq_manager) {
if (priv->dnsmasq_state_id) {
@ -2857,8 +2913,14 @@ nm_device_state_changed (NMDevice *device,
if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware)
nm_warning ("%s: firmware may be missing.", nm_device_get_iface (device));
}
/* Fall through, so when the device needs to be deactivated due to
* eg carrier changes we actually deactivate it */
/* Ensure the device gets deactivated in response to stuff like
* carrier changes or rfkill. But don't deactivate devices that are
* about to assume a connection since that defeats the purpose of
* assuming the device's existing connection.
*/
if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED)
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device), reason);
break;
case NM_DEVICE_STATE_DISCONNECTED:
if (old_state != NM_DEVICE_STATE_UNAVAILABLE)
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device), reason);
@ -2935,7 +2997,7 @@ nm_device_set_managed (NMDevice *device,
}
static gboolean
nm_device_spec_match_list (NMDeviceInterface *device, const GSList *specs)
spec_match_list (NMDeviceInterface *device, const GSList *specs)
{
NMDevice *self;
@ -2948,6 +3010,16 @@ nm_device_spec_match_list (NMDeviceInterface *device, const GSList *specs)
return FALSE;
}
static NMConnection *
connection_match_config (NMDeviceInterface *device, const GSList *connections)
{
g_return_val_if_fail (device != NULL, FALSE);
if (NM_DEVICE_GET_CLASS (device)->connection_match_config)
return NM_DEVICE_GET_CLASS (device)->connection_match_config (NM_DEVICE (device), connections);
return NULL;
}
void
nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout)
{

View file

@ -115,6 +115,8 @@ typedef struct {
gboolean (* can_interrupt_activation) (NMDevice *self);
gboolean (* spec_match_list) (NMDevice *self, const GSList *specs);
NMConnection * (* connection_match_config) (NMDevice *self, const GSList *connections);
} NMDeviceClass;

View file

@ -114,6 +114,14 @@ static void add_device (NMManager *self, NMDevice *device);
static void hostname_provider_init (NMHostnameProvider *provider_class);
static const char *internal_activate_device (NMManager *manager,
NMDevice *device,
NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
GError **error);
#define SSD_POKE_INTERVAL 120
#define ORIGDEV_TAG "originating-device"
@ -349,12 +357,24 @@ manager_device_state_changed (NMDevice *device,
/* Removes a device from a device list; returns the start of the new device list */
static GSList *
remove_one_device (NMManager *manager, GSList *list, NMDevice *device)
remove_one_device (NMManager *manager,
GSList *list,
NMDevice *device,
gboolean quitting)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (nm_device_get_managed (device))
nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
if (nm_device_get_managed (device)) {
gboolean unmanage = !quitting;
/* Don't unmanage active assume-connection-capable devices at shutdown */
if ( nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))
&& nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
unmanage = FALSE;
if (unmanage)
nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
}
g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager);
@ -373,7 +393,7 @@ modem_removed (NMModemManager *modem_manager,
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
priv->devices = remove_one_device (self, priv->devices, modem);
priv->devices = remove_one_device (self, priv->devices, modem, FALSE);
}
static void
@ -1154,6 +1174,9 @@ add_device (NMManager *self, NMDevice *device)
char *path;
static guint32 devcount = 0;
const GSList *unmanaged_specs;
NMConnection *existing = NULL;
GHashTableIter iter;
gpointer value;
priv->devices = g_slist_append (priv->devices, device);
@ -1190,13 +1213,50 @@ add_device (NMManager *self, NMDevice *device)
nm_info ("(%s): exported as %s", iface, path);
g_free (path);
/* Check if we should assume the device's active connection by matching its
* config with an existing system connection.
*/
if (nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))) {
GSList *connections = NULL;
g_hash_table_iter_init (&iter, priv->system_connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
connections = g_slist_append (connections, value);
existing = nm_device_interface_connection_match_config (NM_DEVICE_INTERFACE (device),
(const GSList *) connections);
g_slist_free (connections);
}
/* Start the device if it's supposed to be managed */
unmanaged_specs = nm_sysconfig_settings_get_unmanaged_specs (priv->sys_settings);
if (!priv->sleeping && !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs))
nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
if ( !priv->sleeping
&& !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) {
nm_device_set_managed (device,
TRUE,
existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED :
NM_DEVICE_STATE_REASON_NOW_MANAGED);
}
nm_sysconfig_settings_device_added (priv->sys_settings, device);
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
/* If the device has a connection it can assume, do that now */
if (existing) {
const char *ac_path;
GError *error = NULL;
ac_path = internal_activate_device (self, device, existing, NULL, FALSE, TRUE, &error);
if (ac_path)
g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
else {
nm_warning ("Assumed connection (%d) %s failed to activate: (%d) %s",
nm_connection_get_scope (existing),
nm_connection_get_path (existing),
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
}
}
}
static gboolean
@ -1303,7 +1363,7 @@ bluez_manager_resync_devices (NMManager *self)
priv->devices = keep;
while (g_slist_length (gone))
gone = remove_one_device (self, gone, NM_DEVICE (gone->data));
gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE);
} else {
g_slist_free (keep);
g_slist_free (gone);
@ -1373,7 +1433,7 @@ bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr,
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), object_path)) {
priv->devices = remove_one_device (self, priv->devices, device);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
break;
}
}
@ -1436,8 +1496,7 @@ udev_device_removed_cb (NMUdevManager *manager,
ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX");
device = find_device_by_ifindex (self, ifindex);
if (device)
priv->devices = remove_one_device (self, priv->devices, device);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
}
static void
@ -1804,6 +1863,7 @@ internal_activate_device (NMManager *manager,
NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
GError **error)
{
NMActRequest *req;
@ -1827,7 +1887,7 @@ internal_activate_device (NMManager *manager,
NM_DEVICE_STATE_REASON_NONE);
}
req = nm_act_request_new (connection, specific_object, user_requested, (gpointer) device);
req = nm_act_request_new (connection, specific_object, user_requested, assumed, (gpointer) device);
g_signal_connect (req, "manager-get-secrets", G_CALLBACK (provider_get_secrets), manager);
g_signal_connect (req, "manager-cancel-secrets", G_CALLBACK (provider_cancel_secrets), manager);
success = nm_device_interface_activate (dev_iface, req, error);
@ -1939,6 +1999,7 @@ nm_manager_activate_connection (NMManager *manager,
connection,
specific_object,
user_requested,
FALSE,
error);
}
@ -2525,7 +2586,7 @@ dispose (GObject *object)
while (g_slist_length (priv->devices)) {
NMDevice *device = NM_DEVICE (priv->devices->data);
priv->devices = remove_one_device (manager, priv->devices, device);
priv->devices = remove_one_device (manager, priv->devices, device, TRUE);
}
user_destroy_connections (manager);

View file

@ -32,7 +32,8 @@ libifcfg_rh_io_la_CPPFLAGS = \
$(DBUS_CFLAGS) \
$(NSS_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DSYSCONFDIR=\"$(sysconfdir)\"
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DSBINDIR=\"$(sbindir)\"
libifcfg_rh_io_la_LIBADD = $(GLIB_LIBS) $(NSS_LIBS)

View file

@ -104,7 +104,7 @@ nm_ifcfg_connection_new (const char *filename,
g_return_val_if_fail (filename != NULL, NULL);
wrapped = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
wrapped = connection_from_file (filename, NULL, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
if (!wrapped)
return NULL;

View file

@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <ctype.h>
#include <sys/inotify.h>
#include <errno.h>
@ -183,6 +184,284 @@ make_connection_setting (const char *file,
return NM_SETTING (s_con);
}
static gboolean
read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
{
char *value = NULL;
struct ether_addr *mac;
g_return_val_if_fail (ifcfg != NULL, FALSE);
g_return_val_if_fail (array != NULL, FALSE);
g_return_val_if_fail (*array == NULL, FALSE);
g_return_val_if_fail (error != NULL, FALSE);
g_return_val_if_fail (*error == NULL, FALSE);
value = svGetValue (ifcfg, "HWADDR", FALSE);
if (!value || !strlen (value)) {
g_free (value);
return TRUE;
}
mac = ether_aton (value);
if (!mac) {
g_free (value);
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"The MAC address '%s' was invalid.", value);
return FALSE;
}
g_free (value);
*array = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
return TRUE;
}
static void
iscsiadm_child_setup (gpointer user_data G_GNUC_UNUSED)
{
/* We are in the child process here; set a different process group to
* ensure signal isolation between child and parent.
*/
pid_t pid = getpid ();
setpgid (pid, pid);
}
static char *
match_iscsiadm_tag (const char *line, const char *tag, gboolean *skip)
{
char *p;
if (g_ascii_strncasecmp (line, tag, strlen (tag)))
return NULL;
p = strchr (line, '=');
if (!p) {
g_warning ("%s: malformed iscsiadm record: no = in '%s'.",
__func__, line);
*skip = TRUE;
return NULL;
}
p++; /* advance past = */
return g_strstrip (p);
}
#define ISCSI_HWADDR_TAG "iface.hwaddress"
#define ISCSI_BOOTPROTO_TAG "iface.bootproto"
#define ISCSI_IPADDR_TAG "iface.ipaddress"
#define ISCSI_SUBNET_TAG "iface.subnet_mask"
#define ISCSI_GATEWAY_TAG "iface.gateway"
#define ISCSI_DNS1_TAG "iface.primary_dns"
#define ISCSI_DNS2_TAG "iface.secondary_dns"
static gboolean
fill_ip4_setting_from_ibft (shvarFile *ifcfg,
NMSettingIP4Config *s_ip4,
const char *iscsiadm_path,
GError **error)
{
const char *argv[4] = { iscsiadm_path, "-m", "fw", NULL };
const char *envp[1] = { NULL };
gboolean success = FALSE, in_record = FALSE, hwaddr_matched = FALSE, skip = FALSE;
char *out = NULL, *err = NULL;
gint status = 0;
GByteArray *ifcfg_mac = NULL;
char **lines = NULL, **iter;
const char *method = NULL;
struct in_addr ipaddr;
struct in_addr gateway;
struct in_addr dns1;
struct in_addr dns2;
guint32 prefix = 0;
g_return_val_if_fail (s_ip4 != NULL, FALSE);
g_return_val_if_fail (iscsiadm_path != NULL, FALSE);
if (!g_spawn_sync ("/", (char **) argv, (char **) envp, 0,
iscsiadm_child_setup, NULL, &out, &err, &status, error))
return FALSE;
if (!WIFEXITED (status)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"%s exited abnormally.", iscsiadm_path);
goto done;
}
if (WEXITSTATUS (status) != 0) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"%s exited with error %d. Message: '%s'",
iscsiadm_path, WEXITSTATUS (status), err ? err : "(none)");
goto done;
}
if (!read_mac_address (ifcfg, &ifcfg_mac, error))
goto done;
/* Ensure we got a MAC */
if (!ifcfg_mac) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing device MAC address (no HWADDR tag present).");
goto done;
}
memset (&ipaddr, 0, sizeof (ipaddr));
memset (&gateway, 0, sizeof (gateway));
memset (&dns1, 0, sizeof (dns1));
memset (&dns2, 0, sizeof (dns2));
/* Success, lets parse the output */
lines = g_strsplit_set (out, "\n\r", -1);
for (iter = lines; iter && *iter; iter++) {
char *p;
if (!g_ascii_strcasecmp (*iter, "# BEGIN RECORD")) {
if (in_record) {
g_warning ("%s: malformed iscsiadm record: already parsing record.", __func__);
skip = TRUE;
}
} else if (!g_ascii_strcasecmp (*iter, "# END RECORD")) {
if (!skip && hwaddr_matched) {
/* Record is good; fill IP4 config with its info */
if (!method) {
g_warning ("%s: malformed iscsiadm record: missing BOOTPROTO.", __func__);
return FALSE;
}
g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, method, NULL);
if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
NMIP4Address *addr;
if (!ipaddr.s_addr || !prefix) {
g_warning ("%s: malformed iscsiadm record: BOOTPROTO=static "
"but missing IP address or prefix.", __func__);
return FALSE;
}
addr = nm_ip4_address_new ();
nm_ip4_address_set_address (addr, ipaddr.s_addr);
nm_ip4_address_set_prefix (addr, prefix);
nm_ip4_address_set_gateway (addr, gateway.s_addr);
nm_setting_ip4_config_add_address (s_ip4, addr);
nm_ip4_address_unref (addr);
if (dns1.s_addr)
nm_setting_ip4_config_add_dns (s_ip4, dns1.s_addr);
if (dns2.s_addr)
nm_setting_ip4_config_add_dns (s_ip4, dns2.s_addr);
// FIXME: DNS search domains?
}
return TRUE;
}
skip = FALSE;
hwaddr_matched = FALSE;
memset (&ipaddr, 0, sizeof (ipaddr));
memset (&gateway, 0, sizeof (gateway));
memset (&dns1, 0, sizeof (dns1));
memset (&dns2, 0, sizeof (dns2));
prefix = 0;
method = NULL;
}
if (skip)
continue;
/* HWADDR */
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_HWADDR_TAG, &skip))) {
struct ether_addr *ibft_mac;
ibft_mac = ether_aton (p);
if (!ibft_mac) {
g_warning ("%s: malformed iscsiadm record: invalid hwaddress.", __func__);
skip = TRUE;
continue;
}
if (memcmp (ifcfg_mac->data, (guint8 *) ibft_mac->ether_addr_octet, ETH_ALEN)) {
/* This record isn't for the current device, ignore it */
skip = TRUE;
continue;
}
/* Success, this record is for this device */
hwaddr_matched = TRUE;
}
/* BOOTPROTO */
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_BOOTPROTO_TAG, &skip))) {
if (!g_ascii_strcasecmp (p, "dhcp"))
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
else if (!g_ascii_strcasecmp (p, "static"))
method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
else {
g_warning ("%s: malformed iscsiadm record: unknown BOOTPROTO '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_IPADDR_TAG, &skip))) {
if (inet_pton (AF_INET, p, &ipaddr) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid IP address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_SUBNET_TAG, &skip))) {
struct in_addr mask;
if (inet_pton (AF_INET, p, &mask) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid subnet mask '%s'.",
__func__, p);
skip = TRUE;
continue;
}
prefix = nm_utils_ip4_netmask_to_prefix (mask.s_addr);
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_GATEWAY_TAG, &skip))) {
if (inet_pton (AF_INET, p, &gateway) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid IP gateway '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS1_TAG, &skip))) {
if (inet_pton (AF_INET, p, &dns1) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid DNS1 address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS2_TAG, &skip))) {
if (inet_pton (AF_INET, p, &dns2) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid DNS2 address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
}
success = TRUE;
done:
if (ifcfg_mac)
g_byte_array_free (ifcfg_mac, TRUE);
g_strfreev (lines);
g_free (out);
g_free (err);
return success;
}
static gboolean
read_ip4_address (shvarFile *ifcfg,
const char *tag,
@ -325,7 +604,10 @@ error:
}
static NMSetting *
make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error)
make_ip4_setting (shvarFile *ifcfg,
const char *network_file,
const char *iscsiadm_path,
GError **error)
{
NMSettingIP4Config *s_ip4 = NULL;
char *value = NULL;
@ -364,7 +646,15 @@ make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error)
if (value) {
if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp"))
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
else if (!g_ascii_strcasecmp (value, "autoip")) {
else if (!g_ascii_strcasecmp (value, "ibft")) {
/* iSCSI Boot Firmware Table: need to read values from the iSCSI
* firmware for this device and create the IP4 setting using those.
*/
if (fill_ip4_setting_from_ibft (ifcfg, s_ip4, iscsiadm_path, error))
return NM_SETTING (s_ip4);
g_object_unref (s_ip4);
return NULL;
} else if (!g_ascii_strcasecmp (value, "autoip")) {
g_free (value);
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
@ -498,38 +788,6 @@ error:
return NULL;
}
static gboolean
read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
{
char *value = NULL;
struct ether_addr *mac;
g_return_val_if_fail (ifcfg != NULL, FALSE);
g_return_val_if_fail (array != NULL, FALSE);
g_return_val_if_fail (*array == NULL, FALSE);
g_return_val_if_fail (error != NULL, FALSE);
g_return_val_if_fail (*error == NULL, FALSE);
value = svGetValue (ifcfg, "HWADDR", FALSE);
if (!value || !strlen (value)) {
g_free (value);
return TRUE;
}
mac = ether_aton (value);
if (!mac) {
g_free (value);
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"The MAC address '%s' was invalid.", value);
return FALSE;
}
g_free (value);
*array = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
return TRUE;
}
static gboolean
add_one_wep_key (shvarFile *ifcfg,
const char *shvar_key,
@ -2032,8 +2290,9 @@ is_wireless_device (const char *iface)
NMConnection *
connection_from_file (const char *filename,
const char *network_file,
const char *test_type, /* for unit tests only */
const char *network_file, /* for unit tests only */
const char *test_type, /* for unit tests only */
const char *iscsiadm_path, /* for unit tests only */
char **unmanaged,
char **keyfile,
GError **error,
@ -2041,7 +2300,7 @@ connection_from_file (const char *filename,
{
NMConnection *connection = NULL;
shvarFile *parsed;
char *type, *nmc = NULL;
char *type, *nmc = NULL, *bootproto;
NMSetting *s_ip4;
char *ifcfg_name = NULL;
gboolean nm_controlled = TRUE;
@ -2056,6 +2315,9 @@ connection_from_file (const char *filename,
if (!network_file)
network_file = SYSCONFDIR "/sysconfig/network";
if (!iscsiadm_path)
iscsiadm_path = SBINDIR "/iscsiadm";
ifcfg_name = utils_get_ifcfg_name (filename);
if (!ifcfg_name) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
@ -2142,7 +2404,7 @@ connection_from_file (const char *filename,
if (!connection || *unmanaged)
goto done;
s_ip4 = make_ip4_setting (parsed, network_file, error);
s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, error);
if (*error) {
g_object_unref (connection);
connection = NULL;
@ -2151,6 +2413,21 @@ connection_from_file (const char *filename,
nm_connection_add_setting (connection, s_ip4);
}
/* iSCSI / ibft connections are read-only since their settings are
* stored in NVRAM and can only be changed in BIOS.
*/
bootproto = svGetValue (parsed, "BOOTPROTO", FALSE);
if ( bootproto
&& connection
&& !g_ascii_strcasecmp (bootproto, "ibft")) {
NMSettingConnection *s_con;
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_READ_ONLY, TRUE, NULL);
}
if (!nm_connection_verify (connection, error)) {
g_object_unref (connection);
connection = NULL;

View file

@ -27,8 +27,9 @@
#include "shvar.h"
NMConnection *connection_from_file (const char *filename,
const char *network_file,
const char *test_type,
const char *network_file, /* for unit tests only */
const char *test_type, /* for unit tests only */
const char *iscsiadm_path, /* for unit tests only */
char **unmanaged,
char **keyfile,
GError **error,

View file

@ -30,3 +30,12 @@ check-local: test-ifcfg-rh
endif
EXTRA_DIST = \
iscsiadm-test-dhcp \
iscsiadm-test-static \
iscsiadm-test-malformed \
iscsiadm-test-bad-ipaddr \
iscsiadm-test-bad-gateway \
iscsiadm-test-bad-dns1 \
iscsiadm-test-bad-dns2

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10000.500.250.1
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = blah.foo.bar.baz
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,35 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = aa.bb.cc.dd
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = bb.cc.dd.ee
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,18 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
EOF

View file

@ -0,0 +1,33 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,35 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -35,7 +35,9 @@ EXTRA_DIST = \
ifcfg-test-wifi-wpa-eap-ttls-tls \
keys-test-wifi-wpa-eap-ttls-tls \
test_ca_cert.pem \
test1_key_and_cert.pem
test1_key_and_cert.pem \
ifcfg-test-ibft-dhcp \
ifcfg-test-ibft-static
check-local:
@for f in $(EXTRA_DIST); do \

View file

@ -0,0 +1,4 @@
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
DEVICE=eth0
HWADDR=00:33:21:98:b9:f1
BOOTPROTO=ibft

View file

@ -0,0 +1,4 @@
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
DEVICE=eth0
HWADDR=00:33:21:98:b9:f0
BOOTPROTO=ibft

View file

@ -176,6 +176,7 @@ test_read_minimal (void)
connection = connection_from_file (TEST_IFCFG_MINIMAL,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -299,6 +300,7 @@ test_read_unmanaged (void)
connection = connection_from_file (TEST_IFCFG_UNMANAGED,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -417,6 +419,7 @@ test_read_wired_static (void)
connection = connection_from_file (TEST_IFCFG_WIRED_STATIC,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -557,7 +560,7 @@ test_read_wired_static (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
"wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
"wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_WIRED_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -612,6 +615,7 @@ test_read_wired_dhcp (void)
connection = connection_from_file (TEST_IFCFG_WIRED_DHCP,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -777,6 +781,7 @@ test_read_wired_global_gateway (void)
connection = connection_from_file (TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
TEST_NETWORK_WIRED_GLOBAL_GATEWAY,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -844,7 +849,7 @@ test_read_wired_global_gateway (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
"wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
"wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -894,6 +899,7 @@ test_read_wired_never_default (void)
connection = connection_from_file (TEST_IFCFG_WIRED_NEVER_DEFAULT,
TEST_NETWORK_WIRED_NEVER_DEFAULT,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -983,6 +989,7 @@ test_read_onboot_no (void)
connection = connection_from_file (TEST_IFCFG_ONBOOT_NO,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1039,6 +1046,7 @@ test_read_wired_8021x_peap_mschapv2 (void)
connection = connection_from_file (TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1226,6 +1234,7 @@ test_read_wifi_open (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1394,6 +1403,7 @@ test_read_wifi_open_ssid_hex (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1463,7 +1473,14 @@ test_read_wifi_open_ssid_bad (const char *file, const char *test)
gboolean ignore_error = FALSE;
GError *error = NULL;
connection = connection_from_file (file, NULL, TYPE_WIRELESS, &unmanaged, &keyfile, &error, &ignore_error);
connection = connection_from_file (file,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection == NULL, test, "unexpected success reading %s", file);
g_clear_error (&error);
}
@ -1488,6 +1505,7 @@ test_read_wifi_open_ssid_quoted (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1575,6 +1593,7 @@ test_read_wifi_wep (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1835,6 +1854,7 @@ test_read_wifi_wep_adhoc (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP_ADHOC,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2088,6 +2108,7 @@ test_read_wifi_leap (void)
connection = connection_from_file (TEST_IFCFG_WIFI_LEAP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2235,6 +2256,7 @@ test_read_wifi_wpa_psk (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2533,6 +2555,7 @@ test_read_wifi_wpa_psk_adhoc (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2715,6 +2738,7 @@ test_read_wifi_wpa_psk_hex (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK_HEX,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2861,6 +2885,7 @@ test_read_wifi_wpa_eap_tls (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TLS,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2995,6 +3020,7 @@ test_read_wifi_wpa_eap_ttls_tls (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3152,6 +3178,7 @@ test_read_wifi_wep_eap_ttls_chap (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3402,6 +3429,7 @@ test_write_wired_static (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3500,6 +3528,7 @@ test_write_wired_dhcp (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3618,6 +3647,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3742,6 +3772,7 @@ test_write_wifi_open (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3846,6 +3877,7 @@ test_write_wifi_open_hex_ssid (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3970,6 +4002,7 @@ test_write_wifi_wep (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4114,6 +4147,7 @@ test_write_wifi_wep_adhoc (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4263,6 +4297,7 @@ test_write_wifi_wpa_psk (const char *name,
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4407,6 +4442,7 @@ test_write_wifi_wpa_psk_adhoc (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4566,6 +4602,7 @@ test_write_wifi_wpa_eap_tls (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4742,6 +4779,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4893,6 +4931,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4917,6 +4956,366 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
g_object_unref (reread);
}
#define TEST_IFCFG_IBFT_DHCP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft-dhcp"
static void
test_read_ibft_dhcp (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
char expected_mac_address[ETH_ALEN] = { 0x00, 0x33, 0x21, 0x98, 0xb9, 0xf1 };
const char *expected_id = "System test-ibft-dhcp";
guint64 expected_timestamp = 0;
connection = connection_from_file (TEST_IFCFG_IBFT_DHCP,
NULL,
TYPE_ETHERNET,
TEST_IFCFG_DIR "/iscsiadm-test-dhcp",
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"ibft-dhcp-read", "failed to read %s: %s", TEST_IFCFG_IBFT_DHCP, error->message);
ASSERT (nm_connection_verify (connection, &error),
"ibft-dhcp-verify", "failed to verify %s: %s", TEST_IFCFG_IBFT_DHCP, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"ibft-dhcp-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"ibft-dhcp-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* UUID can't be tested if the ifcfg does not contain the UUID key, because
* the UUID is generated on the full path of the ifcfg file, which can change
* depending on where the tests are run.
*/
/* Timestamp */
ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_TIMESTAMP);
/* Autoconnect */
ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_AUTOCONNECT);
/* Read-only */
ASSERT (nm_setting_connection_get_read_only (s_con) == TRUE,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_READ_ONLY);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"ibft-dhcp-verify-wired", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
ASSERT (array != NULL,
"ibft-dhcp-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (array->len == ETH_ALEN,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MTU);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"ibft-dhcp-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
"ibft-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
g_object_unref (connection);
}
#define TEST_IFCFG_IBFT_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft-static"
static void
test_read_ibft_static (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
char expected_mac_address[ETH_ALEN] = { 0x00, 0x33, 0x21, 0x98, 0xb9, 0xf0 };
const char *expected_id = "System test-ibft-static";
guint64 expected_timestamp = 0;
const char *expected_dns1 = "10.16.255.2";
const char *expected_dns2 = "10.16.255.3";
struct in_addr addr;
const char *expected_address1 = "192.168.32.72";
const char *expected_address1_gw = "192.168.35.254";
NMIP4Address *ip4_addr;
connection = connection_from_file (TEST_IFCFG_IBFT_STATIC,
NULL,
TYPE_ETHERNET,
TEST_IFCFG_DIR "/iscsiadm-test-static",
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"ibft-static-read", "failed to read %s: %s", TEST_IFCFG_IBFT_STATIC, error->message);
ASSERT (nm_connection_verify (connection, &error),
"ibft-static-verify", "failed to verify %s: %s", TEST_IFCFG_IBFT_STATIC, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"ibft-static-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"ibft-static-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* UUID can't be tested if the ifcfg does not contain the UUID key, because
* the UUID is generated on the full path of the ifcfg file, which can change
* depending on where the tests are run.
*/
/* Timestamp */
ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_TIMESTAMP);
/* Autoconnect */
ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_AUTOCONNECT);
/* Read-only */
ASSERT (nm_setting_connection_get_read_only (s_con) == TRUE,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_READ_ONLY);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"ibft-static-verify-wired", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
ASSERT (array != NULL,
"ibft-static-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (array->len == ETH_ALEN,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MTU);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"ibft-static-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
/* DNS Addresses */
ASSERT (nm_setting_ip4_config_get_num_dns (s_ip4) == 2,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (inet_pton (AF_INET, expected_dns1, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (inet_pton (AF_INET, expected_dns2, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #2",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 1,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
/* Address #1 */
ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
ASSERT (ip4_addr,
"ibft-static-verify-ip4", "failed to verify %s: missing IP4 address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 22,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET, expected_address1, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET, expected_address1_gw, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1 gateway",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
g_object_unref (connection);
}
static void
test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
{
NMConnection *connection;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
connection = connection_from_file (TEST_IFCFG_IBFT_STATIC,
NULL,
TYPE_ETHERNET,
iscsiadm_path,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection == NULL,
name, "unexpectedly able to read %s", TEST_IFCFG_IBFT_STATIC);
}
static void
test_write_wired_pppoe (void)
{
@ -5236,6 +5635,16 @@ int main (int argc, char **argv)
test_write_wifi_wpa_eap_ttls_tls ();
test_write_wifi_wpa_eap_ttls_mschapv2 ();
/* iSCSI / ibft */
test_read_ibft_dhcp ();
test_read_ibft_static ();
test_read_ibft_malformed ("ibft-bad-record-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-record");
test_read_ibft_malformed ("ibft-bad-entry-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-entry");
test_read_ibft_malformed ("ibft-bad-ipaddr-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-ipaddr");
test_read_ibft_malformed ("ibft-bad-gateway-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-gateway");
test_read_ibft_malformed ("ibft-bad-dns1-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns1");
test_read_ibft_malformed ("ibft-bad-dns2-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns2");
/* Stuff we expect to fail for now */
test_write_wired_pppoe ();
test_write_vpn ();