~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to wpa_cli.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant - command line interface for wpa_supplicant daemon
3
 
 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#include "includes.h"
16
 
 
17
 
#ifdef CONFIG_CTRL_IFACE
18
 
 
19
 
#ifdef CONFIG_CTRL_IFACE_UNIX
20
 
#include <dirent.h>
21
 
#endif /* CONFIG_CTRL_IFACE_UNIX */
22
 
#ifdef CONFIG_READLINE
23
 
#include <readline/readline.h>
24
 
#include <readline/history.h>
25
 
#endif /* CONFIG_READLINE */
26
 
 
27
 
#include "wpa_ctrl.h"
28
 
#include "common.h"
29
 
#include "version.h"
30
 
 
31
 
 
32
 
static const char *wpa_cli_version =
33
 
"wpa_cli v" VERSION_STR "\n"
34
 
"Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> and contributors";
35
 
 
36
 
 
37
 
static const char *wpa_cli_license =
38
 
"This program is free software. You can distribute it and/or modify it\n"
39
 
"under the terms of the GNU General Public License version 2.\n"
40
 
"\n"
41
 
"Alternatively, this software may be distributed under the terms of the\n"
42
 
"BSD license. See README and COPYING for more details.\n";
43
 
 
44
 
static const char *wpa_cli_full_license =
45
 
"This program is free software; you can redistribute it and/or modify\n"
46
 
"it under the terms of the GNU General Public License version 2 as\n"
47
 
"published by the Free Software Foundation.\n"
48
 
"\n"
49
 
"This program is distributed in the hope that it will be useful,\n"
50
 
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51
 
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
52
 
"GNU General Public License for more details.\n"
53
 
"\n"
54
 
"You should have received a copy of the GNU General Public License\n"
55
 
"along with this program; if not, write to the Free Software\n"
56
 
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
57
 
"\n"
58
 
"Alternatively, this software may be distributed under the terms of the\n"
59
 
"BSD license.\n"
60
 
"\n"
61
 
"Redistribution and use in source and binary forms, with or without\n"
62
 
"modification, are permitted provided that the following conditions are\n"
63
 
"met:\n"
64
 
"\n"
65
 
"1. Redistributions of source code must retain the above copyright\n"
66
 
"   notice, this list of conditions and the following disclaimer.\n"
67
 
"\n"
68
 
"2. Redistributions in binary form must reproduce the above copyright\n"
69
 
"   notice, this list of conditions and the following disclaimer in the\n"
70
 
"   documentation and/or other materials provided with the distribution.\n"
71
 
"\n"
72
 
"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73
 
"   names of its contributors may be used to endorse or promote products\n"
74
 
"   derived from this software without specific prior written permission.\n"
75
 
"\n"
76
 
"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77
 
"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78
 
"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79
 
"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80
 
"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81
 
"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82
 
"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83
 
"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84
 
"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85
 
"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86
 
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87
 
"\n";
88
 
 
89
 
static const char *commands_help =
90
 
"commands:\n"
91
 
"  status [verbose] = get current WPA/EAPOL/EAP status\n"
92
 
"  mib = get MIB variables (dot1x, dot11)\n"
93
 
"  help = show this usage help\n"
94
 
"  interface [ifname] = show interfaces/select interface\n"
95
 
"  level <debug level> = change debug level\n"
96
 
"  license = show full wpa_cli license\n"
97
 
"  logoff = IEEE 802.1X EAPOL state machine logoff\n"
98
 
"  logon = IEEE 802.1X EAPOL state machine logon\n"
99
 
"  set = set variables (shows list of variables when run without arguments)\n"
100
 
"  pmksa = show PMKSA cache\n"
101
 
"  reassociate = force reassociation\n"
102
 
"  reconfigure = force wpa_supplicant to re-read its configuration file\n"
103
 
"  preauthenticate <BSSID> = force preauthentication\n"
104
 
"  identity <network id> <identity> = configure identity for an SSID\n"
105
 
"  password <network id> <password> = configure password for an SSID\n"
106
 
"  new_password <network id> <password> = change password for an SSID\n"
107
 
"  pin <network id> <pin> = configure pin for an SSID\n"
108
 
"  otp <network id> <password> = configure one-time-password for an SSID\n"
109
 
"  passphrase <network id> <passphrase> = configure private key passphrase\n"
110
 
"    for an SSID\n"
111
 
"  bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
112
 
"  list_networks = list configured networks\n"
113
 
"  select_network <network id> = select a network (disable others)\n"
114
 
"  enable_network <network id> = enable a network\n"
115
 
"  disable_network <network id> = disable a network\n"
116
 
"  add_network = add a network\n"
117
 
"  remove_network <network id> = remove a network\n"
118
 
"  set_network <network id> <variable> <value> = set network variables "
119
 
"(shows\n"
120
 
"    list of variables when run without arguments)\n"
121
 
"  get_network <network id> <variable> = get network variables\n"
122
 
"  save_config = save the current configuration\n"
123
 
"  disconnect = disconnect and wait for reassociate command before "
124
 
"connecting\n"
125
 
"  scan = request new BSS scan\n"
126
 
"  scan_results = get latest scan results\n"
127
 
"  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
128
 
"get capabilies\n"
129
 
"  ap_scan <value> = set ap_scan parameter\n"
130
 
"  stkstart <addr> = request STK negotiation with <addr>\n"
131
 
"  terminate = terminate wpa_supplicant\n"
132
 
"  quit = exit wpa_cli\n";
133
 
 
134
 
static struct wpa_ctrl *ctrl_conn;
135
 
static int wpa_cli_quit = 0;
136
 
static int wpa_cli_attached = 0;
137
 
static int wpa_cli_connected = 0;
138
 
static int wpa_cli_last_id = 0;
139
 
static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
140
 
static char *ctrl_ifname = NULL;
141
 
static const char *pid_file = NULL;
142
 
static const char *action_file = NULL;
143
 
 
144
 
 
145
 
static void usage(void)
146
 
{
147
 
        printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
148
 
               "[-a<action file>] \\\n"
149
 
               "        [-P<pid file>] [-g<global ctrl>]  [command..]\n"
150
 
               "  -h = help (show this usage text)\n"
151
 
               "  -v = shown version information\n"
152
 
               "  -a = run in daemon mode executing the action file based on "
153
 
               "events from\n"
154
 
               "       wpa_supplicant\n"
155
 
               "  -B = run a daemon in the background\n"
156
 
               "  default path: /var/run/wpa_supplicant\n"
157
 
               "  default interface: first interface found in socket path\n"
158
 
               "%s",
159
 
               commands_help);
160
 
}
161
 
 
162
 
 
163
 
static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
164
 
{
165
 
#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
166
 
        ctrl_conn = wpa_ctrl_open(ifname);
167
 
        return ctrl_conn;
168
 
#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
169
 
        char *cfile;
170
 
        int flen;
171
 
 
172
 
        if (ifname == NULL)
173
 
                return NULL;
174
 
 
175
 
        flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
176
 
        cfile = os_malloc(flen);
177
 
        if (cfile == NULL)
178
 
                return NULL;
179
 
        os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
180
 
 
181
 
        ctrl_conn = wpa_ctrl_open(cfile);
182
 
        os_free(cfile);
183
 
        return ctrl_conn;
184
 
#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
185
 
}
186
 
 
187
 
 
188
 
