--- loader/loader.c | 2 + loader/loader.h | 4 +- loader/net.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- loader/net.h | 15 +++ 4 files changed, 302 insertions(+), 2 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index 3b0204b..ec07b78 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -1050,6 +1050,8 @@ static void parseCmdLineFlags(struct loaderData_s * loaderData) { loaderData->mtu = argToLong(v); } else if (!strcasecmp(k, "wepkey")) { loaderData->wepkey = g_strdup(v); + } else if (!strcasecmp(k, "wpakey")) { + loaderData->wpakey = g_strdup(v); } else if (!strcasecmp(k, "linksleep")) { num_link_checks = argToLong(v); } else if (!strcasecmp(k, "nicdelay")) { diff --git a/loader/loader.h b/loader/loader.h index d761a4a..b81fc40 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -130,7 +130,9 @@ struct loaderData_s { int bootIf_set; char * netCls; int netCls_set; - char *ipv4, *netmask, *gateway, *dns, *domain, *hostname, *peerid, *ethtool, *subchannels, *portname, *essid, *wepkey, *nettype, *ctcprot, *options, *macaddr; + char *ipv4, *netmask, *gateway, *dns, *domain, *hostname, *peerid, *ethtool; + char *subchannels, *portname, *nettype, *ctcprot, *options, *macaddr; + char *essid, *wepkey, *wpakey; #ifdef ENABLE_IPV6 char *ipv6; char *ipv6prefix; diff --git a/loader/net.c b/loader/net.c index ebb8e3c..51a0840 100644 --- a/loader/net.c +++ b/loader/net.c @@ -54,6 +54,14 @@ #include "windows.h" #include "ibft.h" +#include <nm-device.h> +#include <nm-setting-connection.h> +#include <nm-setting-wireless.h> +#include <nm-setting-ip4-config.h> +#include <nm-utils.h> +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> + /* boot flags */ extern uint64_t flags; @@ -1819,6 +1827,7 @@ int chooseNetworkInterface(struct loaderData_s * loaderData) { * kickstart install so that we can do things like grab the ks.cfg from * the network */ int kickstartNetworkUp(struct loaderData_s * loaderData, iface_t * iface) { + int rc = -1; if ((is_nm_connected() == TRUE) && (loaderData->netDev != NULL) && (loaderData->netDev_set == 1)) @@ -1826,8 +1835,30 @@ int kickstartNetworkUp(struct loaderData_s * loaderData, iface_t * iface) { iface_init_iface_t(iface); - return activateDevice(loaderData, iface); + if (loaderData->essid != NULL) { + if (loaderData->wepkey != NULL) + rc = add_and_activate_wifi_connection(&(loaderData->netDev), + loaderData->essid, WIFI_PROTECTION_WEP, loaderData->wepkey, + loaderData->ipinfo_set, loaderData->ipv4); + + else if (loaderData->wpakey != NULL) + rc = add_and_activate_wifi_connection(&(loaderData->netDev), + loaderData->essid, WIFI_PROTECTION_WPA, loaderData->wpakey, + loaderData->ipinfo_set, loaderData->ipv4); + + else + rc = add_and_activate_wifi_connection(&(loaderData->netDev), + loaderData->essid, WIFI_PROTECTION_UNPROTECTED, NULL, + loaderData->ipinfo_set, loaderData->ipv4); + + if (rc == 0) { + loaderData->netDev_set = 1; + return 0; + } + else logMessage(ERROR, "wifi activation failed"); + } + return activateDevice(loaderData, iface); } int disconnectDevice(char *device) { @@ -2179,4 +2210,254 @@ int isURLRemote(char *url) { } } +gboolean byte_array_cmp(const GByteArray *array, char *string) { + //returns TRUE if array and char* contain the same strings + int i=0; + gboolean ret = TRUE; + if (array->len != strlen(string)) { + return FALSE; + } + while (i<array->len && ret) { + ret = ret && array->data[i] == string[i]; + i++; + } + return ret; +} + +NMAccessPoint* get_best_ap(NMDeviceWifi *device, char *ssid) { + const GPtrArray *aps; + int i; + NMAccessPoint *candidate = NULL; + guint8 max = 0; + aps = nm_device_wifi_get_access_points(device); + + if (!aps) return NULL; + + for (i = 0; i < aps->len; i++) { + NMAccessPoint *ap = g_ptr_array_index(aps, i); + const GByteArray *byte_ssid = nm_access_point_get_ssid(ap); + if (byte_array_cmp(byte_ssid, ssid)) { + if (nm_access_point_get_strength(ap) > max) { + max = nm_access_point_get_strength(ap); + candidate = ap; + } + } + } + return candidate; +} + +gboolean get_device_and_ap(NMClient *client, char **iface, char *ssid, + NMDeviceWifi **device, NMAccessPoint **ap) { + //returns TRUE if device and ap (according to iface and ssid) + //were found + //iface, device and ap are used for storing the results + //iface is also used as argument + + const GPtrArray *devices; + int i; + NMAccessPoint *candidate_ap = NULL; + NMDevice *candidate = NULL; + char *tmp_iface = NULL; + char *dev_iface = NULL; + + devices = nm_client_get_devices(client); + + for (i = 0; i < devices->len; i++) { + candidate = g_ptr_array_index(devices, i); + tmp_iface = (char *)nm_device_get_iface(candidate); + + if (!tmp_iface) continue; + dev_iface = strdup((char *)tmp_iface); + if (strcmp(*iface, "") && strcmp(dev_iface, *iface)) continue; + if (NM_IS_DEVICE_WIFI(candidate)) { + candidate_ap = get_best_ap((NMDeviceWifi*)candidate, ssid); + if (candidate_ap != NULL) { + *device = (NMDeviceWifi*)candidate; + *ap = candidate_ap; + *iface = dev_iface; + return TRUE; + } + } + else free(dev_iface); + } + return FALSE; +} + + +static void +add_cb(NMClient *client, + const char *connection_path, + const char *active_path, + GError *error, + gpointer user_data) { + if (error) logMessage(ERROR, "Error adding wifi connection: %s", error->message); +} + +guint32 ip_str_to_nbo(char* ip) { + //get NBO representation of ip address + struct in_addr tmp_addr = { 0 }; + + inet_pton(AF_INET, ip, &tmp_addr); + return tmp_addr.s_addr; +} + + +int add_and_activate_wifi_connection(char **iface, char *ssid, + int protection, char *password, int ip_method_manual, char *address) { + + NMClient *client = NULL; + NMDeviceWifi *device = NULL; + NMAccessPoint *ap = NULL; + GMainLoop *loop; + GMainContext *ctx; + DBusGConnection *DBconnection; + GError *error; + GByteArray *ssid_ba; + int ssid_len; + gboolean success = FALSE; + gint8 count = 0, ret; + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_sec; + NMSettingIP4Config *s_ip; + char *uuid; + + if (*iface == NULL) *iface = ""; + error = NULL; + DBconnection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + if (DBconnection == NULL) { + g_error_free(error); + return WIFI_ACTIVATION_DBUS_ERROR; + } + + client = nm_client_new(); + if (!client) return WIFI_ACTIVATION_NM_CLIENT_ERROR; + + if (!nm_client_wireless_hardware_get_enabled(client)) + return WIFI_ACTIVATION_WIFI_HW_DISABLED; + + if (!nm_client_wireless_get_enabled(client)) + nm_client_wireless_set_enabled(client, TRUE); + + if (!ssid) return WIFI_ACTIVATION_BAD_SSID; + ssid_len = strlen(ssid); + if (!ssid_len || ssid_len > 32) return WIFI_ACTIVATION_BAD_SSID; + ssid_ba = g_byte_array_sized_new(ssid_len); + g_byte_array_append(ssid_ba, (unsigned char *) ssid, ssid_len); + + loop = g_main_loop_new(NULL, FALSE); + ctx = g_main_loop_get_context(loop); + + while (g_main_context_pending(ctx)) + g_main_context_iteration(ctx, FALSE); + + /* display status */ + if (FL_CMDLINE(flags)) + printf(_("Waiting for NetworkManager to activate wifi.\n")); + else + winStatus(55, 3, NULL, + _("Waiting for NetworkManager to activate wifi.\n"), 0); + + while (count < 45 && !success) { + while (g_main_context_pending(ctx)) + g_main_context_iteration(ctx, FALSE); + success = get_device_and_ap(client, iface, ssid, &device, &ap); + sleep(1); + count++; + } + + if (!FL_CMDLINE(flags)) newtPopWindow(); + + if (!success) return WIFI_ACTIVATION_CANNOT_FIND_AP; + + connection = nm_connection_new(); + + s_con = (NMSettingConnection*) nm_setting_connection_new(); + uuid = nm_utils_uuid_generate(); + g_object_set(G_OBJECT (s_con), + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_ID, ssid, + NM_SETTING_CONNECTION_TYPE, "802-11-wireless", + NULL); + g_free(uuid); + nm_connection_add_setting(connection, NM_SETTING (s_con)); + + s_wireless = (NMSettingWireless*) nm_setting_wireless_new(); + g_object_set(G_OBJECT (s_wireless), + NM_SETTING_WIRELESS_SSID, ssid_ba, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NULL); + g_byte_array_free(ssid_ba, TRUE); + if ((protection == WIFI_PROTECTION_WEP) || protection == WIFI_PROTECTION_WPA) { + g_object_set(G_OBJECT (s_wireless), + NM_SETTING_WIRELESS_SEC, "802-11-wireless-security", + NULL); + } + nm_connection_add_setting(connection, NM_SETTING (s_wireless)); + + if (protection == WIFI_PROTECTION_WEP) { + s_sec = (NMSettingWirelessSecurity*) nm_setting_wireless_security_new(); + g_object_set (G_OBJECT (s_sec), + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", + NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 0, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, 1, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, password, + NULL); + if (strlen(password) == 32) { + g_object_set(G_OBJECT (s_sec), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, 2, + NULL); + } + nm_connection_add_setting(connection, NM_SETTING (s_sec)); + + } else if (protection == WIFI_PROTECTION_WPA) { + s_sec = (NMSettingWirelessSecurity*) nm_setting_wireless_security_new(); + g_object_set(G_OBJECT (s_sec), + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_PSK, password, + NULL); + nm_connection_add_setting(connection, NM_SETTING (s_sec)); + } + + if (ip_method_manual) { + GPtrArray *addresses = g_ptr_array_new(); + GArray *address_array = g_array_new(FALSE, FALSE, sizeof(guint32)); + guint32 nbo_ip = ip_str_to_nbo(address); + guint32 mask = 24; + guint32 gw = 0; + + g_array_append_val(address_array, nbo_ip); + g_array_append_val(address_array, mask); + g_array_append_val(address_array, gw); + + g_ptr_array_add(addresses, address_array); + + s_ip = (NMSettingIP4Config*) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT (s_ip), + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP4_CONFIG_ADDRESSES, addresses, + NULL); + nm_connection_add_setting(connection, NM_SETTING (s_ip)); + g_array_free(address_array, TRUE); + g_ptr_array_free(addresses, TRUE); + } + + const char *ap_path = nm_object_get_path((NMObject*) ap); + nm_client_add_and_activate_connection(client, connection, + (NMDevice*) device, ap_path, (NMClientAddActivateFn) add_cb, + NULL); + + ret = wait_for_iface_activation(*iface); + if (!FL_CMDLINE(flags)) newtPopWindow(); + if (ret == 0) { + g_main_loop_unref(loop); + return WIFI_ACTIVATION_OK; + } + + *iface = NULL; + g_main_loop_unref(loop); + return WIFI_ACTIVATION_TIMED_OUT; +} + /* vim:set shiftwidth=4 softtabstop=4: */ diff --git a/loader/net.h b/loader/net.h index 2a74cdf..cb1c39e 100644 --- a/loader/net.h +++ b/loader/net.h @@ -82,8 +82,23 @@ int wait_for_iface_activation(char * ifname); int wait_for_iface_disconnection(char *ifname); int isURLRemote(char *url); int isValidIPv4Address(const char *address); +int add_and_activate_wifi_connection (char **iface, char *ssid, + int protection, char *password, + int ip_method_manual, char *address); #ifdef ENABLE_IPV6 int isValidIPv6Address(const char *address); #endif #endif + +#define WIFI_PROTECTION_UNPROTECTED 0 +#define WIFI_PROTECTION_WEP 1 +#define WIFI_PROTECTION_WPA 2 + +#define WIFI_ACTIVATION_OK 0 +#define WIFI_ACTIVATION_DBUS_ERROR 1 +#define WIFI_ACTIVATION_NM_CLIENT_ERROR 2 +#define WIFI_ACTIVATION_WIFI_HW_DISABLED 3 +#define WIFI_ACTIVATION_BAD_SSID 4 +#define WIFI_ACTIVATION_CANNOT_FIND_AP 5 +#define WIFI_ACTIVATION_TIMED_OUT 6 -- 1.7.4.4 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list