diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-11-18 16:16:40 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-11-18 16:16:40 +0000 |
commit | d20df6e557a1d8dde42cf2b05740796f12d9d51a (patch) | |
tree | 50690861e39d095c88806d578910f791afc73080 /usr.sbin | |
parent | 72c5fa8fa8af0e6f4cc03462d05805e5e90988f2 (diff) |
Add support for multiple listening sockets
One can now specify multiple "listen on" statements. The default is to
listen on 0.0.0.0 and ::, which means better handling of dual-stack
setups. ok sthen@ on a previous version, input and ok reyk@.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/snmpd/control.c | 4 | ||||
-rw-r--r-- | usr.sbin/snmpd/parse.y | 40 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpd.h | 16 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpe.c | 35 | ||||
-rw-r--r-- | usr.sbin/snmpd/traphandler.c | 43 |
5 files changed, 87 insertions, 51 deletions
diff --git a/usr.sbin/snmpd/control.c b/usr.sbin/snmpd/control.c index c4240d14f3b..833d2be7725 100644 --- a/usr.sbin/snmpd/control.c +++ b/usr.sbin/snmpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.39 2016/09/02 13:28:36 eric Exp $ */ +/* $OpenBSD: control.c,v 1.40 2016/11/18 16:16:39 jca Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -592,7 +592,7 @@ control_dispatch_agentx(int fd, short event, void *arg) } } dispatch: - snmpe_dispatchmsg(msg); + snmpe_dispatchmsg(msg, fd); break; } diff --git a/usr.sbin/snmpd/parse.y b/usr.sbin/snmpd/parse.y index f173650fcab..533db0b2ab7 100644 --- a/usr.sbin/snmpd/parse.y +++ b/usr.sbin/snmpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.40 2016/11/09 20:31:56 jca Exp $ */ +/* $OpenBSD: parse.y,v 1.41 2016/11/18 16:16:39 jca Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -198,25 +198,13 @@ yesno : STRING { ; main : LISTEN ON STRING { - struct addresslist al; - struct address *h; - - TAILQ_INIT(&al); - if (host($3, &al, 1, SNMPD_PORT, NULL, NULL, NULL) - <= 0) { + if (host($3, &conf->sc_addresses, 16, SNMPD_PORT, NULL, + NULL, NULL) <= 0) { yyerror("invalid ip address: %s", $3); free($3); YYERROR; } free($3); - h = TAILQ_FIRST(&al); - bcopy(&h->ss, &conf->sc_address.ss, sizeof(*h)); - conf->sc_address.port = h->port; - - while ((h = TAILQ_FIRST(&al)) != NULL) { - TAILQ_REMOVE(&al, h, entry); - free(h); - } } | READONLY COMMUNITY STRING { if (strlcpy(conf->sc_rdcommunity, $3, @@ -989,8 +977,8 @@ parse_config(const char *filename, u_int flags) conf->sc_flags = flags; conf->sc_confpath = filename; - conf->sc_address.ss.ss_family = AF_INET; - conf->sc_address.port = SNMPD_PORT; + TAILQ_INIT(&conf->sc_addresses); + TAILQ_INIT(&conf->sc_sockets); conf->sc_ps.ps_csock.cs_name = SNMPD_SOCKET; TAILQ_INIT(&conf->sc_ps.ps_rcsocks); strlcpy(conf->sc_rdcommunity, "public", SNMPD_MAXCOMMUNITYLEN); @@ -1011,6 +999,20 @@ parse_config(const char *filename, u_int flags) endservent(); + if (TAILQ_EMPTY(&conf->sc_addresses)) { + struct address *h; + if ((h = calloc(1, sizeof(*h))) == NULL) + fatal("snmpe: %s", __func__); + h->ss.ss_family = AF_INET; + h->port = SNMPD_PORT; + TAILQ_INSERT_TAIL(&conf->sc_addresses, h, entry); + if ((h = calloc(1, sizeof(*h))) == NULL) + fatal("snmpe: %s", __func__); + h->ss.ss_family = AF_INET6; + h->port = SNMPD_PORT; + TAILQ_INSERT_TAIL(&conf->sc_addresses, h, entry); + } + /* Free macros and check which have not been used. */ for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { next = TAILQ_NEXT(sym, entry); @@ -1215,7 +1217,7 @@ host_dns(const char *s, struct addresslist *al, int max, h->sa_srcaddr = src; - TAILQ_INSERT_HEAD(al, h, entry); + TAILQ_INSERT_TAIL(al, h, entry); cnt++; } if (cnt == max && res) { @@ -1262,7 +1264,7 @@ host(const char *s, struct addresslist *al, int max, } h->sa_srcaddr = src; - TAILQ_INSERT_HEAD(al, h, entry); + TAILQ_INSERT_TAIL(al, h, entry); return (1); } diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index 38d01f0f5bd..46782c3f46d 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.72 2016/11/09 20:31:56 jca Exp $ */ +/* $OpenBSD: snmpd.h,v 1.73 2016/11/18 16:16:39 jca Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -518,6 +518,13 @@ struct address { }; TAILQ_HEAD(addresslist, address); +struct listen_sock { + int s_fd; + struct event s_ev; + TAILQ_ENTRY(listen_sock) entry; +}; +TAILQ_HEAD(socklist, listen_sock); + enum usmauth { AUTH_NONE = 0, AUTH_MD5, /* HMAC-MD5-96, RFC3414 */ @@ -556,9 +563,8 @@ struct snmpd { #define SNMPD_F_NONAMES 0x02 const char *sc_confpath; - struct address sc_address; - int sc_sock; - struct event sc_ev; + struct addresslist sc_addresses; + struct socklist sc_sockets; struct timeval sc_starttime; u_int32_t sc_engine_boots; @@ -652,7 +658,7 @@ struct kif_arp *karp_getaddr(struct sockaddr *, u_short, int); /* snmpe.c */ void snmpe(struct privsep *, struct privsep_proc *); void snmpe_shutdown(void); -void snmpe_dispatchmsg(struct snmp_message *); +void snmpe_dispatchmsg(struct snmp_message *, int); /* trap.c */ void trap_init(void); diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c index 23d0dfe32c5..7bb2ea6ee32 100644 --- a/usr.sbin/snmpd/snmpe.c +++ b/usr.sbin/snmpd/snmpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpe.c,v 1.45 2016/11/09 20:31:56 jca Exp $ */ +/* $OpenBSD: snmpe.c,v 1.46 2016/11/18 16:16:39 jca Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -61,7 +61,9 @@ static struct privsep_proc procs[] = { void snmpe(struct privsep *ps, struct privsep_proc *p) { - struct snmpd *env = ps->ps_env; + struct snmpd *env = ps->ps_env; + struct address *h; + struct listen_sock *so; #ifdef DEBUG char buf[BUFSIZ]; struct oid *oid; @@ -74,9 +76,13 @@ snmpe(struct privsep *ps, struct privsep_proc *p) } #endif - /* bind SNMP UDP socket */ - if ((env->sc_sock = snmpe_bind(&env->sc_address)) == -1) - fatalx("snmpe: failed to bind SNMP UDP socket"); + TAILQ_FOREACH(h, &env->sc_addresses, entry) { + if ((so = calloc(1, sizeof(*so))) == NULL) + fatal("snmpe: %s", __func__); + if ((so->s_fd = snmpe_bind(h)) == -1) + fatal("snmpe: failed to bind SNMP UDP socket"); + TAILQ_INSERT_TAIL(&env->sc_sockets, so, entry); + } proc_run(ps, p, procs, nitems(procs), snmpe_init, NULL); } @@ -85,7 +91,8 @@ snmpe(struct privsep *ps, struct privsep_proc *p) void snmpe_init(struct privsep *ps, struct privsep_proc *p, void *arg) { - struct snmpd *env = ps->ps_env; + struct snmpd *env = ps->ps_env; + struct listen_sock *so; kr_init(); trap_init(); @@ -93,9 +100,11 @@ snmpe_init(struct privsep *ps, struct privsep_proc *p, void *arg) usm_generate_keys(); /* listen for incoming SNMP UDP messages */ - event_set(&env->sc_ev, env->sc_sock, EV_READ|EV_PERSIST, - snmpe_recvmsg, env); - event_add(&env->sc_ev, NULL); + TAILQ_FOREACH(so, &env->sc_sockets, entry) { + event_set(&so->s_ev, so->s_fd, EV_READ|EV_PERSIST, + snmpe_recvmsg, env); + event_add(&so->s_ev, NULL); + } } void @@ -156,7 +165,7 @@ snmpe_bind(struct address *addr) if (print_host(&addr->ss, buf, sizeof(buf)) == NULL) goto bad; - log_info("snmpe_bind: binding to address %s:%d", buf, addr->port); + log_info("snmpe: listening on %s:%d", buf, addr->port); return (s); @@ -519,18 +528,18 @@ snmpe_recvmsg(int fd, short sig, void *arg) } } - snmpe_dispatchmsg(msg); + snmpe_dispatchmsg(msg, fd); } void -snmpe_dispatchmsg(struct snmp_message *msg) +snmpe_dispatchmsg(struct snmp_message *msg, int sock) { if (snmpe_parsevarbinds(msg) == 1) return; /* not dispatched to subagent; respond directly */ msg->sm_context = SNMP_C_GETRESP; - snmpe_response(snmpd_env->sc_sock, msg); + snmpe_response(sock, msg); } void diff --git a/usr.sbin/snmpd/traphandler.c b/usr.sbin/snmpd/traphandler.c index a89ac42c120..76f48bfa031 100644 --- a/usr.sbin/snmpd/traphandler.c +++ b/usr.sbin/snmpd/traphandler.c @@ -1,4 +1,4 @@ -/* $OpenBSD: traphandler.c,v 1.6 2016/10/28 09:07:08 rzalamena Exp $ */ +/* $OpenBSD: traphandler.c,v 1.7 2016/11/18 16:16:39 jca Exp $ */ /* * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org> @@ -43,8 +43,6 @@ #include "snmpd.h" #include "mib.h" -int trapsock; -struct event trapev; char trap_path[PATH_MAX]; void traphandler_init(struct privsep *, struct privsep_proc *, void *arg); @@ -76,10 +74,18 @@ void traphandler(struct privsep *ps, struct privsep_proc *p) { struct snmpd *env = ps->ps_env; - - if (env->sc_traphandler && - (trapsock = traphandler_bind(&env->sc_address)) == -1) - fatal("could not create trap listener socket"); + struct address *h; + struct listen_sock *so; + + if (env->sc_traphandler) { + TAILQ_FOREACH(h, &env->sc_addresses, entry) { + if ((so = calloc(1, sizeof(*so))) == NULL) + fatal("%s", __func__); + if ((so->s_fd = traphandler_bind(h)) == -1) + fatal("could not create trap listener socket"); + TAILQ_INSERT_TAIL(&env->sc_sockets, so, entry); + } + } proc_run(ps, p, procs, nitems(procs), traphandler_init, NULL); } @@ -88,20 +94,24 @@ void traphandler_init(struct privsep *ps, struct privsep_proc *p, void *arg) { struct snmpd *env = ps->ps_env; + struct listen_sock *so; if (!env->sc_traphandler) return; /* listen for SNMP trap messages */ - event_set(&trapev, trapsock, EV_READ|EV_PERSIST, traphandler_recvmsg, - ps); - event_add(&trapev, NULL); + TAILQ_FOREACH(so, &env->sc_sockets, entry) { + event_set(&so->s_ev, so->s_fd, EV_READ|EV_PERSIST, + traphandler_recvmsg, ps); + event_add(&so->s_ev, NULL); + } } int traphandler_bind(struct address *addr) { int s; + char buf[512]; if ((s = snmpd_socket_af(&addr->ss, htons(SNMPD_TRAPPORT))) == -1) return (-1); @@ -112,6 +122,11 @@ traphandler_bind(struct address *addr) if (bind(s, (struct sockaddr *)&addr->ss, addr->ss.ss_len) == -1) goto bad; + if (print_host(&addr->ss, buf, sizeof(buf)) == NULL) + goto bad; + + log_info("traphandler: listening on %s:%d", buf, SNMPD_TRAPPORT); + return (s); bad: close (s); @@ -121,8 +136,12 @@ traphandler_bind(struct address *addr) void traphandler_shutdown(void) { - event_del(&trapev); - close(trapsock); + struct listen_sock *so; + + TAILQ_FOREACH(so, &snmpd_env->sc_sockets, entry) { + event_del(&so->s_ev); + close(so->s_fd); + } } int |