summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdk-stage1/Makefile2
-rw-r--r--mdk-stage1/network.c17
-rw-r--r--mdk-stage1/wireless.c157
-rw-r--r--mdk-stage1/wireless.h22
4 files changed, 194 insertions, 4 deletions
diff --git a/mdk-stage1/Makefile b/mdk-stage1/Makefile
index 235560454..3caf6989b 100644
--- a/mdk-stage1/Makefile
+++ b/mdk-stage1/Makefile
@@ -113,7 +113,7 @@ endif
STAGE1SRC = stage1.c log.c tools.c modules.c probing.c mount.c automatic.c frontend-common.c lomount.c thirdparty.c
CDROMSRC = cdrom.c
DISKSRC = disk.c directory.c partition.c
-NETWORKSRC = network.c nfsmount.c dhcp.c url.c dns.c adsl.c directory.c
+NETWORKSRC = network.c nfsmount.c dhcp.c url.c dns.c adsl.c directory.c wireless.c
# use sort to remove duplicates
STAGE1_ALLSRC = $(sort $(STAGE1SRC) $(CDROMSRC) $(DISKSRC) $(NETWORKSRC))
diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c
index a3ff5e696..351edc8d3 100644
--- a/mdk-stage1/network.c
+++ b/mdk-stage1/network.c
@@ -46,6 +46,7 @@
#include "network.h"
#include "directory.h"
+#include "wireless.h"
/* include it after config-stage1.h so that _GNU_SOURCE is defined and strndup is available */
#include <string.h>
@@ -558,17 +559,27 @@ static enum return_type configure_network(struct interface_info * intf)
static enum return_type bringup_networking(struct interface_info * intf)
{
static struct interface_info loopback;
- enum return_type results = RETURN_ERROR;
+ enum return_type results;
my_insmod("af_packet", ANY_DRIVER_TYPE, NULL, 1);
- while (results != RETURN_OK) {
+ do {
+ results = configure_wireless(intf->device);
+ } while (results == RETURN_ERROR);
+
+ if (results == RETURN_BACK)
+ return RETURN_BACK;
+
+ do {
results = setup_network_interface(intf);
if (results != RETURN_OK)
return results;
write_resolvconf();
results = configure_network(intf);
- }
+ } while (results == RETURN_ERROR);
+
+ if (results == RETURN_BACK)
+ return bringup_networking(intf);
write_resolvconf(); /* maybe we have now domain to write also */
diff --git a/mdk-stage1/wireless.c b/mdk-stage1/wireless.c
new file mode 100644
index 000000000..ba3224468
--- /dev/null
+++ b/mdk-stage1/wireless.c
@@ -0,0 +1,157 @@
+/*
+ * Olivier Blin (oblin@mandriva.com)
+ *
+ * Copyright 2005 Mandriva
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/wireless.h>
+
+#include "automatic.h"
+#include "stage1.h"
+#include "log.h"
+#include "wireless.h"
+
+static int wireless_open_socket();
+static int wireless_close_socket(int socket);
+static int wireless_ioctl(int socket, const char *ifname, int request, struct iwreq *wrq);
+static int wireless_is_aware(int socket, const char *ifname);
+static int wireless_set_mode_managed(int socket, const char *ifname);
+static int wireless_disable_key(int socket, const char *ifname);
+static int wireless_set_restricted_key(int socket, const char *ifname, const char *key);
+static int wireless_set_essid(int socket, const char *ifname, const char *essid);
+
+static int wireless_open_socket()
+{
+ return socket(AF_INET, SOCK_DGRAM, 0);
+}
+
+static int wireless_close_socket(int socket)
+{
+ return close(socket);
+}
+
+static int wireless_ioctl(int socket, const char *ifname, int request, struct iwreq *wrq)
+{
+ strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
+ return ioctl(socket, request, wrq);
+}
+
+static int wireless_is_aware(int socket, const char *ifname)
+{
+ struct iwreq wrq;
+ return wireless_ioctl(socket, ifname, SIOCGIWNAME, &wrq) == 0;
+}
+
+static int wireless_set_mode_managed(int socket, const char *ifname)
+{
+ struct iwreq wrq;
+
+ wrq.u.mode = IW_MODE_INFRA; /* managed */
+
+ return wireless_ioctl(socket, ifname, SIOCSIWMODE, &wrq) == 0;
+}
+
+static int wireless_set_essid(int socket, const char *ifname, const char *essid)
+{
+ struct iwreq wrq;
+
+ wrq.u.essid.flags = 1;
+ wrq.u.essid.pointer = (void *) essid;
+ wrq.u.essid.length = strlen(essid) + 1;
+
+ return wireless_ioctl(socket, ifname, SIOCSIWESSID, &wrq) == 0;
+}
+
+static int wireless_disable_key(int socket, const char *ifname)
+{
+ struct iwreq wrq;
+
+ wrq.u.data.flags = IW_ENCODE_DISABLED;
+ wrq.u.data.pointer = NULL;
+ wrq.u.data.length = 0;
+
+ return wireless_ioctl(socket, ifname, SIOCSIWENCODE, &wrq) == 0;
+}
+
+static int wireless_set_restricted_key(int socket, const char *ifname, const char *key)
+{
+ struct iwreq wrq;
+ char real_key[IW_ENCODING_TOKEN_MAX];
+ int key_len = 0;
+ unsigned int tmp;
+
+ while (sscanf(key + key_len, "%2X", &tmp) == 1)
+ real_key[key_len++] = (unsigned char) tmp;
+
+ wrq.u.data.flags = IW_ENCODE_RESTRICTED;
+ wrq.u.data.pointer = (char *) real_key;
+ wrq.u.data.length = key_len;
+
+ return wireless_ioctl(socket, ifname, SIOCSIWENCODE, &wrq) == 0;
+}
+
+enum return_type configure_wireless(const char *ifname)
+{
+ enum return_type results;
+ char * questions[] = { "ESSID", "WEP key", NULL };
+ char * questions_auto[] = { "essid", "wep_key" };
+ static char ** answers = NULL;
+ int wsock = wireless_open_socket();
+
+ if (!wireless_is_aware(wsock, ifname)) {
+ log_message("interface %s doesn't support wireless", ifname);
+ wireless_close_socket(wsock);
+ return RETURN_OK;
+ }
+
+ results = ask_from_entries_auto("Please enter your wireless settings.",
+ questions, &answers, 32, questions_auto, NULL);
+ if (results != RETURN_OK) {
+ wireless_close_socket(wsock);
+ return RETURN_BACK;
+ }
+
+ if (!wireless_set_mode_managed(wsock, ifname)) {
+ stg1_error_message("unable to set mode Managed on device \"%s\": %s", ifname, strerror(errno));
+ wireless_close_socket(wsock);
+ return RETURN_ERROR;
+ }
+
+ log_message("setting ESSID \"%s\" on device \"%s\"", answers[0], ifname);
+ if (!wireless_set_essid(wsock, ifname, answers[0])) {
+ stg1_error_message("unable to set ESSID \"%s\" on device \"%s\": %s", answers[0], ifname, strerror(errno));
+ return RETURN_ERROR;
+ }
+
+ if (answers[1] && !streq(answers[1], "")) {
+ log_message("setting WEP key \"%s\" on device \"%s\"", answers[1], ifname);
+ if (!wireless_set_restricted_key(wsock, ifname, answers[1])) {
+ stg1_error_message("unable to set WEP key \"%s\" on device \"%s\": %s", answers[1], ifname, strerror(errno));
+ return RETURN_ERROR;
+ }
+ } else {
+ log_message("disabling WEP key on device \"%s\"", ifname);
+ if (!wireless_disable_key(wsock, ifname)) {
+ stg1_error_message("unable to disable WEP key on device \"%s\": %s", ifname, strerror(errno));
+ return RETURN_ERROR;
+ }
+ }
+
+ wireless_close_socket(wsock);
+ return RETURN_OK;
+}
diff --git a/mdk-stage1/wireless.h b/mdk-stage1/wireless.h
new file mode 100644
index 000000000..36f247b23
--- /dev/null
+++ b/mdk-stage1/wireless.h
@@ -0,0 +1,22 @@
+/*
+ * Olivier Blin (oblin@mandriva.com)
+ *
+ * Copyright 2005 Mandriva
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _WIRELESS_H_
+#define _WIRELESS_H_
+
+#include "frontend.h"
+
+enum return_type configure_wireless(const char *ifname);
+
+#endif