static void wpa_cli_close_connection(void)
189
 
{
190
 
        if (ctrl_conn == NULL)
191
 
                return;
192
 
 
193
 
        if (wpa_cli_attached) {
194
 
                wpa_ctrl_detach(ctrl_conn);
195
 
                wpa_cli_attached = 0;
196
 
        }
197
 
        wpa_ctrl_close(ctrl_conn);
198
 
        ctrl_conn = NULL;
199
 
}
200
 
 
201
 
 
202
 
static void wpa_cli_msg_cb(char *msg, size_t len)
203
 
{
204
 
        printf("%s\n", msg);
205
 
}
206
 
 
207
 
 
208
 
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
209
 
{
210
 
        char buf[2048];
211
 
        size_t len;
212
 
        int ret;
213
 
 
214
 
        if (ctrl_conn == NULL) {
215
 
                printf("Not connected to wpa_supplicant - command dropped.\n");
216
 
                return -1;
217
 
        }
218
 
        len = sizeof(buf) - 1;
219
 
        ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
220
 
                               wpa_cli_msg_cb);
221
 
        if (ret == -2) {
222
 
                printf("'%s' command timed out.\n", cmd);
223
 
                return -2;
224
 
        } else if (ret < 0) {
225
 
                printf("'%s' command failed.\n", cmd);
226
 
                return -1;
227
 
        }
228
 
        if (print) {
229
 
                buf[len] = '\0';
230
 
                printf("%s", buf);
231
 
        }
232
 
        return 0;
233
 
}
234
 
 
235
 
 
236
 
static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
237
 
{
238
 
        return _wpa_ctrl_command(ctrl, cmd, 1);
239
 
}
240
 
 
241
 
 
242
 
static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
243
 
{
244
 
        int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
245
 
        return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
246
 
}
247
 
 
248
 
 
249
 
static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
250
 
{
251
 
        return wpa_ctrl_command(ctrl, "PING");
252
 
}
253
 
 
254
 
 
255
 
static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
256
 
{
257
 
        return wpa_ctrl_command(ctrl, "MIB");
258
 
}
259
 
 
260
 
 
261
 
static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
262
 
{
263
 
        return wpa_ctrl_command(ctrl, "PMKSA");
264
 
}
265
 
 
266
 
 
267
 
static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
268
 
{
269
 
        printf("%s", commands_help);
270
 
        return 0;
271
 
}
272
 
 
273
 
 
274
 
static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
275
 
{
276
 
        printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
277
 
        return 0;
278
 
}
279
 
 
280
 
 
281
 
static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
282
 
{
283
 
        wpa_cli_quit = 1;
284
 
        return 0;
285
 
}
286
 
 
287
 
 
288
 
static void wpa_cli_show_variables(void)
289
 
{
290
 
        printf("set variables:\n"
291
 
               "  EAPOL::heldPeriod (EAPOL state machine held period, "
292
 
               "in seconds)\n"
293
 
               "  EAPOL::authPeriod (EAPOL state machine authentication "
294
 
               "period, in seconds)\n"
295
 
               "  EAPOL::startPeriod (EAPOL state machine start period, in "
296
 
               "seconds)\n"
297
 
               "  EAPOL::maxStart (EAPOL state machine maximum start "
298
 
               "attempts)\n");
299
 
        printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
300
 
               "seconds)\n"
301
 
               "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
302
 
               " threshold\n\tpercentage)\n"
303
 
               "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
304
 
               "security\n\tassociation in seconds)\n");
305
 
}
306
 
 
307
 
 
308
 
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
309
 
{
310
 
        char cmd[256];
311
 
        int res;
312
 
 
313
 
        if (argc == 0) {
314
 
                wpa_cli_show_variables();
315
 
                return 0;
316
 
        }
317
 
 
318
 
        if (argc != 2) {
319
 
                printf("Invalid SET command: needs two arguments (variable "
320
 
                       "name and value)\n");
321
 
                return 0;
322
 
        }
323
 
 
324
 
        res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
325
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
326
 
                printf("Too long SET command.\n");
327
 
                return 0;
328
 
        }
329
 
        return wpa_ctrl_command(ctrl, cmd);
330
 
}
331
 
 
332
 
 
333
 
static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
334
 
{
335
 
        return wpa_ctrl_command(ctrl, "LOGOFF");
336
 
}
337
 
 
338
 
 
339
 
static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
340
 
{
341
 
        return wpa_ctrl_command(ctrl, "LOGON");
342
 
}
343
 
 
344
 
 
345
 
static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
346
 
                                   char *argv[])
347
 
{
348
 
        return wpa_ctrl_command(ctrl, "REASSOCIATE");
349
 
}
350
 
 
351
 
 
352
 
static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
353
 
                                       char *argv[])
354
 
{
355
 
        char cmd[256];
356
 
        int res;
357
 
 
358
 
        if (argc != 1) {
359
 
                printf("Invalid PREAUTH command: needs one argument "
360
 
                       "(BSSID)\n");
361
 
                return 0;
362
 
        }
363
 
 
364
 
        res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
365
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
366
 
                printf("Too long PREAUTH command.\n");
367
 
                return 0;
368
 
        }
369
 
        return wpa_ctrl_command(ctrl, cmd);
370
 
}
371
 
 
372
 
 
373
 
static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
374
 
{
375
 
        char cmd[256];
376
 
        int res;
377
 
 
378
 
        if (argc != 1) {
379
 
                printf("Invalid AP_SCAN command: needs one argument (ap_scan "
380
 
                       "value)\n");
381
 
                return 0;
382
 
        }
383
 
        res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
384
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
385
 
                printf("Too long AP_SCAN command.\n");
386
 
                return 0;
387
 
        }
388
 
        return wpa_ctrl_command(ctrl, cmd);
389
 
}
390
 
 
391
 
 
392
 
static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
393
 
                                char *argv[])
394
 
{
395
 
        char cmd[256];
396
 
        int res;
397
 
 
398
 
        if (argc != 1) {
399
 
                printf("Invalid STKSTART command: needs one argument "
400
 
                       "(Peer STA MAC address)\n");
401
 
                return 0;
402
 
        }
403
 
 
404
 
        res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
405
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
406
 
                printf("Too long STKSTART command.\n");
407
 
                return 0;
408
 
        }
409
 
        return wpa_ctrl_command(ctrl, cmd);
410
 
}
411
 
 
412
 
 
413
 
static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
414
 
{
415
 
        char cmd[256];
416
 
        int res;
417
 
 
418
 
        if (argc != 1) {
419
 
                printf("Invalid LEVEL command: needs one argument (debug "
420
 
                       "level)\n");
421
 
                return 0;
422
 
        }
423
 
        res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
424
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
425
 
                printf("Too long LEVEL command.\n");
426
 
                return 0;
427
 
        }
428
 
        return wpa_ctrl_command(ctrl, cmd);
429
 
}
430
 
 
431
 
 
432
 
static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
433
 
