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