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) { 3977c933da6SEnji Cooper warn("Snmp dialog"); 398a7398723SShteryana Shopova break; 399a7398723SShteryana Shopova } 400a7398723SShteryana Shopova 401a7398723SShteryana Shopova if (snmp_parse_resp(&resp, &req) >= 0) { 402b9288caaSShteryana Shopova snmp_output_resp(snmptoolctx, &resp, NULL); 403*570afb92SEnji Cooper snmp_pdu_free(&resp); 404a7398723SShteryana Shopova break; 405a7398723SShteryana Shopova } 406a7398723SShteryana Shopova 407a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 408a7398723SShteryana Shopova if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK || 409*570afb92SEnji Cooper !ISSET_RETRY(snmptoolctx)) { 410*570afb92SEnji Cooper snmp_pdu_free(&resp); 411a7398723SShteryana Shopova break; 412*570afb92SEnji Cooper } 413a7398723SShteryana Shopova 414a7398723SShteryana Shopova /* 415a7398723SShteryana Shopova * Loop through the object list and set object->error to the 416a7398723SShteryana Shopova * varbinding that caused the error. 417a7398723SShteryana Shopova */ 418a7398723SShteryana Shopova if (snmp_object_seterror(snmptoolctx, 419a7398723SShteryana Shopova &(resp.bindings[resp.error_index - 1]), 420*570afb92SEnji Cooper resp.error_status) <= 0) { 421*570afb92SEnji Cooper snmp_pdu_free(&resp); 422a7398723SShteryana Shopova break; 423*570afb92SEnji Cooper } 424a7398723SShteryana Shopova 425a7398723SShteryana Shopova fprintf(stderr, "Retrying...\n"); 426a7398723SShteryana Shopova snmp_pdu_free(&resp); 427a7398723SShteryana Shopova snmp_pdu_create(&req, GET_PDUTYPE(snmptoolctx)); 428a7398723SShteryana Shopova } 429a7398723SShteryana Shopova 4301b135e4fSEnji Cooper snmp_pdu_free(&req); 431a7398723SShteryana Shopova 432a7398723SShteryana Shopova return (0); 433a7398723SShteryana Shopova } 434a7398723SShteryana Shopova 435a7398723SShteryana Shopova 436a7398723SShteryana Shopova /* ***************************************************************************** 437a7398723SShteryana Shopova * bsnmpwalk private functions. 438a7398723SShteryana Shopova */ 439a7398723SShteryana Shopova /* The default tree to walk. */ 440a7398723SShteryana Shopova static const struct asn_oid snmp_mibII_OID = { 441a7398723SShteryana Shopova 6 , { 1, 3, 6, 1, 2, 1 } 442a7398723SShteryana Shopova }; 443a7398723SShteryana Shopova 444a7398723SShteryana Shopova static int32_t 445a7398723SShteryana Shopova snmpwalk_add_default(struct snmp_toolinfo *snmptoolctx __unused, 446a7398723SShteryana Shopova struct snmp_object *obj, char *string __unused) 447a7398723SShteryana Shopova { 448a7398723SShteryana Shopova asn_append_oid(&(obj->val.var), &snmp_mibII_OID); 449a7398723SShteryana Shopova return (1); 450a7398723SShteryana Shopova } 451a7398723SShteryana Shopova 452a7398723SShteryana Shopova /* 453a7398723SShteryana Shopova * Prepare the next GetNext/Get PDU to send. 454a7398723SShteryana Shopova */ 455a7398723SShteryana Shopova static void 456a7398723SShteryana Shopova snmpwalk_nextpdu_create(uint32_t op, struct asn_oid *var, struct snmp_pdu *pdu) 457a7398723SShteryana Shopova { 458a7398723SShteryana Shopova snmp_pdu_create(pdu, op); 459a7398723SShteryana Shopova asn_append_oid(&(pdu->bindings[0].var), var); 460a7398723SShteryana Shopova pdu->nbindings = 1; 461a7398723SShteryana Shopova } 462a7398723SShteryana Shopova 463a7398723SShteryana Shopova static int 464a7398723SShteryana Shopova snmptool_walk(struct snmp_toolinfo *snmptoolctx) 465a7398723SShteryana Shopova { 466a7398723SShteryana Shopova struct snmp_pdu req, resp; 4673df5ecacSUlrich Spörlein struct asn_oid root; /* Keep the initial oid. */ 468a7398723SShteryana Shopova int32_t outputs, rc; 469b9288caaSShteryana Shopova uint32_t op; 470a7398723SShteryana Shopova 471b9288caaSShteryana Shopova if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK) 472b9288caaSShteryana Shopova op = SNMP_PDU_GETBULK; 473b9288caaSShteryana Shopova else 474b9288caaSShteryana Shopova op = SNMP_PDU_GETNEXT; 475b9288caaSShteryana Shopova 476b9288caaSShteryana Shopova snmp_pdu_create(&req, op); 477a7398723SShteryana Shopova 478a7398723SShteryana Shopova while ((rc = snmp_pdu_add_bindings(snmptoolctx, NULL, 479a7398723SShteryana Shopova snmptool_add_vbind, &req, 1)) > 0) { 480a7398723SShteryana Shopova 481a7398723SShteryana Shopova /* Remember the root where the walk started from. */ 482a7398723SShteryana Shopova memset(&root, 0, sizeof(struct asn_oid)); 483a7398723SShteryana Shopova asn_append_oid(&root, &(req.bindings[0].var)); 484a7398723SShteryana Shopova 485b9288caaSShteryana Shopova if (op == SNMP_PDU_GETBULK) 486b9288caaSShteryana Shopova snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), 487b9288caaSShteryana Shopova GET_NONREP(snmptoolctx)); 488b9288caaSShteryana Shopova 489a7398723SShteryana Shopova outputs = 0; 490a7398723SShteryana Shopova while (snmp_dialog(&req, &resp) >= 0) { 491a7398723SShteryana Shopova if ((snmp_parse_resp(&resp, &req)) < 0) { 492a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 493a7398723SShteryana Shopova snmp_pdu_free(&resp); 494a7398723SShteryana Shopova outputs = -1; 495a7398723SShteryana Shopova break; 496a7398723SShteryana Shopova } 497a7398723SShteryana Shopova 498b9288caaSShteryana Shopova rc = snmp_output_resp(snmptoolctx, &resp, &root); 499b9288caaSShteryana Shopova if (rc < 0) { 500a7398723SShteryana Shopova snmp_pdu_free(&resp); 501a7398723SShteryana Shopova outputs = -1; 502a7398723SShteryana Shopova break; 503a7398723SShteryana Shopova } 504b9288caaSShteryana Shopova 505b9288caaSShteryana Shopova outputs += rc; 506a7398723SShteryana Shopova 507*570afb92SEnji Cooper if ((u_int)rc < resp.nbindings) { 508*570afb92SEnji Cooper snmp_pdu_free(&resp); 509b9288caaSShteryana Shopova break; 510*570afb92SEnji Cooper } 511b9288caaSShteryana Shopova 512b9288caaSShteryana Shopova snmpwalk_nextpdu_create(op, 513b9288caaSShteryana Shopova &(resp.bindings[resp.nbindings - 1].var), &req); 514b9288caaSShteryana Shopova if (op == SNMP_PDU_GETBULK) 515b9288caaSShteryana Shopova snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx), 516b9288caaSShteryana Shopova GET_NONREP(snmptoolctx)); 5171b135e4fSEnji Cooper snmp_pdu_free(&resp); 518a7398723SShteryana Shopova } 519a7398723SShteryana Shopova 520a7398723SShteryana Shopova /* Just in case our root was a leaf. */ 521a7398723SShteryana Shopova if (outputs == 0) { 522a7398723SShteryana Shopova snmpwalk_nextpdu_create(SNMP_PDU_GET, &root, &req); 523a7398723SShteryana Shopova if (snmp_dialog(&req, &resp) == SNMP_CODE_OK) { 524a7398723SShteryana Shopova if (snmp_parse_resp(&resp, &req) < 0) 525a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 526a7398723SShteryana Shopova else 527*570afb92SEnji Cooper snmp_output_resp(snmptoolctx, &resp, 528*570afb92SEnji Cooper NULL); 5291b135e4fSEnji Cooper snmp_pdu_free(&resp); 530a7398723SShteryana Shopova } else 5317c933da6SEnji Cooper warn("Snmp dialog"); 532a7398723SShteryana Shopova } 533a7398723SShteryana Shopova 534a7398723SShteryana Shopova if (snmp_object_remove(snmptoolctx, &root) < 0) { 535a7398723SShteryana Shopova warnx("snmp_object_remove"); 536a7398723SShteryana Shopova break; 537a7398723SShteryana Shopova } 538a7398723SShteryana Shopova 5391b135e4fSEnji Cooper snmp_pdu_free(&req); 540b9288caaSShteryana Shopova snmp_pdu_create(&req, op); 541a7398723SShteryana Shopova } 542a7398723SShteryana Shopova 5431b135e4fSEnji Cooper snmp_pdu_free(&req); 5441b135e4fSEnji Cooper 545a7398723SShteryana Shopova if (rc == 0) 546a7398723SShteryana Shopova return (0); 547a7398723SShteryana Shopova else 548a7398723SShteryana Shopova return (1); 549a7398723SShteryana Shopova } 550a7398723SShteryana Shopova 551a7398723SShteryana Shopova /* ***************************************************************************** 552a7398723SShteryana Shopova * bsnmpset private functions. 553a7398723SShteryana Shopova */ 554a7398723SShteryana Shopova 555a7398723SShteryana Shopova static int32_t 556a7398723SShteryana Shopova parse_oid_numeric(struct snmp_value *value, char *val) 557a7398723SShteryana Shopova { 558a7398723SShteryana Shopova char *endptr; 559a7398723SShteryana Shopova int32_t saved_errno; 560a7398723SShteryana Shopova asn_subid_t suboid; 561a7398723SShteryana Shopova 562a7398723SShteryana Shopova do { 563a7398723SShteryana Shopova saved_errno = errno; 564a7398723SShteryana Shopova errno = 0; 565a7398723SShteryana Shopova suboid = strtoul(val, &endptr, 10); 566a7398723SShteryana Shopova if (errno != 0) { 5677c933da6SEnji Cooper warn("Value %s not supported", val); 568a7398723SShteryana Shopova errno = saved_errno; 569a7398723SShteryana Shopova return (-1); 570a7398723SShteryana Shopova } 571a7398723SShteryana Shopova errno = saved_errno; 572a7398723SShteryana Shopova if ((asn_subid_t) suboid > ASN_MAXID) { 573a7398723SShteryana Shopova warnx("Suboid %u > ASN_MAXID", suboid); 574a7398723SShteryana Shopova return (-1); 575a7398723SShteryana Shopova } 576a7398723SShteryana Shopova if (snmp_suboid_append(&(value->v.oid), suboid) < 0) 577a7398723SShteryana Shopova return (-1); 578a7398723SShteryana Shopova val = endptr + 1; 579a7398723SShteryana Shopova } while (*endptr == '.'); 580a7398723SShteryana Shopova 581a7398723SShteryana Shopova if (*endptr != '\0') 582a7398723SShteryana Shopova warnx("OID value %s not supported", val); 583a7398723SShteryana Shopova 584a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_OID; 585a7398723SShteryana Shopova return (0); 586a7398723SShteryana Shopova } 587a7398723SShteryana Shopova 588a7398723SShteryana Shopova /* 589a7398723SShteryana Shopova * Allow OID leaf in both forms: 590a7398723SShteryana Shopova * 1) 1.3.6.1.2... -> in such case call directly the function reading raw OIDs; 591a7398723SShteryana Shopova * 2) begemotSnmpdAgentFreeBSD -> lookup the ASN OID corresponding to that. 592a7398723SShteryana Shopova */ 593a7398723SShteryana Shopova static int32_t 594a7398723SShteryana Shopova parse_oid_string(struct snmp_toolinfo *snmptoolctx, 595a7398723SShteryana Shopova struct snmp_value *value, char *string) 596a7398723SShteryana Shopova { 597a7398723SShteryana Shopova struct snmp_object obj; 598a7398723SShteryana Shopova 599a7398723SShteryana Shopova if (isdigit(string[0])) 600a7398723SShteryana Shopova return (parse_oid_numeric(value, string)); 601a7398723SShteryana Shopova 602a7398723SShteryana Shopova memset(&obj, 0, sizeof(struct snmp_object)); 603a7398723SShteryana Shopova if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) { 604a7398723SShteryana Shopova warnx("Unknown OID enum string - %s", string); 605a7398723SShteryana Shopova return (-1); 606a7398723SShteryana Shopova } 607a7398723SShteryana Shopova 608a7398723SShteryana Shopova asn_append_oid(&(value->v.oid), &(obj.val.var)); 609a7398723SShteryana Shopova return (1); 610a7398723SShteryana Shopova } 611a7398723SShteryana Shopova 612a7398723SShteryana Shopova static int32_t 613a7398723SShteryana Shopova parse_ip(struct snmp_value * value, char * val) 614a7398723SShteryana Shopova { 615a7398723SShteryana Shopova char *endptr, *str; 616f16a380fSEnji Cooper int32_t i; 617f16a380fSEnji Cooper uint32_t v; 618a7398723SShteryana Shopova 619a7398723SShteryana Shopova str = val; 620a7398723SShteryana Shopova for (i = 0; i < 4; i++) { 621a7398723SShteryana Shopova v = strtoul(str, &endptr, 10); 622a7398723SShteryana Shopova if (v > 0xff) 623a7398723SShteryana Shopova return (-1); 624a7398723SShteryana Shopova if (*endptr != '.' && *endptr != '\0' && i != 3) 625a7398723SShteryana Shopova break; 626a7398723SShteryana Shopova str = endptr + 1; 627a7398723SShteryana Shopova value->v.ipaddress[i] = (uint8_t) v; 628a7398723SShteryana Shopova } 629a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_IPADDRESS; 630f16a380fSEnji Cooper 631a7398723SShteryana Shopova return (0); 632a7398723SShteryana Shopova } 633a7398723SShteryana Shopova 634a7398723SShteryana Shopova static int32_t 635a7398723SShteryana Shopova parse_int(struct snmp_value *value, char *val) 636a7398723SShteryana Shopova { 637a7398723SShteryana Shopova char *endptr; 638a7398723SShteryana Shopova int32_t v, saved_errno; 639a7398723SShteryana Shopova 640a7398723SShteryana Shopova saved_errno = errno; 641a7398723SShteryana Shopova errno = 0; 642a7398723SShteryana Shopova 643a7398723SShteryana Shopova v = strtol(val, &endptr, 10); 644a7398723SShteryana Shopova 645a7398723SShteryana Shopova if (errno != 0) { 6467c933da6SEnji Cooper warn("Value %s not supported", val); 647a7398723SShteryana Shopova errno = saved_errno; 648a7398723SShteryana Shopova return (-1); 649a7398723SShteryana Shopova } 650a7398723SShteryana Shopova 651a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_INTEGER; 652a7398723SShteryana Shopova value->v.integer = v; 653a7398723SShteryana Shopova errno = saved_errno; 654a7398723SShteryana Shopova 655a7398723SShteryana Shopova return (0); 656a7398723SShteryana Shopova } 657a7398723SShteryana Shopova 658a7398723SShteryana Shopova static int32_t 659a7398723SShteryana Shopova parse_int_string(struct snmp_object *object, char *val) 660a7398723SShteryana Shopova { 661a7398723SShteryana Shopova int32_t v; 662a7398723SShteryana Shopova 663a7398723SShteryana Shopova if (isdigit(val[0])) 664a7398723SShteryana Shopova return ((parse_int(&(object->val), val))); 665a7398723SShteryana Shopova 666a7398723SShteryana Shopova if (object->info == NULL) { 667a7398723SShteryana Shopova warnx("Unknown enumerated integer type - %s", val); 668a7398723SShteryana Shopova return (-1); 669a7398723SShteryana Shopova } 670a7398723SShteryana Shopova if ((v = enum_number_lookup(object->info->snmp_enum, val)) < 0) 671a7398723SShteryana Shopova warnx("Unknown enumerated integer type - %s", val); 672a7398723SShteryana Shopova 673a7398723SShteryana Shopova object->val.v.integer = v; 674a7398723SShteryana Shopova return (1); 675a7398723SShteryana Shopova } 676a7398723SShteryana Shopova 677a7398723SShteryana Shopova /* 678a7398723SShteryana Shopova * Here syntax may be one of SNMP_SYNTAX_COUNTER, SNMP_SYNTAX_GAUGE, 679a7398723SShteryana Shopova * SNMP_SYNTAX_TIMETICKS. 680a7398723SShteryana Shopova */ 681a7398723SShteryana Shopova static int32_t 682a7398723SShteryana Shopova parse_uint(struct snmp_value *value, char *val) 683a7398723SShteryana Shopova { 684a7398723SShteryana Shopova char *endptr; 685a7398723SShteryana Shopova uint32_t v = 0; 686a7398723SShteryana Shopova int32_t saved_errno; 687a7398723SShteryana Shopova 688a7398723SShteryana Shopova saved_errno = errno; 689a7398723SShteryana Shopova errno = 0; 690a7398723SShteryana Shopova 691a7398723SShteryana Shopova v = strtoul(val, &endptr, 10); 692a7398723SShteryana Shopova 693a7398723SShteryana Shopova if (errno != 0) { 6947c933da6SEnji Cooper warn("Value %s not supported", val); 695a7398723SShteryana Shopova errno = saved_errno; 696a7398723SShteryana Shopova return (-1); 697a7398723SShteryana Shopova } 698a7398723SShteryana Shopova 699a7398723SShteryana Shopova value->v.uint32 = v; 700a7398723SShteryana Shopova errno = saved_errno; 701a7398723SShteryana Shopova 702a7398723SShteryana Shopova return (0); 703a7398723SShteryana Shopova } 704a7398723SShteryana Shopova 705a7398723SShteryana Shopova static int32_t 706a7398723SShteryana Shopova parse_ticks(struct snmp_value *value, char *val) 707a7398723SShteryana Shopova { 708a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 709a7398723SShteryana Shopova return (-1); 710a7398723SShteryana Shopova 711a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_TIMETICKS; 712a7398723SShteryana Shopova return (0); 713a7398723SShteryana Shopova } 714a7398723SShteryana Shopova 715a7398723SShteryana Shopova static int32_t 716a7398723SShteryana Shopova parse_gauge(struct snmp_value *value, char *val) 717a7398723SShteryana Shopova { 718a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 719a7398723SShteryana Shopova return (-1); 720a7398723SShteryana Shopova 721a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_GAUGE; 722a7398723SShteryana Shopova return (0); 723a7398723SShteryana Shopova } 724a7398723SShteryana Shopova 725a7398723SShteryana Shopova static int32_t 726a7398723SShteryana Shopova parse_counter(struct snmp_value *value, char *val) 727a7398723SShteryana Shopova { 728a7398723SShteryana Shopova if (parse_uint(value, val) < 0) 729a7398723SShteryana Shopova return (-1); 730a7398723SShteryana Shopova 731a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_COUNTER; 732a7398723SShteryana Shopova return (0); 733a7398723SShteryana Shopova } 734a7398723SShteryana Shopova 735a7398723SShteryana Shopova static int32_t 736a7398723SShteryana Shopova parse_uint64(struct snmp_value *value, char *val) 737a7398723SShteryana Shopova { 738a7398723SShteryana Shopova char *endptr; 739a7398723SShteryana Shopova int32_t saved_errno; 740a7398723SShteryana Shopova uint64_t v; 741a7398723SShteryana Shopova 742a7398723SShteryana Shopova saved_errno = errno; 743a7398723SShteryana Shopova errno = 0; 744a7398723SShteryana Shopova 745a7398723SShteryana Shopova v = strtoull(val, &endptr, 10); 746a7398723SShteryana Shopova 747a7398723SShteryana Shopova if (errno != 0) { 7487c933da6SEnji Cooper warnx("Value %s not supported", val); 749a7398723SShteryana Shopova errno = saved_errno; 750a7398723SShteryana Shopova return (-1); 751a7398723SShteryana Shopova } 752a7398723SShteryana Shopova 753a7398723SShteryana Shopova value->syntax = SNMP_SYNTAX_COUNTER64; 754a7398723SShteryana Shopova value->v.counter64 = v; 755a7398723SShteryana Shopova errno = saved_errno; 756a7398723SShteryana Shopova 757a7398723SShteryana Shopova return (0); 758a7398723SShteryana Shopova } 759a7398723SShteryana Shopova 760a7398723SShteryana Shopova static int32_t 761a7398723SShteryana Shopova parse_syntax_val(struct snmp_value *value, enum snmp_syntax syntax, char *val) 762a7398723SShteryana Shopova { 763a7398723SShteryana Shopova switch (syntax) { 764a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 765a7398723SShteryana Shopova return (parse_int(value, val)); 766a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 767a7398723SShteryana Shopova return (parse_ip(value, val)); 768a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 769a7398723SShteryana Shopova return (parse_counter(value, val)); 770a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 771a7398723SShteryana Shopova return (parse_gauge(value, val)); 772a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 773a7398723SShteryana Shopova return (parse_ticks(value, val)); 774a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 775a7398723SShteryana Shopova return (parse_uint64(value, val)); 776a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 777a7398723SShteryana Shopova return (snmp_tc2oct(SNMP_STRING, value, val)); 778a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 779a7398723SShteryana Shopova return (parse_oid_numeric(value, val)); 780a7398723SShteryana Shopova default: 781a7398723SShteryana Shopova /* NOTREACHED */ 782a7398723SShteryana Shopova break; 783a7398723SShteryana Shopova } 784a7398723SShteryana Shopova 785a7398723SShteryana Shopova return (-1); 786a7398723SShteryana Shopova } 787a7398723SShteryana Shopova 788a7398723SShteryana Shopova /* 789a7398723SShteryana Shopova * Parse a command line argument of type OID=syntax:value and fill in whatever 790a7398723SShteryana Shopova * fields can be derived from the input into snmp_value structure. Reads numeric 791a7398723SShteryana Shopova * OIDs. 792a7398723SShteryana Shopova */ 793a7398723SShteryana Shopova static int32_t 794a7398723SShteryana Shopova parse_pair_numoid_val(char *str, struct snmp_value *snmp_val) 795a7398723SShteryana Shopova { 796a7398723SShteryana Shopova int32_t cnt; 797a7398723SShteryana Shopova char *ptr; 798a7398723SShteryana Shopova enum snmp_syntax syntax; 799a7398723SShteryana Shopova char oid_str[ASN_OIDSTRLEN]; 800a7398723SShteryana Shopova 801a7398723SShteryana Shopova ptr = str; 802a7398723SShteryana Shopova for (cnt = 0; cnt < ASN_OIDSTRLEN; cnt++) 803a7398723SShteryana Shopova if (ptr[cnt] == '=') 804a7398723SShteryana Shopova break; 805a7398723SShteryana Shopova 806a7398723SShteryana Shopova if (cnt >= ASN_OIDSTRLEN) { 807a7398723SShteryana Shopova warnx("OID too long - %s", str); 808a7398723SShteryana Shopova return (-1); 809a7398723SShteryana Shopova } 810a7398723SShteryana Shopova strlcpy(oid_str, ptr, (size_t) (cnt + 1)); 811a7398723SShteryana Shopova 812a7398723SShteryana Shopova ptr = str + cnt + 1; 813a7398723SShteryana Shopova for (cnt = 0; cnt < MAX_CMD_SYNTAX_LEN; cnt++) 814a7398723SShteryana Shopova if(ptr[cnt] == ':') 815a7398723SShteryana Shopova break; 816a7398723SShteryana Shopova 817a7398723SShteryana Shopova if (cnt >= MAX_CMD_SYNTAX_LEN) { 818a7398723SShteryana Shopova warnx("Unknown syntax in OID - %s", str); 819a7398723SShteryana Shopova return (-1); 820a7398723SShteryana Shopova } 821a7398723SShteryana Shopova 822a7398723SShteryana Shopova if ((syntax = parse_syntax(ptr)) <= SNMP_SYNTAX_NULL) { 823a7398723SShteryana Shopova warnx("Unknown syntax in OID - %s", ptr); 824a7398723SShteryana Shopova return (-1); 825a7398723SShteryana Shopova } 826a7398723SShteryana Shopova 827a7398723SShteryana Shopova ptr = ptr + cnt + 1; 828a7398723SShteryana Shopova for (cnt = 0; cnt < MAX_OCTSTRING_LEN; cnt++) 829a7398723SShteryana Shopova if (ptr[cnt] == '\0') 830a7398723SShteryana Shopova break; 831a7398723SShteryana Shopova 832a7398723SShteryana Shopova if (ptr[cnt] != '\0') { 833a7398723SShteryana Shopova warnx("Value string too long - %s", ptr); 834a7398723SShteryana Shopova return (-1); 835a7398723SShteryana Shopova } 836a7398723SShteryana Shopova 837a7398723SShteryana Shopova /* 838a7398723SShteryana Shopova * Here try parsing the OIDs and syntaxes and then check values - have 839a7398723SShteryana Shopova * to know syntax to check value boundaries. 840a7398723SShteryana Shopova */ 841a7398723SShteryana Shopova if (snmp_parse_numoid(oid_str, &(snmp_val->var)) < 0) { 842a7398723SShteryana Shopova warnx("Error parsing OID %s", oid_str); 843a7398723SShteryana Shopova return (-1); 844a7398723SShteryana Shopova } 845a7398723SShteryana Shopova 846a7398723SShteryana Shopova if (parse_syntax_val(snmp_val, syntax, ptr) < 0) 847a7398723SShteryana Shopova return (-1); 848a7398723SShteryana Shopova 849a7398723SShteryana Shopova return (1); 850a7398723SShteryana Shopova } 851a7398723SShteryana Shopova 852a7398723SShteryana Shopova /* XXX-BZ aruments should be swapped. */ 853a7398723SShteryana Shopova static int32_t 854a7398723SShteryana Shopova parse_syntax_strval(struct snmp_toolinfo *snmptoolctx, char *str, 855a7398723SShteryana Shopova struct snmp_object *object) 856a7398723SShteryana Shopova { 857a7398723SShteryana Shopova uint32_t len; 858a7398723SShteryana Shopova enum snmp_syntax syn; 859a7398723SShteryana Shopova 860a7398723SShteryana Shopova /* 861a7398723SShteryana Shopova * Syntax string here not required - still may be present. 862a7398723SShteryana Shopova */ 863a7398723SShteryana Shopova 864a7398723SShteryana Shopova if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) { 865a7398723SShteryana Shopova for (len = 0 ; *(str + len) != ':'; len++) { 866a7398723SShteryana Shopova if (*(str + len) == '\0') { 867a7398723SShteryana Shopova warnx("Syntax missing in value - %s", str); 868a7398723SShteryana Shopova return (-1); 869a7398723SShteryana Shopova } 870a7398723SShteryana Shopova } 871a7398723SShteryana Shopova if ((syn = parse_syntax(str)) <= SNMP_SYNTAX_NULL) { 872a7398723SShteryana Shopova warnx("Unknown syntax in - %s", str); 873a7398723SShteryana Shopova return (-1); 874a7398723SShteryana Shopova } 875a7398723SShteryana Shopova if (syn != object->val.syntax) { 876a7398723SShteryana Shopova if (!ISSET_ERRIGNORE(snmptoolctx)) { 877a7398723SShteryana Shopova warnx("Bad syntax in - %s", str); 878a7398723SShteryana Shopova return (-1); 879a7398723SShteryana Shopova } else 880a7398723SShteryana Shopova object->val.syntax = syn; 881a7398723SShteryana Shopova } 882a7398723SShteryana Shopova len++; 883a7398723SShteryana Shopova } else 884a7398723SShteryana Shopova len = 0; 885a7398723SShteryana Shopova 886a7398723SShteryana Shopova switch (object->val.syntax) { 887a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 888a7398723SShteryana Shopova return (parse_int_string(object, str + len)); 889a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 890a7398723SShteryana Shopova return (parse_ip(&(object->val), str + len)); 891a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 892a7398723SShteryana Shopova return (parse_counter(&(object->val), str + len)); 893a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 894a7398723SShteryana Shopova return (parse_gauge(&(object->val), str + len)); 895a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 896a7398723SShteryana Shopova return (parse_ticks(&(object->val), str + len)); 897a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 898a7398723SShteryana Shopova return (parse_uint64(&(object->val), str + len)); 899a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 900a7398723SShteryana Shopova return (snmp_tc2oct(object->info->tc, &(object->val), 901a7398723SShteryana Shopova str + len)); 902a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 903a7398723SShteryana Shopova return (parse_oid_string(snmptoolctx, &(object->val), 904a7398723SShteryana Shopova str + len)); 905a7398723SShteryana Shopova default: 906a7398723SShteryana Shopova /* NOTREACHED */ 907a7398723SShteryana Shopova break; 908a7398723SShteryana Shopova } 909a7398723SShteryana Shopova 910a7398723SShteryana Shopova return (-1); 911a7398723SShteryana Shopova } 912a7398723SShteryana Shopova 913a7398723SShteryana Shopova static int32_t 914a7398723SShteryana Shopova parse_pair_stroid_val(struct snmp_toolinfo *snmptoolctx, 915a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 916a7398723SShteryana Shopova { 917a7398723SShteryana Shopova char *ptr; 918a7398723SShteryana Shopova 919a7398723SShteryana Shopova if ((ptr = snmptools_parse_stroid(snmptoolctx, obj, argv)) == NULL) 920a7398723SShteryana Shopova return (-1); 921a7398723SShteryana Shopova 922a7398723SShteryana Shopova if (*ptr != '=') { 923a7398723SShteryana Shopova warnx("Value to set expected after OID"); 924a7398723SShteryana Shopova return (-1); 925a7398723SShteryana Shopova } 926a7398723SShteryana Shopova 927a7398723SShteryana Shopova if (parse_syntax_strval(snmptoolctx, ptr + 1, obj) < 0) 928a7398723SShteryana Shopova return (-1); 929a7398723SShteryana Shopova 930a7398723SShteryana Shopova return (1); 931a7398723SShteryana Shopova } 932a7398723SShteryana Shopova 933a7398723SShteryana Shopova 934a7398723SShteryana Shopova static int32_t 935a7398723SShteryana Shopova snmpset_parse_oid(struct snmp_toolinfo *snmptoolctx, 936a7398723SShteryana Shopova struct snmp_object *obj, char *argv) 937a7398723SShteryana Shopova { 938a7398723SShteryana Shopova if (argv == NULL) 939a7398723SShteryana Shopova return (-1); 940a7398723SShteryana Shopova 941a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx)) { 942a7398723SShteryana Shopova if (parse_pair_numoid_val(argv, &(obj->val)) < 0) 943a7398723SShteryana Shopova return (-1); 944a7398723SShteryana Shopova } else { 945a7398723SShteryana Shopova if (parse_pair_stroid_val(snmptoolctx, obj, argv) < 0) 946a7398723SShteryana Shopova return (-1); 947a7398723SShteryana Shopova } 948a7398723SShteryana Shopova 949a7398723SShteryana Shopova return (1); 950a7398723SShteryana Shopova } 951a7398723SShteryana Shopova 952a7398723SShteryana Shopova static int32_t 953a7398723SShteryana Shopova add_ip_syntax(struct snmp_value *dst, struct snmp_value *src) 954a7398723SShteryana Shopova { 955a7398723SShteryana Shopova int8_t i; 956a7398723SShteryana Shopova 957a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_IPADDRESS; 958a7398723SShteryana Shopova for (i = 0; i < 4; i++) 959a7398723SShteryana Shopova dst->v.ipaddress[i] = src->v.ipaddress[i]; 960a7398723SShteryana Shopova 961a7398723SShteryana Shopova return (1); 962a7398723SShteryana Shopova } 963a7398723SShteryana Shopova 964a7398723SShteryana Shopova static int32_t 965a7398723SShteryana Shopova add_octstring_syntax(struct snmp_value *dst, struct snmp_value *src) 966a7398723SShteryana Shopova { 967a7398723SShteryana Shopova if (src->v.octetstring.len > ASN_MAXOCTETSTRING) { 968a7398723SShteryana Shopova warnx("OctetString len too big - %u", src->v.octetstring.len); 969a7398723SShteryana Shopova return (-1); 970a7398723SShteryana Shopova } 971a7398723SShteryana Shopova 972a7398723SShteryana Shopova if ((dst->v.octetstring.octets = malloc(src->v.octetstring.len)) == 973a7398723SShteryana Shopova NULL) { 974a7398723SShteryana Shopova syslog(LOG_ERR, "malloc() failed - %s", strerror(errno)); 975a7398723SShteryana Shopova return (-1); 976a7398723SShteryana Shopova } 977a7398723SShteryana Shopova 978a7398723SShteryana Shopova memcpy(dst->v.octetstring.octets, src->v.octetstring.octets, 979a7398723SShteryana Shopova src->v.octetstring.len); 980a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_OCTETSTRING; 981a7398723SShteryana Shopova dst->v.octetstring.len = src->v.octetstring.len; 982a7398723SShteryana Shopova 983a7398723SShteryana Shopova return(0); 984a7398723SShteryana Shopova } 985a7398723SShteryana Shopova 986a7398723SShteryana Shopova static int32_t 987a7398723SShteryana Shopova add_oid_syntax(struct snmp_value *dst, struct snmp_value *src) 988a7398723SShteryana Shopova { 989a7398723SShteryana Shopova asn_append_oid(&(dst->v.oid), &(src->v.oid)); 990a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_OID; 991a7398723SShteryana Shopova return (0); 992a7398723SShteryana Shopova } 993a7398723SShteryana Shopova 994a7398723SShteryana Shopova /* 995a7398723SShteryana Shopova * Check syntax - if one of SNMP_SYNTAX_NULL, SNMP_SYNTAX_NOSUCHOBJECT, 996a7398723SShteryana Shopova * SNMP_SYNTAX_NOSUCHINSTANCE, SNMP_SYNTAX_ENDOFMIBVIEW or anything not known - 997a7398723SShteryana Shopova * return error. 998a7398723SShteryana Shopova */ 999a7398723SShteryana Shopova static int32_t 1000a7398723SShteryana Shopova snmpset_add_value(struct snmp_value *dst, struct snmp_value *src) 1001a7398723SShteryana Shopova { 1002a7398723SShteryana Shopova if (dst == NULL || src == NULL) 1003a7398723SShteryana Shopova return (-1); 1004a7398723SShteryana Shopova 1005a7398723SShteryana Shopova switch (src->syntax) { 1006a7398723SShteryana Shopova case SNMP_SYNTAX_INTEGER: 1007a7398723SShteryana Shopova dst->v.integer = src->v.integer; 1008a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_INTEGER; 1009a7398723SShteryana Shopova break; 1010a7398723SShteryana Shopova case SNMP_SYNTAX_TIMETICKS: 1011a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1012a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_TIMETICKS; 1013a7398723SShteryana Shopova break; 1014a7398723SShteryana Shopova case SNMP_SYNTAX_GAUGE: 1015a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1016a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_GAUGE; 1017a7398723SShteryana Shopova break; 1018a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER: 1019a7398723SShteryana Shopova dst->v.uint32 = src->v.uint32; 1020a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_COUNTER; 1021a7398723SShteryana Shopova break; 1022a7398723SShteryana Shopova case SNMP_SYNTAX_COUNTER64: 1023a7398723SShteryana Shopova dst->v.counter64 = src->v.counter64; 1024a7398723SShteryana Shopova dst->syntax = SNMP_SYNTAX_COUNTER64; 1025a7398723SShteryana Shopova break; 1026a7398723SShteryana Shopova case SNMP_SYNTAX_IPADDRESS: 1027a7398723SShteryana Shopova add_ip_syntax(dst, src); 1028a7398723SShteryana Shopova break; 1029a7398723SShteryana Shopova case SNMP_SYNTAX_OCTETSTRING: 1030a7398723SShteryana Shopova add_octstring_syntax(dst, src); 1031a7398723SShteryana Shopova break; 1032a7398723SShteryana Shopova case SNMP_SYNTAX_OID: 1033a7398723SShteryana Shopova add_oid_syntax(dst, src); 1034a7398723SShteryana Shopova break; 1035a7398723SShteryana Shopova default: 1036a7398723SShteryana Shopova warnx("Unknown syntax %d", src->syntax); 1037a7398723SShteryana Shopova return (-1); 1038a7398723SShteryana Shopova } 1039a7398723SShteryana Shopova 1040a7398723SShteryana Shopova return (0); 1041a7398723SShteryana Shopova } 1042a7398723SShteryana Shopova 1043a7398723SShteryana Shopova static int32_t 1044a7398723SShteryana Shopova snmpset_verify_vbind(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu, 1045a7398723SShteryana Shopova struct snmp_object *obj) 1046a7398723SShteryana Shopova { 1047a7398723SShteryana Shopova if (pdu->version == SNMP_V1 && obj->val.syntax == 1048a7398723SShteryana Shopova SNMP_SYNTAX_COUNTER64) { 1049a7398723SShteryana Shopova warnx("64-bit counters are not supported in SNMPv1 PDU"); 1050a7398723SShteryana Shopova return (-1); 1051a7398723SShteryana Shopova } 1052a7398723SShteryana Shopova 1053a7398723SShteryana Shopova if (ISSET_NUMERIC(snmptoolctx) || ISSET_ERRIGNORE(snmptoolctx)) 1054a7398723SShteryana Shopova return (1); 1055a7398723SShteryana Shopova 1056a7398723SShteryana Shopova if (obj->info->access < SNMP_ACCESS_SET) { 1057a7398723SShteryana Shopova warnx("Object %s not accessible for set - try 'bsnmpset -a'", 1058a7398723SShteryana Shopova obj->info->string); 1059a7398723SShteryana Shopova return (-1); 1060a7398723SShteryana Shopova } 1061a7398723SShteryana Shopova 1062a7398723SShteryana Shopova return (1); 1063a7398723SShteryana Shopova } 1064a7398723SShteryana Shopova 1065a7398723SShteryana Shopova static int32_t 1066a7398723SShteryana Shopova snmpset_add_vbind(struct snmp_pdu *pdu, struct snmp_object *obj) 1067a7398723SShteryana Shopova { 1068a7398723SShteryana Shopova if (pdu->nbindings > SNMP_MAX_BINDINGS) { 1069a7398723SShteryana Shopova warnx("Too many OIDs for one PDU"); 1070a7398723SShteryana Shopova return (-1); 1071a7398723SShteryana Shopova } 1072a7398723SShteryana Shopova 1073a7398723SShteryana Shopova if (obj->error > 0) 1074a7398723SShteryana Shopova return (0); 1075a7398723SShteryana Shopova 1076a7398723SShteryana Shopova if (snmpset_add_value(&(pdu->bindings[pdu->nbindings]), &(obj->val)) 1077a7398723SShteryana Shopova < 0) 1078a7398723SShteryana Shopova return (-1); 1079a7398723SShteryana Shopova 1080a7398723SShteryana Shopova asn_append_oid(&(pdu->bindings[pdu->nbindings].var), &(obj->val.var)); 1081a7398723SShteryana Shopova pdu->nbindings++; 1082a7398723SShteryana Shopova 1083a7398723SShteryana Shopova return (pdu->nbindings); 1084a7398723SShteryana Shopova } 1085a7398723SShteryana Shopova 1086a7398723SShteryana Shopova static int 1087a7398723SShteryana Shopova snmptool_set(struct snmp_toolinfo *snmptoolctx) 1088a7398723SShteryana Shopova { 1089a7398723SShteryana Shopova struct snmp_pdu req, resp; 1090a7398723SShteryana Shopova 1091a7398723SShteryana Shopova snmp_pdu_create(&req, SNMP_PDU_SET); 1092a7398723SShteryana Shopova 1093a7398723SShteryana Shopova while ((snmp_pdu_add_bindings(snmptoolctx, snmpset_verify_vbind, 1094a7398723SShteryana Shopova snmpset_add_vbind, &req, SNMP_MAX_BINDINGS)) > 0) { 1095a7398723SShteryana Shopova if (snmp_dialog(&req, &resp)) { 10967c933da6SEnji Cooper warn("Snmp dialog"); 1097a7398723SShteryana Shopova break; 1098a7398723SShteryana Shopova } 1099a7398723SShteryana Shopova 1100a7398723SShteryana Shopova if (snmp_pdu_check(&req, &resp) > 0) { 1101a7398723SShteryana Shopova if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) 1102b9288caaSShteryana Shopova snmp_output_resp(snmptoolctx, &resp, NULL); 1103*570afb92SEnji Cooper snmp_pdu_free(&resp); 1104a7398723SShteryana Shopova break; 1105a7398723SShteryana Shopova } 1106a7398723SShteryana Shopova 1107a7398723SShteryana Shopova snmp_output_err_resp(snmptoolctx, &resp); 1108*570afb92SEnji Cooper if (!ISSET_RETRY(snmptoolctx)) { 1109*570afb92SEnji Cooper snmp_pdu_free(&resp); 1110a7398723SShteryana Shopova break; 1111*570afb92SEnji Cooper } 1112a7398723SShteryana Shopova 1113a7398723SShteryana Shopova if (snmp_object_seterror(snmptoolctx, 1114a7398723SShteryana Shopova &(resp.bindings[resp.error_index - 1]), 1115*570afb92SEnji Cooper resp.error_status) <= 0) { 1116*570afb92SEnji Cooper snmp_pdu_free(&resp); 1117a7398723SShteryana Shopova break; 1118*570afb92SEnji Cooper } 1119a7398723SShteryana Shopova 1120a7398723SShteryana Shopova fprintf(stderr, "Retrying...\n"); 1121a7398723SShteryana Shopova snmp_pdu_free(&req); 1122a7398723SShteryana Shopova snmp_pdu_create(&req, SNMP_PDU_SET); 1123a7398723SShteryana Shopova } 1124a7398723SShteryana Shopova 1125*570afb92SEnji Cooper snmp_pdu_free(&req); 1126a7398723SShteryana Shopova 1127a7398723SShteryana Shopova return (0); 1128a7398723SShteryana Shopova } 1129a7398723SShteryana Shopova 1130a7398723SShteryana Shopova /* ***************************************************************************** 1131a7398723SShteryana Shopova * main 1132a7398723SShteryana Shopova */ 1133a7398723SShteryana Shopova /* 1134a7398723SShteryana Shopova * According to command line options prepare SNMP Get | GetNext | GetBulk PDU. 11353df5ecacSUlrich Spörlein * Wait for a response and print it. 1136a7398723SShteryana Shopova */ 1137a7398723SShteryana Shopova /* 1138a7398723SShteryana Shopova * Do a 'snmp walk' - according to command line options request for values 1139a7398723SShteryana Shopova * lexicographically subsequent and subrooted at a common node. Send a GetNext 11403df5ecacSUlrich Spörlein * PDU requesting the value for each next variable and print the response. Stop 11413df5ecacSUlrich Spörlein * when a Response PDU is received that contains the value of a variable not 1142a7398723SShteryana Shopova * subrooted at the variable the walk started. 1143a7398723SShteryana Shopova */ 1144a7398723SShteryana Shopova int 1145a7398723SShteryana Shopova main(int argc, char ** argv) 1146a7398723SShteryana Shopova { 1147a7398723SShteryana Shopova struct snmp_toolinfo snmptoolctx; 1148a7398723SShteryana Shopova int32_t oid_cnt, last_oid, opt_num; 1149a7398723SShteryana Shopova int rc = 0; 1150a7398723SShteryana Shopova 1151a7398723SShteryana Shopova /* Make sure program_name is set and valid. */ 1152a7398723SShteryana Shopova if (*argv == NULL) 1153a7398723SShteryana Shopova program_name = "snmptool"; 1154a7398723SShteryana Shopova else { 1155a7398723SShteryana Shopova program_name = strrchr(*argv, '/'); 1156a7398723SShteryana Shopova if (program_name != NULL) 1157a7398723SShteryana Shopova program_name++; 1158a7398723SShteryana Shopova else 1159a7398723SShteryana Shopova program_name = *argv; 1160a7398723SShteryana Shopova } 1161a7398723SShteryana Shopova 1162a7398723SShteryana Shopova if (program_name == NULL) { 1163a7398723SShteryana Shopova fprintf(stderr, "Error: No program name?\n"); 1164a7398723SShteryana Shopova exit (1); 1165a7398723SShteryana Shopova } else if (strcmp(program_name, "bsnmpget") == 0) 1166a7398723SShteryana Shopova program = BSNMPGET; 1167a7398723SShteryana Shopova else if (strcmp(program_name, "bsnmpwalk") == 0) 1168a7398723SShteryana Shopova program = BSNMPWALK; 1169a7398723SShteryana Shopova else if (strcmp(program_name, "bsnmpset") == 0) 1170a7398723SShteryana Shopova program = BSNMPSET; 1171a7398723SShteryana Shopova else { 1172a7398723SShteryana Shopova fprintf(stderr, "Unknown snmp tool name '%s'.\n", program_name); 1173a7398723SShteryana Shopova exit (1); 1174a7398723SShteryana Shopova } 1175a7398723SShteryana Shopova 1176a7398723SShteryana Shopova /* Initialize. */ 1177a7398723SShteryana Shopova if (snmptool_init(&snmptoolctx) < 0) 1178a7398723SShteryana Shopova exit (1); 1179a7398723SShteryana Shopova 1180a7398723SShteryana Shopova if ((opt_num = snmptool_parse_options(&snmptoolctx, argc, argv)) < 0) { 1181a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1182a7398723SShteryana Shopova /* On -h (help) exit without error. */ 1183a7398723SShteryana Shopova if (opt_num == -2) 1184a7398723SShteryana Shopova exit(0); 1185a7398723SShteryana Shopova else 1186a7398723SShteryana Shopova exit(1); 1187a7398723SShteryana Shopova } 1188a7398723SShteryana Shopova 1189a7398723SShteryana Shopova oid_cnt = argc - opt_num - 1; 1190a7398723SShteryana Shopova if (oid_cnt == 0) { 1191a7398723SShteryana Shopova switch (program) { 1192a7398723SShteryana Shopova case BSNMPGET: 1193a7398723SShteryana Shopova if (!ISSET_EDISCOVER(&snmptoolctx) && 1194a7398723SShteryana Shopova !ISSET_LOCALKEY(&snmptoolctx)) { 1195a7398723SShteryana Shopova fprintf(stderr, "No OID given.\n"); 1196a7398723SShteryana Shopova usage(); 1197a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1198a7398723SShteryana Shopova exit(1); 1199a7398723SShteryana Shopova } 1200a7398723SShteryana Shopova break; 1201a7398723SShteryana Shopova 1202a7398723SShteryana Shopova case BSNMPWALK: 1203a7398723SShteryana Shopova if (snmp_object_add(&snmptoolctx, snmpwalk_add_default, 1204a7398723SShteryana Shopova NULL) < 0) { 1205a7398723SShteryana Shopova fprintf(stderr, 1206a7398723SShteryana Shopova "Error setting default subtree.\n"); 1207a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1208a7398723SShteryana Shopova exit(1); 1209a7398723SShteryana Shopova } 1210a7398723SShteryana Shopova break; 1211a7398723SShteryana Shopova 1212a7398723SShteryana Shopova case BSNMPSET: 1213a7398723SShteryana Shopova fprintf(stderr, "No OID given.\n"); 1214a7398723SShteryana Shopova usage(); 1215a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1216a7398723SShteryana Shopova exit(1); 1217a7398723SShteryana Shopova } 1218a7398723SShteryana Shopova } 1219a7398723SShteryana Shopova 1220a7398723SShteryana Shopova if (snmp_import_all(&snmptoolctx) < 0) { 1221a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1222a7398723SShteryana Shopova exit(1); 1223a7398723SShteryana Shopova } 1224a7398723SShteryana Shopova 1225a7398723SShteryana Shopova /* A simple sanity check - can not send GETBULK when using SNMPv1. */ 1226a7398723SShteryana Shopova if (program == BSNMPGET && snmp_client.version == SNMP_V1 && 1227a7398723SShteryana Shopova GET_PDUTYPE(&snmptoolctx) == SNMP_PDU_GETBULK) { 1228a7398723SShteryana Shopova fprintf(stderr, "Cannot send GETBULK PDU with SNMPv1.\n"); 1229a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1230a7398723SShteryana Shopova exit(1); 1231a7398723SShteryana Shopova } 1232a7398723SShteryana Shopova 1233a7398723SShteryana Shopova for (last_oid = argc - 1; oid_cnt > 0; last_oid--, oid_cnt--) { 1234a7398723SShteryana Shopova if ((snmp_object_add(&snmptoolctx, (program == BSNMPSET) ? 1235a7398723SShteryana Shopova snmpset_parse_oid : snmptools_parse_oid, 1236a7398723SShteryana Shopova argv[last_oid])) < 0) { 1237a7398723SShteryana Shopova fprintf(stderr, "Error parsing OID string '%s'.\n", 1238a7398723SShteryana Shopova argv[last_oid]); 1239a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1240a7398723SShteryana Shopova exit(1); 1241a7398723SShteryana Shopova } 1242a7398723SShteryana Shopova } 1243a7398723SShteryana Shopova 1244a7398723SShteryana Shopova if (snmp_open(NULL, NULL, NULL, NULL)) { 12457c933da6SEnji Cooper warn("Failed to open snmp session"); 1246a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1247a7398723SShteryana Shopova exit(1); 1248a7398723SShteryana Shopova } 1249a7398723SShteryana Shopova 1250a7398723SShteryana Shopova if (snmp_client.version == SNMP_V3 && snmp_client.engine.engine_len == 0) 1251a7398723SShteryana Shopova SET_EDISCOVER(&snmptoolctx); 1252a7398723SShteryana Shopova 1253a7398723SShteryana Shopova if (ISSET_EDISCOVER(&snmptoolctx) && 1254a7398723SShteryana Shopova snmp_discover_engine(snmptoolctx.passwd) < 0) { 12557c933da6SEnji Cooper warn("Unknown SNMP Engine ID"); 1256a7398723SShteryana Shopova rc = 1; 1257a7398723SShteryana Shopova goto cleanup; 1258a7398723SShteryana Shopova } 1259a7398723SShteryana Shopova 1260a7398723SShteryana Shopova if (GET_OUTPUT(&snmptoolctx) == OUTPUT_VERBOSE || 1261a7398723SShteryana Shopova ISSET_EDISCOVER(&snmptoolctx)) 1262a7398723SShteryana Shopova snmp_output_engine(); 1263a7398723SShteryana Shopova 1264a7398723SShteryana Shopova if (snmp_client.version == SNMP_V3 && ISSET_LOCALKEY(&snmptoolctx) && 1265a7398723SShteryana Shopova !ISSET_EDISCOVER(&snmptoolctx)) { 1266a7398723SShteryana Shopova if (snmp_passwd_to_keys(&snmp_client.user, 1267a7398723SShteryana Shopova snmptoolctx.passwd) != SNMP_CODE_OK || 1268a7398723SShteryana Shopova snmp_get_local_keys(&snmp_client.user, 1269a7398723SShteryana Shopova snmp_client.engine.engine_id, 1270a7398723SShteryana Shopova snmp_client.engine.engine_len) != SNMP_CODE_OK) { 12717c933da6SEnji Cooper warn("Failed to get keys"); 1272a7398723SShteryana Shopova rc = 1; 1273a7398723SShteryana Shopova goto cleanup; 1274a7398723SShteryana Shopova } 1275a7398723SShteryana Shopova } 1276a7398723SShteryana Shopova 1277a7398723SShteryana Shopova if (GET_OUTPUT(&snmptoolctx) == OUTPUT_VERBOSE || 1278a7398723SShteryana Shopova ISSET_EDISCOVER(&snmptoolctx)) 1279a7398723SShteryana Shopova snmp_output_keys(); 1280a7398723SShteryana Shopova 1281a7398723SShteryana Shopova if (ISSET_EDISCOVER(&snmptoolctx) && snmptoolctx.objects == 0) 1282a7398723SShteryana Shopova goto cleanup; 1283a7398723SShteryana Shopova 1284a7398723SShteryana Shopova switch (program) { 1285a7398723SShteryana Shopova case BSNMPGET: 1286a7398723SShteryana Shopova rc = snmptool_get(&snmptoolctx); 1287a7398723SShteryana Shopova break; 1288a7398723SShteryana Shopova case BSNMPWALK: 1289a7398723SShteryana Shopova rc = snmptool_walk(&snmptoolctx); 1290a7398723SShteryana Shopova break; 1291a7398723SShteryana Shopova case BSNMPSET: 1292a7398723SShteryana Shopova rc = snmptool_set(&snmptoolctx); 1293a7398723SShteryana Shopova break; 1294a7398723SShteryana Shopova } 1295a7398723SShteryana Shopova 1296a7398723SShteryana Shopova 1297a7398723SShteryana Shopova cleanup: 1298a7398723SShteryana Shopova snmp_tool_freeall(&snmptoolctx); 1299a7398723SShteryana Shopova snmp_close(); 1300a7398723SShteryana Shopova 1301a7398723SShteryana Shopova exit(rc); 1302a7398723SShteryana Shopova } 1303