xref: /openbsd-src/usr.sbin/relayctl/parser.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /*	$OpenBSD: parser.c,v 1.21 2009/08/17 11:36:01 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/queue.h>
24 
25 #include <net/if.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 
29 #include <err.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <event.h>
36 
37 #include <openssl/ssl.h>
38 
39 #include "relayd.h"
40 
41 #include "parser.h"
42 
43 enum token_type {
44 	NOTOKEN,
45 	ENDTOKEN,
46 	HOSTID,
47 	TABLEID,
48 	RDRID,
49 	KEYWORD
50 };
51 
52 struct token {
53 	enum token_type		 type;
54 	const char		*keyword;
55 	int			 value;
56 	const struct token	*next;
57 };
58 
59 static const struct token t_main[];
60 static const struct token t_show[];
61 static const struct token t_rdr[];
62 static const struct token t_table[];
63 static const struct token t_host[];
64 static const struct token t_rdr_id[];
65 static const struct token t_table_id[];
66 static const struct token t_host_id[];
67 
68 static const struct token t_main[] = {
69 	{KEYWORD,	"monitor",	MONITOR,	NULL},
70 	{KEYWORD,	"show",		NONE,		t_show},
71 	{KEYWORD,	"poll",		POLL,		NULL},
72 	{KEYWORD,	"reload",	RELOAD,		NULL},
73 	{KEYWORD,	"stop",		SHUTDOWN,	NULL},
74 	{KEYWORD,	"redirect",	NONE,		t_rdr},
75 	{KEYWORD,	"table",	NONE,		t_table},
76 	{KEYWORD,	"host",		NONE,		t_host},
77 	{ENDTOKEN,	"",		NONE,		NULL}
78 };
79 
80 static const struct token t_show[] = {
81 	{KEYWORD,	"summary",	SHOW_SUM,	NULL},
82 	{KEYWORD,	"hosts",	SHOW_HOSTS,	NULL},
83 	{KEYWORD,	"redirects",	SHOW_RDRS,	NULL},
84 	{KEYWORD,	"relays",	SHOW_RELAYS,	NULL},
85 	{KEYWORD,	"routers",	SHOW_ROUTERS,	NULL},
86 	{KEYWORD,	"sessions",	SHOW_SESSIONS,	NULL},
87 	{ENDTOKEN,	"",		NONE,		NULL}
88 };
89 
90 static const struct token t_rdr[] = {
91 	{NOTOKEN,	"",		NONE,		NULL},
92 	{KEYWORD,	"disable",	RDR_DISABLE,	t_rdr_id},
93 	{KEYWORD,	"enable",	RDR_ENABLE,	t_rdr_id},
94 	{ENDTOKEN,	"",		NONE,		NULL}
95 };
96 
97 static const struct token t_table[] = {
98 	{NOTOKEN,	"",		NONE,		NULL},
99 	{KEYWORD,	"disable",	TABLE_DISABLE,	t_table_id},
100 	{KEYWORD,	"enable",	TABLE_ENABLE,	t_table_id},
101 	{ENDTOKEN,	"",		NONE,		NULL}
102 };
103 
104 static const struct token t_host[] = {
105 	{NOTOKEN,	"",		NONE,		NULL},
106 	{KEYWORD,	"disable",	HOST_DISABLE,	t_host_id},
107 	{KEYWORD,	"enable",	HOST_ENABLE,	t_host_id},
108 	{ENDTOKEN,	"",		NONE,		NULL}
109 };
110 
111 static const struct token t_rdr_id[] = {
112 	{RDRID,		"",		NONE,		NULL},
113 	{ENDTOKEN,	"",		NONE,		NULL}
114 };
115 
116 static const struct token t_table_id[] = {
117 	{TABLEID,	"",		NONE,		NULL},
118 	{ENDTOKEN,	"",		NONE,		NULL}
119 };
120 
121 static const struct token t_host_id[] = {
122 	{HOSTID,	"",		NONE,		NULL},
123 	{ENDTOKEN,	"",		NONE,		NULL}
124 };
125 
126 static struct parse_result	res;
127 
128 struct parse_result *
129 parse(int argc, char *argv[])
130 {
131 	const struct token	*table = t_main;
132 	const struct token	*match;
133 
134 	bzero(&res, sizeof(res));
135 
136 	while (argc >= 0) {
137 		if ((match = match_token(argv[0], table)) == NULL) {
138 			fprintf(stderr, "valid commands/args:\n");
139 			show_valid_args(table);
140 			return (NULL);
141 		}
142 
143 		argc--;
144 		argv++;
145 
146 		if (match->type == NOTOKEN || match->next == NULL)
147 			break;
148 
149 		table = match->next;
150 	}
151 
152 	if (argc > 0) {
153 		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
154 		return (NULL);
155 	}
156 
157 	return (&res);
158 }
159 
160 const struct token *
161 match_token(const char *word, const struct token table[])
162 {
163 	u_int			 i, match;
164 	const struct token	*t = NULL;
165 	const char		*errstr;
166 
167 	match = 0;
168 
169 	for (i = 0; table[i].type != ENDTOKEN; i++) {
170 		switch (table[i].type) {
171 		case NOTOKEN:
172 			if (word == NULL || strlen(word) == 0) {
173 				match++;
174 				t = &table[i];
175 			}
176 			break;
177 		case KEYWORD:
178 			if (word != NULL && strncmp(word, table[i].keyword,
179 			    strlen(word)) == 0) {
180 				match++;
181 				t = &table[i];
182 				if (t->value)
183 					res.action = t->value;
184 			}
185 			break;
186 		case HOSTID:
187 			if (word == NULL)
188 				break;
189 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
190 			if (errstr) {
191 				strlcpy(res.id.name, word, sizeof(res.id.name));
192 				res.id.id = EMPTY_ID;
193 			}
194 			t = &table[i];
195 			match++;
196 			break;
197 		case TABLEID:
198 			if (word == NULL)
199 				break;
200 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
201 			if (errstr) {
202 				strlcpy(res.id.name, word, sizeof(res.id.name));
203 				res.id.id = EMPTY_ID;
204 			}
205 			t = &table[i];
206 			match++;
207 			break;
208 		case RDRID:
209 			if (word == NULL)
210 				break;
211 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
212 			if (errstr) {
213 				strlcpy(res.id.name, word, sizeof(res.id.name));
214 				res.id.id = EMPTY_ID;
215 			}
216 			t = &table[i];
217 			match++;
218 			break;
219 		case ENDTOKEN:
220 			break;
221 		}
222 	}
223 
224 	if (match != 1) {
225 		if (word == NULL)
226 			fprintf(stderr, "missing argument:\n");
227 		else if (match > 1)
228 			fprintf(stderr, "ambiguous argument: %s\n", word);
229 		else if (match < 1)
230 			fprintf(stderr, "unknown argument: %s\n", word);
231 		return (NULL);
232 	}
233 
234 	return (t);
235 }
236 
237 void
238 show_valid_args(const struct token table[])
239 {
240 	int	i;
241 
242 	for (i = 0; table[i].type != ENDTOKEN; i++) {
243 		switch (table[i].type) {
244 		case NOTOKEN:
245 			fprintf(stderr, "  <cr>\n");
246 			break;
247 		case KEYWORD:
248 			fprintf(stderr, "  %s\n", table[i].keyword);
249 			break;
250 		case RDRID:
251 			fprintf(stderr, "  <redirectid>\n");
252 			break;
253 		case TABLEID:
254 			fprintf(stderr, "  <tableid>\n");
255 			break;
256 		case HOSTID:
257 			fprintf(stderr, "  <hostid>\n");
258 			break;
259 		case ENDTOKEN:
260 			break;
261 		}
262 	}
263 }
264