You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

337 lines
9.0 KiB

  1. /* Wireless support using iwlib for netcfg.
  2. * (C) 2004 Joshua Kwan, Bastian Blank
  3. *
  4. * Licensed under the GNU General Public License
  5. */
  6. #include "netcfg.h"
  7. #ifdef WIRELESS
  8. #include <debian-installer/log.h>
  9. #include <iwlib.h>
  10. #include <sys/types.h>
  11. #include <assert.h>
  12. #define ENTER_MANUALLY 10
  13. int is_wireless_iface (const char* if_name)
  14. {
  15. wireless_config wc;
  16. return (iw_get_basic_config (wfd, (char*)if_name, &wc) == 0);
  17. }
  18. void free_network_list(wireless_scan **network_list)
  19. {
  20. wireless_scan *old, *network;
  21. if (network_list == NULL) {
  22. return;
  23. }
  24. for (network = *network_list; network; ) {
  25. old = network;
  26. network = network->next;
  27. free(old);
  28. }
  29. *network_list = NULL;
  30. }
  31. int netcfg_wireless_choose_essid_manually(struct debconfclient *client,
  32. struct netcfg_interface *interface, char *question)
  33. {
  34. wireless_config wconf;
  35. iw_get_basic_config (wfd, interface->name, &wconf);
  36. debconf_subst(client, question, "iface", interface->name);
  37. debconf_subst(client, "netcfg/wireless_adhoc_managed", "iface", interface->name);
  38. if (debconf_go(client) == CMD_GOBACK) {
  39. debconf_fset(client, question, "seen", "false");
  40. return GO_BACK;
  41. }
  42. debconf_get(client, "netcfg/wireless_adhoc_managed");
  43. if (!strcmp(client->value, "Ad-hoc network (Peer to peer)")) {
  44. interface->mode = ADHOC;
  45. }
  46. wconf.has_mode = 1;
  47. wconf.mode = interface->mode;
  48. get_essid:
  49. debconf_input(client, "high", question);
  50. if (debconf_go(client) == CMD_GOBACK) {
  51. return GO_BACK;
  52. }
  53. debconf_get(client, question);
  54. if (client->value && strlen(client->value) > IW_ESSID_MAX_SIZE) {
  55. char max_len_string[5];
  56. sprintf(max_len_string, "%d", IW_ESSID_MAX_SIZE);
  57. debconf_capb(client, "");
  58. debconf_subst(client, "netcfg/invalid_essid", "essid", client->value);
  59. debconf_subst(client, "netcfg/invalid_essid", "max_essid_len",
  60. max_len_string);
  61. debconf_input(client, "critical", "netcfg/invalid_essid");
  62. debconf_go(client);
  63. debconf_fset(client, question, "seen", "false");
  64. debconf_capb(client, "backup");
  65. goto get_essid;
  66. }
  67. interface->essid = strdup(client->value);
  68. memset(wconf.essid, 0, IW_ESSID_MAX_SIZE + 1);
  69. snprintf(wconf.essid, IW_ESSID_MAX_SIZE + 1, "%s", interface->essid);
  70. wconf.has_essid = 1;
  71. wconf.essid_on = 1;
  72. iw_set_basic_config(wfd, interface->name, &wconf);
  73. di_info("Network chosen: %s. Proceeding to connect.", interface->essid);
  74. return 0;
  75. }
  76. int exists_in_network_list(wireless_scan_head list, wireless_scan *network)
  77. {
  78. wireless_scan *it;
  79. for (it = list.result; it != network; it = it->next) {
  80. if (strcmp(it->b.essid, network->b.essid) == 0) {
  81. return 1;
  82. }
  83. }
  84. return 0;
  85. }
  86. int netcfg_wireless_show_essids(struct debconfclient *client, struct netcfg_interface *interface)
  87. {
  88. wireless_scan_head network_list;
  89. wireless_config wconf;
  90. char *buffer;
  91. int essid_list_len = 1;
  92. iw_get_basic_config (wfd, interface->name, &wconf);
  93. interface_up(interface->name);
  94. if (iw_scan(wfd, interface->name, iw_get_kernel_we_version(),
  95. &network_list) >= 0 ) {
  96. wireless_scan *network;
  97. di_info("Scan of wireless interface %s succeeded.", interface->name);
  98. /* Determine the actual length of the buffer. */
  99. for (network = network_list.result; network; network =
  100. network->next) {
  101. if (!exists_in_network_list(network_list, network)) {
  102. essid_list_len += (strlen(network->b.essid) + 2);
  103. }
  104. }
  105. /* Buffer initialization. */
  106. buffer = malloc(essid_list_len * sizeof(char));
  107. if (buffer == NULL) {
  108. /* Error in memory allocation. */
  109. di_warning("Unable to allocate memory for network list buffer.");
  110. return ENTER_MANUALLY;
  111. }
  112. strcpy(buffer, "");
  113. /* Create list of available ESSIDs. */
  114. for (network = network_list.result; network; network = network->next) {
  115. if (!exists_in_network_list(network_list, network)) {
  116. strcat(buffer, network->b.essid);
  117. strcat(buffer, ", ");
  118. }
  119. }
  120. /* Asking the user. */
  121. debconf_capb(client, "backup");
  122. debconf_subst(client, "netcfg/wireless_show_essids", "essid_list", buffer);
  123. debconf_fset(client, "netcfg/wireless_show_essids", "seen", "false");
  124. debconf_input(client, "high", "netcfg/wireless_show_essids");
  125. if (debconf_go(client) == CMD_GOBACK) {
  126. debconf_fset(client, "netcfg/wireless_show_essids", "seen",
  127. "false");
  128. free_network_list(&network_list.result);
  129. free(buffer);
  130. return GO_BACK;
  131. }
  132. debconf_get(client, "netcfg/wireless_show_essids");
  133. /* User wants to enter an ESSID manually. */
  134. if (strcmp(client->value, "manual") == 0) {
  135. free_network_list(&network_list.result);
  136. free(buffer);
  137. return ENTER_MANUALLY;
  138. }
  139. /* User has chosen a network from the list, need to find which one and
  140. * get its cofiguration. */
  141. for (network = network_list.result; network; network = network->next) {
  142. if (strcmp(network->b.essid, client->value) == 0) {
  143. wconf = network->b;
  144. interface->essid = strdup(network->b.essid);
  145. break;
  146. }
  147. }
  148. /* Free the network list. */
  149. free_network_list(&network_list.result);
  150. free(buffer);
  151. }
  152. else {
  153. /* Go directly to choosing manually, use the wireless_essid_again
  154. * question. */
  155. if (netcfg_wireless_choose_essid_manually(client, interface,
  156. "netcfg/wireless_essid_again") == GO_BACK) {
  157. return GO_BACK;
  158. }
  159. return 0;
  160. }
  161. iw_set_basic_config(wfd, interface->name, &wconf);
  162. interface_down(interface->name);
  163. di_info("Network chosen: %s. Proceeding to connect.", interface->essid);
  164. return 0;
  165. }
  166. int netcfg_wireless_set_essid(struct debconfclient *client, struct netcfg_interface *interface)
  167. {
  168. wireless_config wconf;
  169. int choose_ret;
  170. select_essid:
  171. iw_get_basic_config(wfd, interface->name, &wconf);
  172. choose_ret = netcfg_wireless_show_essids(client, interface);
  173. if (choose_ret == GO_BACK) {
  174. return GO_BACK;
  175. }
  176. if (choose_ret == ENTER_MANUALLY) {
  177. if (netcfg_wireless_choose_essid_manually(client, interface,
  178. "netcfg/wireless_essid") == GO_BACK) {
  179. goto select_essid;
  180. }
  181. }
  182. return 0;
  183. }
  184. static void unset_wep_key (const char *if_name)
  185. {
  186. wireless_config wconf;
  187. iw_get_basic_config(wfd, if_name, &wconf);
  188. wconf.has_key = 1;
  189. wconf.key[0] = '\0';
  190. wconf.key_flags = IW_ENCODE_DISABLED | IW_ENCODE_NOKEY;
  191. wconf.key_size = 0;
  192. iw_set_basic_config (wfd, if_name, &wconf);
  193. }
  194. int netcfg_wireless_set_wep (struct debconfclient * client, struct netcfg_interface *interface)
  195. {
  196. wireless_config wconf;
  197. char* rv = NULL;
  198. int ret, keylen, err = 0;
  199. unsigned char buf [IW_ENCODING_TOKEN_MAX + 1];
  200. struct iwreq wrq;
  201. iw_get_basic_config (wfd, interface->name, &wconf);
  202. debconf_subst(client, "netcfg/wireless_wep", "iface", interface->name);
  203. debconf_input (client, "high", "netcfg/wireless_wep");
  204. ret = debconf_go(client);
  205. if (ret == CMD_GOBACK)
  206. return GO_BACK;
  207. debconf_get(client, "netcfg/wireless_wep");
  208. rv = client->value;
  209. if (empty_str(rv)) {
  210. unset_wep_key (interface->name);
  211. if (interface->wepkey != NULL) {
  212. free(interface->wepkey);
  213. interface->wepkey = NULL;
  214. }
  215. return 0;
  216. }
  217. while ((keylen = iw_in_key (rv, buf)) == -1) {
  218. debconf_subst(client, "netcfg/invalid_wep", "wepkey", rv);
  219. debconf_input(client, "critical", "netcfg/invalid_wep");
  220. debconf_go(client);
  221. debconf_input (client, "high", "netcfg/wireless_wep");
  222. ret = debconf_go(client);
  223. if (ret == CMD_GOBACK)
  224. return GO_BACK;
  225. debconf_get(client, "netcfg/wireless_wep");
  226. rv = client->value;
  227. }
  228. /* Now rv is safe to store since it parsed fine */
  229. interface->wepkey = strdup(rv);
  230. wrq.u.data.pointer = buf;
  231. wrq.u.data.flags = 0;
  232. wrq.u.data.length = keylen;
  233. if ((err = iw_set_ext(skfd, interface->name, SIOCSIWENCODE, &wrq)) < 0) {
  234. di_warning("setting WEP key on %s failed with code %d", interface->name, err);
  235. return -1;
  236. }
  237. return 0;
  238. }
  239. #else
  240. int is_wireless_iface (const char *if_name)
  241. {
  242. (void) if_name;
  243. return 0;
  244. }
  245. int netcfg_wireless_set_essid (struct debconfclient *client, struct netcfg_interface *interface)
  246. {
  247. (void) client;
  248. (void) interface;
  249. return 0;
  250. }
  251. int netcfg_wireless_set_wep (struct debconfclient *client, struct netcfg_interface *interface)
  252. {
  253. (void) client;
  254. (void) interface;
  255. return 0;
  256. }
  257. #endif