xref: /openbsd-src/usr.sbin/relayctl/parser.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: parser.c,v 1.20 2007/12/20 20:15:43 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,	"sessions",	SHOW_SESSIONS,	NULL},
86 	{ENDTOKEN,	"",		NONE,		NULL}
87 };
88 
89 static const struct token t_rdr[] = {
90 	{NOTOKEN,	"",		NONE,		NULL},
91 	{KEYWORD,	"disable",	RDR_DISABLE,	t_rdr_id},
92 	{KEYWORD,	"enable",	RDR_ENABLE,	t_rdr_id},
93 	{ENDTOKEN,	"",		NONE,		NULL}
94 };
95 
96 static const struct token t_table[] = {
97 	{NOTOKEN,	"",		NONE,		NULL},
98 	{KEYWORD,	"disable",	TABLE_DISABLE,	t_table_id},
99 	{KEYWORD,	"enable",	TABLE_ENABLE,	t_table_id},
100 	{ENDTOKEN,	"",		NONE,		NULL}
101 };
102 
103 static const struct token t_host[] = {
104 	{NOTOKEN,	"",		NONE,		NULL},
105 	{KEYWORD,	"disable",	HOST_DISABLE,	t_host_id},
106 	{KEYWORD,	"enable",	HOST_ENABLE,	t_host_id},
107 	{ENDTOKEN,	"",		NONE,		NULL}
108 };
109 
110 static const struct token t_rdr_id[] = {
111 	{RDRID,		"",		NONE,		NULL},
112 	{ENDTOKEN,	"",		NONE,		NULL}
113 };
114 
115 static const struct token t_table_id[] = {
116 	{TABLEID,	"",		NONE,		NULL},
117 	{ENDTOKEN,	"",		NONE,		NULL}
118 };
119 
120 static const struct token t_host_id[] = {
121 	{HOSTID,	"",		NONE,		NULL},
122 	{ENDTOKEN,	"",		NONE,		NULL}
123 };
124 
125 static struct parse_result	res;
126 
127 struct parse_result *
128 parse(int argc, char *argv[])
129 {
130 	const struct token	*table = t_main;
131 	const struct token	*match;
132 
133 	bzero(&res, sizeof(res));
134 
135 	while (argc >= 0) {
136 		if ((match = match_token(argv[0], table)) == NULL) {
137 			fprintf(stderr, "valid commands/args:\n");
138 			show_valid_args(table);
139 			return (NULL);
140 		}
141 
142 		argc--;
143 		argv++;
144 
145 		if (match->type == NOTOKEN || match->next == NULL)
146 			break;
147 
148 		table = match->next;
149 	}
150 
151 	if (argc > 0) {
152 		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
153 		return (NULL);
154 	}
155 
156 	return (&res);
157 }
158 
159 const struct token *
160 match_token(const char *word, const struct token table[])
161 {
162 	u_int			 i, match;
163 	const struct token	*t = NULL;
164 	const char		*errstr;
165 
166 	match = 0;
167 
168 	for (i = 0; table[i].type != ENDTOKEN; i++) {
169 		switch (table[i].type) {
170 		case NOTOKEN:
171 			if (word == NULL || strlen(word) == 0) {
172 				match++;
173 				t = &table[i];
174 			}
175 			break;
176 		case KEYWORD:
177 			if (word != NULL && strncmp(word, table[i].keyword,
178 			    strlen(word)) == 0) {
179 				match++;
180 				t = &table[i];
181 				if (t->value)
182 					res.action = t->value;
183 			}
184 			break;
185 		case HOSTID:
186 			if (word == NULL)
187 				break;
188 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
189 			if (errstr) {
190 				strlcpy(res.id.name, word, sizeof(res.id.name));
191 				res.id.id = EMPTY_ID;
192 			}
193 			t = &table[i];
194 			match++;
195 			break;
196 		case TABLEID:
197 			if (word == NULL)
198 				break;
199 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
200 			if (errstr) {
201 				strlcpy(res.id.name, word, sizeof(res.id.name));
202 				res.id.id = EMPTY_ID;
203 			}
204 			t = &table[i];
205 			match++;
206 			break;
207 		case RDRID:
208 			if (word == NULL)
209 				break;
210 			res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
211 			if (errstr) {
212 				strlcpy(res.id.name, word, sizeof(res.id.name));
213 				res.id.id = EMPTY_ID;
214 			}
215 			t = &table[i];
216 			match++;
217 			break;
218 		case ENDTOKEN:
219 			break;
220 		}
221 	}
222 
223 	if (match != 1) {
224 		if (word == NULL)
225 			fprintf(stderr, "missing argument:\n");
226 		else if (match > 1)
227 			fprintf(stderr, "ambiguous argument: %s\n", word);
228 		else if (match < 1)
229 			fprintf(stderr, "unknown argument: %s\n", word);
230 		return (NULL);
231 	}
232 
233 	return (t);
234 }
235 
236 void
237 show_valid_args(const struct token table[])
238 {
239 	int	i;
240 
241 	for (i = 0; table[i].type != ENDTOKEN; i++) {
242 		switch (table[i].type) {
243 		case NOTOKEN:
244 			fprintf(stderr, "  <cr>\n");
245 			break;
246 		case KEYWORD:
247 			fprintf(stderr, "  %s\n", table[i].keyword);
248 			break;
249 		case RDRID:
250 			fprintf(stderr, "  <redirectid>\n");
251 			break;
252 		case TABLEID:
253 			fprintf(stderr, "  <tableid>\n");
254 			break;
255 		case HOSTID:
256 			fprintf(stderr, "  <hostid>\n");
257 			break;
258 		case ENDTOKEN:
259 			break;
260 		}
261 	}
262 }
263