2005-12-31 08:21:24 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* Dan Williams <dcbw@redhat.com>
|
|
|
|
|
*
|
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
*
|
|
|
|
|
* (C) Copyright 2005 Red Hat, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
|
#include <dbus/dbus.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "nm-device.h"
|
|
|
|
|
#include "nm-device-private.h"
|
|
|
|
|
#include "nm-device-802-3-ethernet.h"
|
|
|
|
|
#include "nm-device-802-11-wireless.h"
|
|
|
|
|
#include "NetworkManagerDbus.h"
|
|
|
|
|
#include "NetworkManagerPolicy.h"
|
|
|
|
|
#include "NetworkManagerUtils.h"
|
|
|
|
|
#include "NetworkManagerSystem.h"
|
|
|
|
|
#include "nm-vpn-manager.h"
|
|
|
|
|
#include "nm-dhcp-manager.h"
|
|
|
|
|
#include "nm-dbus-nmi.h"
|
|
|
|
|
#include "nm-utils.h"
|
|
|
|
|
#include "autoip.h"
|
|
|
|
|
|
|
|
|
|
#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
|
|
|
|
|
|
|
|
|
|
struct _NMDevicePrivate
|
|
|
|
|
{
|
|
|
|
|
gboolean dispose_has_run;
|
|
|
|
|
|
|
|
|
|
char * udi;
|
|
|
|
|
char * iface;
|
|
|
|
|
NMDeviceType type;
|
|
|
|
|
guint32 capabilities;
|
|
|
|
|
char * driver;
|
|
|
|
|
gboolean removed;
|
|
|
|
|
|
|
|
|
|
gboolean link_active;
|
|
|
|
|
guint32 ip4_address;
|
|
|
|
|
struct in6_addr ip6_address;
|
|
|
|
|
NMData * app_data;
|
|
|
|
|
|
|
|
|
|
NMActRequest * act_request;
|
|
|
|
|
gboolean quit_activation;
|
|
|
|
|
|
|
|
|
|
/* IP configuration info */
|
|
|
|
|
void * system_config_data; /* Distro-specific config data (parsed config file, etc) */
|
|
|
|
|
gboolean use_dhcp;
|
|
|
|
|
NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */
|
|
|
|
|
|
|
|
|
|
GMainContext * context;
|
|
|
|
|
GMainLoop * loop;
|
|
|
|
|
GThread * worker;
|
|
|
|
|
gboolean worker_started;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static gpointer nm_device_worker (gpointer user_data);
|
|
|
|
|
|
|
|
|
|
static void nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req);
|
|
|
|
|
static void nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req);
|
|
|
|
|
|
|
|
|
|
static void nm_device_schedule_activation_handle_cancel (NMActRequest *req);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_test_wireless_extensions
|
|
|
|
|
*
|
|
|
|
|
* Test whether a given device is a wireless one or not.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static NMDeviceType
|
|
|
|
|
discover_device_type (const char *iface)
|
|
|
|
|
{
|
2006-01-02 02:50:47 +00:00
|
|
|
int err = -1;
|
|
|
|
|
int fd;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (iface != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if ((fd = iw_sockets_open ()) >= 0)
|
|
|
|
|
{
|
2006-01-02 02:50:47 +00:00
|
|
|
char buf[64];
|
|
|
|
|
|
|
|
|
|
strncpy (buf, iface, 62);
|
|
|
|
|
buf[63] = '\0';
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
#ifdef IOCTL_DEBUG
|
2006-01-02 02:50:47 +00:00
|
|
|
nm_info ("%s: About to GET IWNAME", iface);
|
2005-12-31 08:21:24 +00:00
|
|
|
#endif
|
2006-01-02 02:50:47 +00:00
|
|
|
err = ioctl (fd, SIOCGIWNAME, buf);
|
2005-12-31 08:21:24 +00:00
|
|
|
#ifdef IOCTL_DEBUG
|
2006-01-02 02:50:47 +00:00
|
|
|
nm_info ("%s: Done with GET IWNAME", iface);
|
2005-12-31 08:21:24 +00:00
|
|
|
#endif
|
|
|
|
|
close (fd);
|
|
|
|
|
}
|
|
|
|
|
return err == 0 ? DEVICE_TYPE_802_11_WIRELESS : DEVICE_TYPE_802_3_ETHERNET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_get_device_driver_name
|
|
|
|
|
*
|
|
|
|
|
* Get the device's driver name from HAL.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static char *
|
|
|
|
|
nm_get_device_driver_name (LibHalContext *ctx, const char *udi)
|
|
|
|
|
{
|
|
|
|
|
char * driver_name = NULL;
|
|
|
|
|
char * physdev_udi = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ctx != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (udi != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
physdev_udi = libhal_device_get_property_string (ctx, udi, "net.physical_device", NULL);
|
|
|
|
|
if (physdev_udi && libhal_device_property_exists (ctx, physdev_udi, "info.linux.driver", NULL))
|
|
|
|
|
{
|
|
|
|
|
char *drv = libhal_device_get_property_string (ctx, physdev_udi, "info.linux.driver", NULL);
|
|
|
|
|
driver_name = g_strdup (drv);
|
|
|
|
|
g_free (drv);
|
|
|
|
|
}
|
|
|
|
|
g_free (physdev_udi);
|
|
|
|
|
|
|
|
|
|
return driver_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_device_new (const char *iface,
|
|
|
|
|
const char *udi,
|
|
|
|
|
gboolean test_dev,
|
|
|
|
|
NMDeviceType test_dev_type,
|
|
|
|
|
NMData *app_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * dev;
|
|
|
|
|
NMDeviceType type;
|
2006-01-02 02:50:47 +00:00
|
|
|
nm_completion_args args;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (iface != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (udi != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (strlen (iface) > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (app_data != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
type = discover_device_type (iface);
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case DEVICE_TYPE_802_11_WIRELESS:
|
|
|
|
|
dev = NM_DEVICE (g_object_new (NM_TYPE_DEVICE_802_11_WIRELESS, NULL));
|
|
|
|
|
break;
|
|
|
|
|
case DEVICE_TYPE_802_3_ETHERNET:
|
|
|
|
|
dev = NM_DEVICE (g_object_new (NM_TYPE_DEVICE_802_3_ETHERNET, NULL));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-02 02:50:47 +00:00
|
|
|
g_assert (dev);
|
2005-12-31 08:21:24 +00:00
|
|
|
dev->priv->iface = g_strdup (iface);
|
|
|
|
|
dev->priv->udi = g_strdup (udi);
|
|
|
|
|
dev->priv->driver = nm_get_device_driver_name (app_data->hal_ctx, udi);
|
|
|
|
|
dev->priv->app_data = app_data;
|
|
|
|
|
dev->priv->type = type;
|
|
|
|
|
|
2006-01-02 02:50:47 +00:00
|
|
|
dev->priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->discover_generic_capabilities (dev);
|
|
|
|
|
|
|
|
|
|
/* Device thread's main loop */
|
|
|
|
|
dev->priv->context = g_main_context_new ();
|
|
|
|
|
dev->priv->loop = g_main_loop_new (dev->priv->context, FALSE);
|
|
|
|
|
|
|
|
|
|
/* Have to bring the device up before checking link status and other stuff */
|
|
|
|
|
nm_device_bring_up_wait (dev, 0);
|
|
|
|
|
|
|
|
|
|
// nm_device_set_active_link (dev, nm_device_probe_link_state (dev));
|
|
|
|
|
// nm_device_update_ip4_address (dev);
|
|
|
|
|
/* FIXME */
|
|
|
|
|
#if 0
|
|
|
|
|
nm_device_update_hw_address (dev);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Grab IP config data for this device from the system configuration files */
|
|
|
|
|
dev->priv->system_config_data = nm_system_device_get_system_config (dev);
|
|
|
|
|
dev->priv->use_dhcp = nm_system_device_get_use_dhcp (dev);
|
|
|
|
|
|
|
|
|
|
nm_print_device_capabilities (dev);
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/* Call type-specific initialization */
|
2006-01-02 02:50:47 +00:00
|
|
|
if (NM_DEVICE_GET_CLASS (dev)->init)
|
|
|
|
|
NM_DEVICE_GET_CLASS (dev)->init (dev);
|
|
|
|
|
|
|
|
|
|
dev->priv->worker = g_thread_create (nm_device_worker, dev, TRUE, NULL);
|
|
|
|
|
g_assert (dev->priv->worker);
|
|
|
|
|
g_object_ref (G_OBJECT (dev)); /* For the worker thread */
|
|
|
|
|
|
|
|
|
|
/* Block until our device thread has actually had a chance to start. */
|
|
|
|
|
args[0] = &dev->priv->worker_started;
|
|
|
|
|
args[1] = (gpointer) "nm_device_init(): waiting for device's worker thread to start";
|
|
|
|
|
args[2] = GINT_TO_POINTER (LOG_INFO);
|
|
|
|
|
args[3] = GINT_TO_POINTER (0);
|
|
|
|
|
nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY,
|
|
|
|
|
G_USEC_PER_SEC / 20, nm_completion_boolean_test, NULL, args);
|
|
|
|
|
|
|
|
|
|
nm_info ("nm_device_init(): device's worker thread started, continuing.");
|
2005-12-31 08:21:24 +00:00
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_init (NMDevice * self)
|
|
|
|
|
{
|
|
|
|
|
self->priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
self->priv->dispose_has_run = FALSE;
|
|
|
|
|
self->priv->udi = NULL;
|
|
|
|
|
self->priv->iface = NULL;
|
|
|
|
|
self->priv->type = DEVICE_TYPE_UNKNOWN;
|
|
|
|
|
self->priv->capabilities = NM_DEVICE_CAP_NONE;
|
|
|
|
|
self->priv->driver = NULL;
|
|
|
|
|
self->priv->removed = FALSE;
|
|
|
|
|
|
|
|
|
|
self->priv->link_active = FALSE;
|
|
|
|
|
self->priv->ip4_address = 0;
|
|
|
|
|
memset (&self->priv->ip6_address, 0, sizeof (struct in6_addr));
|
|
|
|
|
self->priv->app_data = NULL;
|
|
|
|
|
|
|
|
|
|
self->priv->act_request = NULL;
|
|
|
|
|
self->priv->quit_activation = FALSE;
|
|
|
|
|
|
|
|
|
|
self->priv->system_config_data = NULL;
|
|
|
|
|
self->priv->use_dhcp = TRUE;
|
|
|
|
|
self->priv->ip4_config = NULL;
|
|
|
|
|
|
|
|
|
|
self->priv->context = NULL;
|
|
|
|
|
self->priv->loop = NULL;
|
|
|
|
|
self->priv->worker = NULL;
|
|
|
|
|
self->priv->worker_started = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
real_discover_generic_capabilities (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
real_start (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_worker
|
|
|
|
|
*
|
|
|
|
|
* Main thread of the device.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gpointer
|
|
|
|
|
nm_device_worker (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->start (self);
|
|
|
|
|
|
|
|
|
|
self->priv->worker_started = TRUE;
|
|
|
|
|
g_main_loop_run (self->priv->loop);
|
|
|
|
|
|
|
|
|
|
g_main_loop_unref (self->priv->loop);
|
|
|
|
|
g_main_context_unref (self->priv->context);
|
|
|
|
|
|
|
|
|
|
self->priv->loop = NULL;
|
|
|
|
|
self->priv->context = NULL;
|
|
|
|
|
|
|
|
|
|
g_object_unref (G_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_worker_thread_stop (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
if (self->priv->loop)
|
|
|
|
|
g_main_loop_quit (self->priv->loop);
|
|
|
|
|
if (self->priv->worker)
|
|
|
|
|
{
|
|
|
|
|
g_thread_join (self->priv->worker);
|
|
|
|
|
self->priv->worker = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GMainContext *
|
|
|
|
|
nm_device_get_main_context (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_get_device_by_udi
|
|
|
|
|
*
|
|
|
|
|
* Search through the device list for a device with a given UDI.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: the caller MUST hold the device list mutex already to make
|
|
|
|
|
* this routine thread-safe.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_get_device_by_udi (NMData *data,
|
|
|
|
|
const char *udi)
|
|
|
|
|
{
|
|
|
|
|
GSList *elt;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (data != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (udi != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
for (elt = data->dev_list; elt; elt = g_slist_next (elt))
|
|
|
|
|
{
|
|
|
|
|
NMDevice *dev = NULL;
|
|
|
|
|
if ((dev = NM_DEVICE (elt->data)))
|
|
|
|
|
{
|
|
|
|
|
if (nm_null_safe_strcmp (nm_device_get_udi (dev), udi) == 0)
|
|
|
|
|
return dev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_get_device_by_iface
|
|
|
|
|
*
|
|
|
|
|
* Search through the device list for a device with a given iface.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: the caller MUST hold the device list mutex already to make
|
|
|
|
|
* this routine thread-safe.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_get_device_by_iface (NMData *data,
|
|
|
|
|
const char *iface)
|
|
|
|
|
{
|
|
|
|
|
GSList *elt;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (data != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (iface != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
for (elt = data->dev_list; elt; elt = g_slist_next (elt))
|
|
|
|
|
{
|
|
|
|
|
NMDevice *dev = NULL;
|
|
|
|
|
if ((dev = NM_DEVICE (elt->data)))
|
|
|
|
|
{
|
|
|
|
|
if (nm_null_safe_strcmp (nm_device_get_iface (dev), iface) == 0)
|
|
|
|
|
return dev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/set functions for UDI
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_device_get_udi (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->udi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_udi (NMDevice *self,
|
|
|
|
|
const char *udi)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
g_return_if_fail (udi != NULL);
|
|
|
|
|
|
|
|
|
|
if (self->priv->udi)
|
|
|
|
|
g_free (self->priv->udi);
|
|
|
|
|
self->priv->udi = g_strdup (udi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/set functions for iface
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_device_get_iface (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->iface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/set functions for driver
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_device_get_driver (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->driver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/set functions for type
|
|
|
|
|
*/
|
|
|
|
|
NMDeviceType
|
|
|
|
|
nm_device_get_device_type (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, DEVICE_TYPE_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
return self->priv->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_device_type (NMDevice *self, const NMDeviceType type)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
self->priv->type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
real_is_test_device (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_test_device (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->is_test_device (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Accessor for capabilities
|
|
|
|
|
*/
|
|
|
|
|
guint32
|
|
|
|
|
nm_device_get_capabilities (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
|
|
|
|
|
|
|
|
|
|
return self->priv->capabilities;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Accessor for type-specific capabilities
|
|
|
|
|
*/
|
|
|
|
|
guint32
|
|
|
|
|
nm_device_get_type_capabilities (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->get_type_capabilities (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
real_get_type_capabilities (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_DEVICE_CAP_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_get_app_data
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
struct NMData *
|
|
|
|
|
nm_device_get_app_data (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return self->priv->app_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/Set for "removed" flag
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_get_removed (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
return self->priv->removed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_removed (NMDevice *self,
|
|
|
|
|
const gboolean removed)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
self->priv->removed = removed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_get_act_request
|
|
|
|
|
*
|
|
|
|
|
* Return the devices activation request, if any.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
NMActRequest *
|
|
|
|
|
nm_device_get_act_request (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->act_request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get/set functions for link_active
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_has_active_link (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return self->priv->link_active;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_active_link (NMDevice *self,
|
|
|
|
|
const gboolean link_active)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
g_return_if_fail (self->priv->app_data != NULL);
|
|
|
|
|
|
|
|
|
|
if (self->priv->link_active != link_active)
|
|
|
|
|
{
|
|
|
|
|
self->priv->link_active = link_active;
|
|
|
|
|
|
|
|
|
|
/* Deactivate a currently active device */
|
|
|
|
|
if (!link_active && self->priv->act_request)
|
|
|
|
|
{
|
|
|
|
|
nm_device_deactivate (self);
|
|
|
|
|
nm_policy_schedule_device_change_check (self->priv->app_data);
|
|
|
|
|
}
|
|
|
|
|
else if (link_active && !self->priv->act_request)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * act_dev = nm_get_active_device (self->priv->app_data);
|
|
|
|
|
NMActRequest * act_dev_req = act_dev ? nm_device_get_act_request (act_dev) : NULL;
|
|
|
|
|
|
|
|
|
|
/* Should we switch to this device now that it has a link?
|
|
|
|
|
*
|
|
|
|
|
* Only auto-switch for wired devices, AND...
|
|
|
|
|
*
|
|
|
|
|
* only switch to fully-supported devices, since ones that don't have carrier detection
|
|
|
|
|
* capability usually report the carrier as "always on" even if its not really on. User
|
|
|
|
|
* must manually choose semi-supported devices.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
if (nm_device_is_802_3_ethernet (self) && (nm_device_get_capabilities (self) & NM_DEVICE_CAP_CARRIER_DETECT))
|
|
|
|
|
{
|
|
|
|
|
gboolean do_switch = act_dev ? FALSE : TRUE; /* If no currently active device, switch to this one */
|
|
|
|
|
NMActRequest * act_req;
|
|
|
|
|
|
|
|
|
|
/* If active device is wireless, switch to this one */
|
|
|
|
|
if (act_dev && nm_device_is_802_11_wireless (act_dev) && act_dev_req && !nm_act_request_get_user_requested (act_dev_req))
|
|
|
|
|
do_switch = TRUE;
|
|
|
|
|
|
|
|
|
|
if (do_switch && (act_req = nm_act_request_new (self->priv->app_data, self, NULL, TRUE)))
|
|
|
|
|
{
|
|
|
|
|
nm_info ("Will activate wired connection '%s' because it now has a link.", nm_device_get_iface (self));
|
|
|
|
|
nm_policy_schedule_device_activation (act_req);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nm_dbus_schedule_device_status_change_signal (self->priv->app_data, self, NULL, link_active ? DEVICE_CARRIER_ON : DEVICE_CARRIER_OFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
real_probe_link (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_probe_link_state
|
|
|
|
|
*
|
|
|
|
|
* Return the current link state of the device.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_probe_link_state (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
gboolean link = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!nm_device_is_up (self))
|
|
|
|
|
nm_device_bring_up (self);
|
|
|
|
|
|
|
|
|
|
link = NM_DEVICE_GET_CLASS (self)->probe_link (self);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (nm_device_is_802_11_wireless (dev))
|
|
|
|
|
{
|
|
|
|
|
link = nm_device_probe_wireless_link_state (dev);
|
|
|
|
|
nm_device_update_signal_strength (dev);
|
|
|
|
|
}
|
|
|
|
|
else if (nm_device_is_802_3_ethernet (dev))
|
|
|
|
|
link = nm_device_probe_wired_link_state (dev);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activation_start
|
|
|
|
|
*
|
|
|
|
|
* Tell the device thread to begin activation.
|
|
|
|
|
*
|
|
|
|
|
* Returns: TRUE on success activation beginning
|
|
|
|
|
* FALSE on error beginning activation (bad params, couldn't create thread)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_activation_start (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMData * data = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (!nm_device_is_activating (self), TRUE); /* Return if activation has already begun */
|
|
|
|
|
|
|
|
|
|
nm_act_request_ref (req);
|
|
|
|
|
self->priv->act_request = req;
|
|
|
|
|
self->priv->quit_activation = FALSE;
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) started...", nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_PREPARE);
|
|
|
|
|
nm_device_activate_schedule_stage1_device_prepare (req);
|
|
|
|
|
|
|
|
|
|
nm_schedule_state_change_signal_broadcast (data);
|
|
|
|
|
nm_dbus_schedule_device_status_change_signal (data, self, NULL, DEVICE_ACTIVATING);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage1_device_prepare
|
|
|
|
|
*
|
|
|
|
|
* Prepare for device activation
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage1_device_prepare (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self;
|
|
|
|
|
NMData * data;
|
|
|
|
|
NMAccessPoint *ap;
|
|
|
|
|
NMAPSecurity * security;
|
|
|
|
|
const char * iface;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
iface = nm_device_get_iface (self);
|
|
|
|
|
nm_info ("Activation (%s) Stage 1 (Device Prepare) started...", iface);
|
|
|
|
|
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->activation_prepare (self, req);
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
else
|
|
|
|
|
nm_device_activate_schedule_stage2_device_config (req);
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) Stage 1 (Device Prepare) complete.", iface);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage1_device_prepare
|
|
|
|
|
*
|
|
|
|
|
* Prepare a device for activation
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_PREPARE);
|
|
|
|
|
nm_info ("Activation (%s) Stage 1 (Device Prepare) scheduled...", nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage1_device_prepare, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
real_activation_prepare (NMDevice *dev, NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
/* Nothing to do */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
real_activation_config (NMDevice *dev, NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
/* Nothing to do */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage2_device_config
|
|
|
|
|
*
|
|
|
|
|
* Determine device parameters and set those on the device, ie
|
|
|
|
|
* for wireless devices, set essid, keys, etc.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage2_device_config (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self;
|
|
|
|
|
NMData * data;
|
|
|
|
|
const char * iface;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
iface = nm_device_get_iface (self);
|
|
|
|
|
nm_info ("Activation (%s) Stage 2 (Device Configure) starting...", iface);
|
|
|
|
|
|
|
|
|
|
/* Bring the device up */
|
|
|
|
|
if (!nm_device_is_up (self))
|
|
|
|
|
nm_device_bring_up (self);
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!NM_DEVICE_GET_CLASS (self)->activation_config (self, req))
|
|
|
|
|
{
|
|
|
|
|
nm_policy_schedule_activation_failed (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) Stage 2 (Device Configure) successful.", iface);
|
|
|
|
|
nm_device_activate_schedule_stage3_ip_config_start (req);
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
nm_info ("Activation (%s) Stage 2 (Device Configure) complete.", iface);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage2_device_config
|
|
|
|
|
*
|
|
|
|
|
* Schedule setup of the hardware device
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_activate_schedule_stage2_device_config (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_CONFIG);
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage2_device_config, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
nm_info ("Activation (%s) Stage 2 (Device Configure) scheduled...", nm_device_get_iface (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage3_ip_config_start
|
|
|
|
|
*
|
|
|
|
|
* Begin IP configuration with either DHCP or static IP.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage3_ip_config_start (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMData * data = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
NMAccessPoint * ap = NULL;
|
|
|
|
|
const char * iface;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
iface = nm_device_get_iface (self);
|
|
|
|
|
nm_info ("Activation (%s) Stage 3 (IP Configure Start) started...", iface);
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_802_11_wireless (self))
|
|
|
|
|
ap = nm_act_request_get_ap (req);
|
|
|
|
|
|
|
|
|
|
if (!(ap && nm_ap_get_user_created (ap)) && nm_device_get_use_dhcp (self))
|
|
|
|
|
{
|
|
|
|
|
/* Begin a DHCP transaction on the interface */
|
|
|
|
|
if (!nm_dhcp_manager_begin_transaction (data->dhcp_manager, req))
|
|
|
|
|
nm_policy_schedule_activation_failed (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Static IP and user-created wireless networks skip directly to IP configure stage */
|
|
|
|
|
nm_device_activate_schedule_stage4_ip_config_get (req);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
nm_info ("Activation (%s) Stage 3 (IP Configure Start) complete.", iface);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage3_ip_config_start
|
|
|
|
|
*
|
|
|
|
|
* Schedule IP configuration start
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_START);
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage3_ip_config_start, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
nm_info ("Activation (%s) Stage 3 (IP Configure Start) scheduled.", nm_device_get_iface (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_new_ip4_autoip_config
|
|
|
|
|
*
|
|
|
|
|
* Build up an IP config with a Link Local address
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static NMIP4Config *
|
|
|
|
|
nm_device_new_ip4_autoip_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
struct in_addr ip;
|
|
|
|
|
NMIP4Config * config = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (get_autoip (self, &ip))
|
|
|
|
|
{
|
|
|
|
|
#define LINKLOCAL_BCAST 0xa9feffff
|
|
|
|
|
|
|
|
|
|
config = nm_ip4_config_new ();
|
|
|
|
|
|
|
|
|
|
nm_ip4_config_set_address (config, (guint32)(ip.s_addr));
|
|
|
|
|
nm_ip4_config_set_netmask (config, (guint32)(ntohl (0xFFFF0000)));
|
|
|
|
|
nm_ip4_config_set_broadcast (config, (guint32)(ntohl (LINKLOCAL_BCAST)));
|
|
|
|
|
nm_ip4_config_set_gateway (config, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage4_ip_config_get
|
|
|
|
|
*
|
|
|
|
|
* Retrieve the correct IP config.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage4_ip_config_get (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMData * data = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
NMAccessPoint * ap = NULL;
|
|
|
|
|
NMIP4Config * ip4_config = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_802_11_wireless (self))
|
|
|
|
|
{
|
|
|
|
|
ap = nm_act_request_get_ap (req);
|
|
|
|
|
g_assert (ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Get) started...", nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ap && nm_ap_get_user_created (ap))
|
|
|
|
|
ip4_config = nm_device_new_ip4_autoip_config (self);
|
|
|
|
|
else if (nm_device_get_use_dhcp (self))
|
|
|
|
|
ip4_config = nm_dhcp_manager_get_ip4_config (data->dhcp_manager, req);
|
|
|
|
|
else
|
|
|
|
|
ip4_config = nm_system_device_new_ip4_system_config (self);
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ip4_config)
|
|
|
|
|
{
|
|
|
|
|
nm_act_request_set_ip4_config (req, ip4_config);
|
|
|
|
|
nm_device_activate_schedule_stage5_ip_config_commit (req);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Interfaces cannot be down if they are the active interface,
|
|
|
|
|
* otherwise we cannot use them for scanning or link detection.
|
|
|
|
|
*/
|
|
|
|
|
if (nm_device_is_802_11_wireless (self))
|
|
|
|
|
{
|
|
|
|
|
NMDevice80211Wireless *wdev = NM_DEVICE_802_11_WIRELESS (self);
|
|
|
|
|
|
|
|
|
|
nm_device_802_11_wireless_set_essid (wdev, "");
|
|
|
|
|
nm_device_802_11_wireless_set_wep_enc_key (wdev, NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_device_is_up (self))
|
|
|
|
|
nm_device_bring_up (self);
|
|
|
|
|
|
|
|
|
|
nm_policy_schedule_activation_failed (req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Get) complete.", nm_device_get_iface (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage4_ip_config_get
|
|
|
|
|
*
|
|
|
|
|
* Schedule creation of the IP config
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_GET);
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Get) scheduled...",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage4_ip_config_get, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage4_ip_config_timeout
|
|
|
|
|
*
|
|
|
|
|
* Retrieve the correct IP config.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage4_ip_config_timeout (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMData * data = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
NMIP4Config * ip4_config = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Timeout) started...",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_802_3_ethernet (self))
|
|
|
|
|
{
|
|
|
|
|
/* Wired network, no DHCP reply. Let's get an IP via Zeroconf. */
|
|
|
|
|
nm_info ("No DHCP reply received. Automatically obtaining IP via Zeroconf.");
|
|
|
|
|
ip4_config = nm_device_new_ip4_autoip_config (self);
|
|
|
|
|
}
|
|
|
|
|
else if (nm_device_is_802_11_wireless (self))
|
|
|
|
|
{
|
|
|
|
|
NMAccessPoint *ap = nm_act_request_get_ap (req);
|
|
|
|
|
NMAPSecurity * security;
|
|
|
|
|
|
|
|
|
|
g_assert (ap);
|
|
|
|
|
|
|
|
|
|
security = nm_ap_get_security (ap);
|
|
|
|
|
|
|
|
|
|
/* FIXME: should we only ask for a new key if the activation request is user-requested? */
|
|
|
|
|
if (ap && (nm_ap_security_get_we_cipher (security) != IW_AUTH_CIPHER_NONE))
|
|
|
|
|
{
|
|
|
|
|
/* Activation failed, we must have bad WEP key */
|
|
|
|
|
nm_debug ("Activation (%s/wireless): could not get IP configuration info for '%s', asking for new key.",
|
|
|
|
|
nm_device_get_iface (self), nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)");
|
|
|
|
|
nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Wireless, not encrypted, no DHCP Reply. Try Zeroconf. We do not do this in
|
|
|
|
|
* the encrypted case, because the problem could be (and more likely is) a bad key.
|
|
|
|
|
*/
|
|
|
|
|
nm_info ("No DHCP reply received. Automatically obtaining IP via Zeroconf.");
|
|
|
|
|
ip4_config = nm_device_new_ip4_autoip_config (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ip4_config)
|
|
|
|
|
{
|
|
|
|
|
nm_act_request_set_ip4_config (req, ip4_config);
|
|
|
|
|
nm_device_activate_schedule_stage5_ip_config_commit (req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Timeout) complete.",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage4_ip_config_timeout
|
|
|
|
|
*
|
|
|
|
|
* Deal with a timed out DHCP transaction
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_activate_schedule_stage4_ip_config_timeout (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_GET);
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage4_ip_config_timeout, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
nm_info ("Activation (%s) Stage 4 (IP Configure Timeout) scheduled...", nm_device_get_iface (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_stage5_ip_config_commit
|
|
|
|
|
*
|
|
|
|
|
* Commit the IP config on the device
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activate_stage5_ip_config_commit (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMData * data = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
NMIP4Config * ip4_config = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
ip4_config = nm_act_request_get_ip4_config (req);
|
|
|
|
|
g_assert (ip4_config);
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) Stage 5 (IP Configure Commit) started...",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
if (nm_device_activation_should_cancel (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (req);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_device_set_ip4_config (self, ip4_config);
|
|
|
|
|
if (nm_system_device_set_from_ip4_config (self))
|
|
|
|
|
{
|
|
|
|
|
nm_device_update_ip4_address (self);
|
|
|
|
|
nm_system_device_add_ip6_link_address (self);
|
|
|
|
|
nm_system_restart_mdns_responder ();
|
|
|
|
|
nm_system_activate_nis (self->priv->ip4_config);
|
|
|
|
|
nm_device_set_active_link (self, nm_device_probe_link_state (self));
|
|
|
|
|
nm_policy_schedule_activation_finish (req);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
nm_policy_schedule_activation_failed (req);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
nm_info ("Activation (%s) Stage 5 (IP Configure Commit) complete.",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage5_ip_config_commit
|
|
|
|
|
*
|
|
|
|
|
* Schedule commit of the IP config
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
GSource * source = NULL;
|
|
|
|
|
NMDevice * self = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_COMMIT);
|
|
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage5_ip_config_commit, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
nm_info ("Activation (%s) Stage 5 (IP Configure Commit) scheduled...", nm_device_get_iface (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activation_handle_cancel
|
|
|
|
|
*
|
|
|
|
|
* Cancel activation on a device and clean up.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_device_activation_handle_cancel (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self;
|
|
|
|
|
NMData * data;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (req != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
if ((req = nm_device_get_act_request (self)) && nm_device_is_activating (self))
|
|
|
|
|
{
|
|
|
|
|
self->priv->act_request = NULL;
|
|
|
|
|
nm_act_request_unref (req);
|
|
|
|
|
}
|
|
|
|
|
nm_schedule_state_change_signal_broadcast (self->priv->app_data);
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) cancellation handled.", nm_device_get_iface (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_schedule_activation_handle_cancel
|
|
|
|
|
*
|
|
|
|
|
* Schedule the activation cancel handler
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
nm_device_schedule_activation_handle_cancel (NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self;
|
|
|
|
|
NMData * data;
|
|
|
|
|
GSource * source;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (req != NULL);
|
|
|
|
|
|
|
|
|
|
data = nm_act_request_get_data (req);
|
|
|
|
|
g_assert (data);
|
|
|
|
|
|
|
|
|
|
self = nm_act_request_get_dev (req);
|
|
|
|
|
g_assert (self);
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s) cancellation handler scheduled...", nm_device_get_iface (self));
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (source, (GSourceFunc) nm_device_activation_handle_cancel, req, NULL);
|
|
|
|
|
g_source_attach (source, self->priv->context);
|
|
|
|
|
g_source_unref (source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activation_cancel
|
|
|
|
|
*
|
|
|
|
|
* Signal activation worker that it should stop and die.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_activation_cancel (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDeviceClass * klass;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
|
|
|
|
|
klass->cancel_activation (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
gboolean nm_ac_test (int tries,
|
|
|
|
|
nm_completion_args args)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self = args[0];
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_activating (self))
|
|
|
|
|
{
|
|
|
|
|
if (tries % 20 == 0)
|
|
|
|
|
nm_info ("Activation (%s): waiting for device to cancel activation.", nm_device_get_iface (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
real_cancel_activation (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
nm_completion_args args;
|
|
|
|
|
NMData * app_data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (self->priv->app_data);
|
|
|
|
|
app_data = self->priv->app_data;
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_activating (self))
|
|
|
|
|
{
|
|
|
|
|
NMActRequest * req = nm_device_get_act_request (self);
|
|
|
|
|
gboolean clear_act_request = FALSE;
|
|
|
|
|
|
|
|
|
|
nm_info ("Activation (%s): cancelling...", nm_device_get_iface (self));
|
|
|
|
|
self->priv->quit_activation = TRUE;
|
|
|
|
|
|
|
|
|
|
/* If the device is waiting for DHCP or a user key, force its current request to stop. */
|
|
|
|
|
if (nm_act_request_get_stage (req) == NM_ACT_STAGE_NEED_USER_KEY)
|
|
|
|
|
{
|
|
|
|
|
nm_dbus_cancel_get_user_key_for_network (app_data->dbus_connection, req);
|
|
|
|
|
clear_act_request = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (nm_act_request_get_stage (req) == NM_ACT_STAGE_IP_CONFIG_START)
|
|
|
|
|
{
|
|
|
|
|
nm_dhcp_manager_cancel_transaction (app_data->dhcp_manager, req);
|
|
|
|
|
clear_act_request = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (clear_act_request)
|
|
|
|
|
{
|
|
|
|
|
self->priv->act_request = NULL;
|
|
|
|
|
nm_act_request_unref (req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Spin until cancelled. Possible race conditions or deadlocks here.
|
|
|
|
|
* The other problem with waiting here is that we hold up dbus traffic
|
|
|
|
|
* that we should respond to.
|
|
|
|
|
*/
|
|
|
|
|
args[0] = self;
|
|
|
|
|
nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY, G_USEC_PER_SEC / 20, nm_ac_test, NULL, args);
|
|
|
|
|
nm_info ("Activation (%s): cancelled.", nm_device_get_iface (self));
|
|
|
|
|
nm_schedule_state_change_signal_broadcast (app_data);
|
|
|
|
|
self->priv->quit_activation = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_deactivate_quickly
|
|
|
|
|
*
|
|
|
|
|
* Quickly deactivate a device, for things like sleep, etc. Doesn't
|
|
|
|
|
* clean much stuff up, and nm_device_deactivate() should be called
|
|
|
|
|
* on the device eventually.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_deactivate_quickly (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMData * app_data;
|
|
|
|
|
NMActRequest * act_request;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (self->priv->app_data != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
nm_system_shutdown_nis ();
|
|
|
|
|
|
|
|
|
|
app_data = self->priv->app_data;
|
|
|
|
|
nm_vpn_manager_deactivate_vpn_connection (app_data->vpn_manager, self);
|
|
|
|
|
|
|
|
|
|
if (nm_device_is_activated (self))
|
|
|
|
|
nm_dbus_schedule_device_status_change_signal (app_data, self, NULL, DEVICE_NO_LONGER_ACTIVE);
|
|
|
|
|
else if (nm_device_is_activating (self))
|
|
|
|
|
nm_device_activation_cancel (self);
|
|
|
|
|
|
|
|
|
|
/* Tear down an existing activation request, which may not have happened
|
|
|
|
|
* in nm_device_activation_cancel() above, for various reasons.
|
|
|
|
|
*/
|
|
|
|
|
if ((act_request = nm_device_get_act_request (self)))
|
|
|
|
|
{
|
|
|
|
|
nm_dhcp_manager_cancel_transaction (app_data->dhcp_manager, act_request);
|
|
|
|
|
nm_act_request_unref (act_request);
|
|
|
|
|
self->priv->act_request = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_deactivate
|
|
|
|
|
*
|
|
|
|
|
* Remove a device's routing table entries and IP address.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_deactivate (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMData * app_data;
|
|
|
|
|
NMIP4Config * config;
|
|
|
|
|
|
2006-01-02 02:50:47 +00:00
|
|
|
g_return_if_fail (self != NULL);
|
2005-12-31 08:21:24 +00:00
|
|
|
g_return_if_fail (self->priv->app_data != NULL);
|
|
|
|
|
|
|
|
|
|
nm_info ("Deactivating device %s.", nm_device_get_iface (self));
|
|
|
|
|
|
|
|
|
|
nm_device_deactivate_quickly (self);
|
|
|
|
|
|
|
|
|
|
app_data = self->priv->app_data;
|
|
|
|
|
|
|
|
|
|
/* Remove any device nameservers and domains */
|
|
|
|
|
if ((config = nm_device_get_ip4_config (self)))
|
|
|
|
|
{
|
|
|
|
|
nm_named_manager_remove_ip4_config (app_data->named_manager, config);
|
|
|
|
|
nm_device_set_ip4_config (self, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Take out any entries in the routing table and any IP address the device had. */
|
|
|
|
|
nm_system_device_flush_routes (self);
|
|
|
|
|
nm_system_device_flush_addresses (self);
|
2006-01-02 02:50:47 +00:00
|
|
|
nm_device_update_ip4_address (self);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2006-01-02 02:50:47 +00:00
|
|
|
/* Call device type-specific deactivation */
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
|
|
|
|
|
|
|
|
|
nm_schedule_state_change_signal_broadcast (self->priv->app_data);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_is_activating
|
|
|
|
|
*
|
|
|
|
|
* Return whether or not the device is currently activating itself.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_activating (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
NMActRequest * req;
|
|
|
|
|
NMActStage stage;
|
|
|
|
|
gboolean activating = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (dev != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!(req = nm_device_get_act_request (dev)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
stage = nm_act_request_get_stage (req);
|
|
|
|
|
switch (stage)
|
|
|
|
|
{
|
|
|
|
|
case NM_ACT_STAGE_DEVICE_PREPARE:
|
|
|
|
|
case NM_ACT_STAGE_DEVICE_CONFIG:
|
|
|
|
|
case NM_ACT_STAGE_NEED_USER_KEY:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_START:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_GET:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_COMMIT:
|
|
|
|
|
activating = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NM_ACT_STAGE_ACTIVATED:
|
|
|
|
|
case NM_ACT_STAGE_FAILED:
|
|
|
|
|
case NM_ACT_STAGE_CANCELLED:
|
|
|
|
|
case NM_ACT_STAGE_UNKNOWN:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return activating;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_is_activated
|
|
|
|
|
*
|
|
|
|
|
* Return whether or not the device is successfully activated.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_activated (NMDevice *dev)
|
|
|
|
|
{
|
|
|
|
|
NMActRequest * req;
|
|
|
|
|
NMActStage stage;
|
|
|
|
|
gboolean activated = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (dev != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!(req = nm_device_get_act_request (dev)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
stage = nm_act_request_get_stage (req);
|
|
|
|
|
switch (stage)
|
|
|
|
|
{
|
|
|
|
|
case NM_ACT_STAGE_ACTIVATED:
|
|
|
|
|
activated = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NM_ACT_STAGE_DEVICE_PREPARE:
|
|
|
|
|
case NM_ACT_STAGE_DEVICE_CONFIG:
|
|
|
|
|
case NM_ACT_STAGE_NEED_USER_KEY:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_START:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_GET:
|
|
|
|
|
case NM_ACT_STAGE_IP_CONFIG_COMMIT:
|
|
|
|
|
case NM_ACT_STAGE_FAILED:
|
|
|
|
|
case NM_ACT_STAGE_CANCELLED:
|
|
|
|
|
case NM_ACT_STAGE_UNKNOWN:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return activated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activation_should_cancel
|
|
|
|
|
*
|
|
|
|
|
* Return whether or not we've been told to cancel activation
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_activation_should_cancel (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return (self->priv->quit_activation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* IP Configuration stuff */
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_get_use_dhcp (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return self->priv->use_dhcp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_use_dhcp (NMDevice *self,
|
|
|
|
|
gboolean use_dhcp)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
self->priv->use_dhcp = use_dhcp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NMIP4Config *
|
|
|
|
|
nm_device_get_ip4_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->ip4_config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config)
|
|
|
|
|
{
|
|
|
|
|
NMIP4Config *old_config;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
old_config = self->priv->ip4_config;
|
|
|
|
|
if (config)
|
|
|
|
|
nm_ip4_config_ref (config);
|
|
|
|
|
self->priv->ip4_config = config;
|
|
|
|
|
if (old_config)
|
|
|
|
|
nm_ip4_config_unref (old_config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_get_ip4_address
|
|
|
|
|
*
|
|
|
|
|
* Get a device's IPv4 address
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
guint32
|
|
|
|
|
nm_device_get_ip4_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, 0);
|
|
|
|
|
|
|
|
|
|
return self->priv->ip4_address;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_update_ip4_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
guint32 new_address;
|
|
|
|
|
struct ifreq req;
|
|
|
|
|
NMSock * sk;
|
|
|
|
|
int err;
|
|
|
|
|
const char * iface;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
g_return_if_fail (self->priv->app_data != NULL);
|
|
|
|
|
g_return_if_fail (nm_device_get_iface (self) != NULL);
|
|
|
|
|
|
|
|
|
|
/* Test devices get a nice, bogus IP address */
|
|
|
|
|
if (nm_device_is_test_device (self))
|
|
|
|
|
{
|
|
|
|
|
self->priv->ip4_address = 0x07030703;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((sk = nm_dev_sock_open (self, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
iface = nm_device_get_iface (self);
|
|
|
|
|
memset (&req, 0, sizeof (struct ifreq));
|
|
|
|
|
strncpy (req.ifr_name, iface, sizeof (req.ifr_name) - 1);
|
|
|
|
|
#ifdef IOCTL_DEBUG
|
|
|
|
|
nm_info ("%s: About to GET IFADDR.", iface);
|
|
|
|
|
#endif
|
|
|
|
|
err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIFADDR, &req);
|
|
|
|
|
#ifdef IOCTL_DEBUG
|
|
|
|
|
nm_info ("%s: Done with GET IFADDR.", iface);
|
|
|
|
|
#endif
|
|
|
|
|
nm_dev_sock_close (sk);
|
|
|
|
|
if (err != 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr;
|
|
|
|
|
if (new_address != nm_device_get_ip4_address (self))
|
|
|
|
|
self->priv->ip4_address = new_address;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_set_up_down
|
|
|
|
|
*
|
|
|
|
|
* Set the up flag on the device on or off
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
nm_device_set_up_down (NMDevice *self,
|
|
|
|
|
gboolean up)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
nm_system_device_set_up_down (self, up);
|
|
|
|
|
|
|
|
|
|
/* Make sure we have a valid MAC address, some cards reload firmware when they
|
|
|
|
|
* are brought up.
|
|
|
|
|
*/
|
|
|
|
|
/* FIXME */
|
|
|
|
|
#if 0
|
|
|
|
|
if (!nm_ethernet_address_is_valid (&(self->priv->hw_addr)))
|
|
|
|
|
nm_device_update_hw_address (self);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Interface state functions: bring up, down, check
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_up (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMSock * sk;
|
|
|
|
|
struct ifreq ifr;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if ((sk = nm_dev_sock_open (self, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
|
|
|
|
|
return (FALSE);
|
|
|
|
|
|
|
|
|
|
/* Get device's flags */
|
|
|
|
|
strncpy (ifr.ifr_name, nm_device_get_iface (self), sizeof (ifr.ifr_name) - 1);
|
|
|
|
|
#ifdef IOCTL_DEBUG
|
|
|
|
|
nm_info ("%s: About to GET IFFLAGS.", nm_device_get_iface (self));
|
|
|
|
|
#endif
|
|
|
|
|
err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIFFLAGS, &ifr);
|
|
|
|
|
#ifdef IOCTL_DEBUG
|
|
|
|
|
nm_info ("%s: Done with GET IFFLAGS.", nm_device_get_iface (self));
|
|
|
|
|
#endif
|
|
|
|
|
nm_dev_sock_close (sk);
|
|
|
|
|
if (!err)
|
|
|
|
|
return (!((ifr.ifr_flags^IFF_UP) & IFF_UP));
|
|
|
|
|
|
|
|
|
|
if (errno != ENODEV)
|
|
|
|
|
{
|
|
|
|
|
nm_warning ("nm_device_is_up() could not get flags for device %s. errno = %d",
|
|
|
|
|
nm_device_get_iface (self), errno );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* I really wish nm_v_wait_for_completion_or_timeout could translate these
|
|
|
|
|
* to first class args instead of a all this void * arg stuff, so these
|
|
|
|
|
* helpers could be nice and _tiny_. */
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_completion_device_is_up_test (int tries,
|
|
|
|
|
nm_completion_args args)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (args[0]);
|
|
|
|
|
gboolean *err = args[1];
|
|
|
|
|
gboolean cancelable = GPOINTER_TO_INT (args[2]);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
g_return_val_if_fail (err != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
*err = FALSE;
|
|
|
|
|
if (cancelable && nm_device_activation_should_cancel (self)) {
|
|
|
|
|
*err = TRUE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
if (nm_device_is_up (self))
|
|
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_bring_up (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
nm_device_set_up_down (self, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_bring_up_wait (NMDevice *self,
|
|
|
|
|
gboolean cancelable)
|
|
|
|
|
{
|
|
|
|
|
gboolean err = FALSE;
|
|
|
|
|
nm_completion_args args;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
nm_device_bring_up (self);
|
|
|
|
|
|
|
|
|
|
args[0] = self;
|
|
|
|
|
args[1] = &err;
|
|
|
|
|
args[2] = GINT_TO_POINTER (cancelable);
|
|
|
|
|
nm_wait_for_completion (400, G_USEC_PER_SEC / 200, NULL, nm_completion_device_is_up_test, args);
|
|
|
|
|
if (err)
|
|
|
|
|
nm_info ("failed to bring up device %s", self->priv->iface);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_bring_down (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (self != NULL);
|
|
|
|
|
|
|
|
|
|
nm_device_set_up_down (self, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
nm_completion_device_is_down_test (int tries,
|
|
|
|
|
nm_completion_args args)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (args[0]);
|
|
|
|
|
gboolean *err = args[1];
|
|
|
|
|
gboolean cancelable = GPOINTER_TO_INT (args[2]);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
g_return_val_if_fail (err != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
*err = FALSE;
|
|
|
|
|
if (cancelable && nm_device_activation_should_cancel (self)) {
|
|
|
|
|
*err = TRUE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
if (!nm_device_is_up (self))
|
|
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_bring_down_wait (NMDevice *self,
|
|
|
|
|
gboolean cancelable)
|
|
|
|
|
{
|
|
|
|
|
gboolean err = FALSE;
|
|
|
|
|
nm_completion_args args;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, TRUE);
|
|
|
|
|
|
|
|
|
|
nm_device_bring_down (self);
|
|
|
|
|
|
|
|
|
|
args[0] = self;
|
|
|
|
|
args[1] = &err;
|
|
|
|
|
args[2] = GINT_TO_POINTER (cancelable);
|
|
|
|
|
nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL,
|
|
|
|
|
nm_completion_device_is_down_test, args);
|
|
|
|
|
if (err)
|
|
|
|
|
nm_info ("failed to bring down device %s", self->priv->iface);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_get_system_config_data
|
|
|
|
|
*
|
|
|
|
|
* Return distro-specific system configuration data for this device.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void *
|
|
|
|
|
nm_device_get_system_config_data (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return self->priv->system_config_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_dispose (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self = NM_DEVICE (object);
|
|
|
|
|
NMDeviceClass * klass;
|
|
|
|
|
GObjectClass * parent_class;
|
|
|
|
|
|
|
|
|
|
if (self->priv->dispose_has_run)
|
|
|
|
|
/* If dispose did already run, return. */
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Make sure dispose does not run twice. */
|
|
|
|
|
self->priv->dispose_has_run = TRUE;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
nm_device_worker_thread_stop (self);
|
|
|
|
|
nm_device_bring_down (self);
|
|
|
|
|
|
|
|
|
|
nm_system_device_free_system_config (self, self->priv->system_config_data);
|
|
|
|
|
if (self->priv->ip4_config)
|
|
|
|
|
{
|
|
|
|
|
nm_ip4_config_unref (self->priv->ip4_config);
|
|
|
|
|
self->priv->ip4_config = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (self->priv->act_request)
|
|
|
|
|
{
|
|
|
|
|
nm_act_request_unref (self->priv->act_request);
|
|
|
|
|
self->priv->act_request = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Chain up to the parent class */
|
|
|
|
|
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
|
|
|
|
|
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
|
|
|
|
|
parent_class->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMDevice * self = NM_DEVICE (object);
|
|
|
|
|
NMDeviceClass * klass;
|
|
|
|
|
GObjectClass * parent_class;
|
|
|
|
|
|
|
|
|
|
g_free (self->priv->udi);
|
|
|
|
|
g_free (self->priv->iface);
|
|
|
|
|
g_free (self->priv->driver);
|
|
|
|
|
|
|
|
|
|
/* Chain up to the parent class */
|
|
|
|
|
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
|
|
|
|
|
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
|
|
|
|
|
parent_class->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_class_init (NMDeviceClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
object_class->dispose = nm_device_dispose;
|
|
|
|
|
object_class->finalize = nm_device_finalize;
|
|
|
|
|
|
|
|
|
|
klass->is_test_device = real_is_test_device;
|
|
|
|
|
klass->cancel_activation = real_cancel_activation;
|
|
|
|
|
klass->get_type_capabilities = real_get_type_capabilities;
|
|
|
|
|
klass->discover_generic_capabilities = real_discover_generic_capabilities;
|
|
|
|
|
klass->start = real_start;
|
|
|
|
|
klass->activation_prepare = real_activation_prepare;
|
|
|
|
|
klass->activation_config = real_activation_config;
|
|
|
|
|
klass->probe_link = real_probe_link;
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (object_class, sizeof (NMDevicePrivate));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GType
|
|
|
|
|
nm_device_get_type (void)
|
|
|
|
|
{
|
|
|
|
|
static GType type = 0;
|
|
|
|
|
if (type == 0)
|
|
|
|
|
{
|
|
|
|
|
static const GTypeInfo info =
|
|
|
|
|
{
|
|
|
|
|
sizeof (NMDeviceClass),
|
|
|
|
|
NULL, /* base_init */
|
|
|
|
|
NULL, /* base_finalize */
|
|
|
|
|
(GClassInitFunc) nm_device_class_init,
|
|
|
|
|
NULL, /* class_finalize */
|
|
|
|
|
NULL, /* class_data */
|
|
|
|
|
sizeof (NMDevice),
|
|
|
|
|
0, /* n_preallocs */
|
|
|
|
|
(GInstanceInitFunc) nm_device_init
|
|
|
|
|
};
|
|
|
|
|
type = g_type_register_static (G_TYPE_OBJECT,
|
|
|
|
|
"NMDevice",
|
|
|
|
|
&info, 0);
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|