/** * Convenience function to add an entire string array to the dict. * * @param iter_dict A valid DBusMessageIter returned from * wpa_dbus_dict_open_write() * @param key The key of the dict item * @param items The array of strings * @param num_items The number of strings in the array * @return TRUE on success, FALSE on failure * */ dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, const char *key, const char **items, const dbus_uint32_t num_items) { DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; dbus_uint32_t i; if (!key) return FALSE; if (!items && (num_items != 0)) return FALSE; if (!wpa_dbus_dict_begin_string_array(iter_dict, key, &iter_dict_entry, &iter_dict_val, &iter_array)) return FALSE; for (i = 0; i < num_items; i++) { if (!wpa_dbus_dict_string_array_add_element(&iter_array, items[i])) return FALSE; } if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) return FALSE; return TRUE; }
/** * wpas_dbus_iface_capabilities - Return interface capabilities * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a dict of strings * * Handler function for "capabilities" method call of an interface. */ DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; struct wpa_driver_capa capa; int res; DBusMessageIter iter, iter_dict; char **eap_methods; size_t num_items; dbus_bool_t strict = FALSE; DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_BOOLEAN, &strict, DBUS_TYPE_INVALID)) strict = FALSE; reply = dbus_message_new_method_return(message); dbus_message_iter_init_append(reply, &iter); if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) goto error; /* EAP methods */ eap_methods = eap_get_names_as_string_array(&num_items); if (eap_methods) { dbus_bool_t success = FALSE; size_t i = 0; success = wpa_dbus_dict_append_string_array( &iter_dict, "eap", (const char **) eap_methods, num_items); /* free returned method array */ while (eap_methods[i]) os_free(eap_methods[i++]); os_free(eap_methods); if (!success) goto error; } res = wpa_drv_get_capa(wpa_s, &capa); /***** pairwise cipher */ if (res < 0) { if (!strict) { const char *args[] = {"CCMP", "TKIP", "NONE"}; if (!wpa_dbus_dict_append_string_array( &iter_dict, "pairwise", args, sizeof(args) / sizeof(char*))) goto error; } } else { if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "CCMP")) goto error; } if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "TKIP")) goto error; } if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "NONE")) goto error; } if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; } /***** group cipher */ if (res < 0) { if (!strict) { const char *args[] = { "CCMP", "TKIP", "WEP104", "WEP40" }; if (!wpa_dbus_dict_append_string_array( &iter_dict, "group", args, sizeof(args) / sizeof(char*))) goto error; } } else { if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "CCMP")) goto error; } if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "TKIP")) goto error; } if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WEP104")) goto error; } if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WEP40")) goto error; } if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; } /***** key management */ if (res < 0) { if (!strict) { const char *args[] = { "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", "NONE" }; if (!wpa_dbus_dict_append_string_array( &iter_dict, "key_mgmt", args, sizeof(args) / sizeof(char*))) goto error; } } else { if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; if (!wpa_dbus_dict_string_array_add_element(&iter_array, "NONE")) goto error; if (!wpa_dbus_dict_string_array_add_element(&iter_array, "IEEE8021X")) goto error; if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WPA-EAP")) goto error; } if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WPA-PSK")) goto error; } if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WPA-NONE")) goto error; } if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; } /***** WPA protocol */ if (res < 0) { if (!strict) { const char *args[] = { "RSN", "WPA" }; if (!wpa_dbus_dict_append_string_array( &iter_dict, "proto", args, sizeof(args) / sizeof(char*))) goto error; } } else { if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "RSN")) goto error; } if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "WPA")) goto error; } if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; } /***** auth alg */ if (res < 0) { if (!strict) { const char *args[] = { "OPEN", "SHARED", "LEAP" }; if (!wpa_dbus_dict_append_string_array( &iter_dict, "auth_alg", args, sizeof(args) / sizeof(char*))) goto error; } } else { if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "OPEN")) goto error; } if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "SHARED")) goto error; } if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "LEAP")) goto error; } if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, &iter_array)) goto error; } if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) goto error; return reply; error: if (reply) dbus_message_unref(reply); return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, "an internal error occurred returning " "interface capabilities."); }