static void
adsl_cleanup (NMDeviceAdsl *self)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	if (priv->ppp_manager) {
		g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_state_changed), self);
		g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_ip4_config), self);
		nm_exported_object_clear_and_unexport (&priv->ppp_manager);
	}

	g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (link_changed_cb), self);

	if (priv->brfd >= 0) {
		close (priv->brfd);
		priv->brfd = -1;
	}

	nm_clear_g_source (&priv->nas_update_id);

	/* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet,
	 * so it gets leaked.  It does get destroyed when it's no longer in use,
	 * but we have no control over that.
	 */
	priv->nas_ifindex = -1;
	g_clear_pointer (&priv->nas_ifname, g_free);
}
Beispiel #2
0
static void
dispose (GObject *object)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (object);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	if (priv->disposed) {
		G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
		return;
	}

	priv->disposed = TRUE;

	if (priv->carrier_poll_id) {
		g_source_remove (priv->carrier_poll_id);
		priv->carrier_poll_id = 0;
	}

	if (priv->lost_link_id) {
		g_signal_handler_disconnect (nm_platform_get (), priv->lost_link_id);
		priv->lost_link_id = 0;
	}

	g_free (priv->nas_ifname);
	priv->nas_ifname = NULL;

	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
}
Beispiel #3
0
static void
deactivate (NMDevice *device)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	if (priv->ppp_manager) {
		g_object_unref (priv->ppp_manager);
		priv->ppp_manager = NULL;
	}

	if (priv->lost_link_id) {
		g_signal_handler_disconnect (nm_platform_get (), priv->lost_link_id);
		priv->lost_link_id = 0;
	}

	if (priv->brfd >= 0) {
		close (priv->brfd);
		priv->brfd = -1;
	}

	/* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet,
	 * so it gets leaked.  It does get destroyed when it's no longer in use,
	 * but we have no control over that.
	 */
	if (priv->nas_ifindex >= 0)
		priv->nas_ifindex = -1;
	g_free (priv->nas_ifname);
	priv->nas_ifname = NULL;

	/* Poke NMDevice to notice that our hw_address is no longer valid */
	nm_device_update_hw_address (NM_DEVICE (self));
}
Beispiel #4
0
static guint
get_hw_address_length (NMDevice *device)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device);

	return priv->nas_ifname ? ETH_ALEN : 0;
}
static gboolean
pppoe_vcc_config (NMDeviceAdsl *self)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	NMDevice *device = NM_DEVICE (self);
	NMSettingAdsl *s_adsl;

	s_adsl = nm_connection_get_setting_adsl (nm_device_get_applied_connection (device));
	g_assert (s_adsl);

	/* Set up the VCC */
	if (!br2684_assign_vcc (self, s_adsl))
		return FALSE;

	/* Watch for the 'nas' interface going away */
	g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED,
	                  G_CALLBACK (link_changed_cb),
	                  self);

	_LOGD (LOGD_ADSL, "ATM setup successful");

	/* otherwise we're good for stage3 */
	nm_platform_link_set_up (NM_PLATFORM_GET, priv->nas_ifindex, NULL);

	return TRUE;
}
static void
deactivate (NMDevice *device)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	if (priv->ppp_manager) {
		g_object_unref (priv->ppp_manager);
		priv->ppp_manager = NULL;
	}

	g_signal_handlers_disconnect_by_func (nm_platform_get (), G_CALLBACK (link_changed_cb), device);

	if (priv->brfd >= 0) {
		close (priv->brfd);
		priv->brfd = -1;
	}

	/* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet,
	 * so it gets leaked.  It does get destroyed when it's no longer in use,
	 * but we have no control over that.
	 */
	if (priv->nas_ifindex >= 0)
		priv->nas_ifindex = -1;
	g_free (priv->nas_ifname);
	priv->nas_ifname = NULL;
}
static GObject*
constructor (GType type,
			 guint n_construct_params,
			 GObjectConstructParam *construct_params)
{
	GObject *object;
	NMDeviceAdsl *self;
	NMDeviceAdslPrivate *priv;

	object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type,
	                                                                    n_construct_params,
	                                                                    construct_params);
	if (!object)
		return NULL;

	self = NM_DEVICE_ADSL (object);
	priv = NM_DEVICE_ADSL_GET_PRIVATE (object);

	priv->atm_index = get_atm_index (nm_device_get_iface (NM_DEVICE (object)));
	if (priv->atm_index < 0) {
		_LOGE (LOGD_ADSL, "error reading ATM device index");
		g_object_unref (object);
		return NULL;
	} else
		_LOGD (LOGD_ADSL, "ATM device index %d", priv->atm_index);

	/* Poll the carrier */
	priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, object);

	return object;
}
Beispiel #8
0
static GObject*
constructor (GType type,
			 guint n_construct_params,
			 GObjectConstructParam *construct_params)
{
	GObject *object;
	NMDeviceAdslPrivate *priv;
	GError *error = NULL;

	object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type,
	                                                                    n_construct_params,
	                                                                    construct_params);
	if (!object)
		return NULL;

	priv = NM_DEVICE_ADSL_GET_PRIVATE (object);

	priv->atm_index = get_atm_index (nm_device_get_iface (NM_DEVICE (object)), &error);
	if (priv->atm_index < 0) {
		nm_log_dbg (LOGD_ADSL, "error reading ATM device index: (%d) %s",
		            error ? error->code : -1,
		            error && error->message ? error->message : "(unknown)");
		g_clear_error (&error);
		g_object_unref (object);
		return NULL;
	} else {
		nm_log_dbg (LOGD_ADSL, "(%s): ATM device index %d",
				    nm_device_get_iface (NM_DEVICE (object)), priv->atm_index);
	}

	/* Poll the carrier */
	priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, object);

	return object;
}
/**
 * nm_device_adsl_get_carrier:
 * @device: a #NMDeviceAdsl
 *
 * Whether the device has carrier.
 *
 * Returns: %TRUE if the device has carrier
 **/
