diff --git a/contrib/bsnmp/FREEBSD-upgrade b/contrib/bsnmp/FREEBSD-upgrade index fff2784c39e5..71e220e3c662 100644 --- a/contrib/bsnmp/FREEBSD-upgrade +++ b/contrib/bsnmp/FREEBSD-upgrade @@ -8,8 +8,9 @@ environments besides FreeBSD. Import should be done by: 1. unpack distribution into clean directory + tar xvf bsnmp-X.Y.tar.gz --exclude-from=FREEBSD-Xlist - 2. remove all unneeded files + 2. remove all unneeded new files (and update FREEBSD-Xlist) 3. cvs import \ -m "Virgin import of bsnmpd X.Y" \ diff --git a/contrib/bsnmp/NEWS b/contrib/bsnmp/NEWS index 3d0ca120fa09..01281ecdb481 100644 --- a/contrib/bsnmp/NEWS +++ b/contrib/bsnmp/NEWS @@ -1,3 +1,24 @@ +09-Dec-2003 + First step on factoring out the transport mapping stuff into + loadable modules. + + Local stream sockets that check the clients privileges. + +03-Dec-2003 + Bump version to 1.5 but leave library version intact. + +03-Dec-2003 + Now works with libbegemot polling stuff instead of libisc. + Use --with-libbegemot[=path] to configure. + +03-Dec-2003 + Fix parsing of non-minimal ASN.1 integers. They are now disallowed. + Non-minimal lengths are allowed. + + Remove copyright clause 3 everywhere. + + Make an autoconf build infrastructure. + 08-Nov-2003 WARNS=6 fixed. diff --git a/contrib/bsnmp/README b/contrib/bsnmp/README index 85ab2edfb724..25d09263fce0 100644 --- a/contrib/bsnmp/README +++ b/contrib/bsnmp/README @@ -1,4 +1,4 @@ -Mon Nov 10 09:50:22 CET 2003 +Fri Dec 5 15:01:16 CET 2003 This is a mini-SNMP daemon. The basic daemon implements the system group and a number of private extensions to manage the UDP transport mapping, @@ -13,16 +13,16 @@ One basic loadable module is provided together with the daemon: Installation ------------ -You need to apply the patch in the patches directory to your system sources. -This adds a sysctl to retrieve multicast address information from the kernel. - As usual by doing: - make obj ; make depend ; make ; make install + configure [--with-libbegemot[=path]] + make + make install This does not install a configuration file. The standard location for the configuration is /etc/snmpd.config, but can be overwritten on the command -line. An example configuration file is provided. +line. An example configuration file is provided. Use --with-libbegemot +to use libbegemot instead of libisc. Running ------- diff --git a/contrib/bsnmp/TODO b/contrib/bsnmp/TODO index 5b3054431ef3..732c82c06296 100644 --- a/contrib/bsnmp/TODO +++ b/contrib/bsnmp/TODO @@ -1,5 +1,17 @@ snmpd_mibII: - handle HC counters by periodically polling the kernel counters. -snmpd_netgraph: - - make some tables writeable +snmpd: + - rethink transports a little bit: make them loadable and make + a private subtree for transports: + OK. Table not writeable yet. + + There should be a transport table that is indexed by the transport name. + This table can be used to load/unload transports at run time. + OK. Table not writeable yet. + + Then there can be a port table that is indexed by transport name and + port name. Plus a transport-specific table indexed by port name only. + + The transport table could contain a column of type OID that points + to the transport-specific table. diff --git a/contrib/bsnmp/VERSION b/contrib/bsnmp/VERSION index c068b2447cc2..941c59621300 100644 --- a/contrib/bsnmp/VERSION +++ b/contrib/bsnmp/VERSION @@ -1 +1 @@ -1.4 +1.5a diff --git a/contrib/bsnmp/gensnmptree/gensnmptree.1 b/contrib/bsnmp/gensnmptree/gensnmptree.1 index 2970355df2bf..9704debb0dd6 100644 --- a/contrib/bsnmp/gensnmptree/gensnmptree.1 +++ b/contrib/bsnmp/gensnmptree/gensnmptree.1 @@ -28,7 +28,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/gensnmptree/gensnmptree.1,v 1.1 2002/08/15 13:27:44 hbb Exp $ +.\" $Begemot: bsnmp/gensnmptree/gensnmptree.1,v 1.2 2003/12/03 09:56:57 hbb Exp $ .\" .\" Author: Harti Brandt .\" diff --git a/contrib/bsnmp/gensnmptree/gensnmptree.c b/contrib/bsnmp/gensnmptree/gensnmptree.c index 5c400e3d7a74..981614483262 100644 --- a/contrib/bsnmp/gensnmptree/gensnmptree.c +++ b/contrib/bsnmp/gensnmptree/gensnmptree.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.34 2003/01/28 13:44:34 hbb Exp $ + * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.36 2003/12/03 09:56:57 hbb Exp $ * * Generate OID table from table description. * diff --git a/contrib/bsnmp/lib/asn1.3 b/contrib/bsnmp/lib/asn1.3 index 3751e50cdb1c..ec01b9a01d90 100644 --- a/contrib/bsnmp/lib/asn1.3 +++ b/contrib/bsnmp/lib/asn1.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/lib/asn1.3,v 1.2 2002/08/16 10:02:53 hbb Exp $ +.\" $Begemot: bsnmp/lib/asn1.3,v 1.3 2003/12/02 15:45:48 hbb Exp $ .\" .Dd August 15, 2002 .Dt asn1 3 diff --git a/contrib/bsnmp/lib/asn1.c b/contrib/bsnmp/lib/asn1.c index 533b9dd6bce6..75d5300639d2 100644 --- a/contrib/bsnmp/lib/asn1.c +++ b/contrib/bsnmp/lib/asn1.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/asn1.c,v 1.24 2003/01/28 13:44:34 hbb Exp $ + * $Begemot: bsnmp/lib/asn1.c,v 1.27 2003/12/08 17:11:58 hbb Exp $ * * ASN.1 for SNMP. */ @@ -244,6 +244,13 @@ asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp) err = ASN_ERR_OK; if (len > 8) err = ASN_ERR_RANGE; + else if (len > 1 && + ((*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) || + (*b->asn_cptr == 0xff && (b->asn_cptr[1] & 0x80) == 0x80))) { + asn_error(b, "non-minimal integer"); + err = ASN_ERR_BADLEN; + } + if (*b->asn_cptr & 0x80) neg = 1; val = 0; @@ -332,6 +339,10 @@ asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, u_int64_t *vp) /* negative integer or too larger */ *vp = 0xffffffffffffffffULL; err = ASN_ERR_RANGE; + } else if (len > 1 && + *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) { + asn_error(b, "non-minimal unsigned"); + err = ASN_ERR_BADLEN; } while (len--) { @@ -718,7 +729,6 @@ asn_get_sequence(struct asn_buf *b, asn_len_t *len) return (ASN_ERR_OK); } - /* * Application types * diff --git a/contrib/bsnmp/lib/asn1.h b/contrib/bsnmp/lib/asn1.h index 83a31e530594..0c21fe491026 100644 --- a/contrib/bsnmp/lib/asn1.h +++ b/contrib/bsnmp/lib/asn1.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/asn1.h,v 1.16 2002/02/11 10:19:57 hbb Exp $ + * $Begemot: bsnmp/lib/asn1.h,v 1.17 2003/12/02 15:52:37 hbb Exp $ * * ASN.1 for SNMP */ diff --git a/contrib/bsnmp/lib/bsnmpagent.3 b/contrib/bsnmp/lib/bsnmpagent.3 index a9a8104013cb..ad2f62838d2c 100644 --- a/contrib/bsnmp/lib/bsnmpagent.3 +++ b/contrib/bsnmp/lib/bsnmpagent.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/lib/bsnmpagent.3,v 1.1 2002/08/16 12:22:58 hbb Exp $ +.\" $Begemot: bsnmp/lib/bsnmpagent.3,v 1.2 2003/12/02 16:13:45 hbb Exp $ .\" .Dd August 16, 2002 .Dt bsnmpagent 3 diff --git a/contrib/bsnmp/lib/bsnmpclient.3 b/contrib/bsnmp/lib/bsnmpclient.3 index f4a7eac62a7f..a4996c4a9430 100644 --- a/contrib/bsnmp/lib/bsnmpclient.3 +++ b/contrib/bsnmp/lib/bsnmpclient.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.3 2002/12/11 15:54:07 hbb Exp $ +.\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.5 2003/12/08 17:11:58 hbb Exp $ .\" .Dd August 15, 2002 .Dt bsnmpclient 3 @@ -107,7 +107,7 @@ that use SNMP versions 1 or 2. Most of the routines use a .Bd -literal -offset indent struct snmp_client { enum snmp_version version; - int local; /* use local socket */ + int trans; /* transport type to use */ /* these two are read-only for the application */ char *cport; /* port number as string */ @@ -147,13 +147,19 @@ This is the version of SNMP to use. See .Xr bsnmplib 3 for applicable values. The default version is .Li SNMP_V2c . -.It Va local -If this is set to true, the library opens a -.Ux -domain socket rather than -an UDP socket. It uses the +.It Va trans +If this is +.Dv SNMP_TRANS_LOC_DGRAM +a local datagram socket is used. +If it is +.Dv SNMP_TRANS_LOC_STREAM +a local stream socket is used. +For +.Dv SNMP_TRANS_UDP +a UDP socket is created. +It uses the .Va chost -field as the path to the server's socket. +field as the path to the server's socket for local sockets. .It Va cport The SNMP agent's UDP port number. This may be a symbolic port number (from .Pa /etc/services diff --git a/contrib/bsnmp/lib/bsnmplib.3 b/contrib/bsnmp/lib/bsnmplib.3 index 13f96516ad96..8f7fcb435d21 100644 --- a/contrib/bsnmp/lib/bsnmplib.3 +++ b/contrib/bsnmp/lib/bsnmplib.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/lib/bsnmplib.3,v 1.2 2002/08/16 10:02:53 hbb Exp $ +.\" $Begemot: bsnmp/lib/bsnmplib.3,v 1.3 2003/12/02 16:14:28 hbb Exp $ .\" .Dd August 15, 2002 .Dt bsnmplib 3 diff --git a/contrib/bsnmp/lib/snmp.c b/contrib/bsnmp/lib/snmp.c index 786bf8cd4048..3369dd32383b 100644 --- a/contrib/bsnmp/lib/snmp.c +++ b/contrib/bsnmp/lib/snmp.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmp.c,v 1.34 2003/01/28 13:44:34 hbb Exp $ + * $Begemot: bsnmp/lib/snmp.c,v 1.37 2003/12/08 17:11:58 hbb Exp $ * * SNMP */ @@ -431,6 +431,64 @@ snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) return (SNMP_CODE_OK); } +/* + * Check whether what we have is the complete PDU by snooping at the + * enclosing structure header. This returns: + * -1 if there are ASN.1 errors + * 0 if we need more data + * > 0 the length of this PDU + */ +int +snmp_pdu_snoop(const struct asn_buf *b0) +{ + u_int length; + asn_len_t len; + struct asn_buf b = *b0; + + /* <0x10|0x20> */ + + if (b.asn_len == 0) + return (0); + if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { + asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); + return (-1); + } + b.asn_len--; + b.asn_cptr++; + + if (b.asn_len == 0) + return (0); + + if (*b.asn_cptr & 0x80) { + /* long length */ + length = *b.asn_cptr++ & 0x7f; + b.asn_len--; + if (length == 0) { + asn_error(&b, "indefinite length not supported"); + return (-1); + } + if (length > ASN_MAXLENLEN) { + asn_error(&b, "long length too long (%u)", length); + return (-1); + } + if (length > b.asn_len) + return (0); + len = 0; + while (length--) { + len = (len << 8) | *b.asn_cptr++; + b.asn_len--; + } + } else { + len = *b.asn_cptr++; + b.asn_len--; + } + + if (len > b.asn_len) + return (0); + + return (len + b.asn_cptr - b0->asn_cptr); +} + /* * Encode the SNMP PDU without the variable bindings field. * We do this the rather uneffective way by diff --git a/contrib/bsnmp/lib/snmp.h b/contrib/bsnmp/lib/snmp.h index 30b1e2c8b6cf..86a36e7a270b 100644 --- a/contrib/bsnmp/lib/snmp.h +++ b/contrib/bsnmp/lib/snmp.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmp.h,v 1.27 2002/03/08 14:24:58 hbb Exp $ + * $Begemot: bsnmp/lib/snmp.h,v 1.29 2003/12/08 17:11:58 hbb Exp $ * * Header file for SNMP functions. */ @@ -164,6 +164,8 @@ void snmp_pdu_free(struct snmp_pdu *); enum snmp_code snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *); enum snmp_code snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b); +int snmp_pdu_snoop(const struct asn_buf *); + void snmp_pdu_dump(const struct snmp_pdu *pdu); extern void (*snmp_error)(const char *, ...); diff --git a/contrib/bsnmp/lib/snmpagent.c b/contrib/bsnmp/lib/snmpagent.c index 19ac661a2f54..c03b606f4262 100644 --- a/contrib/bsnmp/lib/snmpagent.c +++ b/contrib/bsnmp/lib/snmpagent.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmpagent.c,v 1.14 2003/01/30 11:23:00 hbb Exp $ + * $Begemot: bsnmp/lib/snmpagent.c,v 1.16 2003/12/03 09:55:58 hbb Exp $ * * SNMP Agent functions */ diff --git a/contrib/bsnmp/lib/snmpagent.h b/contrib/bsnmp/lib/snmpagent.h index a854138981c0..cd89456329aa 100644 --- a/contrib/bsnmp/lib/snmpagent.h +++ b/contrib/bsnmp/lib/snmpagent.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmpagent.h,v 1.9 2002/03/08 14:24:58 hbb Exp $ + * $Begemot: bsnmp/lib/snmpagent.h,v 1.10 2003/12/03 09:55:58 hbb Exp $ * * Header file for SNMP functions. This requires snmp.h to be included. */ diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c index e1206b06d2f8..ce3b2c07167c 100644 --- a/contrib/bsnmp/lib/snmpclient.c +++ b/contrib/bsnmp/lib/snmpclient.c @@ -31,7 +31,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmpclient.c,v 1.24 2003/01/28 13:44:34 hbb Exp $ + * $Begemot: bsnmp/lib/snmpclient.c,v 1.27 2003/12/08 17:11:58 hbb Exp $ * * Support functions for SNMP clients. */ @@ -826,7 +826,7 @@ snmp_client_init(struct snmp_client *c) memset(c, 0, sizeof(*c)); c->version = SNMP_V2c; - c->local = 0; + c->trans = SNMP_TRANS_UDP; c->chost = NULL; c->cport = NULL; @@ -941,6 +941,7 @@ open_client_local(const char *path) { struct sockaddr_un sa; char *ptr; + int stype; if (snmp_client.chost == NULL) { if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_LOCAL))) @@ -960,7 +961,12 @@ open_client_local(const char *path) strcpy(snmp_client.chost, path); } - if ((snmp_client.fd = socket(PF_LOCAL, SOCK_DGRAM, 0)) == -1) { + if (snmp_client.trans == SNMP_TRANS_LOC_DGRAM) + stype = SOCK_DGRAM; + else + stype = SOCK_STREAM; + + if ((snmp_client.fd = socket(PF_LOCAL, stype, 0)) == -1) { seterr("%s", strerror(errno)); return (-1); } @@ -1028,12 +1034,22 @@ snmp_open(const char *host, const char *port, const char *readcomm, strlcpy(snmp_client.write_community, writecomm, sizeof(snmp_client.write_community)); - if (!snmp_client.local) { + switch (snmp_client.trans) { + + case SNMP_TRANS_UDP: if (open_client_udp(host, port)) return (-1); - } else { + break; + + case SNMP_TRANS_LOC_DGRAM: + case SNMP_TRANS_LOC_STREAM: if (open_client_local(host)) return (-1); + break; + + default: + seterr("bad transport mapping"); + return (-1); } tout.tv_sec = 0; tout.tv_usec = 0; @@ -1042,7 +1058,7 @@ snmp_open(const char *host, const char *port, const char *readcomm, seterr("%s", strerror(errno)); (void)close(snmp_client.fd); snmp_client.fd = -1; - if (snmp_client.local) + if (snmp_client.local_path[0] != '\0') (void)remove(snmp_client.local_path); return (-1); } @@ -1075,7 +1091,7 @@ snmp_close(void) if (snmp_client.fd != -1) { (void)close(snmp_client.fd); snmp_client.fd = -1; - if (snmp_client.local) + if (snmp_client.local_path[0] != '\0') (void)remove(snmp_client.local_path); } while(!LIST_EMPTY(&sent_pdus)){ diff --git a/contrib/bsnmp/lib/snmpclient.h b/contrib/bsnmp/lib/snmpclient.h index 700d020700e8..80acb1481a4e 100644 --- a/contrib/bsnmp/lib/snmpclient.h +++ b/contrib/bsnmp/lib/snmpclient.h @@ -31,7 +31,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmpclient.h,v 1.15 2002/12/11 15:54:07 hbb Exp $ + * $Begemot: bsnmp/lib/snmpclient.h,v 1.17 2003/12/08 17:11:58 hbb Exp $ */ #ifndef _BSNMP_SNMPCLIENT_H #define _BSNMP_SNMPCLIENT_H @@ -47,6 +47,12 @@ #define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX" +/* + * transport methods + */ +#define SNMP_TRANS_UDP 0 +#define SNMP_TRANS_LOC_DGRAM 1 +#define SNMP_TRANS_LOC_STREAM 2 /* type of callback function for responses * this callback function is responsible for free() any memory associated with @@ -68,7 +74,7 @@ typedef void (*snmp_timeout_stop_f)(void *timeout_id); */ struct snmp_client { enum snmp_version version; - int local; /* use local socket */ + int trans; /* which transport to use */ /* these two are read-only for the application */ char *cport; /* port number as string */ diff --git a/contrib/bsnmp/lib/snmppriv.h b/contrib/bsnmp/lib/snmppriv.h index 82189f0c34b4..9fb66aad7f2e 100644 --- a/contrib/bsnmp/lib/snmppriv.h +++ b/contrib/bsnmp/lib/snmppriv.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/lib/snmppriv.h,v 1.7 2002/12/11 15:54:07 hbb Exp $ + * $Begemot: bsnmp/lib/snmppriv.h,v 1.8 2003/12/03 09:55:58 hbb Exp $ * * Private functions. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c index 74817948bd81..ae38b6f95a20 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.c +++ b/contrib/bsnmp/snmp_mibII/mibII.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII.c,v 1.16 2003/01/28 13:44:34 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII.c,v 1.17 2003/12/03 10:01:19 hbb Exp $ * * Implementation of the standard interfaces and ip MIB. */ @@ -978,11 +978,15 @@ mib_fetch_rtab(int af, int info, int arg, size_t *lenp) name[4] = info; name[5] = arg; + *lenp = 0; + if (sysctl(name, 6, 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); } + if (*lenp == 0) + return (NULL); if ((buf = malloc(*lenp)) == NULL) { syslog(LOG_ERR, "sysctl buffer: %m"); diff --git a/contrib/bsnmp/snmp_mibII/mibII.h b/contrib/bsnmp/snmp_mibII/mibII.h index 89ccd05c797f..6e8cd993c764 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.h +++ b/contrib/bsnmp/snmp_mibII/mibII.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII.h,v 1.11 2002/03/21 10:43:06 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII.h,v 1.12 2003/12/03 10:01:19 hbb Exp $ * * Implementation of the interfaces and IP groups of MIB-II. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_ifmib.c b/contrib/bsnmp/snmp_mibII/mibII_ifmib.c index 1f09d59d3f4b..24a57f8f0930 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_ifmib.c +++ b/contrib/bsnmp/snmp_mibII/mibII_ifmib.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_ifmib.c,v 1.7 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_ifmib.c,v 1.8 2003/12/03 10:01:19 hbb Exp $ * * Interfaces group. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_ifstack.c b/contrib/bsnmp/snmp_mibII/mibII_ifstack.c index 93aa259ea645..b19ea4e221e3 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_ifstack.c +++ b/contrib/bsnmp/snmp_mibII/mibII_ifstack.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_ifstack.c,v 1.5 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_ifstack.c,v 1.6 2003/12/03 10:01:19 hbb Exp $ * * ifStackTable. Read-only. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c index 02a90caa36c0..a0023bd0056b 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_interfaces.c +++ b/contrib/bsnmp/snmp_mibII/mibII_interfaces.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.9 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.10 2003/12/03 10:01:19 hbb Exp $ * * Interfaces group. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_ip.c b/contrib/bsnmp/snmp_mibII/mibII_ip.c index d0d25904cd17..8b638e336c8a 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_ip.c +++ b/contrib/bsnmp/snmp_mibII/mibII_ip.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.8 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.9 2003/12/03 10:01:19 hbb Exp $ * * ip group scalars. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_ipaddr.c b/contrib/bsnmp/snmp_mibII/mibII_ipaddr.c index 0cc593663abe..a0050f6c7bec 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_ipaddr.c +++ b/contrib/bsnmp/snmp_mibII/mibII_ipaddr.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.6 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_ipaddr.c,v 1.7 2003/12/03 10:01:19 hbb Exp $ * * IP address table. This table is writeable! * diff --git a/contrib/bsnmp/snmp_mibII/mibII_nettomedia.c b/contrib/bsnmp/snmp_mibII/mibII_nettomedia.c index e8a791994350..bafa6e1cda74 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_nettomedia.c +++ b/contrib/bsnmp/snmp_mibII/mibII_nettomedia.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_nettomedia.c,v 1.6 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_nettomedia.c,v 1.7 2003/12/03 10:01:19 hbb Exp $ * * Read-only implementation of the Arp table (ipNetToMediaTable) * diff --git a/contrib/bsnmp/snmp_mibII/mibII_rcvaddr.c b/contrib/bsnmp/snmp_mibII/mibII_rcvaddr.c index 7226e1019000..e257f17f9496 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_rcvaddr.c +++ b/contrib/bsnmp/snmp_mibII/mibII_rcvaddr.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_rcvaddr.c,v 1.7 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_rcvaddr.c,v 1.8 2003/12/03 10:01:19 hbb Exp $ * * Interface receive address table. */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_route.c b/contrib/bsnmp/snmp_mibII/mibII_route.c index d2683ce6f7a1..e220de9af129 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_route.c +++ b/contrib/bsnmp/snmp_mibII/mibII_route.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_route.c,v 1.3 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_route.c,v 1.4 2003/12/03 10:01:19 hbb Exp $ * * Routing table */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_tcp.c b/contrib/bsnmp/snmp_mibII/mibII_tcp.c index f4509f958078..ec2c5fd06ce6 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_tcp.c +++ b/contrib/bsnmp/snmp_mibII/mibII_tcp.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_tcp.c,v 1.4 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_tcp.c,v 1.5 2003/12/03 10:01:19 hbb Exp $ * * tcp */ diff --git a/contrib/bsnmp/snmp_mibII/mibII_tree.def b/contrib/bsnmp/snmp_mibII/mibII_tree.def index 63842641e1eb..fabc6b524a60 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_tree.def +++ b/contrib/bsnmp/snmp_mibII/mibII_tree.def @@ -30,7 +30,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# $Begemot: bsnmp/snmp_mibII/mibII_tree.def,v 1.10 2002/02/06 12:43:51 hbb Exp $ +# $Begemot: bsnmp/snmp_mibII/mibII_tree.def,v 1.11 2003/12/03 10:01:19 hbb Exp $ # # Definition of the standard interfaces and ip trees. # diff --git a/contrib/bsnmp/snmp_mibII/mibII_udp.c b/contrib/bsnmp/snmp_mibII/mibII_udp.c index 232bc45b4cff..0dde816027cc 100644 --- a/contrib/bsnmp/snmp_mibII/mibII_udp.c +++ b/contrib/bsnmp/snmp_mibII/mibII_udp.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.4 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.5 2003/12/03 10:01:19 hbb Exp $ * * udp */ diff --git a/contrib/bsnmp/snmp_mibII/snmp_mibII.3 b/contrib/bsnmp/snmp_mibII/snmp_mibII.3 index 62b354da0484..1d7018a76bbf 100644 --- a/contrib/bsnmp/snmp_mibII/snmp_mibII.3 +++ b/contrib/bsnmp/snmp_mibII/snmp_mibII.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/snmp_mibII/snmp_mibII.3,v 1.1 2002/08/19 09:30:14 hbb Exp $ +.\" $Begemot: bsnmp/snmp_mibII/snmp_mibII.3,v 1.2 2003/12/03 10:01:19 hbb Exp $ .\" .Dd August 19, 2002 .Dt snmp_mibII 3 diff --git a/contrib/bsnmp/snmp_mibII/snmp_mibII.h b/contrib/bsnmp/snmp_mibII/snmp_mibII.h index 79423cbd4cc5..7efba8635cba 100644 --- a/contrib/bsnmp/snmp_mibII/snmp_mibII.h +++ b/contrib/bsnmp/snmp_mibII/snmp_mibII.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmp_mibII/snmp_mibII.h,v 1.13 2002/03/21 11:18:51 hbb Exp $ + * $Begemot: bsnmp/snmp_mibII/snmp_mibII.h,v 1.14 2003/12/03 10:01:19 hbb Exp $ * * Implementation of the interfaces and IP groups of MIB-II. */ diff --git a/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt b/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt index f2822763777e..73268bb69bb5 100644 --- a/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt +++ b/contrib/bsnmp/snmpd/BEGEMOT-MIB.txt @@ -30,7 +30,7 @@ -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- --- $Begemot: bsnmp/snmpd/BEGEMOT-MIB.txt,v 1.3 2002/02/06 12:43:51 hbb Exp $ +-- $Begemot: bsnmp/snmpd/BEGEMOT-MIB.txt,v 1.4 2003/12/03 10:08:47 hbb Exp $ -- -- Begemot private definitions and root. -- diff --git a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt index 8c0996b11562..76fcbd59c4f0 100644 --- a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt +++ b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt @@ -30,7 +30,7 @@ -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- --- $Begemot: bsnmp/snmpd/BEGEMOT-SNMPD.txt,v 1.18 2002/12/11 15:54:07 hbb Exp $ +-- $Begemot: bsnmp/snmpd/BEGEMOT-SNMPD.txt,v 1.21 2003/12/09 12:28:52 hbb Exp $ -- -- Begemot Private SNMPd MIB. -- @@ -134,6 +134,19 @@ begemotSnmpdTrap1Addr OBJECT-TYPE "The trap sink for v1 traps." ::= { begemotSnmpdConfig 4 } +begemotSnmpdVersionEnable OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The SNMP versions that the agent processes. The following + bits are defined: + + 0x00000001 - SNMPv1 + 0x00000002 - SNMPv2c" + DEFVAL { 0x3 } + ::= { begemotSnmpdConfig 5 } + -- -- Trap destinations -- @@ -423,6 +436,8 @@ begemotSnmpdDebugSnmpTrace OBJECT-TYPE 0x00000004 trace SET operator 0x00000008 trace dependency processing 0x00000010 trace node finding + 0x10000000 log ASN1 errors + 0x20000000 log SNMP errors Individual values can be or-ed together." DEFVAL { 0 } ::= { begemotSnmpdDebug 2 } @@ -461,6 +476,7 @@ begemotSnmpdLocalPortEntry OBJECT-TYPE BegemotSnmpdLocalPortEntry ::= SEQUENCE { begemotSnmpdLocalPortPath OCTET STRING, begemotSnmpdLocalPortStatus INTEGER + begemotSnmpdLocalPortType INTEGER } begemotSnmpdLocalPortPath OBJECT-TYPE @@ -479,4 +495,79 @@ begemotSnmpdLocalPortStatus OBJECT-TYPE "Set status to 1 to create entry, set it to 2 to delete it." ::= { begemotSnmpdLocalPortEntry 2 } +begemotSnmpdLocalPortType OBJECT-TYPE + SYNTAX INTEGER { + dgram-unpriv(1), + dgram-priv(2), + stream-unpriv(3), + stream-priv(4) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Type of the port. If the type is unpriv SET operations + are allowed from all clients if the community matches. For + priv SET operations are allowed only from peers with uid + zero. If the daemon cannot determine the peer uid it disallows + the SET operation for -priv ports." + ::= { begemotSnmpdLocalPortEntry 3 } + +-- +-- Transport mapping table +-- +begemotSnmpdTransportMappings OBJECT IDENTIFIER ::= { begemotSnmpdObjects 10 } + +begemotSnmpdTransportTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdTransportEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing all the currently loaded transport mappings." + ::= { begemotSnmpdTransportMappings 1 } + +begemotSnmpdTransportEntry OBJECT-TYPE + SYNTAX BegemotSnmpdTransportEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the table with the transport mappings." + INDEX { begemotSnmpdTransportName } + ::= { begemotSnmpdTransportTable 1 } + +BegemotSnmpdTransportEntry ::= SEQUENCE { + begemotSnmpdTransportName OCTET STRING, + begemotSnmpdTransportStatus INTEGER + begemotSnmpdTransportOid OBJECT IDENTIFIER +} + +begemotSnmpdTransportName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(1..256)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The name of the mapping." + ::= { begemotSnmpdTransportEntry 1 } + +begemotSnmpdTransportStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Used to create/activate/destroy the entry." + ::= { begemotSnmpdTransportEntry 2 } + +begemotSnmpdTransportOid OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A pointer to the group with the transport-dependend stuff." + ::= { begemotSnmpdTransportEntry 3 } + +-- +-- XXX These should go into their own MIB +-- +begemotSnmpdTransUdp OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 2 } +begemotSnmpdTransLsock OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 3 } + END diff --git a/contrib/bsnmp/snmpd/FOKUS-MIB.txt b/contrib/bsnmp/snmpd/FOKUS-MIB.txt index c0939babee88..767ace75f6e2 100644 --- a/contrib/bsnmp/snmpd/FOKUS-MIB.txt +++ b/contrib/bsnmp/snmpd/FOKUS-MIB.txt @@ -30,7 +30,7 @@ -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- --- $Begemot: bsnmp/snmpd/FOKUS-MIB.txt,v 1.3 2002/02/06 12:43:51 hbb Exp $ +-- $Begemot: bsnmp/snmpd/FOKUS-MIB.txt,v 1.4 2003/12/03 10:08:47 hbb Exp $ -- -- Begemot private definitions and fokus root. -- diff --git a/contrib/bsnmp/snmpd/action.c b/contrib/bsnmp/snmpd/action.c index 7c87beaf445e..0fee3b9aaaa0 100644 --- a/contrib/bsnmp/snmpd/action.c +++ b/contrib/bsnmp/snmpd/action.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/action.c,v 1.53 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/action.c,v 1.56 2003/12/09 12:28:52 hbb Exp $ * * Variable access for SNMPd */ @@ -557,6 +557,9 @@ op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, break; case LEAF_begemotSnmpdTrap1Addr: return (ip_get(value, snmpd.trap1addr)); + case LEAF_begemotSnmpdVersionEnable: + value->v.uint32 = snmpd.version_enable; + break; default: return (SNMP_ERR_NOSUCHNAME); } @@ -595,6 +598,16 @@ op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, case LEAF_begemotSnmpdTrap1Addr: return (ip_save(value, ctx, snmpd.trap1addr)); + + case LEAF_begemotSnmpdVersionEnable: + if (community != COMM_INITIALIZE) + return (SNMP_ERR_NOT_WRITEABLE); + ctx->scratch->int1 = snmpd.version_enable; + if (value->v.uint32 == 0 || + (value->v.uint32 & ~VERS_ENABLE_ALL)) + return (SNMP_ERR_WRONG_VALUE); + snmpd.version_enable = value->v.uint32; + return (SNMP_ERR_NOERROR); } abort(); @@ -613,6 +626,9 @@ op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, case LEAF_begemotSnmpdTrap1Addr: ip_rollback(ctx, snmpd.trap1addr); return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdVersionEnable: + snmpd.version_enable = ctx->scratch->int1; + return (SNMP_ERR_NOERROR); } abort(); @@ -626,6 +642,8 @@ op_snmpd_config(struct snmp_context *ctx, struct snmp_value *value, case LEAF_begemotSnmpdTrap1Addr: ip_commit(ctx); return (SNMP_ERR_NOERROR); + case LEAF_begemotSnmpdVersionEnable: + return (SNMP_ERR_NOERROR); } abort(); } @@ -702,203 +720,6 @@ op_community(struct snmp_context *ctx, struct snmp_value *value, abort(); } -/* - * Port table - */ -int -op_snmp_port(struct snmp_context *ctx, struct snmp_value *value, - u_int sub, u_int iidx, enum snmp_op op) -{ - asn_subid_t which = value->var.subs[sub-1]; - struct snmp_port *p; - u_int8_t addr[4]; - u_int32_t port; - - switch (op) { - - case SNMP_OP_GETNEXT: - if ((p = NEXT_OBJECT_OID(&snmp_port_list, &value->var, sub)) - == NULL) - return (SNMP_ERR_NOSUCHNAME); - index_append(&value->var, sub, &p->index); - break; - - case SNMP_OP_GET: - if ((p = FIND_OBJECT_OID(&snmp_port_list, &value->var, sub)) - == NULL) - return (SNMP_ERR_NOSUCHNAME); - break; - - case SNMP_OP_SET: - p = FIND_OBJECT_OID(&snmp_port_list, &value->var, sub); - ctx->scratch->int1 = (p != NULL); - - if (which != LEAF_begemotSnmpdPortStatus) - abort(); - if (!TRUTH_OK(value->v.integer)) - return (SNMP_ERR_WRONG_VALUE); - - ctx->scratch->int2 = TRUTH_GET(value->v.integer); - - if (ctx->scratch->int2) { - /* open an SNMP port */ - if (p != NULL) - /* already open - do nothing */ - return (SNMP_ERR_NOERROR); - - if (index_decode(&value->var, sub, iidx, addr, &port)) - return (SNMP_ERR_NO_CREATION); - return (open_snmp_port(addr, port, &p)); - - } else { - /* close SNMP port - do in commit */ - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_ROLLBACK: - p = FIND_OBJECT_OID(&snmp_port_list, &value->var, sub); - if (ctx->scratch->int1 == 0) { - /* did not exist */ - if (ctx->scratch->int2 == 1) { - /* created */ - if (p != NULL) - close_snmp_port(p); - } - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_COMMIT: - p = FIND_OBJECT_OID(&snmp_port_list, &value->var, sub); - if (ctx->scratch->int1 == 1) { - /* did exist */ - if (ctx->scratch->int2 == 0) { - /* delete */ - if (p != NULL) - close_snmp_port(p); - } - } - return (SNMP_ERR_NOERROR); - - default: - abort(); - } - - /* - * Come here to fetch the value - */ - switch (which) { - - case LEAF_begemotSnmpdPortStatus: - value->v.integer = 1; - break; - - default: - abort(); - } - - return (SNMP_ERR_NOERROR); -} - -/* - * Local port table - */ -int -op_local_port(struct snmp_context *ctx, struct snmp_value *value, - u_int sub, u_int iidx, enum snmp_op op) -{ - asn_subid_t which = value->var.subs[sub-1]; - struct local_port *p; - u_char *name; - size_t namelen; - - switch (op) { - - case SNMP_OP_GETNEXT: - if ((p = NEXT_OBJECT_OID(&local_port_list, &value->var, sub)) - == NULL) - return (SNMP_ERR_NOSUCHNAME); - index_append(&value->var, sub, &p->index); - break; - - case SNMP_OP_GET: - if ((p = FIND_OBJECT_OID(&local_port_list, &value->var, sub)) - == NULL) - return (SNMP_ERR_NOSUCHNAME); - break; - - case SNMP_OP_SET: - p = FIND_OBJECT_OID(&local_port_list, &value->var, sub); - ctx->scratch->int1 = (p != NULL); - - if (which != LEAF_begemotSnmpdLocalPortStatus) - abort(); - if (!TRUTH_OK(value->v.integer)) - return (SNMP_ERR_WRONG_VALUE); - - ctx->scratch->int2 = TRUTH_GET(value->v.integer); - - if (ctx->scratch->int2) { - /* open a local port */ - if (p != NULL) - /* already open - do nothing */ - return (SNMP_ERR_NOERROR); - - if (index_decode(&value->var, sub, iidx, - &name, &namelen)) - return (SNMP_ERR_NO_CREATION); - return (open_local_port(name, namelen, &p)); - - } else { - /* close local port - do in commit */ - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_ROLLBACK: - p = FIND_OBJECT_OID(&local_port_list, &value->var, sub); - if (ctx->scratch->int1 == 0) { - /* did not exist */ - if (ctx->scratch->int2 == 1) { - /* created */ - if (p != NULL) - close_local_port(p); - } - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_COMMIT: - p = FIND_OBJECT_OID(&local_port_list, &value->var, sub); - if (ctx->scratch->int1 == 1) { - /* did exist */ - if (ctx->scratch->int2 == 0) { - /* delete */ - if (p != NULL) - close_local_port(p); - } - } - return (SNMP_ERR_NOERROR); - - default: - abort(); - } - - /* - * Come here to fetch the value - */ - switch (which) { - - case LEAF_begemotSnmpdLocalPortStatus: - value->v.integer = 1; - break; - - default: - abort(); - } - - return (SNMP_ERR_NOERROR); -} - - - /* * Module table. */ @@ -1143,3 +964,79 @@ op_snmp_set(struct snmp_context *ctx __unused, struct snmp_value *value, } abort(); } + +/* + * Transport table + */ +int +op_transport_table(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub - 1]; + struct transport *t; + u_char *tname, *ptr; + size_t tnamelen; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((t = NEXT_OBJECT_OID(&transport_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &t->index); + break; + + case SNMP_OP_GET: + if ((t = FIND_OBJECT_OID(&transport_list, &value->var, sub)) + == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + t = FIND_OBJECT_OID(&transport_list, &value->var, sub); + if (which != LEAF_begemotSnmpdTransportStatus) { + if (t == NULL) + return (SNMP_ERR_NO_CREATION); + return (SNMP_ERR_NOT_WRITEABLE); + } + + /* the errors in the next few statements can only happen when + * t is NULL, hence the NO_CREATION error. */ + if (index_decode(&value->var, sub, iidx, + &tname, &tnamelen)) + return (SNMP_ERR_NO_CREATION); + + /* check the section name */ + if (tnamelen >= TRANS_NAMELEN || tnamelen == 0) { + free(tname); + return (SNMP_ERR_NO_CREATION); + } + for (ptr = tname; ptr < tname + tnamelen; ptr++) { + if (!isascii(*ptr) || !isalnum(*ptr)) { + free(tname); + return (SNMP_ERR_NO_CREATION); + } + } + + /* for now */ + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + default: + abort(); + } + + switch (which) { + + case LEAF_begemotSnmpdTransportStatus: + value->v.integer = 1; + break; + + case LEAF_begemotSnmpdTransportOid: + memcpy(&value->v.oid, &t->vtab->id, sizeof(t->vtab->id)); + break; + } + return (SNMP_ERR_NOERROR); +} diff --git a/contrib/bsnmp/snmpd/bsnmpd.1 b/contrib/bsnmp/snmpd/bsnmpd.1 index 01c7a1c52e99..334ac1891a15 100644 --- a/contrib/bsnmp/snmpd/bsnmpd.1 +++ b/contrib/bsnmp/snmpd/bsnmpd.1 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/snmpd/snmpd.1,v 1.2 2002/08/15 13:27:47 hbb Exp $ +.\" $Begemot: bsnmp/snmpd/bsnmpd.1,v 1.1 2003/12/03 10:08:33 hbb Exp $ .\" .Dd August 15, 2002 .Dt SNMPD 1 diff --git a/contrib/bsnmp/snmpd/config.c b/contrib/bsnmp/snmpd/config.c index e247797ff69e..4001156276f1 100644 --- a/contrib/bsnmp/snmpd/config.c +++ b/contrib/bsnmp/snmpd/config.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/config.c,v 1.18 2003/03/11 15:30:01 hbb Exp $ + * $Begemot: bsnmp/snmpd/config.c,v 1.19 2003/12/03 10:08:47 hbb Exp $ * * Parse configuration file. */ diff --git a/contrib/bsnmp/snmpd/export.c b/contrib/bsnmp/snmpd/export.c index 4cebdb330b10..12a981a2be4d 100644 --- a/contrib/bsnmp/snmpd/export.c +++ b/contrib/bsnmp/snmpd/export.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/export.c,v 1.5 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/export.c,v 1.6 2003/12/03 10:08:47 hbb Exp $ * * Support functions for modules. */ diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c index 1568b4b34c89..1a528ac44991 100644 --- a/contrib/bsnmp/snmpd/main.c +++ b/contrib/bsnmp/snmpd/main.c @@ -30,13 +30,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/main.c,v 1.76 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/main.c,v 1.82 2003/12/09 12:28:52 hbb Exp $ * * SNMPd main stuff. */ #include #include -#include +#include #include #include #include @@ -49,8 +49,6 @@ #include #include #include -#include -#include #include "snmpmod.h" #include "snmpd.h" @@ -82,6 +80,7 @@ struct snmpd snmpd = { 0, /* comm_dis */ 0, /* auth_traps */ {0, 0, 0, 0}, /* trap1addr */ + VERS_ENABLE_ALL,/* version_enable */ }; struct snmpd_stats snmpd_stats; @@ -126,20 +125,14 @@ static int nprogargs; u_int community; static struct community *comm; -/* list of all IP ports we are listening on */ -struct snmp_port_list snmp_port_list = - TAILQ_HEAD_INITIALIZER(snmp_port_list); - -/* list of all local ports we are listening on */ -struct local_port_list local_port_list = - TAILQ_HEAD_INITIALIZER(local_port_list); - /* file names */ static char config_file[MAXPATHLEN + 1]; static char pid_file[MAXPATHLEN + 1]; +#ifndef USE_LIBBEGEMOT /* event context */ static evContext evctx; +#endif /* signal mask */ static sigset_t blocked_sigs; @@ -178,6 +171,12 @@ options:\n\ -p file specify pid file\n\ "; +/* transports */ +extern const struct transport_def udp_trans; +extern const struct transport_def lsock_trans; + +struct transport_list transport_list = TAILQ_HEAD_INITIALIZER(transport_list); + /* forward declarations */ static void snmp_printf_func(const char *fmt, ...); static void snmp_error_func(const char *err, ...); @@ -192,7 +191,7 @@ buf_alloc(int tx) { void *buf; - if ((buf = malloc(tx ? snmpd.txbuf : (snmpd.rxbuf + 1))) == NULL) { + if ((buf = malloc(tx ? snmpd.txbuf : snmpd.rxbuf)) == NULL) { syslog(LOG_CRIT, "cannot allocate buffer"); if (tx) snmpd_stats.noTxbuf++; @@ -204,19 +203,19 @@ buf_alloc(int tx) } /* - * Return the buffer size. (one more for RX). + * Return the buffer size. */ size_t buf_size(int tx) { - return (tx ? snmpd.txbuf : (snmpd.rxbuf + 1)); + return (tx ? snmpd.txbuf : snmpd.rxbuf); } /* * Prepare a PDU for output */ void -snmp_output(struct snmp_v1_pdu *pdu, u_char *sndbuf, size_t *sndlen, +snmp_output(struct snmp_pdu *pdu, u_char *sndbuf, size_t *sndlen, const char *dest) { struct asn_buf resp_b; @@ -235,56 +234,37 @@ snmp_output(struct snmp_v1_pdu *pdu, u_char *sndbuf, size_t *sndlen, *sndlen = (size_t)(resp_b.asn_ptr - sndbuf); } -/* - * Send a PDU to a given port - */ -void -snmp_send_port(const struct asn_oid *port, struct snmp_v1_pdu *pdu, - const struct sockaddr *addr, socklen_t addrlen) -{ - struct snmp_port *p; - u_char *sndbuf; - size_t sndlen; - ssize_t len; - - TAILQ_FOREACH(p, &snmp_port_list, link) - if (asn_compare_oid(port, &p->index) == 0) - break; - - if (p == 0) - return; - - if ((sndbuf = buf_alloc(1)) == NULL) - return; - - snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY"); - - if ((len = sendto(p->sock, sndbuf, sndlen, 0, addr, addrlen)) == -1) - syslog(LOG_ERR, "sendto: %m"); - else if ((size_t)len != sndlen) - syslog(LOG_ERR, "sendto: short write %zu/%zu", - sndlen, (size_t)len); - - free(sndbuf); -} - /* * SNMP input. Start: decode the PDU, find the community. */ enum snmpd_input_err snmp_input_start(const u_char *buf, size_t len, const char *source, - struct snmp_v1_pdu *pdu, int32_t *ip) + struct snmp_pdu *pdu, int32_t *ip, size_t *pdulen) { struct asn_buf b; enum snmp_code code; enum snmpd_input_err ret; - - snmpd_stats.inPkts++; + int sret; b.asn_cptr = buf; b.asn_len = len; + + /* look whether we have enough bytes for the entire PDU. */ + switch (sret = snmp_pdu_snoop(&b)) { + + case 0: + return (SNMPD_INPUT_TRUNC); + + case -1: + snmpd_stats.inASNParseErrs++; + return (SNMPD_INPUT_FAILED); + } + b.asn_len = *pdulen = (size_t)sret; + code = snmp_pdu_decode(&b, pdu, ip); + snmpd_stats.inPkts++; + ret = SNMPD_INPUT_OK; switch (code) { @@ -293,6 +273,7 @@ snmp_input_start(const u_char *buf, size_t len, const char *source, return (SNMPD_INPUT_FAILED); case SNMP_CODE_BADVERS: + bad_vers: snmpd_stats.inBadVersions++; return (SNMPD_INPUT_FAILED); @@ -312,6 +293,21 @@ snmp_input_start(const u_char *buf, size_t len, const char *source, break; case SNMP_CODE_OK: + switch (pdu->version) { + + case SNMP_V1: + if (!(snmpd.version_enable & VERS_ENABLE_V1)) + goto bad_vers; + break; + + case SNMP_V2c: + if (!(snmpd.version_enable & VERS_ENABLE_V2C)) + goto bad_vers; + break; + + case SNMP_Verr: + goto bad_vers; + } break; } @@ -449,13 +445,143 @@ snmp_input_finish(struct snmp_pdu *pdu, const u_char *rcvbuf, size_t rcvlen, abort(); } +/* + * Insert a port into the right place in the transport's table of ports + */ +void +trans_insert_port(struct transport *t, struct tport *port) +{ + struct tport *p; + TAILQ_FOREACH(p, &t->table, link) { + if (asn_compare_oid(&p->index, &port->index) > 0) { + TAILQ_INSERT_BEFORE(p, port, link); + return; + } + } + port->transport = t; + TAILQ_INSERT_TAIL(&t->table, port, link); +} + +/* + * Remove a port from a transport's list + */ +void +trans_remove_port(struct tport *port) +{ + + TAILQ_REMOVE(&port->transport->table, port, link); +} + +/* + * Find a port on a transport's list + */ +struct tport * +trans_find_port(struct transport *t, const struct asn_oid *idx, u_int sub) +{ + + return (FIND_OBJECT_OID(&t->table, idx, sub)); +} + +/* + * Find next port on a transport's list + */ +struct tport * +trans_next_port(struct transport *t, const struct asn_oid *idx, u_int sub) +{ + + return (NEXT_OBJECT_OID(&t->table, idx, sub)); +} + +/* + * Return first port + */ +struct tport * +trans_first_port(struct transport *t) +{ + + return (TAILQ_FIRST(&t->table)); +} + +/* + * Iterate through all ports until a function returns a 0. + */ +struct tport * +trans_iter_port(struct transport *t, int (*func)(struct tport *, intptr_t), + intptr_t arg) +{ + struct tport *p; + + TAILQ_FOREACH(p, &t->table, link) + if (func(p, arg) == 0) + return (p); + return (NULL); +} + +/* + * Register a transport + */ +int +trans_register(const struct transport_def *def, struct transport **pp) +{ + u_int i; + char or_descr[256]; + + if ((*pp = malloc(sizeof(**pp))) == NULL) + return (SNMP_ERR_GENERR); + + /* construct index */ + (*pp)->index.len = strlen(def->name) + 1; + (*pp)->index.subs[0] = strlen(def->name); + for (i = 0; i < (*pp)->index.subs[0]; i++) + (*pp)->index.subs[i + 1] = def->name[i]; + + (*pp)->vtab = def; + + if (FIND_OBJECT_OID(&transport_list, &(*pp)->index, 0) != NULL) { + free(*pp); + return (SNMP_ERR_INCONS_VALUE); + } + + /* register module */ + snprintf(or_descr, sizeof(or_descr), "%s transport mapping", def->name); + if (((*pp)->or_index = or_register(&def->id, or_descr, NULL)) == 0) { + free(*pp); + return (SNMP_ERR_GENERR); + } + + INSERT_OBJECT_OID((*pp), &transport_list); + + TAILQ_INIT(&(*pp)->table); + + return (SNMP_ERR_NOERROR); +} + +/* + * Unregister transport + */ +int +trans_unregister(struct transport *t) +{ + if (!TAILQ_EMPTY(&t->table)) + return (SNMP_ERR_INCONS_VALUE); + + or_unregister(t->or_index); + TAILQ_REMOVE(&transport_list, t, link); + + return (SNMP_ERR_NOERROR); +} /* * File descriptor support */ +#ifdef USE_LIBBEGEMOT +static void +input(int fd, int mask __unused, void *uap) +#else static void input(evContext ctx __unused, void *uap, int fd, int mask __unused) +#endif { struct fdesc *f = uap; @@ -467,10 +593,17 @@ fd_suspend(void *p) { struct fdesc *f = p; +#ifdef USE_LIBBEGEMOT + if (f->id >= 0) { + poll_unregister(f->id); + f->id = -1; + } +#else if (evTestID(f->id)) { (void)evDeselectFD(evctx, f->id); evInitID(&f->id); } +#endif } int @@ -479,6 +612,16 @@ fd_resume(void *p) struct fdesc *f = p; int err; +#ifdef USE_LIBBEGEMOT + if (f->id >= 0) + return (0); + if ((f->fd = poll_register(f->fd, input, f, POLL_IN)) < 0) { + err = errno; + syslog(LOG_ERR, "select fd %d: %m", f->fd); + errno = err; + return (-1); + } +#else if (evTestID(f->id)) return (0); if (evSelectFD(evctx, f->fd, EV_READ, input, f, &f->id)) { @@ -487,6 +630,7 @@ fd_resume(void *p) errno = err; return (-1); } +#endif return (0); } @@ -506,7 +650,11 @@ fd_select(int fd, void (*func)(int, void *), void *udata, struct lmodule *mod) f->func = func; f->udata = udata; f->owner = mod; +#ifdef USE_LIBBEGEMOT + f->id = -1; +#else evInitID(&f->id); +#endif if (fd_resume(f)) { err = errno; @@ -542,56 +690,237 @@ fd_flush(struct lmodule *mod) fd_deselect(t); t = t1; } - } - /* - * Input from UDP socket + * Consume a message from the input buffer */ static void -do_input(int fd, const struct asn_oid *port_index, - struct sockaddr *ret, socklen_t *retlen) +snmp_input_consume(struct port_input *pi) +{ + if (!pi->stream) { + /* always consume everything */ + pi->length = 0; + return; + } + if (pi->consumed >= pi->length) { + /* all bytes consumed */ + pi->length = 0; + return; + } + memmove(pi->buf, pi->buf + pi->consumed, pi->length - pi->consumed); + pi->length -= pi->consumed; +} + +struct credmsg { + struct cmsghdr hdr; + struct cmsgcred cred; +}; + +static void +check_priv(struct port_input *pi, struct msghdr *msg) +{ + struct credmsg *cmsg; + struct xucred ucred; + socklen_t ucredlen; + + pi->priv = 0; + + if (msg->msg_controllen == sizeof(*cmsg)) { + /* process explicitely sends credentials */ + + cmsg = (struct credmsg *)msg->msg_control; + pi->priv = (cmsg->cred.cmcred_euid == 0); + return; + } + + /* ok, 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); +} + +/* + * Input from a stream socket. + */ +static int +recv_stream(struct port_input *pi) +{ + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + struct credmsg cmsg; + + 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; + if (pi->cred) { + msg.msg_control = &cmsg; + msg.msg_controllen = sizeof(cmsg); + + cmsg.hdr.cmsg_len = sizeof(cmsg); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDS; + } else { + 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(pi, &msg); + + return (0); +} + +/* + * Input from a datagram socket. + * Each receive should return one datagram. + */ +static int +recv_dgram(struct port_input *pi) +{ + u_char embuf[1000]; + struct msghdr msg; + struct iovec iov[1]; + ssize_t len; + struct credmsg cmsg; + + 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; + if (pi->cred) { + msg.msg_control = &cmsg; + msg.msg_controllen = sizeof(cmsg); + + cmsg.hdr.cmsg_len = sizeof(cmsg); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDS; + } else { + msg.msg_control = NULL; + msg.msg_controllen = NULL; + } + 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; + + if (pi->cred) + check_priv(pi, &msg); + + return (0); +} + +/* + * Input from a socket + */ +int +snmpd_input(struct port_input *pi, struct tport *tport) { - u_char *resbuf, embuf[100]; u_char *sndbuf; size_t sndlen; - ssize_t len; - struct snmp_v1_pdu pdu; + struct snmp_pdu pdu; enum snmpd_input_err ierr, ferr; enum snmpd_proxy_err perr; int32_t vi; + int ret; + ssize_t slen; - if ((resbuf = buf_alloc(0)) == NULL) { - (void)recvfrom(fd, embuf, sizeof(embuf), 0, ret, retlen); - return; - } - if ((len = recvfrom(fd, resbuf, buf_size(0), 0, ret, retlen)) == -1) { - free(resbuf); - return; - } - if (len == 0) { - free(resbuf); - return; - } - if ((size_t)len == buf_size(0)) { - free(resbuf); - snmpd_stats.silentDrops++; - snmpd_stats.inTooLong++; - return; + /* get input depending on the transport */ + if (pi->stream) { + ret = recv_stream(pi); + } else { + ret = recv_dgram(pi); } + if (ret == -1) + return (-1); + /* * Handle input */ - ierr = snmp_input_start(resbuf, (size_t)len, "SNMP", &pdu, &vi); + ierr = snmp_input_start(pi->buf, pi->length, "SNMP", &pdu, &vi, + &pi->consumed); + if (ierr == SNMPD_INPUT_TRUNC) { + /* need more bytes. This is ok only for streaming transports. + * but only if we have not reached bufsiz yet. */ + if (pi->stream) { + if (pi->length == buf_size(0)) { + snmpd_stats.silentDrops++; + return (-1); + } + return (0); + } + snmpd_stats.silentDrops++; + return (-1); + } /* can't check for bad SET pdus here, because a proxy may have to * check the access first. We don't want to return an error response * to a proxy PDU with a wrong community */ if (ierr == SNMPD_INPUT_FAILED) { - free(resbuf); - return; + /* for streaming transports this is fatal */ + if (pi->stream) + return (-1); + snmp_input_consume(pi); + return (0); } /* @@ -599,41 +928,41 @@ do_input(int fd, const struct asn_oid *port_index, * the hand it over to the module. */ if (comm->owner != NULL && comm->owner->config->proxy != NULL) { - perr = (*comm->owner->config->proxy)(&pdu, port_index, - ret, *retlen, ierr, vi); + perr = (*comm->owner->config->proxy)(&pdu, tport->transport, + &tport->index, pi->peer, pi->peerlen, ierr, vi, pi->priv); switch (perr) { case SNMPD_PROXY_OK: - free(resbuf); - return; + snmp_input_consume(pi); + return (0); case SNMPD_PROXY_REJ: break; case SNMPD_PROXY_DROP: - free(resbuf); + snmp_input_consume(pi); snmp_pdu_free(&pdu); snmpd_stats.proxyDrops++; - return; + return (0); case SNMPD_PROXY_BADCOMM: - free(resbuf); + snmp_input_consume(pi); snmp_pdu_free(&pdu); snmpd_stats.inBadCommunityNames++; if (snmpd.auth_traps) snmp_send_trap(&oid_authenticationFailure, NULL); - return; + return (0); case SNMPD_PROXY_BADCOMMUSE: - free(resbuf); + snmp_input_consume(pi); snmp_pdu_free(&pdu); snmpd_stats.inBadCommunityUses++; if (snmpd.auth_traps) snmp_send_trap(&oid_authenticationFailure, NULL); - return; + return (0); } } @@ -646,21 +975,22 @@ do_input(int fd, const struct asn_oid *port_index, snmpd_stats.silentDrops++; snmpd_stats.inBadPduTypes++; snmp_pdu_free(&pdu); - free(resbuf); - return; + snmp_input_consume(pi); + return (0); } /* * Check community */ - if (community != COMM_WRITE && - (pdu.type == SNMP_PDU_SET || community != COMM_READ)) { + if ((pi->cred && !pi->priv && pdu.type == SNMP_PDU_SET) || + (community != COMM_WRITE && + (pdu.type == SNMP_PDU_SET || community != COMM_READ))) { snmpd_stats.inBadCommunityUses++; snmp_pdu_free(&pdu); - free(resbuf); + snmp_input_consume(pi); if (snmpd.auth_traps) snmp_send_trap(&oid_authenticationFailure, NULL); - return; + return (0); } /* @@ -669,271 +999,87 @@ do_input(int fd, const struct asn_oid *port_index, if ((sndbuf = buf_alloc(1)) == NULL) { snmpd_stats.silentDrops++; snmp_pdu_free(&pdu); - free(resbuf); - return; + snmp_input_consume(pi); + return (0); } - ferr = snmp_input_finish(&pdu, resbuf, len, sndbuf, &sndlen, "SNMP", - ierr, vi, NULL); + ferr = snmp_input_finish(&pdu, pi->buf, pi->length, + sndbuf, &sndlen, "SNMP", ierr, vi, NULL); if (ferr == SNMPD_INPUT_OK) { - if ((len = sendto(fd, sndbuf, sndlen, 0, ret, *retlen)) == -1) + slen = sendto(pi->fd, sndbuf, sndlen, 0, pi->peer, pi->peerlen); + if (slen == -1) syslog(LOG_ERR, "sendto: %m"); - else if ((size_t)len != sndlen) + else if ((size_t)slen != sndlen) syslog(LOG_ERR, "sendto: short write %zu/%zu", - sndlen, (size_t)len); + sndlen, (size_t)slen); } snmp_pdu_free(&pdu); free(sndbuf); - free(resbuf); -} + snmp_input_consume(pi); -static void -ssock_input(int fd, void *udata) -{ - struct snmp_port *p = udata; - - p->retlen = sizeof(p->ret); - do_input(fd, &p->index, (struct sockaddr *)&p->ret, &p->retlen); -} - -static void -lsock_input(int fd, void *udata) -{ - struct local_port *p = udata; - - p->retlen = sizeof(p->ret); - do_input(fd, &p->index, (struct sockaddr *)&p->ret, &p->retlen); -} - - -/* - * Create a UDP socket and bind it to the given port - */ -static int -init_snmp(struct snmp_port *p) -{ - struct sockaddr_in addr; - u_int32_t ip; - - if ((p->sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "creating UDP socket: %m"); - return (SNMP_ERR_RES_UNAVAIL); - } - ip = (p->addr[0] << 24) | (p->addr[1] << 16) | (p->addr[2] << 8) | - p->addr[3]; - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(ip); - addr.sin_port = htons(p->port); - addr.sin_family = AF_INET; - addr.sin_len = sizeof(addr); - if (bind(p->sock, (struct sockaddr *)&addr, sizeof(addr))) { - if (errno == EADDRNOTAVAIL) { - close(p->sock); - p->sock = -1; - return (SNMP_ERR_INCONS_NAME); - } - syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(addr.sin_addr), - p->port); - close(p->sock); - p->sock = -1; - return (SNMP_ERR_GENERR); - } - if ((p->id = fd_select(p->sock, ssock_input, p, NULL)) == NULL) { - close(p->sock); - p->sock = -1; - return (SNMP_ERR_GENERR); - } - return (SNMP_ERR_NOERROR); -} - - -/* - * Create a new SNMP Port object and start it, if we are not - * in initialisation mode. The arguments are in host byte order. - */ -int -open_snmp_port(u_int8_t *addr, u_int32_t port, struct snmp_port **pp) -{ - struct snmp_port *snmp, *p; - int err; - - if (port > 0xffff) - return (SNMP_ERR_NO_CREATION); - if ((snmp = malloc(sizeof(*snmp))) == NULL) - return (SNMP_ERR_GENERR); - snmp->addr[0] = addr[0]; - snmp->addr[1] = addr[1]; - snmp->addr[2] = addr[2]; - snmp->addr[3] = addr[3]; - snmp->port = port; - snmp->sock = -1; - snmp->id = NULL; - snmp->index.len = 5; - snmp->index.subs[0] = addr[0]; - snmp->index.subs[1] = addr[1]; - snmp->index.subs[2] = addr[2]; - snmp->index.subs[3] = addr[3]; - snmp->index.subs[4] = port; - - /* - * Insert it into the right place - */ - TAILQ_FOREACH(p, &snmp_port_list, link) { - if (asn_compare_oid(&p->index, &snmp->index) > 0) { - TAILQ_INSERT_BEFORE(p, snmp, link); - break; - } - } - if (p == NULL) - TAILQ_INSERT_TAIL(&snmp_port_list, snmp, link); - - if (community != COMM_INITIALIZE && - (err = init_snmp(snmp)) != SNMP_ERR_NOERROR) { - TAILQ_REMOVE(&snmp_port_list, snmp, link); - free(snmp); - return (err); - } - *pp = snmp; - return (SNMP_ERR_NOERROR); + return (0); } /* - * Close an SNMP port + * Send a PDU to a given port */ void -close_snmp_port(struct snmp_port *snmp) +snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu, + const struct sockaddr *addr, socklen_t addrlen) { - if (snmp->id != NULL) - fd_deselect(snmp->id); - if (snmp->sock >= 0) - (void)close(snmp->sock); + struct transport *trans = targ; + struct tport *tp; + u_char *sndbuf; + size_t sndlen; + ssize_t len; - TAILQ_REMOVE(&snmp_port_list, snmp, link); - free(snmp); -} - -/* - * Create a local socket - */ -static int -init_local(struct local_port *p) -{ - struct sockaddr_un sa; - - if ((p->sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "creating local socket: %m"); - return (SNMP_ERR_RES_UNAVAIL); - } - strcpy(sa.sun_path, p->name); - sa.sun_family = AF_LOCAL; - sa.sun_len = strlen(p->name) + offsetof(struct sockaddr_un, sun_path); - - (void)remove(p->name); - - if (bind(p->sock, (struct sockaddr *)&sa, sizeof(sa))) { - if (errno == EADDRNOTAVAIL) { - close(p->sock); - p->sock = -1; - return (SNMP_ERR_INCONS_NAME); - } - syslog(LOG_ERR, "bind: %s %m", p->name); - close(p->sock); - p->sock = -1; - return (SNMP_ERR_GENERR); - } - if (chmod(p->name, 0666) == -1) - syslog(LOG_WARNING, "chmod(%s,0666): %m", p->name); - if ((p->id = fd_select(p->sock, lsock_input, p, NULL)) == NULL) { - (void)remove(p->name); - close(p->sock); - p->sock = -1; - return (SNMP_ERR_GENERR); - } - return (SNMP_ERR_NOERROR); -} - - -/* - * Open a local port - */ -int -open_local_port(u_char *name, size_t namelen, struct local_port **pp) -{ - struct local_port *port, *p; - size_t u; - int err; - struct sockaddr_un sa; - - if (namelen == 0 || namelen + 1 > sizeof(sa.sun_path)) { - free(name); - return (SNMP_ERR_BADVALUE); - } - if ((port = malloc(sizeof(*port))) == NULL) { - free(name); - return (SNMP_ERR_GENERR); - } - if ((port->name = malloc(namelen + 1)) == NULL) { - free(name); - free(port); - return (SNMP_ERR_GENERR); - } - strncpy(port->name, name, namelen); - port->name[namelen] = '\0'; - - port->sock = -1; - port->id = NULL; - port->index.len = namelen + 1; - port->index.subs[0] = namelen; - for (u = 0; u < namelen; u++) - port->index.subs[u + 1] = name[u]; - - /* - * Insert it into the right place - */ - TAILQ_FOREACH(p, &local_port_list, link) { - if (asn_compare_oid(&p->index, &port->index) > 0) { - TAILQ_INSERT_BEFORE(p, port, link); + TAILQ_FOREACH(tp, &trans->table, link) + if (asn_compare_oid(port, &tp->index) == 0) break; - } - } - if (p == NULL) - TAILQ_INSERT_TAIL(&local_port_list, port, link); + if (tp == 0) + return; - if (community != COMM_INITIALIZE && - (err = init_local(port)) != SNMP_ERR_NOERROR) { - TAILQ_REMOVE(&local_port_list, port, link); - free(port->name); - free(port); - return (err); - } + if ((sndbuf = buf_alloc(1)) == NULL) + return; - *pp = p; + snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY"); - return (SNMP_ERR_NOERROR); + len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen); + + if (len == -1) + syslog(LOG_ERR, "sendto: %m"); + else if ((size_t)len != sndlen) + syslog(LOG_ERR, "sendto: short write %zu/%zu", + sndlen, (size_t)len); + + free(sndbuf); } + /* - * Close a local port + * Close an input source */ void -close_local_port(struct local_port *port) +snmpd_input_close(struct port_input *pi) { - if (port->id != NULL) - fd_deselect(port->id); - if (port->sock >= 0) - (void)close(port->sock); - (void)remove(port->name); - - TAILQ_REMOVE(&local_port_list, port, link); - free(port->name); - free(port); + if (pi->id != NULL) + fd_deselect(pi->id); + if (pi->fd >= 0) + (void)close(pi->fd); + if (pi->buf != NULL) + free(pi->buf); } /* * Dump internal state. */ +#ifdef USE_LIBBEGEMOT +static void +info_func(void) +#else static void info_func(evContext ctx __unused, void *uap __unused, const void *tag __unused) +#endif { struct lmodule *m; u_int i; @@ -964,9 +1110,14 @@ info_func(evContext ctx __unused, void *uap __unused, const void *tag __unused) /* * Re-read configuration */ +#ifdef USE_LIBBEGEMOT +static void +config_func(void) +#else static void config_func(evContext ctx __unused, void *uap __unused, const void *tag __unused) +#endif { struct lmodule *m; @@ -985,26 +1136,24 @@ config_func(evContext ctx __unused, void *uap __unused, static void onusr1(int s __unused) { + work |= WORK_DOINFO; } static void onhup(int s __unused) { + work |= WORK_RECONFIG; } static void onterm(int s __unused) { - struct local_port *p; - - TAILQ_FOREACH(p, &local_port_list, link) - (void)remove(p->name); + /* allow clean-up */ exit(0); } - static void init_sigs(void) { @@ -1066,6 +1215,15 @@ term(void) (void)unlink(pid_file); } +static void +trans_stop(void) +{ + struct transport *t; + + TAILQ_FOREACH(t, &transport_list, link) + (void)t->vtab->stop(1); +} + /* * Define a macro from the command line */ @@ -1130,7 +1288,7 @@ getsubopt1(char **arg, const char *const *options, char **valp, char **optp) *arg = ptr; for (i = 0; *options != NULL; options++, i++) - if (strcmp(suboptarg, *options) == 0) + if (strcmp(*optp, *options) == 0) return (i); return (-1); } @@ -1141,11 +1299,11 @@ main(int argc, char *argv[]) int opt; FILE *fp; int background = 1; - struct snmp_port *p; - struct local_port *pl; + struct tport *p; const char *prefix = "snmpd"; struct lmodule *m; char *value, *option; + struct transport *t; #define DBG_DUMP 0 #define DBG_EVENTS 1 @@ -1268,22 +1426,40 @@ main(int argc, char *argv[]) snprintf(config_file, sizeof(config_file), PATH_CONFIG, prefix); init_actvals(); + + start_tick = get_ticks(); + this_tick = get_ticks(); + + /* start transports */ + if (atexit(trans_stop) == -1) { + syslog(LOG_ERR, "atexit failed: %m"); + exit(1); + } + if (udp_trans.start() != SNMP_ERR_NOERROR) + syslog(LOG_WARNING, "cannot start UDP transport"); + if (lsock_trans.start() != SNMP_ERR_NOERROR) + syslog(LOG_WARNING, "cannot start LSOCK transport"); + if (read_config(config_file, NULL)) { syslog(LOG_ERR, "error in config file"); exit(1); } +#ifdef USE_LIBBEGEMOT + if (debug.evdebug > 0) + rpoll_trace = 1; +#else if (evCreate(&evctx)) { syslog(LOG_ERR, "evCreate: %m"); exit(1); } if (debug.evdebug > 0) evSetDebug(evctx, 10, stderr); +#endif - TAILQ_FOREACH(p, &snmp_port_list, link) - (void)init_snmp(p); - TAILQ_FOREACH(pl, &local_port_list, link) - (void)init_local(pl); + TAILQ_FOREACH(t, &transport_list, link) + TAILQ_FOREACH(p, &t->table, link) + t->vtab->init_port(p); init_sigs(); @@ -1293,12 +1469,13 @@ main(int argc, char *argv[]) if ((fp = fopen(pid_file, "w")) != NULL) { fprintf(fp, "%u", getpid()); fclose(fp); - atexit(term); + if (atexit(term) == -1) { + syslog(LOG_ERR, "atexit failed: %m"); + (void)remove(pid_file); + exit(0); + } } - start_tick = get_ticks(); - this_tick = get_ticks(); - if (or_register(&oid_snmpMIB, "The MIB module for SNMPv2 entities.", NULL) == 0) { syslog(LOG_ERR, "cannot register SNMPv2 MIB"); @@ -1319,13 +1496,16 @@ main(int argc, char *argv[]) } for (;;) { +#ifndef USE_LIBBEGEMOT evEvent event; +#endif struct lmodule *mod; TAILQ_FOREACH(mod, &lmodules, link) if (mod->config->idle != NULL) (*mod->config->idle)(); +#ifndef USE_LIBBEGEMOT if (evGetNext(evctx, &event, EV_WAIT) == 0) { if (evDispatch(evctx, event)) syslog(LOG_ERR, "evDispatch: %m"); @@ -1333,29 +1513,42 @@ main(int argc, char *argv[]) syslog(LOG_ERR, "evGetNext: %m"); exit(1); } +#else + poll_dispatch(1); +#endif if (work != 0) { block_sigs(); if (work & WORK_DOINFO) { +#ifdef USE_LIBBEGEMOT + info_func(); +#else if (evWaitFor(evctx, &work, info_func, NULL, NULL) == -1) { syslog(LOG_ERR, "evWaitFor: %m"); exit(1); } +#endif } if (work & WORK_RECONFIG) { +#ifdef USE_LIBBEGEMOT + config_func(); +#else if (evWaitFor(evctx, &work, config_func, NULL, NULL) == -1) { syslog(LOG_ERR, "evWaitFor: %m"); exit(1); } +#endif } work = 0; unblock_sigs(); +#ifndef USE_LIBBEGEMOT if (evDo(evctx, &work) == -1) { syslog(LOG_ERR, "evDo: %m"); exit(1); } +#endif } } @@ -1377,9 +1570,14 @@ get_ticks() /* * Timer support */ +#ifdef USE_LIBBEGEMOT +static void +tfunc(int tid __unused, void *uap) +#else static void tfunc(evContext ctx __unused, void *uap, struct timespec due __unused, struct timespec inter __unused) +#endif { struct timer *tp = uap; @@ -1395,14 +1593,28 @@ void * timer_start(u_int ticks, void (*func)(void *), void *udata, struct lmodule *mod) { struct timer *tp; +#ifdef USE_LIBBEGEMOT + struct timeval due; +#else struct timespec due; +#endif if ((tp = malloc(sizeof(struct timer))) == NULL) { syslog(LOG_CRIT, "out of memory for timer"); exit(1); } +#ifdef USE_LIBBEGEMOT + (void)gettimeofday(&due, NULL); + due.tv_sec += ticks / 100; + due.tv_usec += (ticks % 100) * 10000; + if (due.tv_usec >= 1000000) { + due.tv_sec++; + due.tv_usec -= 1000000; + } +#else due = evAddTime(evNowTime(), - evConsTime(ticks / 100, (ticks % 100) * 10000)); + evConsTime(ticks / 100, (ticks % 100) * 10000)); +#endif tp->udata = udata; tp->owner = mod; @@ -1410,11 +1622,19 @@ timer_start(u_int ticks, void (*func)(void *), void *udata, struct lmodule *mod) LIST_INSERT_HEAD(&timer_list, tp, link); +#ifdef USE_LIBBEGEMOT + if ((tp->id = poll_start_timer(due.tv_sec * 1000 + due.tv_usec / 1000, + 0, tfunc, tp)) < 0) { + syslog(LOG_ERR, "cannot set timer: %m"); + exit(1); + } +#else if (evSetTimer(evctx, tfunc, tp, due, evConsTime(0, 0), &tp->id) == -1) { syslog(LOG_ERR, "cannot set timer: %m"); exit(1); } +#endif return (tp); } @@ -1424,10 +1644,14 @@ timer_stop(void *p) struct timer *tp = p; LIST_REMOVE(tp, link); +#ifdef USE_LIBBEGEMOT + poll_stop_timer(tp->id); +#else if (evClearTimer(evctx, tp->id) == -1) { syslog(LOG_ERR, "cannot stop timer: %m"); exit(1); } +#endif free(p); } @@ -1488,10 +1712,13 @@ snmp_error_func(const char *err, ...) char errbuf[1000]; va_list ap; + if (!(snmp_trace & LOG_SNMP_ERRORS)) + return; + va_start(ap, err); snprintf(errbuf, sizeof(errbuf), "SNMP: "); - vsnprintf(errbuf+strlen(errbuf), sizeof(errbuf)-strlen(errbuf), - err, ap); + vsnprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), err, ap); va_end(ap); syslog(LOG_ERR, "%s", errbuf); @@ -1519,18 +1746,22 @@ asn_error_func(const struct asn_buf *b, const char *err, ...) va_list ap; u_int i; + if (!(snmp_trace & LOG_ASN1_ERRORS)) + return; + va_start(ap, err); snprintf(errbuf, sizeof(errbuf), "ASN.1: "); - vsnprintf(errbuf+strlen(errbuf), sizeof(errbuf)-strlen(errbuf), - err, ap); + vsnprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), err, ap); va_end(ap); if (b != NULL) { - snprintf(errbuf+strlen(errbuf), sizeof(errbuf)-strlen(errbuf), - " at"); + snprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), " at"); for (i = 0; b->asn_len > i; i++) - snprintf(errbuf+strlen(errbuf), - sizeof(errbuf)-strlen(errbuf), " %02x", b->asn_cptr[i]); + snprintf(errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), + " %02x", b->asn_cptr[i]); } syslog(LOG_ERR, "%s", errbuf); diff --git a/contrib/bsnmp/snmpd/snmpd.config b/contrib/bsnmp/snmpd/snmpd.config index 128b020132e7..3b2e2f578f61 100644 --- a/contrib/bsnmp/snmpd/snmpd.config +++ b/contrib/bsnmp/snmpd/snmpd.config @@ -30,7 +30,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# $Begemot: bsnmp/snmpd/snmpd.config,v 1.11 2002/12/11 15:54:08 hbb Exp $ +# $Begemot: bsnmp/snmpd/snmpd.config,v 1.12 2003/12/03 10:08:47 hbb Exp $ # # Example configuration file. # diff --git a/contrib/bsnmp/snmpd/snmpd.h b/contrib/bsnmp/snmpd/snmpd.h index 5c8e78f4a459..d8cf5a16c3e4 100644 --- a/contrib/bsnmp/snmpd/snmpd.h +++ b/contrib/bsnmp/snmpd/snmpd.h @@ -30,15 +30,24 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/snmpd.h,v 1.17 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/snmpd.h,v 1.23 2003/12/09 12:28:53 hbb Exp $ * * Private SNMPd data and functions. */ #include +#ifdef USE_LIBBEGEMOT +#include +#else #include +#endif #define PATH_SYSCONFIG "/etc:/usr/etc:/usr/local/etc" +#ifdef USE_LIBBEGEMOT +#define evTimerID int +#define evFileID int +#endif + /************************************************************* * * Communities @@ -140,43 +149,80 @@ void lm_start(struct lmodule *); * * SNMP ports */ -struct snmp_port { - u_int8_t addr[4];/* host byteorder */ - u_int16_t port; /* host byteorder */ +/* + * Common input stuff + */ +struct port_input { + int fd; /* socket */ + void *id; /* evSelect handle */ - int sock; /* the socket */ - void * id; /* evSelect handle */ + int stream : 1; /* stream socket */ + int cred : 1; /* want credentials */ - struct sockaddr_in ret; /* the return address */ - socklen_t retlen; /* length of that address */ + struct sockaddr *peer; /* last received packet */ + socklen_t peerlen; + int priv : 1; /* peer is privileged */ - TAILQ_ENTRY(snmp_port) link; - - struct asn_oid index; + u_char *buf; /* receive buffer */ + size_t buflen; /* buffer length */ + size_t length; /* received length */ + size_t consumed; /* how many bytes used */ }; -TAILQ_HEAD(snmp_port_list, snmp_port); -extern struct snmp_port_list snmp_port_list; -void close_snmp_port(struct snmp_port *); -int open_snmp_port(u_int8_t *, u_int32_t, struct snmp_port **); - -struct local_port { - char *name; /* unix path name */ - int sock; /* the socket */ - void *id; /* evSelect handle */ - - struct sockaddr_un ret; /* the return address */ - socklen_t retlen; /* length of that address */ - - TAILQ_ENTRY(local_port) link; - - struct asn_oid index; +struct tport { + struct asn_oid index; /* table index of this tp point */ + TAILQ_ENTRY(tport) link; /* table link */ + struct transport *transport; /* who handles this */ }; -TAILQ_HEAD(local_port_list, local_port); -extern struct local_port_list local_port_list; +TAILQ_HEAD(tport_list, tport); -void close_local_port(struct local_port *); -int open_local_port(u_char *, size_t, struct local_port **); +int snmpd_input(struct port_input *, struct tport *); +void snmpd_input_close(struct port_input *); + + +/* + * Transport domain + */ +#define TRANS_NAMELEN 64 + +struct transport_def { + const char *name; /* name of this transport */ + struct asn_oid id; /* OBJID of this transport */ + + int (*start)(void); + int (*stop)(int); + + void (*close_port)(struct tport *); + int (*init_port)(struct tport *); + + ssize_t (*send)(struct tport *, const u_char *, size_t, + const struct sockaddr *, size_t); +}; +struct transport { + struct asn_oid index; /* transport table index */ + TAILQ_ENTRY(transport) link; /* ... and link */ + u_int or_index; /* registration index */ + + struct tport_list table; /* list of open ports */ + + const struct transport_def *vtab; +}; + +TAILQ_HEAD(transport_list, transport); +extern struct transport_list transport_list; + +void trans_insert_port(struct transport *, struct tport *); +void trans_remove_port(struct tport *); +struct tport *trans_find_port(struct transport *, + const struct asn_oid *, u_int); +struct tport *trans_next_port(struct transport *, + const struct asn_oid *, u_int); +struct tport *trans_first_port(struct transport *); +struct tport *trans_iter_port(struct transport *, + int (*)(struct tport *, intptr_t), intptr_t); + +int trans_register(const struct transport_def *, struct transport **); +int trans_unregister(struct transport *); /************************************************************* * @@ -197,9 +243,16 @@ struct snmpd { /* source address for V1 traps */ u_char trap1addr[4]; + + /* version enable flags */ + uint32_t version_enable; }; extern struct snmpd snmpd; +#define VERS_ENABLE_V1 0x00000001 +#define VERS_ENABLE_V2C 0x00000002 +#define VERS_ENABLE_ALL 0x00000003 + /* * The debug group */ @@ -275,3 +328,6 @@ extern int32_t snmp_serial_no; int init_actvals(void); int read_config(const char *, struct lmodule *); int define_macro(const char *name, const char *value); + +#define LOG_ASN1_ERRORS 0x10000000 +#define LOG_SNMP_ERRORS 0x20000000 diff --git a/contrib/bsnmp/snmpd/snmpd.sh b/contrib/bsnmp/snmpd/snmpd.sh index 86ec962d0159..3cd6d51da7f0 100755 --- a/contrib/bsnmp/snmpd/snmpd.sh +++ b/contrib/bsnmp/snmpd/snmpd.sh @@ -31,7 +31,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# $Begemot: bsnmp/snmpd/snmpd.sh,v 1.1 2002/12/04 11:15:23 hbb Exp $ +# $Begemot: bsnmp/snmpd/snmpd.sh,v 1.2 2003/12/03 10:08:47 hbb Exp $ # # SNMPd startup script # diff --git a/contrib/bsnmp/snmpd/snmpmod.3 b/contrib/bsnmp/snmpd/snmpmod.3 index 143d12d2fab8..be0136c89402 100644 --- a/contrib/bsnmp/snmpd/snmpmod.3 +++ b/contrib/bsnmp/snmpd/snmpmod.3 @@ -30,7 +30,7 @@ .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Begemot: bsnmp/snmpd/snmpmod.3,v 1.3 2003/01/28 13:44:35 hbb Exp $ +.\" $Begemot: bsnmp/snmpd/snmpmod.3,v 1.5 2003/12/08 16:55:58 hbb Exp $ .\" .Dd August 16, 2002 .Dt snmpmod 3 @@ -166,7 +166,7 @@ Begemot SNMP library .Fn buf_size "int tx" .Ft enum snmpd_input_err .Fn snmp_input_start "const u_char *buf" "size_t len" "const char *source" \ - "struct snmp_pdu *pdu" "int32_t *ip" + "struct snmp_pdu *pdu" "int32_t *ip" "size_t *pdulen" .Ft enum snmpd_input_err .Fn snmp_input_finish "struct snmp_pdu *pdu" "const u_char *rcvbuf" \ "size_t rcvlen" "u_char *sndbuf" "size_t *sndlen" "const char *source" \ @@ -175,8 +175,8 @@ Begemot SNMP library .Fn snmp_output "struct snmp_pdu *pdu" "u_char *sndbuf" "size_t *sndlen" \ "const char *dest" .Ft void -.Fn snmp_send_port "const struct asn_oid *port" "struct snmp_pdu *pdu" \ - "const struct sockaddr *addr" "socklen_t addrlen" +.Fn snmp_send_port "void *trans" "const struct asn_oid *port" \ + "struct snmp_pdu *pdu" "const struct sockaddr *addr" "socklen_t addrlen" .Ft void .Fn snmp_send_trap "const struct asn_oid *oid" "..." .Ft int @@ -245,7 +245,7 @@ a global symbol This symbol should be a variable of type .Vt struct snmp_module : .Bd -literal -offset indent -typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *, +typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *, void *, const struct asn_oid *, const struct sockaddr *, socklen_t, enum snmpd_input_err, int32_t); @@ -657,6 +657,12 @@ A SET PDU had a value field in a binding with a value that is out of range for the given ASN.1 type. .It Er SNMPD_INPUT_VALBADENC A SET PDU had a value field in a binding with wrong ASN.1 encoding. +.It Er SNMPD_INPUT_TRUNC +The buffer appears to contain a valid begin of a PDU, but is too short. +For streaming transports this means that the caller must save what he +already has and trying to obtain more input and reissue this input to +the function. For datagram transports this means that part of the +datagram was lost and the input should be ignored. .El .Pp The function @@ -680,7 +686,7 @@ takes a PDU and encodes it. The function .Fn snmp_send_port takes a PDU, encodes it and sends it through the given port (identified by -the index in the port table) to the given address. +the transport and the index in the port table) to the given address. .Pp The function .Fn snmp_send_trap diff --git a/contrib/bsnmp/snmpd/snmpmod.h b/contrib/bsnmp/snmpd/snmpmod.h index 5e4cbbd32838..2f262415521a 100644 --- a/contrib/bsnmp/snmpd/snmpmod.h +++ b/contrib/bsnmp/snmpd/snmpmod.h @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.23 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.25 2003/12/08 16:55:58 hbb Exp $ * * SNMP daemon data and functions exported to modules. */ @@ -199,6 +199,8 @@ enum snmpd_input_err { SNMPD_INPUT_VALRANGE, /* value has bad encoding */ SNMPD_INPUT_VALBADENC, + /* need more data (truncated packet) */ + SNMPD_INPUT_TRUNC, }; /* @@ -228,9 +230,9 @@ struct snmp_module { void (*start)(void); /* proxy a PDU */ - enum snmpd_proxy_err (*proxy)(struct snmp_v1_pdu *, + enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *, const struct asn_oid *, const struct sockaddr *, socklen_t, - enum snmpd_input_err, int32_t); + enum snmpd_input_err, int32_t, int); /* the tree this module is going to server */ const struct snmp_node *tree; @@ -320,15 +322,15 @@ size_t buf_size(int tx); /* decode PDU and find community */ enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *, - struct snmp_v1_pdu *, int32_t *); + struct snmp_pdu *, int32_t *, size_t *); /* process the pdu. returns either _OK or _FAILED */ enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *, size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t, void *); -void snmp_output(struct snmp_v1_pdu *, u_char *, size_t *, const char *); -void snmp_send_port(const struct asn_oid *, struct snmp_v1_pdu *, +void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *); +void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *, const struct sockaddr *, socklen_t); /* sending traps */ diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c new file mode 100644 index 000000000000..1e0da59f4573 --- /dev/null +++ b/contrib/bsnmp/snmpd/trans_lsock.c @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_lsock.c,v 1.3 2003/12/09 12:28:53 hbb Exp $ + * + * Local domain socket transport + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "trans_lsock.h" +#include "tree.h" +#include "oid.h" + +static const struct asn_oid + oid_begemotSnmpdLocalPortTable = OIDX_begemotSnmpdLocalPortTable; + +static int lsock_start(void); +static int lsock_stop(int); +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); + +/* exported */ +const struct transport_def lsock_trans = { + "lsock", + OIDX_begemotSnmpdTransLsock, + lsock_start, + lsock_stop, + lsock_close_port, + lsock_init_port, + lsock_send +}; +static struct transport *my_trans; + +static int +lsock_remove(struct tport *tp, intptr_t arg __unused) +{ + struct lsock_port *port = (struct lsock_port *)tp; + + (void)remove(port->name); + + return (-1); +} + +static int +lsock_stop(int force) +{ + + if (my_trans != NULL) { + if (!force && trans_first_port(my_trans) != NULL) + return (SNMP_ERR_GENERR); + trans_iter_port(my_trans, lsock_remove, NULL); + return (trans_unregister(my_trans)); + } + return (SNMP_ERR_NOERROR); +} + +static int +lsock_start(void) +{ + return (trans_register(&lsock_trans, &my_trans)); +} + +/* + * Open a local port. If this is a datagram socket create also the + * one and only peer. + */ +static int +lsock_open_port(u_char *name, size_t namelen, struct lsock_port **pp, + int type) +{ + struct lsock_port *port; + struct lsock_peer *peer = NULL; + int is_stream, need_cred; + size_t u; + int err; + struct sockaddr_un sa; + + if (namelen == 0 || namelen + 1 > sizeof(sa.sun_path)) { + free(name); + return (SNMP_ERR_BADVALUE); + } + switch (type) { + case LOCP_DGRAM_UNPRIV: + is_stream = 0; + need_cred = 0; + break; + + case LOCP_DGRAM_PRIV: + is_stream = 0; + need_cred = 1; + break; + + case LOCP_STREAM_UNPRIV: + is_stream = 1; + need_cred = 0; + break; + + case LOCP_STREAM_PRIV: + is_stream = 1; + need_cred = 1; + break; + + default: + free(name); + return (SNMP_ERR_BADVALUE); + } + + if ((port = malloc(sizeof(*port))) == NULL) { + free(name); + return (SNMP_ERR_GENERR); + } + memset(port, 0, sizeof(*port)); + if (!is_stream) { + if ((peer = malloc(sizeof(*peer))) == NULL) { + free(name); + free(port); + return (SNMP_ERR_GENERR); + } + memset(peer, 0, sizeof(*peer)); + } + if ((port->name = malloc(namelen + 1)) == NULL) { + free(name); + free(port); + if (!is_stream) + free(peer); + return (SNMP_ERR_GENERR); + } + strncpy(port->name, name, namelen); + port->name[namelen] = '\0'; + + port->type = type; + port->str_sock = -1; + LIST_INIT(&port->peers); + + port->tport.index.len = namelen + 1; + port->tport.index.subs[0] = namelen; + for (u = 0; u < namelen; u++) + port->tport.index.subs[u + 1] = name[u]; + + if (peer != NULL) { + LIST_INSERT_HEAD(&port->peers, peer, link); + + peer->port = port; + + peer->input.fd = -1; + peer->input.id = NULL; + peer->input.stream = is_stream; + peer->input.cred = need_cred; + peer->input.peer = (struct sockaddr *)&peer->peer; + } + + trans_insert_port(my_trans, &port->tport); + + if (community != COMM_INITIALIZE && + (err = lsock_init_port(&port->tport)) != SNMP_ERR_NOERROR) { + lsock_close_port(&port->tport); + return (err); + } + + *pp = port; + + return (SNMP_ERR_NOERROR); +} + +/* + * Close a local domain peer + */ +static void +lsock_peer_close(struct lsock_peer *peer) +{ + + LIST_REMOVE(peer, link); + snmpd_input_close(&peer->input); + free(peer); +} + +/* + * Close a local port + */ +static void +lsock_close_port(struct tport *tp) +{ + struct lsock_port *port = (struct lsock_port *)tp; + struct lsock_peer *peer; + + if (port->str_id != NULL) + fd_deselect(port->str_id); + if (port->str_sock >= 0) + (void)close(port->str_sock); + (void)remove(port->name); + + trans_remove_port(tp); + + while ((peer = LIST_FIRST(&port->peers)) != NULL) + lsock_peer_close(peer); + + free(port->name); + free(port); +} + +/* + * Input on a local socket (either datagram or stream) + */ +static void +lsock_input(int fd __unused, void *udata) +{ + struct lsock_peer *peer = udata; + struct lsock_port *p = peer->port; + + peer->input.peerlen = sizeof(peer->peer); + if (snmpd_input(&peer->input, &p->tport) == -1 && peer->input.stream) + /* framing or other input error */ + lsock_peer_close(peer); +} + +/* + * A UNIX domain listening socket is ready. This means we have a peer + * that we need to accept + */ +static void +lsock_listen_input(int fd, void *udata) +{ + struct lsock_port *p = udata; + struct lsock_peer *peer; + + if ((peer = malloc(sizeof(*peer))) == NULL) { + syslog(LOG_WARNING, "%s: peer malloc failed", p->name); + (void)close(accept(fd, NULL, NULL)); + return; + } + memset(peer, 0, sizeof(*peer)); + + peer->port = p; + + peer->input.stream = 1; + peer->input.cred = (p->type == LOCP_DGRAM_PRIV || + p->type == LOCP_STREAM_PRIV); + peer->input.peerlen = sizeof(peer->peer); + peer->input.peer = (struct sockaddr *)&peer->peer; + + peer->input.fd = accept(fd, peer->input.peer, &peer->input.peerlen); + if (peer->input.fd == -1) { + syslog(LOG_WARNING, "%s: accept failed: %m", p->name); + free(peer); + return; + } + + if ((peer->input.id = fd_select(peer->input.fd, lsock_input, + peer, NULL)) == NULL) { + close(peer->input.fd); + free(peer); + return; + } + + LIST_INSERT_HEAD(&p->peers, peer, link); +} + +/* + * Create a local socket + */ +static int +lsock_init_port(struct tport *tp) +{ + struct lsock_port *p = (struct lsock_port *)tp; + struct sockaddr_un sa; + + if (p->type == LOCP_STREAM_PRIV || p->type == LOCP_STREAM_UNPRIV) { + if ((p->str_sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "creating local socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + strcpy(sa.sun_path, p->name); + sa.sun_family = AF_LOCAL; + sa.sun_len = strlen(p->name) + + offsetof(struct sockaddr_un, sun_path); + + (void)remove(p->name); + + if (bind(p->str_sock, (struct sockaddr *)&sa, sizeof(sa))) { + if (errno == EADDRNOTAVAIL) { + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s %m", p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + if (chmod(p->name, 0666) == -1) + syslog(LOG_WARNING, "chmod(%s,0666): %m", p->name); + + if (listen(p->str_sock, 10) == -1) { + syslog(LOG_ERR, "listen: %s %m", p->name); + (void)remove(p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + + p->str_id = fd_select(p->str_sock, lsock_listen_input, p, NULL); + if (p->str_id == NULL) { + (void)remove(p->name); + close(p->str_sock); + p->str_sock = -1; + return (SNMP_ERR_GENERR); + } + } else { + struct lsock_peer *peer; + + peer = LIST_FIRST(&p->peers); + + if ((peer->input.fd = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "creating local socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + + strcpy(sa.sun_path, p->name); + sa.sun_family = AF_LOCAL; + sa.sun_len = strlen(p->name) + + offsetof(struct sockaddr_un, sun_path); + + (void)remove(p->name); + + if (bind(peer->input.fd, (struct sockaddr *)&sa, sizeof(sa))) { + if (errno == EADDRNOTAVAIL) { + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s %m", p->name); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + if (chmod(p->name, 0666) == -1) + syslog(LOG_WARNING, "chmod(%s,0666): %m", p->name); + + peer->input.id = fd_select(peer->input.fd, lsock_input, + peer, NULL); + if (peer->input.id == NULL) { + (void)remove(p->name); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + } + return (SNMP_ERR_NOERROR); +} + +/* + * Send something + */ +static ssize_t +lsock_send(struct tport *tp, const u_char *buf, size_t len, + const struct sockaddr *addr, size_t addrlen) +{ + struct lsock_port *p = (struct lsock_port *)tp; + struct lsock_peer *peer; + + if (p->type == LOCP_DGRAM_PRIV || p->type == LOCP_DGRAM_UNPRIV) { + peer = LIST_FIRST(&p->peers); + + } else { + /* search for the peer */ + LIST_FOREACH(peer, &p->peers, link) + if (peer->input.peerlen == addrlen && + memcmp(peer->input.peer, addr, addrlen) == 0) + break; + if (peer == NULL) { + errno = ENOTCONN; + return (-1); + } + } + + return (sendto(peer->input.fd, buf, len, 0, addr, addrlen)); +} + +/* + * Dependency to create a lsock port + */ +struct lsock_dep { + struct snmp_dependency dep; + + /* index (path name) */ + u_char *path; + size_t pathlen; + + /* the port */ + struct lsock_port *port; + + /* which of the fields are set */ + u_int set; + + /* type of the port */ + int type; + + /* status */ + int status; +}; +#define LD_TYPE 0x01 +#define LD_STATUS 0x02 +#define LD_CREATE 0x04 /* rollback create */ + +/* + * Finish handler for deleting a port - this cannot fail :-) + */ +static void +lsock_del(struct snmp_context *ctx __unused, int fail, void *arg) +{ + struct lsock_dep *ld = (struct lsock_dep *)(void *)arg; + + if (!fail) + lsock_close_port(&ld->port->tport); +} + +/* + * dependency handler for lsock ports + */ +static int +lsock_func(struct snmp_context *ctx, struct snmp_dependency *dep, + enum snmp_depop op) +{ + struct lsock_dep *ld = (struct lsock_dep *)(void *)dep; + int err = SNMP_ERR_NOERROR; + + switch (op) { + + case SNMP_DEPOP_COMMIT: + if (!(ld->set & LD_STATUS)) + err = SNMP_ERR_BADVALUE; + else if (ld->port == NULL) { + if (!ld->status) + err = SNMP_ERR_BADVALUE; + + else { + /* create */ + err = lsock_open_port(ld->path, ld->pathlen, + &ld->port, ld->type); + if (err == SNMP_ERR_NOERROR) + ld->set |= LD_CREATE; + } + } else if (!ld->status) { + /* delete - hard to roll back so defer to + * finish handler */ + if (snmp_set_atfinish(ctx, lsock_del, ld->port)) + err = SNMP_ERR_RES_UNAVAIL; + } else + /* modify - read-only */ + err = SNMP_ERR_READONLY; + + free(ld->path); + ld->path = NULL; + return (err); + + case SNMP_DEPOP_ROLLBACK: + if (ld->set & LD_CREATE) { + /* was create */ + lsock_close_port(&ld->port->tport); + } + return (SNMP_ERR_NOERROR); + } + abort(); +} + +/* + * Local port table + */ +int +op_lsock_port(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub-1]; + struct lsock_port *p; + u_char *name; + size_t namelen; + struct lsock_dep *ld; + struct asn_oid didx; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((p = (struct lsock_port *)trans_next_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &p->tport.index); + break; + + case SNMP_OP_GET: + if ((p = (struct lsock_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + p = (struct lsock_port *)trans_find_port(my_trans, + &value->var, sub); + + if (index_decode(&value->var, sub, iidx, &name, &namelen)) + return (SNMP_ERR_NO_CREATION); + + asn_slice_oid(&didx, &value->var, sub, value->var.len); + if ((ld = (struct lsock_dep *)(void *)snmp_dep_lookup(ctx, + &oid_begemotSnmpdLocalPortTable, &didx, sizeof(*ld), + lsock_func)) == NULL) { + free(name); + return (SNMP_ERR_GENERR); + } + + if (ld->path == NULL) { + ld->path = name; + ld->pathlen = namelen; + } else { + free(name); + } + ld->port = p; + + switch (which) { + + case LEAF_begemotSnmpdLocalPortStatus: + if (ld->set & LD_STATUS) + return (SNMP_ERR_INCONS_VALUE); + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + + ld->status = TRUTH_GET(value->v.integer); + ld->set |= LD_STATUS; + break; + + case LEAF_begemotSnmpdLocalPortType: + if (ld->set & LD_TYPE) + return (SNMP_ERR_INCONS_VALUE); + if (value->v.integer < 1 || value->v.integer > 4) + return (SNMP_ERR_WRONG_VALUE); + + ld->type = value->v.integer; + ld->set |= LD_TYPE; + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here to fetch the value + */ + switch (which) { + + case LEAF_begemotSnmpdLocalPortStatus: + value->v.integer = 1; + break; + + case LEAF_begemotSnmpdLocalPortType: + value->v.integer = p->type; + break; + + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} diff --git a/contrib/bsnmp/snmpd/trans_lsock.h b/contrib/bsnmp/snmpd/trans_lsock.h new file mode 100644 index 000000000000..d32964c45ac7 --- /dev/null +++ b/contrib/bsnmp/snmpd/trans_lsock.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_lsock.h,v 1.2 2003/12/09 12:28:53 hbb Exp $ + * + * Local domain socket transport + */ + +enum locp { + LOCP_DGRAM_UNPRIV = 1, + LOCP_DGRAM_PRIV = 2, + LOCP_STREAM_UNPRIV = 3, + LOCP_STREAM_PRIV = 4, +}; +struct lsock_peer { + LIST_ENTRY(lsock_peer) link; + struct port_input input; + struct sockaddr_un peer; + struct lsock_port *port; /* parent port */ +}; + +struct lsock_port { + struct tport tport; /* must begin with this */ + + char *name; /* unix path name */ + enum locp type; /* type of port */ + + int str_sock; /* stream socket */ + void *str_id; /* select handle */ + + LIST_HEAD(, lsock_peer) peers; +}; + +extern const struct transport_def lsock_trans; diff --git a/contrib/bsnmp/snmpd/trans_udp.c b/contrib/bsnmp/snmpd/trans_udp.c new file mode 100644 index 000000000000..c55c4e1b5a30 --- /dev/null +++ b/contrib/bsnmp/snmpd/trans_udp.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_udp.c,v 1.3 2003/12/09 12:28:53 hbb Exp $ + * + * UDP transport + */ +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "snmpmod.h" +#include "snmpd.h" +#include "trans_udp.h" +#include "tree.h" +#include "oid.h" + +static int udp_start(void); +static int udp_stop(int); +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); + +/* exported */ +const struct transport_def udp_trans = { + "udp", + OIDX_begemotSnmpdTransUdp, + udp_start, + udp_stop, + udp_close_port, + udp_init_port, + udp_send +}; +static struct transport *my_trans; + +static int +udp_start(void) +{ + return (trans_register(&udp_trans, &my_trans)); +} + +static int +udp_stop(int force __unused) +{ + if (my_trans != NULL) + if (trans_unregister(my_trans) != 0) + return (SNMP_ERR_GENERR); + return (SNMP_ERR_NOERROR); +} + +/* + * A UDP port is ready + */ +static void +udp_input(int fd __unused, void *udata) +{ + struct udp_port *p = udata; + + p->input.peerlen = sizeof(p->ret); + snmpd_input(&p->input, &p->tport); +} + +/* + * Create a UDP socket and bind it to the given port + */ +static int +udp_init_port(struct tport *tp) +{ + struct udp_port *p = (struct udp_port *)tp; + struct sockaddr_in addr; + u_int32_t ip; + + if ((p->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "creating UDP socket: %m"); + return (SNMP_ERR_RES_UNAVAIL); + } + ip = (p->addr[0] << 24) | (p->addr[1] << 16) | (p->addr[2] << 8) | + p->addr[3]; + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(ip); + addr.sin_port = htons(p->port); + addr.sin_family = AF_INET; + addr.sin_len = sizeof(addr); + if (bind(p->input.fd, (struct sockaddr *)&addr, sizeof(addr))) { + if (errno == EADDRNOTAVAIL) { + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_INCONS_NAME); + } + syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(addr.sin_addr), + p->port); + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + if ((p->input.id = fd_select(p->input.fd, udp_input, + p, NULL)) == NULL) { + close(p->input.fd); + p->input.fd = -1; + return (SNMP_ERR_GENERR); + } + return (SNMP_ERR_NOERROR); +} + +/* + * Create a new SNMP Port object and start it, if we are not + * in initialisation mode. The arguments are in host byte order. + */ +static int +udp_open_port(u_int8_t *addr, u_int32_t udp_port, struct udp_port **pp) +{ + struct udp_port *port; + int err; + + if (udp_port > 0xffff) + return (SNMP_ERR_NO_CREATION); + if ((port = malloc(sizeof(*port))) == NULL) + return (SNMP_ERR_GENERR); + memset(port, 0, sizeof(*port)); + + /* initialize common part */ + port->tport.index.len = 5; + port->tport.index.subs[0] = addr[0]; + port->tport.index.subs[1] = addr[1]; + port->tport.index.subs[2] = addr[2]; + port->tport.index.subs[3] = addr[3]; + port->tport.index.subs[4] = udp_port; + + port->addr[0] = addr[0]; + port->addr[1] = addr[1]; + port->addr[2] = addr[2]; + port->addr[3] = addr[3]; + port->port = udp_port; + + port->input.fd = -1; + port->input.id = NULL; + port->input.stream = 0; + port->input.cred = 0; + port->input.peer = (struct sockaddr *)&port->ret; + port->input.peerlen = sizeof(port->ret); + + trans_insert_port(my_trans, &port->tport); + + if (community != COMM_INITIALIZE && + (err = udp_init_port(&port->tport)) != SNMP_ERR_NOERROR) { + udp_close_port(&port->tport); + return (err); + } + *pp = port; + return (SNMP_ERR_NOERROR); +} + +/* + * Close an SNMP port + */ +static void +udp_close_port(struct tport *tp) +{ + struct udp_port *port = (struct udp_port *)tp; + + snmpd_input_close(&port->input); + trans_remove_port(tp); + free(port); +} + +/* + * Send something + */ +static ssize_t +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; + + return (sendto(p->input.fd, buf, len, 0, addr, addrlen)); +} + +/* + * Port table + */ +int +op_snmp_port(struct snmp_context *ctx, struct snmp_value *value, + u_int sub, u_int iidx, enum snmp_op op) +{ + asn_subid_t which = value->var.subs[sub-1]; + struct udp_port *p; + u_int8_t addr[4]; + u_int32_t port; + + switch (op) { + + case SNMP_OP_GETNEXT: + if ((p = (struct udp_port *)trans_next_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &p->tport.index); + break; + + case SNMP_OP_GET: + if ((p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + ctx->scratch->int1 = (p != NULL); + + if (which != LEAF_begemotSnmpdPortStatus) + abort(); + if (!TRUTH_OK(value->v.integer)) + return (SNMP_ERR_WRONG_VALUE); + + ctx->scratch->int2 = TRUTH_GET(value->v.integer); + + if (ctx->scratch->int2) { + /* open an SNMP port */ + if (p != NULL) + /* already open - do nothing */ + return (SNMP_ERR_NOERROR); + + if (index_decode(&value->var, sub, iidx, addr, &port)) + return (SNMP_ERR_NO_CREATION); + return (udp_open_port(addr, port, &p)); + + } else { + /* close SNMP port - do in commit */ + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_ROLLBACK: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + if (ctx->scratch->int1 == 0) { + /* did not exist */ + if (ctx->scratch->int2 == 1) { + /* created */ + if (p != NULL) + udp_close_port(&p->tport); + } + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + p = (struct udp_port *)trans_find_port(my_trans, + &value->var, sub); + if (ctx->scratch->int1 == 1) { + /* did exist */ + if (ctx->scratch->int2 == 0) { + /* delete */ + if (p != NULL) + udp_close_port(&p->tport); + } + } + return (SNMP_ERR_NOERROR); + + default: + abort(); + } + + /* + * Come here to fetch the value + */ + switch (which) { + + case LEAF_begemotSnmpdPortStatus: + value->v.integer = 1; + break; + + default: + abort(); + } + + return (SNMP_ERR_NOERROR); +} diff --git a/contrib/bsnmp/snmpd/trans_udp.h b/contrib/bsnmp/snmpd/trans_udp.h new file mode 100644 index 000000000000..0731882dbfb7 --- /dev/null +++ b/contrib/bsnmp/snmpd/trans_udp.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: bsnmp/snmpd/trans_udp.h,v 1.2 2003/12/09 12:28:53 hbb Exp $ + * + * UDP transport + */ +struct udp_port { + struct tport tport; /* must begin with this */ + + uint8_t addr[4]; /* host byteorder */ + uint16_t port; /* host byteorder */ + + struct port_input input; /* common input stuff */ + + struct sockaddr_in ret; /* the return address */ +}; + +/* argument for open call */ +struct udp_open { + uint8_t addr[4]; /* host byteorder */ + uint16_t port; /* host byteorder */ +}; + +extern const struct transport_def udp_trans; diff --git a/contrib/bsnmp/snmpd/trap.c b/contrib/bsnmp/snmpd/trap.c index 4853ea9d2160..2dd6b82b90b6 100644 --- a/contrib/bsnmp/snmpd/trap.c +++ b/contrib/bsnmp/snmpd/trap.c @@ -30,7 +30,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Begemot: bsnmp/snmpd/trap.c,v 1.5 2003/01/28 13:44:35 hbb Exp $ + * $Begemot: bsnmp/snmpd/trap.c,v 1.6 2003/12/03 10:08:47 hbb Exp $ * * TrapSinkTable */ diff --git a/contrib/bsnmp/snmpd/tree.def b/contrib/bsnmp/snmpd/tree.def index 355a5a006d37..9fec0c9cb23d 100644 --- a/contrib/bsnmp/snmpd/tree.def +++ b/contrib/bsnmp/snmpd/tree.def @@ -30,7 +30,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# $Begemot: bsnmp/snmpd/tree.def,v 1.34 2002/12/11 15:54:08 hbb Exp $ +# $Begemot: bsnmp/snmpd/tree.def,v 1.37 2003/12/09 12:28:53 hbb Exp $ # # System group and private Begemot SNMPd MIB. # @@ -90,6 +90,7 @@ (2 begemotSnmpdReceiveBuffer INTEGER op_snmpd_config GET SET) (3 begemotSnmpdCommunityDisable INTEGER op_snmpd_config GET SET) (4 begemotSnmpdTrap1Addr IPADDRESS op_snmpd_config GET SET) + (5 begemotSnmpdVersionEnable UNSIGNED32 op_snmpd_config GET SET) ) (2 begemotTrapSinkTable (1 begemotTrapSinkEntry : IPADDRESS INTEGER op_trapsink @@ -148,10 +149,22 @@ # Local (UNIX domain) port table # (9 begemotSnmpdLocalPortTable - (1 begemotSnmpdLocalPortEntry : OCTETSTRING op_local_port + (1 begemotSnmpdLocalPortEntry : OCTETSTRING op_lsock_port (1 begemotSnmpdLocalPortPath OCTETSTRING) (2 begemotSnmpdLocalPortStatus INTEGER GET SET) + (3 begemotSnmpdLocalPortType INTEGER GET SET) )) + + (10 begemotSnmpdTransportMappings + (1 begemotSnmpdTransportTable + (1 begemotSnmpdTransportEntry : OCTETSTRING op_transport_table + (1 begemotSnmpdTransportName OCTETSTRING) + (2 begemotSnmpdTransportStatus INTEGER GET) + (3 begemotSnmpdTransportOid OID GET) + )) + (2 begemotSnmpdTransUdp OID op_transport_dummy) + (3 begemotSnmpdTransLsock OID op_transport_dummy) + ) ) (2 begemotSnmpdDefs (1 begemotSnmpdAgent