1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt * Common hostapd/wpa_supplicant command line interface functions
3*a1157835SDaniel Fojt * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4*a1157835SDaniel Fojt *
5*a1157835SDaniel Fojt * This software may be distributed under the terms of the BSD license.
6*a1157835SDaniel Fojt * See README for more details.
7*a1157835SDaniel Fojt */
8*a1157835SDaniel Fojt
9*a1157835SDaniel Fojt #include "includes.h"
10*a1157835SDaniel Fojt
11*a1157835SDaniel Fojt #include "utils/common.h"
12*a1157835SDaniel Fojt #include "common/cli.h"
13*a1157835SDaniel Fojt
14*a1157835SDaniel Fojt
15*a1157835SDaniel Fojt const char *const cli_license =
16*a1157835SDaniel Fojt "This software may be distributed under the terms of the BSD license.\n"
17*a1157835SDaniel Fojt "See README for more details.\n";
18*a1157835SDaniel Fojt
19*a1157835SDaniel Fojt const char *const cli_full_license =
20*a1157835SDaniel Fojt "This software may be distributed under the terms of the BSD license.\n"
21*a1157835SDaniel Fojt "\n"
22*a1157835SDaniel Fojt "Redistribution and use in source and binary forms, with or without\n"
23*a1157835SDaniel Fojt "modification, are permitted provided that the following conditions are\n"
24*a1157835SDaniel Fojt "met:\n"
25*a1157835SDaniel Fojt "\n"
26*a1157835SDaniel Fojt "1. Redistributions of source code must retain the above copyright\n"
27*a1157835SDaniel Fojt " notice, this list of conditions and the following disclaimer.\n"
28*a1157835SDaniel Fojt "\n"
29*a1157835SDaniel Fojt "2. Redistributions in binary form must reproduce the above copyright\n"
30*a1157835SDaniel Fojt " notice, this list of conditions and the following disclaimer in the\n"
31*a1157835SDaniel Fojt " documentation and/or other materials provided with the distribution.\n"
32*a1157835SDaniel Fojt "\n"
33*a1157835SDaniel Fojt "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
34*a1157835SDaniel Fojt " names of its contributors may be used to endorse or promote products\n"
35*a1157835SDaniel Fojt " derived from this software without specific prior written permission.\n"
36*a1157835SDaniel Fojt "\n"
37*a1157835SDaniel Fojt "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
38*a1157835SDaniel Fojt "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
39*a1157835SDaniel Fojt "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
40*a1157835SDaniel Fojt "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
41*a1157835SDaniel Fojt "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
42*a1157835SDaniel Fojt "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
43*a1157835SDaniel Fojt "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
44*a1157835SDaniel Fojt "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
45*a1157835SDaniel Fojt "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
46*a1157835SDaniel Fojt "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
47*a1157835SDaniel Fojt "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
48*a1157835SDaniel Fojt "\n";
49*a1157835SDaniel Fojt
50*a1157835SDaniel Fojt
cli_txt_list_free(struct cli_txt_entry * e)51*a1157835SDaniel Fojt void cli_txt_list_free(struct cli_txt_entry *e)
52*a1157835SDaniel Fojt {
53*a1157835SDaniel Fojt dl_list_del(&e->list);
54*a1157835SDaniel Fojt os_free(e->txt);
55*a1157835SDaniel Fojt os_free(e);
56*a1157835SDaniel Fojt }
57*a1157835SDaniel Fojt
58*a1157835SDaniel Fojt
cli_txt_list_flush(struct dl_list * list)59*a1157835SDaniel Fojt void cli_txt_list_flush(struct dl_list *list)
60*a1157835SDaniel Fojt {
61*a1157835SDaniel Fojt struct cli_txt_entry *e;
62*a1157835SDaniel Fojt
63*a1157835SDaniel Fojt while ((e = dl_list_first(list, struct cli_txt_entry, list)))
64*a1157835SDaniel Fojt cli_txt_list_free(e);
65*a1157835SDaniel Fojt }
66*a1157835SDaniel Fojt
67*a1157835SDaniel Fojt
cli_txt_list_get(struct dl_list * txt_list,const char * txt)68*a1157835SDaniel Fojt struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
69*a1157835SDaniel Fojt const char *txt)
70*a1157835SDaniel Fojt {
71*a1157835SDaniel Fojt struct cli_txt_entry *e;
72*a1157835SDaniel Fojt
73*a1157835SDaniel Fojt dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
74*a1157835SDaniel Fojt if (os_strcmp(e->txt, txt) == 0)
75*a1157835SDaniel Fojt return e;
76*a1157835SDaniel Fojt }
77*a1157835SDaniel Fojt return NULL;
78*a1157835SDaniel Fojt }
79*a1157835SDaniel Fojt
80*a1157835SDaniel Fojt
cli_txt_list_del(struct dl_list * txt_list,const char * txt)81*a1157835SDaniel Fojt void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
82*a1157835SDaniel Fojt {
83*a1157835SDaniel Fojt struct cli_txt_entry *e;
84*a1157835SDaniel Fojt
85*a1157835SDaniel Fojt e = cli_txt_list_get(txt_list, txt);
86*a1157835SDaniel Fojt if (e)
87*a1157835SDaniel Fojt cli_txt_list_free(e);
88*a1157835SDaniel Fojt }
89*a1157835SDaniel Fojt
90*a1157835SDaniel Fojt
cli_txt_list_del_addr(struct dl_list * txt_list,const char * txt)91*a1157835SDaniel Fojt void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
92*a1157835SDaniel Fojt {
93*a1157835SDaniel Fojt u8 addr[ETH_ALEN];
94*a1157835SDaniel Fojt char buf[18];
95*a1157835SDaniel Fojt
96*a1157835SDaniel Fojt if (hwaddr_aton(txt, addr) < 0)
97*a1157835SDaniel Fojt return;
98*a1157835SDaniel Fojt os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
99*a1157835SDaniel Fojt cli_txt_list_del(txt_list, buf);
100*a1157835SDaniel Fojt }
101*a1157835SDaniel Fojt
102*a1157835SDaniel Fojt
cli_txt_list_del_word(struct dl_list * txt_list,const char * txt,int separator)103*a1157835SDaniel Fojt void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
104*a1157835SDaniel Fojt int separator)
105*a1157835SDaniel Fojt {
106*a1157835SDaniel Fojt const char *end;
107*a1157835SDaniel Fojt char *buf;
108*a1157835SDaniel Fojt
109*a1157835SDaniel Fojt end = os_strchr(txt, separator);
110*a1157835SDaniel Fojt if (end == NULL)
111*a1157835SDaniel Fojt end = txt + os_strlen(txt);
112*a1157835SDaniel Fojt buf = dup_binstr(txt, end - txt);
113*a1157835SDaniel Fojt if (buf == NULL)
114*a1157835SDaniel Fojt return;
115*a1157835SDaniel Fojt cli_txt_list_del(txt_list, buf);
116*a1157835SDaniel Fojt os_free(buf);
117*a1157835SDaniel Fojt }
118*a1157835SDaniel Fojt
119*a1157835SDaniel Fojt
cli_txt_list_add(struct dl_list * txt_list,const char * txt)120*a1157835SDaniel Fojt int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
121*a1157835SDaniel Fojt {
122*a1157835SDaniel Fojt struct cli_txt_entry *e;
123*a1157835SDaniel Fojt
124*a1157835SDaniel Fojt e = cli_txt_list_get(txt_list, txt);
125*a1157835SDaniel Fojt if (e)
126*a1157835SDaniel Fojt return 0;
127*a1157835SDaniel Fojt e = os_zalloc(sizeof(*e));
128*a1157835SDaniel Fojt if (e == NULL)
129*a1157835SDaniel Fojt return -1;
130*a1157835SDaniel Fojt e->txt = os_strdup(txt);
131*a1157835SDaniel Fojt if (e->txt == NULL) {
132*a1157835SDaniel Fojt os_free(e);
133*a1157835SDaniel Fojt return -1;
134*a1157835SDaniel Fojt }
135*a1157835SDaniel Fojt dl_list_add(txt_list, &e->list);
136*a1157835SDaniel Fojt return 0;
137*a1157835SDaniel Fojt }
138*a1157835SDaniel Fojt
139*a1157835SDaniel Fojt
cli_txt_list_add_addr(struct dl_list * txt_list,const char * txt)140*a1157835SDaniel Fojt int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
141*a1157835SDaniel Fojt {
142*a1157835SDaniel Fojt u8 addr[ETH_ALEN];
143*a1157835SDaniel Fojt char buf[18];
144*a1157835SDaniel Fojt
145*a1157835SDaniel Fojt if (hwaddr_aton(txt, addr) < 0)
146*a1157835SDaniel Fojt return -1;
147*a1157835SDaniel Fojt os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
148*a1157835SDaniel Fojt return cli_txt_list_add(txt_list, buf);
149*a1157835SDaniel Fojt }
150*a1157835SDaniel Fojt
151*a1157835SDaniel Fojt
cli_txt_list_add_word(struct dl_list * txt_list,const char * txt,int separator)152*a1157835SDaniel Fojt int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
153*a1157835SDaniel Fojt int separator)
154*a1157835SDaniel Fojt {
155*a1157835SDaniel Fojt const char *end;
156*a1157835SDaniel Fojt char *buf;
157*a1157835SDaniel Fojt int ret;
158*a1157835SDaniel Fojt
159*a1157835SDaniel Fojt end = os_strchr(txt, separator);
160*a1157835SDaniel Fojt if (end == NULL)
161*a1157835SDaniel Fojt end = txt + os_strlen(txt);
162*a1157835SDaniel Fojt buf = dup_binstr(txt, end - txt);
163*a1157835SDaniel Fojt if (buf == NULL)
164*a1157835SDaniel Fojt return -1;
165*a1157835SDaniel Fojt ret = cli_txt_list_add(txt_list, buf);
166*a1157835SDaniel Fojt os_free(buf);
167*a1157835SDaniel Fojt return ret;
168*a1157835SDaniel Fojt }
169*a1157835SDaniel Fojt
170*a1157835SDaniel Fojt
cli_txt_list_array(struct dl_list * txt_list)171*a1157835SDaniel Fojt char ** cli_txt_list_array(struct dl_list *txt_list)
172*a1157835SDaniel Fojt {
173*a1157835SDaniel Fojt unsigned int i, count = dl_list_len(txt_list);
174*a1157835SDaniel Fojt char **res;
175*a1157835SDaniel Fojt struct cli_txt_entry *e;
176*a1157835SDaniel Fojt
177*a1157835SDaniel Fojt res = os_calloc(count + 1, sizeof(char *));
178*a1157835SDaniel Fojt if (res == NULL)
179*a1157835SDaniel Fojt return NULL;
180*a1157835SDaniel Fojt
181*a1157835SDaniel Fojt i = 0;
182*a1157835SDaniel Fojt dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
183*a1157835SDaniel Fojt res[i] = os_strdup(e->txt);
184*a1157835SDaniel Fojt if (res[i] == NULL)
185*a1157835SDaniel Fojt break;
186*a1157835SDaniel Fojt i++;
187*a1157835SDaniel Fojt }
188*a1157835SDaniel Fojt
189*a1157835SDaniel Fojt return res;
190*a1157835SDaniel Fojt }
191*a1157835SDaniel Fojt
192*a1157835SDaniel Fojt
get_cmd_arg_num(const char * str,int pos)193*a1157835SDaniel Fojt int get_cmd_arg_num(const char *str, int pos)
194*a1157835SDaniel Fojt {
195*a1157835SDaniel Fojt int arg = 0, i;
196*a1157835SDaniel Fojt
197*a1157835SDaniel Fojt for (i = 0; i <= pos; i++) {
198*a1157835SDaniel Fojt if (str[i] != ' ') {
199*a1157835SDaniel Fojt arg++;
200*a1157835SDaniel Fojt while (i <= pos && str[i] != ' ')
201*a1157835SDaniel Fojt i++;
202*a1157835SDaniel Fojt }
203*a1157835SDaniel Fojt }
204*a1157835SDaniel Fojt
205*a1157835SDaniel Fojt if (arg > 0)
206*a1157835SDaniel Fojt arg--;
207*a1157835SDaniel Fojt return arg;
208*a1157835SDaniel Fojt }
209*a1157835SDaniel Fojt
210*a1157835SDaniel Fojt
write_cmd(char * buf,size_t buflen,const char * cmd,int argc,char * argv[])211*a1157835SDaniel Fojt int write_cmd(char *buf, size_t buflen, const char *cmd, int argc, char *argv[])
212*a1157835SDaniel Fojt {
213*a1157835SDaniel Fojt int i, res;
214*a1157835SDaniel Fojt char *pos, *end;
215*a1157835SDaniel Fojt
216*a1157835SDaniel Fojt pos = buf;
217*a1157835SDaniel Fojt end = buf + buflen;
218*a1157835SDaniel Fojt
219*a1157835SDaniel Fojt res = os_snprintf(pos, end - pos, "%s", cmd);
220*a1157835SDaniel Fojt if (os_snprintf_error(end - pos, res))
221*a1157835SDaniel Fojt goto fail;
222*a1157835SDaniel Fojt pos += res;
223*a1157835SDaniel Fojt
224*a1157835SDaniel Fojt for (i = 0; i < argc; i++) {
225*a1157835SDaniel Fojt res = os_snprintf(pos, end - pos, " %s", argv[i]);
226*a1157835SDaniel Fojt if (os_snprintf_error(end - pos, res))
227*a1157835SDaniel Fojt goto fail;
228*a1157835SDaniel Fojt pos += res;
229*a1157835SDaniel Fojt }
230*a1157835SDaniel Fojt
231*a1157835SDaniel Fojt buf[buflen - 1] = '\0';
232*a1157835SDaniel Fojt return 0;
233*a1157835SDaniel Fojt
234*a1157835SDaniel Fojt fail:
235*a1157835SDaniel Fojt printf("Too long command\n");
236*a1157835SDaniel Fojt return -1;
237*a1157835SDaniel Fojt }
238*a1157835SDaniel Fojt
239*a1157835SDaniel Fojt
tokenize_cmd(char * cmd,char * argv[])240*a1157835SDaniel Fojt int tokenize_cmd(char *cmd, char *argv[])
241*a1157835SDaniel Fojt {
242*a1157835SDaniel Fojt char *pos;
243*a1157835SDaniel Fojt int argc = 0;
244*a1157835SDaniel Fojt
245*a1157835SDaniel Fojt pos = cmd;
246*a1157835SDaniel Fojt for (;;) {
247*a1157835SDaniel Fojt while (*pos == ' ')
248*a1157835SDaniel Fojt pos++;
249*a1157835SDaniel Fojt if (*pos == '\0')
250*a1157835SDaniel Fojt break;
251*a1157835SDaniel Fojt argv[argc] = pos;
252*a1157835SDaniel Fojt argc++;
253*a1157835SDaniel Fojt if (argc == max_args)
254*a1157835SDaniel Fojt break;
255*a1157835SDaniel Fojt if (*pos == '"') {
256*a1157835SDaniel Fojt char *pos2 = os_strrchr(pos, '"');
257*a1157835SDaniel Fojt if (pos2)
258*a1157835SDaniel Fojt pos = pos2 + 1;
259*a1157835SDaniel Fojt }
260*a1157835SDaniel Fojt while (*pos != '\0' && *pos != ' ')
261*a1157835SDaniel Fojt pos++;
262*a1157835SDaniel Fojt if (*pos == ' ')
263*a1157835SDaniel Fojt *pos++ = '\0';
264*a1157835SDaniel Fojt }
265*a1157835SDaniel Fojt
266*a1157835SDaniel Fojt return argc;
267*a1157835SDaniel Fojt }
268