diff options
author | Gilles Chehade <gilles@poolp.org> | 2020-05-22 14:32:22 +0200 |
---|---|---|
committer | Gilles Chehade <gilles@poolp.org> | 2020-05-22 14:32:22 +0200 |
commit | 90620a574d8824e5b2aa18709f2d5b5b6bb3cb38 (patch) | |
tree | 251ab90cb9264a2cd476a19b33e066868a4f7849 /smtpd/parser.c | |
parent | mv back (diff) | |
download | OpenSMTPD-90620a574d8824e5b2aa18709f2d5b5b6bb3cb38.tar.xz OpenSMTPD-90620a574d8824e5b2aa18709f2d5b5b6bb3cb38.zip |
moving smtpd to usr.sbin/smtpd to ease cherry-picking of upstream
Diffstat (limited to 'smtpd/parser.c')
-rw-r--r-- | smtpd/parser.c | 341 |
1 files changed, 0 insertions, 341 deletions
diff --git a/smtpd/parser.c b/smtpd/parser.c deleted file mode 100644 index 4c2321ec..00000000 --- a/smtpd/parser.c +++ /dev/null @@ -1,341 +0,0 @@ -/* $OpenBSD: parser.c,v 1.42 2020/01/06 11:02:38 gilles Exp $ */ - -/* - * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <net/if.h> -#include <arpa/inet.h> - -#include <err.h> -#include <inttypes.h> -#include <limits.h> -#include <netdb.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "parser.h" - -uint64_t text_to_evpid(const char *); -uint32_t text_to_msgid(const char *); - -struct node { - int type; - const char *token; - struct node *parent; - TAILQ_ENTRY(node) entry; - TAILQ_HEAD(, node) children; - int (*cmd)(int, struct parameter*); -}; - -static struct node *root; - -static int text_to_sockaddr(struct sockaddr *, int, const char *); - -#define ARGVMAX 64 - -int -cmd_install(const char *pattern, int (*cmd)(int, struct parameter*)) -{ - struct node *node, *tmp; - char *s, *str, *argv[ARGVMAX], **ap; - int i, n; - - /* Tokenize */ - str = s = strdup(pattern); - if (str == NULL) - err(1, "strdup"); - n = 0; - for (ap = argv; n < ARGVMAX && (*ap = strsep(&str, " \t")) != NULL;) { - if (**ap != '\0') { - ap++; - n++; - } - } - *ap = NULL; - - if (root == NULL) { - root = calloc(1, sizeof (*root)); - TAILQ_INIT(&root->children); - } - node = root; - - for (i = 0; i < n; i++) { - TAILQ_FOREACH(tmp, &node->children, entry) { - if (!strcmp(tmp->token, argv[i])) { - node = tmp; - break; - } - } - if (tmp == NULL) { - tmp = calloc(1, sizeof (*tmp)); - TAILQ_INIT(&tmp->children); - if (!strcmp(argv[i], "<str>")) - tmp->type = P_STR; - else if (!strcmp(argv[i], "<int>")) - tmp->type = P_INT; - else if (!strcmp(argv[i], "<msgid>")) - tmp->type = P_MSGID; - else if (!strcmp(argv[i], "<evpid>")) - tmp->type = P_EVPID; - else if (!strcmp(argv[i], "<routeid>")) - tmp->type = P_ROUTEID; - else if (!strcmp(argv[i], "<addr>")) - tmp->type = P_ADDR; - else - tmp->type = P_TOKEN; - tmp->token = strdup(argv[i]); - tmp->parent = node; - TAILQ_INSERT_TAIL(&node->children, tmp, entry); - node = tmp; - } - } - - if (node->cmd) - errx(1, "duplicate pattern: %s", pattern); - node->cmd = cmd; - - free(s); - return (n); -} - -static int -cmd_check(const char *str, struct node *node, struct parameter *res) -{ - const char *e; - - switch (node->type) { - case P_TOKEN: - if (!strcmp(str, node->token)) - return (1); - return (0); - - case P_STR: - res->u.u_str = str; - return (1); - - case P_INT: - res->u.u_int = strtonum(str, INT_MIN, INT_MAX, &e); - if (e) - return (0); - return (1); - - case P_MSGID: - if (strlen(str) != 8) - return (0); - res->u.u_msgid = text_to_msgid(str); - if (res->u.u_msgid == 0) - return (0); - return (1); - - case P_EVPID: - if (strlen(str) != 16) - return (0); - res->u.u_evpid = text_to_evpid(str); - if (res->u.u_evpid == 0) - return (0); - return (1); - - case P_ROUTEID: - res->u.u_routeid = strtonum(str, 1, LLONG_MAX, &e); - if (e) - return (0); - return (1); - - case P_ADDR: - if (text_to_sockaddr((struct sockaddr *)&res->u.u_ss, PF_UNSPEC, str) == 0) - return (1); - return (0); - - default: - errx(1, "bad token type: %d", node->type); - return (0); - } -} - -int -cmd_run(int argc, char **argv) -{ - struct parameter param[ARGVMAX]; - struct node *node, *tmp, *stack[ARGVMAX], *best; - int i, j, np; - - node = root; - np = 0; - - for (i = 0; i < argc; i++) { - TAILQ_FOREACH(tmp, &node->children, entry) { - if (cmd_check(argv[i], tmp, ¶m[np])) { - stack[i] = tmp; - node = tmp; - param[np].type = node->type; - if (node->type != P_TOKEN) - np++; - break; - } - } - if (tmp == NULL) { - best = NULL; - TAILQ_FOREACH(tmp, &node->children, entry) { - if (tmp->type != P_TOKEN) - continue; - if (strstr(tmp->token, argv[i]) != tmp->token) - continue; - if (best) - goto fail; - best = tmp; - } - if (best == NULL) - goto fail; - stack[i] = best; - node = best; - param[np].type = node->type; - if (node->type != P_TOKEN) - np++; - } - } - - if (node->cmd == NULL) - goto fail; - - return (node->cmd(np, np ? param : NULL)); - -fail: - if (TAILQ_FIRST(&node->children) == NULL) { - fprintf(stderr, "invalid command\n"); - return (-1); - } - - fprintf(stderr, "possibilities are:\n"); - TAILQ_FOREACH(tmp, &node->children, entry) { - for (j = 0; j < i; j++) - fprintf(stderr, "%s%s", j?" ":"", stack[j]->token); - fprintf(stderr, "%s%s\n", i?" ":"", tmp->token); - } - - return (-1); -} - -int -cmd_show_params(int argc, struct parameter *argv) -{ - int i; - - for (i = 0; i < argc; i++) { - switch(argv[i].type) { - case P_STR: - printf(" str:\"%s\"", argv[i].u.u_str); - break; - case P_INT: - printf(" int:%d", argv[i].u.u_int); - break; - case P_MSGID: - printf(" msgid:%08"PRIx32, argv[i].u.u_msgid); - break; - case P_EVPID: - printf(" evpid:%016"PRIx64, argv[i].u.u_evpid); - break; - case P_ROUTEID: - printf(" routeid:%016"PRIx64, argv[i].u.u_routeid); - break; - default: - printf(" ???:%d", argv[i].type); - } - } - printf ("\n"); - return (1); -} - -static int -text_to_sockaddr(struct sockaddr *sa, int family, const char *str) -{ - struct in_addr ina; - struct in6_addr in6a; - struct sockaddr_in *in; - struct sockaddr_in6 *in6; - char *cp, *str2; - const char *errstr; - - switch (family) { - case PF_UNSPEC: - if (text_to_sockaddr(sa, PF_INET, str) == 0) - return (0); - return text_to_sockaddr(sa, PF_INET6, str); - - case PF_INET: - if (inet_pton(PF_INET, str, &ina) != 1) - return (-1); - - in = (struct sockaddr_in *)sa; - memset(in, 0, sizeof *in); -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - in->sin_len = sizeof(struct sockaddr_in); -#endif - in->sin_family = PF_INET; - in->sin_addr.s_addr = ina.s_addr; - return (0); - - case PF_INET6: - cp = strchr(str, SCOPE_DELIMITER); - if (cp) { - str2 = strdup(str); - if (str2 == NULL) - return (-1); - str2[cp - str] = '\0'; - if (inet_pton(PF_INET6, str2, &in6a) != 1) { - free(str2); - return (-1); - } - cp++; - free(str2); - } else if (inet_pton(PF_INET6, str, &in6a) != 1) - return (-1); - - in6 = (struct sockaddr_in6 *)sa; - memset(in6, 0, sizeof *in6); -#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN - in6->sin6_len = sizeof(struct sockaddr_in6); -#endif - in6->sin6_family = PF_INET6; - in6->sin6_addr = in6a; - - if (cp == NULL) - return (0); - - if (IN6_IS_ADDR_LINKLOCAL(&in6a) || - IN6_IS_ADDR_MC_LINKLOCAL(&in6a) || - IN6_IS_ADDR_MC_NODELOCAL(&in6a)) - if ((in6->sin6_scope_id = if_nametoindex(cp))) - return (0); - - in6->sin6_scope_id = strtonum(cp, 0, UINT32_MAX, &errstr); - if (errstr) - return (-1); - return (0); - - default: - break; - } - - return (-1); -} |