{
434
 
        char cmd[256], *pos, *end;
435
 
        int i, ret;
436
 
 
437
 
        if (argc < 2) {
438
 
                printf("Invalid IDENTITY command: needs two arguments "
439
 
                       "(network id and identity)\n");
440
 
                return 0;
441
 
        }
442
 
 
443
 
        end = cmd + sizeof(cmd);
444
 
        pos = cmd;
445
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
446
 
                          argv[0], argv[1]);
447
 
        if (ret < 0 || ret >= end - pos) {
448
 
                printf("Too long IDENTITY command.\n");
449
 
                return 0;
450
 
        }
451
 
        pos += ret;
452
 
        for (i = 2; i < argc; i++) {
453
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
454
 
                if (ret < 0 || ret >= end - pos) {
455
 
                        printf("Too long IDENTITY command.\n");
456
 
                        return 0;
457
 
                }
458
 
                pos += ret;
459
 
        }
460
 
 
461
 
        return wpa_ctrl_command(ctrl, cmd);
462
 
}
463
 
 
464
 
 
465
 
static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
466
 
{
467
 
        char cmd[256], *pos, *end;
468
 
        int i, ret;
469
 
 
470
 
        if (argc < 2) {
471
 
                printf("Invalid PASSWORD command: needs two arguments "
472
 
                       "(network id and password)\n");
473
 
                return 0;
474
 
        }
475
 
 
476
 
        end = cmd + sizeof(cmd);
477
 
        pos = cmd;
478
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
479
 
                          argv[0], argv[1]);
480
 
        if (ret < 0 || ret >= end - pos) {
481
 
                printf("Too long PASSWORD command.\n");
482
 
                return 0;
483
 
        }
484
 
        pos += ret;
485
 
        for (i = 2; i < argc; i++) {
486
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
487
 
                if (ret < 0 || ret >= end - pos) {
488
 
                        printf("Too long PASSWORD command.\n");
489
 
                        return 0;
490
 
                }
491
 
                pos += ret;
492
 
        }
493
 
 
494
 
        return wpa_ctrl_command(ctrl, cmd);
495
 
}
496
 
 
497
 
 
498
 
static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
499
 
                                    char *argv[])
500
 
{
501
 
        char cmd[256], *pos, *end;
502
 
        int i, ret;
503
 
 
504
 
        if (argc < 2) {
505
 
                printf("Invalid NEW_PASSWORD command: needs two arguments "
506
 
                       "(network id and password)\n");
507
 
                return 0;
508
 
        }
509
 
 
510
 
        end = cmd + sizeof(cmd);
511
 
        pos = cmd;
512
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
513
 
                          argv[0], argv[1]);
514
 
        if (ret < 0 || ret >= end - pos) {
515
 
                printf("Too long NEW_PASSWORD command.\n");
516
 
                return 0;
517
 
        }
518
 
        pos += ret;
519
 
        for (i = 2; i < argc; i++) {
520
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
521
 
                if (ret < 0 || ret >= end - pos) {
522
 
                        printf("Too long NEW_PASSWORD command.\n");
523
 
                        return 0;
524
 
                }
525
 
                pos += ret;
526
 
        }
527
 
 
528
 
        return wpa_ctrl_command(ctrl, cmd);
529
 
}
530
 
 
531
 
 
532
 
static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
533
 
{
534
 
        char cmd[256], *pos, *end;
535
 
        int i, ret;
536
 
 
537
 
        if (argc < 2) {
538
 
                printf("Invalid PIN command: needs two arguments "
539
 
                       "(network id and pin)\n");
540
 
                return 0;
541
 
        }
542
 
 
543
 
        end = cmd + sizeof(cmd);
544
 
        pos = cmd;
545
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
546
 
                          argv[0], argv[1]);
547
 
        if (ret < 0 || ret >= end - pos) {
548
 
                printf("Too long PIN command.\n");
549
 
                return 0;
550
 
        }
551
 
        pos += ret;
552
 
        for (i = 2; i < argc; i++) {
553
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
554
 
                if (ret < 0 || ret >= end - pos) {
555
 
                        printf("Too long PIN command.\n");
556
 
                        return 0;
557
 
                }
558
 
                pos += ret;
559
 
        }
560
 
        return wpa_ctrl_command(ctrl, cmd);
561
 
}
562
 
 
563
 
 
564
 
static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
565
 
{
566
 
        char cmd[256], *pos, *end;
567
 
        int i, ret;
568
 
 
569
 
        if (argc < 2) {
570
 
                printf("Invalid OTP command: needs two arguments (network "
571
 
                       "id and password)\n");
572
 
                return 0;
573
 
        }
574
 
 
575
 
        end = cmd + sizeof(cmd);
576
 
        pos = cmd;
577
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
578
 
                          argv[0], argv[1]);
579
 
        if (ret < 0 || ret >= end - pos) {
580
 
                printf("Too long OTP command.\n");
581
 
                return 0;
582
 
        }
583
 
        pos += ret;
584
 
        for (i = 2; i < argc; i++) {
585
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
586
 
                if (ret < 0 || ret >= end - pos) {
587
 
                        printf("Too long OTP command.\n");
588
 
                        return 0;
589
 
                }
590
 
                pos += ret;
591
 
        }
592
 
 
593
 
        return wpa_ctrl_command(ctrl, cmd);
594
 
}
595
 
 
596
 
 
597
 
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
598
 
                                  char *argv[])
599
 
{
600
 
        char cmd[256], *pos, *end;
601
 
        int i, ret;
602
 
 
603
 
        if (argc < 2) {
604
 
                printf("Invalid PASSPHRASE command: needs two arguments "
605
 
                       "(network id and passphrase)\n");
606
 
                return 0;
607
 
        }
608
 
 
609
 
        end = cmd + sizeof(cmd);
610
 
        pos = cmd;
611
 
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
612
 
                          argv[0], argv[1]);
613
 
        if (ret < 0 || ret >= end - pos) {
614
 
                printf("Too long PASSPHRASE command.\n");
615
 
                return 0;
616
 
        }
617
 
        pos += ret;
618
 
        for (i = 2; i < argc; i++) {
619
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
620
 
                if (ret < 0 || ret >= end - pos) {
621
 
                        printf("Too long PASSPHRASE command.\n");
622
 
                        return 0;
623
 
                }
624
 
                pos += ret;
625
 
        }
626
 
 
627
 
        return wpa_ctrl_command(ctrl, cmd);
628
 
}
629
 
 
630
 
 
631
 
static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
632
 
{
633
 
        char cmd[256], *pos, *end;
634
 
        int i, ret;
635
 
 
636
 
        if (argc < 2) {
637
 
                printf("Invalid BSSID command: needs two arguments (network "
638
 
                       "id and BSSID)\n");
639
 
                return 0;
640
 
        }
641
 
 
642
 
        end = cmd + sizeof(cmd);
643
 
        pos = cmd;
644
 
        ret = os_snprintf(pos, end - pos, "BSSID");
645
 
        if (ret < 0 || ret >= end - pos) {
646
 
                printf("Too long BSSID command.\n");
647
 
                return 0;
648
 
        }
649
 
        pos += ret;
650
 
        for (i = 0; i < argc; i++) {
651
 
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
652
 
                if (ret < 0 || ret >= end - pos) {
653
 
                        printf("Too long BSSID command.\n");
654
 
                        return 0;
655
 
                }
656
 
                pos += ret;
657
 
        }
658
 
 
659
 
        return wpa_ctrl_command(ctrl, cmd);
660
 
}
661
 
 
662
 
 
663
 
