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