/* Wireless support using iwlib for netcfg. * (C) 2004 Joshua Kwan, Bastian Blank * * Licensed under the GNU General Public License */ #include "netcfg.h" #ifdef WIRELESS #include #include #include #include #endif /* Wireless mode */ wifimode_t mode = MANAGED; /* wireless config */ char* wepkey = NULL; char* essid = NULL; #ifdef WIRELESS int is_wireless_iface (const char* iface) { wireless_config wc; return (iw_get_basic_config (wfd, (char*)iface, &wc) == 0); } int netcfg_wireless_set_essid (struct debconfclient * client, char *iface, char* priority) { int ret, couldnt_associate = 0; wireless_config wconf; char* tf = NULL, *user_essid = NULL, *ptr = wconf.essid; iw_get_basic_config (wfd, iface, &wconf); debconf_subst(client, "netcfg/wireless_essid", "iface", iface); debconf_subst(client, "netcfg/wireless_essid_again", "iface", iface); debconf_subst(client, "netcfg/wireless_adhoc_managed", "iface", iface); debconf_input(client, priority ? priority : "low", "netcfg/wireless_adhoc_managed"); if (debconf_go(client) == 30) return GO_BACK; debconf_get(client, "netcfg/wireless_adhoc_managed"); if (!strcmp(client->value, "Ad-hoc network (Peer to peer)")) mode = ADHOC; wconf.has_mode = 1; wconf.mode = mode; debconf_input(client, priority ? priority : "low", "netcfg/wireless_essid"); if (debconf_go(client) == 30) return GO_BACK; debconf_get(client, "netcfg/wireless_essid"); tf = strdup(client->value); automatic: /* question not asked or user doesn't care or we're successfully associated */ if (!empty_str(wconf.essid) || empty_str(client->value)) { int i, success = 0; /* Default to any AP */ wconf.essid[0] = '\0'; wconf.essid_on = 0; iw_set_basic_config (wfd, iface, &wconf); /* Wait for association.. (MAX_SECS seconds)*/ #define MAX_SECS 3 debconf_capb(client, "backup progresscancel"); debconf_progress_start(client, 0, MAX_SECS, "netcfg/wifi_progress_title"); if (debconf_progress_info(client, "netcfg/wifi_progress_info") == 30) goto stop; netcfg_progress_displayed = 1; for (i = 0; i <= MAX_SECS; i++) { int progress_ret; interface_up(iface); sleep (1); iw_get_basic_config (wfd, iface, &wconf); if (!empty_str(wconf.essid)) { /* Save for later */ debconf_set(client, "netcfg/wireless_essid", wconf.essid); debconf_progress_set(client, MAX_SECS); success = 1; break; } progress_ret = debconf_progress_step(client, 1); interface_down(iface); if (progress_ret == 30) break; } stop: debconf_progress_stop(client); debconf_capb(client, "backup"); netcfg_progress_displayed = 0; if (success) return 0; couldnt_associate = 1; } /* yes, wants to set an essid by himself */ if (strlen(tf) <= IW_ESSID_MAX_SIZE) /* looks ok, let's use it */ user_essid = tf; while (!user_essid || empty_str(user_essid) || strlen(user_essid) > IW_ESSID_MAX_SIZE) { /* Misnomer of a check. Basically, if we went through autodetection, * we want to enter this loop, but we want to suppress anything that * relied on the checking of tf/user_essid (i.e. "", in most cases.) */ if (!couldnt_associate) { debconf_subst(client, "netcfg/invalid_essid", "essid", user_essid); debconf_input(client, "high", "netcfg/invalid_essid"); debconf_go(client); } if (couldnt_associate) ret = debconf_input(client, "critical", "netcfg/wireless_essid_again"); else ret = debconf_input(client, "low", "netcfg/wireless_essid"); /* we asked the question once, why can't we ask it again? */ if (ret == 30) /* maybe netcfg/wireless_essid was preseeded; if so, give up */ break; if (debconf_go(client) == 30) /* well, we did, but he wants to go back */ return GO_BACK; if (couldnt_associate) debconf_get(client, "netcfg/wireless_essid_again"); else debconf_get(client, "netcfg/wireless_essid"); if (empty_str(client->value)) { if (couldnt_associate) /* we've already tried the empty string here, so give up */ break; else goto automatic; } /* But now we'd not like to suppress any MORE errors */ couldnt_associate = 0; free(user_essid); user_essid = strdup(client->value); } essid = user_essid; memset(ptr, 0, IW_ESSID_MAX_SIZE + 1); snprintf(wconf.essid, IW_ESSID_MAX_SIZE + 1, "%s", essid); wconf.has_essid = 1; wconf.essid_on = 1; iw_set_basic_config (wfd, iface, &wconf); return 0; } static void unset_wep_key (char* iface) { wireless_config wconf; int ret; iw_get_basic_config(wfd, iface, &wconf); wconf.has_key = 1; wconf.key[0] = '\0'; wconf.key_flags = IW_ENCODE_DISABLED | IW_ENCODE_NOKEY; wconf.key_size = 0; ret = iw_set_basic_config (wfd, iface, &wconf); } int netcfg_wireless_set_wep (struct debconfclient * client, char* iface) { wireless_config wconf; char* rv = NULL; int ret, keylen, err = 0; unsigned char buf [IW_ENCODING_TOKEN_MAX + 1]; struct iwreq wrq; iw_get_basic_config (wfd, iface, &wconf); debconf_subst(client, "netcfg/wireless_wep", "iface", iface); debconf_input (client, "high", "netcfg/wireless_wep"); ret = debconf_go(client); if (ret == 30) return GO_BACK; debconf_get(client, "netcfg/wireless_wep"); rv = client->value; if (empty_str(rv)) { unset_wep_key (iface); if (wepkey != NULL) { free(wepkey); wepkey = NULL; } return 0; } while ((keylen = iw_in_key (rv, buf)) == -1) { debconf_subst(client, "netcfg/invalid_wep", "wepkey", rv); debconf_input(client, "critical", "netcfg/invalid_wep"); debconf_go(client); debconf_input (client, "high", "netcfg/wireless_wep"); ret = debconf_go(client); if (ret == 30) return GO_BACK; debconf_get(client, "netcfg/wireless_wep"); rv = client->value; } /* Now rv is safe to store since it parsed fine */ wepkey = strdup(rv); wrq.u.data.pointer = buf; wrq.u.data.flags = 0; wrq.u.data.length = keylen; if ((err = iw_set_ext(skfd, iface, SIOCSIWENCODE, &wrq)) < 0) { di_warning("setting WEP key on %s failed with code %d", iface, err); return -1; } return 0; } #else int is_wireless_iface (const char *iface) { (void) iface; return 0; } int netcfg_wireless_set_essid (struct debconfclient *client, char *iface, char *priority) { (void) client; (void) iface; (void) priority; return 0; } int netcfg_wireless_set_wep (struct debconfclient *client, char *iface) { (void) client; (void) iface; return 0; } #endif