static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
664
 
                                     char *argv[])
665
 
{
666
 
        return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
667
 
}
668
 
 
669
 
 
670
 
static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
671
 
                                      char *argv[])
672
 
{
673
 
        char cmd[32];
674
 
 
675
 
        if (argc < 1) {
676
 
                printf("Invalid SELECT_NETWORK command: needs one argument "
677
 
                       "(network id)\n");
678
 
                return 0;
679
 
        }
680
 
 
681
 
        os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
682
 
        cmd[sizeof(cmd) - 1] = '\0';
683
 
 
684
 
        return wpa_ctrl_command(ctrl, cmd);
685
 
}
686
 
 
687
 
 
688
 
static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
689
 
                                      char *argv[])
690
 
{
691
 
        char cmd[32];
692
 
 
693
 
        if (argc < 1) {
694
 
                printf("Invalid ENABLE_NETWORK command: needs one argument "
695
 
                       "(network id)\n");
696
 
                return 0;
697
 
        }
698
 
 
699
 
        os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
700
 
        cmd[sizeof(cmd) - 1] = '\0';
701
 
 
702
 
        return wpa_ctrl_command(ctrl, cmd);
703
 
}
704
 
 
705
 
 
706
 
static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
707
 
                                       char *argv[])
708
 
{
709
 
        char cmd[32];
710
 
 
711
 
        if (argc < 1) {
712
 
                printf("Invalid DISABLE_NETWORK command: needs one argument "
713
 
                       "(network id)\n");
714
 
                return 0;
715
 
        }
716
 
 
717
 
        os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
718
 
        cmd[sizeof(cmd) - 1] = '\0';
719
 
 
720
 
        return wpa_ctrl_command(ctrl, cmd);
721
 
}
722
 
 
723
 
 
724
 
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
725
 
                                   char *argv[])
726
 
{
727
 
        return wpa_ctrl_command(ctrl, "ADD_NETWORK");
728
 
}
729
 
 
730
 
 
731
 
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
732
 
                                      char *argv[])
733
 
{
734
 
        char cmd[32];
735
 
 
736
 
        if (argc < 1) {
737
 
                printf("Invalid REMOVE_NETWORK command: needs one argument "
738
 
                       "(network id)\n");
739
 
                return 0;
740
 
        }
741
 
 
742
 
        os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
743
 
        cmd[sizeof(cmd) - 1] = '\0';
744
 
 
745
 
        return wpa_ctrl_command(ctrl, cmd);
746
 
}
747
 
 
748
 
 
749
 
static void wpa_cli_show_network_variables(void)
750
 
{
751
 
        printf("set_network variables:\n"
752
 
               "  ssid (network name, SSID)\n"
753
 
               "  psk (WPA passphrase or pre-shared key)\n"
754
 
               "  key_mgmt (key management protocol)\n"
755
 
               "  identity (EAP identity)\n"
756
 
               "  password (EAP password)\n"
757
 
               "  ...\n"
758
 
               "\n"
759
 
               "Note: Values are entered in the same format as the "
760
 
               "configuration file is using,\n"
761
 
               "i.e., strings values need to be inside double quotation "
762
 
               "marks.\n"
763
 
               "For example: set_network 1 ssid \"network name\"\n"
764
 
               "\n"
765
 
               "Please see wpa_supplicant.conf documentation for full list "
766
 
               "of\navailable variables.\n");
767
 
}
768
 
 
769
 
 
770
 
static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
771
 
                                   char *argv[])
772
 
{
773
 
        char cmd[256];
774
 
        int res;
775
 
 
776
 
        if (argc == 0) {
777
 
                wpa_cli_show_network_variables();
778
 
                return 0;
779
 
        }
780
 
 
781
 
        if (argc != 3) {
782
 
                printf("Invalid SET_NETWORK command: needs three arguments\n"
783
 
                       "(network id, variable name, and value)\n");
784
 
                return 0;
785
 
        }
786
 
 
787
 
        res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
788
 
                          argv[0], argv[1], argv[2]);
789
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
790
 
                printf("Too long SET_NETWORK command.\n");
791
 
                return 0;
792
 
        }
793
 
        return wpa_ctrl_command(ctrl, cmd);
794
 
}
795
 
 
796
 
 
797
 
static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
798
 
                                   char *argv[])
799
 
{
800
 
        char cmd[256];
801
 
        int res;
802
 
 
803
 
        if (argc == 0) {
804
 
                wpa_cli_show_network_variables();
805
 
                return 0;
806
 
        }
807
 
 
808
 
        if (argc != 2) {
809
 
                printf("Invalid GET_NETWORK command: needs two arguments\n"
810
 
                       "(network id and variable name)\n");
811
 
                return 0;
812
 
        }
813
 
 
814
 
        res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
815
 
                          argv[0], argv[1]);
816
 
        if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
817
 
                printf("Too long GET_NETWORK command.\n");
818
 
                return 0;
819
 
        }
820
 
        return wpa_ctrl_command(ctrl, cmd);
821
 
}
822
 
 
823
 
 
824
 
static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
825
 
                                  char *argv[])
826
 
{
827
 
        return wpa_ctrl_command(ctrl, "DISCONNECT");
828
 
}
829
 
 
830
 
 
831
 
static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
832
 
                                   char *argv[])
833
 
{
834
 
        return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
835
 
}
836
 
 
837
 
 
838
 
static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
839
 
{
840
 
        return wpa_ctrl_command(ctrl, "SCAN");
841
 
}
842
 
 
843
 
 
844
 
static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
845
 
                                    char *argv[])
846
 
{
847
 
        return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
848
 
}
849
 
 
850
 
 
851
 
static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
852
 
                                      char *argv[])
853
 
{
854
 
        char cmd[64];
855
 
 
856
 
        if (argc < 1 || argc > 2) {
857
 
                printf("Invalid GET_CAPABILITY command: need either one or "
858
 
                       "two arguments\n");
859
 
                return 0;
860
 
        }
861
 
 
862
 
        if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
863
 
                printf("Invalid GET_CAPABILITY command: second argument, "
864
 
                       "if any, must be 'strict'\n");
865
 
                return 0;
866
 
        }
867
 
 
868
 
        os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
869
 
                    (argc == 2) ? " strict" : "");
870
 
        cmd[sizeof(cmd) - 1] = '\0';
871
 
 
872
 
        return wpa_ctrl_command(ctrl, cmd);
873
 
}
874
 
 
875
 
 
876
 
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
877
 
{
878
 
        printf("Available interfaces:\n");
879
 
        return wpa_ctrl_command(ctrl, "INTERFACES");
880
 
}
881
 
 
882
 
 
883
 
static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
884
 
