Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Dec 2010 14:30:25 +0000 (UTC)
From:      Shteryana Shopova <syrinx@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r216295 - in head/usr.sbin/bsnmpd: . tools tools/bsnmptools tools/libbsnmptools
Message-ID:  <201012081430.oB8EUP8J006067@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: syrinx
Date: Wed Dec  8 14:30:25 2010
New Revision: 216295
URL: http://svn.freebsd.org/changeset/base/216295

Log:
  Add bsnmpd(1)'s SNMP client tools (including SNMPv3 support) to the base system.
  
  Sponsored by:   The FreeBSD Foundation (the SNMPv3 bits), Google Summer of Code 2005
  Reviewed by:    philip@ (mostly), bz@ (earlier version based on p4 ch124545)
  Approved by:    philip@

Added:
  head/usr.sbin/bsnmpd/tools/
  head/usr.sbin/bsnmpd/tools/Makefile   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/Makefile.inc   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/bsnmptools/
  head/usr.sbin/bsnmpd/tools/bsnmptools/Makefile   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/
  head/usr.sbin/bsnmpd/tools/libbsnmptools/Makefile   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmpimport.c   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmpmap.c   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptc.c   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptc.h   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c   (contents, props changed)
  head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.h   (contents, props changed)
Modified:
  head/usr.sbin/bsnmpd/Makefile

Modified: head/usr.sbin/bsnmpd/Makefile
==============================================================================
--- head/usr.sbin/bsnmpd/Makefile	Wed Dec  8 13:51:38 2010	(r216294)
+++ head/usr.sbin/bsnmpd/Makefile	Wed Dec  8 14:30:25 2010	(r216295)
@@ -2,6 +2,7 @@
 
 SUBDIR=	gensnmptree	\
 	bsnmpd		\
-	modules
+	modules		\
+	tools
 
 .include <bsd.subdir.mk>

Added: head/usr.sbin/bsnmpd/tools/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsnmpd/tools/Makefile	Wed Dec  8 14:30:25 2010	(r216295)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+# Author: Shteryana Shopova <syrinx@FreeBSD.org>
+
+SUBDIR=	libbsnmptools \
+	bsnmptools
+
+.include <bsd.subdir.mk>

Added: head/usr.sbin/bsnmpd/tools/Makefile.inc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsnmpd/tools/Makefile.inc	Wed Dec  8 14:30:25 2010	(r216295)
@@ -0,0 +1,13 @@
+# $FreeBSD$
+# Author: Shteryana Shopova <syrinx@FreeBSD.org>
+
+BINDIR?= /usr/bin
+
+CFLAGS+= -I. -I${.CURDIR}
+
+.if exists(${.OBJDIR}/../libbsnmptools)
+LIBBSNMPTOOLSDIR=      ${.OBJDIR}/../libbsnmptools
+.else
+LIBBSNMPTOOLSDIR=      ${.CURDIR}/../libbsnmptools
+.endif
+LIBBSNMPTOOLS=         ${LIBBSNMPTOOLSDIR}/libbsnmptools.a

Added: head/usr.sbin/bsnmpd/tools/bsnmptools/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsnmpd/tools/bsnmptools/Makefile	Wed Dec  8 14:30:25 2010	(r216295)
@@ -0,0 +1,28 @@
+# $FreeBSD$
+# Author: Shteryana Shopova <syrinx@FreeBSD.org>
+
+.include <bsd.own.mk>
+
+.PATH: ${.CURDIR}
+
+PROG=	bsnmpget
+
+DPADD+=	${LIBBSNMP} ${LIBBSNMPTOOLS}
+LDADD+=	-lbsnmp -lbsnmptools
+CFLAGS+=	-I${.CURDIR}/../libbsnmptools
+LDFLAGS+=	-L${LIBBSNMPTOOLSDIR}
+
+.if ${MK_OPENSSL} != "no"
+DPADD+= ${LIBCRYPTO}
+LDADD+= -lcrypto
+.endif
+
+LINKS=  ${DESTDIR}/usr/bin/bsnmpget ${DESTDIR}/usr/bin/bsnmpwalk
+LINKS+=  ${DESTDIR}/usr/bin/bsnmpget ${DESTDIR}/usr/bin/bsnmpset
+
+MAN=	bsnmpget.1
+
+MLINKS=		bsnmpget.1 bsnmpwalk.1
+MLINKS+=	bsnmpget.1 bsnmpset.1
+
+.include <bsd.prog.mk>

