static gint sort_nsps (gconstpointer a, gconstpointer b) { const char *name_a = NULL, *name_b = NULL; if (a) name_a = nm_wimax_nsp_get_name (NM_WIMAX_NSP (a)); if (b) name_b = nm_wimax_nsp_get_name (NM_WIMAX_NSP (b)); return g_strcmp0 (name_a, name_b); }
static NMActStageReturn real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); NMActRequest *req; GSList *iter; const char *path; clear_link_timeout (NM_DEVICE_WIMAX (device)); req = nm_device_get_act_request (device); if (!req) goto err; path = nm_act_request_get_specific_object (req); if (!path) goto err; for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); if (!strcmp (path, nm_wimax_nsp_get_dbus_path (nsp))) { set_current_nsp (NM_DEVICE_WIMAX (device), nsp); return NM_ACT_STAGE_RETURN_SUCCESS; } } err: *reason = NM_DEVICE_STATE_REASON_NONE; return NM_ACT_STAGE_RETURN_FAILURE; }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMWimaxNsp *nsp = NM_WIMAX_NSP (object); _nm_object_ensure_inited (NM_OBJECT (object)); switch (prop_id) { case PROP_NAME: g_value_set_string (value, nm_wimax_nsp_get_name (nsp)); break; case PROP_SIGNAL_QUALITY: g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (nsp)); break; case PROP_NETWORK_TYPE: g_value_set_uint (value, nm_wimax_nsp_get_network_type (nsp)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void clean_up_nsps (NMDeviceWimax *self, gboolean notify) { NMDeviceWimaxPrivate *priv; g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); if (priv->active_nsp) { g_object_unref (priv->active_nsp); priv->active_nsp = NULL; } if (priv->nsps) { while (priv->nsps->len) { NMWimaxNsp *nsp = NM_WIMAX_NSP (g_ptr_array_index (priv->nsps, 0)); if (notify) g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); g_ptr_array_remove (priv->nsps, nsp); g_object_unref (nsp); } g_ptr_array_free (priv->nsps, TRUE); priv->nsps = NULL; } }
NMWimaxNsp * nm_wimax_nsp_new (const char *name) { g_return_val_if_fail (name != NULL, NULL); return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP, NM_WIMAX_NSP_NAME, name, NULL)); }
static void constructed (GObject *object) { NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructed (object); priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_WIMAX_NSP); register_properties (NM_WIMAX_NSP (object)); }
static gboolean impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); GSList *iter; *nsps = g_ptr_array_sized_new (4); for (iter = priv->nsp_list; iter; iter = iter->next) g_ptr_array_add (*nsps, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))); return TRUE; }
static void remove_outdated_nsps (NMDeviceWimax *self, WIMAX_API_NSP_INFO_EX *nsp_list, guint32 list_size) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); GSList *iter; GSList *to_remove = NULL; for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); gboolean found = FALSE; int i; for (i = 0; i < list_size; i++) { WIMAX_API_NSP_INFO_EX *info = &nsp_list[i]; if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) { found = TRUE; break; } } if (!found) to_remove = g_slist_prepend (to_remove, nsp); } for (iter = to_remove; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); g_object_unref (nsp); } if (g_slist_length(to_remove) > 0) nm_device_recheck_available_connections (NM_DEVICE (self)); g_slist_free (to_remove); }
static NMWimaxNsp * get_nsp_by_name (NMDeviceWimax *self, const char *name) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); GSList *iter; for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name)) return nsp; } return NULL; }
static void remove_all_nsps (NMDeviceWimax *self) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); while (g_slist_length (priv->nsp_list)) { NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data); priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); g_object_unref (nsp); } g_slist_free (priv->nsp_list); priv->nsp_list = NULL; }
static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); NMActRequest *req; GSList *iter; const char *path; NMWimaxNsp *nsp = NULL; clear_link_timeout (NM_DEVICE_WIMAX (device)); *reason = NM_DEVICE_STATE_REASON_NONE; req = nm_device_get_act_request (device); if (!req) return NM_ACT_STAGE_RETURN_FAILURE; path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); if (!path) return NM_ACT_STAGE_RETURN_FAILURE; /* Find the NSP in the scan list */ for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *candidate = NM_WIMAX_NSP (iter->data); if (!strcmp (path, nm_wimax_nsp_get_dbus_path (candidate))) { nsp = candidate; break; } } /* Couldn't find the NSP for some reason */ if (nsp == NULL) return NM_ACT_STAGE_RETURN_FAILURE; set_current_nsp (NM_DEVICE_WIMAX (device), nsp); priv->prepare_done = TRUE; /* If the device is scanning, it won't connect, so we have to wait until * it's not scanning to proceed to stage 2. */ if (priv->status == WIMAX_API_DEVICE_STATUS_Scanning) return NM_ACT_STAGE_RETURN_POSTPONE; return NM_ACT_STAGE_RETURN_SUCCESS; }
static NMWimaxNsp * get_nsp_by_path (NMDeviceWimax *self, const char *path) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); GSList *iter; g_return_val_if_fail (path, NULL); for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); if (!strcmp (nm_wimax_nsp_get_dbus_path (nsp), path)) return nsp; } return NULL; }
static void remove_all_nsps (NMDeviceWimax *self) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); set_current_nsp (self, NULL); while (priv->nsp_list) { NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data); priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); g_object_unref (nsp); } nm_device_recheck_available_connections (NM_DEVICE (self)); }
static NMConnection * real_get_best_auto_connection (NMDevice *device, GSList *connections, char **specific_object) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); GSList *iter; for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *connection = NM_CONNECTION (iter->data); NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *connection_type; const GByteArray *mac; s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); g_assert (s_con); if (!nm_setting_connection_get_autoconnect (s_con)) continue; connection_type = nm_setting_connection_get_connection_type (s_con); if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) continue; s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); if (!s_wimax) continue; mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN)) continue; for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); if (nm_wimax_nsp_check_compatible (nsp, connection)) { *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp); return connection; } } } return NULL; }
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 gboolean can_auto_connect (NMDevice *device, NMConnection *connection, char **specific_object) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); GSList *iter; if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->can_auto_connect (device, connection, specific_object)) return FALSE; for (iter = priv->nsp_list; iter; iter = iter->next) { NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); if (nm_wimax_nsp_check_compatible (nsp, connection)) { *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp); return TRUE; } } return FALSE; }
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 detail_nsp (gpointer data, gpointer user_data) { NMWimaxNsp *nsp = NM_WIMAX_NSP (data); const char *active_name = (const char *) user_data; const char *name; char *label; char *data_str; gboolean active = FALSE; name = nm_wimax_nsp_get_name (nsp); if (active_name) active = g_strcmp0 (active_name, name) == 0; label = g_strdup_printf (" %s%s", active ? "*" : "", name); data_str = g_strdup_printf ("%d%% (%s)", nm_wimax_nsp_get_signal_quality (nsp), wimax_network_type_to_str (nm_wimax_nsp_get_network_type (nsp))); print_string (label, data_str); g_free (label); g_free (data_str); }
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 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; }
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); }