{
885
 
        if (argc < 1) {
886
 
                wpa_cli_list_interfaces(ctrl);
887
 
                return 0;
888
 
        }
889
 
 
890
 
        wpa_cli_close_connection();
891
 
        os_free(ctrl_ifname);
892
 
        ctrl_ifname = os_strdup(argv[0]);
893
 
 
894
 
        if (wpa_cli_open_connection(ctrl_ifname)) {
895
 
                printf("Connected to interface '%s.\n", ctrl_ifname);
896
 
                if (wpa_ctrl_attach(ctrl_conn) == 0) {
897
 
                        wpa_cli_attached = 1;
898
 
                } else {
899
 
                        printf("Warning: Failed to attach to "
900
 
                               "wpa_supplicant.\n");
901
 
                }
902
 
        } else {
903
 
                printf("Could not connect to interface '%s' - re-trying\n",
904
 
                        ctrl_ifname);
905
 
        }
906
 
        return 0;
907
 
}
908
 
 
909
 
 
910
 
static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
911
 
                                   char *argv[])
912
 
{
913
 
        return wpa_ctrl_command(ctrl, "RECONFIGURE");
914
 
}
915
 
 
916
 
 
917
 
static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
918
 
                                 char *argv[])
919
 
{
920
 
        return wpa_ctrl_command(ctrl, "TERMINATE");
921
 
}
922
 
 
923
 
 
924
 
static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
925
 
                                     char *argv[])
926
 
{
927
 
        char cmd[256];
928
 
 
929
 
        if (argc < 1) {
930
 
                printf("Invalid INTERFACE_ADD command: needs at least one "
931
 
                       "argument (interface name)\n"
932
 
                        "All arguments: ifname confname driver ctrl_interface "
933
 
                        "driver_param bridge_name\n");
934
 
                return 0;
935
 
        }
936
 
 
937
 
        /*
938
 
         * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
939
 
         * <driver_param>TAB<bridge_name>
940
 
         */
941
 
        os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
942
 
                    argv[0],
943
 
                    argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
944
 
                    argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
945
 
                    argc > 5 ? argv[5] : "");
946
 
        cmd[sizeof(cmd) - 1] = '\0';
947
 
        return wpa_ctrl_command(ctrl, cmd);
948
 
}
949
 
 
950
 
 
951
 
static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
952
 
                                        char *argv[])
953
 
{
954
 
        char cmd[128];
955
 
 
956
 
        if (argc != 1) {
957
 
                printf("Invalid INTERFACE_REMOVE command: needs one argument "
958
 
                       "(interface name)\n");
959
 
                return 0;
960
 
        }
961
 
 
962
 
        os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
963
 
        cmd[sizeof(cmd) - 1] = '\0';
964
 
        return wpa_ctrl_command(ctrl, cmd);
965
 
}
966
 
 
967
 
 
968
 
struct wpa_cli_cmd {
969
 
        const char *cmd;
970
 
        int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
971
 
};
972
 
 
973
 
static struct wpa_cli_cmd wpa_cli_commands[] = {
974
 
        { "status", wpa_cli_cmd_status },
975
 
        { "ping", wpa_cli_cmd_ping },
976
 
        { "mib", wpa_cli_cmd_mib },
977
 
        { "help", wpa_cli_cmd_help },
978
 
        { "interface", wpa_cli_cmd_interface },
979
 
        { "level", wpa_cli_cmd_level },
980
 
        { "license", wpa_cli_cmd_license },
981
 
        { "quit", wpa_cli_cmd_quit },
982
 
        { "set", wpa_cli_cmd_set },
983
 
        { "logon", wpa_cli_cmd_logon },
984
 
        { "logoff", wpa_cli_cmd_logoff },
985
 
        { "pmksa", wpa_cli_cmd_pmksa },
986
 
        { "reassociate", wpa_cli_cmd_reassociate },
987
 
        { "preauthenticate", wpa_cli_cmd_preauthenticate },
988
 
        { "identity", wpa_cli_cmd_identity },
989
 
        { "password", wpa_cli_cmd_password },
990
 
        { "new_password", wpa_cli_cmd_new_password },
991
 
        { "pin", wpa_cli_cmd_pin },
992
 
        { "otp", wpa_cli_cmd_otp },
993
 
        { "passphrase", wpa_cli_cmd_passphrase },
994
 
        { "bssid", wpa_cli_cmd_bssid },
995
 
        { "list_networks", wpa_cli_cmd_list_networks },
996
 
        { "select_network", wpa_cli_cmd_select_network },
997
 
        { "enable_network", wpa_cli_cmd_enable_network },
998
 
        { "disable_network", wpa_cli_cmd_disable_network },
999
 
        { "add_network", wpa_cli_cmd_add_network },
1000
 
        { "remove_network", wpa_cli_cmd_remove_network },
1001
 
        { "set_network", wpa_cli_cmd_set_network },
1002
 
        { "get_network", wpa_cli_cmd_get_network },
1003
 
        { "save_config", wpa_cli_cmd_save_config },
1004
 
        { "disconnect", wpa_cli_cmd_disconnect },
1005
 
        { "scan", wpa_cli_cmd_scan },
1006
 
        { "scan_results", wpa_cli_cmd_scan_results },
1007
 
        { "get_capability", wpa_cli_cmd_get_capability },
1008
 
        { "reconfigure", wpa_cli_cmd_reconfigure },
1009
 
        { "terminate", wpa_cli_cmd_terminate },
1010
 
        { "interface_add", wpa_cli_cmd_interface_add },
1011
 
        { "interface_remove", wpa_cli_cmd_interface_remove },
1012
 
        { "ap_scan", wpa_cli_cmd_ap_scan },
1013
 
        { "stkstart", wpa_cli_cmd_stkstart },
1014
 
        { NULL, NULL }
1015
 
};
1016
 
 
1017
 
 
1018
 
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1019
 
{
1020
 
        struct wpa_cli_cmd *cmd, *match = NULL;
1021
 
        int count;
1022
 
 
1023
 
        count = 0;
1024
 
        cmd = wpa_cli_commands;
1025
 
        while (cmd->cmd) {
1026
 
                if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1027
 
                {
1028
 
                        match = cmd;
1029
 
                        if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1030
 
                                /* we have an exact match */
1031
 
                                count = 1;
1032
 
                                break;
1033
 
                        }
1034
 
                        count++;
1035
 
                }
1036
 
                cmd++;
1037
 
        }
1038
 
 
1039
 
        if (count > 1) {
1040
 
                printf("Ambiguous command '%s'; possible commands:", argv[0]);
1041
 
                cmd = wpa_cli_commands;
1042
 
                while (cmd->cmd) {
1043
 
                        if (os_strncasecmp(cmd->cmd, argv[0],
1044
 
                                           os_strlen(argv[0])) == 0) {
1045
 
                                printf(" %s", cmd->cmd);
1046
 
                        }
1047
 
                        cmd++;
1048
 
                }
1049
 
                printf("\n");
1050
 
        } else if (count == 0) {
1051
 
                printf("Unknown command '%s'\n", argv[0]);
1052
 
        } else {
1053
 
                match->handler(ctrl, argc - 1, &argv[1]);
1054
 
        }
1055
 
}
1056
 
 
1057
 
 
1058
 
static int str_match(const char *a, const char *b)
1059
 
{
1060
 
        return os_strncmp(a, b, os_strlen(b)) == 0;
1061
 
}
1062
 
 
1063
 
 
1064
 
