1*d3140113Seric /* $OpenBSD: parser.c,v 1.43 2021/06/14 17:58:15 eric Exp $ */
2c4f9d530Sgilles
3c4f9d530Sgilles /*
47a7bc169Seric * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
5c4f9d530Sgilles *
6c4f9d530Sgilles * Permission to use, copy, modify, and distribute this software for any
7c4f9d530Sgilles * purpose with or without fee is hereby granted, provided that the above
8c4f9d530Sgilles * copyright notice and this permission notice appear in all copies.
9c4f9d530Sgilles *
10c4f9d530Sgilles * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11c4f9d530Sgilles * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12c4f9d530Sgilles * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13c4f9d530Sgilles * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14c4f9d530Sgilles * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15c4f9d530Sgilles * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16c4f9d530Sgilles * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17c4f9d530Sgilles */
18c4f9d530Sgilles
19c4f9d530Sgilles #include <sys/queue.h>
205b6a9ce9Seric #include <sys/socket.h>
215b6a9ce9Seric
225b6a9ce9Seric #include <netinet/in.h>
235b6a9ce9Seric #include <net/if.h>
24c4f9d530Sgilles
25*d3140113Seric #include <arpa/inet.h>
267a7bc169Seric #include <err.h>
277a7bc169Seric #include <inttypes.h>
287a7bc169Seric #include <limits.h>
295b6a9ce9Seric #include <netdb.h>
307a7bc169Seric #include <stdio.h>
317a7bc169Seric #include <stdlib.h>
327a7bc169Seric #include <string.h>
33c4f9d530Sgilles
34c4f9d530Sgilles #include "parser.h"
35c4f9d530Sgilles
367a7bc169Seric uint64_t text_to_evpid(const char *);
377a7bc169Seric uint32_t text_to_msgid(const char *);
387a7bc169Seric
397a7bc169Seric struct node {
407a7bc169Seric int type;
417a7bc169Seric const char *token;
427a7bc169Seric struct node *parent;
437a7bc169Seric TAILQ_ENTRY(node) entry;
447a7bc169Seric TAILQ_HEAD(, node) children;
457a7bc169Seric int (*cmd)(int, struct parameter*);
46c4f9d530Sgilles };
47c4f9d530Sgilles
487a7bc169Seric static struct node *root;
49c4f9d530Sgilles
505b6a9ce9Seric static int text_to_sockaddr(struct sockaddr *, int, const char *);
515b6a9ce9Seric
527a7bc169Seric #define ARGVMAX 64
53c4f9d530Sgilles
547a7bc169Seric int
cmd_install(const char * pattern,int (* cmd)(int,struct parameter *))557a7bc169Seric cmd_install(const char *pattern, int (*cmd)(int, struct parameter*))
56c4f9d530Sgilles {
577a7bc169Seric struct node *node, *tmp;
587a7bc169Seric char *s, *str, *argv[ARGVMAX], **ap;
597a7bc169Seric int i, n;
60c4f9d530Sgilles
617a7bc169Seric /* Tokenize */
627a7bc169Seric str = s = strdup(pattern);
637a7bc169Seric if (str == NULL)
647a7bc169Seric err(1, "strdup");
657a7bc169Seric n = 0;
667a7bc169Seric for (ap = argv; n < ARGVMAX && (*ap = strsep(&str, " \t")) != NULL;) {
677a7bc169Seric if (**ap != '\0') {
687a7bc169Seric ap++;
697a7bc169Seric n++;
703d46f2feSgilles }
713d46f2feSgilles }
727a7bc169Seric *ap = NULL;
737a7bc169Seric
747a7bc169Seric if (root == NULL) {
757a7bc169Seric root = calloc(1, sizeof (*root));
767a7bc169Seric TAILQ_INIT(&root->children);
777a7bc169Seric }
787a7bc169Seric node = root;
797a7bc169Seric
807a7bc169Seric for (i = 0; i < n; i++) {
817a7bc169Seric TAILQ_FOREACH(tmp, &node->children, entry) {
827a7bc169Seric if (!strcmp(tmp->token, argv[i])) {
837a7bc169Seric node = tmp;
84c4f9d530Sgilles break;
85c4f9d530Sgilles }
86c4f9d530Sgilles }
877a7bc169Seric if (tmp == NULL) {
887a7bc169Seric tmp = calloc(1, sizeof (*tmp));
897a7bc169Seric TAILQ_INIT(&tmp->children);
907a7bc169Seric if (!strcmp(argv[i], "<str>"))
917a7bc169Seric tmp->type = P_STR;
927a7bc169Seric else if (!strcmp(argv[i], "<int>"))
937a7bc169Seric tmp->type = P_INT;
947a7bc169Seric else if (!strcmp(argv[i], "<msgid>"))
957a7bc169Seric tmp->type = P_MSGID;
967a7bc169Seric else if (!strcmp(argv[i], "<evpid>"))
977a7bc169Seric tmp->type = P_EVPID;
987a7bc169Seric else if (!strcmp(argv[i], "<routeid>"))
997a7bc169Seric tmp->type = P_ROUTEID;
1005b6a9ce9Seric else if (!strcmp(argv[i], "<addr>"))
1015b6a9ce9Seric tmp->type = P_ADDR;
1027a7bc169Seric else
1037a7bc169Seric tmp->type = P_TOKEN;
1047a7bc169Seric tmp->token = strdup(argv[i]);
1057a7bc169Seric tmp->parent = node;
1067a7bc169Seric TAILQ_INSERT_TAIL(&node->children, tmp, entry);
1077a7bc169Seric node = tmp;
1087a7bc169Seric }
109c4f9d530Sgilles }
110c4f9d530Sgilles
1117a7bc169Seric if (node->cmd)
1127a7bc169Seric errx(1, "duplicate pattern: %s", pattern);
1137a7bc169Seric node->cmd = cmd;
1147a7bc169Seric
1157a7bc169Seric free(s);
1167a7bc169Seric return (n);
117c4f9d530Sgilles }
118c4f9d530Sgilles
1197a7bc169Seric static int
cmd_check(const char * str,struct node * node,struct parameter * res)1207a7bc169Seric cmd_check(const char *str, struct node *node, struct parameter *res)
1217a7bc169Seric {
1227a7bc169Seric const char *e;
1237a7bc169Seric
1247a7bc169Seric switch (node->type) {
1257a7bc169Seric case P_TOKEN:
1267a7bc169Seric if (!strcmp(str, node->token))
1277a7bc169Seric return (1);
1287a7bc169Seric return (0);
1297a7bc169Seric
1307a7bc169Seric case P_STR:
1317a7bc169Seric res->u.u_str = str;
1327a7bc169Seric return (1);
1337a7bc169Seric
1347a7bc169Seric case P_INT:
1357a7bc169Seric res->u.u_int = strtonum(str, INT_MIN, INT_MAX, &e);
1367a7bc169Seric if (e)
1377a7bc169Seric return (0);
1387a7bc169Seric return (1);
1397a7bc169Seric
1407a7bc169Seric case P_MSGID:
1417a7bc169Seric if (strlen(str) != 8)
1427a7bc169Seric return (0);
1437a7bc169Seric res->u.u_msgid = text_to_msgid(str);
1447a7bc169Seric if (res->u.u_msgid == 0)
1457a7bc169Seric return (0);
1467a7bc169Seric return (1);
1477a7bc169Seric
1487a7bc169Seric case P_EVPID:
1497a7bc169Seric if (strlen(str) != 16)
1507a7bc169Seric return (0);
1517a7bc169Seric res->u.u_evpid = text_to_evpid(str);
1527a7bc169Seric if (res->u.u_evpid == 0)
1537a7bc169Seric return (0);
1547a7bc169Seric return (1);
1557a7bc169Seric
1567a7bc169Seric case P_ROUTEID:
15722cff71cSeric res->u.u_routeid = strtonum(str, 1, LLONG_MAX, &e);
1587a7bc169Seric if (e)
1597a7bc169Seric return (0);
1607a7bc169Seric return (1);
1617a7bc169Seric
1625b6a9ce9Seric case P_ADDR:
1635b6a9ce9Seric if (text_to_sockaddr((struct sockaddr *)&res->u.u_ss, PF_UNSPEC, str) == 0)
1645b6a9ce9Seric return (1);
1655b6a9ce9Seric return (0);
1665b6a9ce9Seric
1677a7bc169Seric default:
168d7bcae4dSeric errx(1, "bad token type: %d", node->type);
1697a7bc169Seric return (0);
1707a7bc169Seric }
1717a7bc169Seric }
1727a7bc169Seric
1737a7bc169Seric int
cmd_run(int argc,char ** argv)1747a7bc169Seric cmd_run(int argc, char **argv)
1757a7bc169Seric {
1767a7bc169Seric struct parameter param[ARGVMAX];
1777a7bc169Seric struct node *node, *tmp, *stack[ARGVMAX], *best;
1787a7bc169Seric int i, j, np;
1797a7bc169Seric
1807a7bc169Seric node = root;
1817a7bc169Seric np = 0;
1827a7bc169Seric
1837a7bc169Seric for (i = 0; i < argc; i++) {
1847a7bc169Seric TAILQ_FOREACH(tmp, &node->children, entry) {
1857a7bc169Seric if (cmd_check(argv[i], tmp, ¶m[np])) {
1867a7bc169Seric stack[i] = tmp;
1877a7bc169Seric node = tmp;
1887a7bc169Seric param[np].type = node->type;
1897a7bc169Seric if (node->type != P_TOKEN)
1907a7bc169Seric np++;
1917a7bc169Seric break;
1927a7bc169Seric }
1937a7bc169Seric }
1947a7bc169Seric if (tmp == NULL) {
1957a7bc169Seric best = NULL;
1967a7bc169Seric TAILQ_FOREACH(tmp, &node->children, entry) {
1977a7bc169Seric if (tmp->type != P_TOKEN)
1987a7bc169Seric continue;
1997a7bc169Seric if (strstr(tmp->token, argv[i]) != tmp->token)
2007a7bc169Seric continue;
2017a7bc169Seric if (best)
2027a7bc169Seric goto fail;
2037a7bc169Seric best = tmp;
2047a7bc169Seric }
2057a7bc169Seric if (best == NULL)
2067a7bc169Seric goto fail;
2077a7bc169Seric stack[i] = best;
2087a7bc169Seric node = best;
2097a7bc169Seric param[np].type = node->type;
2107a7bc169Seric if (node->type != P_TOKEN)
2117a7bc169Seric np++;
2127a7bc169Seric }
2137a7bc169Seric }
2147a7bc169Seric
2157a7bc169Seric if (node->cmd == NULL)
2167a7bc169Seric goto fail;
2177a7bc169Seric
2180fcb81a3Seric return (node->cmd(np, np ? param : NULL));
2197a7bc169Seric
2207a7bc169Seric fail:
22174c984d4Sgilles if (TAILQ_FIRST(&node->children) == NULL) {
22274c984d4Sgilles fprintf(stderr, "invalid command\n");
22374c984d4Sgilles return (-1);
22474c984d4Sgilles }
22574c984d4Sgilles
2267a7bc169Seric fprintf(stderr, "possibilities are:\n");
2277a7bc169Seric TAILQ_FOREACH(tmp, &node->children, entry) {
2287a7bc169Seric for (j = 0; j < i; j++)
2297a7bc169Seric fprintf(stderr, "%s%s", j?" ":"", stack[j]->token);
2307a7bc169Seric fprintf(stderr, "%s%s\n", i?" ":"", tmp->token);
2317a7bc169Seric }
2327a7bc169Seric
2337a7bc169Seric return (-1);
2347a7bc169Seric }
2357a7bc169Seric
2367a7bc169Seric int
cmd_show_params(int argc,struct parameter * argv)2377a7bc169Seric cmd_show_params(int argc, struct parameter *argv)
238c4f9d530Sgilles {
239c4f9d530Sgilles int i;
240c4f9d530Sgilles
2417a7bc169Seric for (i = 0; i < argc; i++) {
2427a7bc169Seric switch(argv[i].type) {
2437a7bc169Seric case P_STR:
2447a7bc169Seric printf(" str:\"%s\"", argv[i].u.u_str);
245c4f9d530Sgilles break;
2467a7bc169Seric case P_INT:
247d7bcae4dSeric printf(" int:%d", argv[i].u.u_int);
248c4f9d530Sgilles break;
2497a7bc169Seric case P_MSGID:
2507a7bc169Seric printf(" msgid:%08"PRIx32, argv[i].u.u_msgid);
2513d46f2feSgilles break;
2527a7bc169Seric case P_EVPID:
2537a7bc169Seric printf(" evpid:%016"PRIx64, argv[i].u.u_evpid);
254c4f9d530Sgilles break;
2557a7bc169Seric case P_ROUTEID:
2567a7bc169Seric printf(" routeid:%016"PRIx64, argv[i].u.u_routeid);
2577a7bc169Seric break;
2587a7bc169Seric default:
259d7bcae4dSeric printf(" ???:%d", argv[i].type);
260c4f9d530Sgilles }
261c4f9d530Sgilles }
2627a7bc169Seric printf ("\n");
2637a7bc169Seric return (1);
264c4f9d530Sgilles }
2655b6a9ce9Seric
2665b6a9ce9Seric static int
text_to_sockaddr(struct sockaddr * sa,int family,const char * str)2675b6a9ce9Seric text_to_sockaddr(struct sockaddr *sa, int family, const char *str)
2685b6a9ce9Seric {
2695b6a9ce9Seric struct in_addr ina;
2705b6a9ce9Seric struct in6_addr in6a;
271c09413deSgilles struct sockaddr_in *in;
272c09413deSgilles struct sockaddr_in6 *in6;
2735b6a9ce9Seric char *cp, *str2;
2745b6a9ce9Seric const char *errstr;
2755b6a9ce9Seric
2765b6a9ce9Seric switch (family) {
2775b6a9ce9Seric case PF_UNSPEC:
2785b6a9ce9Seric if (text_to_sockaddr(sa, PF_INET, str) == 0)
2795b6a9ce9Seric return (0);
2805b6a9ce9Seric return text_to_sockaddr(sa, PF_INET6, str);
2815b6a9ce9Seric
2825b6a9ce9Seric case PF_INET:
2835b6a9ce9Seric if (inet_pton(PF_INET, str, &ina) != 1)
2845b6a9ce9Seric return (-1);
2855b6a9ce9Seric
286c09413deSgilles in = (struct sockaddr_in *)sa;
287c09413deSgilles memset(in, 0, sizeof *in);
288c09413deSgilles in->sin_len = sizeof(struct sockaddr_in);
289c09413deSgilles in->sin_family = PF_INET;
290c09413deSgilles in->sin_addr.s_addr = ina.s_addr;
2915b6a9ce9Seric return (0);
2925b6a9ce9Seric
2935b6a9ce9Seric case PF_INET6:
2945b6a9ce9Seric cp = strchr(str, SCOPE_DELIMITER);
2955b6a9ce9Seric if (cp) {
2965b6a9ce9Seric str2 = strdup(str);
2975b6a9ce9Seric if (str2 == NULL)
2985b6a9ce9Seric return (-1);
2995b6a9ce9Seric str2[cp - str] = '\0';
3005b6a9ce9Seric if (inet_pton(PF_INET6, str2, &in6a) != 1) {
3015b6a9ce9Seric free(str2);
3025b6a9ce9Seric return (-1);
3035b6a9ce9Seric }
3045b6a9ce9Seric cp++;
3055b6a9ce9Seric free(str2);
3065b6a9ce9Seric } else if (inet_pton(PF_INET6, str, &in6a) != 1)
3075b6a9ce9Seric return (-1);
3085b6a9ce9Seric
309c09413deSgilles in6 = (struct sockaddr_in6 *)sa;
310c09413deSgilles memset(in6, 0, sizeof *in6);
311c09413deSgilles in6->sin6_len = sizeof(struct sockaddr_in6);
312c09413deSgilles in6->sin6_family = PF_INET6;
313c09413deSgilles in6->sin6_addr = in6a;
3145b6a9ce9Seric
3155b6a9ce9Seric if (cp == NULL)
3165b6a9ce9Seric return (0);
3175b6a9ce9Seric
3185b6a9ce9Seric if (IN6_IS_ADDR_LINKLOCAL(&in6a) ||
3195b6a9ce9Seric IN6_IS_ADDR_MC_LINKLOCAL(&in6a) ||
3205b6a9ce9Seric IN6_IS_ADDR_MC_INTFACELOCAL(&in6a))
321c09413deSgilles if ((in6->sin6_scope_id = if_nametoindex(cp)))
3225b6a9ce9Seric return (0);
3235b6a9ce9Seric
324c09413deSgilles in6->sin6_scope_id = strtonum(cp, 0, UINT32_MAX, &errstr);
3255b6a9ce9Seric if (errstr)
3265b6a9ce9Seric return (-1);
3275b6a9ce9Seric return (0);
3285b6a9ce9Seric
3295b6a9ce9Seric default:
3305b6a9ce9Seric break;
3315b6a9ce9Seric }
3325b6a9ce9Seric
3335b6a9ce9Seric return (-1);
3345b6a9ce9Seric }
335