xref: /openbsd-src/usr.sbin/ikectl/parser.c (revision b41cc0c801858fe3ff012a866515bd2e80dfe6af)
1*b41cc0c8Stobhe /*	$OpenBSD: parser.c,v 1.21 2022/09/19 20:54:02 tobhe Exp $	*/
2901ee4f0Sreyk 
3901ee4f0Sreyk /*
4fcebd35dSreyk  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5901ee4f0Sreyk  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6901ee4f0Sreyk  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7901ee4f0Sreyk  *
8901ee4f0Sreyk  * Permission to use, copy, modify, and distribute this software for any
9901ee4f0Sreyk  * purpose with or without fee is hereby granted, provided that the above
10901ee4f0Sreyk  * copyright notice and this permission notice appear in all copies.
11901ee4f0Sreyk  *
12901ee4f0Sreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13901ee4f0Sreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14901ee4f0Sreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15901ee4f0Sreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16901ee4f0Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17901ee4f0Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18901ee4f0Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19901ee4f0Sreyk  */
20901ee4f0Sreyk 
21901ee4f0Sreyk #include <sys/types.h>
22901ee4f0Sreyk #include <sys/socket.h>
23901ee4f0Sreyk #include <sys/queue.h>
24901ee4f0Sreyk #include <sys/tree.h>
25901ee4f0Sreyk 
26901ee4f0Sreyk #include <err.h>
27901ee4f0Sreyk #include <errno.h>
28901ee4f0Sreyk #include <limits.h>
29901ee4f0Sreyk #include <stdio.h>
30901ee4f0Sreyk #include <stdlib.h>
31901ee4f0Sreyk #include <string.h>
32901ee4f0Sreyk #include <event.h>
33901ee4f0Sreyk #include <netdb.h>
34901ee4f0Sreyk 
35901ee4f0Sreyk #include "iked.h"
36901ee4f0Sreyk #include "parser.h"
37901ee4f0Sreyk 
38901ee4f0Sreyk enum token_type {
39901ee4f0Sreyk 	NOTOKEN,
40901ee4f0Sreyk 	ENDTOKEN,
41901ee4f0Sreyk 	KEYWORD,
427638a50cSjsg 	PATH,
43901ee4f0Sreyk 	CANAME,
440dd4c7c3Sjsg 	PEER,
45901ee4f0Sreyk 	ADDRESS,
46cfd26ebdSreyk 	FQDN,
478c502e93Stobhe 	PASSWORD,
488c502e93Stobhe 	IKEID
49901ee4f0Sreyk };
50901ee4f0Sreyk 
51901ee4f0Sreyk struct token {
52901ee4f0Sreyk 	enum token_type		 type;
53901ee4f0Sreyk 	const char		*keyword;
54901ee4f0Sreyk 	int			 value;
55901ee4f0Sreyk 	const struct token	*next;
56901ee4f0Sreyk };
57901ee4f0Sreyk 
58901ee4f0Sreyk static const struct token t_main[];
59901ee4f0Sreyk static const struct token t_reset[];
608c502e93Stobhe static const struct token t_reset_id[];
61901ee4f0Sreyk static const struct token t_log[];
62901ee4f0Sreyk static const struct token t_load[];
63901ee4f0Sreyk static const struct token t_ca[];
64cfd26ebdSreyk static const struct token t_ca_pass[];
65cfe372e4Sreyk static const struct token t_ca_pass_val[];
66cfe372e4Sreyk static const struct token t_ca_export[];
670dd4c7c3Sjsg static const struct token t_ca_ex_peer[];
68cfe372e4Sreyk static const struct token t_ca_ex_pass[];
69901ee4f0Sreyk static const struct token t_ca_modifiers[];
70901ee4f0Sreyk static const struct token t_ca_cert[];
71cfd26ebdSreyk static const struct token t_ca_cert_extusage[];
72901ee4f0Sreyk static const struct token t_ca_cert_modifiers[];
731dbb1d4aSjsg static const struct token t_ca_key[];
741dbb1d4aSjsg static const struct token t_ca_key_modifiers[];
751dbb1d4aSjsg static const struct token t_ca_key_path[];
76901ee4f0Sreyk static const struct token t_show[];
77901ee4f0Sreyk static const struct token t_show_ca[];
78901ee4f0Sreyk static const struct token t_show_ca_modifiers[];
7969ffd282Sreyk static const struct token t_show_ca_cert[];
807638a50cSjsg static const struct token t_opt_path[];
81901ee4f0Sreyk 
82901ee4f0Sreyk static const struct token t_main[] = {
83fc20f985Sreyk 	{ KEYWORD,	"active",	ACTIVE,		NULL },
84fc20f985Sreyk 	{ KEYWORD,	"passive",	PASSIVE,	NULL },
85fc20f985Sreyk 	{ KEYWORD,	"couple",	COUPLE,		NULL },
86fc20f985Sreyk 	{ KEYWORD,	"decouple",	DECOUPLE,	NULL },
87fc20f985Sreyk 	{ KEYWORD,	"load",		LOAD,		t_load },
88901ee4f0Sreyk 	{ KEYWORD,	"log",		NONE,		t_log },
89901ee4f0Sreyk 	{ KEYWORD,	"monitor",	MONITOR,	NULL },
90901ee4f0Sreyk 	{ KEYWORD,	"reload",	RELOAD,		NULL },
91fc20f985Sreyk 	{ KEYWORD,	"reset",	NONE,		t_reset },
92901ee4f0Sreyk 	{ KEYWORD,	"show",		NONE,		t_show },
93fc20f985Sreyk 	{ KEYWORD,	"ca",		CA,		t_ca },
94901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
95901ee4f0Sreyk };
96901ee4f0Sreyk 
97901ee4f0Sreyk static const struct token t_log[] = {
98901ee4f0Sreyk 	{ KEYWORD,	"verbose",	LOG_VERBOSE,	NULL },
99901ee4f0Sreyk 	{ KEYWORD,	"brief",	LOG_BRIEF,	NULL },
100901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
101901ee4f0Sreyk };
102901ee4f0Sreyk 
103901ee4f0Sreyk static const struct token t_reset[] = {
104901ee4f0Sreyk 	{ KEYWORD,	"all",		RESETALL,	NULL },
105901ee4f0Sreyk 	{ KEYWORD,	"ca",		RESETCA,	NULL },
106901ee4f0Sreyk 	{ KEYWORD,	"policy",	RESETPOLICY,	NULL },
107901ee4f0Sreyk 	{ KEYWORD,	"sa",		RESETSA,	NULL },
108901ee4f0Sreyk 	{ KEYWORD,	"user",		RESETUSER,	NULL },
1098c502e93Stobhe 	{ KEYWORD,	"id",		RESET_ID,	t_reset_id },
1108c502e93Stobhe 	{ ENDTOKEN,	"",		NONE,		NULL }
1118c502e93Stobhe };
1128c502e93Stobhe 
1138c502e93Stobhe static const struct token t_reset_id[] = {
1148c502e93Stobhe 	{ IKEID,	"",		NONE,		NULL },
115901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
116901ee4f0Sreyk };
117901ee4f0Sreyk 
118901ee4f0Sreyk static const struct token t_load[] = {
1197638a50cSjsg 	{ PATH,		"",		NONE,		NULL },
120901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
121901ee4f0Sreyk };
122901ee4f0Sreyk 
123901ee4f0Sreyk static const struct token t_ca[] = {
124901ee4f0Sreyk 	{ CANAME,	"",		NONE,		t_ca_modifiers },
125901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL },
126901ee4f0Sreyk };
127901ee4f0Sreyk 
128901ee4f0Sreyk static const struct token t_ca_modifiers[] = {
129cfd26ebdSreyk 	{ KEYWORD,	"create",	CA_CREATE,	t_ca_pass },
130901ee4f0Sreyk 	{ KEYWORD,	"delete",	CA_DELETE,	NULL },
1317638a50cSjsg 	{ KEYWORD,	"install",	CA_INSTALL,	t_opt_path },
132901ee4f0Sreyk 	{ KEYWORD,	"certificate",	CA_CERTIFICATE,	t_ca_cert },
1331dbb1d4aSjsg 	{ KEYWORD,	"key",		NONE,		t_ca_key },
134cfe372e4Sreyk 	{ KEYWORD,	"export",	CA_EXPORT,	t_ca_export },
135cfe372e4Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
136cfe372e4Sreyk };
137cfe372e4Sreyk 
138cfe372e4Sreyk static const struct token t_ca_pass_val[] = {
139cfe372e4Sreyk 	{ PASSWORD,	"",		NONE,		NULL },
140901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
141901ee4f0Sreyk };
142901ee4f0Sreyk 
143cfd26ebdSreyk static const struct token t_ca_pass[] = {
144cfd26ebdSreyk 	{ NOTOKEN,	"",		NONE,		NULL },
145cfe372e4Sreyk 	{ KEYWORD,	"password",	NONE,		t_ca_pass_val },
146cfe372e4Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
147cfe372e4Sreyk };
148cfe372e4Sreyk 
149cfe372e4Sreyk static const struct token t_ca_export[] = {
150cfe372e4Sreyk 	{ NOTOKEN,	"",		NONE,		NULL },
151cfe372e4Sreyk 	{ KEYWORD,	"peer",		NONE,		t_ca_ex_peer },
152cfe372e4Sreyk 	{ KEYWORD,	"password",	NONE,		t_ca_ex_pass },
153cfe372e4Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
154cfd26ebdSreyk };
155cfd26ebdSreyk 
1560dd4c7c3Sjsg static const struct token t_ca_ex_peer[] = {
157cfe372e4Sreyk 	{ PEER,		"",		NONE,		t_ca_export },
158cfe372e4Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
159cfe372e4Sreyk };
160cfe372e4Sreyk 
161cfe372e4Sreyk static const struct token t_ca_ex_pass[] = {
162cfe372e4Sreyk 	{ PASSWORD,	"",		NONE,		t_ca_export },
163cfe372e4Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
1640dd4c7c3Sjsg };
1650dd4c7c3Sjsg 
1667638a50cSjsg static const struct token t_opt_path[] = {
1677638a50cSjsg 	{ NOTOKEN,	"",		NONE,		NULL },
1687638a50cSjsg 	{ PATH,		"",		NONE,		NULL },
1697638a50cSjsg 	{ ENDTOKEN,	"",		NONE,		NULL }
1707638a50cSjsg };
1717638a50cSjsg 
172901ee4f0Sreyk static const struct token t_ca_cert[] = {
173901ee4f0Sreyk 	{ ADDRESS,	"",		NONE,		t_ca_cert_modifiers },
174901ee4f0Sreyk 	{ FQDN,		"",		NONE,		t_ca_cert_modifiers },
175901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
176901ee4f0Sreyk };
177901ee4f0Sreyk 
178901ee4f0Sreyk static const struct token t_ca_cert_modifiers[] = {
179cfd26ebdSreyk 	{ KEYWORD,	"create",	CA_CERT_CREATE,		t_ca_cert_extusage },
180901ee4f0Sreyk 	{ KEYWORD,	"delete",	CA_CERT_DELETE,		NULL },
1817638a50cSjsg 	{ KEYWORD,	"install",	CA_CERT_INSTALL,	t_opt_path },
182cfe372e4Sreyk 	{ KEYWORD,	"export",	CA_CERT_EXPORT,		t_ca_export },
183c3cc2c5eSjsg 	{ KEYWORD,	"revoke",	CA_CERT_REVOKE,		NULL },
184901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,			NULL }
185901ee4f0Sreyk };
186901ee4f0Sreyk 
187cfd26ebdSreyk static const struct token t_ca_cert_extusage[] = {
188cfd26ebdSreyk 	{ NOTOKEN,	"",		NONE,		NULL},
189cfd26ebdSreyk 	{ KEYWORD,	"server",	CA_SERVER,	NULL },
190cfd26ebdSreyk 	{ KEYWORD,	"client",	CA_CLIENT,	NULL },
191ab7171b1Sjsg 	{ KEYWORD,	"ocsp",		CA_OCSP,	NULL },
192cfd26ebdSreyk 	{ ENDTOKEN,	"",		NONE,		NULL },
193cfd26ebdSreyk };
194cfd26ebdSreyk 
1951dbb1d4aSjsg static const struct token t_ca_key[] = {
1961dbb1d4aSjsg 	{ ADDRESS,	"",		NONE,		t_ca_key_modifiers },
1971dbb1d4aSjsg 	{ FQDN,		"",		NONE,		t_ca_key_modifiers },
1981dbb1d4aSjsg 	{ ENDTOKEN,	"",		NONE,		NULL }
1991dbb1d4aSjsg };
2001dbb1d4aSjsg 
2011dbb1d4aSjsg static const struct token t_ca_key_modifiers[] = {
2021dbb1d4aSjsg 	{ KEYWORD,	"create",	CA_KEY_CREATE,		NULL },
2031dbb1d4aSjsg 	{ KEYWORD,	"delete",	CA_KEY_DELETE,		NULL },
2047638a50cSjsg 	{ KEYWORD,	"install",	CA_KEY_INSTALL,		t_opt_path },
2051dbb1d4aSjsg 	{ KEYWORD,	"import",	CA_KEY_IMPORT,		t_ca_key_path },
2061dbb1d4aSjsg 	{ ENDTOKEN,	"",		NONE,			NULL }
2071dbb1d4aSjsg };
2081dbb1d4aSjsg 
2091dbb1d4aSjsg static const struct token t_ca_key_path[] = {
2107638a50cSjsg 	{ PATH,		"",		NONE,		NULL },
2117638a50cSjsg 	{ PATH,		"",		NONE,		NULL }
2121dbb1d4aSjsg };
2131dbb1d4aSjsg 
214901ee4f0Sreyk static const struct token t_show[] = {
215901ee4f0Sreyk 	{ KEYWORD,	"ca",		SHOW_CA,	t_show_ca },
216969a8793Stobhe 	{ KEYWORD,	"sa",		SHOW_SA,	NULL },
2176cf0fa19Stobhe 	{ KEYWORD,	"certstore",	SHOW_CERTSTORE,NULL },
218*b41cc0c8Stobhe 	{ KEYWORD,	"stats",	SHOW_STATS,	NULL },
219901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
220901ee4f0Sreyk };
221901ee4f0Sreyk 
222901ee4f0Sreyk static const struct token t_show_ca[] = {
223901ee4f0Sreyk 	{ CANAME,	"",		NONE,		t_show_ca_modifiers },
224901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL },
225901ee4f0Sreyk };
226901ee4f0Sreyk 
227901ee4f0Sreyk static const struct token t_show_ca_modifiers[] = {
22869ffd282Sreyk 	{ KEYWORD,	"certificates",	SHOW_CA_CERTIFICATES,	t_show_ca_cert },
22969ffd282Sreyk 	{ ENDTOKEN,	"",		NONE,			NULL }
23069ffd282Sreyk };
23169ffd282Sreyk 
23269ffd282Sreyk static const struct token t_show_ca_cert[] = {
23369ffd282Sreyk 	{ NOTOKEN,	"",		NONE,		NULL },
23469ffd282Sreyk 	{ ADDRESS,	"",		NONE,		NULL },
23569ffd282Sreyk 	{ FQDN,		"",		NONE,		NULL },
236901ee4f0Sreyk 	{ ENDTOKEN,	"",		NONE,		NULL }
237901ee4f0Sreyk };
238901ee4f0Sreyk 
239901ee4f0Sreyk static struct parse_result	 res;
240901ee4f0Sreyk 
241901ee4f0Sreyk const struct token		*match_token(char *, const struct token []);
242901ee4f0Sreyk void				 show_valid_args(const struct token []);
243901ee4f0Sreyk int				 parse_addr(const char *);
244901ee4f0Sreyk 
245901ee4f0Sreyk struct parse_result *
parse(int argc,char * argv[])246901ee4f0Sreyk parse(int argc, char *argv[])
247901ee4f0Sreyk {
248901ee4f0Sreyk 	const struct token	*table = t_main;
249901ee4f0Sreyk 	const struct token	*match;
250901ee4f0Sreyk 
251901ee4f0Sreyk 	bzero(&res, sizeof(res));
252901ee4f0Sreyk 
253901ee4f0Sreyk 	while (argc >= 0) {
254901ee4f0Sreyk 		if ((match = match_token(argv[0], table)) == NULL) {
255901ee4f0Sreyk 			fprintf(stderr, "valid commands/args:\n");
256901ee4f0Sreyk 			show_valid_args(table);
257901ee4f0Sreyk 			return (NULL);
258901ee4f0Sreyk 		}
259901ee4f0Sreyk 
260901ee4f0Sreyk 		argc--;
261901ee4f0Sreyk 		argv++;
262901ee4f0Sreyk 
263901ee4f0Sreyk 		if (match->type == NOTOKEN || match->next == NULL)
264901ee4f0Sreyk 			break;
265901ee4f0Sreyk 
266901ee4f0Sreyk 		table = match->next;
267901ee4f0Sreyk 	}
268901ee4f0Sreyk 
269901ee4f0Sreyk 	if (argc > 0) {
270901ee4f0Sreyk 		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
271901ee4f0Sreyk 		return (NULL);
272901ee4f0Sreyk 	}
273901ee4f0Sreyk 
274901ee4f0Sreyk 	return (&res);
275901ee4f0Sreyk }
276901ee4f0Sreyk 
277901ee4f0Sreyk int
parse_addr(const char * word)278901ee4f0Sreyk parse_addr(const char *word)
279901ee4f0Sreyk {
280901ee4f0Sreyk 	struct addrinfo hints, *r;
281901ee4f0Sreyk 
282901ee4f0Sreyk 	bzero(&hints, sizeof(hints));
283901ee4f0Sreyk 	hints.ai_socktype = SOCK_DGRAM; /* dummy */
284901ee4f0Sreyk 	hints.ai_family = PF_UNSPEC;
285901ee4f0Sreyk 	hints.ai_flags = AI_NUMERICHOST;
286901ee4f0Sreyk 	if (getaddrinfo(word, "0", &hints, &r) == 0) {
28785b76f66Sbenno 		freeaddrinfo(r);
288901ee4f0Sreyk 		return (0);
289901ee4f0Sreyk 	}
290901ee4f0Sreyk 
291901ee4f0Sreyk 	return (1);
292901ee4f0Sreyk }
293901ee4f0Sreyk 
294901ee4f0Sreyk 
295901ee4f0Sreyk const struct token *
match_token(char * word,const struct token table[])296901ee4f0Sreyk match_token(char *word, const struct token table[])
297901ee4f0Sreyk {
298ef316c85Sreyk 	unsigned int		 i, match = 0;
299901ee4f0Sreyk 	const struct token	*t = NULL;
300901ee4f0Sreyk 
301901ee4f0Sreyk 	for (i = 0; table[i].type != ENDTOKEN; i++) {
302901ee4f0Sreyk 		switch (table[i].type) {
303901ee4f0Sreyk 		case NOTOKEN:
304901ee4f0Sreyk 			if (word == NULL || strlen(word) == 0) {
305901ee4f0Sreyk 				match++;
306901ee4f0Sreyk 				t = &table[i];
307901ee4f0Sreyk 			}
308901ee4f0Sreyk 			break;
309901ee4f0Sreyk 		case KEYWORD:
310901ee4f0Sreyk 			if (word != NULL && strncmp(word, table[i].keyword,
311901ee4f0Sreyk 			    strlen(word)) == 0) {
312901ee4f0Sreyk 				match++;
313901ee4f0Sreyk 				t = &table[i];
314901ee4f0Sreyk 				if (t->value)
315901ee4f0Sreyk 					res.action = t->value;
316901ee4f0Sreyk 			}
317901ee4f0Sreyk 			break;
3187638a50cSjsg 		case PATH:
319901ee4f0Sreyk 			if (!match && word != NULL && strlen(word) > 0) {
3207638a50cSjsg 				res.path = strdup(word);
321901ee4f0Sreyk 				match++;
322901ee4f0Sreyk 				t = &table[i];
323901ee4f0Sreyk 			}
324901ee4f0Sreyk 			break;
325901ee4f0Sreyk 		case CANAME:
326901ee4f0Sreyk 			if (!match && word != NULL && strlen(word) > 0) {
327901ee4f0Sreyk 				res.caname = strdup(word);
328901ee4f0Sreyk 				match++;
329901ee4f0Sreyk 				t = &table[i];
330901ee4f0Sreyk 			}
331901ee4f0Sreyk 			break;
3320dd4c7c3Sjsg 		case PEER:
3330dd4c7c3Sjsg 			if (!match && word != NULL && strlen(word) > 0) {
3340dd4c7c3Sjsg 				res.peer = strdup(word);
3350dd4c7c3Sjsg 				match++;
3360dd4c7c3Sjsg 				t = &table[i];
3370dd4c7c3Sjsg 			}
3380dd4c7c3Sjsg 			break;
339901ee4f0Sreyk 		case ADDRESS:
340901ee4f0Sreyk 		case FQDN:
341901ee4f0Sreyk 			if (!match && word != NULL && strlen(word) > 0) {
342901ee4f0Sreyk 				res.host = strdup(word);
343901ee4f0Sreyk 				if (parse_addr(word) == 0)
344901ee4f0Sreyk 					res.htype = HOST_IPADDR;
345901ee4f0Sreyk 				else
346901ee4f0Sreyk 					res.htype = HOST_FQDN;
347901ee4f0Sreyk 				match++;
348901ee4f0Sreyk 				t = &table[i];
349901ee4f0Sreyk 			}
350901ee4f0Sreyk 			break;
351cfd26ebdSreyk 		case PASSWORD:
352cfd26ebdSreyk 			if (!match && word != NULL && strlen(word) > 0) {
353cfd26ebdSreyk 				res.pass = strdup(word);
354cfd26ebdSreyk 				match++;
355cfd26ebdSreyk 				t = &table[i];
356cfd26ebdSreyk 			}
357cfd26ebdSreyk 			break;
3588c502e93Stobhe 		case IKEID:
3598c502e93Stobhe 			if (!match && word != NULL && strlen(word) > 0) {
3608c502e93Stobhe 				res.id = strdup(word);
3618c502e93Stobhe 				match++;
3628c502e93Stobhe 				t = &table[i];
3638c502e93Stobhe 			}
3648c502e93Stobhe 			break;
365901ee4f0Sreyk 		case ENDTOKEN:
366901ee4f0Sreyk 			break;
367901ee4f0Sreyk 		}
368901ee4f0Sreyk 	}
369901ee4f0Sreyk 
370901ee4f0Sreyk 	if (match != 1) {
371901ee4f0Sreyk 		if (word == NULL)
372901ee4f0Sreyk 			fprintf(stderr, "missing argument:\n");
373901ee4f0Sreyk 		else if (match > 1)
374901ee4f0Sreyk 			fprintf(stderr, "ambiguous argument: %s\n", word);
375901ee4f0Sreyk 		else if (match < 1)
376901ee4f0Sreyk 			fprintf(stderr, "unknown argument: %s\n", word);
377901ee4f0Sreyk 		return (NULL);
378901ee4f0Sreyk 	}
379901ee4f0Sreyk 
380901ee4f0Sreyk 	return (t);
381901ee4f0Sreyk }
382901ee4f0Sreyk 
383901ee4f0Sreyk void
show_valid_args(const struct token table[])384901ee4f0Sreyk show_valid_args(const struct token table[])
385901ee4f0Sreyk {
386901ee4f0Sreyk 	int	i;
387901ee4f0Sreyk 
388901ee4f0Sreyk 	for (i = 0; table[i].type != ENDTOKEN; i++) {
389901ee4f0Sreyk 		switch (table[i].type) {
390901ee4f0Sreyk 		case NOTOKEN:
391901ee4f0Sreyk 			fprintf(stderr, "  <cr>\n");
392901ee4f0Sreyk 			break;
393901ee4f0Sreyk 		case KEYWORD:
394901ee4f0Sreyk 			fprintf(stderr, "  %s\n", table[i].keyword);
395901ee4f0Sreyk 			break;
3967638a50cSjsg 		case PATH:
3977638a50cSjsg 			fprintf(stderr, "  <path>\n");
398901ee4f0Sreyk 			break;
399901ee4f0Sreyk 		case CANAME:
400901ee4f0Sreyk 			fprintf(stderr, "  <caname>\n");
401901ee4f0Sreyk 			break;
402cfd26ebdSreyk 		case PASSWORD:
403cfd26ebdSreyk 			fprintf(stderr, "  <password>\n");
404cfd26ebdSreyk 			break;
4050dd4c7c3Sjsg 		case PEER:
4060dd4c7c3Sjsg 			fprintf(stderr, "  <peer>\n");
4070dd4c7c3Sjsg 			break;
408901ee4f0Sreyk 		case ADDRESS:
409901ee4f0Sreyk 			fprintf(stderr, "  <ipaddr>\n");
410901ee4f0Sreyk 			break;
411901ee4f0Sreyk 		case FQDN:
412901ee4f0Sreyk 			fprintf(stderr, "  <fqdn>\n");
413901ee4f0Sreyk 			break;
4148c502e93Stobhe 		case IKEID:
4158c502e93Stobhe 			fprintf(stderr, "  <ikeid>\n");
4168c502e93Stobhe 			break;
417901ee4f0Sreyk 		case ENDTOKEN:
418901ee4f0Sreyk 			break;
419901ee4f0Sreyk 		}
420901ee4f0Sreyk 	}
421901ee4f0Sreyk }
422