/** * nm_wimax_nsp_connection_valid: * @nsp: an #NMWimaxNsp to validate @connection against * @connection: an #NMConnection to validate against @nsp * * Validates a given connection against a given WiMAX NSP to ensure that the * connection may be activated with that NSP. The connection must match the * @nsp's network name and other attributes. * * Returns: %TRUE if the connection may be activated with this WiMAX NSP, * %FALSE if it cannot be. **/ gboolean nm_wimax_nsp_connection_valid (NMWimaxNsp *nsp, NMConnection *connection) { NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *ctype; const char *nsp_name; const char *setting_name; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); ctype = nm_setting_connection_get_connection_type (s_con); if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0) return FALSE; s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) return FALSE; setting_name = nm_setting_wimax_get_network_name (s_wimax); if (!setting_name) return FALSE; nsp_name = nm_wimax_nsp_get_name (nsp); g_warn_if_fail (nsp_name != NULL); if (g_strcmp0 (nsp_name, setting_name) != 0) return FALSE; return TRUE; }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingWimax *s_wimax; const char *hwaddr, *setting_hwaddr; if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->connection_compatible (device, connection, error)) return FALSE; if (!nm_connection_is_type (connection, NM_SETTING_WIMAX_SETTING_NAME)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The connection was not a WiMAX connection.")); return FALSE; } /* Check MAC address */ hwaddr = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)); if (hwaddr) { if (!nm_utils_hwaddr_valid (hwaddr, ETH_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, _("Invalid device MAC address.")); return FALSE; } s_wimax = nm_connection_get_setting_wimax (connection); setting_hwaddr = nm_setting_wimax_get_mac_address (s_wimax); if (setting_hwaddr && !nm_utils_hwaddr_matches (setting_hwaddr, -1, hwaddr, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The MACs of the device and the connection didn't match.")); return FALSE; } } return TRUE; }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *connection_type; const char *mac; if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); connection_type = nm_setting_connection_get_connection_type (s_con); if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) return FALSE; s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) return FALSE; mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac && !nm_utils_hwaddr_matches (mac, -1, nm_device_get_hw_address (device), -1)) return FALSE; return TRUE; }
/* return value must be freed by caller with g_free() */ static gchar * get_mac_address_of_connection (NMConnection *connection) { const GByteArray *mac = NULL; if (!connection) return NULL; /* check the connection type */ if (nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)) { /* check wireless settings */ NMSettingWireless *s_wireless = nm_connection_get_setting_wireless (connection); if (!s_wireless) return NULL; mac = nm_setting_wireless_get_mac_address (s_wireless); if (mac) return nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER); } else if (nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { /* check wired settings */ NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); if (!s_wired) return NULL; mac = nm_setting_wired_get_mac_address (s_wired); if (mac) return nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER); } else if (nm_connection_is_type (connection, NM_SETTING_WIMAX_SETTING_NAME)) { /* check wimax settings */ NMSettingWimax *s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) return NULL; mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac) return nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER); } else if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { /* check infiniband settings */ NMSettingInfiniband *s_infiniband = \ nm_connection_get_setting_infiniband (connection); if (!s_infiniband) return NULL; mac = nm_setting_infiniband_get_mac_address (s_infiniband); if (mac) return nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND); } /* no MAC address found */ return NULL; }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *ctype; const GByteArray *mac; const char *hw_str; struct ether_addr *hw_mac; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); ctype = nm_setting_connection_get_connection_type (s_con); if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0) { g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION, "The connection was not a Wimax connection."); return FALSE; } s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) { g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION, "The connection was not a valid Wimax connection."); return FALSE; } /* Check MAC address */ hw_str = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)); if (hw_str) { hw_mac = ether_aton (hw_str); if (!hw_mac) { g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC, "Invalid device MAC address."); return FALSE; } mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) { g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH, "The MACs of the device and the connection didn't match."); return FALSE; } } return NM_DEVICE_CLASS (nm_device_wimax_parent_class)->connection_compatible (device, connection, error); }
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 = nm_connection_get_setting_connection (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 = nm_connection_get_setting_wimax (connection); 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; }
gboolean nm_wimax_nsp_check_compatible (NMWimaxNsp *self, NMConnection *connection) { NMWimaxNspPrivate *priv; NMSettingWimax *s_wimax; g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); priv = GET_PRIVATE (self); s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) return FALSE; return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0; }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *connection_type; const GByteArray *mac; if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->check_connection_compatible (device, connection, error)) return FALSE; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); connection_type = nm_setting_connection_get_connection_type (s_con); if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "The connection was not a WiMAX connection."); return FALSE; } s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INVALID, "The connection was not a valid WiMAX connection."); return FALSE; } mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac && memcmp (mac->data, nm_device_get_hw_address (device, NULL), ETH_ALEN)) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "The connection's MAC address did not match this device."); return FALSE; } return TRUE; }
static NMConnection * get_connection_for_nsp (GSList *connections, NMWimaxNsp *nsp) { GSList *iter; const char *nsp_name, *candidate_name; nsp_name = nm_wimax_nsp_get_name (nsp); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *candidate = NM_CONNECTION (iter->data); NMSettingWimax *s_wimax; s_wimax = nm_connection_get_setting_wimax (candidate); if (s_wimax) { candidate_name = nm_setting_wimax_get_network_name (s_wimax); if (g_strcmp0 (nsp_name, candidate_name) == 0) return candidate; } } return NULL; }
static gboolean real_check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); NMSettingConnection *s_con; NMSettingWimax *s_wimax; const char *connection_type; const GByteArray *mac; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); connection_type = nm_setting_connection_get_connection_type (s_con); if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "The connection was not a WiMAX connection."); return FALSE; } s_wimax = nm_connection_get_setting_wimax (connection); if (!s_wimax) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INVALID, "The connection was not a valid WiMAX connection."); return FALSE; } mac = nm_setting_wimax_get_mac_address (s_wimax); if (mac && memcmp (mac->data, &(priv->hw_addr.ether_addr_octet), ETH_ALEN)) { g_set_error (error, NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "The connection's MAC address did not match this device."); return FALSE; } return TRUE; }
static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); NMConnection *connection; NMSettingWimax *s_wimax; const char *nsp_name, *iface; int ret; iface = nm_device_get_iface (device); g_assert (iface); connection = nm_device_get_connection (device); g_assert (connection); s_wimax = nm_connection_get_setting_wimax (connection); g_assert (s_wimax); nsp_name = nm_setting_wimax_get_network_name (s_wimax); g_assert (nsp_name); nm_log_info (LOGD_WIMAX, "(%s): connecting to NSP '%s'", iface, nsp_name); priv->connect_failed = FALSE; ret = iwmx_sdk_connect (priv->sdk, nsp_name); if (ret < 0 && ret != -EINPROGRESS) { nm_log_err (LOGD_WIMAX, "(%s): failed to connect to NSP '%s'", iface, nsp_name); *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } /* FIXME: Is 40 seconds good estimation? I have no idea */ priv->activation_timeout_id = g_timeout_add_seconds (40, activation_timed_out, device); return NM_ACT_STAGE_RETURN_POSTPONE; }
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 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; }