[PATCH 1/2] enable establishing wpa connection in "early networking"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 loader/loader.c |    2 +
 loader/loader.h |    4 +-
 loader/net.c    |  335 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 loader/net.h    |    3 +
 4 files changed, 342 insertions(+), 2 deletions(-)

diff --git a/loader/loader.c b/loader/loader.c
index 2a5d21e..98dfda9 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 21c8b1e..04e0cd6 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;
 
@@ -1869,6 +1877,8 @@ 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;
+    char *ip_method;
 
     if ((is_nm_connected() == TRUE) &&
         (loaderData->netDev != NULL) && (loaderData->netDev_set == 1))
@@ -1876,8 +1886,36 @@ int kickstartNetworkUp(struct loaderData_s * loaderData, iface_t * iface) {
 
     iface_init_iface_t(iface);
 
-    return activateDevice(loaderData, iface);
+    if (loaderData->ipinfo_set == 1) {
+        ip_method = "manual";
+    }
+    else {
+        ip_method = "auto";
+    }
+    if (loaderData->essid != NULL) {
+        if (loaderData->wepkey != NULL) {
+            rc = add_and_activate_wifi_connection(&(loaderData->netDev), 
+                    loaderData->essid, "wep", loaderData->wepkey,
+                    ip_method, loaderData->ipv4);
+        }
+        else if (loaderData->wpakey != NULL) {
+            rc = add_and_activate_wifi_connection(&(loaderData->netDev), 
+                    loaderData->essid, "wpa", loaderData->wpakey,
+                    ip_method, loaderData->ipv4);
+        }
+        else {
+            rc = add_and_activate_wifi_connection(&(loaderData->netDev), 
+                    loaderData->essid, "unprotected", NULL, 
+                    ip_method, loaderData->ipv4);
+        }
+        if (0 == rc) {
+            loaderData->netDev_set = 1;
+            return(0);
+        }
+        else logMessage(ERROR, "wifi activation failed");
+    }
 
+    return(activateDevice(loaderData, iface));
 }
 
 int disconnectDevice(char *device) {
@@ -2229,4 +2267,299 @@ 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 == NULL)
+    {
+        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 **in_out_iface, char *ssid, 
+            NMDeviceWifi **out_device, NMAccessPoint **out_ap)
+{
+    //returns TRUE if device and ap (according to iface and ssid)
+    //were found
+    //in_out_iface, out_device, out_ap
+    const GPtrArray *devices;
+    int i;
+
+    devices = nm_client_get_devices(client);
+    for (i = 0; i < devices->len; i++)
+    {
+        NMDevice *candidate = g_ptr_array_index(devices, i);
+        char *dev_iface = strdup((char *)nm_device_get_iface(candidate));
+        if (strcmp(*in_out_iface, ""))
+        {
+            if (strcmp(dev_iface, *in_out_iface))
+            {
+                continue;
+            }
+        }
+        if (NM_IS_DEVICE_WIFI(candidate))
+        {
+            NMAccessPoint *ap = NULL;
+            ap = get_best_ap((NMDeviceWifi*)candidate, ssid);
+            if (ap != NULL)
+            {
+                *out_device = (NMDeviceWifi*)candidate;
+                *out_ap = ap;
+                *in_out_iface = strdup(dev_iface);
+                return TRUE;
+            }
+        }
+    }
+    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, 
+    char *protection, char *password, char *ip_method, char *address)
+        //return values mean:
+        //0 - everything ok
+        //1 - cannot open connection to D-Bus
+        //2 - cannot create NM Client
+        //3 - wifi disabled (hardware switch)
+        //4 - bad ssid format
+        //5 - no wifi device knowing about network with given ssid
+        //6 - activation failed (timed out)
+{
+    NMClient *client = NULL;
+    NMDeviceWifi *device = NULL;
+    NMAccessPoint *ap = NULL;
+    GMainLoop *loop;
+    GMainContext *ctx;
+    DBusGConnection *DBconnection;
+    GError *error;
+    gboolean success;
+    gint8 count=0, ret;
+    gboolean switched = FALSE;
+
+    if (*iface == NULL) *iface = "";
+    error = NULL;
+    DBconnection = dbus_g_bus_get (DBUS_BUS_SYSTEM,
+                               &error);
+    if (DBconnection == NULL)
+    {
+      g_error_free (error);
+      return(1);
+    }
+
+    client = nm_client_new();
+    if (!client) {
+        return(2);
+    }
+
+    if (!nm_client_wireless_hardware_get_enabled(client))
+    {
+        return(3);
+    }
+
+    if (!nm_client_wireless_get_enabled(client))
+    {
+        nm_client_wireless_set_enabled(client, TRUE);
+    }
+
+    GByteArray *ssid_ba;
+    int ssid_len;
+
+    ssid_len = strlen (ssid);
+    if (!ssid || !ssid_len || (ssid_len > 32))
+    {
+        return(4);
+    }
+    ssid_len = strlen (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 && (!switched))
+    {
+        while (g_main_context_pending(ctx))
+        {
+            g_main_context_iteration(ctx, FALSE);
+        }
+        success = get_device_and_ap(client, iface, ssid, &device, &ap);
+        if (success)
+        {
+            switched = TRUE;
+        }
+        sleep(1);
+        count++;
+    }
+
+    newtPopWindow();
+
+    if (!success)
+    {
+        return(5);
+    }
+
+    NMConnection *connection;
+    NMSettingConnection *s_con;
+    NMSettingWireless *s_wireless;
+    NMSettingWirelessSecurity *s_sec;
+    NMSettingIP4Config *s_ip;
+    char *uuid;
+
+    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);
+    if (!strcmp(protection, "wep") || (!strcmp(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 (!strcmp(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 (!strcmp(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 (!strcmp(ip_method, NM_SETTING_IP4_CONFIG_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, "manual",
+            NM_SETTING_IP4_CONFIG_ADDRESSES, addresses,
+            NULL);
+        nm_connection_add_setting(connection, NM_SETTING (s_ip));
+    }
+
+    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);
+    newtPopWindow();
+    if (ret == 0)
+    {
+        g_main_loop_unref(loop);
+        return(0);
+    }
+
+    *iface = NULL;
+    g_main_loop_unref(loop);
+    return(6);
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4: */
diff --git a/loader/net.h b/loader/net.h
index 2a74cdf..90a08b6 100644
--- a/loader/net.h
+++ b/loader/net.h
@@ -82,6 +82,9 @@ 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, 
+				      char *protection, char *password, 
+				      char *ip_method, char *address);
 #ifdef ENABLE_IPV6
 int isValidIPv6Address(const char *address);
 #endif
-- 
1.7.4.4

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list


[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux