GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/dvmrpctl/parser.c Lines: 0 84 0.0 %
Date: 2017-11-13 Branches: 0 76 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parser.c,v 1.6 2017/07/28 13:03:23 florian Exp $ */
2
3
/*
4
 * Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org>
5
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/socket.h>
22
#include <netinet/in.h>
23
#include <arpa/inet.h>
24
#include <err.h>
25
#include <errno.h>
26
#include <limits.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include "dvmrpd.h"
32
#include "parser.h"
33
34
enum token_type {
35
	NOTOKEN,
36
	ENDTOKEN,
37
	KEYWORD,
38
	ADDRESS,
39
	FLAG,
40
	PREFIX,
41
	IFNAME
42
};
43
44
struct token {
45
	enum token_type		 type;
46
	const char		*keyword;
47
	int			 value;
48
	const struct token	*next;
49
};
50
51
static const struct token t_main[];
52
static const struct token t_show[];
53
static const struct token t_show_iface[];
54
static const struct token t_show_nbr[];
55
static const struct token t_show_mfc[];
56
static const struct token t_show_rib[];
57
static const struct token t_log[];
58
59
static const struct token t_main[] = {
60
/*	{KEYWORD,	"reload",	RELOAD,		NULL}, */
61
	{KEYWORD,	"show",		SHOW,		t_show},
62
	{KEYWORD,	"log",		NONE,		t_log},
63
	{ENDTOKEN,	"",		NONE,		NULL}
64
};
65
66
static const struct token t_show[] = {
67
	{NOTOKEN,	"",		NONE,		NULL},
68
	{KEYWORD,	"igmp",		SHOW_IGMP,	NULL},
69
	{KEYWORD,	"interfaces",	SHOW_IFACE,	t_show_iface},
70
	{KEYWORD,	"mfc",		SHOW_MFC,	t_show_mfc},
71
	{KEYWORD,	"neighbor",	SHOW_NBR,	t_show_nbr},
72
	{KEYWORD,	"rib",		SHOW_RIB,	t_show_rib},
73
	{KEYWORD,	"summary",	SHOW_SUM,	NULL},
74
	{ENDTOKEN,	"",		NONE,		NULL}
75
};
76
77
static const struct token t_show_iface[] = {
78
	{NOTOKEN,	"",		NONE,		NULL},
79
	{KEYWORD,	"detail",	SHOW_IFACE_DTAIL,NULL},
80
	{IFNAME,	"",		SHOW_IFACE_DTAIL,NULL},
81
	{ENDTOKEN,	"",		NONE,		NULL}
82
};
83
84
static const struct token t_show_mfc[] = {
85
	{NOTOKEN,	"",		NONE,		NULL},
86
	{KEYWORD,	"detail",	SHOW_MFC_DTAIL,	NULL},
87
	{ENDTOKEN,	"",		NONE,		NULL}
88
};
89
90
static const struct token t_show_nbr[] = {
91
	{NOTOKEN,	"",		NONE,		NULL},
92
	{KEYWORD,	"detail",	SHOW_NBR_DTAIL,	NULL},
93
	{ENDTOKEN,	"",		NONE,		NULL}
94
};
95
96
static const struct token t_show_rib[] = {
97
	{NOTOKEN,	"",		NONE,		NULL},
98
	{KEYWORD,	"detail",	SHOW_RIB_DTAIL,	NULL},
99
	{ENDTOKEN,	"",		NONE,		NULL}
100
};
101
102
static const struct token t_log[] = {
103
	{KEYWORD,	"verbose",	LOG_VERBOSE,	NULL},
104
	{KEYWORD,	"brief",	LOG_BRIEF,	NULL},
105
	{ENDTOKEN,	"",		NONE,		NULL}
106
};
107
108
109
static void show_valid_args(const struct token *);
110
static const struct token *match_token(const char *, const struct token *,
111
    struct parse_result *);
112
113
struct parse_result *
114
parse(int argc, char *argv[])
115
{
116
	static struct parse_result	res;
117
	const struct token	*table = t_main;
118
	const struct token	*match;
119
120
	bzero(&res, sizeof(res));
121
122
	while (argc >= 0) {
123
		if ((match = match_token(argv[0], table, &res)) == NULL) {
124
			fprintf(stderr, "valid commands/args:\n");
125
			show_valid_args(table);
126
			return (NULL);
127
		}
128
129
		argc--;
130
		argv++;
131
132
		if (match->type == NOTOKEN || match->next == NULL)
133
			break;
134
135
		table = match->next;
136
	}
137
138
	if (argc > 0) {
139
		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
140
		return (NULL);
141
	}
142
143
	return (&res);
144
}
145
146
static const struct token *
147
match_token(const char *word, const struct token *table,
148
    struct parse_result *res)
