New diff, which 
 a) deals with ENFILE
 b) fixes an embarrassing bug for IPv6 accepts

Any OKs?

Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v
retrieving revision 1.43
diff -u -p -p -u -r1.43 parse.y
--- parse.y     5 Jan 2017 13:53:10 -0000       1.43
+++ parse.y     28 Jul 2017 14:21:21 -0000
@@ -99,9 +99,9 @@ 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 *);
+                   struct address *, int);
 int             host(const char *, struct addresslist *,
-                   int, in_port_t, struct ber_oid *, char *, char *);
+                   int, in_port_t, struct ber_oid *, char *, char *, int);
 
 typedef struct {
        union {
@@ -128,12 +128,12 @@ typedef struct {
 %token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER
 %token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER
 %token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED
-%token SOCKET RESTRICTED AGENTX HANDLE DEFAULT SRCADDR
+%token SOCKET RESTRICTED AGENTX HANDLE DEFAULT SRCADDR TCP UDP
 %token <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.string>      hostcmn
 %type  <v.string>      srcaddr
-%type  <v.number>      optwrite yesno seclevel socktype
+%type  <v.number>      optwrite yesno seclevel socktype proto
 %type  <v.data>        objtype cmd
 %type  <v.oid>         oid hostoid trapoid
 %type  <v.auth>        auth
@@ -197,9 +197,9 @@ yesno               :  STRING                       {
                }
                ;
 
-main           : LISTEN ON STRING              {
+main           : LISTEN ON STRING proto        {
                        if (host($3, &conf->sc_addresses, 16, SNMPD_PORT, NULL,
-                           NULL, NULL) <= 0) {
+                           NULL, NULL, $4) <= 0) {
                                yyerror("invalid ip address: %s", $3);
                                free($3);
                                YYERROR;
@@ -442,7 +442,7 @@ srcaddr             : /* empty */                           
{ $$ = NULL; }
 
 hostdef                : STRING hostoid hostcmn srcaddr        {
                        if (host($1, hlist, 1,
-                           SNMPD_TRAPPORT, $2, $3, $4) <= 0) {
+                           SNMPD_TRAPPORT, $2, $3, $4, 0) <= 0) {
                                yyerror("invalid host: %s", $1);
                                free($1);
                                YYERROR;
@@ -524,6 +524,11 @@ socktype   : RESTRICTED            { $$ = SOCK_TYPE_
                | /* nothing */         { $$ = 0; }
                ;
 
+proto          : /* empty */                   { $$ = IPPROTO_UDP; }
+               | TCP                           { $$ = IPPROTO_TCP; }
+               | UDP                           { $$ = IPPROTO_UDP; }
+               ;
+
 cmd            : STRING                {
                        struct           trapcmd *cmd;
                        size_t           span, limit;
@@ -634,7 +639,9 @@ lookup(char *s)
                { "source-address",     SRCADDR },
                { "string",             OCTETSTRING },
                { "system",             SYSTEM },
+               { "tcp",                TCP },
                { "trap",               TRAP },
+               { "udp",                UDP },
                { "user",               USER }
        };
        const struct keywords   *p;
@@ -969,6 +976,8 @@ struct snmpd *
 parse_config(const char *filename, u_int flags)
 {
        struct sym      *sym, *next;
+       struct address  *h;
+       int found;
 
        if ((conf = calloc(1, sizeof(*conf))) == NULL) {
                log_warn("cannot allocate memory");
@@ -999,18 +1008,25 @@ parse_config(const char *filename, u_int
 
        endservent();
 
+       /* Setup default listen addresses */
        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);
+               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 (conf->sc_traphandler) {
+               found = 0;
+               TAILQ_FOREACH(h, &conf->sc_addresses, entry) {
+                       if (h->ipproto == IPPROTO_UDP)
+                               found = 1;
+               }
+               if (!found) {
+                       log_warnx("trap handler needs at least one "
+                           "udp listen address");
+                       free(conf);
+                       return (NULL);
+               }
        }
 
        /* Free macros and check which have not been used. */
@@ -1162,7 +1178,8 @@ host_v6(const char *s)
 
 int
 host_dns(const char *s, struct addresslist *al, int max,
-       in_port_t port, struct ber_oid *oid, char *cmn, struct address *src)
+    in_port_t port, struct ber_oid *oid, char *cmn,
+    struct address *src, int ipproto)
 {
        struct addrinfo          hints, *res0, *res;
        int                      error, cnt = 0;
@@ -1193,6 +1210,7 @@ host_dns(const char *s, struct addressli
                        fatal(__func__);
 
                h->port = port;
+               h->ipproto = ipproto;
                if (oid != NULL) {
                        if ((h->sa_oid = calloc(1, sizeof(*oid))) == NULL)
                                fatal(__func__);
@@ -1235,7 +1253,7 @@ host_dns(const char *s, struct addressli
 
 int
 host(const char *s, struct addresslist *al, int max,
-    in_port_t port, struct ber_oid *oid, char *cmn, char *srcaddr)
+    in_port_t port, struct ber_oid *oid, char *cmn, char *srcaddr, int ipproto)
 {
        struct address  *h, *src = NULL;
 
@@ -1259,6 +1277,7 @@ host(const char *s, struct addresslist *
                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);
@@ -1269,5 +1288,5 @@ host(const char *s, struct addresslist *
                return (1);
        }
 
-       return (host_dns(s, al, max, port, oid, cmn, src));
+       return (host_dns(s, al, max, port, oid, cmn, src, ipproto));
 }
Index: snmpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.c,v
retrieving revision 1.36
diff -u -p -p -u -r1.36 snmpd.c
--- snmpd.c     4 Apr 2017 02:37:15 -0000       1.36
+++ snmpd.c     28 Jul 2017 14:21:21 -0000
@@ -310,7 +310,7 @@ snmpd_dispatch_snmpe(int fd, struct priv
 }
 
 int
-snmpd_socket_af(struct sockaddr_storage *ss, in_port_t port)
+snmpd_socket_af(struct sockaddr_storage *ss, in_port_t port, int ipproto)
 {
        int      s;
 
@@ -329,7 +329,13 @@ snmpd_socket_af(struct sockaddr_storage 
                return (-1);
        }
 
-       s = socket(ss->ss_family, SOCK_DGRAM, IPPROTO_UDP);
+       if (ipproto == IPPROTO_TCP)
+               s = socket(ss->ss_family,
+                   SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
+       else
+               s = socket(ss->ss_family,
+                   SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, IPPROTO_UDP);
+
        return (s);
 }
 
Index: snmpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.conf.5,v
retrieving revision 1.35
diff -u -p -p -u -r1.35 snmpd.conf.5
--- snmpd.conf.5        9 Nov 2016 20:31:56 -0000       1.35
+++ snmpd.conf.5        28 Jul 2017 14:21:21 -0000
@@ -86,10 +86,13 @@ Routing table information will not be av
 reduced during bulk updates.
 The default is
 .Ic no .
-.It Ic listen on Ar address
+.It Ic listen on Ar address Op Ic tcp | udp
 Specify the local address
 .Xr snmpd 8
 should listen on for incoming SNMP messages.
+Multiple
+.Ic listen on
+statements are supported, the default is UDP.
 .It Ic read-only community Ar string
 Specify the name of the read-only community.
 The default value is
@@ -198,6 +201,9 @@ the resolved hostname of the host sendin
 the IP address of the host sending the trap,
 and any variable bindings contained in the trap
 (the OID followed by the value, separated by a single space).
+Traps will will be accepted on all
+.Ic listen on
+UDP addresses.
 .It Xo
 .Ic trap receiver Ar string
 .Op Ic oid Ar oid-string
Index: snmpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v
retrieving revision 1.75
diff -u -p -p -u -r1.75 snmpd.h
--- snmpd.h     21 Apr 2017 13:50:23 -0000      1.75
+++ snmpd.h     28 Jul 2017 14:21:21 -0000
@@ -403,6 +403,8 @@ struct pfr_buffer {
 struct snmp_message {
        int                      sm_sock;
        struct sockaddr_storage  sm_ss;
+       int                      sm_sock_tcp;
+       struct event             sm_sockev;
        socklen_t                sm_slen;
        char                     sm_host[HOST_NAME_MAX+1];
 
@@ -509,6 +511,7 @@ struct snmp_stats {
 struct address {
        struct sockaddr_storage  ss;
        in_port_t                port;
+       int                      ipproto;
 
        TAILQ_ENTRY(address)     entry;
 
@@ -521,7 +524,9 @@ TAILQ_HEAD(addresslist, address);
 
 struct listen_sock {
        int                             s_fd;
+       int                             s_ipproto;
        struct event                    s_ev;
+       struct event                    s_evt;
        TAILQ_ENTRY(listen_sock)        entry;
 };
 TAILQ_HEAD(socklist, listen_sock);
@@ -739,7 +744,7 @@ char                *smi_print_element(struct ber_elem
 void            timer_init(void);
 
 /* snmpd.c */
-int             snmpd_socket_af(struct sockaddr_storage *, in_port_t);
+int             snmpd_socket_af(struct sockaddr_storage *, in_port_t, int);
 u_long          snmpd_engine_time(void);
 char           *tohexstr(u_int8_t *, int);
 
Index: snmpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v
retrieving revision 1.47
diff -u -p -p -u -r1.47 snmpe.c
--- snmpe.c     21 Apr 2017 13:50:23 -0000      1.47
+++ snmpe.c     28 Jul 2017 14:21:22 -0000
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (c) 2007, 2008, 2012 Reyk Floeter <[email protected]>
+ * Copyright (c) 2017 Marco Pfatschbacher <[email protected]>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -49,10 +50,16 @@ void         snmpe_sig_handler(int sig, short, 
 int     snmpe_dispatch_parent(int, struct privsep_proc *, struct imsg *);
 int     snmpe_bind(struct address *);
 void    snmpe_recvmsg(int fd, short, void *);
+void    snmpe_readcb(int fd, short, void *);
+void    snmpe_writecb(int fd, short, void *);
+void    snmpe_accept_cb(int fd, short, void *);
+void    snmpe_prepare_read(struct snmp_message *, int);
 int     snmpe_encode(struct snmp_message *);
 void    snmp_msgfree(struct snmp_message *);
 
 struct imsgev  *iev_parent;
+struct timeval snmpe_tcp_timeout;
+#define SNMPE_TCP_TIMEOUT 10
 
 static struct privsep_proc procs[] = {
        { "parent",     PROC_PARENT,    snmpe_dispatch_parent }
@@ -76,11 +83,13 @@ snmpe(struct privsep *ps, struct privsep
        }
 #endif
 
+       /* bind SNMP UDP/TCP sockets */
        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");
+                       fatal("snmpe: failed to bind SNMP socket");
+               so->s_ipproto = h->ipproto;
                TAILQ_INSERT_TAIL(&env->sc_sockets, so, entry);
        }
 
@@ -99,10 +108,20 @@ snmpe_init(struct privsep *ps, struct pr
        timer_init();
        usm_generate_keys();
 
-       /* listen for incoming SNMP UDP messages */
+       timerclear(&snmpe_tcp_timeout);
+       snmpe_tcp_timeout.tv_sec = SNMPE_TCP_TIMEOUT;
+
+       /* listen for incoming SNMP UDP/TCP messages */
        TAILQ_FOREACH(so, &env->sc_sockets, entry) {
-               event_set(&so->s_ev, so->s_fd, EV_READ|EV_PERSIST,
-                   snmpe_recvmsg, env);
+               if (so->s_ipproto == IPPROTO_TCP) {
+                       if (listen(so->s_fd, 5) < 0)
+                               fatalx("snmpe: failed to listen on socket");
+                       event_set(&so->s_ev, so->s_fd, EV_READ, 
snmpe_accept_cb, so);
+                       evtimer_set(&so->s_evt, snmpe_accept_cb, so);
+               } else {
+                       event_set(&so->s_ev, so->s_fd, EV_READ|EV_PERSIST,
+                           snmpe_recvmsg, env);
+               }
                event_add(&so->s_ev, NULL);
        }
 }
@@ -110,6 +129,13 @@ snmpe_init(struct privsep *ps, struct pr
 void
 snmpe_shutdown(void)
 {
+       struct listen_sock *so;
+
+       TAILQ_FOREACH(so, &snmpd_env->sc_sockets, entry) {
+               event_del(&so->s_ev);
+               event_del(&so->s_evt);
+               close(so->s_fd);
+       }
        kr_shutdown();
 }
 
@@ -130,32 +156,34 @@ snmpe_bind(struct address *addr)
        char     buf[512];
        int      val, s;
 
-       if ((s = snmpd_socket_af(&addr->ss, htons(addr->port))) == -1)
+       if ((s = snmpd_socket_af(&addr->ss, htons(addr->port),
+           addr->ipproto)) == -1)
                return (-1);
 
-       /*
-        * Socket options
-        */
-       if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
-               goto bad;
-
-       switch (addr->ss.ss_family) {
-       case AF_INET:
-               val = 1;
-               if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
-                   &val, sizeof(int)) == -1) {
-                       log_warn("%s: failed to set IPv4 packet info",
-                           __func__);
-                       goto bad;
-               }
-               break;
-       case AF_INET6:
+       if (addr->ipproto == IPPROTO_TCP) {
                val = 1;
-               if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
-                   &val, sizeof(int)) == -1) {
-                       log_warn("%s: failed to set IPv6 packet info",
-                           __func__);
-                       goto bad;
+               if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                   &val, sizeof(val)) == -1)
+                       fatal("setsockopt: %s", strerror(errno));
+       } else { /* UDP */
+               switch (addr->ss.ss_family) {
+               case AF_INET:
+                       val = 1;
+                       if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
+                           &val, sizeof(int)) == -1) {
+                               log_warn("%s: failed to set IPv4 packet info",
+                                   __func__);
+                               goto bad;
+                       }
+                       break;
+               case AF_INET6:
+                       val = 1;
+                       if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+                           &val, sizeof(int)) == -1) {
+                               log_warn("%s: failed to set IPv6 packet info",
+                                   __func__);
+                               goto bad;
+                       }
                }
        }
 
@@ -165,7 +193,8 @@ snmpe_bind(struct address *addr)
        if (print_host(&addr->ss, buf, sizeof(buf)) == NULL)
                goto bad;
 
-       log_info("snmpe: listening on %s:%d", buf, addr->port);
+       log_info("snmpe: listening on %s %s:%d",
+           (addr->ipproto == IPPROTO_TCP) ? "tcp" : "udp", buf, addr->port);
 
        return (s);
 
@@ -479,6 +508,149 @@ snmpe_parsevarbinds(struct snmp_message 
 }
 
 void
+snmpe_accept_cb(int fd, short type, void *arg)
+{
+       struct listen_sock      *so = arg;
+       struct sockaddr_storage ss;
+       socklen_t len = sizeof(ss);
+       struct snmp_message     *msg;
+       int afd;
+
+       event_add(&so->s_ev, NULL);
+       if ((type & EV_TIMEOUT))
+               return;
+
+       if ((afd = accept4(fd, (struct sockaddr *)&ss, &len,
+           SOCK_NONBLOCK|SOCK_CLOEXEC)) < 0) {
+               /* Pause accept if we are out of file descriptors  */
+               if (errno == ENFILE || errno == EMFILE) {
+                       struct timeval evtpause = { 1, 0 };
+
+                       event_del(&so->s_ev);
+                       evtimer_add(&so->s_evt, &evtpause);
+               } else if (errno != EWOULDBLOCK && errno != EAGAIN)
+                       log_warnx("%s: accept4: %s", __func__, strerror(errno));
+               return;
+       }
+       if ((msg = calloc(1, sizeof(*msg))) == NULL)
+               goto fail;
+
+       snmpe_prepare_read(msg, afd);
+       return;
+fail:
+       free(msg);
+       close(afd);
+       return;
+}
+
+void
+snmpe_prepare_read(struct snmp_message *msg, int fd)
+{
+       msg->sm_sock = fd;
+       msg->sm_sock_tcp = 1;
+       msg->sm_ber.fd = -1;
+       event_set(&msg->sm_sockev, fd, EV_READ,
+           snmpe_readcb, msg);
+       event_add(&msg->sm_sockev, &snmpe_tcp_timeout);
+}
+
+void
+snmpe_readcb(int fd, short type, void *arg)
+{
+       struct snmp_stats       *stats = &snmpd_env->sc_stats;
+       struct snmp_message *msg = arg;
+       ssize_t len;
+
+       if (type == EV_TIMEOUT) {
+               snmp_msgfree(msg);
+               close(fd);
+               return;
+       }
+       len = read(fd, msg->sm_data + msg->sm_datalen,
+           sizeof(msg->sm_data) - msg->sm_datalen);
+       if (len <= 0) {
+               if (errno != EAGAIN && errno != EINTR) {
+                       snmp_msgfree(msg);
+                       close(fd);
+                       return;
+               }
+               snmpe_prepare_read(msg, fd);
+               return;
+       }
+
+       msg->sm_datalen += (size_t)len;
+       msg->sm_ber.fd = -1;
+       ber_set_application(&msg->sm_ber, smi_application);
+       ber_set_readbuf(&msg->sm_ber, msg->sm_data, msg->sm_datalen);
+       msg->sm_req = ber_read_elements(&msg->sm_ber, NULL);
+       if (msg->sm_req == NULL) {
+               /* short read; try again */
+               snmpe_prepare_read(msg, fd);
+               return;
+       }
+
+       if (snmpe_parse(msg) == -1) {
+               if (msg->sm_usmerr && MSG_REPORT(msg)) {
+                       usm_make_report(msg);
+                       snmpe_response(msg);
+                       return;
+               } else {
+                       snmp_msgfree(msg);
+                       close(fd);
+                       return;
+               }
+       }
+       stats->snmp_inpkts++;
+
+       snmpe_dispatchmsg(msg);
+}
+
+void
+snmpe_writecb(int fd, short type, void *arg)
+{
+       struct snmp_stats       *stats = &snmpd_env->sc_stats;
+       struct snmp_message *msg = arg;
+       ssize_t len;
+       struct ber *ber = &msg->sm_ber;
+
+       if (type == EV_TIMEOUT)
+               goto fail;
+
+       len = ber->br_wend - ber->br_wbuf;
+       ber->br_wptr = ber->br_wbuf;
+
+       log_debug("%s: write fd %d len %zd", __func__, fd, len);
+
+       len = write(fd, ber->br_wptr, len);
+       if (len == -1 && errno != EAGAIN && errno != EINTR)
+               goto fail;
+
+       ber->br_wptr += len;
+
+       if (ber->br_wptr < ber->br_wend) {
+               event_set(&msg->sm_sockev, msg->sm_sock, EV_WRITE,
+                   snmpe_writecb, msg);
+               event_add(&msg->sm_sockev, &snmpe_tcp_timeout);
+               return;
+       }
+
+       stats->snmp_outpkts++;
+       snmp_msgfree(msg);
+
+       /* socket can be reused; wait for another message */
+       if ((msg = calloc(1, sizeof(*msg))) == NULL) {
+               close(fd);
+               return;
+       }
+       snmpe_prepare_read(msg, fd);
+       return;
+
+ fail:
+       close(fd);
+       snmp_msgfree(msg);
+}
+
+void
 snmpe_recvmsg(int fd, short sig, void *arg)
 {
        struct snmpd            *env = arg;
@@ -535,10 +707,11 @@ snmpe_recvmsg(int fd, short sig, void *a
 void
 snmpe_dispatchmsg(struct snmp_message *msg)
 {
+       /* dispatched to subagent */
        if (snmpe_parsevarbinds(msg) == 1)
                return;
 
-       /* not dispatched to subagent; respond directly */
+       /* respond directly */
        msg->sm_context = SNMP_C_GETRESP;
        snmpe_response(msg);
 }
@@ -581,11 +754,18 @@ snmpe_response(struct snmp_message *msg)
                goto done;
 
        usm_finalize_digest(msg, ptr, len);
-       len = sendtofrom(msg->sm_sock, ptr, len, 0,
-           (struct sockaddr *)&msg->sm_ss, msg->sm_slen,
-           (struct sockaddr *)&msg->sm_local_ss, msg->sm_local_slen);
-       if (len != -1)
-               stats->snmp_outpkts++;
+       if (msg->sm_sock_tcp) {
+               event_set(&msg->sm_sockev, msg->sm_sock, EV_WRITE,
+                   snmpe_writecb, msg);
+               event_add(&msg->sm_sockev, &snmpe_tcp_timeout);
+               return;
+       } else {
+               len = sendtofrom(msg->sm_sock, ptr, len, 0,
+                   (struct sockaddr *)&msg->sm_ss, msg->sm_slen,
+                   (struct sockaddr *)&msg->sm_local_ss, msg->sm_local_slen);
+               if (len != -1)
+                       stats->snmp_outpkts++;
+       }
 
  done:
        snmp_msgfree(msg);
Index: trap.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/trap.c,v
retrieving revision 1.29
diff -u -p -p -u -r1.29 trap.c
--- trap.c      21 Apr 2017 13:46:15 -0000      1.29
+++ trap.c      28 Jul 2017 14:21:22 -0000
@@ -196,7 +196,8 @@ trap_send(struct ber_oid *oid, struct be
                                continue;
                }
 
-               if ((s = snmpd_socket_af(&tr->ss, htons(tr->port))) == -1) {
+               if ((s = snmpd_socket_af(&tr->ss, htons(tr->port),
+                   IPPROTO_UDP)) == -1) {
                        ret = -1;
                        goto done;
                }
Index: traphandler.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v
retrieving revision 1.8
diff -u -p -p -u -r1.8 traphandler.c
--- traphandler.c       9 Jan 2017 14:49:22 -0000       1.8
+++ traphandler.c       28 Jul 2017 14:21:22 -0000
@@ -79,6 +79,8 @@ traphandler(struct privsep *ps, struct p
 
        if (env->sc_traphandler) {
                TAILQ_FOREACH(h, &env->sc_addresses, entry) {
+                       if (h->ipproto != IPPROTO_UDP)
+                               continue;
                        if ((so = calloc(1, sizeof(*so))) == NULL)
                                fatal("%s", __func__);
                        if ((so->s_fd = traphandler_bind(h)) == -1)
@@ -113,7 +115,8 @@ traphandler_bind(struct address *addr)
        int                      s;
        char                     buf[512];
 
-       if ((s = snmpd_socket_af(&addr->ss, htons(SNMPD_TRAPPORT))) == -1)
+       if ((s = snmpd_socket_af(&addr->ss, htons(SNMPD_TRAPPORT),
+           IPPROTO_UDP)) == -1)
                return (-1);
 
        if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)

Reply via email to