diff options
Diffstat (limited to 'mdk-stage1')
-rw-r--r-- | mdk-stage1/Makefile | 2 | ||||
-rw-r--r-- | mdk-stage1/network.c | 17 | ||||
-rw-r--r-- | mdk-stage1/wireless.c | 157 | ||||
-rw-r--r-- | mdk-stage1/wireless.h | 22 |
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 |