static int wpa_cli_exec(const char *program, const char *arg1,
1065
 
                        const char *arg2)
1066
 
{
1067
 
        char *cmd;
1068
 
        size_t len;
1069
 
 
1070
 
        len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1071
 
        cmd = os_malloc(len);
1072
 
        if (cmd == NULL)
1073
 
                return -1;
1074
 
        os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1075
 
        cmd[len - 1] = '\0';
1076
 
#ifndef _WIN32_WCE
1077
 
        system(cmd);
1078
 
#endif /* _WIN32_WCE */
1079
 
        os_free(cmd);
1080
 
 
1081
 
        return 0;
1082
 
}
1083
 
 
1084
 
 
1085
 
static void wpa_cli_action_process(const char *msg)
1086
 
{
1087
 
        const char *pos;
1088
 
        char *copy = NULL, *id, *pos2;
1089
 
 
1090
 
        pos = msg;
1091
 
        if (*pos == '<') {
1092
 
                /* skip priority */
1093
 
                pos = os_strchr(pos, '>');
1094
 
                if (pos)
1095
 
                        pos++;
1096
 
                else
1097
 
                        pos = msg;
1098
 
        }
1099
 
 
1100
 
        if (str_match(pos, WPA_EVENT_CONNECTED)) {
1101
 
                int new_id = -1;
1102
 
                os_unsetenv("WPA_ID");
1103
 
                os_unsetenv("WPA_ID_STR");
1104
 
                os_unsetenv("WPA_CTRL_DIR");
1105
 
 
1106
 
                pos = os_strstr(pos, "[id=");
1107
 
                if (pos)
1108
 
                        copy = os_strdup(pos + 4);
1109
 
 
1110
 
                if (copy) {
1111
 
                        pos2 = id = copy;
1112
 
                        while (*pos2 && *pos2 != ' ')
1113
 
                                pos2++;
1114
 
                        *pos2++ = '\0';
1115
 
                        new_id = atoi(id);
1116
 
                        os_setenv("WPA_ID", id, 1);
1117
 
                        while (*pos2 && *pos2 != '=')
1118
 
                                pos2++;
1119
 
                        if (*pos2 == '=')
1120
 
                                pos2++;
1121
 
                        id = pos2;
1122
 
                        while (*pos2 && *pos2 != ']')
1123
 
                                pos2++;
1124
 
                        *pos2 = '\0';
1125
 
                        os_setenv("WPA_ID_STR", id, 1);
1126
 
                        os_free(copy);
1127
 
                }
1128
 
 
1129
 
                os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1130
 
 
1131
 
                if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1132
 
                        wpa_cli_connected = 1;
1133
 
                        wpa_cli_last_id = new_id;
1134
 
                        wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1135
 
                }
1136
 
        } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1137
 
                if (wpa_cli_connected) {
1138
 
                        wpa_cli_connected = 0;
1139
 
                        wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1140
 
                }
1141
 
        } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1142
 
                printf("wpa_supplicant is terminating - stop monitoring\n");
1143
 
                wpa_cli_quit = 1;
1144
 
        }
1145
 
}
1146
 
 
1147
 
 
1148
 
#ifndef CONFIG_ANSI_C_EXTRA
1149
 
static void wpa_cli_action_cb(char *msg, size_t len)
1150
 
{
1151
 
        wpa_cli_action_process(msg);
1152
 
}
1153
 
#endif /* CONFIG_ANSI_C_EXTRA */
1154
 
 
1155
 
 
1156
 
static void wpa_cli_reconnect(void)
1157
 
{
1158
 
        wpa_cli_close_connection();
1159
 
        ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1160
 
        if (ctrl_conn) {
1161
 
                printf("Connection to wpa_supplicant re-established\n");
1162
 
                if (wpa_ctrl_attach(ctrl_conn) == 0) {
1163
 
                        wpa_cli_attached = 1;
1164
 
                } else {
1165
 
                        printf("Warning: Failed to attach to "
1166
 
                               "wpa_supplicant.\n");
1167
 
                }
1168
 
        }
1169
 
}
1170
 
 
1171
 
 
1172
 
static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1173
 
                                 int action_monitor)
1174
 
{
1175
 
        int first = 1;
1176
 
        if (ctrl_conn == NULL) {
1177
 
                wpa_cli_reconnect();
1178
 
                return;
1179
 
        }
1180
 
        while (wpa_ctrl_pending(ctrl) > 0) {
1181
 
                char buf[256];
1182
 
                size_t len = sizeof(buf) - 1;
1183
 
                if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1184
 
                        buf[len] = '\0';
1185
 
                        if (action_monitor)
1186
 
                                wpa_cli_action_process(buf);
1187
 
                        else {
1188
 
                                if (in_read && first)
1189
 
                                        printf("\n");
1190
 
                                first = 0;
1191
 
                                printf("%s\n", buf);
1192
 
                        }
1193
 
                } else {
1194
 
                        printf("Could not read pending message.\n");
1195
 
                        break;
1196
 
                }
1197
 
        }
1198
 
 
1199
 
        if (wpa_ctrl_pending(ctrl) < 0) {
1200
 
                printf("Connection to wpa_supplicant lost - trying to "
1201
 
                       "reconnect\n");
1202
 
                wpa_cli_reconnect();
1203
 
        }
1204
 
}
1205
 
 
1206
 
 
1207
 
#ifdef CONFIG_READLINE
1208
 
static char * wpa_cli_cmd_gen(const char *text, int state)
1209
 
{
1210
 
        static int i, len;
1211
 
        const char *cmd;
1212
 
 
1213
 
        if (state == 0) {
1214
 
                i = 0;
1215
 
                len = os_strlen(text);
1216
 
        }
1217
 
 
1218
 
        while ((cmd = wpa_cli_commands[i].cmd)) {
1219
 
                i++;
1220
 
                if (os_strncasecmp(cmd, text, len) == 0)
1221
 
                        return os_strdup(cmd);
1222
 
        }
1223
 
 
1224
 
        return NULL;
1225
 
}
1226
 
 
1227
 
 
1228
 
static char * wpa_cli_dummy_gen(const char *text, int state)
1229
 
{
1230
 
        return NULL;
1231
 
}
1232
 
 
1233
 
 
1234
 
static char ** wpa_cli_completion(const char *text, int start, int end)
1235
 
