1a7398723SShteryana Shopova /*- 2a7398723SShteryana Shopova * Copyright (c) 2005-2006 The FreeBSD Project 3a7398723SShteryana Shopova * All rights reserved. 4a7398723SShteryana Shopova * 5a7398723SShteryana Shopova * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6a7398723SShteryana Shopova * 7a7398723SShteryana Shopova * Redistribution of this software and documentation and use in source and 8a7398723SShteryana Shopova * binary forms, with or without modification, are permitted provided that 9a7398723SShteryana Shopova * the following conditions are met: 10a7398723SShteryana Shopova * 11a7398723SShteryana Shopova * 1. Redistributions of source code or documentation must retain the above 12a7398723SShteryana Shopova * copyright notice, this list of conditions and the following disclaimer. 13a7398723SShteryana Shopova * 2. Redistributions in binary form must reproduce the above copyright 14a7398723SShteryana Shopova * notice, this list of conditions and the following disclaimer in the 15a7398723SShteryana Shopova * documentation and/or other materials provided with the distribution. 16a7398723SShteryana Shopova * 17a7398723SShteryana Shopova * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18a7398723SShteryana Shopova * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19a7398723SShteryana Shopova * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20a7398723SShteryana Shopova * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21a7398723SShteryana Shopova * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22a7398723SShteryana Shopova * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23a7398723SShteryana Shopova * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24a7398723SShteryana Shopova * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25a7398723SShteryana Shopova * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26a7398723SShteryana Shopova * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27a7398723SShteryana Shopova * SUCH DAMAGE. 28a7398723SShteryana Shopova * 29a7398723SShteryana Shopova * Bsnmpget and bsnmpwalk are simple tools for querying SNMP agents, 30a7398723SShteryana Shopova * bsnmpset can be used to set MIB objects in an agent. 31a7398723SShteryana Shopova * 32a7398723SShteryana Shopova * $FreeBSD$ 33a7398723SShteryana Shopova */ 34a7398723SShteryana Shopova 35a7398723SShteryana Shopova #include <sys/queue.h> 36a7398723SShteryana Shopova #include <sys/types.h> 37a7398723SShteryana Shopova 38a7398723SShteryana Shopova #include <assert.h> 39a7398723SShteryana Shopova #include <ctype.h> 40a7398723SShteryana Shopova #include <err.h> 41a7398723SShteryana Shopova #include <errno.h> 42a7398723SShteryana Shopova #include <stdarg.h> 43a7398723SShteryana Shopova #include <stdio.h> 44a7398723SShteryana Shopova #include <stdlib.h> 45a7398723SShteryana Shopova #include <string.h> 46a7398723SShteryana Shopova #include <syslog.h> 47a7398723SShteryana Shopova #include <unistd.h> 48a7398723SShteryana Shopova 49a7398723SShteryana Shopova #include <bsnmp/asn1.h> 50a7398723SShteryana Shopova #include <bsnmp/snmp.h> 51a7398723SShteryana Shopova #include <bsnmp/snmpclient.h> 52a7398723SShteryana Shopova #include "bsnmptc.h" 53a7398723SShteryana Shopova #include "bsnmptools.h" 54a7398723SShteryana Shopova 55a7398723SShteryana Shopova static const char *program_name = NULL; 56a7398723SShteryana Shopova static enum program_e { 57a7398723SShteryana Shopova BSNMPGET, 58a7398723SShteryana Shopova BSNMPWALK, 59a7398723SShteryana Shopova BSNMPSET 60a7398723SShteryana Shopova } program; 61a7398723SShteryana Shopova 62a7398723SShteryana Shopova /* ***************************************************************************** 63a7398723SShteryana Shopova * Common bsnmptools functions. 64a7398723SShteryana Shopova */ 65a7398723SShteryana Shopova static void 66a7398723SShteryana Shopova usage(void) 67a7398723SShteryana Shopova { 68a7398723SShteryana Shopova fprintf(stderr, 69a7398723SShteryana Shopova "Usage:\n" 70a7398723SShteryana Shopova "%s %s [-A options] [-b buffersize] [-C options] [-I options]\n" 71a7398723SShteryana Shopova "\t[-i filelist] [-l filename]%s [-o output] [-P options]\n" 72a7398723SShteryana Shopova "\t%s[-r retries] [-s [trans::][community@][server][:port]]\n" 73a7398723SShteryana Shopova "\t[-t timeout] [-U options] [-v version]%s\n", 74a7398723SShteryana Shopova program_name, 75a7398723SShteryana Shopova (program == BSNMPGET) ? "[-aDdehnK]" : 76a7398723SShteryana Shopova (program == BSNMPWALK) ? "[-dhnK]" : 77a7398723SShteryana Shopova (program == BSNMPSET) ? "[-adehnK]" : 78a7398723SShteryana Shopova "", 79b9288caaSShteryana Shopova (program == BSNMPGET || program == BSNMPWALK) ? 80b9288caaSShteryana Shopova " [-M max-repetitions] [-N non-repeaters]" : "", 81b9288caaSShteryana Shopova (program == BSNMPGET || program == BSNMPWALK) ? "[-p pdu] " : "", 82a7398723SShteryana Shopova (program == BSNMPGET) ? " OID [OID ...]" : 83a7398723SShteryana Shopova (program == BSNMPWALK || program == BSNMPSET) ? " [OID ...]" : 84a7398723SShteryana Shopova "" 85a7398723SShteryana Shopova ); 86a7398723SShteryana Shopova } 87a7398723SShteryana Shopova 88a7398723SShteryana Shopova static int32_t 89a7398723SShteryana Shopova parse_max_repetitions(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 90a7398723SShteryana Shopova { 91a7398723SShteryana Shopova uint32_t v; 92a7398723SShteryana Shopova 93a7398723SShteryana Shopova assert(opt_arg != NULL); 94a7398723SShteryana Shopova 95a7398723SShteryana Shopova v = strtoul(opt_arg, (void *) NULL, 10); 96a7398723SShteryana Shopova 97a7398723SShteryana Shopova if (v > SNMP_MAX_BINDINGS) { 98a7398723SShteryana Shopova warnx("Max repetitions value greater than %d maximum allowed.", 99a7398723SShteryana Shopova SNMP_MAX_BINDINGS); 100a7398723SShteryana Shopova return (-1); 101a7398723SShteryana Shopova } 102a7398723SShteryana Shopova 103a7398723SShteryana Shopova SET_MAXREP(snmptoolctx, v); 104a7398723SShteryana Shopova return (2); 105a7398723SShteryana Shopova } 106a7398723SShteryana Shopova 107a7398723SShteryana Shopova static int32_t 108a7398723SShteryana Shopova parse_non_repeaters(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 109a7398723SShteryana Shopova { 110a7398723SShteryana Shopova uint32_t v; 111a7398723SShteryana Shopova 112a7398723SShteryana Shopova assert(opt_arg != NULL); 113a7398723SShteryana Shopova 114a7398723SShteryana Shopova v = strtoul(opt_arg, (void *) NULL, 10); 115a7398723SShteryana Shopova 116a7398723SShteryana Shopova if (v > SNMP_MAX_BINDINGS) { 117a7398723SShteryana Shopova warnx("Non repeaters value greater than %d maximum allowed.", 118a7398723SShteryana Shopova SNMP_MAX_BINDINGS); 119a7398723SShteryana Shopova return (-1); 120a7398723SShteryana Shopova } 121a7398723SShteryana Shopova 122a7398723SShteryana Shopova SET_NONREP(snmptoolctx, v); 123a7398723SShteryana Shopova return (2); 124a7398723SShteryana Shopova } 125a7398723SShteryana Shopova 126a7398723SShteryana Shopova static int32_t 127a7398723SShteryana Shopova parse_pdu_type(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 128a7398723SShteryana Shopova { 129a7398723SShteryana Shopova assert(opt_arg != NULL); 130a7398723SShteryana Shopova 131a7398723SShteryana Shopova if (strcasecmp(opt_arg, "getbulk") == 0) 132a7398723SShteryana Shopova SET_PDUTYPE(snmptoolctx, SNMP_PDU_GETBULK); 133a7398723SShteryana Shopova else if (strcasecmp(opt_arg, "getnext") == 0) 134a7398723SShteryana Shopova SET_PDUTYPE(snmptoolctx, SNMP_PDU_GETNEXT); 135a7398723SShteryana Shopova else if (strcasecmp(opt_arg, "get") == 0) 136a7398723SShteryana Shopova SET_PDUTYPE(snmptoolctx, SNMP_PDU_GET); 137a7398723SShteryana Shopova else { 138a7398723SShteryana Shopova warnx("PDU type '%s' not supported.", opt_arg); 139a7398723SShteryana Shopova return (-1); 140a7398723SShteryana Shopova } 141a7398723SShteryana Shopova 142a7398723SShteryana Shopova return (2); 143a7398723SShteryana Shopova } 144a7398723SShteryana Shopova 145a7398723SShteryana Shopova static int32_t 146a7398723SShteryana Shopova snmptool_parse_options(struct snmp_toolinfo *snmptoolctx, int argc, char **argv) 147a7398723SShteryana Shopova { 148a7398723SShteryana Shopova int32_t count, optnum = 0; 149a7398723SShteryana Shopova int ch; 150a7398723SShteryana Shopova const char *opts; 151a7398723SShteryana Shopova 152a7398723SShteryana Shopova switch (program) { 153a7398723SShteryana Shopova case BSNMPWALK: 154b9288caaSShteryana Shopova opts = "dhnKA:b:C:I:i:l:M:N:o:P:p:r:s:t:U:v:"; 155a7398723SShteryana Shopova break; 156a7398723SShteryana Shopova case BSNMPGET: 157a7398723SShteryana Shopova opts = "aDdehnKA:b:C:I:i:l:M:N:o:P:p:r:s:t:U:v:"; 158a7398723SShteryana Shopova break; 159a7398723SShteryana Shopova case BSNMPSET: 160a7398723SShteryana Shopova opts = "adehnKA:b:C:I:i:l:o:P:r:s:t:U:v:"; 161a7398723SShteryana Shopova break; 162a7398723SShteryana Shopova default: 163a7398723SShteryana Shopova return (-1); 164a7398723SShteryana Shopova } 165a7398723SShteryana Shopova 166a7398723SShteryana Shopova while ((ch = getopt(argc, argv, opts)) != EOF) { 167a7398723SShteryana Shopova switch (ch) { 168a7398723SShteryana Shopova case 'A': 169a7398723SShteryana Shopova count = parse_authentication(snmptoolctx, optarg); 170a7398723SShteryana Shopova break; 171a7398723SShteryana Shopova case 'a': 172a7398723SShteryana Shopova count = parse_skip_access(snmptoolctx); 173a7398723SShteryana Shopova break; 174a7398723SShteryana Shopova case 'b': 175a7398723SShteryana Shopova count = parse_buflen(optarg); 176a7398723SShteryana Shopova break; 177a7398723SShteryana Shopova case 'D': 178a7398723SShteryana Shopova count = parse_discovery(snmptoolctx); 179a7398723SShteryana Shopova break; 180a7398723SShteryana Shopova case 'd': 181a7398723SShteryana Shopova count = parse_debug(); 182a7398723SShteryana Shopova break; 183a7398723SShteryana Shopova case 'e': 184a7398723SShteryana Shopova count = parse_errors(snmptoolctx); 185a7398723SShteryana Shopova break; 186a7398723SShteryana Shopova case 'h': 187a7398723SShteryana Shopova usage(); 188a7398723SShteryana Shopova return (-2); 189a7398723SShteryana Shopova case 'C': 190a7398723SShteryana Shopova count = parse_context(snmptoolctx, optarg); 191a7398723SShteryana Shopova break; 192a7398723SShteryana Shopova case 'I': 193a7398723SShteryana Shopova count = parse_include(snmptoolctx, optarg); 194a7398723SShteryana Shopova break; 195a7398723SShteryana Shopova case 'i': 196a7398723SShteryana Shopova count = parse_file(snmptoolctx, optarg); 197a7398723SShteryana Shopova break; 198a7398723SShteryana Shopova case 'K': 199a7398723SShteryana Shopova count = parse_local_key(snmptoolctx); 200a7398723SShteryana Shopova break; 201a7398723SShteryana Shopova case 'l': 202a7398723SShteryana Shopova count = parse_local_path(optarg); 203a7398723SShteryana Shopova break; 204a7398723SShteryana Shopova case 'M': 205a7398723SShteryana Shopova count = parse_max_repetitions(snmptoolctx, optarg); 206a7398723SShteryana Shopova break; 207a7398723SShteryana Shopova case 'N': 208a7398723SShteryana Shopova count = parse_non_repeaters(snmptoolctx, optarg); 209a7398723SShteryana Shopova break; 210a7398723SShteryana Shopova case 'n': 211a7398723SShteryana Shopova count = parse_num_oids(snmptoolctx); 212a7398723SShteryana Shopova break; 213a7398723SShteryana Shopova case 'o': 214a7398723SShteryana Shopova count = parse_output(snmptoolctx, optarg); 215a7398723SShteryana Shopova break; 216a7398723SShteryana Shopova case 'P': 217a7398723SShteryana Shopova count = parse_privacy(snmptoolctx, optarg); 218a7398723SShteryana Shopova break; 219a7398723SShteryana Shopova case 'p': 220a7398723SShteryana Shopova count = parse_pdu_type(snmptoolctx, optarg); 221a7398723SShteryana Shopova break; 222a7398723SShteryana Shopova case 'r': 223a7398723SShteryana Shopova count = parse_retry(optarg); 224a7398723SShteryana Shopova break; 225a7398723SShteryana Shopova case 's': 226a7398723SShteryana Shopova count = parse_server(optarg); 227a7398723SShteryana Shopova break; 228a7398723SShteryana Shopova case 't': 229a7398723SShteryana Shopova count = parse_timeout(optarg); 230a7398723SShteryana Shopova break; 231a7398723SShteryana Shopova case 'U': 232a7398723SShteryana Shopova count = parse_user_security(snmptoolctx, optarg); 233a7398723SShteryana Shopova break; 234a7398723SShteryana Shopova case 'v': 235a7398723SShteryana Shopova count = parse_version(optarg); 236a7398723SShteryana Shopova break; 237a7398723SShteryana Shopova case '?': 238a7398723SShteryana Shopova default: 239a7398723SShteryana Shopova usage(); 240a7398723SShteryana Shopova return (-1); 241a7398723SShteryana Shopova } 242a7398723SShteryana Shopova if (count < 0) 243a7398723SShteryana Shopova return (-1); 244a7398723SShteryana Shopova optnum += count; 245a7398723SShteryana Shopova } 246a7398723SShteryana Shopova 247a7398723SShteryana Shopova return (optnum); 248a7398723SShteryana Shopova } 249a7398723SShteryana Shopova 250a7398723SShteryana Shopova /* 251a7398723SShteryana Shopova * Read user input OID - one of following formats: 2523df5ecacSUlrich Spörlein * 1) 1.2.1.1.2.1.0 - that is if option numeric was given; 253a7398723SShteryana Shopova * 2) string - in such case append .0 to the asn_oid subs; 2543df5ecacSUlrich Spörlein * 3) string.1 - no additional processing required in such case. 255a7398723SShteryana Shopova */ 256a7398723SShteryana Shopova static char * 257a7398723SShteryana Shopova snmptools_parse_stroid(struct snmp_toolinfo *snmptoolctx, 258a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 259a7398723SShteryana Shopova { 260a7398723SShteryana Shopova char string[MAXSTR], *str; 261a7398723SShteryana Shopova int32_t i = 0; 262a7398723SShteryana Shopova struct asn_oid in_oid; 263a7398723SShteryana Shopova 264a7398723SShteryana Shopova str = argv; 265a7398723SShteryana Shopova 266a7398723SShteryana Shopova if (*str == '.') 267a7398723SShteryana Shopova str++; 268a7398723SShteryana Shopova 269a7398723SShteryana Shopova while (isalpha(*str) || *str == '_' || (i != 0 && isdigit(*str))) { 270a7398723SShteryana Shopova str++; 271a7398723SShteryana Shopova i++; 272a7398723SShteryana Shopova } 273a7398723SShteryana Shopova 274a7398723SShteryana Shopova if (i <= 0 || i >= MAXSTR) 275a7398723SShteryana Shopova return (NULL); 276a7398723SShteryana Shopova 277a7398723SShteryana Shopova memset(&in_oid, 0, sizeof(struct asn_oid)); 278a7398723SShteryana Shopova if ((str = snmp_parse_suboid((argv + i), &in_oid)) == NULL) { 279a7398723SShteryana Shopova warnx("Invalid OID - %s", argv); 280a7398723SShteryana Shopova return (NULL); 281a7398723SShteryana Shopova } 282a7398723SShteryana Shopova 283a7398723SShteryana Shopova strlcpy(string, argv, i + 1); 284a7398723SShteryana Shopova if (snmp_lookup_oidall(snmptoolctx, obj, string) < 0) { 285a7398723SShteryana Shopova warnx("No entry for %s in mapping lists", string); 286a7398723SShteryana Shopova return (NULL); 287a7398723SShteryana Shopova } 288a7398723SShteryana Shopova 289a7398723SShteryana Shopova /* If OID given on command line append it. */ 290a7398723SShteryana Shopova if (in_oid.len > 0) 291a7398723SShteryana Shopova asn_append_oid(&(obj->val.var), &in_oid); 292a7398723SShteryana Shopova else if (*str == '[') { 293a7398723SShteryana Shopova if ((str = snmp_parse_index(snmptoolctx, str + 1, obj)) == NULL) 294a7398723SShteryana Shopova return (NULL); 295a7398723SShteryana Shopova } else if (obj->val.syntax > 0 && GET_PDUTYPE(snmptoolctx) == 296a7398723SShteryana Shopova SNMP_PDU_GET) { 297a7398723SShteryana Shopova if (snmp_suboid_append(&(obj->val.var), (asn_subid_t) 0) < 0) 298a7398723SShteryana Shopova return (NULL); 299a7398723SShteryana Shopova } 300a7398723SShteryana Shopova 301a7398723SShteryana Shopova return (str); 302a7398723SShteryana Shopova } 303a7398723SShteryana Shopova 304a7398723SShteryana Shopova static int32_t 305a7398723SShteryana Shopova snmptools_parse_oid(struct snmp_toolinfo *snmptoolctx, 306a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 307a7398723SShteryana Shopova { 308a7398723SShteryana Shopova if (argv == NULL) 309a7398723SShteryana Shopova return (-1); 310a7398723SShteryana Shopova 311a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx)) { 312a7398723SShteryana Shopova if (snmp_parse_numoid(argv, &(obj->val.var)) < 0) 313a7398723SShteryana Shopova return (-1); 314a7398723SShteryana Shopova } else { 315a7398723SShteryana Shopova if (snmptools_parse_stroid(snmptoolctx, obj, argv) == NULL && 316a7398723SShteryana Shopova snmp_parse_numoid(argv, &(obj->val.var)) < 0) 317a7398723SShteryana Shopova return (-1); 318a7398723SShteryana Shopova } 319a7398723SShteryana Shopova 320a7398723SShteryana Shopova return (1); 321a7398723SShteryana Shopova } 322a7398723SShteryana Shopova 323a7398723SShteryana Shopova static int32_t 324a7398723SShteryana Shopova snmptool_add_vbind(struct snmp_pdu *pdu, struct snmp_object *obj) 325a7398723SShteryana Shopova { 326a7398723SShteryana Shopova if (obj->error > 0) 327a7398723SShteryana Shopova return (0); 328a7398723SShteryana Shopova 329a7398723SShteryana Shopova asn_append_oid(&(pdu->bindings[pdu->nbindings].var), &(obj->val.var)); 330a7398723SShteryana Shopova pdu->nbindings++; 331a7398723SShteryana Shopova 332a7398723SShteryana Shopova return (pdu->nbindings); 333a7398723SShteryana Shopova } 334a7398723SShteryana Shopova 335a7398723SShteryana Shopova /* ***************************************************************************** 336a7398723SShteryana Shopova * bsnmpget private functions. 337a7398723SShteryana Shopova */ 338a7398723SShteryana Shopova static int32_t 339a7398723SShteryana Shopova snmpget_verify_vbind(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu, 340a7398723SShteryana Shopova struct snmp_object *obj) 341a7398723SShteryana Shopova { 342a7398723SShteryana Shopova if (pdu->version == SNMP_V1 && obj->val.syntax == 343a7398723SShteryana Shopova SNMP_SYNTAX_COUNTER64) { 344a7398723SShteryana Shopova warnx("64-bit counters are not supported in SNMPv1 PDU"); 345a7398723SShteryana Shopova return (-1); 346a7398723SShteryana Shopova } 347a7398723SShteryana Shopova 348a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx) || pdu->type == SNMP_PDU_GETNEXT || 349a7398723SShteryana Shopova pdu->type == SNMP_PDU_GETBULK) 350a7398723SShteryana Shopova return (1); 351a7398723SShteryana Shopova 352a7398723SShteryana Shopova if (pdu->type == SNMP_PDU_GET && obj->val.syntax == SNMP_SYNTAX_NULL) { 353a7398723SShteryana Shopova warnx("Only leaf object values can be added to GET PDU"); 354a7398723SShteryana Shopova return (-1); 355a7398723SShteryana Shopova } 356a7398723SShteryana Shopova 357a7398723SShteryana Shopova return (1); 358a7398723SShteryana Shopova } 359a7398723SShteryana Shopova 360a7398723SShteryana Shopova /* 361a7398723SShteryana Shopova * In case of a getbulk PDU, the error_status and error_index fields are used by 362a7398723SShteryana Shopova * libbsnmp to hold the values of the non-repeaters and max-repetitions fields 363a7398723SShteryana Shopova * that are present only in the getbulk - so before sending the PDU make sure 364a7398723SShteryana Shopova * these have correct values as well. 365a7398723SShteryana Shopova */ 366a7398723SShteryana Shopova static void 367a7398723SShteryana Shopova snmpget_fix_getbulk(struct snmp_pdu *pdu, uint32_t max_rep, uint32_t non_rep) 368a7398723SShteryana Shopova { 369a7398723SShteryana Shopova assert(pdu != NULL); 370a7398723SShteryana Shopova 371a7398723SShteryana Shopova if (pdu->nbindings < non_rep) 372a7398723SShteryana Shopova pdu->error_status = pdu->nbindings; 373a7398723SShteryana Shopova else 374a7398723SShteryana Shopova pdu->error_status = non_rep; 375a7398723SShteryana Shopova 376a7398723SShteryana Shopova if (max_rep > 0) 377a7398723SShteryana Shopova pdu->error_index = max_rep; 378a7398723SShteryana Shopova else 379a7398723SShteryana Shopova pdu->error_index = 1; 380a7398723SShteryana Shopova } 381a7398723SShteryana Shopova 382a7398723SShteryana Shopova static int 383a7398723SShteryana Shopova snmptool_get(struct snmp_toolinfo *snmptoolctx) 384a7398723SShteryana Shopova { 385a7398723SShteryana Shopova struct snmp_pdu req, resp; 386a7398723SShteryana Shopova 387a7398723SShteryana Shopova snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx)); 388a7398723SShteryana Shopova 389a7398723SShteryana Shopova while ((snmp_pdu_add_bindings(snmptoolctx, snmpget_verify_vbind, 390a7398723SShteryana Shopova snmptool_add_vbind, &req, SNMP_MAX_BINDINGS)) > 0) { 391a7398723SShteryana Shopova 392a7398723SShteryana Shopova if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK) 393a7398723SShteryana Shopova snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), 394a7398723SShteryana Shopova GET_NONREP(snmptoolctx)); 395a7398723SShteryana Shopova 396a7398723SShteryana Shopova if (snmp_dialog(&req, &resp) == -1) { 397a7398723SShteryana Shopova warnx("Snmp dialog - %s", strerror(errno)); 398a7398723SShteryana Shopova break; 399a7398723SShteryana Shopova } 400a7398723SShteryana Shopova 401a7398723SShteryana Shopova if (snmp_parse_resp(&resp, &req) >= 0) { 402b9288caaSShteryana Shopova snmp_output_resp(snmptoolctx, &resp, NULL); 403a7398723SShteryana Shopova break; 404a7398723SShteryana Shopova } 405a7398723SShteryana Shopova 406a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 407a7398723SShteryana Shopova if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK || 408a7398723SShteryana Shopova !ISSET_RETRY(snmptoolctx)) 409a7398723SShteryana Shopova break; 410a7398723SShteryana Shopova 411a7398723SShteryana Shopova /* 412a7398723SShteryana Shopova * Loop through the object list and set object->error to the 413a7398723SShteryana Shopova * varbinding that caused the error. 414a7398723SShteryana Shopova */ 415a7398723SShteryana Shopova if (snmp_object_seterror(snmptoolctx, 416a7398723SShteryana Shopova &(resp.bindings[resp.error_index - 1]), 417a7398723SShteryana Shopova resp.error_status) <= 0) 418a7398723SShteryana Shopova break; 419a7398723SShteryana Shopova 420a7398723SShteryana Shopova fprintf(stderr, "Retrying...\n"); 421a7398723SShteryana Shopova snmp_pdu_free(&resp); 422a7398723SShteryana Shopova snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx)); 423a7398723SShteryana Shopova } 424a7398723SShteryana Shopova 425a7398723SShteryana Shopova snmp_pdu_free(&resp); 426a7398723SShteryana Shopova 427a7398723SShteryana Shopova return (0); 428a7398723SShteryana Shopova } 429a7398723SShteryana Shopova 430a7398723SShteryana Shopova 431a7398723SShteryana Shopova /* ***************************************************************************** 432a7398723SShteryana Shopova * bsnmpwalk private functions. 433a7398723SShteryana Shopova */ 434a7398723SShteryana Shopova /* The default tree to walk. */ 435a7398723SShteryana Shopova static const struct asn_oid snmp_mibII_OID = { 436a7398723SShteryana Shopova 6 , { 1, 3, 6, 1, 2, 1 } 437a7398723SShteryana Shopova }; 438a7398723SShteryana Shopova 439a7398723SShteryana Shopova static int32_t 440a7398723SShteryana Shopova snmpwalk_add_default(struct snmp_toolinfo *snmptoolctx __unused, 441a7398723SShteryana Shopova struct snmp_object *obj, char *string __unused) 442a7398723SShteryana Shopova { 443a7398723SShteryana Shopova asn_append_oid(&(obj->val.var), &snmp_mibII_OID); 444a7398723SShteryana Shopova return (1); 445a7398723SShteryana Shopova } 446a7398723SShteryana Shopova 447a7398723SShteryana Shopova /* 448a7398723SShteryana Shopova * Prepare the next GetNext/Get PDU to send. 449a7398723SShteryana Shopova */ 450a7398723SShteryana Shopova static void 451a7398723SShteryana Shopova snmpwalk_nextpdu_create(uint32_t op, struct asn_oid *var, struct snmp_pdu *pdu) 452a7398723SShteryana Shopova { 453a7398723SShteryana Shopova snmp_pdu_create(pdu, op); 454a7398723SShteryana Shopova asn_append_oid(&(pdu->bindings[0].var), var); 455a7398723SShteryana Shopova pdu->nbindings = 1; 456a7398723SShteryana Shopova } 457a7398723SShteryana Shopova 458a7398723SShteryana Shopova static int 459a7398723SShteryana Shopova snmptool_walk(struct snmp_toolinfo *snmptoolctx) 460a7398723SShteryana Shopova { 461a7398723SShteryana Shopova struct snmp_pdu req, resp; 4623df5ecacSUlrich Spörlein struct asn_oid root; /* Keep the initial oid. */ 463a7398723SShteryana Shopova int32_t outputs, rc; 464b9288caaSShteryana Shopova uint32_t op; 465a7398723SShteryana Shopova 466b9288caaSShteryana Shopova if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK) 467b9288caaSShteryana Shopova op = SNMP_PDU_GETBULK; 468b9288caaSShteryana Shopova else 469b9288caaSShteryana Shopova op = SNMP_PDU_GETNEXT; 470b9288caaSShteryana Shopova 471b9288caaSShteryana Shopova snmp_pdu_create(&req, op); 472a7398723SShteryana Shopova 473a7398723SShteryana Shopova while ((rc = snmp_pdu_add_bindings(snmptoolctx, NULL, 474a7398723SShteryana Shopova snmptool_add_vbind, &req, 1)) > 0) { 475a7398723SShteryana Shopova 476a7398723SShteryana Shopova /* Remember the root where the walk started from. */ 477a7398723SShteryana Shopova memset(&root, 0, sizeof(struct asn_oid)); 478a7398723SShteryana Shopova asn_append_oid(&root, &(req.bindings[0].var)); 479a7398723SShteryana Shopova 480b9288caaSShteryana Shopova if (op == SNMP_PDU_GETBULK) 481b9288caaSShteryana Shopova snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), 482b9288caaSShteryana Shopova GET_NONREP(snmptoolctx)); 483b9288caaSShteryana Shopova 484a7398723SShteryana Shopova outputs = 0; 485a7398723SShteryana Shopova while (snmp_dialog(&req, &resp) >= 0) { 486a7398723SShteryana Shopova if ((snmp_parse_resp(&resp, &req)) < 0) { 487a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 488a7398723SShteryana Shopova snmp_pdu_free(&resp); 489a7398723SShteryana Shopova outputs = -1; 490a7398723SShteryana Shopova break; 491a7398723SShteryana Shopova } 492a7398723SShteryana Shopova 493b9288caaSShteryana Shopova rc = snmp_output_resp(snmptoolctx, &resp, &root); 494b9288caaSShteryana Shopova if (rc < 0) { 495a7398723SShteryana Shopova snmp_pdu_free(&resp); 496a7398723SShteryana Shopova outputs = -1; 497a7398723SShteryana Shopova break; 498a7398723SShteryana Shopova } 499b9288caaSShteryana Shopova 500b9288caaSShteryana Shopova outputs += rc; 501a7398723SShteryana Shopova snmp_pdu_free(&resp); 502a7398723SShteryana Shopova 50319ffd5ecSEnji Cooper if ((u_int)rc < resp.nbindings) 504b9288caaSShteryana Shopova break; 505b9288caaSShteryana Shopova 506b9288caaSShteryana Shopova snmpwalk_nextpdu_create(op, 507b9288caaSShteryana Shopova &(resp.bindings[resp.nbindings - 1].var), &req); 508b9288caaSShteryana Shopova if (op == SNMP_PDU_GETBULK) 509b9288caaSShteryana Shopova snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), 510b9288caaSShteryana Shopova GET_NONREP(snmptoolctx)); 511a7398723SShteryana Shopova } 512a7398723SShteryana Shopova 513a7398723SShteryana Shopova /* Just in case our root was a leaf. */ 514a7398723SShteryana Shopova if (outputs == 0) { 515a7398723SShteryana Shopova snmpwalk_nextpdu_create(SNMP_PDU_GET, &root, &req); 516a7398723SShteryana Shopova if (snmp_dialog(&req, &resp) == SNMP_CODE_OK) { 517a7398723SShteryana Shopova if (snmp_parse_resp(&resp,&req) < 0) 518a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 519a7398723SShteryana Shopova else 520b9288caaSShteryana Shopova snmp_output_resp(snmptoolctx, &(resp), NULL); 521a7398723SShteryana Shopova 522a7398723SShteryana Shopova snmp_pdu_free(&resp); 523a7398723SShteryana Shopova } else 524a7398723SShteryana Shopova warnx("Snmp dialog - %s", strerror(errno)); 525a7398723SShteryana Shopova } 526a7398723SShteryana Shopova 527a7398723SShteryana Shopova if (snmp_object_remove(snmptoolctx, &root) < 0) { 528a7398723SShteryana Shopova warnx("snmp_object_remove"); 529a7398723SShteryana Shopova break; 530a7398723SShteryana Shopova } 531a7398723SShteryana Shopova 532b9288caaSShteryana Shopova snmp_pdu_create(&req, op); 533a7398723SShteryana Shopova } 534a7398723SShteryana Shopova 535a7398723SShteryana Shopova if (rc == 0) 536a7398723SShteryana Shopova return (0); 537a7398723SShteryana Shopova else 538a7398723SShteryana Shopova return (1); 539a7398723SShteryana Shopova } 540a7398723SShteryana Shopova 541a7398723SShteryana Shopova /* ***************************************************************************** 542a7398723SShteryana Shopova * bsnmpset private functions. 543a7398723SShteryana Shopova */ 544a7398723SShteryana Shopova 545a7398723SShteryana Shopova static int32_t 546a7398723SShteryana Shopova parse_oid_numeric(struct snmp_value *value, char *val) 547a7398723SShteryana Shopova { 548a7398723SShteryana Shopova char *endptr; 549a7398723SShteryana Shopova int32_t saved_errno; 550a7398723SShteryana Shopova asn_subid_t suboid; 551a7398723SShteryana Shopova 552a7398723SShteryana Shopova do { 553a7398723SShteryana Shopova saved_errno = errno; 554a7398723SShteryana Shopova errno = 0; 555a7398723SShteryana Shopova suboid = strtoul(val, &endptr, 10); 556a7398723SShteryana Shopova if (errno != 0) { 557a7398723SShteryana Shopova warnx("Value %s not supported - %s", val, 558a7398723SShteryana Shopova strerror(errno)); 559a7398723SShteryana Shopova errno = saved_errno; 560a7398723SShteryana Shopova return (-1); 561a7398723SShteryana Shopova } 562a7398723SShteryana Shopova errno = saved_errno; 563a7398723SShteryana Shopova if ((asn_subid_t) suboid > ASN_MAXID) { 564a7398723SShteryana Shopova warnx("Suboid %u > ASN_MAXID", suboid); 565a7398723SShteryana Shopova return (-1); 566a7398723SShteryana Shopova } 567a7398723SShteryana Shopova if (snmp_suboid_append(&(value->v.oid), suboid) < 0) 568a7398723SShteryana Shopova return (-1); 569a7398723SShteryana Shopova val = endptr + 1; 570a7398723SShteryana Shopova } while (*endptr == '.'); 571a7398723SShteryana Shopova 572a7398723SShteryana Shopova if (*endptr != '\0') 573a7398723SShteryana Shopova warnx("OID value %s not supported", val); 574a7398723SShteryana Shopova 575a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_OID; 576a7398723SShteryana Shopova return (0); 577a7398723SShteryana Shopova } 578a7398723SShteryana Shopova 579a7398723SShteryana Shopova /* 580a7398723SShteryana Shopova * Allow OID leaf in both forms: 581a7398723SShteryana Shopova * 1) 1.3.6.1.2... -> in such case call directly the function reading raw OIDs; 582a7398723SShteryana Shopova * 2) begemotSnmpdAgentFreeBSD -> lookup the ASN OID corresponding to that. 583a7398723SShteryana Shopova */ 584a7398723SShteryana Shopova static int32_t 585a7398723SShteryana Shopova parse_oid_string(struct snmp_toolinfo *snmptoolctx, 586a7398723SShteryana Shopova struct snmp_value *value, char *string) 587a7398723SShteryana Shopova { 588a7398723SShteryana Shopova struct snmp_object obj; 589a7398723SShteryana Shopova 590a7398723SShteryana Shopova if (isdigit(string[0])) 591a7398723SShteryana Shopova return (parse_oid_numeric(value, string)); 592a7398723SShteryana Shopova 593a7398723SShteryana Shopova memset(&obj, 0, sizeof(struct snmp_object)); 594a7398723SShteryana Shopova if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) { 595a7398723SShteryana Shopova warnx("Unknown OID enum string - %s", string); 596a7398723SShteryana Shopova return (-1); 597a7398723SShteryana Shopova } 598a7398723SShteryana Shopova 599a7398723SShteryana Shopova asn_append_oid(&(value->v.oid), &(obj.val.var)); 600a7398723SShteryana Shopova return (1); 601a7398723SShteryana Shopova } 602a7398723SShteryana Shopova 603a7398723SShteryana Shopova static int32_t 604a7398723SShteryana Shopova parse_ip(struct snmp_value * value, char * val) 605a7398723SShteryana Shopova { 606a7398723SShteryana Shopova char *endptr, *str; 607*f16a380fSEnji Cooper int32_t i; 608*f16a380fSEnji Cooper uint32_t v; 609a7398723SShteryana Shopova 610a7398723SShteryana Shopova str = val; 611a7398723SShteryana Shopova for (i = 0; i < 4; i++) { 612a7398723SShteryana Shopova v = strtoul(str, &endptr, 10); 613a7398723SShteryana Shopova if (v > 0xff) 614a7398723SShteryana Shopova return (-1); 615a7398723SShteryana Shopova if (*endptr != '.' && *endptr != '\0' && i != 3) 616a7398723SShteryana Shopova break; 617a7398723SShteryana Shopova str = endptr + 1; 618a7398723SShteryana Shopova value->v.ipaddress[i] = (uint8_t) v; 619a7398723SShteryana Shopova } 620a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_IPADDRESS; 621*f16a380fSEnji Cooper 622a7398723SShteryana Shopova return (0); 623a7398723SShteryana Shopova } 624a7398723SShteryana Shopova 625a7398723SShteryana Shopova static int32_t 626a7398723SShteryana Shopova parse_int(struct snmp_value *value, char *val) 627a7398723SShteryana Shopova { 628a7398723SShteryana Shopova char *endptr; 629a7398723SShteryana Shopova int32_t v, saved_errno; 630a7398723SShteryana Shopova 631a7398723SShteryana Shopova saved_errno = errno; 632a7398723SShteryana Shopova errno = 0; 633a7398723SShteryana Shopova 634a7398723SShteryana Shopova v = strtol(val, &endptr, 10); 635a7398723SShteryana Shopova 636a7398723SShteryana Shopova if (errno != 0) { 637a7398723SShteryana Shopova warnx("Value %s not supported - %s", val, strerror(errno)); 638a7398723SShteryana Shopova errno = saved_errno; 639a7398723SShteryana Shopova return (-1); 640a7398723SShteryana Shopova } 641a7398723SShteryana Shopova 642a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_INTEGER; 643a7398723SShteryana Shopova value->v.integer = v; 644a7398723SShteryana Shopova errno = saved_errno; 645a7398723SShteryana Shopova 646a7398723SShteryana Shopova return (0); 647a7398723SShteryana Shopova } 648a7398723SShteryana Shopova 649a7398723SShteryana Shopova static int32_t 650a7398723SShteryana Shopova parse_int_string(struct snmp_object *object, char *val) 651a7398723SShteryana Shopova { 652a7398723SShteryana Shopova int32_t v; 653a7398723SShteryana Shopova 654a7398723SShteryana Shopova if (isdigit(val[0])) 655a7398723SShteryana Shopova return ((parse_int(&(object->val), val))); 656a7398723SShteryana Shopova 657a7398723SShteryana Shopova if (object->info == NULL) { 658a7398723SShteryana Shopova warnx("Unknown enumerated integer type - %s", val); 659a7398723SShteryana Shopova return (-1); 660a7398723SShteryana Shopova } 661a7398723SShteryana Shopova if ((v = enum_number_lookup(object->info->snmp_enum, val)) < 0) 662a7398723SShteryana Shopova warnx("Unknown enumerated integer type - %s", val); 663a7398723SShteryana Shopova 664a7398723SShteryana Shopova object->val.v.integer = v; 665a7398723SShteryana Shopova return (1); 666a7398723SShteryana Shopova } 667a7398723SShteryana Shopova 668a7398723SShteryana Shopova /* 669a7398723SShteryana Shopova * Here syntax may be one of SNMP_SYNTAX_COUNTER, SNMP_SYNTAX_GAUGE, 670a7398723SShteryana Shopova * SNMP_SYNTAX_TIMETICKS. 671a7398723SShteryana Shopova */ 672a7398723SShteryana Shopova static int32_t 673a7398723SShteryana Shopova parse_uint(struct snmp_value *value, char *val) 674a7398723SShteryana Shopova { 675a7398723SShteryana Shopova char *endptr; 676a7398723SShteryana Shopova uint32_t v = 0; 677a7398723SShteryana Shopova int32_t saved_errno; 678a7398723SShteryana Shopova 679a7398723SShteryana Shopova saved_errno = errno; 680a7398723SShteryana Shopova errno = 0; 681a7398723SShteryana Shopova 682a7398723SShteryana Shopova v = strtoul(val, &endptr, 10); 683a7398723SShteryana Shopova 684a7398723SShteryana Shopova if (errno != 0) { 685a7398723SShteryana Shopova warnx("Value %s not supported - %s", val, strerror(errno)); 686a7398723SShteryana Shopova errno = saved_errno; 687a7398723SShteryana Shopova return (-1); 688a7398723SShteryana Shopova } 689a7398723SShteryana Shopova 690a7398723SShteryana Shopova value->v.uint32 = v; 691a7398723SShteryana Shopova errno = saved_errno; 692a7398723SShteryana Shopova 693a7398723SShteryana Shopova return (0); 694a7398723SShteryana Shopova } 695a7398723SShteryana Shopova 696a7398723SShteryana Shopova static int32_t 697a7398723SShteryana Shopova parse_ticks(struct snmp_value *value, char *val) 698a7398723SShteryana Shopova { 699a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 700a7398723SShteryana Shopova return (-1); 701a7398723SShteryana Shopova 702a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_TIMETICKS; 703a7398723SShteryana Shopova return (0); 704a7398723SShteryana Shopova } 705a7398723SShteryana Shopova 706a7398723SShteryana Shopova static int32_t 707a7398723SShteryana Shopova parse_gauge(struct snmp_value *value, char *val) 708a7398723SShteryana Shopova { 709a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 710a7398723SShteryana Shopova return (-1); 711a7398723SShteryana Shopova 712a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_GAUGE; 713a7398723SShteryana Shopova return (0); 714a7398723SShteryana Shopova } 715a7398723SShteryana Shopova 716a7398723SShteryana Shopova static int32_t 717a7398723SShteryana Shopova parse_counter(struct snmp_value *value, char *val) 718a7398723SShteryana Shopova { 719a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 720a7398723SShteryana Shopova return (-1); 721a7398723SShteryana Shopova 722a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_COUNTER; 723a7398723SShteryana Shopova return (0); 724a7398723SShteryana Shopova } 725a7398723SShteryana Shopova 726a7398723SShteryana Shopova static int32_t 727a7398723SShteryana Shopova parse_uint64(struct snmp_value *value, char *val) 728a7398723SShteryana Shopova { 729a7398723SShteryana Shopova char *endptr; 730a7398723SShteryana Shopova int32_t saved_errno; 731a7398723SShteryana Shopova uint64_t v; 732a7398723SShteryana Shopova 733a7398723SShteryana Shopova saved_errno = errno; 734a7398723SShteryana Shopova errno = 0; 735a7398723SShteryana Shopova 736a7398723SShteryana Shopova v = strtoull(val, &endptr, 10); 737a7398723SShteryana Shopova 738a7398723SShteryana Shopova if (errno != 0) { 739a7398723SShteryana Shopova warnx("Value %s not supported - %s", val, strerror(errno)); 740a7398723SShteryana Shopova errno = saved_errno; 741a7398723SShteryana Shopova return (-1); 742a7398723SShteryana Shopova } 743a7398723SShteryana Shopova 744a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_COUNTER64; 745a7398723SShteryana Shopova value->v.counter64 = v; 746a7398723SShteryana Shopova errno = saved_errno; 747a7398723SShteryana Shopova 748a7398723SShteryana Shopova return (0); 749a7398723SShteryana Shopova } 750a7398723SShteryana Shopova 751a7398723SShteryana Shopova static int32_t 752a7398723SShteryana Shopova parse_syntax_val(struct snmp_value *value, enum snmp_syntax syntax, char *val) 753a7398723SShteryana Shopova { 754a7398723SShteryana Shopova switch (syntax) { 755a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 756a7398723SShteryana Shopova return (parse_int(value, val)); 757a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 758a7398723SShteryana Shopova return (parse_ip(value, val)); 759a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 760a7398723SShteryana Shopova return (parse_counter(value, val)); 761a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 762a7398723SShteryana Shopova return (parse_gauge(value, val)); 763a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 764a7398723SShteryana Shopova return (parse_ticks(value, val)); 765a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 766a7398723SShteryana Shopova return (parse_uint64(value, val)); 767a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 768a7398723SShteryana Shopova return (snmp_tc2oct(SNMP_STRING, value, val)); 769a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 770a7398723SShteryana Shopova return (parse_oid_numeric(value, val)); 771a7398723SShteryana Shopova default: 772a7398723SShteryana Shopova /* NOTREACHED */ 773a7398723SShteryana Shopova break; 774a7398723SShteryana Shopova } 775a7398723SShteryana Shopova 776a7398723SShteryana Shopova return (-1); 777a7398723SShteryana Shopova } 778a7398723SShteryana Shopova 779a7398723SShteryana Shopova /* 780a7398723SShteryana Shopova * Parse a command line argument of type OID=syntax:value and fill in whatever 781a7398723SShteryana Shopova * fields can be derived from the input into snmp_value structure. Reads numeric 782a7398723SShteryana Shopova * OIDs. 783a7398723SShteryana Shopova */ 784a7398723SShteryana Shopova static int32_t 785a7398723SShteryana Shopova parse_pair_numoid_val(char *str, struct snmp_value *snmp_val) 786a7398723SShteryana Shopova { 787a7398723SShteryana Shopova int32_t cnt; 788a7398723SShteryana Shopova char *ptr; 789a7398723SShteryana Shopova enum snmp_syntax syntax; 790a7398723SShteryana Shopova char oid_str[ASN_OIDSTRLEN]; 791a7398723SShteryana Shopova 792a7398723SShteryana Shopova ptr = str; 793a7398723SShteryana Shopova for (cnt = 0; cnt < ASN_OIDSTRLEN; cnt++) 794a7398723SShteryana Shopova if (ptr[cnt] == '=') 795a7398723SShteryana Shopova break; 796a7398723SShteryana Shopova 797a7398723SShteryana Shopova if (cnt >= ASN_OIDSTRLEN) { 798a7398723SShteryana Shopova warnx("OID too long - %s", str); 799a7398723SShteryana Shopova return (-1); 800a7398723SShteryana Shopova } 801a7398723SShteryana Shopova strlcpy(oid_str, ptr, (size_t) (cnt + 1)); 802a7398723SShteryana Shopova 803a7398723SShteryana Shopova ptr = str + cnt + 1; 804a7398723SShteryana Shopova for (cnt = 0; cnt < MAX_CMD_SYNTAX_LEN; cnt++) 805a7398723SShteryana Shopova if(ptr[cnt] == ':') 806a7398723SShteryana Shopova break; 807a7398723SShteryana Shopova 808a7398723SShteryana Shopova if (cnt >= MAX_CMD_SYNTAX_LEN) { 809a7398723SShteryana Shopova warnx("Unknown syntax in OID - %s", str); 810a7398723SShteryana Shopova return (-1); 811a7398723SShteryana Shopova } 812a7398723SShteryana Shopova 813a7398723SShteryana Shopova if ((syntax = parse_syntax(ptr)) <= SNMP_SYNTAX_NULL) { 814a7398723SShteryana Shopova warnx("Unknown syntax in OID - %s", ptr); 815a7398723SShteryana Shopova return (-1); 816a7398723SShteryana Shopova } 817a7398723SShteryana Shopova 818a7398723SShteryana Shopova ptr = ptr + cnt + 1; 819a7398723SShteryana Shopova for (cnt = 0; cnt < MAX_OCTSTRING_LEN; cnt++) 820a7398723SShteryana Shopova if (ptr[cnt] == '\0') 821a7398723SShteryana Shopova break; 822a7398723SShteryana Shopova 823a7398723SShteryana Shopova if (ptr[cnt] != '\0') { 824a7398723SShteryana Shopova warnx("Value string too long - %s",ptr); 825a7398723SShteryana Shopova return (-1); 826a7398723SShteryana Shopova } 827a7398723SShteryana Shopova 828a7398723SShteryana Shopova /* 829a7398723SShteryana Shopova * Here try parsing the OIDs and syntaxes and then check values - have 830a7398723SShteryana Shopova * to know syntax to check value boundaries. 831a7398723SShteryana Shopova */ 832a7398723SShteryana Shopova if (snmp_parse_numoid(oid_str, &(snmp_val->var)) < 0) { 833a7398723SShteryana Shopova warnx("Error parsing OID %s",oid_str); 834a7398723SShteryana Shopova return (-1); 835a7398723SShteryana Shopova } 836a7398723SShteryana Shopova 837a7398723SShteryana Shopova if (parse_syntax_val(snmp_val, syntax, ptr) < 0) 838a7398723SShteryana Shopova return (-1); 839a7398723SShteryana Shopova 840a7398723SShteryana Shopova return (1); 841a7398723SShteryana Shopova } 842a7398723SShteryana Shopova 843a7398723SShteryana Shopova /* XXX-BZ aruments should be swapped. */ 844a7398723SShteryana Shopova static int32_t 845a7398723SShteryana Shopova parse_syntax_strval(struct snmp_toolinfo *snmptoolctx, char *str, 846a7398723SShteryana Shopova struct snmp_object *object) 847a7398723SShteryana Shopova { 848a7398723SShteryana Shopova uint32_t len; 849a7398723SShteryana Shopova enum snmp_syntax syn; 850a7398723SShteryana Shopova 851a7398723SShteryana Shopova /* 852a7398723SShteryana Shopova * Syntax string here not required - still may be present. 853a7398723SShteryana Shopova */ 854a7398723SShteryana Shopova 855a7398723SShteryana Shopova if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) { 856a7398723SShteryana Shopova for (len = 0 ; *(str + len) != ':'; len++) { 857a7398723SShteryana Shopova if (*(str + len) == '\0') { 858a7398723SShteryana Shopova warnx("Syntax missing in value - %s", str); 859a7398723SShteryana Shopova return (-1); 860a7398723SShteryana Shopova } 861a7398723SShteryana Shopova } 862a7398723SShteryana Shopova if ((syn = parse_syntax(str)) <= SNMP_SYNTAX_NULL) { 863a7398723SShteryana Shopova warnx("Unknown syntax in - %s", str); 864a7398723SShteryana Shopova return (-1); 865a7398723SShteryana Shopova } 866a7398723SShteryana Shopova if (syn != object->val.syntax) { 867a7398723SShteryana Shopova if (!ISSET_ERRIGNORE(snmptoolctx)) { 868a7398723SShteryana Shopova warnx("Bad syntax in - %s", str); 869a7398723SShteryana Shopova return (-1); 870a7398723SShteryana Shopova } else 871a7398723SShteryana Shopova object->val.syntax = syn; 872a7398723SShteryana Shopova } 873a7398723SShteryana Shopova len++; 874a7398723SShteryana Shopova } else 875a7398723SShteryana Shopova len = 0; 876a7398723SShteryana Shopova 877a7398723SShteryana Shopova switch (object->val.syntax) { 878a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 879a7398723SShteryana Shopova return (parse_int_string(object, str + len)); 880a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 881a7398723SShteryana Shopova return (parse_ip(&(object->val), str + len)); 882a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 883a7398723SShteryana Shopova return (parse_counter(&(object->val), str + len)); 884a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 885a7398723SShteryana Shopova return (parse_gauge(&(object->val), str + len)); 886a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 887a7398723SShteryana Shopova return (parse_ticks(&(object->val), str + len)); 888a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 889a7398723SShteryana Shopova return (parse_uint64(&(object->val), str + len)); 890a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 891a7398723SShteryana Shopova return (snmp_tc2oct(object->info->tc, &(object->val), 892a7398723SShteryana Shopova str + len)); 893a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 894a7398723SShteryana Shopova return (parse_oid_string(snmptoolctx, &(object->val), 895a7398723SShteryana Shopova str + len)); 896a7398723SShteryana Shopova default: 897a7398723SShteryana Shopova /* NOTREACHED */ 898a7398723SShteryana Shopova break; 899a7398723SShteryana Shopova } 900a7398723SShteryana Shopova 901a7398723SShteryana Shopova return (-1); 902a7398723SShteryana Shopova } 903a7398723SShteryana Shopova 904a7398723SShteryana Shopova static int32_t 905a7398723SShteryana Shopova parse_pair_stroid_val(struct snmp_toolinfo *snmptoolctx, 906a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 907a7398723SShteryana Shopova { 908a7398723SShteryana Shopova char *ptr; 909a7398723SShteryana Shopova 910a7398723SShteryana Shopova if ((ptr = snmptools_parse_stroid(snmptoolctx, obj, argv)) == NULL) 911a7398723SShteryana Shopova return (-1); 912a7398723SShteryana Shopova 913a7398723SShteryana Shopova if (*ptr != '=') { 914a7398723SShteryana Shopova warnx("Value to set expected after OID"); 915a7398723SShteryana Shopova return (-1); 916a7398723SShteryana Shopova } 917a7398723SShteryana Shopova 918a7398723SShteryana Shopova if (parse_syntax_strval(snmptoolctx, ptr + 1, obj) < 0) 919a7398723SShteryana Shopova return (-1); 920a7398723SShteryana Shopova 921a7398723SShteryana Shopova return (1); 922a7398723SShteryana Shopova } 923a7398723SShteryana Shopova 924a7398723SShteryana Shopova 925a7398723SShteryana Shopova static int32_t 926a7398723SShteryana Shopova snmpset_parse_oid(struct snmp_toolinfo *snmptoolctx, 927a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 928a7398723SShteryana Shopova { 929a7398723SShteryana Shopova if (argv == NULL) 930a7398723SShteryana Shopova return (-1); 931a7398723SShteryana Shopova 932a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx)) { 933a7398723SShteryana Shopova if (parse_pair_numoid_val(argv, &(obj->val)) < 0) 934a7398723SShteryana Shopova return (-1); 935a7398723SShteryana Shopova } else { 936a7398723SShteryana Shopova if (parse_pair_stroid_val(snmptoolctx, obj, argv) < 0) 937a7398723SShteryana Shopova return (-1); 938a7398723SShteryana Shopova } 939a7398723SShteryana Shopova 940a7398723SShteryana Shopova return (1); 941a7398723SShteryana Shopova } 942a7398723SShteryana Shopova 943a7398723SShteryana Shopova static int32_t 944a7398723SShteryana Shopova add_ip_syntax(struct snmp_value *dst, struct snmp_value *src) 945a7398723SShteryana Shopova { 946a7398723SShteryana Shopova int8_t i; 947a7398723SShteryana Shopova 948a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_IPADDRESS; 949a7398723SShteryana Shopova for (i = 0; i < 4; i++) 950a7398723SShteryana Shopova dst->v.ipaddress[i] = src->v.ipaddress[i]; 951a7398723SShteryana Shopova 952a7398723SShteryana Shopova return (1); 953a7398723SShteryana Shopova } 954a7398723SShteryana Shopova 955a7398723SShteryana Shopova static int32_t 956a7398723SShteryana Shopova add_octstring_syntax(struct snmp_value *dst, struct snmp_value *src) 957a7398723SShteryana Shopova { 958a7398723SShteryana Shopova if (src->v.octetstring.len > ASN_MAXOCTETSTRING) { 959a7398723SShteryana Shopova warnx("OctetString len too big - %u",src->v.octetstring.len); 960a7398723SShteryana Shopova return (-1); 961a7398723SShteryana Shopova } 962a7398723SShteryana Shopova 963a7398723SShteryana Shopova if ((dst->v.octetstring.octets = malloc(src->v.octetstring.len)) == 964a7398723SShteryana Shopova NULL) { 965a7398723SShteryana Shopova syslog(LOG_ERR, "malloc() failed - %s", strerror(errno)); 966a7398723SShteryana Shopova return (-1); 967a7398723SShteryana Shopova } 968a7398723SShteryana Shopova 969a7398723SShteryana Shopova memcpy(dst->v.octetstring.octets, src->v.octetstring.octets, 970a7398723SShteryana Shopova src->v.octetstring.len); 971a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_OCTETSTRING; 972a7398723SShteryana Shopova dst->v.octetstring.len = src->v.octetstring.len; 973a7398723SShteryana Shopova 974a7398723SShteryana Shopova return(0); 975a7398723SShteryana Shopova } 976a7398723SShteryana Shopova 977a7398723SShteryana Shopova static int32_t 978a7398723SShteryana Shopova add_oid_syntax(struct snmp_value *dst, struct snmp_value *src) 979a7398723SShteryana Shopova { 980a7398723SShteryana Shopova asn_append_oid(&(dst->v.oid), &(src->v.oid)); 981a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_OID; 982a7398723SShteryana Shopova return (0); 983a7398723SShteryana Shopova } 984a7398723SShteryana Shopova 985a7398723SShteryana Shopova /* 986a7398723SShteryana Shopova * Check syntax - if one of SNMP_SYNTAX_NULL, SNMP_SYNTAX_NOSUCHOBJECT, 987a7398723SShteryana Shopova * SNMP_SYNTAX_NOSUCHINSTANCE, SNMP_SYNTAX_ENDOFMIBVIEW or anything not known - 988a7398723SShteryana Shopova * return error. 989a7398723SShteryana Shopova */ 990a7398723SShteryana Shopova static int32_t 991a7398723SShteryana Shopova snmpset_add_value(struct snmp_value *dst, struct snmp_value *src) 992a7398723SShteryana Shopova { 993a7398723SShteryana Shopova if (dst == NULL || src == NULL) 994a7398723SShteryana Shopova return (-1); 995a7398723SShteryana Shopova 996a7398723SShteryana Shopova switch (src->syntax) { 997a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 998a7398723SShteryana Shopova dst->v.integer = src->v.integer; 999a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_INTEGER; 1000a7398723SShteryana Shopova break; 1001a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 1002a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1003a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_TIMETICKS; 1004a7398723SShteryana Shopova break; 1005a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 1006a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1007a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_GAUGE; 1008a7398723SShteryana Shopova break; 1009a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 1010a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1011a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_COUNTER; 1012a7398723SShteryana Shopova break; 1013a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 1014a7398723SShteryana Shopova dst->v.counter64 = src->v.counter64; 1015a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_COUNTER64; 1016a7398723SShteryana Shopova break; 1017a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 1018a7398723SShteryana Shopova add_ip_syntax(dst, src); 1019a7398723SShteryana Shopova break; 1020a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 1021a7398723SShteryana Shopova add_octstring_syntax(dst, src); 1022a7398723SShteryana Shopova break; 1023a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 1024a7398723SShteryana Shopova add_oid_syntax(dst, src); 1025a7398723SShteryana Shopova break; 1026a7398723SShteryana Shopova default: 1027a7398723SShteryana Shopova warnx("Unknown syntax %d", src->syntax); 1028a7398723SShteryana Shopova return (-1); 1029a7398723SShteryana Shopova } 1030a7398723SShteryana Shopova 1031a7398723SShteryana Shopova return (0); 1032a7398723SShteryana Shopova } 1033a7398723SShteryana Shopova 1034a7398723SShteryana Shopova static int32_t 1035a7398723SShteryana Shopova snmpset_verify_vbind(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu, 1036a7398723SShteryana Shopova struct snmp_object *obj) 1037a7398723SShteryana Shopova { 1038a7398723SShteryana Shopova if (pdu->version == SNMP_V1 && obj->val.syntax == 1039a7398723SShteryana Shopova SNMP_SYNTAX_COUNTER64) { 1040a7398723SShteryana Shopova warnx("64-bit counters are not supported in SNMPv1 PDU"); 1041a7398723SShteryana Shopova return (-1); 1042a7398723SShteryana Shopova } 1043a7398723SShteryana Shopova 1044a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx) || ISSET_ERRIGNORE(snmptoolctx)) 1045a7398723SShteryana Shopova return (1); 1046a7398723SShteryana Shopova 1047a7398723SShteryana Shopova if (obj->info->access < SNMP_ACCESS_SET) { 1048a7398723SShteryana Shopova warnx("Object %s not accessible for set - try 'bsnmpset -a'", 1049a7398723SShteryana Shopova obj->info->string); 1050a7398723SShteryana Shopova return (-1); 1051a7398723SShteryana Shopova } 1052a7398723SShteryana Shopova 1053a7398723SShteryana Shopova return (1); 1054a7398723SShteryana Shopova } 1055a7398723SShteryana Shopova 1056a7398723SShteryana Shopova static int32_t 1057a7398723SShteryana Shopova snmpset_add_vbind(struct snmp_pdu *pdu, struct snmp_object *obj) 1058a7398723SShteryana Shopova { 1059a7398723SShteryana Shopova if (pdu->nbindings > SNMP_MAX_BINDINGS) { 1060a7398723SShteryana Shopova warnx("Too many OIDs for one PDU"); 1061a7398723SShteryana Shopova return (-1); 1062a7398723SShteryana Shopova } 1063a7398723SShteryana Shopova 1064a7398723SShteryana Shopova if (obj->error > 0) 1065a7398723SShteryana Shopova return (0); 1066a7398723SShteryana Shopova 1067a7398723SShteryana Shopova if (snmpset_add_value(&(pdu->bindings[pdu->nbindings]), &(obj->val)) 1068a7398723SShteryana Shopova < 0) 1069a7398723SShteryana Shopova return (-1); 1070a7398723SShteryana Shopova 1071a7398723SShteryana Shopova asn_append_oid(&(pdu->bindings[pdu->nbindings].var), &(obj->val.var)); 1072a7398723SShteryana Shopova pdu->nbindings++; 1073a7398723SShteryana Shopova 1074a7398723SShteryana Shopova return (pdu->nbindings); 1075a7398723SShteryana Shopova } 1076a7398723SShteryana Shopova 1077a7398723SShteryana Shopova static int 1078a7398723SShteryana Shopova snmptool_set(struct snmp_toolinfo *snmptoolctx) 1079a7398723SShteryana Shopova { 1080a7398723SShteryana Shopova struct snmp_pdu req, resp; 1081a7398723SShteryana Shopova 1082a7398723SShteryana Shopova snmp_pdu_create(&req, SNMP_PDU_SET); 1083a7398723SShteryana Shopova 1084a7398723SShteryana Shopova while ((snmp_pdu_add_bindings(snmptoolctx, snmpset_verify_vbind, 1085a7398723SShteryana Shopova snmpset_add_vbind, &req, SNMP_MAX_BINDINGS)) > 0) { 1086a7398723SShteryana Shopova if (snmp_dialog(&req, &resp)) { 1087a7398723SShteryana Shopova warnx("Snmp dialog - %s", strerror(errno)); 1088a7398723SShteryana Shopova break; 1089a7398723SShteryana Shopova } 1090a7398723SShteryana Shopova 1091a7398723SShteryana Shopova if (snmp_pdu_check(&req, &resp) > 0) { 1092a7398723SShteryana Shopova if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) 1093b9288caaSShteryana Shopova snmp_output_resp(snmptoolctx, &resp, NULL); 1094a7398723SShteryana Shopova break; 1095a7398723SShteryana Shopova } 1096a7398723SShteryana Shopova 1097a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 1098a7398723SShteryana Shopova if (!ISSET_RETRY(snmptoolctx)) 1099a7398723SShteryana Shopova break; 1100a7398723SShteryana Shopova 1101a7398723SShteryana Shopova if (snmp_object_seterror(snmptoolctx, 1102a7398723SShteryana Shopova &(resp.bindings[resp.error_index - 1]), 1103a7398723SShteryana Shopova resp.error_status) <= 0) 1104a7398723SShteryana Shopova break; 1105a7398723SShteryana Shopova 1106a7398723SShteryana Shopova fprintf(stderr, "Retrying...\n"); 1107a7398723SShteryana Shopova snmp_pdu_free(&req); 1108a7398723SShteryana Shopova snmp_pdu_free(&resp); 1109a7398723SShteryana Shopova snmp_pdu_create(&req, SNMP_PDU_SET); 1110a7398723SShteryana Shopova } 1111a7398723SShteryana Shopova 1112a7398723SShteryana Shopova snmp_pdu_free(&resp); 1113a7398723SShteryana Shopova 1114a7398723SShteryana Shopova return (0); 1115a7398723SShteryana Shopova } 1116a7398723SShteryana Shopova 1117a7398723SShteryana Shopova /* ***************************************************************************** 1118a7398723SShteryana Shopova * main 1119a7398723SShteryana Shopova */ 1120a7398723SShteryana Shopova /* 1121a7398723SShteryana Shopova * According to command line options prepare SNMP Get | GetNext | GetBulk PDU. 11223df5ecacSUlrich Spörlein * Wait for a response and print it. 1123a7398723SShteryana Shopova */ 1124a7398723SShteryana Shopova /* 1125a7398723SShteryana Shopova * Do a 'snmp walk' - according to command line options request for values 1126a7398723SShteryana Shopova * lexicographically subsequent and subrooted at a common node. Send a GetNext 11273df5ecacSUlrich Spörlein * PDU requesting the value for each next variable and print the response. Stop 11283df5ecacSUlrich Spörlein * when a Response PDU is received that contains the value of a variable not 1129a7398723SShteryana Shopova * subrooted at the variable the walk started. 1130a7398723SShteryana Shopova */ 1131a7398723SShteryana Shopova int 1132a7398723SShteryana Shopova main(int argc, char ** argv) 1133a7398723SShteryana Shopova { 1134a7398723SShteryana Shopova struct snmp_toolinfo snmptoolctx; 1135a7398723SShteryana Shopova int32_t oid_cnt, last_oid, opt_num; 1136a7398723SShteryana Shopova int rc = 0; 1137a7398723SShteryana Shopova 1138a7398723SShteryana Shopova /* Make sure program_name is set and valid. */ 1139a7398723SShteryana Shopova if (*argv == NULL) 1140a7398723SShteryana Shopova program_name = "snmptool"; 1141a7398723SShteryana Shopova else { 1142a7398723SShteryana Shopova program_name = strrchr(*argv, '/'); 1143a7398723SShteryana Shopova if (program_name != NULL) 1144a7398723SShteryana Shopova program_name++; 1145a7398723SShteryana Shopova else 1146a7398723SShteryana Shopova program_name = *argv; 1147a7398723SShteryana Shopova } 1148a7398723SShteryana Shopova 1149a7398723SShteryana Shopova if (program_name == NULL) { 1150a7398723SShteryana Shopova fprintf(stderr, "Error: No program name?\n"); 1151a7398723SShteryana Shopova exit (1); 1152a7398723SShteryana Shopova } else if (strcmp(program_name, "bsnmpget") == 0) 1153a7398723SShteryana Shopova program = BSNMPGET; 1154a7398723SShteryana Shopova else if (strcmp(program_name, "bsnmpwalk") == 0) 1155a7398723SShteryana Shopova program = BSNMPWALK; 1156a7398723SShteryana Shopova else if (strcmp(program_name, "bsnmpset") == 0) 1157a7398723SShteryana Shopova program = BSNMPSET; 1158a7398723SShteryana Shopova else { 1159a7398723SShteryana Shopova fprintf(stderr, "Unknown snmp tool name '%s'.\n", program_name); 1160a7398723SShteryana Shopova exit (1); 1161a7398723SShteryana Shopova } 1162a7398723SShteryana Shopova 1163a7398723SShteryana Shopova /* Initialize. */ 1164a7398723SShteryana Shopova if (snmptool_init(&snmptoolctx) < 0) 1165a7398723SShteryana Shopova exit (1); 1166a7398723SShteryana Shopova 1167a7398723SShteryana Shopova if ((opt_num = snmptool_parse_options(&snmptoolctx, argc, argv)) < 0) { 1168a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1169a7398723SShteryana Shopova /* On -h (help) exit without error. */ 1170a7398723SShteryana Shopova if (opt_num == -2) 1171a7398723SShteryana Shopova exit(0); 1172a7398723SShteryana Shopova else 1173a7398723SShteryana Shopova exit(1); 1174a7398723SShteryana Shopova } 1175a7398723SShteryana Shopova 1176a7398723SShteryana Shopova oid_cnt = argc - opt_num - 1; 1177a7398723SShteryana Shopova if (oid_cnt == 0) { 1178a7398723SShteryana Shopova switch (program) { 1179a7398723SShteryana Shopova case BSNMPGET: 1180a7398723SShteryana Shopova if (!ISSET_EDISCOVER(&snmptoolctx) && 1181a7398723SShteryana Shopova !ISSET_LOCALKEY(&snmptoolctx)) { 1182a7398723SShteryana Shopova fprintf(stderr, "No OID given.\n"); 1183a7398723SShteryana Shopova usage(); 1184a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1185a7398723SShteryana Shopova exit(1); 1186a7398723SShteryana Shopova } 1187a7398723SShteryana Shopova break; 1188a7398723SShteryana Shopova 1189a7398723SShteryana Shopova case BSNMPWALK: 1190a7398723SShteryana Shopova if (snmp_object_add(&snmptoolctx, snmpwalk_add_default, 1191a7398723SShteryana Shopova NULL) < 0) { 1192a7398723SShteryana Shopova fprintf(stderr, 1193a7398723SShteryana Shopova "Error setting default subtree.\n"); 1194a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1195a7398723SShteryana Shopova exit(1); 1196a7398723SShteryana Shopova } 1197a7398723SShteryana Shopova break; 1198a7398723SShteryana Shopova 1199a7398723SShteryana Shopova case BSNMPSET: 1200a7398723SShteryana Shopova fprintf(stderr, "No OID given.\n"); 1201a7398723SShteryana Shopova usage(); 1202a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1203a7398723SShteryana Shopova exit(1); 1204a7398723SShteryana Shopova } 1205a7398723SShteryana Shopova } 1206a7398723SShteryana Shopova 1207a7398723SShteryana Shopova if (snmp_import_all(&snmptoolctx) < 0) { 1208a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1209a7398723SShteryana Shopova exit(1); 1210a7398723SShteryana Shopova } 1211a7398723SShteryana Shopova 1212a7398723SShteryana Shopova /* A simple sanity check - can not send GETBULK when using SNMPv1. */ 1213a7398723SShteryana Shopova if (program == BSNMPGET && snmp_client.version == SNMP_V1 && 1214a7398723SShteryana Shopova GET_PDUTYPE(&snmptoolctx) == SNMP_PDU_GETBULK) { 1215a7398723SShteryana Shopova fprintf(stderr, "Cannot send GETBULK PDU with SNMPv1.\n"); 1216a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1217a7398723SShteryana Shopova exit(1); 1218a7398723SShteryana Shopova } 1219a7398723SShteryana Shopova 1220a7398723SShteryana Shopova for (last_oid = argc - 1; oid_cnt > 0; last_oid--, oid_cnt--) { 1221a7398723SShteryana Shopova if ((snmp_object_add(&snmptoolctx, (program == BSNMPSET) ? 1222a7398723SShteryana Shopova snmpset_parse_oid : snmptools_parse_oid, 1223a7398723SShteryana Shopova argv[last_oid])) < 0) { 1224a7398723SShteryana Shopova fprintf(stderr, "Error parsing OID string '%s'.\n", 1225a7398723SShteryana Shopova argv[last_oid]); 1226a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1227a7398723SShteryana Shopova exit(1); 1228a7398723SShteryana Shopova } 1229a7398723SShteryana Shopova } 1230a7398723SShteryana Shopova 1231a7398723SShteryana Shopova if (snmp_open(NULL, NULL, NULL, NULL)) { 1232a7398723SShteryana Shopova warnx("Failed to open snmp session: %s.", strerror(errno)); 1233a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1234a7398723SShteryana Shopova exit(1); 1235a7398723SShteryana Shopova } 1236a7398723SShteryana Shopova 1237a7398723SShteryana Shopova if (snmp_client.version == SNMP_V3 && snmp_client.engine.engine_len == 0) 1238a7398723SShteryana Shopova SET_EDISCOVER(&snmptoolctx); 1239a7398723SShteryana Shopova 1240a7398723SShteryana Shopova if (ISSET_EDISCOVER(&snmptoolctx) && 1241a7398723SShteryana Shopova snmp_discover_engine(snmptoolctx.passwd) < 0) { 1242a7398723SShteryana Shopova warnx("Unknown SNMP Engine ID: %s.", strerror(errno)); 1243a7398723SShteryana Shopova rc = 1; 1244a7398723SShteryana Shopova goto cleanup; 1245a7398723SShteryana Shopova } 1246a7398723SShteryana Shopova 1247a7398723SShteryana Shopova if (GET_OUTPUT(&snmptoolctx) == OUTPUT_VERBOSE || 1248a7398723SShteryana Shopova ISSET_EDISCOVER(&snmptoolctx)) 1249a7398723SShteryana Shopova snmp_output_engine(); 1250a7398723SShteryana Shopova 1251a7398723SShteryana Shopova if (snmp_client.version == SNMP_V3 && ISSET_LOCALKEY(&snmptoolctx) && 1252a7398723SShteryana Shopova !ISSET_EDISCOVER(&snmptoolctx)) { 1253a7398723SShteryana Shopova if (snmp_passwd_to_keys(&snmp_client.user, 1254a7398723SShteryana Shopova snmptoolctx.passwd) != SNMP_CODE_OK || 1255a7398723SShteryana Shopova snmp_get_local_keys(&snmp_client.user, 1256a7398723SShteryana Shopova snmp_client.engine.engine_id, 1257a7398723SShteryana Shopova snmp_client.engine.engine_len) != SNMP_CODE_OK) { 1258a7398723SShteryana Shopova warnx("Failed to get keys: %s.", strerror(errno)); 1259a7398723SShteryana Shopova rc = 1; 1260a7398723SShteryana Shopova goto cleanup; 1261a7398723SShteryana Shopova } 1262a7398723SShteryana Shopova } 1263a7398723SShteryana Shopova 1264a7398723SShteryana Shopova if (GET_OUTPUT(&snmptoolctx) == OUTPUT_VERBOSE || 1265a7398723SShteryana Shopova ISSET_EDISCOVER(&snmptoolctx)) 1266a7398723SShteryana Shopova snmp_output_keys(); 1267a7398723SShteryana Shopova 1268a7398723SShteryana Shopova if (ISSET_EDISCOVER(&snmptoolctx) && snmptoolctx.objects == 0) 1269a7398723SShteryana Shopova goto cleanup; 1270a7398723SShteryana Shopova 1271a7398723SShteryana Shopova switch (program) { 1272a7398723SShteryana Shopova case BSNMPGET: 1273a7398723SShteryana Shopova rc = snmptool_get(&snmptoolctx); 1274a7398723SShteryana Shopova break; 1275a7398723SShteryana Shopova case BSNMPWALK: 1276a7398723SShteryana Shopova rc = snmptool_walk(&snmptoolctx); 1277a7398723SShteryana Shopova break; 1278a7398723SShteryana Shopova case BSNMPSET: 1279a7398723SShteryana Shopova rc = snmptool_set(&snmptoolctx); 1280a7398723SShteryana Shopova break; 1281a7398723SShteryana Shopova } 1282a7398723SShteryana Shopova 1283a7398723SShteryana Shopova 1284a7398723SShteryana Shopova cleanup: 1285a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1286a7398723SShteryana Shopova snmp_close(); 1287a7398723SShteryana Shopova 1288a7398723SShteryana Shopova exit(rc); 1289a7398723SShteryana Shopova } 1290