~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to wpa_supplicant/wpa_cli.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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