gboolean
nm_device_adsl_get_carrier (NMDeviceAdsl *device)
{
	g_return_val_if_fail (NM_IS_DEVICE_ADSL (device), FALSE);

	_nm_object_ensure_inited (NM_OBJECT (device));
	return NM_DEVICE_ADSL_GET_PRIVATE (device)->carrier;
}
static void
dispose (GObject *object)
{
	adsl_cleanup (NM_DEVICE_ADSL (object));

	nm_clear_g_source (&NM_DEVICE_ADSL_GET_PRIVATE (object)->carrier_poll_id);

	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
}
Beispiel #11
0
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
                             NMIP4Config **out_config,
                             NMDeviceStateReason *reason)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	NMConnection *connection;
	NMSettingAdsl *s_adsl;
	NMActRequest *req;
	GError *err = NULL;
	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
	const char *iface = nm_device_get_iface (device);
	const char *ppp_iface;

	req = nm_device_get_act_request (device);
	g_assert (req);

	connection = nm_act_request_get_connection (req);
	g_assert (req);

	s_adsl = nm_connection_get_setting_adsl (connection);
	g_assert (s_adsl);

	/* PPPoE uses the NAS inteface, not the ATM interface */
	if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) {
		g_assert (priv->nas_ifname);
		ppp_iface = priv->nas_ifname;

		nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoE on NAS interface %s",
			        iface, priv->nas_ifname);
	} else {
		ppp_iface = iface;
		nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoA", iface);
	}

	priv->ppp_manager = nm_ppp_manager_new (ppp_iface);
	if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) {
		g_signal_connect (priv->ppp_manager, "state-changed",
		                  G_CALLBACK (ppp_state_changed),
		                  self);
		g_signal_connect (priv->ppp_manager, "ip4-config",
		                  G_CALLBACK (ppp_ip4_config),
		                  self);
		ret = NM_ACT_STAGE_RETURN_POSTPONE;
	} else {
		nm_log_warn (LOGD_ADSL, "(%s): PPP failed to start: %s", iface, err->message);
		g_error_free (err);

		g_object_unref (priv->ppp_manager);
		priv->ppp_manager = NULL;

		*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
	}

	return ret;
}
static void
constructed (GObject *object)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object);

	G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructed (object);

	priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_ADSL);
	register_properties (NM_DEVICE_ADSL (object));
}
Beispiel #13
0
static gboolean
br2684_create_iface (NMDeviceAdsl *self, NMSettingAdsl *s_adsl)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	struct atm_newif_br2684 ni;
	int err, fd, errsv;
	gboolean success = FALSE;
	guint num = 0;

	g_return_val_if_fail (s_adsl != NULL, FALSE);

	fd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
	if (fd < 0) {
		errsv = errno;
		_LOGE (LOGD_ADSL, "failed to open ATM control socket (%d)", errsv);
		return FALSE;
	}

	memset (&ni, 0, sizeof (ni));
	ni.backend_num = ATM_BACKEND_BR2684;
	ni.media = BR2684_MEDIA_ETHERNET;
	ni.mtu = 1500;

	/* Loop attempting to create an interface that doesn't exist yet.  The
	 * kernel can create one for us automatically, but due to API issues it
	 * cannot return that name to us.  Since we want to know the name right
	 * away, just brute-force it.
	 */
	while (num < 10000) {
		memset (&ni.ifname, 0, sizeof (ni.ifname));
		g_snprintf (ni.ifname, sizeof (ni.ifname), "nas%d", num);

		err = ioctl (fd, ATM_NEWBACKENDIF, &ni);
		if (err == 0) {
			set_nas_iface (self, -1, ni.ifname);
			_LOGI (LOGD_ADSL, "using NAS interface %s (%d)",
			       priv->nas_ifname, priv->nas_ifindex);
			success = TRUE;
			break;
		} else {
			errsv = errno;
			if (errsv == -EEXIST) {
				/* Try again */
				num++;
			} else {
				_LOGW (LOGD_ADSL, "failed to create br2684 interface (%d)", errsv);
				break;
			}
		}
	}

	close (fd);
	return success;
}
Beispiel #14
0
static NMActStageReturn
act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
	NMSettingAdsl *s_adsl;
	const char *protocol;

	g_assert (out_reason);

	s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device));
	g_assert (s_adsl);

	protocol = nm_setting_adsl_get_protocol (s_adsl);
	nm_log_dbg (LOGD_ADSL, "(%s): using ADSL protocol '%s'",
	             nm_device_get_iface (device), protocol);

	if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) {

		/* PPPoE needs RFC2684 bridging before we can do PPP over it */
		if (!br2684_create_iface (self, s_adsl)) {
			*out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED;
			goto done;
		}

		/* Set up the VCC */
		if (!br2684_assign_vcc (self, s_adsl)) {
			*out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED;
			goto done;
		}

		/* Watch for the 'nas' interface going away */
		priv->lost_link_id = g_signal_connect (nm_platform_get (), "link-removed",
		                                       G_CALLBACK (lost_link),
		                                       self);

		nm_log_dbg (LOGD_ADSL, "(%s): ATM setup successful", nm_device_get_iface (device));

		/* otherwise we're good for stage3 */
		nm_platform_link_set_up (priv->nas_ifindex);
		ret = NM_ACT_STAGE_RETURN_SUCCESS;

	} else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) {
		/* PPPoA doesn't need anything special */
		ret = NM_ACT_STAGE_RETURN_SUCCESS;
	} else {
		nm_log_warn (LOGD_ADSL, "(%s): unhandled ADSL protocol '%s'",
		             nm_device_get_iface (device), protocol);
	}