Added: head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1	Wed Dec  8 14:30:25 2010	(r216295)
@@ -0,0 +1,401 @@
+.\"
+.\" Copyright (c) 2010 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" Portions of this documentation were written by Shteryana Sotirova Shopova
+.\" under sponsorship from the FreeBSD Foundation.
+.\"
+.\" Copyright (c) 2005-2007 The FreeBSD Project.
+.\"	All rights reserved.
+.\"
+.\" Author: Shteryana Shopova <syrinx@FreeBSD.org>
+.\"
+.\" Redistribution 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 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND 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 AUTHOR OR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 17, 2007
+.Dt BSNMPGET 1
+.Os
+.Sh NAME
+.Nm bsnmpget ,
+.Nm bsnmpwalk ,
+.Nm bsnmpset
+.Nd "simple tools for querying SNMP agents"
+.Sh SYNOPSIS
+.Nm
+.Op Fl aDdehnK
+.Op Fl A Ar options
+.Op Fl b Ar buffersize
+.Op Fl C Ar options
+.Op Fl I Ar options
+.Op Fl i Ar filelist
+.Op Fl l Ar filename
+.Op Fl M Ar max-repetitions
+.Op Fl N Ar non-repeaters
+.Op Fl o Ar output
+.Op Fl P Ar options
+.Op Fl p Ar pdu
+.Op Fl r Ar retries
+.Op Fl s Ar [trans::][community@][server][:port]
+.Op Fl t Ar timeout
+.Op Fl U Ar options
+.Op Fl v Ar version
+.Op Ar OID ...
+.Pp
+.Nm bsnmpwalk
+.Op Fl dhnK
+.Op Fl A Ar options
+.Op Fl b Ar buffersize
+.Op Fl C Ar options
+.Op Fl I Ar options
+.Op Fl i Ar filelist
+.Op Fl l Ar filename
+.Op Fl o Ar output
+.Op Fl P Ar options
+.Op Fl r Ar retries
+.Op Fl s Ar [trans::][community@][server][:port]
+.Op Fl t Ar timeout
+.Op Fl U Ar options
+.Op Fl v Ar version
+.Op Ar OID ...
+.Pp
+.Nm bsnmpset
+.Op Fl adehnK
+.Op Fl A Ar options
+.Op Fl b Ar buffersize
+.Op Fl C Ar options
+.Op Fl I Ar options
+.Op Fl i Ar filelist
+.Op Fl l Ar filename
+.Op Fl o Ar output
+.Op Fl P Ar options
+.Op Fl r Ar retries
+.Op Fl s Ar [trans::][community@][server][:port]
+.Op Fl t Ar timeout
+.Op Fl U Ar options
+.Op Fl v Ar version
+.Ar OID Ns = Ar syntax Ns : Ns Ar value
+.Op Ar OID Ns = Ar syntax Ns : Ns Ar value ...
+.Sh DESCRIPTION
+.Nm ,
+.Nm bsnmpwalk
+and
+.Nm bsnmpset
+are simple tools for retrieving management information from and setting
+management information to a Simple Network Managment Protocol (SNMP) agent.
+.Pp
+Depending on the options
+.Nm bsnmpget
+constructs either a SMNP GetRequest, GetNextRequest
+or a GetBulkRequest packet, fills in the object identifiers (OIDs) of the
+objects whose values will be retrived, waits for a response and prints it if
+received successfully.
+.Pp
+.Nm Bsnmpwalk
+queries an agent with SMNP GetNextRequest packets,
+asking for values of OID instances that are a part of the object subtree
+rooted at the provided OIDs.
+.Pp
+.Nm Bsnmpset
+constructs a SMNP SetRequest packet, fills in the OIDs (object identifiers),
+syntaxes and values of the objects whose values are to be set and waits for a
+responce from server.
+.Sh OPTIONS
+.Pp
+The options are as follows (not all apply to all three programs):
+.Bl -tag -width ".It Fl D Ar options"
+.It Fl A Ar options
+Authentication options to use with SNMPv3 PDUs
+.Bl -tag -width
+.It Cm proto=[md5|sha]
+The protocol to use when calculating the PDU message digest.
+.It Cm key=authkey
+A binary localized authentication key to use when calculating the PDU message
+digest.
+.El
+.Pp
+By default SNMPv3 PDUs are sent unauthenticated.
+.It Fl a
+Skip any sanity checks when adding OIDs to a Protocol Data Unit (PDU):
+ingore syntax/access type, allow adding of non-leaf objects for GetPdu and
+read-only objects to a SetPDU.
+.It Fl b Ar buffersize
+Tune the size of buffers used to send and receive packets.
+The default size is 10000 bytes which should be enough unless an agent sends
+a really large octetstring.
+The maximum allowed length is 65535 according to the Structure of Management
+Information (SMIv2).
+.It Fl C Ar options
+The context to query with SNMPv3 PDUs.
+.Bl -tag -width
+.It Cm context=name
+The context name. Default is "" (empty).
+.It Cm context-engine=engine-id
+The SNMP Engine ID of the context to query with SNMPv3 PDUs, represented as
+binary octet string. By default, this is set to the Engine ID of the SNMP agent.
+.El
+.It Fl D
+Perform SNMP USM Engine Discovery, rather than sending a request for the value
+of a specific object.
+.It Fl d
+Turn on debugging.
+This option will cause the packets sent and received to be dumped to the
+terminal.
+.It Fl e
+Retry on error.
+If an error is returned in the response PDU, resend the request removing the
+variable that caused the error until a valid response is received.
+This is only usefull for a GetRequest- and a GetNextRequest-PDU.
+.It Fl h
+Print a short help text with default values for various options.
+.It Fl I Ar options
+Load each MIB description file from the given list to translate symbolic
+object names to their numerical representation and vice versa.
+Use the other options to obtain a non-default behaviour:
+.Bl -tag -width
+.It Cm cut=OID
+Specifies the initial OID that was cut by
+.Xr gensnmpdef 1
+when producing the MIB description file.
+The default value is .iso(1).org(3).dod(6) which is what should have been
+used for all the files installed under /usr/share/snmp/defs/ .
+Use this only if you generated your own files, providing a '-c' option to
+.Xr gensnmpdef 1 .
+.It Cm path=filedir
+The directory where files in the list will be searched.
+The default is
+.Pa /usr/share/snmp/defs/ .
+.It Cm file=filelist
+A comma separated list of files to which the two options above will apply.
+.El
+.Pp
+The file suboption has to come after the other suboptions so that their
+non-default values will be applied to the list of files.
+The order of the other suboptions before each file suboption can be random.
+Suboptions may be separated either by commas or by spaces.
+If using spaces make sure the entire option string is one argument, for
+example using quotes.
+.It Fl i Ar filelist
+List of MIB description files produced by
+.Xr gensnmpdef 1 which
+.Nm bsnmpget ,
+.Nm bsnmpwalk
+or
+.Nm bsnmpset
+will search to translate numerical OIDs to their symbolic object names.
+Multiple files can be provided either giving this option multiple times
+or a comma separated list of file names.
+If a filename begins with a letter the default directory,
+/usr/share/snmp/defs/ ,
+will be searched.
+.It Fl K
+Calculate and display the localized authentication and privacy keys
+corresponding to a plain text password. The password is obtain via the
+environment. Additionally, if one or more OIDs are specified, the calculated
+keys are used when processing the SNMPv3 requests.
+.It Fl l Ar filename
+The path of the posix local (unix domain) socket if local
+transport is used.
+.It Fl M Ar max-repetitions
+The value for the max-repetitions field in a GetBulk PDU.
+Default is 1.
+.It Fl N Ar non-repeaters
+The value for the non-repeaters field in a GetBulk PDU.
+Default is 0.
+.It Fl n
+Only use numerical representations for input and output OIDs and do not
+try to resolve symbolic object names.
+Note that
+.Nm bsnmpget ,
+.Nm bsnmpwalk
+and
+.Nm bsnmpset
+will print numerical OIDs anyway if the corresponding string representation
+is not found in the MIB description files.
+.It Fl o Ar [quiet|short|verbose]
+The format used to print the received response.
+Quiet only prints values, short (default) prints an abbreviated OID
+representation and the value.
+In addition to the short output verbose prints the type before the value.
+.It Fl P Ar options
+Privacy options to use with SNMPv3 PDUs
+.Bl -tag -width
+.It Cm proto=[aes|des]
+The protocol to use when encypting/decrypting SNMPv3 PDU data.
+.It Cm key=privkey
+A binary localized privacy key to use when encypting/decrypting SNMPv3 PDU data.
+.El
+.Pp
+By default plain text SNMPv3 PDUs are sent.
+.It Fl p Ar [get|getnext|getbulk]
+The PDU type to send by
+.Nm bsmpget .
+Default is get.
+.It Fl r Ar retries
+Number of resends of request packets before giving up if the agent does
+not respond after the first try.
+Default is 3.
+.It Fl s Ar [trans::] Ns Ar [community@] Ns Ar [server] Ns Ar [:port]
+Each of the server specification components is optional but at least one
+has to be provided if '-s' option is used.
+The server specification is constructed in the following manner:
+.Bl -tag -width
+.It Cm trans::
+Transport type may be one of udp, stream or dgram.
+If this option is not provided an udp inet/inet6 socket will be used, which
+is the most common.
+Stream stands for a posix local stream socket and a posix local datagram
+socket will be used if dgram is specified.
+.It Cm community@
+Specify an SNMP community string to be used when sending packets.
+If the option is skipped the default "public" will be used for
+.Nm
+and
+.Nm bsnmpwalk
+and the default "private" community string will be used for
+.Nm bsnmpset .
+.It Cm server
+This might be either the IP address or the hostname where the agent is
+listening.
+The default is 'localhost'.
+.It Cm port
+The destination port to send the requests to.
+This is useful if the SNMP agent listens on a non-default port.
+Default is given by the 'snmp' entry in /etc/services, port 161.
+.El
+.It Fl t Ar timeout
+Number of seconds before resending a request packet if the agent does
+not respond.
+The default value is 3 seconds.
+.It Fl U Ar options
+User credentials when sending SNMPv3 PDUs.
+.Bl -tag -width
+.It Cm engine=id
+The Engine ID of the SNMP agent represented as a binary octet string.
+.It Cm engine-boots=value
+The value of the snmpEngineBoots of the SNMP agent.
+.It Cm engine-time=value
+The value of the snmpEngineTime of the SNMP agent.
+.Pp
+If any of the above is not specified, SNMP USM Engine Discovery is attempted.
+This is also the default behavior.
+.It Cm name=username
+The USM user name to include in the SNMPv3 PDUs. By default, the user name is
+obtain via the environment
+.El
+.It Fl v Ar version
+The SNMP protocol version to use when sending requests. SNMP versions 1, 2 and
+3 are supported.
+If no version option is provided
+.Nm bsnmpget ,
+.Nm bsnmpwalk
+and
+.Nm bsnmpset
+will use version 2.
+Note that GetBulkRequest-PDUs were introduced in SNMPv2 thus setting the
+version to 1 is incompatiable with sending a GetBulk PDU.
+.It OID
+The object identifier whose value to retrive.
+At least one OID should be provided for
+.Nm bsnmpget
+to be able to send a request.
+.Pp
+For
+.Nm bsnmpwalk
+this is the root object identifier of the subtree whose values are to be
+retrived.
+If no OID is provided
+.Nm bsnmpwalk
+will walk the mib2 subtree rooted
+at .iso(1).org(3).dod(6).internet(1).mgmt(2).mib2(1) .
+.Pp
+Any of the formats used to print a single variable
+is valid as input OID:
+.Bl -tag -width
+.It 1.3.6.1.2.1.25.1.1.0
+.It sysDescr
+.It ifPhysAddress.1
+.It ifRcvAddressStatus.2.6.255.255.255.255.255.255
+.It ifRcvAddressType[2,ff:ff:ff:ff:ff:ff]
+.It ifRcvAddressStatus[Integer:1,OctetString:ff:ff:ff:ff:ff:ff]
+(requires '-o verbose' option)
+.El
+.Pp
+Square brackets are used to denote an entry's indexes.
+When used in an input OID, the square brackets may have to be
+escaped or the OID has to be quoted to protect it from the shell.
+Note there is no difference between ifName.1 and "ifName[1]".
+.It OID Ns = Ns Ar [syntax Ns :] Ns Ar value
+The object identifier with its syntax type and value that is to be set.
+At least one such string OID=[syntax:]value should be provided to
+.Nm bsnmpset
+to be able to send a request.
+.Bl -tag -width
+.It Cm OID
+OID may be input as a string, a string followed by a random number of integers
+(suboids) separated by dots, a sequence of integers separated by dots - that is
+if '-n' options is used - and in such case a syntax is required for every value,
+or a string followed by square brackets (used to denote an entry's indexes) and
+corresponding indexes.
+Any of formats used to print a single variable by
+.Nm bsnmpset is
+valid for inpit OID as well:
+.Bl -tag -width
+.It 1.3.6.1.2.1.25.1.1.0=TimeTicks:537615486
+.It sysLocation=OctetString:"@ Home" (with '-o verbose' option)
+.It sysLocation.0="@ Home"
+.It 1.3.6.1.2.1.2.2.1.6.1=OctetString:ffffffffffff
+.It ifPhysAddress.1="00:02:b3:1d:1c:a3"
+.It ifRcvAddressStatus.1.6.255.255.255.255.255.255=1
+.It "ifRcvAddressStatus[Integer:1,OctetString:ff:ff:ff:ff:ff:ff]=Integer:1"
+(with '-o verbose' option)
+.El
+.It Cm syntax
+where syntax string is one of :
+Integer, OctetString, OID, IpAddress, Counter32, Gauge, TimeTicks, Counter64.
+.It Cm value
+The value to be set - IP address in form of u.u.u.u  - for example
+1.3.1.6.1.2.0=IpAddress:192.168.0.1, strings require inverted-commas if they
+contain any special characters or spaces, all other numeric types don't.
+.El
+.Sh ENVIRONMENT
+.Nm ,
+.Nm bsnmpwalk
+and
+.Nm bsnmpset
+use the following environment variables:
+.Bl -tag -width SNMPAUTH
+.It Ev SNMPAUTH
+Specifies a default SNMP USM authentication protocol.
+.It Ev SNMPPRIV
+Specifies a default SNMP USM privacy protocol.
+.It Ev SNMPUSER
+Specifies a default SNMP USM user name.
+.It Ev SNMPPASSWD
+Specifies the SNMP USM plain text password to use when calculating localized
+authentication and privacy keys. If this variable exists in the environment,
+SMNPv3 is the default version to use for outgoing requests.
+.Sh SEE ALSO
+.Xr gensnmpdef 1
+.Sh AUTHORS
+.An Shteryana Shopova Aq syrinx@FreeBSD.org

Added: head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c	Wed Dec  8 14:30:25 2010	(r216295)
@@ -0,0 +1,1275 @@
+/*-
+ * Copyright (c) 2005-2006 The FreeBSD Project
+ * All rights reserved.
+ *
+ * Author: Shteryana Shopova <syrinx@FreeBSD.org>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+ *
+ * Bsnmpget and bsnmpwalk are simple tools for querying SNMP agents,
+ * bsnmpset can be used to set MIB objects in an agent.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <bsnmp/asn1.h>
+#include <bsnmp/snmp.h>
+#include <bsnmp/snmpclient.h>
+#include "bsnmptc.h"
+#include "bsnmptools.h"
+
+static const char *program_name = NULL;
+static enum program_e {
+	BSNMPGET,
+	BSNMPWALK,
+	BSNMPSET
+} program;
+
+/* *****************************************************************************
+ * Common bsnmptools functions.
+ */
+static void
+usage(void)
+{
+	fprintf(stderr,
+"Usage:\n"
+"%s %s [-A options] [-b buffersize] [-C options] [-I options]\n"
+"\t[-i filelist] [-l filename]%s [-o output] [-P options]\n"
+"\t%s[-r retries] [-s [trans::][community@][server][:port]]\n"
+"\t[-t timeout] [-U options] [-v version]%s\n",
+	program_name,
+	(program == BSNMPGET) ? "[-aDdehnK]" :
+	    (program == BSNMPWALK) ? "[-dhnK]" :
+	    (program == BSNMPSET) ? "[-adehnK]" :
+	    "",
+	(program == BSNMPGET) ? " [-M max-repetitions] [-N non-repeaters]" : "",
+	(program == BSNMPGET) ? "[-p pdu] " : "",
+	(program == BSNMPGET) ? " OID [OID ...]" :
+	    (program == BSNMPWALK || program == BSNMPSET) ? " [OID ...]" :
+	    ""
+	);
+}
+
+static int32_t
+parse_max_repetitions(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
+{
+	uint32_t v;
+
+	assert(opt_arg != NULL);
+
+	v = strtoul(opt_arg, (void *) NULL, 10);
+
+	if (v > SNMP_MAX_BINDINGS) {
+		warnx("Max repetitions value greater than %d maximum allowed.",
+		    SNMP_MAX_BINDINGS);
+		return (-1);
+	}
+
+	SET_MAXREP(snmptoolctx, v);
+	return (2);
+}
+
+static int32_t
+parse_non_repeaters(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
+{
+	uint32_t v;
+
+	assert(opt_arg != NULL);
+
+	v = strtoul(opt_arg, (void *) NULL, 10);
+
+	if (v > SNMP_MAX_BINDINGS) {
+		warnx("Non repeaters value greater than %d maximum allowed.",
+		    SNMP_MAX_BINDINGS);
+		return (-1);
+	}
+
+	SET_NONREP(snmptoolctx, v);
+	return (2);
+}
+
+static int32_t
+parse_pdu_type(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
+{
+	assert(opt_arg != NULL);
+
+	if (strcasecmp(opt_arg, "getbulk") == 0)
+		SET_PDUTYPE(snmptoolctx, SNMP_PDU_GETBULK);
+	else if (strcasecmp(opt_arg, "getnext") == 0)
+		SET_PDUTYPE(snmptoolctx, SNMP_PDU_GETNEXT);
+	else if (strcasecmp(opt_arg, "get") == 0)
+		SET_PDUTYPE(snmptoolctx, SNMP_PDU_GET);
+	else {
+		warnx("PDU type '%s' not supported.", opt_arg);
+		return (-1);
+	}
+
+	return (2);
+}
+
+static int32_t
+snmptool_parse_options(struct snmp_toolinfo *snmptoolctx, int argc, char **argv)
+{
+	int32_t count, optnum = 0;
+	int ch;
+	const char *opts;
+
+	switch (program) {
+		case BSNMPWALK:
+			opts = "dhnKA:b:C:I:i:l:o:P:r:s:t:U:v:";
+			break;
+		case BSNMPGET:
+			opts = "aDdehnKA:b:C:I:i:l:M:N:o:P:p:r:s:t:U:v:";
+			break;
+		case BSNMPSET:
+			opts = "adehnKA:b:C:I:i:l:o:P:r:s:t:U:v:";
+			break;
+		default:
+			return (-1);
+	}
+
+	while ((ch = getopt(argc, argv, opts)) != EOF) {
+		switch (ch) {
+		case 'A':
+			count = parse_authentication(snmptoolctx, optarg);
+			break;
+		case 'a':
+			count = parse_skip_access(snmptoolctx);
+			break;
+		case 'b':
+			count = parse_buflen(optarg);
+			break;
+		case 'D':
+			count = parse_discovery(snmptoolctx);
+			break;
+		case 'd':
+			count = parse_debug();
+			break;
+		case 'e':
+			count = parse_errors(snmptoolctx);
+			break;
+		case 'h':
+			usage();
+			return (-2);
+		case 'C':
+			count = parse_context(snmptoolctx, optarg);
+			break;
+		case 'I':
+			count = parse_include(snmptoolctx, optarg);
+			break;
+		case 'i':
+			count = parse_file(snmptoolctx, optarg);
+			break;
+		case 'K':
+			count = parse_local_key(snmptoolctx);
+			break;
+		case 'l':
+			count = parse_local_path(optarg);
+			break;
+		case 'M':
+			count = parse_max_repetitions(snmptoolctx, optarg);
+			break;
+		case 'N':
+			count = parse_non_repeaters(snmptoolctx, optarg);
+			break;
+		case 'n':
+			count = parse_num_oids(snmptoolctx);
+			break;
+		case 'o':
+			count = parse_output(snmptoolctx, optarg);
+			break;
+		case 'P':
+			count = parse_privacy(snmptoolctx, optarg);
+			break;
+		case 'p':
+			count = parse_pdu_type(snmptoolctx, optarg);
+			break;
+		case 'r':
+			count = parse_retry(optarg);
+			break;
+		case 's':
+			count = parse_server(optarg);
+			break;
+		case 't':
+			count = parse_timeout(optarg);
+			break;
+		case 'U':
+			count = parse_user_security(snmptoolctx, optarg);
+			break;
+		case 'v':
+			count = parse_version(optarg);
+			break;
+		case '?':
+		default:
+			usage();
+			return (-1);
+		}
+		if (count < 0)
+			return (-1);
+	    optnum += count;
+	}
+
+	return (optnum);
+}
+
+/*
+ * Read user input OID - one of following formats:
+ * 1) 1.2.1.1.2.1.0 - that is if option numeric was giveni;
+ * 2) string - in such case append .0 to the asn_oid subs;
+ * 3) string.1 - no additional proccessing required in such case.
+ */
+static char *
+snmptools_parse_stroid(struct snmp_toolinfo *snmptoolctx,
+    struct snmp_object *obj, char *argv)
+{
+	char string[MAXSTR], *str;
+	int32_t i = 0;
+	struct asn_oid in_oid;
+
+	str = argv;
+
+	if (*str == '.')
+		str++;
+
+	while (isalpha(*str) || *str == '_' || (i != 0 && isdigit(*str))) {
+		str++;
+		i++;
+	}
+
+	if (i <= 0 || i >= MAXSTR)
+		return (NULL);
+
+	memset(&in_oid, 0, sizeof(struct asn_oid));
+	if ((str = snmp_parse_suboid((argv + i), &in_oid)) == NULL) {
+		warnx("Invalid OID - %s", argv);
+		return (NULL);
+	}
+
+	strlcpy(string, argv, i + 1);
+	if (snmp_lookup_oidall(snmptoolctx, obj, string) < 0) {
+		warnx("No entry for %s in mapping lists", string);
+		return (NULL);
+	}
+
+	/* If OID given on command line append it. */
+	if (in_oid.len > 0)
+		asn_append_oid(&(obj->val.var), &in_oid);
+	else if (*str == '[') {
+		if ((str = snmp_parse_index(snmptoolctx, str + 1, obj)) == NULL)
+			return (NULL);
+	} else if (obj->val.syntax > 0 && GET_PDUTYPE(snmptoolctx) ==
+	    SNMP_PDU_GET) {
+		if (snmp_suboid_append(&(obj->val.var), (asn_subid_t) 0) < 0)
+			return (NULL);
+	}
+
+	return (str);
+}
+
+static int32_t
+snmptools_parse_oid(struct snmp_toolinfo *snmptoolctx,
+    struct snmp_object *obj, char *argv)
+{
+	if (argv == NULL)
+		return (-1);
+
+	if (ISSET_NUMERIC(snmptoolctx)) {
+		if (snmp_parse_numoid(argv, &(obj->val.var)) < 0)
+			return (-1);
+	} else {
+		if (snmptools_parse_stroid(snmptoolctx, obj, argv) == NULL &&
+		    snmp_parse_numoid(argv, &(obj->val.var)) < 0)
+			return (-1);
+	}
+
+	return (1);
+}
+
+static int32_t
+snmptool_add_vbind(struct snmp_pdu *pdu, struct snmp_object *obj)
+{
+	if (obj->error > 0)
+		return (0);
+
+	asn_append_oid(&(pdu->bindings[pdu->nbindings].var), &(obj->val.var));
+	pdu->nbindings++;
+
+	return (pdu->nbindings);
+}
+
+/* *****************************************************************************
+ * bsnmpget private functions.
+ */
+static int32_t
+snmpget_verify_vbind(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu,
+    struct snmp_object *obj)
+{
+	if (pdu->version == SNMP_V1 && obj->val.syntax ==
+	    SNMP_SYNTAX_COUNTER64) {
+		warnx("64-bit counters are not supported in SNMPv1 PDU");
+		return (-1);
+	}
+
+	if (ISSET_NUMERIC(snmptoolctx) || pdu->type == SNMP_PDU_GETNEXT ||
+	    pdu->type == SNMP_PDU_GETBULK)
+		return (1);
+
+	if (pdu->type == SNMP_PDU_GET && obj->val.syntax == SNMP_SYNTAX_NULL) {
+		warnx("Only leaf object values can be added to GET PDU");
+		return (-1);
+	}
+
+	return (1);
+}
+
+/*
+ * In case of a getbulk PDU, the error_status and error_index fields are used by
+ * libbsnmp to hold the values of the non-repeaters and max-repetitions fields
+ * that are present only in the getbulk - so before sending the PDU make sure
+ * these have correct values as well.
+ */
+static void
+snmpget_fix_getbulk(struct snmp_pdu *pdu, uint32_t max_rep, uint32_t non_rep)
+{
+	assert(pdu != NULL);
+
+	if (pdu->nbindings < non_rep)
+		pdu->error_status = pdu->nbindings;
+	else
+		pdu->error_status = non_rep;
+
+	if (max_rep > 0)
+		pdu->error_index = max_rep;
+	else
+		pdu->error_index = 1;
+}
+
+static int
+snmptool_get(struct snmp_toolinfo *snmptoolctx)
+{
+	struct snmp_pdu req, resp;
+
+	snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx));
+
+	while ((snmp_pdu_add_bindings(snmptoolctx, snmpget_verify_vbind,
+	     snmptool_add_vbind, &req, SNMP_MAX_BINDINGS)) > 0) {
+
+		if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK)
+			snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx),
+			    GET_NONREP(snmptoolctx));
+
+		if (snmp_dialog(&req, &resp) == -1) {
+			warnx("Snmp dialog - %s", strerror(errno));
+			break;
+		}
+
+		if (snmp_parse_resp(&resp, &req) >= 0) {
+			snmp_output_resp(snmptoolctx, &resp);
+			break;
+		}
+
+		snmp_output_err_resp(snmptoolctx, &resp);
+		if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK ||
+		    !ISSET_RETRY(snmptoolctx))
+			break;
+
+		/*
+		 * Loop through the object list and set object->error to the
+		 * varbinding that caused the error.
+		 */
+		if (snmp_object_seterror(snmptoolctx,
+		    &(resp.bindings[resp.error_index - 1]),
+		    resp.error_status) <= 0)
+			break;
+
+		fprintf(stderr, "Retrying...\n");
+		snmp_pdu_free(&resp);
+		snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx));
+	}
+
+	snmp_pdu_free(&resp);
+
+	return (0);
+}
+
+
+/* *****************************************************************************
+ * bsnmpwalk private functions.
+ */
+/* The default tree to walk. */
+static const struct asn_oid snmp_mibII_OID = {
+	6 , { 1, 3, 6, 1, 2, 1 }
+};
+
+static int32_t
+snmpwalk_add_default(struct snmp_toolinfo *snmptoolctx __unused,
+    struct snmp_object *obj, char *string __unused)
+{
+	asn_append_oid(&(obj->val.var), &snmp_mibII_OID);
+	return (1);
+}
+
+/*
+ * Prepare the next GetNext/Get PDU to send.
+ */
+static void
+snmpwalk_nextpdu_create(uint32_t op, struct asn_oid *var, struct snmp_pdu *pdu)
+{
+	snmp_pdu_create(pdu, op);
+	asn_append_oid(&(pdu->bindings[0].var), var);
+	pdu->nbindings = 1;
+}
+
+static int
+snmptool_walk(struct snmp_toolinfo *snmptoolctx)
+{
+	struct snmp_pdu req, resp;
+	struct asn_oid root;	/* Keep the inital oid. */
+	int32_t outputs, rc;
+
+	snmp_pdu_create(&req, SNMP_PDU_GETNEXT);
+
+	while ((rc = snmp_pdu_add_bindings(snmptoolctx, NULL,
+	    snmptool_add_vbind, &req, 1)) > 0) {
+
+		/* Remember the root where the walk started from. */
+		memset(&root, 0, sizeof(struct asn_oid));
+		asn_append_oid(&root, &(req.bindings[0].var));
+
+		outputs = 0;
+		while (snmp_dialog(&req, &resp) >= 0) {
+			if ((snmp_parse_resp(&resp, &req)) < 0) {
+				snmp_output_err_resp(snmptoolctx, &resp);
+				snmp_pdu_free(&resp);
+				outputs = -1;
+				break;
+			}
+
+			if (!(asn_is_suboid(&root, &(resp.bindings[0].var)))) {
+				snmp_pdu_free(&resp);
+				break;
+			}
+
+			if (snmp_output_resp(snmptoolctx, &resp)!= 0) {
+				snmp_pdu_free(&resp);
+				outputs = -1;
+				break;
+			}
+			outputs++;
+			snmp_pdu_free(&resp);
+
+			snmpwalk_nextpdu_create(SNMP_PDU_GETNEXT,
+			    &(resp.bindings[0].var), &req);
+		}
+
+		/* Just in case our root was a leaf. */
+		if (outputs == 0) {
+			snmpwalk_nextpdu_create(SNMP_PDU_GET, &root, &req);
+			if (snmp_dialog(&req, &resp) == SNMP_CODE_OK) {
+				if (snmp_parse_resp(&resp,&req) < 0)
+					snmp_output_err_resp(snmptoolctx, &resp);
+				else
+					snmp_output_resp(snmptoolctx, &(resp));
+
+				snmp_pdu_free(&resp);
+			} else
+				warnx("Snmp dialog - %s", strerror(errno));
+		}
+
+		if (snmp_object_remove(snmptoolctx, &root) < 0) {
+			warnx("snmp_object_remove");
+			break;
+		}
+
+		snmp_pdu_create(&req, SNMP_PDU_GETNEXT);
+	}
+
+	if (rc == 0)
+		return (0);
+	else
+		return (1);
+}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012081430.oB8EUP8J006067>