--- 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