{
1236
 
        return rl_completion_matches(text, start == 0 ?
1237
 
                                     wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1238
 
}
1239
 
#endif /* CONFIG_READLINE */
1240
 
 
1241
 
 
1242
 
static void wpa_cli_interactive(void)
1243
 
{
1244
 
#define max_args 10
1245
 
        char cmdbuf[256], *cmd, *argv[max_args], *pos;
1246
 
        int argc;
1247
 
#ifdef CONFIG_READLINE
1248
 
        char *home, *hfile = NULL;
1249
 
#endif /* CONFIG_READLINE */
1250
 
 
1251
 
        printf("\nInteractive mode\n\n");
1252
 
 
1253
 
#ifdef CONFIG_READLINE
1254
 
        rl_attempted_completion_function = wpa_cli_completion;
1255
 
        home = getenv("HOME");
1256
 
        if (home) {
1257
 
                const char *fname = ".wpa_cli_history";
1258
 
                int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1259
 
                hfile = os_malloc(hfile_len);
1260
 
                if (hfile) {
1261
 
                        os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1262
 
                        hfile[hfile_len - 1] = '\0';
1263
 
                        read_history(hfile);
1264
 
                        stifle_history(100);
1265
 
                }
1266
 
        }
1267
 
#endif /* CONFIG_READLINE */
1268
 
 
1269
 
        do {
1270
 
                wpa_cli_recv_pending(ctrl_conn, 0, 0);
1271
 
#ifndef CONFIG_NATIVE_WINDOWS
1272
 
                alarm(1);
1273
 
#endif /* CONFIG_NATIVE_WINDOWS */
1274
 
#ifdef CONFIG_READLINE
1275
 
                cmd = readline("> ");
1276
 
                if (cmd && *cmd) {
1277
 
                        HIST_ENTRY *h;
1278
 
                        while (next_history())
1279
 
                                ;
1280
 
                        h = previous_history();
1281
 
                        if (h == NULL || os_strcmp(cmd, h->line) != 0)
1282
 
                                add_history(cmd);
1283
 
                        next_history();
1284
 
                }
1285
 
#else /* CONFIG_READLINE */
1286
 
                printf("> ");
1287
 
                cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1288
 
#endif /* CONFIG_READLINE */
1289
 
#ifndef CONFIG_NATIVE_WINDOWS
1290
 
                alarm(0);
1291
 
#endif /* CONFIG_NATIVE_WINDOWS */
1292
 
                if (cmd == NULL)
1293
 
                        break;
1294
 
                wpa_cli_recv_pending(ctrl_conn, 0, 0);
1295
 
                pos = cmd;
1296
 
                while (*pos != '\0') {
1297
 
                        if (*pos == '\n') {
1298
 
                                *pos = '\0';
1299
 
                                break;
1300
 
                        }
1301
 
                        pos++;
1302
 
                }
1303
 
                argc = 0;
1304
 
                pos = cmd;
1305
 
                for (;;) {
1306
 
                        while (*pos == ' ')
1307
 
                                pos++;
1308
 
                        if (*pos == '\0')
1309
 
                                break;
1310
 
                        argv[argc] = pos;
1311
 
                        argc++;
1312
 
                        if (argc == max_args)
1313
 
                                break;
1314
 
                        if (*pos == '"') {
1315
 
                                char *pos2 = os_strrchr(pos, '"');
1316
 
                                if (pos2)
1317
 
                                        pos = pos2 + 1;
1318
 
                        }
1319
 
                        while (*pos != '\0' && *pos != ' ')
1320
 
                                pos++;
1321
 
                        if (*pos == ' ')
1322
 
                                *pos++ = '\0';
1323
 
                }
1324
 
                if (argc)
1325
 
                        wpa_request(ctrl_conn, argc, argv);
1326
 
 
1327
 
                if (cmd != cmdbuf)
1328
 
                        os_free(cmd);
1329
 
        } while (!wpa_cli_quit);
1330
 
 
1331
 
#ifdef CONFIG_READLINE
1332
 
        if (hfile) {
1333
 
                /* Save command history, excluding lines that may contain
1334
 
                 * passwords. */
1335
 
                HIST_ENTRY *h;
1336
 
                history_set_pos(0);
1337
 
                h = next_history();
1338
 
                while (h) {
1339
 
                        char *p = h->line;
1340
 
                        while (*p == ' ' || *p == '\t')
1341
 
                                p++;
1342
 
                        if (os_strncasecmp(p, "pa", 2) == 0 ||
1343
 
                            os_strncasecmp(p, "o", 1) == 0 ||
1344
 
                            os_strncasecmp(p, "n", 1)) {
1345
 
                                h = remove_history(where_history());
1346
 
                                if (h) {
1347
 
                                        os_free(h->line);
1348
 
                                        os_free(h->data);
1349
 
                                        os_free(h);
1350
 
                                }
1351
 
                                h = current_history();
1352
 
                        } else {
1353
 
                                h = next_history();
1354
 
                        }
1355
 
                }
1356
 
                write_history(hfile);
1357
 
                os_free(hfile);
1358
 
        }
1359
 
#endif /* CONFIG_READLINE */
1360
 
}
1361
 
 
1362
 
 
1363
 
static void wpa_cli_action(struct wpa_ctrl *ctrl)
1364
 
{
1365
 
#ifdef CONFIG_ANSI_C_EXTRA
1366
 
        /* TODO: ANSI C version(?) */
1367
 
        printf("Action processing not supported in ANSI C build.\n");
1368
 
#else /* CONFIG_ANSI_C_EXTRA */
1369
 
        fd_set rfds;
1370
 
        int fd, res;
1371
 
        struct timeval tv;
1372
 
        char buf[256]; /* note: large enough to fit in unsolicited messages */
1373
 
        size_t len;
1374
 
 
1375
 
        fd = wpa_ctrl_get_fd(ctrl);
1376
 
 
1377
 
        while (!wpa_cli_quit) {
1378
 
                FD_ZERO(&rfds);
1379
 
                FD_SET(fd, &rfds);
1380
 
                tv.tv_sec = 2;
1381
 
                tv.tv_usec = 0;
1382
 
                res = select(fd + 1, &rfds, NULL, NULL, &tv);
1383
 
                if (res < 0 && errno != EINTR) {
1384
 
                        perror("select");
1385
 
                        break;
1386
 
                }
1387
 
 
1388
 
                if (FD_ISSET(fd, &rfds))
1389
 
                        wpa_cli_recv_pending(ctrl, 0, 1);
1390
 
                else {
1391
 
                        /* verify that connection is still working */
1392
 
                        len = sizeof(buf) - 1;
1393
 
                        if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1394
 
                                             wpa_cli_action_cb) < 0 ||
1395
 
                            len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1396
 
                                printf("wpa_supplicant did not reply to PING "
1397
 
                                       "command - exiting\n");
1398
 
                                break;
1399
 
                        }
1400
 
                }
1401
 
        }
1402
 
#endif /* CONFIG_ANSI_C_EXTRA */
1403
 
}
1404
 
 
1405
 
 
1406
 
static void wpa_cli_cleanup(void)
1407
 
{
1408
 
        wpa_cli_close_connection();
1409
 
        if (pid_file)
1410
 
                os_daemonize_terminate(pid_file);
1411
 
 
1412
 
        os_program_deinit();
1413
 
}
1414
 
 
1415
 
static void wpa_cli_terminate(int sig)
1416
 
{
1417
 
        wpa_cli_cleanup();
1418
 
        exit(0);
1419
 
}
1420
 
 
1421
 
 
1422
 
#ifndef CONFIG_NATIVE_WINDOWS
1423
 
static void wpa_cli_alarm(int sig)
1424
 
{
1425
 
        if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1426
 
                printf("Connection to wpa_supplicant lost - trying to "
1427
 
                       "reconnect\n");
1428
 
                wpa_cli_close_connection();
1429
 
        }
1430
 
        if (!ctrl_conn)
1431
 
                wpa_cli_reconnect();
1432
 
        if (ctrl_conn)
1433
 
                wpa_cli_recv_pending(ctrl_conn, 1, 0);
