diff options
Diffstat (limited to 'contrib/bsnmp')
-rw-r--r-- | contrib/bsnmp/gensnmpdef/gensnmpdef.c | 11 | ||||
-rw-r--r-- | contrib/bsnmp/lib/snmp.c | 6 | ||||
-rw-r--r-- | contrib/bsnmp/lib/snmpclient.c | 11 | ||||
-rw-r--r-- | contrib/bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt | 3 | ||||
-rw-r--r-- | contrib/bsnmp/snmp_mibII/mibII.c | 22 | ||||
-rw-r--r-- | contrib/bsnmp/snmp_mibII/mibII_interfaces.c | 6 | ||||
-rw-r--r-- | contrib/bsnmp/snmp_mibII/snmp_mibII.3 | 4 | ||||
-rw-r--r-- | contrib/bsnmp/snmp_usm/usm_snmp.c | 6 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/BEGEMOT-MIB.txt | 3 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/FOKUS-MIB.txt | 3 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/main.c | 205 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/snmpd.h | 1 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/trans_lsock.c | 82 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/trans_udp.c | 137 | ||||
-rw-r--r-- | contrib/bsnmp/snmpd/trans_udp.h | 3 |
15 files changed, 268 insertions, 235 deletions
diff --git a/contrib/bsnmp/gensnmpdef/gensnmpdef.c b/contrib/bsnmp/gensnmpdef/gensnmpdef.c index 32c835d..b0bfdaf 100644 --- a/contrib/bsnmp/gensnmpdef/gensnmpdef.c +++ b/contrib/bsnmp/gensnmpdef/gensnmpdef.c @@ -126,9 +126,11 @@ open_node(const SmiNode *n, u_int level, SmiNode **last) while (level < n->oidlen - 1) { if (level >= cut) { + n1 = smiGetNodeByOID(level + 1, n->oid); + if (n1 == NULL) + continue; pindent(level); printf("(%u", n->oid[level]); - n1 = smiGetNodeByOID(level + 1, n->oid); printf(" "); print_name(n1); printf("\n"); @@ -397,12 +399,11 @@ static void save_typdef(char *name) { struct tdef *t; - t = malloc(sizeof(struct tdef)); + t = calloc(1, sizeof(struct tdef)); if (t == NULL) err(1, NULL); - memset(t, 0 , sizeof(struct tdef)); t->name = name; SLIST_INSERT_HEAD(&tdefs, t, link); } @@ -559,7 +560,11 @@ main(int argc, char *argv[]) level = 0; last = NULL; for (opt = 0; opt < argc; opt++) { + if (mods[opt] == NULL) /* smiGetModule failed above */ + continue; n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY); + if (n == NULL) + continue; for (;;) { if (do_typedef == 0) { level = open_node(n, level, &last); diff --git a/contrib/bsnmp/lib/snmp.c b/contrib/bsnmp/lib/snmp.c index 68f46f9..d86f88a 100644 --- a/contrib/bsnmp/lib/snmp.c +++ b/contrib/bsnmp/lib/snmp.c @@ -1154,8 +1154,11 @@ snmp_pdu_dump(const struct snmp_pdu *pdu) void snmp_value_free(struct snmp_value *value) { - if (value->syntax == SNMP_SYNTAX_OCTETSTRING) + + if (value->syntax == SNMP_SYNTAX_OCTETSTRING) { free(value->v.octetstring.octets); + value->v.octetstring.octets = NULL; + } value->syntax = SNMP_SYNTAX_NULL; } @@ -1216,6 +1219,7 @@ snmp_pdu_free(struct snmp_pdu *pdu) for (i = 0; i < pdu->nbindings; i++) snmp_value_free(&pdu->bindings[i]); + pdu->nbindings = 0; } /* diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c index 90b7d4a..10c58f5 100644 --- a/contrib/bsnmp/lib/snmpclient.c +++ b/contrib/bsnmp/lib/snmpclient.c @@ -728,8 +728,11 @@ snmp_table_fetch_async(const struct snmp_table *descr, void *list, work->last_change = 0; table_init_pdu(descr, &work->pdu); - if (snmp_pdu_send(&work->pdu, table_cb, work) == -1) + if (snmp_pdu_send(&work->pdu, table_cb, work) == -1) { + free(work); + work = NULL; return (-1); + } return (0); } @@ -1231,7 +1234,7 @@ snmp_send_packet(struct snmp_pdu * pdu) struct asn_buf b; ssize_t ret; - if ((buf = malloc(snmp_client.txbuflen)) == NULL) { + if ((buf = calloc(1, snmp_client.txbuflen)) == NULL) { seterr(&snmp_client, "%s", strerror(errno)); return (-1); } @@ -1256,7 +1259,7 @@ snmp_send_packet(struct snmp_pdu * pdu) } free(buf); - return pdu->request_id; + return (pdu->request_id); } /* @@ -1352,7 +1355,7 @@ snmp_receive_packet(struct snmp_pdu *pdu, struct timeval *tv) socklen_t optlen; #endif - if ((buf = malloc(snmp_client.rxbuflen)) == NULL) { + if ((buf = calloc(1, snmp_client.rxbuflen)) == NULL) { seterr(&snmp_client, "%s", strerror(errno)); return (-1); } diff --git a/contrib/bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt b/contrib/bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt index 761876a..29f7844 100644 --- a/contrib/bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt +++ b/contrib/bsnmp/snmp_mibII/BEGEMOT-IP-MIB.txt @@ -54,6 +54,9 @@ begemotIp MODULE-IDENTITY E-mail: harti@freebsd.org" DESCRIPTION "The MIB for IP stuff that is not in the official IP MIBs." + REVISION "200602130000Z" + DESCRIPTION + "Initial revision." ::= { begemot 3 } begemotIpObjects OBJECT IDENTIFIER ::= { begemotIp 1 } diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c index 85c61d5..e66a951 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.c +++ b/contrib/bsnmp/snmp_mibII/mibII.c @@ -265,7 +265,7 @@ mib_if_admin(struct mibif *ifp, int up) { struct ifreq ifr; - strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) { syslog(LOG_ERR, "SIOCGIFFLAGS(%s): %m", ifp->name); return (-1); @@ -319,7 +319,7 @@ fetch_generic_mib(struct mibif *ifp, const struct ifmibdata *old) name[5] = IFDATA_GENERAL; len = sizeof(ifp->mib); - if (sysctl(name, 6, &ifp->mib, &len, NULL, 0) == -1) { + if (sysctl(name, nitems(name), &ifp->mib, &len, NULL, 0) == -1) { if (errno != ENOENT) syslog(LOG_WARNING, "sysctl(ifmib, %s) failed %m", ifp->name); @@ -480,7 +480,7 @@ mib_fetch_ifmib(struct mibif *ifp) name[3] = IFMIB_IFDATA; name[4] = ifp->sysindex; name[5] = IFDATA_LINKSPECIFIC; - if (sysctl(name, 6, NULL, &len, NULL, 0) == -1) { + if (sysctl(name, nitems(name), NULL, &len, NULL, 0) == -1) { syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m", ifp->name); if (ifp->specmib != NULL) { @@ -506,7 +506,7 @@ mib_fetch_ifmib(struct mibif *ifp) ifp->specmib = newmib; ifp->specmiblen = len; } - if (sysctl(name, 6, ifp->specmib, &len, NULL, 0) == -1) { + if (sysctl(name, nitems(name), ifp->specmib, &len, NULL, 0) == -1) { syslog(LOG_WARNING, "sysctl linkmib (%s): %m", ifp->name); if (ifp->specmib != NULL) { ifp->specmib = NULL; @@ -515,7 +515,7 @@ mib_fetch_ifmib(struct mibif *ifp) } out: - strncpy(irr.ifr_name, ifp->name, sizeof(irr.ifr_name)); + strlcpy(irr.ifr_name, ifp->name, sizeof(irr.ifr_name)); irr.ifr_buffer.buffer = MIBIF_PRIV(ifp)->alias; irr.ifr_buffer.length = sizeof(MIBIF_PRIV(ifp)->alias); if (ioctl(mib_netsock, SIOCGIFDESCR, &irr) == -1) { @@ -902,7 +902,7 @@ mib_refresh_iflist(void) for (idx = 1; idx <= count; idx++) { name[4] = idx; len = sizeof(mib); - if (sysctl(name, 6, &mib, &len, NULL, 0) == -1) { + if (sysctl(name, nitems(name), &mib, &len, NULL, 0) == -1) { if (errno == ENOENT) continue; syslog(LOG_ERR, "ifmib(%u): %m", idx); @@ -1213,7 +1213,7 @@ mib_fetch_rtab(int af, int info, int arg, size_t *lenp) *lenp = 0; /* initial estimate */ - if (sysctl(name, 6, NULL, lenp, NULL, 0) == -1) { + if (sysctl(name, nitems(name), NULL, lenp, NULL, 0) == -1) { syslog(LOG_ERR, "sysctl estimate (%d,%d,%d,%d,%d,%d): %m", name[0], name[1], name[2], name[3], name[4], name[5]); return (NULL); @@ -1230,7 +1230,7 @@ mib_fetch_rtab(int af, int info, int arg, size_t *lenp) } buf = newbuf; - if (sysctl(name, 6, buf, lenp, NULL, 0) == 0) + if (sysctl(name, nitems(name), buf, lenp, NULL, 0) == 0) break; if (errno != ENOMEM) { @@ -1384,7 +1384,7 @@ siocaifaddr(char *ifname, struct in_addr addr, struct in_addr mask, struct sockaddr_in *sa; memset(&addreq, 0, sizeof(addreq)); - strncpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); + strlcpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); sa = (struct sockaddr_in *)(void *)&addreq.ifra_addr; sa->sin_family = AF_INET; @@ -1414,7 +1414,7 @@ siocdifaddr(const char *ifname, struct in_addr addr) struct sockaddr_in *sa; memset(&delreq, 0, sizeof(delreq)); - strncpy(delreq.ifr_name, ifname, sizeof(delreq.ifr_name)); + strlcpy(delreq.ifr_name, ifname, sizeof(delreq.ifr_name)); sa = (struct sockaddr_in *)(void *)&delreq.ifr_addr; sa->sin_family = AF_INET; sa->sin_len = sizeof(*sa); @@ -1433,7 +1433,7 @@ verify_ifa(const char *name, struct mibifa *ifa) struct sockaddr_in *sa; memset(&req, 0, sizeof(req)); - strncpy(req.ifr_name, name, sizeof(req.ifr_name)); + strlcpy(req.ifr_name, name, sizeof(req.ifr_name)); sa = (struct sockaddr_in *)(void *)&req.ifr_addr; sa->sin_family = AF_INET; sa->sin_len = sizeof(*sa); diff --git a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c index c0f61c7..03ca28c 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c +++ b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c @@ -77,7 +77,7 @@ ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep, switch (op) { case SNMP_DEPOP_COMMIT: - strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) { syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); return (SNMP_ERR_GENERR); @@ -95,7 +95,7 @@ ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep, ifc->rb |= IFRB_FLAGS; } if (ifc->rb & IFRB_FLAGS) { - strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name)); + strlcpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name)); if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) { syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name); return (SNMP_ERR_GENERR); @@ -116,7 +116,7 @@ ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep, case SNMP_DEPOP_ROLLBACK: if (ifc->rb & IFRB_FLAGS) { - strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); ifr.ifr_flags = ifc->rb_flags; if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) { syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name); diff --git a/contrib/bsnmp/snmp_mibII/snmp_mibII.3 b/contrib/bsnmp/snmp_mibII/snmp_mibII.3 index 36653e6..09a9145 100644 --- a/contrib/bsnmp/snmp_mibII/snmp_mibII.3 +++ b/contrib/bsnmp/snmp_mibII/snmp_mibII.3 @@ -31,7 +31,7 @@ .\" .\" $Begemot: bsnmp/snmp_mibII/snmp_mibII.3,v 1.10 2005/10/04 08:46:52 brandt_h Exp $ .\" -.Dd October 4, 2005 +.Dd January 4, 2017 .Dt SNMP_MIBII 3 .Os .Sh NAME @@ -63,6 +63,8 @@ .Sh LIBRARY .Pq begemotSnmpdModulePath."mibII" = "@MODPATH@snmp_mibII.so" .Sh SYNOPSIS +.In net/if.h +.In net/if_mib.h .In bsnmp/snmpmod.h .In bsnmp/snmp_mibII.h .Ft typedef void diff --git a/contrib/bsnmp/snmp_usm/usm_snmp.c b/contrib/bsnmp/snmp_usm/usm_snmp.c index 6ed639a..a6c7b86 100644 --- a/contrib/bsnmp/snmp_usm/usm_snmp.c +++ b/contrib/bsnmp/snmp_usm/usm_snmp.c @@ -169,8 +169,12 @@ op_usm_users(struct snmp_context *ctx, struct snmp_value *val, val->var.subs[sub - 1] != LEAF_usmUserCloneFrom) return (SNMP_ERR_NOSUCHNAME); + /* + * XXX (ngie): need to investigate the MIB to determine how + * this is possible given some of the transitions below. + */ if (community != COMM_INITIALIZE && - uuser->type == StorageType_readOnly) + uuser != NULL && uuser->type == StorageType_readOnly) return (SNMP_ERR_NOT_WRITEABLE); switch (val->var.subs[sub - 1]) { diff --git a/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt b/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt index 9d99eab..d7f6099 100644 --- a/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt +++ b/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt @@ -54,6 +54,9 @@ begemot MODULE-IDENTITY E-mail: harti@freebsd.org" DESCRIPTION "The root of the Begemot subtree of the fokus tree." + REVISION "200201300000Z" + DESCRIPTION + "Initial revision." ::= { fokus 1 } END diff --git a/contrib/bsnmp/snmpd/FOKUS-MIB.txt b/contrib/bsnmp/snmpd/FOKUS-MIB.txt index d4671e8..f356d14 100644 --- a/contrib/bsnmp/snmpd/FOKUS-MIB.txt +++ b/contrib/bsnmp/snmpd/FOKUS-MIB.txt @@ -52,6 +52,9 @@ fokus MODULE-IDENTITY E-mail: harti@freebsd.org" DESCRIPTION "The root of the Fokus enterprises tree." + REVISION "200202050000Z" + DESCRIPTION + "Initial revision." ::= { enterprises 12325 } END diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c index 2ab8bbd..a2053e8 100644 --- a/contrib/bsnmp/snmpd/main.c +++ b/contrib/bsnmp/snmpd/main.c @@ -1024,154 +1024,6 @@ snmp_input_consume(struct port_input *pi) pi->length -= pi->consumed; } -static void -check_priv_dgram(struct port_input *pi, struct sockcred *cred) -{ - - /* process explicitly sends credentials */ - if (cred) - pi->priv = (cred->sc_euid == 0); - else - pi->priv = 0; -} - -static void -check_priv_stream(struct port_input *pi) -{ - struct xucred ucred; - socklen_t ucredlen; - - /* obtain the accept time credentials */ - ucredlen = sizeof(ucred); - - if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 && - ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION) - pi->priv = (ucred.cr_uid == 0); - else - pi->priv = 0; -} - -/* - * Input from a stream socket. - */ -static int -recv_stream(struct port_input *pi) -{ - struct msghdr msg; - struct iovec iov[1]; - ssize_t len; - - if (pi->buf == NULL) { - /* no buffer yet - allocate one */ - if ((pi->buf = buf_alloc(0)) == NULL) { - /* ups - could not get buffer. Return an error - * the caller must close the transport. */ - return (-1); - } - pi->buflen = buf_size(0); - pi->consumed = 0; - pi->length = 0; - } - - /* try to get a message */ - msg.msg_name = pi->peer; - msg.msg_namelen = pi->peerlen; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - iov[0].iov_base = pi->buf + pi->length; - iov[0].iov_len = pi->buflen - pi->length; - - len = recvmsg(pi->fd, &msg, 0); - - if (len == -1 || len == 0) - /* receive error */ - return (-1); - - pi->length += len; - - if (pi->cred) - check_priv_stream(pi); - - return (0); -} - -/* - * Input from a datagram socket. - * Each receive should return one datagram. - */ -static int -recv_dgram(struct port_input *pi, struct in_addr *laddr) -{ - u_char embuf[1000]; - char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + - CMSG_SPACE(sizeof(struct in_addr))]; - struct msghdr msg; - struct iovec iov[1]; - ssize_t len; - struct cmsghdr *cmsg; - struct sockcred *cred = NULL; - - if (pi->buf == NULL) { - /* no buffer yet - allocate one */ - if ((pi->buf = buf_alloc(0)) == NULL) { - /* ups - could not get buffer. Read away input - * and drop it */ - (void)recvfrom(pi->fd, embuf, sizeof(embuf), - 0, NULL, NULL); - /* return error */ - return (-1); - } - pi->buflen = buf_size(0); - } - - /* try to get a message */ - msg.msg_name = pi->peer; - msg.msg_namelen = pi->peerlen; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - memset(cbuf, 0, sizeof(cbuf)); - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); - msg.msg_flags = 0; - - iov[0].iov_base = pi->buf; - iov[0].iov_len = pi->buflen; - - len = recvmsg(pi->fd, &msg, 0); - - if (len == -1 || len == 0) - /* receive error */ - return (-1); - - if (msg.msg_flags & MSG_TRUNC) { - /* truncated - drop */ - snmpd_stats.silentDrops++; - snmpd_stats.inTooLong++; - return (-1); - } - - pi->length = (size_t)len; - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == IPPROTO_IP && - cmsg->cmsg_type == IP_RECVDSTADDR) - memcpy(laddr, CMSG_DATA(cmsg), sizeof(struct in_addr)); - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDS) - cred = (struct sockcred *)CMSG_DATA(cmsg); - } - - if (pi->cred) - check_priv_dgram(pi, cred); - - return (0); -} - /* * Input from a socket */ @@ -1183,43 +1035,13 @@ snmpd_input(struct port_input *pi, struct tport *tport) struct snmp_pdu pdu; enum snmpd_input_err ierr, ferr; enum snmpd_proxy_err perr; + ssize_t ret, slen; int32_t vi; - int ret; - ssize_t slen; #ifdef USE_TCPWRAPPERS char client[16]; #endif - struct msghdr msg; - struct iovec iov[1]; - char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; - struct cmsghdr *cmsgp; - - /* get input depending on the transport */ - if (pi->stream) { - msg.msg_control = NULL; - msg.msg_controllen = 0; - - ret = recv_stream(pi); - } else { - struct in_addr *laddr; - - memset(cbuf, 0, CMSG_SPACE(sizeof(struct in_addr))); - msg.msg_control = cbuf; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); - cmsgp = CMSG_FIRSTHDR(&msg); - cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); - cmsgp->cmsg_level = IPPROTO_IP; - cmsgp->cmsg_type = IP_SENDSRCADDR; - laddr = (struct in_addr *)CMSG_DATA(cmsgp); - - ret = recv_dgram(pi, laddr); - - if (laddr->s_addr == 0) { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } - } + ret = tport->transport->vtab->recv(tport, pi); if (ret == -1) return (-1); @@ -1362,21 +1184,15 @@ snmpd_input(struct port_input *pi, struct tport *tport) sndbuf, &sndlen, "SNMP", ierr, vi, NULL); if (ferr == SNMPD_INPUT_OK) { - msg.msg_name = pi->peer; - msg.msg_namelen = pi->peerlen; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - iov[0].iov_base = sndbuf; - iov[0].iov_len = sndlen; - - slen = sendmsg(pi->fd, &msg, 0); + slen = tport->transport->vtab->send(tport, sndbuf, sndlen, + pi->peer, pi->peerlen); if (slen == -1) - syslog(LOG_ERR, "sendmsg: %m"); + syslog(LOG_ERR, "send*: %m"); else if ((size_t)slen != sndlen) - syslog(LOG_ERR, "sendmsg: short write %zu/%zu", - sndlen, (size_t)slen); + syslog(LOG_ERR, "send*: short write %zu/%zu", sndlen, + (size_t)slen); } + snmp_pdu_free(&pdu); free(sndbuf); snmp_input_consume(pi); @@ -2508,13 +2324,12 @@ lm_load(const char *path, const char *section) } m->handle = NULL; m->flags = 0; - strcpy(m->section, section); + strlcpy(m->section, section, sizeof(m->section)); - if ((m->path = malloc(strlen(path) + 1)) == NULL) { + if ((m->path = strdup(path)) == NULL) { syslog(LOG_ERR, "lm_load: %m"); goto err; } - strcpy(m->path, path); /* * Make index diff --git a/contrib/bsnmp/snmpd/snmpd.h b/contrib/bsnmp/snmpd/snmpd.h index 009b2e7..6afbc96 100644 --- a/contrib/bsnmp/snmpd/snmpd.h +++ b/contrib/bsnmp/snmpd/snmpd.h @@ -193,6 +193,7 @@ struct transport_def { ssize_t (*send)(struct tport *, const u_char *, size_t, const struct sockaddr *, size_t); + ssize_t (*recv)(struct tport *, struct port_input *); }; struct transport { struct asn_oid index; /* transport table index */ diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c index 6c168ac..a390839 100644 --- a/contrib/bsnmp/snmpd/trans_lsock.c +++ b/contrib/bsnmp/snmpd/trans_lsock.c @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/queue.h> #include <sys/stat.h> +#include <sys/ucred.h> #include <sys/un.h> #include <errno.h> @@ -58,6 +59,7 @@ static void lsock_close_port(struct tport *); static int lsock_init_port(struct tport *); static ssize_t lsock_send(struct tport *, const u_char *, size_t, const struct sockaddr *, size_t); +static ssize_t lsock_recv(struct tport *, struct port_input *); /* exported */ const struct transport_def lsock_trans = { @@ -67,7 +69,8 @@ const struct transport_def lsock_trans = { lsock_stop, lsock_close_port, lsock_init_port, - lsock_send + lsock_send, + lsock_recv }; static struct transport *my_trans; @@ -302,10 +305,9 @@ lsock_init_port(struct tport *tp) return (SNMP_ERR_RES_UNAVAIL); } - strcpy(sa.sun_path, p->name); + strlcpy(sa.sun_path, p->name, sizeof(sa.sun_path)); sa.sun_family = AF_LOCAL; - sa.sun_len = strlen(p->name) + - offsetof(struct sockaddr_un, sun_path); + sa.sun_len = SUN_LEN(&sa); (void)remove(p->name); @@ -357,10 +359,9 @@ lsock_init_port(struct tport *tp) return (SNMP_ERR_GENERR); } - strcpy(sa.sun_path, p->name); + strlcpy(sa.sun_path, p->name, sizeof(sa.sun_path)); sa.sun_family = AF_LOCAL; - sa.sun_len = strlen(p->name) + - offsetof(struct sockaddr_un, sun_path); + sa.sun_len = SUN_LEN(&sa); (void)remove(p->name); @@ -418,6 +419,73 @@ lsock_send(struct tport *tp, const u_char *buf, size_t len, return (sendto(peer->input.fd, buf, len, 0, addr, addrlen)); } +static void +check_priv_stream(struct port_input *pi) +{ + struct xucred ucred; + socklen_t ucredlen; + + /* obtain the accept time credentials */ + ucredlen = sizeof(ucred); + + if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 && + ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION) + pi->priv = (ucred.cr_uid == 0); + else + pi->priv = 0; +} + +/* + * Receive something + */ +static ssize_t +lsock_recv(struct tport *tp __unused, struct port_input *pi) +{ + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + + if (pi->buf == NULL) { + /* no buffer yet - allocate one */ + if ((pi->buf = buf_alloc(0)) == NULL) { + /* ups - could not get buffer. Return an error + * the caller must close the transport. */ + return (-1); + } + pi->buflen = buf_size(0); + pi->consumed = 0; + pi->length = 0; + } + + /* try to get a message */ + msg.msg_name = pi->peer; + msg.msg_namelen = pi->peerlen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + iov[0].iov_base = pi->buf + pi->length; + iov[0].iov_len = pi->buflen - pi->length; + + len = recvmsg(pi->fd, &msg, 0); + + if (len == -1 || len == 0) + /* receive error */ + return (-1); + + pi->length += len; + + if (pi->cred) + check_priv_stream(pi); + + return (0); +} + /* * Dependency to create a lsock port */ diff --git a/contrib/bsnmp/snmpd/trans_udp.c b/contrib/bsnmp/snmpd/trans_udp.c index a41d3f0..5c9a7fd 100644 --- a/contrib/bsnmp/snmpd/trans_udp.c +++ b/contrib/bsnmp/snmpd/trans_udp.c @@ -32,7 +32,9 @@ */ #include <sys/types.h> #include <sys/queue.h> +#include <sys/ucred.h> +#include <stdbool.h> #include <stdlib.h> #include <syslog.h> #include <string.h> @@ -54,6 +56,7 @@ static void udp_close_port(struct tport *); static int udp_init_port(struct tport *); static ssize_t udp_send(struct tport *, const u_char *, size_t, const struct sockaddr *, size_t); +static ssize_t udp_recv(struct tport *, struct port_input *); /* exported */ const struct transport_def udp_trans = { @@ -63,7 +66,8 @@ const struct transport_def udp_trans = { udp_stop, udp_close_port, udp_init_port, - udp_send + udp_send, + udp_recv }; static struct transport *my_trans; @@ -116,13 +120,15 @@ udp_init_port(struct tport *tp) addr.sin_port = htons(p->port); addr.sin_family = AF_INET; addr.sin_len = sizeof(addr); - if (addr.sin_addr.s_addr == INADDR_ANY && - setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, - sizeof(on)) == -1) { - syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); - close(p->input.fd); - p->input.fd = -1; - return (SNMP_ERR_GENERR); + if (addr.sin_addr.s_addr == INADDR_ANY) { + if (setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, + sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + p->recvdstaddr = true; } if (bind(p->input.fd, (struct sockaddr *)&addr, sizeof(addr))) { if (errno == EADDRNOTAVAIL) { @@ -214,8 +220,121 @@ udp_send(struct tport *tp, const u_char *buf, size_t len, const struct sockaddr *addr, size_t addrlen) { struct udp_port *p = (struct udp_port *)tp; + struct cmsghdr *cmsg; + struct msghdr msg; + char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; + struct iovec iov; + + iov.iov_base = __DECONST(void*, buf); + iov.iov_len = len; + + msg.msg_flags = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = __DECONST(void *, addr); + msg.msg_namelen = addrlen; + + if (p->recvdstaddr) { + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + memcpy(CMSG_DATA(cmsg), &p->dstaddr, sizeof(struct in_addr)); + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + return (sendmsg(p->input.fd, &msg, 0)); +} + +static void +check_priv_dgram(struct port_input *pi, struct sockcred *cred) +{ + + /* process explicitly sends credentials */ + if (cred) + pi->priv = (cred->sc_euid == 0); + else + pi->priv = 0; +} + +/* + * Input from a datagram socket. + * Each receive should return one datagram. + */ +static ssize_t +udp_recv(struct tport *tp, struct port_input *pi) +{ + u_char embuf[1000]; + char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + + CMSG_SPACE(sizeof(struct in_addr))]; + struct udp_port *p = (struct udp_port *)tp; + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + struct cmsghdr *cmsg; + struct sockcred *cred = NULL; + + if (pi->buf == NULL) { + /* no buffer yet - allocate one */ + if ((pi->buf = buf_alloc(0)) == NULL) { + /* ups - could not get buffer. Read away input + * and drop it */ + (void)recvfrom(pi->fd, embuf, sizeof(embuf), + 0, NULL, NULL); + /* return error */ + return (-1); + } + pi->buflen = buf_size(0); + } + + /* try to get a message */ + msg.msg_name = pi->peer; + msg.msg_namelen = pi->peerlen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + memset(cbuf, 0, sizeof(cbuf)); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + msg.msg_flags = 0; + + iov[0].iov_base = pi->buf; + iov[0].iov_len = pi->buflen; + + len = recvmsg(pi->fd, &msg, 0); + + if (len == -1 || len == 0) + /* receive error */ + return (-1); + + if (msg.msg_flags & MSG_TRUNC) { + /* truncated - drop */ + snmpd_stats.silentDrops++; + snmpd_stats.inTooLong++; + return (-1); + } + + pi->length = (size_t)len; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTADDR) + memcpy(&p->dstaddr, CMSG_DATA(cmsg), + sizeof(struct in_addr)); + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDS) + cred = (struct sockcred *)CMSG_DATA(cmsg); + } + + if (pi->cred) + check_priv_dgram(pi, cred); - return (sendto(p->input.fd, buf, len, 0, addr, addrlen)); + return (0); } /* diff --git a/contrib/bsnmp/snmpd/trans_udp.h b/contrib/bsnmp/snmpd/trans_udp.h index d383711..2f50e2a 100644 --- a/contrib/bsnmp/snmpd/trans_udp.h +++ b/contrib/bsnmp/snmpd/trans_udp.h @@ -39,6 +39,9 @@ struct udp_port { struct port_input input; /* common input stuff */ struct sockaddr_in ret; /* the return address */ + + bool recvdstaddr; /* IP_RECVDSTADDR is on */ + struct in_addr dstaddr; /* address the request was sent to */ }; /* argument for open call */ |