xref: /openbsd-src/usr.sbin/dvmrpctl/parser.c (revision 2eb014afe8bae0be6719f8769b3ad1fcf60679f6)
1*2eb014afSflorian /*	$OpenBSD: parser.c,v 1.6 2017/07/28 13:03:23 florian Exp $ */
289189827Snorby 
389189827Snorby /*
489189827Snorby  * Copyright (c) 2004, 2005, 2006 Esben Norby <norby@openbsd.org>
589189827Snorby  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
689189827Snorby  *
789189827Snorby  * Permission to use, copy, modify, and distribute this software for any
889189827Snorby  * purpose with or without fee is hereby granted, provided that the above
989189827Snorby  * copyright notice and this permission notice appear in all copies.
1089189827Snorby  *
1189189827Snorby  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1289189827Snorby  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1389189827Snorby  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1489189827Snorby  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1589189827Snorby  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1689189827Snorby  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1789189827Snorby  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1889189827Snorby  */
1989189827Snorby 
2089189827Snorby #include <sys/types.h>
2189189827Snorby #include <sys/socket.h>
2289189827Snorby #include <netinet/in.h>
2389189827Snorby #include <arpa/inet.h>
2489189827Snorby #include <err.h>
2589189827Snorby #include <errno.h>
2689189827Snorby #include <limits.h>
2789189827Snorby #include <stdio.h>
2889189827Snorby #include <stdlib.h>
2989189827Snorby #include <string.h>
3089189827Snorby 
3189189827Snorby #include "dvmrpd.h"
3289189827Snorby #include "parser.h"
3389189827Snorby 
3489189827Snorby enum token_type {
3589189827Snorby 	NOTOKEN,
3689189827Snorby 	ENDTOKEN,
3789189827Snorby 	KEYWORD,
3889189827Snorby 	ADDRESS,
3989189827Snorby 	FLAG,
4089189827Snorby 	PREFIX,
4189189827Snorby 	IFNAME
4289189827Snorby };
4389189827Snorby 
4489189827Snorby struct token {
4589189827Snorby 	enum token_type		 type;
4689189827Snorby 	const char		*keyword;
4789189827Snorby 	int			 value;
4889189827Snorby 	const struct token	*next;
4989189827Snorby };
5089189827Snorby 
5189189827Snorby static const struct token t_main[];
5289189827Snorby static const struct token t_show[];
5389189827Snorby static const struct token t_show_iface[];
5489189827Snorby static const struct token t_show_nbr[];
5589189827Snorby static const struct token t_show_mfc[];
5689189827Snorby static const struct token t_show_rib[];
57c3319070Sclaudio static const struct token t_log[];
5889189827Snorby 
5989189827Snorby static const struct token t_main[] = {
6089189827Snorby /*	{KEYWORD,	"reload",	RELOAD,		NULL}, */
6189189827Snorby 	{KEYWORD,	"show",		SHOW,		t_show},
62c3319070Sclaudio 	{KEYWORD,	"log",		NONE,		t_log},
6389189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
6489189827Snorby };
6589189827Snorby 
6689189827Snorby static const struct token t_show[] = {
6789189827Snorby 	{NOTOKEN,	"",		NONE,		NULL},
6889189827Snorby 	{KEYWORD,	"igmp",		SHOW_IGMP,	NULL},
6989189827Snorby 	{KEYWORD,	"interfaces",	SHOW_IFACE,	t_show_iface},
7089189827Snorby 	{KEYWORD,	"mfc",		SHOW_MFC,	t_show_mfc},
7189189827Snorby 	{KEYWORD,	"neighbor",	SHOW_NBR,	t_show_nbr},
7289189827Snorby 	{KEYWORD,	"rib",		SHOW_RIB,	t_show_rib},
7389189827Snorby 	{KEYWORD,	"summary",	SHOW_SUM,	NULL},
7489189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
7589189827Snorby };
7689189827Snorby 
7789189827Snorby static const struct token t_show_iface[] = {
7889189827Snorby 	{NOTOKEN,	"",		NONE,		NULL},
7989189827Snorby 	{KEYWORD,	"detail",	SHOW_IFACE_DTAIL,NULL},
8089189827Snorby 	{IFNAME,	"",		SHOW_IFACE_DTAIL,NULL},
8189189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
8289189827Snorby };
8389189827Snorby 
8489189827Snorby static const struct token t_show_mfc[] = {
8589189827Snorby 	{NOTOKEN,	"",		NONE,		NULL},
8689189827Snorby 	{KEYWORD,	"detail",	SHOW_MFC_DTAIL,	NULL},
8789189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
8889189827Snorby };
8989189827Snorby 
9089189827Snorby static const struct token t_show_nbr[] = {
9189189827Snorby 	{NOTOKEN,	"",		NONE,		NULL},
9289189827Snorby 	{KEYWORD,	"detail",	SHOW_NBR_DTAIL,	NULL},
9389189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
9489189827Snorby };
9589189827Snorby 
9689189827Snorby static const struct token t_show_rib[] = {
9789189827Snorby 	{NOTOKEN,	"",		NONE,		NULL},
9889189827Snorby 	{KEYWORD,	"detail",	SHOW_RIB_DTAIL,	NULL},
9989189827Snorby 	{ENDTOKEN,	"",		NONE,		NULL}
10089189827Snorby };
10189189827Snorby 
102c3319070Sclaudio static const struct token t_log[] = {
103c3319070Sclaudio 	{KEYWORD,	"verbose",	LOG_VERBOSE,	NULL},
104c3319070Sclaudio 	{KEYWORD,	"brief",	LOG_BRIEF,	NULL},
105c3319070Sclaudio 	{ENDTOKEN,	"",		NONE,		NULL}
106c3319070Sclaudio };
107c3319070Sclaudio 
108c3319070Sclaudio 
1096be5843eStedu static void show_valid_args(const struct token *);
1106be5843eStedu static const struct token *match_token(const char *, const struct token *,
1116be5843eStedu     struct parse_result *);
11289189827Snorby 
11389189827Snorby struct parse_result *
parse(int argc,char * argv[])11489189827Snorby parse(int argc, char *argv[])
11589189827Snorby {
1166be5843eStedu 	static struct parse_result	res;
11789189827Snorby 	const struct token	*table = t_main;
11889189827Snorby 	const struct token	*match;
11989189827Snorby 
12089189827Snorby 	bzero(&res, sizeof(res));
12189189827Snorby 
1228af2c3a1Sclaudio 	while (argc >= 0) {
1236be5843eStedu 		if ((match = match_token(argv[0], table, &res)) == NULL) {
12489189827Snorby 			fprintf(stderr, "valid commands/args:\n");
12589189827Snorby 			show_valid_args(table);
12689189827Snorby 			return (NULL);
12789189827Snorby 		}
12889189827Snorby 
12989189827Snorby 		argc--;
13089189827Snorby 		argv++;
13189189827Snorby 
13289189827Snorby 		if (match->type == NOTOKEN || match->next == NULL)
13389189827Snorby 			break;
13489189827Snorby 
13589189827Snorby 		table = match->next;
13689189827Snorby 	}
13789189827Snorby 
13889189827Snorby 	if (argc > 0) {
13989189827Snorby 		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
14089189827Snorby 		return (NULL);
14189189827Snorby 	}
14289189827Snorby 
14389189827Snorby 	return (&res);
14489189827Snorby }
14589189827Snorby 
1466be5843eStedu static const struct token *
match_token(const char * word,const struct token * table,struct parse_result * res)1476be5843eStedu match_token(const char *word, const struct token *table,
1486be5843eStedu     struct parse_result *res)
14989189827Snorby {
15089189827Snorby 	u_int			 i, match;
15189189827Snorby 	const struct token	*t = NULL;
15289189827Snorby 
15389189827Snorby 	match = 0;
15489189827Snorby 
15589189827Snorby 	for (i = 0; table[i].type != ENDTOKEN; i++) {
15689189827Snorby 		switch (table[i].type) {
15789189827Snorby 		case NOTOKEN:
15889189827Snorby 			if (word == NULL || strlen(word) == 0) {
15989189827Snorby 				match++;
16089189827Snorby 				t = &table[i];
16189189827Snorby 			}
16289189827Snorby 			break;
16389189827Snorby 		case KEYWORD:
16489189827Snorby 			if (word != NULL && strncmp(word, table[i].keyword,
16589189827Snorby 			    strlen(word)) == 0) {
16689189827Snorby 				match++;
16789189827Snorby 				t = &table[i];
16889189827Snorby 				if (t->value)
1696be5843eStedu 					res->action = t->value;
17089189827Snorby 			}
17189189827Snorby 			break;
17289189827Snorby 		case FLAG:
17389189827Snorby 			if (word != NULL && strncmp(word, table[i].keyword,
17489189827Snorby 			    strlen(word)) == 0) {
17589189827Snorby 				match++;
17689189827Snorby 				t = &table[i];
1776be5843eStedu 				res->flags |= t->value;
17889189827Snorby 			}
17989189827Snorby 			break;
18089189827Snorby 		case ADDRESS:
1816be5843eStedu 			if (parse_addr(word, &res->addr)) {
18289189827Snorby 				match++;
18389189827Snorby 				t = &table[i];
18489189827Snorby 				if (t->value)
1856be5843eStedu 					res->action = t->value;
18689189827Snorby 			}
18789189827Snorby 			break;
18889189827Snorby 		case PREFIX:
1896be5843eStedu 			if (parse_prefix(word, &res->addr, &res->prefixlen)) {
19089189827Snorby 				match++;
19189189827Snorby 				t = &table[i];
19289189827Snorby 				if (t->value)
1936be5843eStedu 					res->action = t->value;
19489189827Snorby 			}
19589189827Snorby 			break;
19689189827Snorby 		case IFNAME:
19789189827Snorby 			if (!match && word != NULL && strlen(word) > 0) {
1986be5843eStedu 				if (strlcpy(res->ifname, word,
1996be5843eStedu 				    sizeof(res->ifname)) >=
2006be5843eStedu 				    sizeof(res->ifname))
20189189827Snorby 					err(1, "interface name too long");
20289189827Snorby 				match++;
20389189827Snorby 				t = &table[i];
20489189827Snorby 				if (t->value)
2056be5843eStedu 					res->action = t->value;
20689189827Snorby 			}
20789189827Snorby 			break;
20889189827Snorby 
20989189827Snorby 		case ENDTOKEN:
21089189827Snorby 			break;
21189189827Snorby 		}
21289189827Snorby 	}
21389189827Snorby 
21489189827Snorby 	if (match != 1) {
2158af2c3a1Sclaudio 		if (word == NULL)
2168af2c3a1Sclaudio 			fprintf(stderr, "missing argument:\n");
2178af2c3a1Sclaudio 		else if (match > 1)
21889189827Snorby 			fprintf(stderr, "ambiguous argument: %s\n", word);
2198af2c3a1Sclaudio 		else if (match < 1)
22089189827Snorby 			fprintf(stderr, "unknown argument: %s\n", word);
22189189827Snorby 		return (NULL);
22289189827Snorby 	}
22389189827Snorby 
22489189827Snorby 	return (t);
22589189827Snorby }
22689189827Snorby 
2276be5843eStedu static void
show_valid_args(const struct token * table)228e331d0fcSjsg show_valid_args(const struct token *table)
22989189827Snorby {
23089189827Snorby 	int	i;
23189189827Snorby 
23289189827Snorby 	for (i = 0; table[i].type != ENDTOKEN; i++) {
23389189827Snorby 		switch (table[i].type) {
23489189827Snorby 		case NOTOKEN:
23589189827Snorby 			fprintf(stderr, "  <cr>\n");
23689189827Snorby 			break;
23789189827Snorby 		case KEYWORD:
23889189827Snorby 		case FLAG:
23989189827Snorby 			fprintf(stderr, "  %s\n", table[i].keyword);
24089189827Snorby 			break;
24189189827Snorby 		case ADDRESS:
24289189827Snorby 			fprintf(stderr, "  <address>\n");
24389189827Snorby 			break;
24489189827Snorby 		case PREFIX:
24589189827Snorby 			fprintf(stderr, "  <address>[/<len>]\n");
24689189827Snorby 			break;
24789189827Snorby 		case IFNAME:
24889189827Snorby 			fprintf(stderr, "  <interface>\n");
24989189827Snorby 		case ENDTOKEN:
25089189827Snorby 			break;
25189189827Snorby 		}
25289189827Snorby 	}
25389189827Snorby }
25489189827Snorby 
25589189827Snorby int
parse_addr(const char * word,struct in_addr * addr)25689189827Snorby parse_addr(const char *word, struct in_addr *addr)
25789189827Snorby {
25889189827Snorby 	struct in_addr	ina;
25989189827Snorby 
26089189827Snorby 	if (word == NULL)
26189189827Snorby 		return (0);
26289189827Snorby 
26389189827Snorby 	bzero(addr, sizeof(struct in_addr));
26489189827Snorby 	bzero(&ina, sizeof(ina));
26589189827Snorby 
26689189827Snorby 	if (inet_pton(AF_INET, word, &ina)) {
26789189827Snorby 		addr->s_addr = ina.s_addr;
26889189827Snorby 		return (1);
26989189827Snorby 	}
27089189827Snorby 
27189189827Snorby 	return (0);
27289189827Snorby }
27389189827Snorby 
27489189827Snorby int
parse_prefix(const char * word,struct in_addr * addr,u_int8_t * prefixlen)27589189827Snorby parse_prefix(const char *word, struct in_addr *addr, u_int8_t *prefixlen)
27689189827Snorby {
27789189827Snorby 	struct in_addr	 ina;
27889189827Snorby 	int		 bits = 32;
27989189827Snorby 
28089189827Snorby 	if (word == NULL)
28189189827Snorby 		return (0);
28289189827Snorby 
28389189827Snorby 	bzero(addr, sizeof(struct in_addr));
28489189827Snorby 	bzero(&ina, sizeof(ina));
28589189827Snorby 
28689189827Snorby 	if (strrchr(word, '/') != NULL) {
28789189827Snorby 		if ((bits = inet_net_pton(AF_INET, word,
28889189827Snorby 		    &ina, sizeof(ina))) == -1)
28989189827Snorby 			return (0);
29089189827Snorby 		addr->s_addr = ina.s_addr & htonl(0xffffffff << (32 - bits));
29189189827Snorby 		*prefixlen = bits;
29289189827Snorby 		return (1);
29389189827Snorby 	} else {
29489189827Snorby 		*prefixlen = 32;
29589189827Snorby 		return (parse_addr(word, addr));
29689189827Snorby 	}
29789189827Snorby 
29889189827Snorby 	return (0);
29989189827Snorby }
300