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