Heres the last one in case the team may still be considering it. Mostly minor 
changes, such
as making a wpa_cmd that covers four functions that were very similar.

I'll build test images should anyone ask.

Cheers

Glenn


Add WPA support to netcfg. With this patch we add the option of installing over 
a WPA-PSK network.
A wpasupplicant udeb is required, and if not available, fall back to previous 
behaviour.
---
 packages/netcfg/Makefile                       |    2 +-
 packages/netcfg/debian/netcfg-common.templates |   44 +++
 packages/netcfg/debian/netcfg-dhcp.templates   |    2 +-
 packages/netcfg/dhcp.c                         |   78 ++++-
 packages/netcfg/netcfg.c                       |   58 +++-
 packages/netcfg/netcfg.h                       |   16 +-
 packages/netcfg/wireless.c                     |    2 +-
 packages/netcfg/wpa.c                          |  423 ++++++++++++++++++++++++
 packages/netcfg/wpa_ctrl.c                     |  256 ++++++++++++++
 packages/netcfg/wpa_ctrl.h                     |  187 +++++++++++
 10 files changed, 1041 insertions(+), 27 deletions(-)
 create mode 100644 packages/netcfg/wpa.c
 create mode 100644 packages/netcfg/wpa_ctrl.c
 create mode 100644 packages/netcfg/wpa_ctrl.h

diff --git a/packages/netcfg/Makefile b/packages/netcfg/Makefile
index 4753350..977aeb3 100644
--- a/packages/netcfg/Makefile
+++ b/packages/netcfg/Makefile
@@ -18,7 +18,7 @@ endif
 all: $(TARGETS)
 
 netcfg-static: netcfg-static.o static.o
-netcfg: netcfg.o dhcp.o static.o ethtool-lite.o
+netcfg: netcfg.o dhcp.o static.o ethtool-lite.o wpa.o wpa_ctrl.o
 
 $(TARGETS): $(COMMON_OBJS)
        $(CC) -o $@ $^ $(LDOPTS)
diff --git a/packages/netcfg/debian/netcfg-common.templates 
b/packages/netcfg/debian/netcfg-common.templates
index 973411e..815c410 100644
--- a/packages/netcfg/debian/netcfg-common.templates
+++ b/packages/netcfg/debian/netcfg-common.templates
@@ -56,6 +56,15 @@ _Description: Wireless ESSID for ${iface}:
  of the wireless network you would like ${iface} to use. To skip wireless
  configuration and continue, leave this field blank.
 
+Template: netcfg/wireless_security_type
+Type: select
+Choices-C: wep/open, wpa 
+__Choices: WEP/Open Network, WPA PSK
+# :sl2:
+_Description: Wireless Network Type for ${iface}:
+ Choose WEP/Open if the network is open or secured with WEP.
+ Choose WPA if the network is a WPA PSK protected network.
+
 Template: netcfg/wireless_wep
 Type: string
 # :sl1:
@@ -80,6 +89,19 @@ _Description: Invalid WEP key
  the next screen carefully on how to enter your WEP key correctly, and try
  again.
 
+Template: netcfg/invalid_pass
+Type: error
+# :sl2:
+_Description: Invalid passphrase
+ The WPA PSK passphrase was either too long (more than 64 characters)
+ or too short (less than 8 characters).
+
+Template: netcfg/wireless_wpa
+Type: string
+# :sl1:
+_Description: WPA passphrase for wireless device ${iface}:
+ Enter a passphrase for WPA PSK authentication.
+
 Template: netcfg/invalid_essid
 Type: error
 # :sl2:
@@ -87,6 +109,28 @@ _Description: Invalid ESSID
  The ESSID "${essid}" is invalid. ESSIDs may only be up to 32 characters,
  but may contain all kinds of characters.
 
+Template: netcfg/wpa_progress
+Type: text
+# :sl1:
+_Description: Attempting to exchange keys with the access point...
+
+Template: netcfg/wpa_progress_note
+Type: text
+# :sl1:
+_Description: This may take some time.
+
+Template: netcfg/wpa_success_note
+Type: text
+# :sl1:
+_Description: WPA connection succeeded
+
+Template: netcfg/wpa_supplicant_failed
+Type: note
+# :sl1:
+_Description: Failure of key exchange and association
+ The exchange of keys and association with the access point failed.
+ Please check the WPA parameters you provided.
+
 Template: netcfg/get_hostname
 Type: string
 Default: debian
diff --git a/packages/netcfg/debian/netcfg-dhcp.templates 
b/packages/netcfg/debian/netcfg-dhcp.templates
index 571a7e9..86ab6c4 100644
--- a/packages/netcfg/debian/netcfg-dhcp.templates
+++ b/packages/netcfg/debian/netcfg-dhcp.templates
@@ -77,7 +77,7 @@ Template: netcfg/dhcp_timeout
 Type: text
 Description: for internal use; can be preseeded
  Timeout for trying DHCP
-Default: 15
+Default: 25
 
 Template: netcfg/dhcp_ntp_servers
 Type: text
