static void
get_property (GObject *object, guint prop_id,
			  GValue *value, GParamSpec *pspec)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	GPtrArray *array;
	GSList *iter;

	switch (prop_id) {
	case PROP_NSPS:
		array = g_ptr_array_sized_new (4);
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter))
			g_ptr_array_add (array, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data))));
		g_value_take_boxed (value, array);
		break;
	case PROP_ACTIVE_NSP:
		if (priv->current_nsp)
			g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp));
		else
			g_value_set_boxed (value, "/");
		break;
	case PROP_CENTER_FREQ:
		g_value_set_uint (value, priv->center_freq);
		break;
	case PROP_RSSI:
		g_value_set_int (value, priv->rssi);
		break;
	case PROP_CINR:
		g_value_set_int (value, priv->cinr);
		break;
	case PROP_TX_POWER:
		g_value_set_int (value, priv->tx_power);
		break;
	case PROP_BSID:
		g_value_set_string (value, priv->bsid);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
wmx_media_status_cb (struct wmxsdk *wmxsdk,
                     WIMAX_API_MEDIA_STATUS new_status,
                     void *user_data)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMDeviceState state;
	const char *iface;

	iface = nm_device_get_iface (NM_DEVICE (self));
	state = nm_device_get_state (NM_DEVICE (self));

	nm_log_dbg (LOGD_WIMAX, "(%s): media status change to %s",
	            iface, iwmx_sdk_media_status_to_str (new_status));

	/* We only care about media events while activated */
	if (state != NM_DEVICE_STATE_ACTIVATED)
		return;

	clear_link_timeout (self);

	switch (new_status) {
	case WIMAX_API_MEDIA_STATUS_LINK_UP:
		break;
	case WIMAX_API_MEDIA_STATUS_LINK_DOWN:
		nm_log_dbg (LOGD_WIMAX, "(%s): starting link timeout", iface);
		priv->link_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, self);
		break;
	case WIMAX_API_MEDIA_STATUS_LINK_RENEW:
		nm_log_dbg (LOGD_WIMAX, "(%s): renewing DHCP lease", iface);
		if (!nm_device_dhcp4_renew (NM_DEVICE (self), TRUE)) {
			nm_device_state_changed (NM_DEVICE (self),
			                         NM_DEVICE_STATE_FAILED,
			                         NM_DEVICE_STATE_REASON_DHCP_FAILED);
		}
		break;
	default:
		nm_log_err (LOGD_WIMAX, "(%s): unhandled media status %d", iface, new_status);
		break;
	}
}
static void
dispose (GObject *object)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);

	if (priv->hw_address) {
		g_free (priv->hw_address);
		priv->hw_address = NULL;
	}

	if (priv->bsid) {
		g_free (priv->bsid);
		priv->bsid = NULL;
	}

	if (priv->nsps)
		clean_up_nsps (NM_DEVICE_WIMAX (object));

	G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
}
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);

	_nm_object_ensure_inited (NM_OBJECT (object));

	switch (prop_id) {
	case PROP_HW_ADDRESS:
		g_value_set_string (value, nm_device_wimax_get_hw_address (self));
		break;
	case PROP_ACTIVE_NSP:
		g_value_set_object (value, nm_device_wimax_get_active_nsp (self));
		break;
	case PROP_CENTER_FREQ:
		g_value_set_uint (value, nm_device_wimax_get_center_frequency (self));
		break;
	case PROP_RSSI:
		g_value_set_int (value, nm_device_wimax_get_rssi (self));
		break;
	case PROP_CINR:
		g_value_set_int (value, nm_device_wimax_get_cinr (self));
		break;
	case PROP_TX_POWER:
		g_value_set_int (value, nm_device_wimax_get_tx_power (self));
		break;
	case PROP_BSID:
		g_value_set_string (value, nm_device_wimax_get_bsid (self));
		break;
	case PROP_NSPS:
		g_value_set_boxed (value, nm_device_wimax_get_nsps (self));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static gboolean
check_connection_available (NMDevice *device,
                            NMConnection *connection,
                            const char *specific_object)
{
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
	const GSList *ns_iter = NULL;
	NMWimaxNsp *nsp;

	if (specific_object) {
		nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object);
		return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE;
	}

	/* Ensure the connection applies to an NSP in the scan list */
	for (ns_iter = priv->nsp_list; ns_iter; ns_iter = ns_iter->next) {
		if (nm_wimax_nsp_check_compatible (NM_WIMAX_NSP (ns_iter->data), connection))
			return TRUE;
	}

	return FALSE;
}
static void
get_property (GObject *object, guint prop_id,
			  GValue *value, GParamSpec *pspec)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	struct ether_addr hw_addr;

	switch (prop_id) {
	case PROP_HW_ADDRESS:
		nm_device_wimax_get_hw_address (self, &hw_addr);
		g_value_take_string (value, nm_ether_ntop (&hw_addr));
		break;
	case PROP_ACTIVE_NSP:
		if (priv->current_nsp)
			g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp));
		else
			g_value_set_boxed (value, "/");
		break;
	case PROP_CENTER_FREQ:
		g_value_set_uint (value, priv->center_freq);
		break;
	case PROP_RSSI:
		g_value_set_int (value, priv->rssi);
		break;
	case PROP_CINR:
		g_value_set_int (value, priv->cinr);
		break;
	case PROP_TX_POWER:
		g_value_set_int (value, priv->tx_power);
		break;
	case PROP_BSID:
		g_value_set_string (value, priv->bsid);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	/* If we now have the SDK, schedule an idle handler to start the device up */
	if (!priv->sdk) {
		priv->sdk = wmxsdk_ref (sdk);
		iwmx_sdk_set_callbacks(priv->sdk,
		                       wmx_state_change_cb,
		                       wmx_media_status_cb,
		                       wmx_connect_result_cb,
		                       wmx_scan_result_cb,
		                       wmx_removed_cb,
		                       self);
		iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0);

		if (!priv->sdk_action_defer_id)
			priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self);
	}
}
static void
device_state_changed (NMDevice *device,
                      NMDeviceState new_state,
                      NMDeviceState old_state,
                      NMDeviceStateReason reason)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (device);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	/* Reset our stage1 (Prepare) done marker since it's only valid while in stage1 */
	priv->prepare_done = FALSE;

	if (new_state < NM_DEVICE_STATE_DISCONNECTED)
		remove_all_nsps (self);

	/* Request initial NSP list when device is first started */
	if (   new_state == NM_DEVICE_STATE_DISCONNECTED
	    && old_state < NM_DEVICE_STATE_DISCONNECTED) {
		if (priv->sdk)
			iwmx_sdk_get_networks (priv->sdk);
	}

	if (new_state == NM_DEVICE_STATE_FAILED || new_state <= NM_DEVICE_STATE_DISCONNECTED) {
		set_current_nsp (self, NULL);
		clear_activation_timeout (self);
	}

	if (new_state == NM_DEVICE_STATE_ACTIVATED) {
		/* poll link quality and BSID */
		clear_connected_poll (self);
		priv->poll_id = g_timeout_add_seconds (10, connected_poll_cb, self);
		connected_poll_cb (self);
	} else {
		clear_link_timeout (self);
		clear_connected_poll (self);
		set_link_status (self, NULL);
	}
}
static void
wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	if (!priv->sdk) {
		nm_log_dbg (LOGD_WIMAX, "(%s): removed unhandled WiMAX interface", wmxsdk->ifname);
		return;
	}

	nm_log_dbg (LOGD_WIMAX, "(%s): removed WiMAX interface", wmxsdk->ifname);

	/* Clear callbacks just in case we don't hold the last reference */
	iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL);
	wmxsdk_unref (priv->sdk);
	priv->sdk = NULL;

	priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized;
	nm_device_state_changed (NM_DEVICE (self),
							 NM_DEVICE_STATE_UNAVAILABLE,
							 NM_DEVICE_STATE_REASON_NONE);
}
static void
dispose (GObject *object)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);

	if (priv->disposed)
		goto done;

	priv->disposed = TRUE;

	clear_activation_timeout (self);
	clear_link_timeout (self);
	clear_connected_poll (self);

	if (priv->sdk_action_defer_id)
		g_source_remove (priv->sdk_action_defer_id);

	if (priv->sdk) {
		iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL);
		wmxsdk_unref (priv->sdk);
	}

	g_free (priv->bsid);

	set_current_nsp (self, NULL);

	g_slist_foreach (priv->nsp_list, (GFunc) g_object_unref, NULL);
	g_slist_free (priv->nsp_list);

	iwmx_sdk_new_callback_unregister (wmx_new_sdk_cb, self);
	nm_wimax_util_sdk_unref ();

