source: mainline/uspace/app/wifi_supplicant/wifi_supplicant.c@ 8e3498b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8e3498b was 38d150e, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Prefer to get memory allocation functions through the standard stdlib header.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2015 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup nic
30 * @{
31 */
32/** @file WiFi device configuration utility.
33 *
34 */
35
36#include <ieee80211_iface.h>
37
38#include <inet/inetcfg.h>
39#include <inet/dhcp.h>
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <loc.h>
44
45#define NAME "wifi_supplicant"
46
47#define enum_name(name_arr, i) \
48 ((i < 0) ? "NA" : name_arr[i])
49
50static const char* ieee80211_security_type_strs[] = {
51 "OPEN", "WEP", "WPA", "WPA2"
52};
53
54static const char* ieee80211_security_alg_strs[] = {
55 "WEP40", "WEP104", "CCMP", "TKIP"
56};
57
58static const char* ieee80211_security_auth_strs[] = {
59 "PSK", "8021X"
60};
61
62static void print_syntax(void)
63{
64 printf("syntax:\n");
65 printf("\t" NAME " [<cmd> [<args...>]]\n");
66 printf("\t<cmd> is:\n");
67 printf("\tlist - list wifi devices in <index>: <name> format\n");
68 printf("\tscan <index> [-n] - output scan results (force scan "
69 "immediately)\n");
70 printf("\tconnect <index> <ssid_prefix> [<password>] - connect to "
71 "network\n");
72 printf("\tdisconnect <index> - disconnect from network\n");
73}
74
75static char *nic_addr_format(nic_address_t *addr)
76{
77 char *str;
78 int rc = asprintf(&str, "%02x:%02x:%02x:%02x:%02x:%02x",
79 addr->address[0], addr->address[1], addr->address[2],
80 addr->address[3], addr->address[4], addr->address[5]);
81
82 if (rc < 0)
83 return NULL;
84
85 return str;
86}
87
88static int get_wifi_list(service_id_t **wifis, size_t *count)
89{
90 category_id_t wifi_cat;
91 int rc = loc_category_get_id("ieee80211", &wifi_cat, 0);
92 if (rc != EOK) {
93 printf("Error resolving category 'ieee80211'.\n");
94 return rc;
95 }
96
97 rc = loc_category_get_svcs(wifi_cat, wifis, count);
98 if (rc != EOK) {
99 printf("Error getting list of WIFIs.\n");
100 return rc;
101 }
102
103 return EOK;
104}
105
106static async_sess_t *get_wifi_by_index(size_t i)
107{
108 service_id_t *wifis = NULL;
109 size_t count;
110
111 int rc = get_wifi_list(&wifis, &count);
112 if (rc != EOK) {
113 printf("Error fetching wifi list.\n");
114 return NULL;
115 }
116
117 if (i >= count) {
118 printf("Invalid wifi index.\n");
119 free(wifis);
120 return NULL;
121 }
122
123 async_sess_t *sess =
124 loc_service_connect(wifis[i], INTERFACE_DDF, 0);
125 if (sess == NULL) {
126 printf("Error connecting to service.\n");
127 free(wifis);
128 return NULL;
129 }
130
131 return sess;
132}
133
134static int wifi_list(void)
135{
136 service_id_t *wifis = NULL;
137 size_t count;
138
139 int rc = get_wifi_list(&wifis, &count);
140 if (rc != EOK) {
141 printf("Error fetching wifi list.\n");
142 return EINVAL;
143 }
144
145 printf("[Index]: [Service Name]\n");
146 for (size_t i = 0; i < count; i++) {
147 char *svc_name;
148 rc = loc_service_get_name(wifis[i], &svc_name);
149 if (rc != EOK) {
150 printf("Error getting service name.\n");
151 free(wifis);
152 return rc;
153 }
154
155 printf("%zu: %s\n", i, svc_name);
156
157 free(svc_name);
158 }
159
160 return EOK;
161}
162
163static int wifi_connect(uint32_t index, char *ssid_start, char *password)
164{
165 assert(ssid_start);
166
167 async_sess_t *sess = get_wifi_by_index(index);
168 if (sess == NULL) {
169 printf("Specified WIFI doesn't exist or cannot connect to "
170 "it.\n");
171 return EINVAL;
172 }
173
174 int rc = ieee80211_disconnect(sess);
175 if(rc != EOK) {
176 if (rc == EREFUSED)
177 printf("Device is not ready yet.\n");
178 else
179 printf("Error when disconnecting device. "
180 "Error: %d\n", rc);
181
182 return rc;
183 }
184
185 rc = ieee80211_connect(sess, ssid_start, password);
186 if(rc != EOK) {
187 if (rc == EREFUSED)
188 printf("Device is not ready yet.\n");
189 else if (rc == ETIMEOUT)
190 printf("Timeout when authenticating to network.\n");
191 else if (rc == ENOENT)
192 printf("Given SSID not in scan results.\n");
193 else
194 printf("Error when connecting to network. "
195 "Error: %d\n", rc);
196
197 return rc;
198 }
199
200 // TODO: Wait for DHCP address?
201
202 printf("Successfully connected to network!\n");
203
204 return EOK;
205}
206
207static int wifi_disconnect(uint32_t index)
208{
209 async_sess_t *sess = get_wifi_by_index(index);
210 if (sess == NULL) {
211 printf("Specified WIFI doesn't exist or cannot connect to "
212 "it.\n");
213 return EINVAL;
214 }
215
216 int rc = ieee80211_disconnect(sess);
217 if (rc != EOK) {
218 if (rc == EREFUSED)
219 printf("Device is not ready yet.\n");
220 else if (rc == EINVAL)
221 printf("Not connected to any WiFi network.\n");
222 else
223 printf("Error when disconnecting from network. "
224 "Error: %d\n", rc);
225
226 return rc;
227 }
228
229 printf("Successfully disconnected.\n");
230
231 return EOK;
232}
233
234static int wifi_scan(uint32_t index, bool now)
235{
236 async_sess_t *sess = get_wifi_by_index(index);
237 if (sess == NULL) {
238 printf("Specified WIFI doesn't exist or cannot connect to "
239 "it.\n");
240 return EINVAL;
241 }
242
243 ieee80211_scan_results_t scan_results;
244 int rc = ieee80211_get_scan_results(sess, &scan_results, now);
245 if (rc != EOK) {
246 if (rc == EREFUSED)
247 printf("Device is not ready yet.\n");
248 else
249 printf("Failed to fetch scan results. Error: %d\n", rc);
250
251 return rc;
252 }
253
254 if (scan_results.length == 0)
255 return EOK;
256
257 printf("%16.16s %17s %4s %5s %5s %7s %7s\n",
258 "SSID", "MAC", "CHAN", "TYPE", "AUTH", "UNI-ALG", "GRP-ALG");
259
260 for (uint8_t i = 0; i < scan_results.length; i++) {
261 ieee80211_scan_result_t result = scan_results.results[i];
262
263 printf("%16.16s %17s %4d %5s %5s %7s %7s\n",
264 result.ssid, nic_addr_format(&result.bssid),
265 result.channel,
266 enum_name(ieee80211_security_type_strs, result.security.type),
267 enum_name(ieee80211_security_auth_strs, result.security.auth),
268 enum_name(ieee80211_security_alg_strs, result.security.pair_alg),
269 enum_name(ieee80211_security_alg_strs, result.security.group_alg));
270 }
271
272 return EOK;
273}
274
275int main(int argc, char *argv[])
276{
277 int rc = inetcfg_init();
278 if (rc != EOK) {
279 printf("%s: Failed connecting to inetcfg service (%d).\n",
280 NAME, rc);
281 return 1;
282 }
283
284 rc = dhcp_init();
285 if (rc != EOK) {
286 printf("%s: Failed connecting to dhcp service (%d).\n",
287 NAME, rc);
288 return 1;
289 }
290
291 if (argc == 2) {
292 if (!str_cmp(argv[1], "list"))
293 return wifi_list();
294 } else if (argc > 2) {
295 uint32_t index;
296 rc = str_uint32_t(argv[2], NULL, 10, false, &index);
297 if (rc != EOK) {
298 printf("%s: Invalid argument.\n", NAME);
299 print_syntax();
300 return EINVAL;
301 }
302
303 if (!str_cmp(argv[1], "scan")) {
304 bool now = false;
305 if (argc > 3)
306 if (!str_cmp(argv[3], "-n"))
307 now = true;
308
309 return wifi_scan(index, now);
310 } else if (!str_cmp(argv[1], "connect")) {
311 char *pass = NULL;
312 if (argc > 3) {
313 if (argc > 4)
314 pass = argv[4];
315
316 return wifi_connect(index, argv[3], pass);
317 }
318 } else if (!str_cmp(argv[1], "disconnect"))
319 return wifi_disconnect(index);
320 }
321
322 print_syntax();
323
324 return EOK;
325}
326
327/** @}
328 */
Note: See TracBrowser for help on using the repository browser.