1434
 
        alarm(1);
1435
 
}
1436
 
#endif /* CONFIG_NATIVE_WINDOWS */
1437
 
 
1438
 
 
1439
 
static char * wpa_cli_get_default_ifname(void)
1440
 
{
1441
 
        char *ifname = NULL;
1442
 
 
1443
 
#ifdef CONFIG_CTRL_IFACE_UNIX
1444
 
        struct dirent *dent;
1445
 
        DIR *dir = opendir(ctrl_iface_dir);
1446
 
        if (!dir)
1447
 
                return NULL;
1448
 
        while ((dent = readdir(dir))) {
1449
 
#ifdef _DIRENT_HAVE_D_TYPE
1450
 
                /*
1451
 
                 * Skip the file if it is not a socket. Also accept
1452
 
                 * DT_UNKNOWN (0) in case the C library or underlying
1453
 
                 * file system does not support d_type.
1454
 
                 */
1455
 
                if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1456
 
                        continue;
1457
 
#endif /* _DIRENT_HAVE_D_TYPE */
1458
 
                if (os_strcmp(dent->d_name, ".") == 0 ||
1459
 
                    os_strcmp(dent->d_name, "..") == 0)
1460
 
                        continue;
1461
 
                printf("Selected interface '%s'\n", dent->d_name);
1462
 
                ifname = os_strdup(dent->d_name);
1463
 
                break;
1464
 
        }
1465
 
        closedir(dir);
1466
 
#endif /* CONFIG_CTRL_IFACE_UNIX */
1467
 
 
1468
 
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1469
 
        char buf[2048], *pos;
1470
 
        size_t len;
1471
 
        struct wpa_ctrl *ctrl;
1472
 
        int ret;
1473
 
 
1474
 
        ctrl = wpa_ctrl_open(NULL);
1475
 
        if (ctrl == NULL)
1476
 
                return NULL;
1477
 
 
1478
 
        len = sizeof(buf) - 1;
1479
 
        ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1480
 
        if (ret >= 0) {
1481
 
                buf[len] = '\0';
1482
 
                pos = os_strchr(buf, '\n');
1483
 
                if (pos)
1484
 
                        *pos = '\0';
1485
 
                ifname = os_strdup(buf);
1486
 
        }
1487
 
        wpa_ctrl_close(ctrl);
1488
 
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1489
 
 
1490
 
        return ifname;
1491
 
}
1492
 
 
1493
 
 
1494
 
int main(int argc, char *argv[])
1495
 
{
1496
 
        int interactive;
1497
 
        int warning_displayed = 0;
1498
 
        int c;
1499
 
        int daemonize = 0;
1500
 
        const char *global = NULL;
1501
 
 
1502
 
        if (os_program_init())
1503
 
                return -1;
1504
 
 
1505
 
        for (;;) {
1506
 
                c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1507
 
                if (c < 0)
1508
 
                        break;
1509
 
                switch (c) {
1510
 
                case 'a':
1511
 
                        action_file = optarg;
1512
 
                        break;
1513
 
                case 'B':
1514
 
                        daemonize = 1;
1515
 
                        break;
1516
 
                case 'g':
1517
 
                        global = optarg;
1518
 
                        break;
1519
 
                case 'h':
1520
 
                        usage();
1521
 
                        return 0;
1522
 
                case 'v':
1523
 
                        printf("%s\n", wpa_cli_version);
1524
 
                        return 0;
1525
 
                case 'i':
1526
 
                        os_free(ctrl_ifname);
1527
 
                        ctrl_ifname = os_strdup(optarg);
1528
 
                        break;
1529
 
                case 'p':
1530
 
                        ctrl_iface_dir = optarg;
1531
 
                        break;
1532
 
                case 'P':
1533
 
                        pid_file = optarg;
1534
 
                        break;
1535
 
                default:
1536
 
                        usage();
1537
 
                        return -1;
1538
 
                }
1539
 
        }
1540
 
 
1541
 
        interactive = (argc == optind) && (action_file == NULL);
1542
 
 
1543
 
        if (interactive)
1544
 
                printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1545
 
 
1546
 
        if (global) {
1547
 
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1548
 
                ctrl_conn = wpa_ctrl_open(NULL);
1549
 
#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1550
 
                ctrl_conn = wpa_ctrl_open(global);
1551
 
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1552
 
                if (ctrl_conn == NULL) {
1553
 
                        perror("Failed to connect to wpa_supplicant - "
1554
 
                               "wpa_ctrl_open");
1555
 
                        return -1;
1556
 
                }
1557
 
        }
1558
 
 
1559
 
        for (; !global;) {
1560
 
                if (ctrl_ifname == NULL)
1561
 
                        ctrl_ifname = wpa_cli_get_default_ifname();
1562
 
                ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1563
 
                if (ctrl_conn) {
1564
 
                        if (warning_displayed)
1565
 
                                printf("Connection established.\n");
1566
 
                        break;
1567
 
                }
1568
 
 
1569
 
                if (!interactive) {
1570
 
                        perror("Failed to connect to wpa_supplicant - "
1571
 
                               "wpa_ctrl_open");
1572
 
                        return -1;
1573
 
                }
1574
 
 
1575
 
                if (!warning_displayed) {
1576
 
                        printf("Could not connect to wpa_supplicant - "
1577
 
                               "re-trying\n");
1578
 
                        warning_displayed = 1;
1579
 
                }
1580
 
                os_sleep(1, 0);
1581
 
                continue;
1582
 
        }
1583
 
 
1584
 
#ifndef _WIN32_WCE
1585
 
        signal(SIGINT, wpa_cli_terminate);
1586
 
        signal(SIGTERM, wpa_cli_terminate);
1587
 
#endif /* _WIN32_WCE */
1588
 
#ifndef CONFIG_NATIVE_WINDOWS
1589
 
        signal(SIGALRM, wpa_cli_alarm);
1590
 
#endif /* CONFIG_NATIVE_WINDOWS */
1591
 
 
1592
 
        if (interactive || action_file) {
1593
 
                if (wpa_ctrl_attach(ctrl_conn) == 0) {
1594
 
                        wpa_cli_attached = 1;
1595
 
                } else {
1596
 
                        printf("Warning: Failed to attach to "
1597
 
                               "wpa_supplicant.\n");
1598
 
                        if (!interactive)
1599
 
                                return -1;
1600
 
                }
1601
 
        }
1602
 
 
1603
 
        if (daemonize && os_daemonize(pid_file))
1604
 
                return -1;
1605
 
 
1606
 
        if (interactive)
1607
 
                wpa_cli_interactive();
1608
 
        else if (action_file)
1609
 
                wpa_cli_action(ctrl_conn);
1610
 
        else
1611
 
                wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1612
 
 
1613
 
        os_free(ctrl_ifname);
1614
 
        wpa_cli_cleanup();
1615
 
 
1616
 
        return 0;
1617
 
}
1618
 
 
1619
 
#else /* CONFIG_CTRL_IFACE */
1620
 
int main(int argc, char *argv[])
1621
 
{
1622
 
        printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1623
 
        return -1;
1624
 
}
1625
 
#endif /* CONFIG_CTRL_IFACE */