diff --git a/packages/netcfg/dhcp.c b/packages/netcfg/dhcp.c
index a98981f..4fd1ca5 100644
--- a/packages/netcfg/dhcp.c
+++ b/packages/netcfg/dhcp.c
@@ -50,13 +50,18 @@ static void netcfg_write_dhcp (char *iface, char *dhostname)
             fprintf(fp, "\thostname %s\n", dhostname);
         }
         if (is_wireless_iface(iface)) {
-            fprintf(fp, "\t# wireless-* options are implemented by the 
wireless-tools package\n");
-            fprintf(fp, "\twireless-mode %s\n",
-                    (mode == MANAGED) ? "managed" : "ad-hoc");
-            fprintf(fp, "\twireless-essid %s\n",
-                    (essid && *essid) ? essid : "any");
-            if (wepkey != NULL)
-                fprintf(fp, "\twireless-key1 %s\n", wepkey);
+            if (wpa_supplicant_status == WPA_QUEUED) {
+                fprintf(fp, "\twpa-ssid %s\n", essid);
+                fprintf(fp, "\twpa-psk  %s\n", passphrase);
+            } else {
+                fprintf(fp, "\t# wireless-* options are implemented by the 
wireless-tools package\n");
+                fprintf(fp, "\twireless-mode %s\n",
+                       (mode == MANAGED) ? "managed" : "ad-hoc");
+                fprintf(fp, "\twireless-essid %s\n",
+                        (essid && *essid) ? essid : "any");
+                if (wepkey != NULL)
+                    fprintf(fp, "\twireless-key1 %s\n", wepkey);
+           }
         }
         fclose(fp);
     }
@@ -221,8 +226,10 @@ int poll_dhcp_client (struct debconfclient *client)
     /* show progress bar */
     debconf_capb(client, "backup progresscancel");
     debconf_progress_start(client, 0, dhcp_seconds, "netcfg/dhcp_progress");
-    if (debconf_progress_info(client, "netcfg/dhcp_progress_note") == 30)
+    if (debconf_progress_info(client, "netcfg/dhcp_progress_note") == 30) {
+        kill_dhcp_client();
         goto stop;
+    }
     netcfg_progress_displayed = 1;
     
     /* wait between 2 and dhcp_seconds seconds for a DHCP lease */
@@ -306,20 +313,59 @@ int ask_dhcp_options (struct debconfclient *client)
 
 int ask_wifi_configuration (struct debconfclient *client)
 {
-    enum { ABORT, DONE, ESSID, WEP } wifistate = ESSID;
+    enum { ABORT, ESSID, SECURITY_TYPE, WEP, WPA, START, DONE } wifistate = 
ESSID;
+
+    extern enum wpa_t wpa_supplicant_status;
+    if (wpa_supplicant_status != WPA_UNAVAIL)
+        kill_wpa_supplicant();
+
     for (;;) {
         switch (wifistate) {
         case ESSID:
-            wifistate = (netcfg_wireless_set_essid(client, interface, "high") 
== GO_BACK) ?
-                ABORT : WEP;
+            if (wpa_supplicant_status == WPA_UNAVAIL)
+                wifistate = (netcfg_wireless_set_essid(client, interface, 
"high") == GO_BACK) ?
+                    ABORT : WEP;
+            else
+                wifistate = (netcfg_wireless_set_essid(client, interface, 
"high") == GO_BACK) ?
+                    ABORT : SECURITY_TYPE;
             break;
+        
+        case SECURITY_TYPE:
+            {
+                int ret;
+                ret = wireless_security_type(client, interface);
+                if (ret == GO_BACK)
+                    wifistate = ESSID;
+                else if (ret == REPLY_WPA)
+                    wifistate = WPA;
+                else
+                    wifistate = WEP;
+                break;
+            }
+        
         case WEP:
-            wifistate = (netcfg_wireless_set_wep(client, interface) == 
GO_BACK) ?
+            if (wpa_supplicant_status == WPA_UNAVAIL)
+                wifistate = (netcfg_wireless_set_wep(client, interface) == 
GO_BACK) ?
+                    ESSID : DONE;
+            else
+                wifistate = (netcfg_wireless_set_wep(client, interface) == 
GO_BACK) ?
+                    SECURITY_TYPE : DONE;
+            break;
+        
+        case WPA:
+            wifistate = (netcfg_set_passphrase(client, interface) == GO_BACK) ?
+                SECURITY_TYPE : START;
+            break;
+        
+        case START:
+            wifistate = (wpa_supplicant_start(client, interface, essid, 
passphrase) == GO_BACK) ?
                 ESSID : DONE;
             break;
+            
         case ABORT:
             return REPLY_ASK_OPTIONS;
             break;
+        
         case DONE:
             return REPLY_CHECK_DHCP;
             break;
@@ -497,12 +543,8 @@ int netcfg_activate_dhcp (struct debconfclient *client)
                 break;
             case REPLY_RECONFIGURE_WIFI:
                 if (ask_wifi_configuration(client) == REPLY_CHECK_DHCP) {
-                    if (dhcp_pid > 0)
-                        state = POLL;
-                    else {
-                        kill_dhcp_client();
-                        state = START;
-                    }
+                    kill_dhcp_client();
+                    state = START;
                 }
                 else
                     state = ASK_OPTIONS;
diff --git a/packages/netcfg/netcfg.c b/packages/netcfg/netcfg.c
index 3c638aa..f1e7f17 100644
--- a/packages/netcfg/netcfg.c
+++ b/packages/netcfg/netcfg.c
@@ -33,6 +33,7 @@
 #endif
 #include "netcfg.h"
 
+enum wpa_t wpa_supplicant_status;
 static method_t netcfg_method = DHCP;
 
 response_t netcfg_get_method(struct debconfclient *client)
@@ -69,11 +70,15 @@ int main(int argc, char *argv[])
            GET_STATIC,
            WCONFIG,
            WCONFIG_ESSID,
+           WCONFIG_SECURITY_TYPE,
            WCONFIG_WEP,
+           WCONFIG_WPA,
+           START_WPA,
            QUIT } state = GET_INTERFACE;
     
     static struct debconfclient *client;
     static int requested_wireless_tools = 0;
+    extern enum wpa_t wpa_supplicant_status;
     char **ifaces;
     char *defiface = NULL, *defwireless = NULL;
     response_t res;
@@ -103,6 +108,12 @@ int main(int argc, char *argv[])
         case BACKUP:
             return 10;
         case GET_INTERFACE:
+            /* If we have returned from outside of netcfg and want to
+             * reconfigure networking, check to see if wpasupplicant is
+             * running, and kill it if it is. If left running when
+             * the interfaces are taken up and down, it appears to
+             * leave it in an inconsistant state */
+            kill_wpa_supplicant();
             /* Choose a default from ethtool-lite */
             if (get_all_ifs(1, &ifaces) > 1) {
                 while (*ifaces) {
@@ -251,19 +262,60 @@ int main(int argc, char *argv[])
         case WCONFIG_ESSID:
             if (netcfg_wireless_set_essid(client, interface, NULL) == GO_BACK)
                 state = BACKUP;
-            else
-                state = WCONFIG_WEP;
+            else {
+                init_wpa_supplicant_support();
+                if (wpa_supplicant_status == WPA_UNAVAIL)
+                    state = WCONFIG_WEP;
+                else
+                    state = WCONFIG_SECURITY_TYPE;
+            }
             break;
             
+        case WCONFIG_SECURITY_TYPE:
+            {
+                int ret;
+                ret = wireless_security_type(client, interface);
+                if (ret == GO_BACK)
+                    state = WCONFIG_ESSID;
+                else if (ret == REPLY_WPA)
+                    state = WCONFIG_WPA;
+                else
+                    state = WCONFIG_WEP;
+                break;
+            }
+
         case WCONFIG_WEP:
             if (netcfg_wireless_set_wep(client, interface) == GO_BACK)
-                state = WCONFIG_ESSID;
+                if (wpa_supplicant_status == WPA_UNAVAIL)
+                    state = WCONFIG_ESSID;
+                else
+                    state = WCONFIG_SECURITY_TYPE;
             else
                 state = GET_METHOD;
             break;
             
+        case WCONFIG_WPA:
+            if (wpa_supplicant_status == WPA_OK) {
+                di_exec_shell_log("apt-install wpasupplicant");
+                wpa_supplicant_status = WPA_QUEUED;
+            }
+
+            if (netcfg_set_passphrase(client, interface) == GO_BACK)
+                state = WCONFIG_SECURITY_TYPE;
+            else
+                state = START_WPA;
+            break;
+            
+        case START_WPA:
+            if (wpa_supplicant_start(client, interface, essid, passphrase) == 
GO_BACK)
+                state = WCONFIG_ESSID;
+            else
+                state = GET_METHOD;
+            break; 
+
         case QUIT:
             return 0;
         }
     }
 }
+
diff --git a/packages/netcfg/netcfg.h b/packages/netcfg/netcfg.h
index a7bc8a9..0d6c2bf 100644
--- a/packages/netcfg/netcfg.h
+++ b/packages/netcfg/netcfg.h
@@ -10,11 +10,16 @@
 #define DHCLIENT3_CONF "/etc/dhcp3/dhclient.conf"
 #define DOMAIN_FILE     "/tmp/domain_name"
 #define NTP_SERVER_FILE "/tmp/dhcp-ntp-servers"
+#define WPASUPP_CTRL    "/var/run/wpa_supplicant"
+#define WPAPID         "/var/run/wpa_supplicant.pid"
 
 #define DEVNAMES       "/etc/network/devnames"
 #define DEVHOTPLUG     "/etc/network/devhotplug"
 #define STAB           "/var/run/stab"
 
+#define WPA_MIN         8    /* minimum passphrase length */
+#define WPA_MAX         64   /* maximum passphrase length */
+
 #define _GNU_SOURCE
 
 #include <sys/types.h>
@@ -41,9 +46,10 @@
 "ff02::2 ip6-allrouters\n" \
 "ff02::3 ip6-allhosts\n"
 
-typedef enum { NOT_ASKED = 30, GO_BACK } response_t;
+typedef enum { NOT_ASKED = 30, GO_BACK, REPLY_WEP, REPLY_WPA } response_t;
 typedef enum { DHCP, STATIC, DUNNO } method_t;
 typedef enum { ADHOC = 1, MANAGED = 2 } wifimode_t;
+extern enum wpa_t { WPA_OK, WPA_QUEUED, WPA_UNAVAIL } wpa_supplicant_status;
 
 extern int netcfg_progress_displayed;
 extern int wfd, skfd;
@@ -64,7 +70,7 @@ extern struct in_addr gateway;
 extern struct in_addr pointopoint;
 
 /* wireless */
-extern char *essid, *wepkey;
+extern char *essid, *wepkey, *passphrase;
 extern wifimode_t mode;
 
 /* common functions */
@@ -108,10 +114,14 @@ extern void netcfg_write_common (struct in_addr 
ipaddress, char *hostname,
 void netcfg_nameservers_to_array(char *nameservers, struct in_addr array[]);
 
 extern int is_wireless_iface (const char* iface);
-
 extern int netcfg_wireless_set_essid (struct debconfclient *client, char* 
iface, char* priority);
 extern int netcfg_wireless_set_wep (struct debconfclient *client, char* iface);
+extern int wireless_security_type (struct debconfclient *client, char* iface);
+extern int netcfg_set_passphrase (struct debconfclient *client, char* iface);
+extern int init_wpa_supplicant_support (void);
+extern int kill_wpa_supplicant (void);
 
+extern int wpa_supplicant_start (struct debconfclient *client, char *iface, 
char *ssid, char *passphrase);
 extern int iface_is_hotpluggable(const char *iface);
 extern short find_in_stab (const char *iface);
 extern void deconfigure_network(void);
diff --git a/packages/netcfg/wireless.c b/packages/netcfg/wireless.c
index ed07b8a..40432d1 100644
--- a/packages/netcfg/wireless.c
+++ b/packages/netcfg/wireless.c
@@ -53,7 +53,7 @@ int netcfg_wireless_set_essid (struct debconfclient * client, 
char *iface, char*
     wconf.has_mode = 1;
     wconf.mode = mode;
     
-    debconf_input(client, priority ? priority : "low", 
"netcfg/wireless_essid");
+    debconf_input(client, priority ? priority : "high", 
"netcfg/wireless_essid");
     
     if (debconf_go(client) == 30)
         return GO_BACK;
diff --git a/packages/netcfg/wpa.c b/packages/netcfg/wpa.c
new file mode 100644
index 0000000..c0ca25b
--- /dev/null
+++ b/packages/netcfg/wpa.c
@@ -0,0 +1,423 @@
+/*
+* WPA module for netcfg
+*
+* Copyright (C) 2008 Glenn Saberton <[EMAIL PROTECTED]>
+*
+* Licensed under the terms of the GNU General Public License version 2
+*
+*/
+
+#include "netcfg.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <debian-installer.h>
+#include "wpa_ctrl.h"
+#include <iwlib.h>
+
+pid_t wpa_supplicant_pid = -1;
+enum wpa_t wpa_supplicant_status;
+struct wpa_ctrl *ctrl;
+char *passphrase = NULL;
+static int wpa_is_running = 0;
+
+int init_wpa_supplicant_support(void)
+{
+    if (access("/sbin/wpa_supplicant", F_OK) == 0)
+        wpa_supplicant_status = WPA_OK;
+    else {
+        wpa_supplicant_status = WPA_UNAVAIL;
+        di_info("Wpasupplicant not found on the system. Disabling WPA 
options");
+    }
+    return 0;
+}
+
+int kill_wpa_supplicant(void)
+{
+    pid_t wpa_pid;
+    FILE *fp;
+
+    fp = (fopen(WPAPID, "r"));
+    if (fp == NULL) {
+        di_warning("Couldn't read Wpasupplicant pid file, not trying to 
kill.");
+        return 0;
+    }
+    else {
+        fscanf(fp, "%d", &wpa_pid);
+        fclose(fp);
+    }
+      if ((kill(wpa_pid, SIGTERM)) == 0)
+          return 0;
+      else {
+          kill(wpa_pid, SIGKILL);
+          unlink(WPAPID);
+          return 0;
+      }
+}
+
+int wireless_security_type (struct debconfclient *client, char *iface)
+{
+    int ret = 0 ;
+    debconf_subst(client, "netcfg/wireless_security_type", "iface", iface);
+    debconf_input(client, "high", "netcfg/wireless_security_type");
+    ret = debconf_go(client);
+
+    if (ret == 30)
+        return GO_BACK;
+
+    debconf_get(client, "netcfg/wireless_security_type");
+
+    if (!strcmp(client->value, "wep/open"))
+        return REPLY_WEP;
+    else
+        return REPLY_WPA;
+
+}
+
+int netcfg_set_passphrase (struct debconfclient *client, char *iface)
+{
+    int ret;
+    
+    debconf_subst(client, "netcfg/wireless_wpa", "iface", iface);
+    debconf_input(client, "high", "netcfg/wireless_wpa");
+    ret = debconf_go(client);
+
+    if (ret == 30)
+        return GO_BACK;
+
+    if (passphrase != NULL)
+        free(passphrase);
+        
+    debconf_get(client, "netcfg/wireless_wpa");
+    passphrase = strdup(client->value);
+
+    while (strlen(passphrase) < WPA_MIN || strlen(passphrase) > WPA_MAX) {
+        debconf_subst(client, "netcfg/invalid_pass", "passphrase", passphrase);
+        debconf_input(client, "critical", "netcfg/invalid_pass");
+        debconf_go(client);
+        free(passphrase);
+
+        debconf_input(client, "high", "netcfg/wireless_wpa");
+        ret = debconf_go(client);
+
+        if (ret == 30)
+            return GO_BACK;
+
+        debconf_get(client, "netcfg/wireless_wpa");
+        passphrase = strdup(client->value);
+    }
+    return 0;
+}
+
+static int start_wpa_daemon(struct debconfclient *client)
+{
+    wpa_supplicant_pid = fork();
+
+    if (wpa_supplicant_pid == 0) {
+        fclose(client->out);
+        if (execlp("wpa_supplicant", "wpa_supplicant", "-i", interface, "-C",
+                   WPASUPP_CTRL, "-P", WPAPID, "-B", NULL) == -1) {
+            di_error("could not exec wpasupplicant: %s", strerror(errno));
+            return 1;
+        }
+        else 
+            return 0;
+    }
+    else {
+        waitpid(wpa_supplicant_pid, NULL, 0);
+        return 0;
+    }
+}
+
+void wpa_daemon_running(void)
+{
+    FILE *fp = fopen(WPAPID, "r");
+    if (fp) {
+        wpa_is_running = 1;
+        fclose(fp);
+    }
+}
+
+static int wpa_connect(char *iface)
+{
+    char *cfile;
+    int flen, res;
+    
+    flen = (strlen(WPASUPP_CTRL) + strlen(iface) + 2);
+    
+    cfile = malloc(flen);
+    if (cfile == NULL) {
+        di_info("Can't allocate memory for WPA control iface.");
+        return 1;
+    }    
+        
+    res = snprintf(cfile, flen, "%s/%s", WPASUPP_CTRL, iface);
+    if ((res < 0) || (res >= flen)) {
+        free(cfile);
+        return 1;
+    }   
+    ctrl = wpa_ctrl_open(cfile);
+    free(cfile);
+    
+    if (ctrl == NULL) {
+        di_info("Couldn't connect to wpasupplicant");
+        return 1;
+    }
+    else
+        return 0;
+}
+
+static int netcfg_wpa_cmd (char *cmd)
+{
+    char buf[256];
+    size_t len;
+    int ret;
+    
+    len = sizeof(buf) -1;
+    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL);
+    
+    if (ret < 0) {
+        di_info("Sending %s to wpasupplicant failed", cmd);
+        return 1;
+    }
+    
+    return 0;
+}
+
+static int wpa_set_ssid (char *ssid)
+{
+    int ret, res;
+    size_t len;
+    char cmd[256];
+    char buf[256];
+    
+    res = snprintf(cmd, sizeof(cmd), "SET_NETWORK 0 %s \"%s\"", "ssid", ssid);
+    if (res < 0)
+        return 1;
+        
+    len = sizeof(buf) -1;
+    ret = wpa_ctrl_request(ctrl, cmd, sizeof(cmd), buf, &len, NULL);
+    if (ret != 0) {
+        di_info("Failed to set the ssid with wpasupplicant");
+        return 1;
+    }
+    return 0;
+}
+
+static int wpa_set_psk(char *passphrase)
+{
+    int ret, res;
+    size_t len;
+    char buf[256];
+    char cmd[256];
+    
+    res = snprintf(cmd, sizeof(cmd), "SET_NETWORK 0 %s \"%s\"", "psk", 
passphrase);
+    if (res < 0)
+        return 1;
+    
+    len = sizeof(buf) -1;    
+    ret = wpa_ctrl_request(ctrl, cmd, sizeof(cmd), buf, &len, NULL);
+    if (ret != 0)
+        return 1;
+
+    return 0;
+}
+
+static int wpa_status(void)
+{
+    int ret;
+    size_t len;
+    char buf[2048];
+    const char *success = "wpa_state=COMPLETED";
+    
+    len = sizeof(buf) -1;
+    ret = wpa_ctrl_request(ctrl, "STATUS", 7, buf, &len, NULL);
+
+    if (ret == 0) {
+        buf[len] = '\0';
+        di_info("buf = %s", buf);
+    }
+    else
+        return 1;
+        
+    if (strstr(buf, success) == NULL)
+        return 1;
+    else {
+        di_info("success");
+        return 0;
+    }
+}
+
+int poll_wpa_supplicant(struct debconfclient *client)
+{
+    int wpa_timeout = 60;
+    int seconds_slept = 0;
+    int state = 1;
+
+    debconf_capb(client, "backup progresscancel");
+    debconf_progress_start(client, 0, wpa_timeout, "netcfg/wpa_progress");
+
+    for (seconds_slept = 0; seconds_slept <= wpa_timeout; seconds_slept++) {
+
+         if (debconf_progress_info(client, "netcfg/wpa_progress_note") == 30)
+             goto stop;
+
+             if (debconf_progress_step(client, 1) == 30)
+                 goto stop;
+
+             sleep(1);
+
+             if ((seconds_slept <= wpa_timeout) && (seconds_slept % 5) == 0) {
+                 if (!wpa_status()) {
+                     debconf_progress_set(client, wpa_timeout);
+                     debconf_progress_info(client, "netcfg/wpa_success_note");
+                     state = 0;
+                     sleep(2);
+                     goto stop;
+                 }
+             }
+             if (seconds_slept == wpa_timeout) {
+                 debconf_progress_stop(client);
+                 debconf_capb(client, "backup");
+                 debconf_capb(client, "");
+                 debconf_input(client, "critical", 
"netcfg/wpa_supplicant_failed");
+                 debconf_go(client);
+                 debconf_capb(client, "backup");
+                 return 1;
+             }
+    }
+    stop:
+        debconf_progress_stop(client);
+        debconf_capb(client, "backup");
+        if (!state)
+            return 0;
+        else
+            return 1;
+
+}
+
+int wpa_supplicant_start(struct debconfclient *client, char *iface, char 
*ssid, char *passphrase)
+{
+    int retry = 0;
+    
+    enum { CHECK_DAEMON,
+           START_DAEMON,
+           CONNECT,
+           PING,
+           ADD_NETWORK,
+           SET_ESSID,
+           SET_PSK,
+           SET_SCAN_SSID,
+           ENABLE_NETWORK,
+           POLL,
+           ABORT,
+           SUCCESS } state = CHECK_DAEMON;
+    
+    for (;;) {
+        switch(state) {
+        
+        case CHECK_DAEMON:
+            wpa_daemon_running();
+            if (wpa_is_running)
+                state = CONNECT;
+            else
+                state = START_DAEMON;
+            break;
+            
+        case START_DAEMON:
+            if (!start_wpa_daemon(client))
+                state = CONNECT;
+            else
+                state = ABORT;
+            break;
+        
+        case CONNECT:
+            if (wpa_connect(iface) == 0)
+                state = PING;
+            else
+                state = ABORT;
+            break;
+        
+        case PING:
+            /* if the daemon doesn't respond, try and ping
+             * it and increment retry. If we have done
+             * this 4 times, something must be wrong
+             * so bail out.  */
+            retry++;
+            if (retry > 4)
+                state = ABORT;
+            else if (netcfg_wpa_cmd("PING")) {
+                kill_wpa_supplicant();
+                state = START_DAEMON;
+                break;
+            }
+            else
+                state = ADD_NETWORK;
+            break;
+        
+        case ADD_NETWORK:
+            if (wpa_is_running) {
+                state = SET_ESSID;
+                break;
+            }
+            if (netcfg_wpa_cmd("ADD_NETWORK"))
+                state = PING;
+            else
+                state = SET_ESSID;
+            break;
+        
+        case SET_ESSID:
+            if (wpa_set_ssid(ssid))
+                state = PING;
+            else
+                state = SET_PSK;
+            break;
+        
+        case SET_PSK:
+            if (wpa_set_psk(passphrase))
+                state = PING;
+            else
+                state = SET_SCAN_SSID;
+            break;
+        
+        case SET_SCAN_SSID:
+            if (netcfg_wpa_cmd("SET_NETWORK 0 scan_ssid 1"))
+                state = PING;
+            else
+                state = ENABLE_NETWORK;
+            break;
+        
+        case ENABLE_NETWORK:
+             if (netcfg_wpa_cmd("ENABLE_NETWORK 0"))
+                 state = PING;
+             else
+                 state = POLL;
+             break;
+        
+        case POLL:
+            if (poll_wpa_supplicant(client))
+                state = ABORT;
+            else
+                state = SUCCESS;
+            break;
+             
+        case ABORT:
+            if (ctrl == NULL) 
+                return GO_BACK;
+            else {
+                wpa_ctrl_close(ctrl);
+                ctrl = NULL;
+                return GO_BACK;
+            }
+             
+         case SUCCESS:
+             if (ctrl == NULL)
+                 return 0;
+             else {
+                 wpa_ctrl_close(ctrl);
+                 ctrl = NULL;
+                 return 0;
+             }
+        }
+    }
+}
diff --git a/packages/netcfg/wpa_ctrl.c b/packages/netcfg/wpa_ctrl.c
new file mode 100644
index 0000000..6e01a9e
--- /dev/null
+++ b/packages/netcfg/wpa_ctrl.c
@@ -0,0 +1,256 @@
+/*
+ * Modifed version of src/common/wpa_ctrl.c from wpa_supplicant, discarding
+ * all code paths except for CONFIG_CTRL_IFACE_UNIX. Define strlcpy inline,
+ * it is not provided by GNU libc.
+ * Copyright (c) 2008, Kel Modderman <[EMAIL PROTECTED]>
+ *
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2007, Jouni Malinen <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "wpa_ctrl.h"
+
+/**
+ * strlcpy - Copy a string with size bound and NUL-termination
+ * @dest: Destination
+ * @src: Source
+ * @siz: Size of the target buffer
+ * Returns: Total length of the target string (length of src) (not including
+ * NUL-termination)
+ *
+ * This function matches in behavior with the strlcpy(3) function in OpenBSD.
+ */
+size_t strlcpy(char *dest, const char *src, size_t siz)
+{
+       const char *s = src;
+       size_t left = siz;
+
+       if (left) {
+               /* Copy string up to the maximum size of the dest buffer */
+               while (--left != 0) {
+                       if ((*dest++ = *s++) == '\0')
+                               break;
+               }
+       }
+
+       if (left == 0) {
+               /* Not enough room for the string; force NUL-termination */
+               if (siz != 0)
+                       *dest = '\0';
+               while (*s++)
+                       ; /* determine total src string length */
+       }
+
+       return s - src - 1;
+}
+
+
+/**
+ * struct wpa_ctrl - Internal structure for control interface library
+ *
+ * This structure is used by the wpa_supplicant/hostapd control interface
+ * library to store internal data. Programs using the library should not touch
+ * this data directly. They can only use the pointer to the data structure as
+ * an identifier for the control interface connection and use this as one of
+ * the arguments for most of the control interface library functions.
+ */
+struct wpa_ctrl {
+       int s;
+       struct sockaddr_un local;
+       struct sockaddr_un dest;
+};
+
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+       struct wpa_ctrl *ctrl;
+       static int counter = 0;
+       int ret;
+       size_t res;
+
+       ctrl = malloc(sizeof(*ctrl));
+       if (ctrl == NULL)
+               return NULL;
+       memset(ctrl, 0, sizeof(*ctrl));
+
+       ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+       if (ctrl->s < 0) {
+               free(ctrl);
+               return NULL;
+       }
+
+       ctrl->local.sun_family = AF_UNIX;
+       ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
+                         "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
+       if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
+               close(ctrl->s);
+               free(ctrl);
+               return NULL;
+       }
+       if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
+                   sizeof(ctrl->local)) < 0) {
+               close(ctrl->s);
+               free(ctrl);
+               return NULL;
+       }
+
+       ctrl->dest.sun_family = AF_UNIX;
+       res = strlcpy(ctrl->dest.sun_path, ctrl_path,
+                        sizeof(ctrl->dest.sun_path));
+       if (res >= sizeof(ctrl->dest.sun_path)) {
+               close(ctrl->s);
+               free(ctrl);
+               return NULL;
+       }
+       if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
+                   sizeof(ctrl->dest)) < 0) {
+               close(ctrl->s);
+               unlink(ctrl->local.sun_path);
+               free(ctrl);
+               return NULL;
+       }
+
+       return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+       unlink(ctrl->local.sun_path);
+       close(ctrl->s);
+       free(ctrl);
+}
+
+
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+                    char *reply, size_t *reply_len,
+                    void (*msg_cb)(char *msg, size_t len))
+{
+       struct timeval tv;
+       int res;
+       fd_set rfds;
+       const char *_cmd;
+       char *cmd_buf = NULL;
+       size_t _cmd_len;
+
+       {
+               _cmd = cmd;
+               _cmd_len = cmd_len;
+       }
+
+       if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
+               free(cmd_buf);
+               return -1;
+       }
+       free(cmd_buf);
+
+       for (;;) {
+               tv.tv_sec = 2;
+               tv.tv_usec = 0;
+               FD_ZERO(&rfds);
+               FD_SET(ctrl->s, &rfds);
+               res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+               if (FD_ISSET(ctrl->s, &rfds)) {
+                       res = recv(ctrl->s, reply, *reply_len, 0);
+                       if (res < 0)
+                               return res;
+                       if (res > 0 && reply[0] == '<') {
+                               /* This is an unsolicited message from
+                                * wpa_supplicant, not the reply to the
+                                * request. Use msg_cb to report this to the
+                                * caller. */
+                               if (msg_cb) {
+                                       /* Make sure the message is nul
+                                        * terminated. */
+                                       if ((size_t) res == *reply_len)
+                                               res = (*reply_len) - 1;
+                                       reply[res] = '\0';
+                                       msg_cb(reply, res);
+                               }
+                               continue;
+                       }
+                       *reply_len = res;
+                       break;
+               } else {
+                       return -2;
+               }
+       }
+       return 0;
+}
+
+
+static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
+{
+       char buf[10];
+       int ret;
+       size_t len = 10;
+
+       ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
+                              buf, &len, NULL);
+       if (ret < 0)
+               return ret;
+       if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
+               return 0;
+       return -1;
+}
+
+
+int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
+{
+       return wpa_ctrl_attach_helper(ctrl, 1);
+}
+
+
+int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
+{
+       return wpa_ctrl_attach_helper(ctrl, 0);
+}
+
+
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+       int res;
+
+       res = recv(ctrl->s, reply, *reply_len, 0);
+       if (res < 0)
+               return res;
+       *reply_len = res;
+       return 0;
+}
+
+
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
+{
+       struct timeval tv;
+       fd_set rfds;
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+       FD_ZERO(&rfds);
+       FD_SET(ctrl->s, &rfds);
+       select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+       return FD_ISSET(ctrl->s, &rfds);
+}
+
+
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
+{
+       return ctrl->s;
+}
diff --git a/packages/netcfg/wpa_ctrl.h b/packages/netcfg/wpa_ctrl.h
new file mode 100644
index 0000000..e4cd490
--- /dev/null
+++ b/packages/netcfg/wpa_ctrl.h
@@ -0,0 +1,187 @@
+/*
+ * Unmodifed version of src/common/wpa_ctrl.h from wpa_supplicant.
+ *
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2006, Jouni Malinen <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ */
+
+#ifndef WPA_CTRL_H
+#define WPA_CTRL_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* wpa_supplicant control interface - fixed message prefixes */
+
+/** Interactive request for identity/password/pin */
+#define WPA_CTRL_REQ "CTRL-REQ-"
+
+/** Response to identity/password/pin request */
+#define WPA_CTRL_RSP "CTRL-RSP-"
+
+/* Event messages with fixed prefix */
+/** Authentication completed successfully and data connection enabled */
+#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
+/** Disconnected, data connection is not available */
+#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
+/** wpa_supplicant is exiting */
+#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
+/** Password change was completed successfully */
+#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
+/** EAP-Request/Notification received */
+#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
+/** EAP authentication started (EAP-Request/Identity received) */
+#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
+/** EAP method selected */
+#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
+/** EAP authentication completed successfully */
+#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
+/** EAP authentication failed (EAP-Failure received) */
+#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
+/** New scan results available */
+#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
+
+
+/* wpa_supplicant/hostapd control interface access */
+
+/**
+ * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
+ * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
+ * Returns: Pointer to abstract control interface data or %NULL on failure
+ *
+ * This function is used to open a control interface to wpa_supplicant/hostapd.
+ * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
+ * is configured in wpa_supplicant/hostapd and other programs using the control
+ * interface need to use matching path configuration.
+ */
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
+
+
+/**
+ * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ *
+ * This function is used to close a control interface.
+ */
+void wpa_ctrl_close(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * @cmd: Command; usually, ASCII text, e.g., "PING"
+ * @cmd_len: Length of the cmd in bytes
+ * @reply: Buffer for the response
+ * @reply_len: Reply buffer length
+ * @msg_cb: Callback function for unsolicited messages or %NULL if not used
+ * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
+ *
+ * This function is used to send commands to wpa_supplicant/hostapd. Received
+ * response will be written to reply and reply_len is set to the actual length
+ * of the reply. This function will block for up to two seconds while waiting
+ * for the reply. If unsolicited messages are received, the blocking time may
+ * be longer.
+ *
+ * msg_cb can be used to register a callback function that will be called for
+ * unsolicited messages received while waiting for the command response. These
+ * messages may be received if wpa_ctrl_request() is called at the same time as
+ * wpa_supplicant/hostapd is sending such a message. This can happen only if
+ * the program has used wpa_ctrl_attach() to register itself as a monitor for
+ * event messages. Alternatively to msg_cb, programs can register two control
+ * interface connections and use one of them for commands and the other one for
+ * receiving event messages, in other words, call wpa_ctrl_attach() only for
+ * the control interface connection that will be used for event messages.
+ */
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+                    char *reply, size_t *reply_len,
+                    void (*msg_cb)(char *msg, size_t len));
+
+
+/**
+ * wpa_ctrl_attach - Register as an event monitor for the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 0 on success, -1 on failure, -2 on timeout
+ *
+ * This function registers the control interface connection as a monitor for
+ * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
+ * control interface connection starts receiving event messages that can be
+ * read with wpa_ctrl_recv().
+ */
+int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_detach - Unregister event monitor from the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 0 on success, -1 on failure, -2 on timeout
+ *
+ * This function unregisters the control interface connection as a monitor for
+ * wpa_supplicant/hostapd events, i.e., cancels the registration done with
+ * wpa_ctrl_attach().
+ */
+int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_recv - Receive a pending control interface message
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * @reply: Buffer for the message data
+ * @reply_len: Length of the reply buffer
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function will receive a pending control interface message. This
+ * function will block if no messages are available. The received response will
+ * be written to reply and reply_len is set to the actual length of the reply.
+ * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
+ * must have been used to register the control interface as an event monitor.
+ */
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
+
+
+/**
+ * wpa_ctrl_pending - Check whether there are pending event messages
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 1 if there are pending messages, 0 if no, or -1 on error
+ *
+ * This function will check whether there are any pending control interface
+ * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
+ * only used for event messages, i.e., wpa_ctrl_attach() must have been used to
+ * register the control interface as an event monitor.
+ */
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_get_fd - Get file descriptor used by the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: File descriptor used for the connection
+ *
+ * This function can be used to get the file descriptor that is used for the
+ * control interface connection. The returned value can be used, e.g., with
+ * select() while waiting for multiple events.
+ *
+ * The returned file descriptor must not be used directly for sending or
+ * receiving packets; instead, the library functions wpa_ctrl_request() and
+ * wpa_ctrl_recv() must be used for this.
+ */
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define WPA_CTRL_IFACE_PORT 9877
+#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* WPA_CTRL_H */
-- 
1.5.6.3


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to