done:
	G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
}
Beispiel #11
0
/* return value must not be freed! */
static const gchar *
get_mac_address_of_device (NMDevice *device)
{
  const gchar *mac = NULL;
  switch (nm_device_get_device_type (device))
    {
    case NM_DEVICE_TYPE_WIFI:
      {
        NMDeviceWifi *device_wifi = NM_DEVICE_WIFI (device);
        mac = nm_device_wifi_get_hw_address (device_wifi);
        break;
      }
    case NM_DEVICE_TYPE_ETHERNET:
      {
        NMDeviceEthernet *device_ethernet = NM_DEVICE_ETHERNET (device);
        mac = nm_device_ethernet_get_hw_address (device_ethernet);
        break;
      }
    case NM_DEVICE_TYPE_WIMAX:
      {
        NMDeviceWimax *device_wimax = NM_DEVICE_WIMAX (device);
        mac = nm_device_wimax_get_hw_address (device_wimax);
        break;
      }
    case NM_DEVICE_TYPE_INFINIBAND:
      {
        NMDeviceInfiniband *device_infiniband = NM_DEVICE_INFINIBAND (device);
        mac = nm_device_infiniband_get_hw_address (device_infiniband);
        break;
      }
    default:
      break;
    }
  /* no MAC address found */
  return mac;
}
static const char *
get_hw_address (NMDevice *device)
{
	return nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device));
}
static void
wmx_state_change_cb (struct wmxsdk *wmxsdk,
                     WIMAX_API_DEVICE_STATUS new_status,
                     WIMAX_API_DEVICE_STATUS old_status,
                     WIMAX_API_STATUS_REASON reason,
                     WIMAX_API_CONNECTION_PROGRESS_INFO progress,
                     void *user_data)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMDeviceState state;
	const char *iface;
	gboolean old_available = FALSE;
	const char *nsp_name = NULL;

	iface = nm_device_get_iface (NM_DEVICE (self));
	nm_log_info (LOGD_WIMAX, "(%s): wimax state change %s -> %s (%s (%d))",
	             iface,
	             iwmx_sdk_dev_status_to_str (old_status),
	             iwmx_sdk_dev_status_to_str (new_status),
	             iwmx_sdk_con_progress_to_str (progress),
	             progress);

	if (new_status == old_status)
		return;

	state = nm_device_get_state (NM_DEVICE (self));
	old_available = nm_device_is_available (NM_DEVICE (self));

	priv->status = new_status;
	if (priv->current_nsp)
		nsp_name = nm_wimax_nsp_get_name (priv->current_nsp);

	switch (new_status) {
	case WIMAX_API_DEVICE_STATUS_UnInitialized:
	case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
	case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
	case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
		if (priv->wimaxd_enabled) {
			priv->wimaxd_enabled = FALSE;
			if (update_availability (self, old_available))
				return;
		}
		break;
	case WIMAX_API_DEVICE_STATUS_Connecting:
	case WIMAX_API_DEVICE_STATUS_Data_Connected:
		/* If for some reason we're initially connected, force a disconnect here */
		if (state < NM_DEVICE_STATE_DISCONNECTED)
			force_disconnect (self, wmxsdk);
		/* Fall through */
	case WIMAX_API_DEVICE_STATUS_Ready:
	case WIMAX_API_DEVICE_STATUS_Scanning:
		if (priv->wimaxd_enabled == FALSE) {
			priv->wimaxd_enabled = TRUE;
			if (update_availability (self, old_available))
				return;
		}
		break;
	default:
		nm_log_warn (LOGD_WIMAX, "(%s): unhandled WiMAX device state %d",
		             iface, new_status);
		break;
	}

	/* Handle activation success and failure */
	if (nm_device_is_activating (NM_DEVICE (self))) {
	    if (new_status == WIMAX_API_DEVICE_STATUS_Data_Connected) {
			/* Success */
			clear_activation_timeout (self);

			nm_log_info (LOGD_WIMAX, "(%s): connected to '%s'",
			             iface, nsp_name);
			nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self));
			return;
		}

		if (priv->connect_failed) {
			/* Connection attempt failed */
			nm_log_info (LOGD_WIMAX, "(%s): connection to '%s' failed: (%d) %s",
			             iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason));
			nm_device_state_changed (NM_DEVICE (self),
			                         NM_DEVICE_STATE_FAILED,
			                         NM_DEVICE_STATE_REASON_CONFIG_FAILED);
			return;
		}

		/* If stage2 was postponed because the device was scanning or something,
		 * then check if we need to move to stage2 now that the device might be
		 * ready.
		 */
		if (state == NM_DEVICE_STATE_PREPARE && priv->prepare_done) {
			if (   new_status == WIMAX_API_DEVICE_STATUS_Ready
			    || new_status == WIMAX_API_DEVICE_STATUS_Connecting) {
				nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self));
				return;
			}
		}
	}

	/* Handle disconnection */
	if (state == NM_DEVICE_STATE_ACTIVATED) {
		if (   old_status == WIMAX_API_DEVICE_STATUS_Data_Connected
			&& new_status < WIMAX_API_DEVICE_STATUS_Connecting) {

			nm_log_info (LOGD_WIMAX, "(%s): disconnected from '%s': (%d) %s",
				         iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason));

			nm_device_state_changed (NM_DEVICE (self),
				                     NM_DEVICE_STATE_FAILED,
				                     NM_DEVICE_STATE_REASON_CONFIG_FAILED);
		}
	}
}
static gboolean
complete_connection (NMDevice *device,
                     NMConnection *connection,
                     const char *specific_object,
                     const GSList *existing_connections,
                     GError **error)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (device);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMSettingWimax *s_wimax;
	const char *setting_mac;
	const char *hw_address;
	const char *nsp_name = NULL;
	NMWimaxNsp *nsp = NULL;
	GSList *iter;

	s_wimax = nm_connection_get_setting_wimax (connection);

	if (!specific_object) {
		/* If not given a specific object, we need at minimum an NSP name */
		if (!s_wimax) {
			g_set_error_literal (error,
			                     NM_DEVICE_ERROR,
			                     NM_DEVICE_ERROR_INVALID_CONNECTION,
			                     "A 'wimax' setting is required if no NSP path was given.");
			return FALSE;
		}

		nsp_name = nm_setting_wimax_get_network_name (s_wimax);
		if (!nsp_name || !strlen (nsp_name)) {
			g_set_error_literal (error,
			                     NM_DEVICE_ERROR,
			                     NM_DEVICE_ERROR_INVALID_CONNECTION,
			                     "A 'wimax' setting with a valid network name is required if no NSP path was given.");
			return FALSE;
		}

		/* Find a compatible NSP in the list */
		nsp = get_nsp_by_name (self, nsp_name);

		/* If we still don't have an NSP, then the WiMAX settings needs to be
		 * fully specified by the client.  Might not be able to find the NSP
		 * if the scan didn't find the NSP yet.
		 */
		if (!nsp) {
			if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error))
				return FALSE;
		}
	} else {
		/* Find a compatible NSP in the list */
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) {
			if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) {
				nsp = NM_WIMAX_NSP (iter->data);
				break;
			}
		}

		if (!nsp) {
			g_set_error (error,
			             NM_DEVICE_ERROR,
			             NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND,
			             "The NSP %s was not in the scan list.",
			             specific_object);
			return FALSE;
		}

		nsp_name = nm_wimax_nsp_get_name (nsp);
	}

	/* Add a WiMAX setting if one doesn't exist */
	if (!s_wimax) {
		s_wimax = (NMSettingWimax *) nm_setting_wimax_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_wimax));
	}

	g_assert (nsp_name);
	nm_utils_complete_generic (connection,
	                           NM_SETTING_WIMAX_SETTING_NAME,
	                           existing_connections,
	                           nsp_name,
	                           nsp_name,
	                           NULL,
	                           TRUE);
	g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL);

	setting_mac = nm_setting_wimax_get_mac_address (s_wimax);
	hw_address = nm_device_get_hw_address (device);
	if (setting_mac) {
		/* Make sure the setting MAC (if any) matches the device's permanent MAC */
		if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) {
			g_set_error_literal (error,
			                     NM_CONNECTION_ERROR,
			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
			                     _("connection does not match device"));
			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_MAC_ADDRESS);
			return FALSE;
		}
	} else {
		/* Lock the connection to this device by default */
		if (!nm_utils_hwaddr_matches (hw_address, -1, NULL, ETH_ALEN))
			g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, hw_address, NULL);
	}

	return TRUE;
}
Beispiel #15
0
static void
detail_device (gpointer data, gpointer user_data)
{
	NMDevice *device = NM_DEVICE (data);
	char *tmp;
	NMDeviceState state;
	guint32 caps;
	guint32 speed;
	const GArray *array;
	gboolean is_default = FALSE;
	const char *id = NULL;
	NMActiveConnection *active;

	active = nm_device_get_active_connection (device);
	if (active) {
		NMConnection *connection;
		NMSettingConnection *s_con;

		is_default = nm_active_connection_get_default (active);

		connection = get_connection_for_active (active);
		if (connection) {
			s_con = nm_connection_get_setting_connection (connection);
			if (s_con)
				id = nm_setting_connection_get_id (s_con);
		}
	}

	print_header ("Device", nm_device_get_iface (device), id);

	/* General information */
	if (NM_IS_DEVICE_ETHERNET (device))
		print_string ("Type", "Wired");
	else if (NM_IS_DEVICE_WIFI (device))
		print_string ("Type", "802.11 WiFi");
	else if (NM_IS_DEVICE_MODEM (device)) {
		NMDeviceModemCapabilities modem_caps;

		modem_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
		if (modem_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)
			print_string ("Type", "Mobile Broadband (GSM)");
		else if (modem_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)
			print_string ("Type", "Mobile Broadband (CDMA)");
		else
			print_string ("Type", "Mobile Broadband (unknown)");
	} else if (NM_IS_DEVICE_BT (device))
		print_string ("Type", "Bluetooth");
	else if (NM_IS_DEVICE_WIMAX (device))
		print_string ("Type", "WiMAX");

	print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)");

	state = nm_device_get_state (device);
	print_string ("State", get_dev_state_string (state));

	if (is_default)
		print_string ("Default", "yes");
	else
		print_string ("Default", "no");

	tmp = NULL;
	if (NM_IS_DEVICE_ETHERNET (device))
		tmp = g_strdup (nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)));
	else if (NM_IS_DEVICE_WIFI (device))
		tmp = g_strdup (nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device)));
	else if (NM_IS_DEVICE_WIMAX (device))
		tmp = g_strdup (nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)));

	if (tmp) {
		print_string ("HW Address", tmp);
		g_free (tmp);
	}

	/* Capabilities */
	caps = nm_device_get_capabilities (device);
	printf ("\n  Capabilities:\n");
	if (caps & NM_DEVICE_CAP_CARRIER_DETECT)
		print_string ("  Carrier Detect", "yes");

	speed = 0;
	if (NM_IS_DEVICE_ETHERNET (device)) {
		/* Speed in Mb/s */
		speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (device));
	} else if (NM_IS_DEVICE_WIFI (device)) {
		/* Speed in b/s */
		speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device));
		speed /= 1000;
	}

	if (speed) {
		char *speed_string;

		speed_string = g_strdup_printf ("%u Mb/s", speed);
		print_string ("  Speed", speed_string);
		g_free (speed_string);
	}

	/* Wireless specific information */
	if ((NM_IS_DEVICE_WIFI (device))) {
		guint32 wcaps;
		NMAccessPoint *active_ap = NULL;
		const char *active_bssid = NULL;
		const GPtrArray *aps;

		printf ("\n  Wireless Properties\n");

		wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device));

		if (wcaps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
			print_string ("  WEP Encryption", "yes");
		if (wcaps & NM_WIFI_DEVICE_CAP_WPA)
			print_string ("  WPA Encryption", "yes");
		if (wcaps & NM_WIFI_DEVICE_CAP_RSN)
			print_string ("  WPA2 Encryption", "yes");

		if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
			active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (device));
			active_bssid = active_ap ? nm_access_point_get_hw_address (active_ap) : NULL;
		}

		printf ("\n  Wireless Access Points %s\n", active_ap ? "(* = current AP)" : "");

		aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
		if (aps && aps->len)
			g_ptr_array_foreach ((GPtrArray *) aps, detail_access_point, (gpointer) active_bssid);
	} else if (NM_IS_DEVICE_ETHERNET (device)) {
		printf ("\n  Wired Properties\n");

		if (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device)))
			print_string ("  Carrier", "on");
		else
			print_string ("  Carrier", "off");
	} else if (NM_IS_DEVICE_WIMAX (device)) {
		NMDeviceWimax *wimax = NM_DEVICE_WIMAX (device);
		NMWimaxNsp *active_nsp = NULL;
		const char *active_name = NULL;
		const GPtrArray *nsps;

		if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
			guint tmp_uint;
			gint tmp_int;
			const char *tmp_str;

			active_nsp = nm_device_wimax_get_active_nsp (wimax);
			active_name = active_nsp ? nm_wimax_nsp_get_name (active_nsp) : NULL;

			printf ("\n  Link Status\n");

			tmp_uint = nm_device_wimax_get_center_frequency (wimax);
			if (tmp_uint)
				tmp = g_strdup_printf ("%'.1f MHz", (double) tmp_uint / 1000.0);
			else
				tmp = g_strdup ("(unknown)");
			print_string ("  Center Freq.", tmp);
			g_free (tmp);

			tmp_int = nm_device_wimax_get_rssi (wimax);
			if (tmp_int)
				tmp = g_strdup_printf ("%d dBm", tmp_int);
			else
				tmp = g_strdup ("(unknown)");
			print_string ("  RSSI", tmp);
			g_free (tmp);

			tmp_int = nm_device_wimax_get_cinr (wimax);
			if (tmp_int)
				tmp = g_strdup_printf ("%d dB", tmp_int);
			else
				tmp = g_strdup ("(unknown)");
			print_string ("  CINR", tmp);
			g_free (tmp);

			tmp_int = nm_device_wimax_get_tx_power (wimax);
			if (tmp_int)
				tmp = g_strdup_printf ("%'.2f dBm", (float) tmp_int / 2.0);
			else
				tmp = g_strdup ("(unknown)");
			print_string ("  TX Power", tmp);
			g_free (tmp);

			tmp_str = nm_device_wimax_get_bsid (wimax);
			if (tmp_str)
				print_string ("  BSID", tmp_str);
			else
				print_string ("  BSID", "(unknown)");
		}

		printf ("\n  WiMAX NSPs %s\n", active_nsp ? "(* current NSP)" : "");

		nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device));
		if (nsps && nsps->len)
			g_ptr_array_foreach ((GPtrArray *) nsps, detail_nsp, (gpointer) active_name);
	}

	/* IP Setup info */
	if (state == NM_DEVICE_STATE_ACTIVATED) {
		NMIP4Config *cfg4 = nm_device_get_ip4_config (device);
		NMIP6Config *cfg6 = nm_device_get_ip6_config (device);
		GSList *iter;

		if (cfg4) {
			printf ("\n  IPv4 Settings:\n");

			for (iter = (GSList *) nm_ip4_config_get_addresses (cfg4); iter; iter = g_slist_next (iter)) {
				NMIP4Address *addr = (NMIP4Address *) iter->data;
				guint32 prefix = nm_ip4_address_get_prefix (addr);
				char *tmp2;

				tmp = ip4_address_as_string (nm_ip4_address_get_address (addr));
				print_string ("  Address", tmp);
				g_free (tmp);

				tmp2 = ip4_address_as_string (nm_utils_ip4_prefix_to_netmask (prefix));
				tmp = g_strdup_printf ("%d (%s)", prefix, tmp2);
				g_free (tmp2);
				print_string ("  Prefix", tmp);
				g_free (tmp);

				tmp = ip4_address_as_string (nm_ip4_address_get_gateway (addr));
				print_string ("  Gateway", tmp);
				g_free (tmp);
				printf ("\n");
			}

			array = nm_ip4_config_get_nameservers (cfg4);
			if (array) {
				int i;

				for (i = 0; i < array->len; i++) {
					tmp = ip4_address_as_string (g_array_index (array, guint32, i));
					print_string ("  DNS", tmp);
					g_free (tmp);
				}
			}
		}

		if (cfg6) {
			printf ("\n  IPv6 Settings:\n");

			for (iter = (GSList *) nm_ip6_config_get_addresses (cfg6); iter; iter = g_slist_next (iter)) {
				NMIP6Address *addr = (NMIP6Address *) iter->data;
				guint32 prefix = nm_ip6_address_get_prefix (addr);

				tmp = ip6_address_as_string (nm_ip6_address_get_address (addr));
				print_string ("  Address", tmp);
				g_free (tmp);

				tmp = g_strdup_printf ("%d", prefix);
				print_string ("  Prefix", tmp);
				g_free (tmp);

				tmp = ip6_address_as_string (nm_ip6_address_get_gateway (addr));
				print_string ("  Gateway", tmp);
				g_free (tmp);
				printf ("\n");
			}

			for (iter = (GSList *) nm_ip6_config_get_nameservers (cfg6); iter; iter = g_slist_next (iter)) {
				tmp = ip6_address_as_string (iter->data);
				print_string ("  DNS", tmp);
				g_free (tmp);
			}
		}
	}

	printf ("\n\n");
}
static gboolean
real_complete_connection (NMDevice *device,
                          NMConnection *connection,
                          const char *specific_object,
                          const GSList *existing_connections,
                          GError **error)
{
	NMDeviceWimax *self = NM_DEVICE_WIMAX (device);
	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
	NMSettingWimax *s_wimax;
	const GByteArray *setting_mac;
	char *format;
	const char *nsp_name = NULL;
	NMWimaxNsp *nsp = NULL;
	GSList *iter;

	s_wimax = nm_connection_get_setting_wimax (connection);

	if (!specific_object) {
		/* If not given a specific object, we need at minimum an NSP name */
		if (!s_wimax) {
			g_set_error_literal (error,
			                     NM_WIMAX_ERROR,
			                     NM_WIMAX_ERROR_CONNECTION_INVALID,
			                     "A 'wimax' setting is required if no NSP path was given.");
			return FALSE;
		}

		nsp_name = nm_setting_wimax_get_network_name (s_wimax);
		if (!nsp_name || !strlen (nsp_name)) {
			g_set_error_literal (error,
			                     NM_WIMAX_ERROR,
			                     NM_WIMAX_ERROR_CONNECTION_INVALID,
			                     "A 'wimax' setting with a valid network name is required if no NSP path was given.");
			return FALSE;
		}

		/* Find a compatible NSP in the list */
		nsp = get_nsp_by_name (self, nsp_name);

		/* If we still don't have an NSP, then the WiMAX settings needs to be
		 * fully specified by the client.  Might not be able to find the NSP
		 * if the scan didn't find the NSP yet.
		 */
		if (!nsp) {
			if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error))
				return FALSE;
		}
	} else {
		/* Find a compatible NSP in the list */
		for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) {
			if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) {
				nsp = NM_WIMAX_NSP (iter->data);
				break;
			}
		}

		if (!nsp) {
			g_set_error (error,
			             NM_WIMAX_ERROR,
			             NM_WIMAX_ERROR_NSP_NOT_FOUND,
			             "The NSP %s was not in the scan list.",
			             specific_object);
			return FALSE;
		}

		nsp_name = nm_wimax_nsp_get_name (nsp);
	}

	/* Add a WiMAX setting if one doesn't exist */
	if (!s_wimax) {
		s_wimax = (NMSettingWimax *) nm_setting_wimax_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_wimax));
	}

	g_assert (nsp_name);
	format = g_strdup_printf ("%s %%d", nsp_name);
	nm_utils_complete_generic (connection,
	                           NM_SETTING_WIMAX_SETTING_NAME,
	                           existing_connections,
	                           format,
	                           nsp_name,
	                           TRUE);
	g_free (format);
	g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL);

	setting_mac = nm_setting_wimax_get_mac_address (s_wimax);
	if (setting_mac) {
		/* Make sure the setting MAC (if any) matches the device's permanent MAC */
		if (memcmp (setting_mac->data, &priv->hw_addr.ether_addr_octet, ETH_ALEN)) {
			g_set_error (error,
				         NM_SETTING_WIMAX_ERROR,
				         NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
				         NM_SETTING_WIMAX_MAC_ADDRESS);
			return FALSE;
		}
	} else {
		GByteArray *mac;
		const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };

		/* Lock the connection to this device by default */
		if (memcmp (&priv->hw_addr.ether_addr_octet, null_mac, ETH_ALEN)) {
			mac = g_byte_array_sized_new (ETH_ALEN);
			g_byte_array_append (mac, priv->hw_addr.ether_addr_octet, ETH_ALEN);
			g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, mac, NULL);
			g_byte_array_free (mac, TRUE);
		}
	}

	return TRUE;
}
static void
wimax_add_menu_item (NMDevice *device,
                     guint32 n_devices,
                     NMConnection *active,
                     GtkWidget *menu,
                     NMApplet *applet)
{
	NMDeviceWimax *wimax = NM_DEVICE_WIMAX (device);
	char *text;
	GtkWidget *item;
	GSList *connections, *all, *iter, *sorted = NULL;
	const GPtrArray *nsps;
	NMWimaxNsp *active_nsp = NULL;
	gboolean wimax_enabled, wimax_hw_enabled;
	int i;

	nsps = nm_device_wimax_get_nsps (wimax);

	if (n_devices > 1) {
		const char *desc;

		desc = nma_utils_get_device_description (device);
		text = g_strdup_printf (_("WiMAX Mobile Broadband (%s)"), desc);
	} else {
		text = g_strdup (_("WiMAX Mobile Broadband"));
	}

	item = applet_menu_item_create_device_item_helper (device, applet, text);
	gtk_widget_set_sensitive (item, FALSE);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);
	g_free (text);

	/* Add the active NSP if we're connected to something and the device is available */
	if (!nma_menu_device_check_unusable (device)) {
		active_nsp = nm_device_wimax_get_active_nsp (wimax);
		if (active_nsp) {
			item = new_nsp_menu_item (wimax, active, TRUE, active_nsp, applet);
			if (item) {
				gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
				gtk_widget_show (item);
			}
		}
	}

	/* Notify user of unmanaged or unavailable device */
	wimax_enabled = nm_client_wimax_get_enabled (applet->nm_client);
	wimax_hw_enabled = nm_client_wimax_hardware_get_enabled (applet->nm_client);
	item = nma_menu_device_get_menu_item (device, applet,
	                                      wimax_hw_enabled ?
	                                          (wimax_enabled ? NULL : _("WiMAX is disabled")) :
	                                          _("WiMAX is disabled by hardware switch"));
	if (item) {
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
		gtk_widget_show (item);
	}

	/* If disabled or rfkilled or whatever, nothing left to do */
	if (nma_menu_device_check_unusable (device))
		return;

	/* Create a sorted list of NSPs */
	for (i = 0; nsps && (i < nsps->len); i++) {
		NMWimaxNsp *nsp = g_ptr_array_index (nsps, i);

		if (nsp != active_nsp)
			sorted = g_slist_insert_sorted (sorted, nsp, sort_nsps);
	}

	if (g_slist_length (sorted)) {
		applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);

		all = applet_get_all_connections (applet);
		connections = nm_device_filter_connections (device, all);
		g_slist_free (all);

		/* And add menu items for each NSP */
		for (iter = sorted; iter; iter = g_slist_next (iter)) {
			NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
			NMConnection *connection = NULL;

			connection = get_connection_for_nsp (connections, nsp);
			item = new_nsp_menu_item (wimax, connection, FALSE, nsp, applet);
			if (item) {
				gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
				gtk_widget_show (item);
			}
		}

		g_slist_free (connections);
	}

	g_slist_free (sorted);
}