done:
	return ret;
}
static void
get_property (GObject *object, guint prop_id,
              GValue *value, GParamSpec *pspec)
{
	switch (prop_id) {
	case PROP_ATM_INDEX:
		g_value_set_int (value, NM_DEVICE_ADSL_GET_PRIVATE (object)->atm_index);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
register_properties (NMDeviceAdsl *device)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device);
	const NMPropertiesInfo property_info[] = {
		{ NM_DEVICE_ADSL_CARRIER,              &priv->carrier },
		{ NULL },
	};

	_nm_object_register_properties (NM_OBJECT (device),
	                                priv->proxy,
	                                property_info);
}
Beispiel #17
0
static void
set_nas_iface (NMDeviceAdsl *self, int idx, const char *name)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	g_return_if_fail (name != NULL);

	g_warn_if_fail (priv->nas_ifindex <= 0);
	priv->nas_ifindex = idx > 0 ? idx : nm_platform_link_get_ifindex (NM_PLATFORM_GET, name);
	g_warn_if_fail (priv->nas_ifindex > 0);

	g_warn_if_fail (priv->nas_ifname == NULL);
	priv->nas_ifname = g_strdup (name);
}
static void
constructed (GObject *object)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (object);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructed (object);

	priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, self);

	_LOGD (LOGD_ADSL, "ATM device index %d", priv->atm_index);

	g_return_if_fail (priv->atm_index >= 0);
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
                             NMIP4Config **out_config,
                             NMDeviceStateReason *reason)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (device);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	NMSettingAdsl *s_adsl;
	NMActRequest *req;
	GError *err = NULL;
	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
	const char *ppp_iface;

	req = nm_device_get_act_request (device);
	g_assert (req);
	s_adsl = (NMSettingAdsl *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_ADSL);
	g_assert (s_adsl);

	/* PPPoE uses the NAS interface, not the ATM interface */
	if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) {
		g_assert (priv->nas_ifname);
		ppp_iface = priv->nas_ifname;

		_LOGD (LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
	} else {
		ppp_iface = nm_device_get_iface (device);
		_LOGD (LOGD_ADSL, "starting PPPoA");
	}

	priv->ppp_manager = nm_ppp_manager_new (ppp_iface);
	if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) {
		g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
		                  G_CALLBACK (ppp_state_changed),
		                  self);
		g_signal_connect (priv->ppp_manager, "ip4-config",
		                  G_CALLBACK (ppp_ip4_config),
		                  self);
		ret = NM_ACT_STAGE_RETURN_POSTPONE;
	} else {
		_LOGW (LOGD_ADSL, "PPP failed to start: %s", err->message);
		g_error_free (err);

		nm_exported_object_clear_and_unexport (&priv->ppp_manager);

		*reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
	}

	return ret;
}
static void
dispose (GObject *object)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object);

	if (priv->disposed) {
		G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
		return;
	}

	priv->disposed = TRUE;

	g_object_unref (priv->proxy);

	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
}
Beispiel #21
0
static void
set_nas_iface (NMDeviceAdsl *self, int idx, const char *name)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);

	g_return_if_fail (name != NULL);

	g_warn_if_fail (priv->nas_ifindex <= 0);
	priv->nas_ifindex = idx > 0 ? idx : nm_platform_link_get_ifindex (name);
	g_warn_if_fail (priv->nas_ifindex > 0);

	g_warn_if_fail (priv->nas_ifname == NULL);
	priv->nas_ifname = g_strdup (name);

	/* Update NAS interface's MAC address */
	nm_device_update_hw_address (NM_DEVICE (self));
}
Beispiel #22
0
static void
lost_link (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMDeviceAdsl *device_adsl)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device_adsl);
	NMDevice *device = NM_DEVICE (device_adsl);

	/* This only gets called for PPPoE connections and "nas" interfaces */

	if (priv->nas_ifindex >= 0 && ifindex == priv->nas_ifindex) {
			/* NAS device went away for some reason; kill the connection */
			nm_log_dbg (LOGD_ADSL, "(%s): NAS interface disappeared",
			            nm_device_get_iface (device));
			nm_device_state_changed (device,
			                         NM_DEVICE_STATE_FAILED,
			                         NM_DEVICE_STATE_REASON_BR2684_FAILED);
	}
}
Beispiel #23
0
static void
link_changed_cb (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, NMPlatformReason reason, NMDeviceAdsl *self)
{
	if (change_type == NM_PLATFORM_SIGNAL_REMOVED) {
		NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
		NMDevice *device = NM_DEVICE (self);

		/* This only gets called for PPPoE connections and "nas" interfaces */

		if (priv->nas_ifindex >= 0 && ifindex == priv->nas_ifindex) {
				/* NAS device went away for some reason; kill the connection */
				_LOGD (LOGD_ADSL, "NAS interface disappeared");
				nm_device_state_changed (device,
				                         NM_DEVICE_STATE_FAILED,
				                         NM_DEVICE_STATE_REASON_BR2684_FAILED);
		}
	}
}
static gboolean
nas_update_cb (gpointer user_data)
{
	NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data);
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	NMDevice *device = NM_DEVICE (self);

	g_assert (priv->nas_ifname);

	priv->nas_update_count++;

	if (priv->nas_update_count > 10) {
		priv->nas_update_id = 0;
		_LOGW (LOGD_ADSL, "failed to find br2684 interface %s ifindex after timeout", priv->nas_ifname);
		nm_device_state_changed (device,
		                         NM_DEVICE_STATE_FAILED,
		                         NM_DEVICE_STATE_REASON_BR2684_FAILED);
		return G_SOURCE_REMOVE;
	}

	g_warn_if_fail (priv->nas_ifindex < 0);
	priv->nas_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->nas_ifname);
	if (priv->nas_ifindex < 0) {
		/* Keep waiting for it to appear */
		return G_SOURCE_CONTINUE;
	}

	priv->nas_update_id = 0;
	_LOGD (LOGD_ADSL, "using br2684 iface '%s' index %d", priv->nas_ifname, priv->nas_ifindex);

	if (pppoe_vcc_config (self)) {
		nm_device_activate_schedule_stage3_ip_config_start (device);
	} else {
		nm_device_state_changed (device,
		                         NM_DEVICE_STATE_FAILED,
		                         NM_DEVICE_STATE_REASON_BR2684_FAILED);
	}

	return G_SOURCE_REMOVE;
}
static NMActStageReturn
br2684_create_iface (NMDeviceAdsl *self,
                     NMSettingAdsl *s_adsl,
                     NMDeviceStateReason *out_reason)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	struct atm_newif_br2684 ni;
	int err, fd, errsv;
	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
	guint num = 0;

	g_return_val_if_fail (s_adsl != NULL, FALSE);

	if (priv->nas_update_id) {
		g_warn_if_fail (priv->nas_update_id == 0);
		nm_clear_g_source (&priv->nas_update_id);
	}

	fd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
	if (fd < 0) {
		errsv = errno;
		_LOGE (LOGD_ADSL, "failed to open ATM control socket (%d)", errsv);
		*out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED;
		return NM_ACT_STAGE_RETURN_FAILURE;
	}

	memset (&ni, 0, sizeof (ni));
	ni.backend_num = ATM_BACKEND_BR2684;
	ni.media = BR2684_MEDIA_ETHERNET;
	ni.mtu = 1500;

	/* Loop attempting to create an interface that doesn't exist yet.  The
	 * kernel can create one for us automatically, but due to API issues it
	 * cannot return that name to us.  Since we want to know the name right
	 * away, just brute-force it.
	 */
	while (num < 10000) {
		memset (&ni.ifname, 0, sizeof (ni.ifname));
		g_snprintf (ni.ifname, sizeof (ni.ifname), "nas%d", num++);

		err = ioctl (fd, ATM_NEWBACKENDIF, &ni);
		if (err == 0) {
			g_free (priv->nas_ifname);
			priv->nas_ifname = g_strdup (ni.ifname);
			_LOGD (LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname);

			priv->nas_update_count = 0;
			priv->nas_update_id = g_timeout_add (100, nas_update_cb, self);
			ret = NM_ACT_STAGE_RETURN_POSTPONE;
			break;
		} else if (errno != EEXIST) {
			errsv = errno;
			_LOGW (LOGD_ADSL, "failed to create br2684 interface (%d)", errsv);
			*out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED;
			break;
		}
	}

	close (fd);
	return ret;
}
Beispiel #26
0
static gboolean
br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl)
{
	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
	const char *iface = nm_device_get_iface (NM_DEVICE (self));
	struct sockaddr_atmpvc addr;
	struct atm_backend_br2684 be;
	struct atm_qos qos;
	int err, bufsize = 8192;
	const char *encapsulation;
	gboolean is_llc;

	g_return_val_if_fail (priv->brfd == -1, FALSE);
	g_return_val_if_fail (priv->nas_ifname != NULL, FALSE);

	priv->brfd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
	if (priv->brfd < 0) {
		nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)",
		            iface, errno);
		return FALSE;
	}

	err = setsockopt (priv->brfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof (bufsize));
	if (err != 0) {
		nm_log_err (LOGD_ADSL, "(%s): failed to set SNDBUF option (%d)",
		            iface, errno);
		goto error;
	}

	/* QoS */
	memset (&qos, 0, sizeof (qos));
	qos.aal = ATM_AAL5;
	qos.txtp.traffic_class = ATM_UBR;
	qos.txtp.max_sdu = 1524;
	qos.txtp.pcr = ATM_MAX_PCR;
	qos.rxtp = qos.txtp;

	err = setsockopt (priv->brfd, SOL_ATM, SO_ATMQOS, &qos, sizeof (qos));
	if (err != 0) {
		nm_log_err (LOGD_ADSL, "(%s): failed to set QoS (%d)",
		            iface, errno);
		goto error;
	}

	encapsulation = nm_setting_adsl_get_encapsulation (s_adsl);

	/* VPI/VCI */
	memset (&addr, 0, sizeof (addr));
	addr.sap_family = AF_ATMPVC;
	addr.sap_addr.itf = priv->atm_index;
	addr.sap_addr.vpi = (guint16) nm_setting_adsl_get_vpi (s_adsl);
	addr.sap_addr.vci = (int) nm_setting_adsl_get_vci (s_adsl);

	nm_log_dbg (LOGD_ADSL, "(%s): assigning address %d.%d.%d encapsulation %s",
	            nm_device_get_iface (NM_DEVICE (self)),
	            priv->atm_index, addr.sap_addr.vpi, addr.sap_addr.vci,
	            encapsulation);

	err = connect (priv->brfd, (struct sockaddr*) &addr, sizeof (addr));
	if (err != 0) {
		nm_log_err (LOGD_ADSL, "(%s): failed to set VPI/VCI (%d)",
		            iface, errno);
		goto error;
	}

	/* And last attach the VCC to the interface */
	is_llc = (g_strcmp0 (encapsulation, "llc") == 0);

	memset (&be, 0, sizeof (be));
	be.backend_num = ATM_BACKEND_BR2684;
	be.ifspec.method = BR2684_FIND_BYIFNAME;
	strcpy (be.ifspec.spec.ifname, priv->nas_ifname);
	be.fcs_in = BR2684_FCSIN_NO;
	be.fcs_out = BR2684_FCSOUT_NO;
	be.encaps = is_llc ? BR2684_ENCAPS_LLC : BR2684_ENCAPS_VC;
	err = ioctl (priv->brfd, ATM_SETBACKEND, &be);
	if (err != 0) {
		nm_log_err (LOGD_ADSL, "(%s): failed to attach VCC (%d)",
		            iface, errno);
		goto error;
	}

	return TRUE;

error:
	close (priv->brfd);
	priv->brfd = -1;
	return FALSE;
}