diff options
author | 2020-09-06 15:51:28 +0000 | |
---|---|---|
committer | 2020-09-06 15:51:28 +0000 | |
commit | 967754d5410daebae22e529b8659dbc50d6fc921 (patch) | |
tree | 0dd9bf84235957f6a0e1c0d6123604e484c4249c | |
parent | After .ti, there are many reasons why the offset may change, so setting (diff) | |
download | wireguard-openbsd-967754d5410daebae22e529b8659dbc50d6fc921.tar.xz wireguard-openbsd-967754d5410daebae22e529b8659dbc50d6fc921.zip |
Split "trap receiver" into its own trap_address struct and clean up the
code surrounding this struct and struct address.
No functional change intended, except that trap receiver's source-address
may now be a resolvable hostname.
Tweaks and OK jan@
-rw-r--r-- | usr.sbin/snmpd/parse.y | 258 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpd.c | 31 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpd.h | 23 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpe.c | 13 | ||||
-rw-r--r-- | usr.sbin/snmpd/trap.c | 13 | ||||
-rw-r--r-- | usr.sbin/snmpd/traphandler.c | 18 |
6 files changed, 135 insertions, 221 deletions
diff --git a/usr.sbin/snmpd/parse.y b/usr.sbin/snmpd/parse.y index 5a7af838155..2efd44d185a 100644 --- a/usr.sbin/snmpd/parse.y +++ b/usr.sbin/snmpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.59 2020/08/23 07:39:57 martijn Exp $ */ +/* $OpenBSD: parse.y,v 1.60 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -91,16 +91,11 @@ char *symget(const char *); struct snmpd *conf = NULL; static int errors = 0; -static struct addresslist *hlist; static struct usmuser *user = NULL; -struct address *host_v4(const char *); -struct address *host_v6(const char *); -int host_dns(const char *, struct addresslist *, - int, in_port_t, struct ber_oid *, char *, - struct address *, int); -int host(const char *, struct addresslist *, - int, in_port_t, struct ber_oid *, char *, char *, int); +int host(const char *, const char *, int, + struct sockaddr_storage *, int); +int listen_add(struct sockaddr_storage *, int); typedef struct { union { @@ -199,13 +194,26 @@ yesno : STRING { ; main : LISTEN ON STRING proto { - if (host($3, &conf->sc_addresses, 16, SNMPD_PORT, NULL, - NULL, NULL, $4) <= 0) { - yyerror("invalid ip address: %s", $3); + struct sockaddr_storage ss[16]; + int nhosts, i; + + nhosts = host($3, SNMPD_PORT, $4, ss, nitems(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $3); free($3); YYERROR; } + if (nhosts > (int)nitems(ss)) + log_warn("%s resolves to more than %zu hosts", + $3, nitems(ss)); free($3); + + for (i = 0; i < nhosts; i++) { + if (listen_add(&(ss[i]), $4) == -1) { + yyerror("calloc"); + YYERROR; + } + } } | READONLY COMMUNITY STRING { if (strlcpy(conf->sc_rdcommunity, $3, @@ -240,11 +248,7 @@ main : LISTEN ON STRING proto { } free($3); } - | TRAP RECEIVER { - hlist = &conf->sc_trapreceivers; - } host { - hlist = NULL; - } + | TRAP RECEIVER host | TRAP HANDLE hostcmn trapoid cmd { struct trapcmd *cmd = $5.data; @@ -420,13 +424,40 @@ srcaddr : /* empty */ { $$ = NULL; } ; hostdef : STRING hostoid hostcmn srcaddr { - if (host($1, hlist, 1, - SNMPD_TRAPPORT, $2, $3, $4, IPPROTO_UDP) <= 0) { + struct sockaddr_storage ss; + struct trap_address *tr; + + if ((tr = calloc(1, sizeof(*tr))) == NULL) { + yyerror("calloc"); + YYERROR; + } + + if (host($1, SNMPD_TRAPPORT, SOCK_DGRAM, &ss, 1) <= 0) { yyerror("invalid host: %s", $1); free($1); + free($2); + free($3); + free($4); + free(tr); YYERROR; } free($1); + memcpy(&(tr->ss), &ss, sizeof(ss)); + if ($4 != NULL) { + if (host($1, "0", SOCK_DGRAM, &ss, 1) <= 0) { + yyerror("invalid host: %s", $1); + free($2); + free($3); + free($4); + free(tr); + YYERROR; + } + free($4); + memcpy(&(tr->ss_local), &ss, sizeof(ss)); + } + tr->sa_oid = $2; + tr->sa_community = $3; + TAILQ_INSERT_TAIL(&(conf->sc_trapreceivers), tr, entry); } ; @@ -510,9 +541,9 @@ enc : STRING { } ; -proto : /* empty */ { $$ = IPPROTO_UDP; } - | TCP { $$ = IPPROTO_TCP; } - | UDP { $$ = IPPROTO_UDP; } +proto : /* empty */ { $$ = SOCK_DGRAM; } + | TCP { $$ = SOCK_STREAM; } + | UDP { $$ = SOCK_DGRAM; } ; cmd : STRING { @@ -985,6 +1016,7 @@ popfile(void) struct snmpd * parse_config(const char *filename, u_int flags) { + struct sockaddr_storage ss; struct sym *sym, *next; struct address *h; int found; @@ -1017,15 +1049,19 @@ parse_config(const char *filename, u_int flags) /* Setup default listen addresses */ if (TAILQ_EMPTY(&conf->sc_addresses)) { - host("0.0.0.0", &conf->sc_addresses, 1, SNMPD_PORT, - NULL, NULL, NULL, IPPROTO_UDP); - host("::", &conf->sc_addresses, 1, SNMPD_PORT, - NULL, NULL, NULL, IPPROTO_UDP); + if (host("0.0.0.0", SNMPD_PORT, SOCK_DGRAM, &ss, 1) != 1) + fatal("Unexpected resolving of 0.0.0.0"); + if (listen_add(&ss, SOCK_DGRAM) == -1) + fatal("calloc"); + if (host("::", SNMPD_PORT, SOCK_DGRAM, &ss, 1) != 1) + fatal("Unexpected resolving of ::"); + if (listen_add(&ss, SOCK_DGRAM) == -1) + fatal("calloc"); } if (conf->sc_traphandler) { found = 0; TAILQ_FOREACH(h, &conf->sc_addresses, entry) { - if (h->ipproto == IPPROTO_UDP) + if (h->type == SOCK_DGRAM) found = 1; } if (!found) { @@ -1128,167 +1164,57 @@ symget(const char *nam) return (NULL); } -struct address * -host_v4(const char *s) -{ - struct in_addr ina; - struct sockaddr_in *sain; - struct address *h; - - bzero(&ina, sizeof(ina)); - if (inet_pton(AF_INET, s, &ina) != 1) - return (NULL); - - if ((h = calloc(1, sizeof(*h))) == NULL) - fatal(__func__); - sain = (struct sockaddr_in *)&h->ss; - sain->sin_len = sizeof(struct sockaddr_in); - sain->sin_family = AF_INET; - sain->sin_addr.s_addr = ina.s_addr; - - return (h); -} - -struct address * -host_v6(const char *s) -{ - struct addrinfo hints, *res; - struct sockaddr_in6 *sa_in6; - struct address *h = NULL; - - bzero(&hints, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; /* dummy */ - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(s, "0", &hints, &res) == 0) { - if ((h = calloc(1, sizeof(*h))) == NULL) - fatal(__func__); - sa_in6 = (struct sockaddr_in6 *)&h->ss; - sa_in6->sin6_len = sizeof(struct sockaddr_in6); - sa_in6->sin6_family = AF_INET6; - memcpy(&sa_in6->sin6_addr, - &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, - sizeof(sa_in6->sin6_addr)); - sa_in6->sin6_scope_id = - ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; - - freeaddrinfo(res); - } - - return (h); -} - int -host_dns(const char *s, struct addresslist *al, int max, - in_port_t port, struct ber_oid *oid, char *cmn, - struct address *src, int ipproto) +host(const char *s, const char *port, int type, struct sockaddr_storage *ss, + int max) { struct addrinfo hints, *res0, *res; - int error, cnt = 0; - struct sockaddr_in *sain; - struct sockaddr_in6 *sin6; - struct address *h; + int error, i; bzero(&hints, sizeof(hints)); hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ - hints.ai_flags = AI_ADDRCONFIG; - error = getaddrinfo(s, NULL, &hints, &res0); + hints.ai_socktype = type; + error = getaddrinfo(s, port, &hints, &res0); if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) - return (0); + return 0; if (error) { - log_warnx("host_dns: could not parse \"%s\": %s", s, - gai_strerror(error)); - return (-1); + log_warnx("Could not parse \"%s\": %s", s, gai_strerror(error)); + return -1; } - for (res = res0; res && cnt < max; res = res->ai_next) { + for (i = 0, res = res0; res; res = res->ai_next, i++) { if (res->ai_family != AF_INET && res->ai_family != AF_INET6) continue; - if (src != NULL && src->ss.ss_family != res->ai_family) + if (i >= max) continue; - if ((h = calloc(1, sizeof(*h))) == NULL) - fatal(__func__); - - h->port = port; - h->ipproto = ipproto; - if (oid != NULL) { - if ((h->sa_oid = calloc(1, sizeof(*oid))) == NULL) - fatal(__func__); - bcopy(oid, h->sa_oid, sizeof(*oid)); - } - if (cmn != NULL) { - if ((h->sa_community = strdup(cmn)) == NULL) - fatal(__func__); - } - h->ss.ss_family = res->ai_family; - if (res->ai_family == AF_INET) { - sain = (struct sockaddr_in *)&h->ss; - sain->sin_len = sizeof(struct sockaddr_in); - sain->sin_addr.s_addr = ((struct sockaddr_in *) - res->ai_addr)->sin_addr.s_addr; - } else { - sin6 = (struct sockaddr_in6 *)&h->ss; - sin6->sin6_len = sizeof(struct sockaddr_in6); - memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) - res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); - } - - h->sa_srcaddr = src; - - TAILQ_INSERT_TAIL(al, h, entry); - cnt++; - } - if (cnt == max && res) { - log_warnx("host_dns: %s resolves to more than %d hosts", - s, max); + bcopy(res->ai_addr, &(ss[i]), res->ai_addrlen); } freeaddrinfo(res0); - if (oid != NULL) - free(oid); - if (cmn != NULL) - free(cmn); - return (cnt); + + return i; } int -host(const char *s, struct addresslist *al, int max, - in_port_t port, struct ber_oid *oid, char *cmn, char *srcaddr, int ipproto) +listen_add(struct sockaddr_storage *ss, int type) { - struct address *h, *src = NULL; - - if (srcaddr != NULL) { - src = host_v4(srcaddr); - if (src == NULL) - src = host_v6(srcaddr); - if (src == NULL) { - log_warnx("invalid source-address %s", srcaddr); - return (-1); - } - } - - h = host_v4(s); - - /* IPv6 address? */ - if (h == NULL) - h = host_v6(s); + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct address *h; - if (h != NULL) { - h->port = port; - h->sa_oid = oid; - h->sa_community = cmn; - h->ipproto = ipproto; - if (src != NULL && h->ss.ss_family != src->ss.ss_family) { - log_warnx("host and source-address family mismatch"); - return (-1); - } - h->sa_srcaddr = src; - - TAILQ_INSERT_TAIL(al, h, entry); - return (1); + if ((h = calloc(1, sizeof(*h))) == NULL) + return -1; + bcopy(ss, &(h->ss), sizeof(*ss)); + if (ss->ss_family == AF_INET) { + sin = (struct sockaddr_in *)ss; + h->port = ntohs(sin->sin_port); + } else { + sin6 = (struct sockaddr_in6*)ss; + h->port = ntohs(sin6->sin6_port); } + h->type = type; + TAILQ_INSERT_TAIL(&(conf->sc_addresses), h, entry); - return (host_dns(s, al, max, port, oid, cmn, src, ipproto)); + return 0; } diff --git a/usr.sbin/snmpd/snmpd.c b/usr.sbin/snmpd/snmpd.c index 48fa45648fe..b7205701b5a 100644 --- a/usr.sbin/snmpd/snmpd.c +++ b/usr.sbin/snmpd/snmpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.c,v 1.41 2019/01/08 15:38:36 bluhm Exp $ */ +/* $OpenBSD: snmpd.c,v 1.42 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -310,33 +310,10 @@ snmpd_dispatch_snmpe(int fd, struct privsep_proc *p, struct imsg *imsg) } int -snmpd_socket_af(struct sockaddr_storage *ss, in_port_t port, int ipproto) +snmpd_socket_af(struct sockaddr_storage *ss, int type) { - int s; - - switch (ss->ss_family) { - case AF_INET: - ((struct sockaddr_in *)ss)->sin_port = port; - ((struct sockaddr_in *)ss)->sin_len = - sizeof(struct sockaddr_in); - break; - case AF_INET6: - ((struct sockaddr_in6 *)ss)->sin6_port = port; - ((struct sockaddr_in6 *)ss)->sin6_len = - sizeof(struct sockaddr_in6); - break; - default: - return (-1); - } - - if (ipproto == IPPROTO_TCP) - s = socket(ss->ss_family, - SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); - else - s = socket(ss->ss_family, - SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); - - return (s); + return socket(ss->ss_family, (type == SOCK_STREAM ? + SOCK_STREAM | SOCK_NONBLOCK : SOCK_DGRAM) | SOCK_CLOEXEC, 0); } void diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index 1782f0fc9af..7d7212e9ffc 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.89 2020/08/23 07:39:57 martijn Exp $ */ +/* $OpenBSD: snmpd.h,v 1.90 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -48,8 +48,8 @@ #define CONF_FILE "/etc/snmpd.conf" #define SNMPD_SOCKET "/var/run/snmpd.sock" #define SNMPD_USER "_snmpd" -#define SNMPD_PORT 161 -#define SNMPD_TRAPPORT 162 +#define SNMPD_PORT "161" +#define SNMPD_TRAPPORT "162" #define SNMPD_MAXSTRLEN 484 #define SNMPD_MAXCOMMUNITYLEN SNMPD_MAXSTRLEN @@ -481,19 +481,24 @@ struct snmp_stats { struct address { struct sockaddr_storage ss; in_port_t port; - int ipproto; + int type; int fd; struct event ev; struct event evt; TAILQ_ENTRY(address) entry; +}; +TAILQ_HEAD(addresslist, address); - /* For SNMP trap receivers etc. */ +struct trap_address { + struct sockaddr_storage ss; + struct sockaddr_storage ss_local; char *sa_community; struct ber_oid *sa_oid; - struct address *sa_srcaddr; + + TAILQ_ENTRY(trap_address) entry; }; -TAILQ_HEAD(addresslist, address); +TAILQ_HEAD(trap_addresslist, trap_address); enum usmauth { AUTH_NONE = 0, @@ -551,7 +556,7 @@ struct snmpd { struct snmp_stats sc_stats; - struct addresslist sc_trapreceivers; + struct trap_addresslist sc_trapreceivers; int sc_ncpu; int64_t *sc_cpustates; @@ -706,7 +711,7 @@ char *smi_print_element(struct ber_element *); void timer_init(void); /* snmpd.c */ -int snmpd_socket_af(struct sockaddr_storage *, in_port_t, int); +int snmpd_socket_af(struct sockaddr_storage *, int); u_long snmpd_engine_time(void); char *tohexstr(u_int8_t *, int); diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c index 817928aac66..fb92cd1b719 100644 --- a/usr.sbin/snmpd/snmpe.c +++ b/usr.sbin/snmpd/snmpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpe.c,v 1.65 2020/08/23 07:39:57 martijn Exp $ */ +/* $OpenBSD: snmpe.c,v 1.66 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -102,7 +102,7 @@ snmpe_init(struct privsep *ps, struct privsep_proc *p, void *arg) /* listen for incoming SNMP UDP/TCP messages */ TAILQ_FOREACH(h, &env->sc_addresses, entry) { - if (h->ipproto == IPPROTO_TCP) { + if (h->type == SOCK_STREAM) { if (listen(h->fd, 5) < 0) fatalx("snmpe: failed to listen on socket"); event_set(&h->ev, h->fd, EV_READ, snmpe_acceptcb, h); @@ -128,7 +128,7 @@ snmpe_shutdown(void) TAILQ_FOREACH(h, &snmpd_env->sc_addresses, entry) { event_del(&h->ev); - if (h->ipproto == IPPROTO_TCP) + if (h->type == SOCK_STREAM) event_del(&h->evt); close(h->fd); } @@ -152,8 +152,7 @@ snmpe_bind(struct address *addr) char buf[512]; int val, s; - if ((s = snmpd_socket_af(&addr->ss, htons(addr->port), - addr->ipproto)) == -1) + if ((s = snmpd_socket_af(&addr->ss, addr->type)) == -1) return (-1); /* @@ -162,7 +161,7 @@ snmpe_bind(struct address *addr) if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) goto bad; - if (addr->ipproto == IPPROTO_TCP) { + if (addr->type == SOCK_STREAM) { val = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) @@ -196,7 +195,7 @@ snmpe_bind(struct address *addr) goto bad; log_info("snmpe: listening on %s %s:%d", - (addr->ipproto == IPPROTO_TCP) ? "tcp" : "udp", buf, addr->port); + (addr->type == SOCK_STREAM) ? "tcp" : "udp", buf, addr->port); return (s); diff --git a/usr.sbin/snmpd/trap.c b/usr.sbin/snmpd/trap.c index 95c68030d90..23e406f5801 100644 --- a/usr.sbin/snmpd/trap.c +++ b/usr.sbin/snmpd/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.35 2020/06/30 17:11:49 martijn Exp $ */ +/* $OpenBSD: trap.c,v 1.36 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org> @@ -55,7 +55,7 @@ int trap_send(struct ber_oid *oid, struct ber_element *elm) { int ret = 0, s; - struct address *tr; + struct trap_address *tr; struct ber_element *root, *b, *c, *trap; struct ber ber; char *cmn; @@ -104,14 +104,13 @@ trap_send(struct ber_oid *oid, struct ber_element *elm) continue; } - if ((s = snmpd_socket_af(&tr->ss, htons(tr->port), - IPPROTO_UDP)) == -1) { + if ((s = snmpd_socket_af(&tr->ss, SOCK_DGRAM)) == -1) { ret = -1; goto done; } - if (tr->sa_srcaddr != NULL) { - if (bind(s, (struct sockaddr *)&tr->sa_srcaddr->ss, - tr->sa_srcaddr->ss.ss_len) == -1) { + if (tr->ss_local.ss_family != 0) { + if (bind(s, (struct sockaddr *)&(tr->ss_local), + tr->ss_local.ss_len) == -1) { ret = -1; goto done; } diff --git a/usr.sbin/snmpd/traphandler.c b/usr.sbin/snmpd/traphandler.c index 7738203f7a6..52866a91b01 100644 --- a/usr.sbin/snmpd/traphandler.c +++ b/usr.sbin/snmpd/traphandler.c @@ -1,4 +1,4 @@ -/* $OpenBSD: traphandler.c,v 1.17 2020/08/23 07:39:57 martijn Exp $ */ +/* $OpenBSD: traphandler.c,v 1.18 2020/09/06 15:51:28 martijn Exp $ */ /* * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org> @@ -77,7 +77,7 @@ traphandler(struct privsep *ps, struct privsep_proc *p) if (env->sc_traphandler) { TAILQ_FOREACH(h, &env->sc_addresses, entry) { - if (h->ipproto != IPPROTO_UDP) + if (h->type != SOCK_DGRAM) continue; if ((h->fd = traphandler_bind(h)) == -1) fatal("could not create trap listener socket"); @@ -112,9 +112,17 @@ traphandler_bind(struct address *addr) { int s; char buf[512]; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; - if ((s = snmpd_socket_af(&addr->ss, htons(SNMPD_TRAPPORT), - IPPROTO_UDP)) == -1) + if (addr->ss.ss_family == AF_INET) { + sin = (struct sockaddr_in *)&(addr->ss); + sin->sin_port = htons(162); + } else { + sin6 = (struct sockaddr_in6 *)&(addr->ss); + sin6->sin6_port = htons(162); + } + if ((s = snmpd_socket_af(&addr->ss, SOCK_DGRAM)) == -1) return (-1); if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) @@ -126,7 +134,7 @@ traphandler_bind(struct address *addr) if (print_host(&addr->ss, buf, sizeof(buf)) == NULL) goto bad; - log_info("traphandler: listening on %s:%d", buf, SNMPD_TRAPPORT); + log_info("traphandler: listening on %s:%s", buf, SNMPD_TRAPPORT); return (s); bad: |