/* * Olivier Blin (oblin) * * 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/types.h> #include <linux/if.h> #include <linux/wireless.h> #include "automatic.h" #include "stage1.h" #include "log.h" #include "utils.h" #include "wireless.h" static int wireless_ioctl(int socket, const char *ifname, int request, struct iwreq *wrq); 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); int wireless_open_socket() { return socket(AF_INET, SOCK_DGRAM, 0); } 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); } 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 + 2*key_len, "%2X", &tmp) == 1) real_key[key_len++] = (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. " "The ESSID is your wireless network identifier. " "The WEP key must be entered in hexadecimal, without any separator.", 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; } 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; } } /* most devices perform discovery when ESSID is set, it needs to be last */ 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; } wireless_close_socket(wsock); return RETURN_OK; }