149
{
150
	u_int			 i, match;
151
	const struct token	*t = NULL;
152
153
	match = 0;
154
155
	for (i = 0; table[i].type != ENDTOKEN; i++) {
156
		switch (table[i].type) {
157
		case NOTOKEN:
158
			if (word == NULL || strlen(word) == 0) {
159
				match++;
160
				t = &table[i];
161
			}
162
			break;
163
		case KEYWORD:
164
			if (word != NULL && strncmp(word, table[i].keyword,
165
			    strlen(word)) == 0) {
166
				match++;
167
				t = &table[i];
168
				if (t->value)
169
					res->action = t->value;
170
			}
171
			break;
172
		case FLAG:
173
			if (word != NULL && strncmp(word, table[i].keyword,
174
			    strlen(word)) == 0) {
175
				match++;
176
				t = &table[i];
177
				res->flags |= t->value;
178
			}
179
			break;
180
		case ADDRESS:
181
			if (parse_addr(word, &res->addr)) {
182
				match++;
183
				t = &table[i];
184
				if (t->value)
185
					res->action = t->value;
186
			}
187
			break;
188
		case PREFIX:
189
			if (parse_prefix(word, &res->addr, &res->prefixlen)) {
190
				match++;
191
				t = &table[i];
192
				if (t->value)
193
					res->action = t->value;
194
			}
195
			break;
196
		case IFNAME:
197
			if (!match && word != NULL && strlen(word) > 0) {
198
				if (strlcpy(res->ifname, word,
199
				    sizeof(res->ifname)) >=
200
				    sizeof(res->ifname))
201
					err(1, "interface name too long");
202
				match++;
203
				t = &table[i];
204
				if (t->value)
205
					res->action = t->value;
206
			}
207
			break;
208
209
		case ENDTOKEN:
210
			break;
211
		}
212
	}
213
214
	if (match != 1) {
215
		if (word == NULL)
216
			fprintf(stderr, "missing argument:\n");
217
		else if (match > 1)
218
			fprintf(stderr, "ambiguous argument: %s\n", word);
219
		else if (match < 1)
220
			fprintf(stderr, "unknown argument: %s\n", word);
221
		return (NULL);
222
	}
223
224
	return (t);
225
}
226
227
static void
228
show_valid_args(const struct token *table)
229
{
230
	int	i;
231
232
	for (i = 0; table[i].type != ENDTOKEN; i++) {
233
		switch (table[i].type) {
234
		case NOTOKEN:
235
			fprintf(stderr, "  <cr>\n");
236
			break;
237
		case KEYWORD:
238
		case FLAG:
239
			fprintf(stderr, "  %s\n", table[i].keyword);
240
			break;
241
		case ADDRESS:
242
			fprintf(stderr, "  <address>\n");
243
			break;
244
		case PREFIX:
245
			fprintf(stderr, "  <address>[/<len>]\n");
246
			break;
247
		case IFNAME:
248
			fprintf(stderr, "  <interface>\n");
249
		case ENDTOKEN:
250
			break;
251
		}
252
	}
253
}
254
255
int
256
parse_addr(const char *word, struct in_addr *addr)
257
{
258
	struct in_addr	ina;
259
260
	if (word == NULL)
261
		return (0);
262
263
	bzero(addr, sizeof(struct in_addr));
264
	bzero(&ina, sizeof(ina));
265
266
	if (inet_pton(AF_INET, word, &ina)) {
267
		addr->s_addr = ina.s_addr;
268
		return (1);
269
	}
270
271
	return (0);
272
}
273
274
int
275
parse_prefix(const char *word, struct in_addr *addr, u_int8_t *prefixlen)
276
{
277
	struct in_addr	 ina;
278
	int		 bits = 32;
279
280
	if (word == NULL)
281
		return (0);
282
283
	bzero(addr, sizeof(struct in_addr));
284
	bzero(&ina, sizeof(ina));
285
286
	if (strrchr(word, '/') != NULL) {
287
		if ((bits = inet_net_pton(AF_INET, word,
288
		    &ina, sizeof(ina))) == -1)
289
			return (0);
290
		addr->s_addr = ina.s_addr & htonl(0xffffffff << (32 - bits));
291
		*prefixlen = bits;
292
		return (1);
293
	} else {
294
		*prefixlen = 32;
295
		return (parse_addr(word, addr));
296
	}
297
298
	return (0);
299
}