Date: Wed, 28 Dec 2016 04:29:10 +0000 (UTC) From: Ngie Cooper <ngie@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r310655 - head/contrib/bsnmp/snmpd Message-ID: <201612280429.uBS4TA1W085321@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ngie Date: Wed Dec 28 04:29:09 2016 New Revision: 310655 URL: https://svnweb.freebsd.org/changeset/base/310655 Log: Fix bsnmpd sending/receiving with multi-homed configurations or INADDR_ANY used as the listening address in snmpd_input(..) Stash the IPv4 address of the receiver via the recv(..) callback and use it in the send(..) callback for the transport by specifying IP_SENDSRCADDR for the control message type. Add sendmsg logic to the UDP transport's send(..) callback and use the respective send(..) callback for the transport instead of calling sendto in snmpd_input(..). MFC after: 3 weeks Obtained from: Isilon OneFS (^/onefs/branches/BR_8_0_0_DEV@r507595) Submitted by: Thor Steingrimsson <thor.steingrimsson@isilon.com> Sponsored by: Dell EMC Isilon Modified: head/contrib/bsnmp/snmpd/main.c head/contrib/bsnmp/snmpd/snmpd.h head/contrib/bsnmp/snmpd/trans_lsock.c head/contrib/bsnmp/snmpd/trans_udp.c head/contrib/bsnmp/snmpd/trans_udp.h Modified: head/contrib/bsnmp/snmpd/main.c ============================================================================== --- head/contrib/bsnmp/snmpd/main.c Wed Dec 28 03:56:25 2016 (r310654) +++ head/contrib/bsnmp/snmpd/main.c Wed Dec 28 04:29:09 2016 (r310655) @@ -1040,10 +1040,8 @@ snmpd_input(struct port_input *pi, struc #ifdef USE_TCPWRAPPERS char client[16]; #endif - struct msghdr msg; - struct iovec iov[1]; - ret = tport->transport->vtab->recv(pi); + ret = tport->transport->vtab->recv(tport, pi); if (ret == -1) return (-1); @@ -1186,21 +1184,15 @@ snmpd_input(struct port_input *pi, struc 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); Modified: head/contrib/bsnmp/snmpd/snmpd.h ============================================================================== --- head/contrib/bsnmp/snmpd/snmpd.h Wed Dec 28 03:56:25 2016 (r310654) +++ head/contrib/bsnmp/snmpd/snmpd.h Wed Dec 28 04:29:09 2016 (r310655) @@ -193,7 +193,7 @@ struct transport_def { ssize_t (*send)(struct tport *, const u_char *, size_t, const struct sockaddr *, size_t); - ssize_t (*recv)(struct port_input *); + ssize_t (*recv)(struct tport *, struct port_input *); }; struct transport { struct asn_oid index; /* transport table index */ Modified: head/contrib/bsnmp/snmpd/trans_lsock.c ============================================================================== --- head/contrib/bsnmp/snmpd/trans_lsock.c Wed Dec 28 03:56:25 2016 (r310654) +++ head/contrib/bsnmp/snmpd/trans_lsock.c Wed Dec 28 04:29:09 2016 (r310655) @@ -59,7 +59,7 @@ static void lsock_close_port(struct tpor 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 port_input *); +static ssize_t lsock_recv(struct tport *, struct port_input *); /* exported */ const struct transport_def lsock_trans = { @@ -444,7 +444,7 @@ check_priv_stream(struct port_input *pi) * Receive something */ static ssize_t -lsock_recv(struct port_input *pi) +lsock_recv(struct tport *tp __unused, struct port_input *pi) { struct msghdr msg; struct iovec iov[1]; Modified: head/contrib/bsnmp/snmpd/trans_udp.c ============================================================================== --- head/contrib/bsnmp/snmpd/trans_udp.c Wed Dec 28 03:56:25 2016 (r310654) +++ head/contrib/bsnmp/snmpd/trans_udp.c Wed Dec 28 04:29:09 2016 (r310655) @@ -55,7 +55,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 port_input *); +static ssize_t udp_recv(struct tport *, struct port_input *); /* exported */ const struct transport_def udp_trans = { @@ -217,8 +217,30 @@ udp_send(struct tport *tp, const u_char const struct sockaddr *addr, size_t addrlen) { struct udp_port *p = (struct udp_port *)tp; + struct cmsghdr *cmsg; + struct in_addr *src_addr; + struct msghdr msg; + char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; + struct iovec iov; - return (sendto(p->input.fd, buf, len, 0, addr, addrlen)); + iov.iov_base = __DECONST(void*, buf); + iov.iov_len = len; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = __DECONST(void *, addr); + msg.msg_namelen = addrlen; + 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)); + src_addr = (struct in_addr *)(void*)CMSG_DATA(cmsg); + memcpy(src_addr, &p->recv_addr, sizeof(struct in_addr)); + + return (sendmsg(p->input.fd, &msg, 0)); } static void @@ -309,8 +331,9 @@ recv_dgram(struct port_input *pi, struct * Receive something */ static ssize_t -udp_recv(struct port_input *pi) +udp_recv(struct tport *tp, struct port_input *pi) { + struct udp_port *p = (struct udp_port *)tp; struct in_addr *laddr; struct msghdr msg; char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; @@ -330,6 +353,8 @@ udp_recv(struct port_input *pi) ret = recv_dgram(pi, laddr); + memcpy(&p->recv_addr, laddr, sizeof(struct in_addr)); + if (laddr->s_addr == INADDR_ANY) { msg.msg_control = NULL; msg.msg_controllen = 0; Modified: head/contrib/bsnmp/snmpd/trans_udp.h ============================================================================== --- head/contrib/bsnmp/snmpd/trans_udp.h Wed Dec 28 03:56:25 2016 (r310654) +++ head/contrib/bsnmp/snmpd/trans_udp.h Wed Dec 28 04:29:09 2016 (r310655) @@ -39,6 +39,7 @@ struct udp_port { struct port_input input; /* common input stuff */ struct sockaddr_in ret; /* the return address */ + struct in_addr recv_addr; /* the address the request was sent to */ }; /* argument for open call */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612280429.uBS4TA1W085321>