1216295Ssyrinx/*- 2216295Ssyrinx * Copyright (c) 2005-2006 The FreeBSD Project 3216295Ssyrinx * All rights reserved. 4216295Ssyrinx * 5216295Ssyrinx * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6216295Ssyrinx * 7216295Ssyrinx * Redistribution of this software and documentation and use in source and 8216295Ssyrinx * binary forms, with or without modification, are permitted provided that 9216295Ssyrinx * the following conditions are met: 10216295Ssyrinx * 11216295Ssyrinx * 1. Redistributions of source code or documentation must retain the above 12216295Ssyrinx * copyright notice, this list of conditions and the following disclaimer. 13216295Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 14216295Ssyrinx * notice, this list of conditions and the following disclaimer in the 15216295Ssyrinx * documentation and/or other materials provided with the distribution. 16216295Ssyrinx * 17216295Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216295Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216295Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216295Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216295Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216295Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216295Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216295Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216295Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216295Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216295Ssyrinx * SUCH DAMAGE. 28216295Ssyrinx * 29216295Ssyrinx * Helper functions for snmp client tools 30216295Ssyrinx * 31216295Ssyrinx * $FreeBSD: stable/10/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c 311595 2017-01-07 08:46:16Z ngie $ 32216295Ssyrinx */ 33216295Ssyrinx 34310903Sngie#include <sys/param.h> 35216295Ssyrinx#include <sys/queue.h> 36216295Ssyrinx#include <sys/uio.h> 37216295Ssyrinx 38216295Ssyrinx#include <assert.h> 39216295Ssyrinx#include <ctype.h> 40216295Ssyrinx#include <err.h> 41216295Ssyrinx#include <errno.h> 42216295Ssyrinx#include <fcntl.h> 43216295Ssyrinx#include <stdio.h> 44216295Ssyrinx#include <stdlib.h> 45216295Ssyrinx#include <string.h> 46216295Ssyrinx#include <syslog.h> 47216295Ssyrinx#include <unistd.h> 48216295Ssyrinx 49216295Ssyrinx#include <bsnmp/asn1.h> 50216295Ssyrinx#include <bsnmp/snmp.h> 51216295Ssyrinx#include <bsnmp/snmpclient.h> 52216295Ssyrinx#include "bsnmptc.h" 53216295Ssyrinx#include "bsnmptools.h" 54216295Ssyrinx 55216295Ssyrinx/* Internal varibale to turn on library debugging for testing and to 56216295Ssyrinx * find bugs. It is not exported via the header file. 57216295Ssyrinx * XXX should we cover it by some #ifdef BSNMPTOOLS_DEBUG? */ 58216295Ssyrinxint _bsnmptools_debug = 0; 59216295Ssyrinx 60216295Ssyrinx/* Default files to import mapping from if none explicitly provided. */ 61216295Ssyrinx#define bsnmpd_defs "/usr/share/snmp/defs/tree.def" 62216295Ssyrinx#define mibII_defs "/usr/share/snmp/defs/mibII_tree.def" 63216295Ssyrinx 64216295Ssyrinx/* 65216295Ssyrinx * The .iso.org.dod oid that has to be prepended to every OID when requesting 66216295Ssyrinx * a value. 67216295Ssyrinx */ 68216295Ssyrinxconst struct asn_oid IsoOrgDod_OID = { 69216295Ssyrinx 3, { 1, 3, 6 } 70216295Ssyrinx}; 71216295Ssyrinx 72216295Ssyrinx 73216295Ssyrinx#define SNMP_ERR_UNKNOWN 0 74216295Ssyrinx 75216295Ssyrinx/* 76216295Ssyrinx * An array of error strings corresponding to error definitions from libbsnmp. 77216295Ssyrinx */ 78216295Ssyrinxstatic const struct { 79216295Ssyrinx const char *str; 80216295Ssyrinx int32_t error; 81216295Ssyrinx} error_strings[] = { 82216295Ssyrinx { "Unknown", SNMP_ERR_UNKNOWN }, 83216295Ssyrinx { "Too big ", SNMP_ERR_TOOBIG }, 84216295Ssyrinx { "No such Name", SNMP_ERR_NOSUCHNAME }, 85216295Ssyrinx { "Bad Value", SNMP_ERR_BADVALUE }, 86216295Ssyrinx { "Readonly", SNMP_ERR_READONLY }, 87216295Ssyrinx { "General error", SNMP_ERR_GENERR }, 88216295Ssyrinx { "No access", SNMP_ERR_NO_ACCESS }, 89216295Ssyrinx { "Wrong type", SNMP_ERR_WRONG_TYPE }, 90228990Suqs { "Wrong length", SNMP_ERR_WRONG_LENGTH }, 91216295Ssyrinx { "Wrong encoding", SNMP_ERR_WRONG_ENCODING }, 92216295Ssyrinx { "Wrong value", SNMP_ERR_WRONG_VALUE }, 93216295Ssyrinx { "No creation", SNMP_ERR_NO_CREATION }, 94216295Ssyrinx { "Inconsistent value", SNMP_ERR_INCONS_VALUE }, 95216295Ssyrinx { "Resource unavailable", SNMP_ERR_RES_UNAVAIL }, 96216295Ssyrinx { "Commit failed", SNMP_ERR_COMMIT_FAILED }, 97216295Ssyrinx { "Undo failed", SNMP_ERR_UNDO_FAILED }, 98216295Ssyrinx { "Authorization error", SNMP_ERR_AUTH_ERR }, 99216295Ssyrinx { "Not writable", SNMP_ERR_NOT_WRITEABLE }, 100216295Ssyrinx { "Inconsistent name", SNMP_ERR_INCONS_NAME }, 101216295Ssyrinx { NULL, 0 } 102216295Ssyrinx}; 103216295Ssyrinx 104216295Ssyrinx/* This one and any following are exceptions. */ 105216295Ssyrinx#define SNMP_SYNTAX_UNKNOWN SNMP_SYNTAX_NOSUCHOBJECT 106216295Ssyrinx 107216295Ssyrinxstatic const struct { 108216295Ssyrinx const char *str; 109216295Ssyrinx enum snmp_syntax stx; 110216295Ssyrinx} syntax_strings[] = { 111216295Ssyrinx { "Null", SNMP_SYNTAX_NULL }, 112216295Ssyrinx { "Integer", SNMP_SYNTAX_INTEGER }, 113216295Ssyrinx { "OctetString", SNMP_SYNTAX_OCTETSTRING }, 114216295Ssyrinx { "OID", SNMP_SYNTAX_OID }, 115216295Ssyrinx { "IpAddress", SNMP_SYNTAX_IPADDRESS }, 116216295Ssyrinx { "Counter32", SNMP_SYNTAX_COUNTER }, 117216295Ssyrinx { "Gauge", SNMP_SYNTAX_GAUGE }, 118216295Ssyrinx { "TimeTicks", SNMP_SYNTAX_TIMETICKS }, 119216295Ssyrinx { "Counter64", SNMP_SYNTAX_COUNTER64 }, 120310903Sngie { "Unknown", SNMP_SYNTAX_UNKNOWN }, 121216295Ssyrinx}; 122216295Ssyrinx 123216295Ssyrinxint 124216295Ssyrinxsnmptool_init(struct snmp_toolinfo *snmptoolctx) 125216295Ssyrinx{ 126216295Ssyrinx char *str; 127216295Ssyrinx size_t slen; 128216295Ssyrinx 129216295Ssyrinx memset(snmptoolctx, 0, sizeof(struct snmp_toolinfo)); 130216295Ssyrinx snmptoolctx->objects = 0; 131216295Ssyrinx snmptoolctx->mappings = NULL; 132216295Ssyrinx snmptoolctx->flags = SNMP_PDU_GET; /* XXX */ 133216295Ssyrinx SLIST_INIT(&snmptoolctx->filelist); 134216295Ssyrinx snmp_client_init(&snmp_client); 135229933Ssyrinx SET_MAXREP(snmptoolctx, SNMP_MAX_REPETITIONS); 136216295Ssyrinx 137216295Ssyrinx if (add_filename(snmptoolctx, bsnmpd_defs, &IsoOrgDod_OID, 0) < 0) 138216295Ssyrinx warnx("Error adding file %s to list", bsnmpd_defs); 139216295Ssyrinx 140216295Ssyrinx if (add_filename(snmptoolctx, mibII_defs, &IsoOrgDod_OID, 0) < 0) 141216295Ssyrinx warnx("Error adding file %s to list", mibII_defs); 142216295Ssyrinx 143216295Ssyrinx /* Read the environment */ 144216295Ssyrinx if ((str = getenv("SNMPAUTH")) != NULL) { 145216295Ssyrinx slen = strlen(str); 146216295Ssyrinx if (slen == strlen("md5") && strcasecmp(str, "md5") == 0) 147216295Ssyrinx snmp_client.user.auth_proto = SNMP_AUTH_HMAC_MD5; 148216295Ssyrinx else if (slen == strlen("sha")&& strcasecmp(str, "sha") == 0) 149216295Ssyrinx snmp_client.user.auth_proto = SNMP_AUTH_HMAC_SHA; 150216295Ssyrinx else if (slen != 0) 151216295Ssyrinx warnx("Bad authentication type - %s in SNMPAUTH", str); 152216295Ssyrinx } 153216295Ssyrinx 154216295Ssyrinx if ((str = getenv("SNMPPRIV")) != NULL) { 155216295Ssyrinx slen = strlen(str); 156216295Ssyrinx if (slen == strlen("des") && strcasecmp(str, "des") == 0) 157216295Ssyrinx snmp_client.user.priv_proto = SNMP_PRIV_DES; 158216295Ssyrinx else if (slen == strlen("aes")&& strcasecmp(str, "aes") == 0) 159216295Ssyrinx snmp_client.user.priv_proto = SNMP_PRIV_AES; 160216295Ssyrinx else if (slen != 0) 161216295Ssyrinx warnx("Bad privacy type - %s in SNMPPRIV", str); 162216295Ssyrinx } 163216295Ssyrinx 164216295Ssyrinx if ((str = getenv("SNMPUSER")) != NULL) { 165216295Ssyrinx if ((slen = strlen(str)) > sizeof(snmp_client.user.sec_name)) { 166216295Ssyrinx warnx("Username too long - %s in SNMPUSER", str); 167216295Ssyrinx return (-1); 168216295Ssyrinx } 169216295Ssyrinx if (slen > 0) { 170216295Ssyrinx strlcpy(snmp_client.user.sec_name, str, 171216295Ssyrinx sizeof(snmp_client.user.sec_name)); 172216295Ssyrinx snmp_client.version = SNMP_V3; 173216295Ssyrinx } 174216295Ssyrinx } 175216295Ssyrinx 176216295Ssyrinx if ((str = getenv("SNMPPASSWD")) != NULL) { 177216295Ssyrinx if ((slen = strlen(str)) > MAXSTR) 178216295Ssyrinx slen = MAXSTR - 1; 179216295Ssyrinx if ((snmptoolctx->passwd = malloc(slen + 1)) == NULL) { 180311595Sngie warn("malloc() failed"); 181216295Ssyrinx return (-1); 182216295Ssyrinx } 183216295Ssyrinx if (slen > 0) 184216295Ssyrinx strlcpy(snmptoolctx->passwd, str, slen + 1); 185216295Ssyrinx } 186216295Ssyrinx 187216295Ssyrinx return (0); 188216295Ssyrinx} 189216295Ssyrinx 190216295Ssyrinx#define OBJECT_IDX_LIST(o) o->info->table_idx->index_list 191216295Ssyrinx 192310903Sngie/* 193216295Ssyrinx * Walk through the file list and import string<->oid mappings from each file. 194216295Ssyrinx */ 195216295Ssyrinxint32_t 196216295Ssyrinxsnmp_import_all(struct snmp_toolinfo *snmptoolctx) 197216295Ssyrinx{ 198216295Ssyrinx int32_t fc; 199216295Ssyrinx struct fname *tmp; 200216295Ssyrinx 201216295Ssyrinx if (snmptoolctx == NULL) 202216295Ssyrinx return (-1); 203216295Ssyrinx 204216295Ssyrinx if (ISSET_NUMERIC(snmptoolctx)) 205216295Ssyrinx return (0); 206216295Ssyrinx 207216295Ssyrinx if ((snmptoolctx->mappings = snmp_mapping_init()) == NULL) 208216295Ssyrinx return (-1); 209216295Ssyrinx 210216295Ssyrinx fc = 0; 211216295Ssyrinx if (SLIST_EMPTY(&snmptoolctx->filelist)) { 212216295Ssyrinx warnx("No files to read OID <-> string conversions from"); 213216295Ssyrinx return (-1); 214216295Ssyrinx } else { 215216295Ssyrinx SLIST_FOREACH(tmp, &snmptoolctx->filelist, link) { 216216295Ssyrinx if (tmp->done) 217216295Ssyrinx continue; 218216295Ssyrinx if (snmp_import_file(snmptoolctx, tmp) < 0) { 219216295Ssyrinx fc = -1; 220216295Ssyrinx break; 221216295Ssyrinx } 222216295Ssyrinx fc++; 223216295Ssyrinx } 224216295Ssyrinx } 225216295Ssyrinx 226216295Ssyrinx snmp_mapping_dump(snmptoolctx); 227216295Ssyrinx return (fc); 228216295Ssyrinx} 229216295Ssyrinx 230216295Ssyrinx/* 231228990Suqs * Add a filename to the file list - the initial idea of keeping a list with all 232216295Ssyrinx * files to read OIDs from was that an application might want to have loaded in 233216295Ssyrinx * memory the OIDs from a single file only and when done with them read the OIDs 234216295Ssyrinx * from another file. This is not used yet but might be a good idea at some 235216295Ssyrinx * point. Size argument is number of bytes in string including trailing '\0', 236228990Suqs * not string length. 237216295Ssyrinx */ 238216295Ssyrinxint32_t 239216295Ssyrinxadd_filename(struct snmp_toolinfo *snmptoolctx, const char *filename, 240216295Ssyrinx const struct asn_oid *cut, int32_t done) 241216295Ssyrinx{ 242216295Ssyrinx char *fstring; 243216295Ssyrinx struct fname *entry; 244216295Ssyrinx 245216295Ssyrinx if (snmptoolctx == NULL) 246216295Ssyrinx return (-1); 247216295Ssyrinx 248216295Ssyrinx /* Make sure file was not in list. */ 249216295Ssyrinx SLIST_FOREACH(entry, &snmptoolctx->filelist, link) { 250216295Ssyrinx if (strncmp(entry->name, filename, strlen(entry->name)) == 0) 251216295Ssyrinx return (0); 252216295Ssyrinx } 253216295Ssyrinx 254300559Sngie if ((fstring = strdup(filename)) == NULL) { 255311595Sngie warn("strdup() failed"); 256216295Ssyrinx return (-1); 257216295Ssyrinx } 258216295Ssyrinx 259300471Sngie if ((entry = calloc(1, sizeof(struct fname))) == NULL) { 260311595Sngie warn("calloc() failed"); 261216295Ssyrinx free(fstring); 262216295Ssyrinx return (-1); 263216295Ssyrinx } 264216295Ssyrinx 265216295Ssyrinx if (cut != NULL) 266216295Ssyrinx asn_append_oid(&(entry->cut), cut); 267216295Ssyrinx entry->name = fstring; 268216295Ssyrinx entry->done = done; 269216295Ssyrinx SLIST_INSERT_HEAD(&snmptoolctx->filelist, entry, link); 270216295Ssyrinx 271216295Ssyrinx return (1); 272216295Ssyrinx} 273216295Ssyrinx 274216295Ssyrinxvoid 275216295Ssyrinxfree_filelist(struct snmp_toolinfo *snmptoolctx) 276216295Ssyrinx{ 277216295Ssyrinx struct fname *f; 278216295Ssyrinx 279216295Ssyrinx if (snmptoolctx == NULL) 280216295Ssyrinx return; /* XXX error handling */ 281216295Ssyrinx 282216295Ssyrinx while ((f = SLIST_FIRST(&snmptoolctx->filelist)) != NULL) { 283216295Ssyrinx SLIST_REMOVE_HEAD(&snmptoolctx->filelist, link); 284216295Ssyrinx if (f->name) 285216295Ssyrinx free(f->name); 286216295Ssyrinx free(f); 287216295Ssyrinx } 288216295Ssyrinx} 289216295Ssyrinx 290310903Sngiestatic char 291216295Ssyrinxisvalid_fchar(char c, int pos) 292216295Ssyrinx{ 293216295Ssyrinx if (isalpha(c)|| c == '/'|| c == '_' || c == '.' || c == '~' || 294216295Ssyrinx (pos != 0 && isdigit(c))){ 295216295Ssyrinx return (c); 296216295Ssyrinx } 297216295Ssyrinx 298216295Ssyrinx if (c == '\0') 299216295Ssyrinx return (0); 300216295Ssyrinx 301216295Ssyrinx if (!isascii(c) || !isprint(c)) 302216295Ssyrinx warnx("Unexpected character %#2x", (u_int) c); 303216295Ssyrinx else 304216295Ssyrinx warnx("Illegal character '%c'", c); 305216295Ssyrinx 306216295Ssyrinx return (-1); 307216295Ssyrinx} 308216295Ssyrinx 309216295Ssyrinx/* 310216295Ssyrinx * Re-implement getsubopt from scratch, because the second argument is broken 311216295Ssyrinx * and will not compile with WARNS=5. 312216295Ssyrinx * Copied from src/contrib/bsnmp/snmpd/main.c. 313216295Ssyrinx */ 314216295Ssyrinxstatic int 315216295Ssyrinxgetsubopt1(char **arg, const char *const *options, char **valp, char **optp) 316216295Ssyrinx{ 317216295Ssyrinx static const char *const delim = ",\t "; 318216295Ssyrinx u_int i; 319216295Ssyrinx char *ptr; 320216295Ssyrinx 321216295Ssyrinx *optp = NULL; 322216295Ssyrinx 323216295Ssyrinx /* Skip leading junk. */ 324216295Ssyrinx for (ptr = *arg; *ptr != '\0'; ptr++) 325216295Ssyrinx if (strchr(delim, *ptr) == NULL) 326216295Ssyrinx break; 327216295Ssyrinx if (*ptr == '\0') { 328216295Ssyrinx *arg = ptr; 329216295Ssyrinx return (-1); 330216295Ssyrinx } 331216295Ssyrinx *optp = ptr; 332216295Ssyrinx 333216295Ssyrinx /* Find the end of the option. */ 334216295Ssyrinx while (*++ptr != '\0') 335216295Ssyrinx if (strchr(delim, *ptr) != NULL || *ptr == '=') 336216295Ssyrinx break; 337216295Ssyrinx 338216295Ssyrinx if (*ptr != '\0') { 339216295Ssyrinx if (*ptr == '=') { 340216295Ssyrinx *ptr++ = '\0'; 341216295Ssyrinx *valp = ptr; 342216295Ssyrinx while (*ptr != '\0' && strchr(delim, *ptr) == NULL) 343216295Ssyrinx ptr++; 344216295Ssyrinx if (*ptr != '\0') 345216295Ssyrinx *ptr++ = '\0'; 346216295Ssyrinx } else 347216295Ssyrinx *ptr++ = '\0'; 348216295Ssyrinx } 349216295Ssyrinx 350216295Ssyrinx *arg = ptr; 351216295Ssyrinx 352216295Ssyrinx for (i = 0; *options != NULL; options++, i++) 353216295Ssyrinx if (strcmp(*optp, *options) == 0) 354216295Ssyrinx return (i); 355216295Ssyrinx return (-1); 356216295Ssyrinx} 357216295Ssyrinx 358216295Ssyrinxstatic int32_t 359216295Ssyrinxparse_path(char *value) 360216295Ssyrinx{ 361216295Ssyrinx int32_t i, len; 362216295Ssyrinx 363216295Ssyrinx if (value == NULL) 364216295Ssyrinx return (-1); 365216295Ssyrinx 366216295Ssyrinx for (len = 0; len < MAXPATHLEN; len++) { 367216295Ssyrinx i = isvalid_fchar(*(value + len), len) ; 368216295Ssyrinx 369216295Ssyrinx if (i == 0) 370216295Ssyrinx break; 371216295Ssyrinx else if (i < 0) 372216295Ssyrinx return (-1); 373216295Ssyrinx } 374216295Ssyrinx 375216295Ssyrinx if (len >= MAXPATHLEN || value[len] != '\0') { 376216295Ssyrinx warnx("Bad pathname - '%s'", value); 377216295Ssyrinx return (-1); 378216295Ssyrinx } 379216295Ssyrinx 380216295Ssyrinx return (len); 381216295Ssyrinx} 382216295Ssyrinx 383216295Ssyrinxstatic int32_t 384216295Ssyrinxparse_flist(struct snmp_toolinfo *snmptoolctx, char *value, char *path, 385216295Ssyrinx const struct asn_oid *cut) 386216295Ssyrinx{ 387216295Ssyrinx int32_t namelen; 388216295Ssyrinx char filename[MAXPATHLEN + 1]; 389216295Ssyrinx 390216295Ssyrinx if (value == NULL) 391216295Ssyrinx return (-1); 392216295Ssyrinx 393216295Ssyrinx do { 394216295Ssyrinx memset(filename, 0, MAXPATHLEN + 1); 395216295Ssyrinx 396216295Ssyrinx if (isalpha(*value) && (path == NULL || path[0] == '\0')) { 397216295Ssyrinx strlcpy(filename, SNMP_DEFS_DIR, MAXPATHLEN + 1); 398216295Ssyrinx namelen = strlen(SNMP_DEFS_DIR); 399216295Ssyrinx } else if (path != NULL){ 400216295Ssyrinx strlcpy(filename, path, MAXPATHLEN + 1); 401216295Ssyrinx namelen = strlen(path); 402216295Ssyrinx } else 403216295Ssyrinx namelen = 0; 404216295Ssyrinx 405216295Ssyrinx for ( ; namelen < MAXPATHLEN; value++) { 406216295Ssyrinx if (isvalid_fchar(*value, namelen) > 0) { 407216295Ssyrinx filename[namelen++] = *value; 408216295Ssyrinx continue; 409216295Ssyrinx } 410216295Ssyrinx 411216295Ssyrinx if (*value == ',' ) 412216295Ssyrinx value++; 413216295Ssyrinx else if (*value == '\0') 414216295Ssyrinx ; 415216295Ssyrinx else { 416216295Ssyrinx if (!isascii(*value) || !isprint(*value)) 417216295Ssyrinx warnx("Unexpected character %#2x in" 418216295Ssyrinx " filename", (u_int) *value); 419216295Ssyrinx else 420216295Ssyrinx warnx("Illegal character '%c' in" 421216295Ssyrinx " filename", *value); 422216295Ssyrinx return (-1); 423216295Ssyrinx } 424216295Ssyrinx 425216295Ssyrinx filename[namelen]='\0'; 426216295Ssyrinx break; 427216295Ssyrinx } 428216295Ssyrinx 429216295Ssyrinx if ((namelen == MAXPATHLEN) && (filename[MAXPATHLEN] != '\0')) { 430216295Ssyrinx warnx("Filename %s too long", filename); 431216295Ssyrinx return (-1); 432216295Ssyrinx } 433216295Ssyrinx 434216295Ssyrinx if (add_filename(snmptoolctx, filename, cut, 0) < 0) { 435216295Ssyrinx warnx("Error adding file %s to list", filename); 436216295Ssyrinx return (-1); 437216295Ssyrinx } 438216295Ssyrinx } while (*value != '\0'); 439216295Ssyrinx 440216295Ssyrinx return(1); 441216295Ssyrinx} 442216295Ssyrinx 443216295Ssyrinxstatic int32_t 444216295Ssyrinxparse_ascii(char *ascii, uint8_t *binstr, size_t binlen) 445216295Ssyrinx{ 446300471Sngie char dptr[3]; 447300471Sngie size_t count; 448300471Sngie int32_t alen, i, saved_errno; 449216295Ssyrinx uint32_t val; 450216295Ssyrinx 451228990Suqs /* Filter 0x at the beginning */ 452216295Ssyrinx if ((alen = strlen(ascii)) > 2 && ascii[0] == '0' && ascii[1] == 'x') 453216295Ssyrinx i = 2; 454216295Ssyrinx else 455216295Ssyrinx i = 0; 456216295Ssyrinx 457216295Ssyrinx saved_errno = errno; 458216295Ssyrinx errno = 0; 459216295Ssyrinx for (count = 0; i < alen; i += 2) { 460216295Ssyrinx /* XXX: consider strlen(ascii) % 2 != 0 */ 461216295Ssyrinx dptr[0] = ascii[i]; 462216295Ssyrinx dptr[1] = ascii[i + 1]; 463216295Ssyrinx dptr[2] = '\0'; 464216295Ssyrinx if ((val = strtoul(dptr, NULL, 16)) > 0xFF || errno != 0) { 465216295Ssyrinx errno = saved_errno; 466216295Ssyrinx return (-1); 467216295Ssyrinx } 468216295Ssyrinx binstr[count] = (uint8_t) val; 469216295Ssyrinx if (++count >= binlen) { 470228990Suqs warnx("Key %s too long - truncating to %zu octets", 471216295Ssyrinx ascii, binlen); 472216295Ssyrinx break; 473216295Ssyrinx } 474216295Ssyrinx } 475216295Ssyrinx 476216295Ssyrinx return (count); 477216295Ssyrinx} 478216295Ssyrinx 479216295Ssyrinx/* 480216295Ssyrinx * Functions to parse common input options for client tools and fill in the 481216295Ssyrinx * snmp_client structure. 482216295Ssyrinx */ 483216295Ssyrinxint32_t 484300471Sngieparse_authentication(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg) 485216295Ssyrinx{ 486216295Ssyrinx int32_t count, subopt; 487216295Ssyrinx char *val, *option; 488216295Ssyrinx const char *const subopts[] = { 489216295Ssyrinx "proto", 490216295Ssyrinx "key", 491216295Ssyrinx NULL 492216295Ssyrinx }; 493216295Ssyrinx 494216295Ssyrinx assert(opt_arg != NULL); 495216295Ssyrinx count = 1; 496216295Ssyrinx while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 497216295Ssyrinx switch (subopt) { 498216295Ssyrinx case 0: 499216295Ssyrinx if (val == NULL) { 500216295Ssyrinx warnx("Suboption 'proto' requires an argument"); 501216295Ssyrinx return (-1); 502216295Ssyrinx } 503216295Ssyrinx if (strlen(val) != 3) { 504216295Ssyrinx warnx("Unknown auth protocol - %s", val); 505216295Ssyrinx return (-1); 506216295Ssyrinx } 507216295Ssyrinx if (strncasecmp("md5", val, strlen("md5")) == 0) 508216295Ssyrinx snmp_client.user.auth_proto = 509216295Ssyrinx SNMP_AUTH_HMAC_MD5; 510216295Ssyrinx else if (strncasecmp("sha", val, strlen("sha")) == 0) 511216295Ssyrinx snmp_client.user.auth_proto = 512216295Ssyrinx SNMP_AUTH_HMAC_SHA; 513216295Ssyrinx else { 514216295Ssyrinx warnx("Unknown auth protocol - %s", val); 515216295Ssyrinx return (-1); 516216295Ssyrinx } 517216295Ssyrinx break; 518216295Ssyrinx case 1: 519216295Ssyrinx if (val == NULL) { 520216295Ssyrinx warnx("Suboption 'key' requires an argument"); 521216295Ssyrinx return (-1); 522216295Ssyrinx } 523216295Ssyrinx if (parse_ascii(val, snmp_client.user.auth_key, 524216295Ssyrinx SNMP_AUTH_KEY_SIZ) < 0) { 525216295Ssyrinx warnx("Bad authentication key- %s", val); 526216295Ssyrinx return (-1); 527216295Ssyrinx } 528216295Ssyrinx break; 529216295Ssyrinx default: 530216295Ssyrinx warnx("Unknown suboption - '%s'", suboptarg); 531216295Ssyrinx return (-1); 532216295Ssyrinx } 533216295Ssyrinx count += 1; 534216295Ssyrinx } 535216295Ssyrinx return (2/* count */); 536216295Ssyrinx} 537216295Ssyrinx 538216295Ssyrinxint32_t 539300471Sngieparse_privacy(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg) 540216295Ssyrinx{ 541216295Ssyrinx int32_t count, subopt; 542216295Ssyrinx char *val, *option; 543216295Ssyrinx const char *const subopts[] = { 544216295Ssyrinx "proto", 545216295Ssyrinx "key", 546216295Ssyrinx NULL 547216295Ssyrinx }; 548216295Ssyrinx 549216295Ssyrinx assert(opt_arg != NULL); 550216295Ssyrinx count = 1; 551216295Ssyrinx while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 552216295Ssyrinx switch (subopt) { 553216295Ssyrinx case 0: 554216295Ssyrinx if (val == NULL) { 555216295Ssyrinx warnx("Suboption 'proto' requires an argument"); 556216295Ssyrinx return (-1); 557216295Ssyrinx } 558216295Ssyrinx if (strlen(val) != 3) { 559216295Ssyrinx warnx("Unknown privacy protocol - %s", val); 560216295Ssyrinx return (-1); 561216295Ssyrinx } 562216295Ssyrinx if (strncasecmp("aes", val, strlen("aes")) == 0) 563216295Ssyrinx snmp_client.user.priv_proto = SNMP_PRIV_AES; 564216295Ssyrinx else if (strncasecmp("des", val, strlen("des")) == 0) 565216295Ssyrinx snmp_client.user.priv_proto = SNMP_PRIV_DES; 566216295Ssyrinx else { 567216295Ssyrinx warnx("Unknown privacy protocol - %s", val); 568216295Ssyrinx return (-1); 569216295Ssyrinx } 570216295Ssyrinx break; 571216295Ssyrinx case 1: 572216295Ssyrinx if (val == NULL) { 573216295Ssyrinx warnx("Suboption 'key' requires an argument"); 574216295Ssyrinx return (-1); 575216295Ssyrinx } 576216295Ssyrinx if (parse_ascii(val, snmp_client.user.priv_key, 577216295Ssyrinx SNMP_PRIV_KEY_SIZ) < 0) { 578216295Ssyrinx warnx("Bad privacy key- %s", val); 579216295Ssyrinx return (-1); 580216295Ssyrinx } 581216295Ssyrinx break; 582216295Ssyrinx default: 583216295Ssyrinx warnx("Unknown suboption - '%s'", suboptarg); 584216295Ssyrinx return (-1); 585216295Ssyrinx } 586216295Ssyrinx count += 1; 587216295Ssyrinx } 588216295Ssyrinx return (2/* count */); 589216295Ssyrinx} 590216295Ssyrinx 591216295Ssyrinxint32_t 592300471Sngieparse_context(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg) 593216295Ssyrinx{ 594216295Ssyrinx int32_t count, subopt; 595216295Ssyrinx char *val, *option; 596216295Ssyrinx const char *const subopts[] = { 597216295Ssyrinx "context", 598216295Ssyrinx "context-engine", 599216295Ssyrinx NULL 600216295Ssyrinx }; 601216295Ssyrinx 602216295Ssyrinx assert(opt_arg != NULL); 603216295Ssyrinx count = 1; 604216295Ssyrinx while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 605216295Ssyrinx switch (subopt) { 606216295Ssyrinx case 0: 607216295Ssyrinx if (val == NULL) { 608216295Ssyrinx warnx("Suboption 'context' - no argument"); 609216295Ssyrinx return (-1); 610216295Ssyrinx } 611216295Ssyrinx strlcpy(snmp_client.cname, val, SNMP_CONTEXT_NAME_SIZ); 612216295Ssyrinx break; 613216295Ssyrinx case 1: 614216295Ssyrinx if (val == NULL) { 615216295Ssyrinx warnx("Suboption 'context-engine' - no argument"); 616216295Ssyrinx return (-1); 617216295Ssyrinx } 618301655Sngie if ((int32_t)(snmp_client.clen = parse_ascii(val, 619301655Sngie snmp_client.cengine, SNMP_ENGINE_ID_SIZ)) == -1) { 620216295Ssyrinx warnx("Bad EngineID - %s", val); 621216295Ssyrinx return (-1); 622216295Ssyrinx } 623216295Ssyrinx break; 624216295Ssyrinx default: 625216295Ssyrinx warnx("Unknown suboption - '%s'", suboptarg); 626216295Ssyrinx return (-1); 627216295Ssyrinx } 628216295Ssyrinx count += 1; 629216295Ssyrinx } 630216295Ssyrinx return (2/* count */); 631216295Ssyrinx} 632216295Ssyrinx 633216295Ssyrinxint32_t 634300471Sngieparse_user_security(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg) 635216295Ssyrinx{ 636216295Ssyrinx int32_t count, subopt, saved_errno; 637216295Ssyrinx char *val, *option; 638216295Ssyrinx const char *const subopts[] = { 639216295Ssyrinx "engine", 640216295Ssyrinx "engine-boots", 641216295Ssyrinx "engine-time", 642216295Ssyrinx "name", 643216295Ssyrinx NULL 644216295Ssyrinx }; 645216295Ssyrinx 646216295Ssyrinx assert(opt_arg != NULL); 647216295Ssyrinx count = 1; 648216295Ssyrinx while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 649216295Ssyrinx switch (subopt) { 650216295Ssyrinx case 0: 651216295Ssyrinx if (val == NULL) { 652216295Ssyrinx warnx("Suboption 'engine' - no argument"); 653216295Ssyrinx return (-1); 654216295Ssyrinx } 655310903Sngie snmp_client.engine.engine_len = parse_ascii(val, 656216295Ssyrinx snmp_client.engine.engine_id, SNMP_ENGINE_ID_SIZ); 657301655Sngie if ((int32_t)snmp_client.engine.engine_len == -1) { 658216295Ssyrinx warnx("Bad EngineID - %s", val); 659216295Ssyrinx return (-1); 660216295Ssyrinx } 661216295Ssyrinx break; 662216295Ssyrinx case 1: 663216295Ssyrinx if (val == NULL) { 664216295Ssyrinx warnx("Suboption 'engine-boots' - no argument"); 665216295Ssyrinx return (-1); 666216295Ssyrinx } 667216295Ssyrinx saved_errno = errno; 668216295Ssyrinx errno = 0; 669216295Ssyrinx snmp_client.engine.engine_boots = strtoul(val, NULL, 10); 670216295Ssyrinx if (errno != 0) { 671311595Sngie warn("Bad 'engine-boots' value %s", val); 672216295Ssyrinx errno = saved_errno; 673216295Ssyrinx return (-1); 674216295Ssyrinx } 675216295Ssyrinx errno = saved_errno; 676216295Ssyrinx break; 677216295Ssyrinx case 2: 678216295Ssyrinx if (val == NULL) { 679216295Ssyrinx warnx("Suboption 'engine-time' - no argument"); 680216295Ssyrinx return (-1); 681216295Ssyrinx } 682216295Ssyrinx saved_errno = errno; 683216295Ssyrinx errno = 0; 684216295Ssyrinx snmp_client.engine.engine_time = strtoul(val, NULL, 10); 685216295Ssyrinx if (errno != 0) { 686311595Sngie warn("Bad 'engine-time' value %s", val); 687216295Ssyrinx errno = saved_errno; 688216295Ssyrinx return (-1); 689216295Ssyrinx } 690216295Ssyrinx errno = saved_errno; 691216295Ssyrinx break; 692216295Ssyrinx case 3: 693216295Ssyrinx strlcpy(snmp_client.user.sec_name, val, 694216295Ssyrinx SNMP_ADM_STR32_SIZ); 695216295Ssyrinx break; 696216295Ssyrinx default: 697216295Ssyrinx warnx("Unknown suboption - '%s'", suboptarg); 698216295Ssyrinx return (-1); 699216295Ssyrinx } 700216295Ssyrinx count += 1; 701216295Ssyrinx } 702216295Ssyrinx return (2/* count */); 703216295Ssyrinx} 704216295Ssyrinx 705216295Ssyrinxint32_t 706216295Ssyrinxparse_file(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 707216295Ssyrinx{ 708216295Ssyrinx assert(opt_arg != NULL); 709216295Ssyrinx 710216295Ssyrinx if (parse_flist(snmptoolctx, opt_arg, NULL, &IsoOrgDod_OID) < 0) 711216295Ssyrinx return (-1); 712216295Ssyrinx 713216295Ssyrinx return (2); 714216295Ssyrinx} 715216295Ssyrinx 716216295Ssyrinxint32_t 717216295Ssyrinxparse_include(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 718216295Ssyrinx{ 719216295Ssyrinx char path[MAXPATHLEN + 1]; 720216295Ssyrinx int32_t cut_dflt, len, subopt; 721216295Ssyrinx struct asn_oid cut; 722216295Ssyrinx char *val, *option; 723216295Ssyrinx const char *const subopts[] = { 724216295Ssyrinx "cut", 725216295Ssyrinx "path", 726216295Ssyrinx "file", 727216295Ssyrinx NULL 728216295Ssyrinx }; 729216295Ssyrinx 730216295Ssyrinx#define INC_CUT 0 731216295Ssyrinx#define INC_PATH 1 732216295Ssyrinx#define INC_LIST 2 733216295Ssyrinx 734216295Ssyrinx assert(opt_arg != NULL); 735216295Ssyrinx 736216295Ssyrinx /* if (opt == 'i') 737216295Ssyrinx free_filelist(snmptoolctx, ); */ 738216295Ssyrinx /* 739216295Ssyrinx * This function should be called only after getopt(3) - otherwise if 740216295Ssyrinx * no previous validation of opt_arg strlen() may not return what is 741216295Ssyrinx * expected. 742216295Ssyrinx */ 743216295Ssyrinx 744216295Ssyrinx path[0] = '\0'; 745216295Ssyrinx memset(&cut, 0, sizeof(struct asn_oid)); 746216295Ssyrinx cut_dflt = -1; 747216295Ssyrinx 748216295Ssyrinx while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 749216295Ssyrinx switch (subopt) { 750216295Ssyrinx case INC_CUT: 751216295Ssyrinx if (val == NULL) { 752216295Ssyrinx warnx("Suboption 'cut' requires an argument"); 753216295Ssyrinx return (-1); 754216295Ssyrinx } else { 755216295Ssyrinx if (snmp_parse_numoid(val, &cut) < 0) 756216295Ssyrinx return (-1); 757216295Ssyrinx } 758216295Ssyrinx cut_dflt = 1; 759216295Ssyrinx break; 760216295Ssyrinx 761216295Ssyrinx case INC_PATH: 762216295Ssyrinx if ((len = parse_path(val)) < 0) 763216295Ssyrinx return (-1); 764216295Ssyrinx strlcpy(path, val, len + 1); 765216295Ssyrinx break; 766216295Ssyrinx 767216295Ssyrinx case INC_LIST: 768216295Ssyrinx if (val == NULL) 769216295Ssyrinx return (-1); 770216295Ssyrinx if (cut_dflt == -1) 771216295Ssyrinx len = parse_flist(snmptoolctx, val, path, &IsoOrgDod_OID); 772216295Ssyrinx else 773216295Ssyrinx len = parse_flist(snmptoolctx, val, path, &cut); 774216295Ssyrinx if (len < 0) 775216295Ssyrinx return (-1); 776216295Ssyrinx break; 777216295Ssyrinx 778216295Ssyrinx default: 779216295Ssyrinx warnx("Unknown suboption - '%s'", suboptarg); 780216295Ssyrinx return (-1); 781216295Ssyrinx } 782216295Ssyrinx } 783216295Ssyrinx 784216295Ssyrinx /* XXX: Fix me - returning two is wrong here */ 785216295Ssyrinx return (2); 786216295Ssyrinx} 787216295Ssyrinx 788216295Ssyrinxint32_t 789216295Ssyrinxparse_server(char *opt_arg) 790216295Ssyrinx{ 791216295Ssyrinx assert(opt_arg != NULL); 792216295Ssyrinx 793216295Ssyrinx if (snmp_parse_server(&snmp_client, opt_arg) < 0) 794216295Ssyrinx return (-1); 795216295Ssyrinx 796216295Ssyrinx if (snmp_client.trans > SNMP_TRANS_UDP && snmp_client.chost == NULL) { 797300276Struckman if ((snmp_client.chost = malloc(strlen(SNMP_DEFAULT_LOCAL) + 1)) 798216295Ssyrinx == NULL) { 799216295Ssyrinx syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 800216295Ssyrinx return (-1); 801216295Ssyrinx } 802216295Ssyrinx strcpy(snmp_client.chost, SNMP_DEFAULT_LOCAL); 803216295Ssyrinx } 804216295Ssyrinx 805216295Ssyrinx return (2); 806216295Ssyrinx} 807216295Ssyrinx 808216295Ssyrinxint32_t 809216295Ssyrinxparse_timeout(char *opt_arg) 810216295Ssyrinx{ 811216295Ssyrinx int32_t v, saved_errno; 812216295Ssyrinx 813216295Ssyrinx assert(opt_arg != NULL); 814216295Ssyrinx 815216295Ssyrinx saved_errno = errno; 816216295Ssyrinx errno = 0; 817216295Ssyrinx 818216295Ssyrinx v = strtol(opt_arg, NULL, 10); 819216295Ssyrinx if (errno != 0) { 820311595Sngie warn("Error parsing timeout value"); 821216295Ssyrinx errno = saved_errno; 822216295Ssyrinx return (-1); 823216295Ssyrinx } 824216295Ssyrinx 825216295Ssyrinx snmp_client.timeout.tv_sec = v; 826216295Ssyrinx errno = saved_errno; 827216295Ssyrinx return (2); 828216295Ssyrinx} 829216295Ssyrinx 830216295Ssyrinxint32_t 831216295Ssyrinxparse_retry(char *opt_arg) 832216295Ssyrinx{ 833216295Ssyrinx uint32_t v; 834216295Ssyrinx int32_t saved_errno; 835216295Ssyrinx 836216295Ssyrinx assert(opt_arg != NULL); 837216295Ssyrinx 838216295Ssyrinx saved_errno = errno; 839216295Ssyrinx errno = 0; 840216295Ssyrinx 841216295Ssyrinx v = strtoul(opt_arg, NULL, 10); 842216295Ssyrinx if (errno != 0) { 843311595Sngie warn("Error parsing retries count"); 844216295Ssyrinx errno = saved_errno; 845216295Ssyrinx return (-1); 846216295Ssyrinx } 847216295Ssyrinx 848216295Ssyrinx snmp_client.retries = v; 849216295Ssyrinx errno = saved_errno; 850216295Ssyrinx return (2); 851216295Ssyrinx} 852216295Ssyrinx 853216295Ssyrinxint32_t 854216295Ssyrinxparse_version(char *opt_arg) 855216295Ssyrinx{ 856216295Ssyrinx uint32_t v; 857216295Ssyrinx int32_t saved_errno; 858216295Ssyrinx 859216295Ssyrinx assert(opt_arg != NULL); 860216295Ssyrinx 861216295Ssyrinx saved_errno = errno; 862216295Ssyrinx errno = 0; 863216295Ssyrinx 864216295Ssyrinx v = strtoul(opt_arg, NULL, 10); 865216295Ssyrinx if (errno != 0) { 866311595Sngie warn("Error parsing version"); 867216295Ssyrinx errno = saved_errno; 868216295Ssyrinx return (-1); 869216295Ssyrinx } 870216295Ssyrinx 871216295Ssyrinx switch (v) { 872216295Ssyrinx case 1: 873216295Ssyrinx snmp_client.version = SNMP_V1; 874216295Ssyrinx break; 875216295Ssyrinx case 2: 876216295Ssyrinx snmp_client.version = SNMP_V2c; 877216295Ssyrinx break; 878216295Ssyrinx case 3: 879216295Ssyrinx snmp_client.version = SNMP_V3; 880216295Ssyrinx break; 881216295Ssyrinx default: 882216295Ssyrinx warnx("Unsupported SNMP version - %u", v); 883216295Ssyrinx errno = saved_errno; 884216295Ssyrinx return (-1); 885216295Ssyrinx } 886216295Ssyrinx 887216295Ssyrinx errno = saved_errno; 888216295Ssyrinx return (2); 889216295Ssyrinx} 890216295Ssyrinx 891216295Ssyrinxint32_t 892216295Ssyrinxparse_local_path(char *opt_arg) 893216295Ssyrinx{ 894216295Ssyrinx assert(opt_arg != NULL); 895216295Ssyrinx 896216295Ssyrinx if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) { 897216295Ssyrinx warnx("Filename too long - %s", opt_arg); 898216295Ssyrinx return (-1); 899216295Ssyrinx } 900216295Ssyrinx 901216295Ssyrinx strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH)); 902216295Ssyrinx return (2); 903216295Ssyrinx} 904216295Ssyrinx 905216295Ssyrinxint32_t 906216295Ssyrinxparse_buflen(char *opt_arg) 907216295Ssyrinx{ 908216295Ssyrinx uint32_t size; 909216295Ssyrinx int32_t saved_errno; 910216295Ssyrinx 911216295Ssyrinx assert(opt_arg != NULL); 912216295Ssyrinx 913216295Ssyrinx saved_errno = errno; 914216295Ssyrinx errno = 0; 915216295Ssyrinx 916216295Ssyrinx size = strtoul(opt_arg, NULL, 10); 917216295Ssyrinx if (errno != 0) { 918311595Sngie warn("Error parsing buffer size"); 919216295Ssyrinx errno = saved_errno; 920216295Ssyrinx return (-1); 921216295Ssyrinx } 922216295Ssyrinx 923216295Ssyrinx if (size > MAX_BUFF_SIZE) { 924216295Ssyrinx warnx("Buffer size too big - %d max allowed", MAX_BUFF_SIZE); 925216295Ssyrinx errno = saved_errno; 926216295Ssyrinx return (-1); 927216295Ssyrinx } 928216295Ssyrinx 929216295Ssyrinx snmp_client.txbuflen = snmp_client.rxbuflen = size; 930216295Ssyrinx errno = saved_errno; 931216295Ssyrinx return (2); 932216295Ssyrinx} 933216295Ssyrinx 934216295Ssyrinxint32_t 935216295Ssyrinxparse_debug(void) 936216295Ssyrinx{ 937216295Ssyrinx snmp_client.dump_pdus = 1; 938216295Ssyrinx return (1); 939216295Ssyrinx} 940216295Ssyrinx 941216295Ssyrinxint32_t 942216295Ssyrinxparse_discovery(struct snmp_toolinfo *snmptoolctx) 943216295Ssyrinx{ 944216295Ssyrinx SET_EDISCOVER(snmptoolctx); 945216295Ssyrinx snmp_client.version = SNMP_V3; 946216295Ssyrinx return (1); 947216295Ssyrinx} 948216295Ssyrinx 949216295Ssyrinxint32_t 950216295Ssyrinxparse_local_key(struct snmp_toolinfo *snmptoolctx) 951216295Ssyrinx{ 952216295Ssyrinx SET_LOCALKEY(snmptoolctx); 953216295Ssyrinx snmp_client.version = SNMP_V3; 954216295Ssyrinx return (1); 955216295Ssyrinx} 956216295Ssyrinx 957216295Ssyrinxint32_t 958216295Ssyrinxparse_num_oids(struct snmp_toolinfo *snmptoolctx) 959216295Ssyrinx{ 960216295Ssyrinx SET_NUMERIC(snmptoolctx); 961216295Ssyrinx return (1); 962216295Ssyrinx} 963216295Ssyrinx 964216295Ssyrinxint32_t 965216295Ssyrinxparse_output(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 966216295Ssyrinx{ 967216295Ssyrinx assert(opt_arg != NULL); 968216295Ssyrinx 969216295Ssyrinx if (strlen(opt_arg) > strlen("verbose")) { 970216295Ssyrinx warnx( "Invalid output option - %s",opt_arg); 971216295Ssyrinx return (-1); 972216295Ssyrinx } 973216295Ssyrinx 974216295Ssyrinx if (strncasecmp(opt_arg, "short", strlen(opt_arg)) == 0) 975216295Ssyrinx SET_OUTPUT(snmptoolctx, OUTPUT_SHORT); 976216295Ssyrinx else if (strncasecmp(opt_arg, "verbose", strlen(opt_arg)) == 0) 977216295Ssyrinx SET_OUTPUT(snmptoolctx, OUTPUT_VERBOSE); 978216295Ssyrinx else if (strncasecmp(opt_arg,"tabular", strlen(opt_arg)) == 0) 979216295Ssyrinx SET_OUTPUT(snmptoolctx, OUTPUT_TABULAR); 980216295Ssyrinx else if (strncasecmp(opt_arg, "quiet", strlen(opt_arg)) == 0) 981216295Ssyrinx SET_OUTPUT(snmptoolctx, OUTPUT_QUIET); 982216295Ssyrinx else { 983216295Ssyrinx warnx( "Invalid output option - %s", opt_arg); 984216295Ssyrinx return (-1); 985216295Ssyrinx } 986216295Ssyrinx 987216295Ssyrinx return (2); 988216295Ssyrinx} 989216295Ssyrinx 990216295Ssyrinxint32_t 991216295Ssyrinxparse_errors(struct snmp_toolinfo *snmptoolctx) 992216295Ssyrinx{ 993216295Ssyrinx SET_RETRY(snmptoolctx); 994216295Ssyrinx return (1); 995216295Ssyrinx} 996216295Ssyrinx 997216295Ssyrinxint32_t 998216295Ssyrinxparse_skip_access(struct snmp_toolinfo *snmptoolctx) 999216295Ssyrinx{ 1000216295Ssyrinx SET_ERRIGNORE(snmptoolctx); 1001216295Ssyrinx return (1); 1002216295Ssyrinx} 1003216295Ssyrinx 1004216295Ssyrinxchar * 1005216295Ssyrinxsnmp_parse_suboid(char *str, struct asn_oid *oid) 1006216295Ssyrinx{ 1007216295Ssyrinx char *endptr; 1008216295Ssyrinx asn_subid_t suboid; 1009216295Ssyrinx 1010216295Ssyrinx if (*str == '.') 1011216295Ssyrinx str++; 1012216295Ssyrinx 1013216295Ssyrinx if (*str < '0' || *str > '9') 1014216295Ssyrinx return (str); 1015216295Ssyrinx 1016216295Ssyrinx do { 1017216295Ssyrinx suboid = strtoul(str, &endptr, 10); 1018216295Ssyrinx if ((asn_subid_t) suboid > ASN_MAXID) { 1019216295Ssyrinx warnx("Suboid %u > ASN_MAXID", suboid); 1020216295Ssyrinx return (NULL); 1021216295Ssyrinx } 1022216295Ssyrinx if (snmp_suboid_append(oid, suboid) < 0) 1023216295Ssyrinx return (NULL); 1024216295Ssyrinx str = endptr + 1; 1025216295Ssyrinx } while (*endptr == '.'); 1026216295Ssyrinx 1027216295Ssyrinx return (endptr); 1028216295Ssyrinx} 1029216295Ssyrinx 1030216295Ssyrinxstatic char * 1031216295Ssyrinxsnmp_int2asn_oid(char *str, struct asn_oid *oid) 1032216295Ssyrinx{ 1033216295Ssyrinx char *endptr; 1034216295Ssyrinx int32_t v, saved_errno; 1035216295Ssyrinx 1036216295Ssyrinx saved_errno = errno; 1037216295Ssyrinx errno = 0; 1038216295Ssyrinx 1039216295Ssyrinx v = strtol(str, &endptr, 10); 1040216295Ssyrinx if (errno != 0) { 1041311595Sngie warn("Integer value %s not supported", str); 1042216295Ssyrinx errno = saved_errno; 1043216295Ssyrinx return (NULL); 1044216295Ssyrinx } 1045216295Ssyrinx errno = saved_errno; 1046216295Ssyrinx 1047216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1048216295Ssyrinx return (NULL); 1049216295Ssyrinx 1050216295Ssyrinx return (endptr); 1051216295Ssyrinx} 1052216295Ssyrinx 1053216295Ssyrinx/* It is a bit weird to have a table indexed by OID but still... */ 1054216295Ssyrinxstatic char * 1055216295Ssyrinxsnmp_oid2asn_oid(struct snmp_toolinfo *snmptoolctx, char *str, 1056216295Ssyrinx struct asn_oid *oid) 1057216295Ssyrinx{ 1058216295Ssyrinx int32_t i; 1059300559Sngie char string[MAXSTR + 1], *endptr; 1060216295Ssyrinx struct snmp_object obj; 1061216295Ssyrinx 1062216295Ssyrinx for (i = 0; i < MAXSTR; i++) 1063216295Ssyrinx if (isalpha (*(str + i)) == 0) 1064216295Ssyrinx break; 1065216295Ssyrinx 1066216295Ssyrinx endptr = str + i; 1067216295Ssyrinx memset(&obj, 0, sizeof(struct snmp_object)); 1068216295Ssyrinx if (i == 0) { 1069216295Ssyrinx if ((endptr = snmp_parse_suboid(str, &(obj.val.var))) == NULL) 1070216295Ssyrinx return (NULL); 1071216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) obj.val.var.len) < 0) 1072216295Ssyrinx return (NULL); 1073216295Ssyrinx } else { 1074216295Ssyrinx strlcpy(string, str, i + 1); 1075216295Ssyrinx if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) { 1076299016Sngie warnx("Unknown string - %s", string); 1077216295Ssyrinx return (NULL); 1078216295Ssyrinx } 1079216295Ssyrinx } 1080216295Ssyrinx 1081216295Ssyrinx asn_append_oid(oid, &(obj.val.var)); 1082216295Ssyrinx return (endptr); 1083216295Ssyrinx} 1084216295Ssyrinx 1085216295Ssyrinxstatic char * 1086216295Ssyrinxsnmp_ip2asn_oid(char *str, struct asn_oid *oid) 1087216295Ssyrinx{ 1088216295Ssyrinx uint32_t v; 1089216295Ssyrinx int32_t i; 1090216295Ssyrinx char *endptr, *ptr; 1091216295Ssyrinx 1092216295Ssyrinx ptr = str; 1093310912Sngie 1094216295Ssyrinx for (i = 0; i < 4; i++) { 1095216295Ssyrinx v = strtoul(ptr, &endptr, 10); 1096216295Ssyrinx if (v > 0xff) 1097216295Ssyrinx return (NULL); 1098216295Ssyrinx if (*endptr != '.' && strchr("],\0", *endptr) == NULL && i != 3) 1099216295Ssyrinx return (NULL); 1100216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1101216295Ssyrinx return (NULL); 1102216295Ssyrinx ptr = endptr + 1; 1103216295Ssyrinx } 1104216295Ssyrinx 1105216295Ssyrinx return (endptr); 1106216295Ssyrinx} 1107216295Ssyrinx 1108216295Ssyrinx/* 32-bit counter, gauge, timeticks. */ 1109216295Ssyrinxstatic char * 1110216295Ssyrinxsnmp_uint2asn_oid(char *str, struct asn_oid *oid) 1111216295Ssyrinx{ 1112216295Ssyrinx char *endptr; 1113216295Ssyrinx uint32_t v; 1114216295Ssyrinx int32_t saved_errno; 1115216295Ssyrinx 1116216295Ssyrinx saved_errno = errno; 1117216295Ssyrinx errno = 0; 1118216295Ssyrinx 1119216295Ssyrinx v = strtoul(str, &endptr, 10); 1120216295Ssyrinx if (errno != 0) { 1121311595Sngie warn("Integer value %s not supported", str); 1122216295Ssyrinx errno = saved_errno; 1123216295Ssyrinx return (NULL); 1124216295Ssyrinx } 1125216295Ssyrinx errno = saved_errno; 1126216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1127216295Ssyrinx return (NULL); 1128216295Ssyrinx 1129216295Ssyrinx return (endptr); 1130216295Ssyrinx} 1131216295Ssyrinx 1132216295Ssyrinxstatic char * 1133216295Ssyrinxsnmp_cnt64_2asn_oid(char *str, struct asn_oid *oid) 1134216295Ssyrinx{ 1135216295Ssyrinx char *endptr; 1136216295Ssyrinx uint64_t v; 1137216295Ssyrinx int32_t saved_errno; 1138216295Ssyrinx 1139216295Ssyrinx saved_errno = errno; 1140216295Ssyrinx errno = 0; 1141216295Ssyrinx 1142216295Ssyrinx v = strtoull(str, &endptr, 10); 1143216295Ssyrinx 1144216295Ssyrinx if (errno != 0) { 1145311595Sngie warn("Integer value %s not supported", str); 1146216295Ssyrinx errno = saved_errno; 1147216295Ssyrinx return (NULL); 1148216295Ssyrinx } 1149216295Ssyrinx errno = saved_errno; 1150216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xffffffff)) < 0) 1151216295Ssyrinx return (NULL); 1152216295Ssyrinx 1153216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (v >> 32)) < 0) 1154216295Ssyrinx return (NULL); 1155216295Ssyrinx 1156216295Ssyrinx return (endptr); 1157216295Ssyrinx} 1158216295Ssyrinx 1159216295Ssyrinxenum snmp_syntax 1160216295Ssyrinxparse_syntax(char *str) 1161216295Ssyrinx{ 1162216295Ssyrinx int32_t i; 1163216295Ssyrinx 1164216295Ssyrinx for (i = 0; i < SNMP_SYNTAX_UNKNOWN; i++) { 1165216295Ssyrinx if (strncmp(syntax_strings[i].str, str, 1166216295Ssyrinx strlen(syntax_strings[i].str)) == 0) 1167216295Ssyrinx return (syntax_strings[i].stx); 1168216295Ssyrinx } 1169216295Ssyrinx 1170216295Ssyrinx return (SNMP_SYNTAX_NULL); 1171216295Ssyrinx} 1172216295Ssyrinx 1173216295Ssyrinxstatic char * 1174216295Ssyrinxsnmp_parse_subindex(struct snmp_toolinfo *snmptoolctx, char *str, 1175216295Ssyrinx struct index *idx, struct snmp_object *object) 1176216295Ssyrinx{ 1177216295Ssyrinx char *ptr; 1178216295Ssyrinx int32_t i; 1179216295Ssyrinx enum snmp_syntax stx; 1180216295Ssyrinx char syntax[MAX_CMD_SYNTAX_LEN]; 1181216295Ssyrinx 1182216295Ssyrinx ptr = str; 1183216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) { 1184216295Ssyrinx for (i = 0; i < MAX_CMD_SYNTAX_LEN ; i++) { 1185216295Ssyrinx if (*(ptr + i) == ':') 1186216295Ssyrinx break; 1187216295Ssyrinx } 1188216295Ssyrinx 1189216295Ssyrinx if (i >= MAX_CMD_SYNTAX_LEN) { 1190216295Ssyrinx warnx("Unknown syntax in OID - %s", str); 1191216295Ssyrinx return (NULL); 1192216295Ssyrinx } 1193216295Ssyrinx /* Expect a syntax string here. */ 1194216295Ssyrinx if ((stx = parse_syntax(str)) <= SNMP_SYNTAX_NULL) { 1195216295Ssyrinx warnx("Invalid syntax - %s",syntax); 1196216295Ssyrinx return (NULL); 1197216295Ssyrinx } 1198216295Ssyrinx 1199216295Ssyrinx if (stx != idx->syntax && !ISSET_ERRIGNORE(snmptoolctx)) { 1200216295Ssyrinx warnx("Syntax mismatch - %d expected, %d given", 1201216295Ssyrinx idx->syntax, stx); 1202216295Ssyrinx return (NULL); 1203216295Ssyrinx } 1204216295Ssyrinx /* 1205216295Ssyrinx * That is where the suboid started + the syntax length + one 1206216295Ssyrinx * character for ':'. 1207216295Ssyrinx */ 1208216295Ssyrinx ptr = str + i + 1; 1209216295Ssyrinx } else 1210216295Ssyrinx stx = idx->syntax; 1211216295Ssyrinx 1212216295Ssyrinx switch (stx) { 1213216295Ssyrinx case SNMP_SYNTAX_INTEGER: 1214216295Ssyrinx return (snmp_int2asn_oid(ptr, &(object->val.var))); 1215216295Ssyrinx case SNMP_SYNTAX_OID: 1216216295Ssyrinx return (snmp_oid2asn_oid(snmptoolctx, ptr, 1217216295Ssyrinx &(object->val.var))); 1218216295Ssyrinx case SNMP_SYNTAX_IPADDRESS: 1219216295Ssyrinx return (snmp_ip2asn_oid(ptr, &(object->val.var))); 1220216295Ssyrinx case SNMP_SYNTAX_COUNTER: 1221216295Ssyrinx /* FALLTHROUGH */ 1222216295Ssyrinx case SNMP_SYNTAX_GAUGE: 1223216295Ssyrinx /* FALLTHROUGH */ 1224216295Ssyrinx case SNMP_SYNTAX_TIMETICKS: 1225216295Ssyrinx return (snmp_uint2asn_oid(ptr, &(object->val.var))); 1226216295Ssyrinx case SNMP_SYNTAX_COUNTER64: 1227216295Ssyrinx return (snmp_cnt64_2asn_oid(ptr, &(object->val.var))); 1228216295Ssyrinx case SNMP_SYNTAX_OCTETSTRING: 1229216295Ssyrinx return (snmp_tc2oid(idx->tc, ptr, &(object->val.var))); 1230216295Ssyrinx default: 1231216295Ssyrinx /* NOTREACHED */ 1232216295Ssyrinx break; 1233216295Ssyrinx } 1234216295Ssyrinx 1235216295Ssyrinx return (NULL); 1236216295Ssyrinx} 1237216295Ssyrinx 1238216295Ssyrinxchar * 1239216295Ssyrinxsnmp_parse_index(struct snmp_toolinfo *snmptoolctx, char *str, 1240216295Ssyrinx struct snmp_object *object) 1241216295Ssyrinx{ 1242216295Ssyrinx char *ptr; 1243216295Ssyrinx struct index *temp; 1244216295Ssyrinx 1245216295Ssyrinx if (object->info->table_idx == NULL) 1246216295Ssyrinx return (NULL); 1247216295Ssyrinx 1248216295Ssyrinx ptr = NULL; 1249216295Ssyrinx STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(object)), link) { 1250216295Ssyrinx if ((ptr = snmp_parse_subindex(snmptoolctx, str, temp, object)) 1251216295Ssyrinx == NULL) 1252216295Ssyrinx return (NULL); 1253216295Ssyrinx 1254216295Ssyrinx if (*ptr != ',' && *ptr != ']') 1255216295Ssyrinx return (NULL); 1256216295Ssyrinx str = ptr + 1; 1257216295Ssyrinx } 1258216295Ssyrinx 1259216295Ssyrinx if (ptr == NULL || *ptr != ']') { 1260216295Ssyrinx warnx("Mismatching index - %s", str); 1261216295Ssyrinx return (NULL); 1262216295Ssyrinx } 1263216295Ssyrinx 1264216295Ssyrinx return (ptr + 1); 1265216295Ssyrinx} 1266216295Ssyrinx 1267216295Ssyrinx/* 1268216295Ssyrinx * Fill in the struct asn_oid member of snmp_value with suboids from input. 1269216295Ssyrinx * If an error occurs - print message on stderr and return (-1). 1270216295Ssyrinx * If all is ok - return the length of the oid. 1271216295Ssyrinx */ 1272216295Ssyrinxint32_t 1273216295Ssyrinxsnmp_parse_numoid(char *argv, struct asn_oid *var) 1274216295Ssyrinx{ 1275216295Ssyrinx char *endptr, *str; 1276216295Ssyrinx asn_subid_t suboid; 1277216295Ssyrinx 1278216295Ssyrinx str = argv; 1279216295Ssyrinx 1280216295Ssyrinx if (*str == '.') 1281216295Ssyrinx str++; 1282216295Ssyrinx 1283216295Ssyrinx do { 1284216295Ssyrinx if (var->len == ASN_MAXOIDLEN) { 1285216295Ssyrinx warnx("Oid too long - %u", var->len); 1286216295Ssyrinx return (-1); 1287216295Ssyrinx } 1288216295Ssyrinx 1289216295Ssyrinx suboid = strtoul(str, &endptr, 10); 1290216295Ssyrinx if (suboid > ASN_MAXID) { 1291216295Ssyrinx warnx("Oid too long - %u", var->len); 1292216295Ssyrinx return (-1); 1293216295Ssyrinx } 1294216295Ssyrinx 1295216295Ssyrinx var->subs[var->len++] = suboid; 1296216295Ssyrinx str = endptr + 1; 1297216295Ssyrinx } while ( *endptr == '.'); 1298216295Ssyrinx 1299216295Ssyrinx if (*endptr != '\0') { 1300216295Ssyrinx warnx("Invalid oid string - %s", argv); 1301216295Ssyrinx return (-1); 1302216295Ssyrinx } 1303216295Ssyrinx 1304216295Ssyrinx return (var->len); 1305216295Ssyrinx} 1306216295Ssyrinx 1307216295Ssyrinx/* Append a length 1 suboid to an asn_oid structure. */ 1308216295Ssyrinxint32_t 1309216295Ssyrinxsnmp_suboid_append(struct asn_oid *var, asn_subid_t suboid) 1310216295Ssyrinx{ 1311216295Ssyrinx if (var == NULL) 1312216295Ssyrinx return (-1); 1313216295Ssyrinx 1314216295Ssyrinx if (var->len >= ASN_MAXOIDLEN) { 1315216295Ssyrinx warnx("Oid too long - %u", var->len); 1316216295Ssyrinx return (-1); 1317216295Ssyrinx } 1318216295Ssyrinx 1319216295Ssyrinx var->subs[var->len++] = suboid; 1320216295Ssyrinx 1321216295Ssyrinx return (1); 1322216295Ssyrinx} 1323216295Ssyrinx 1324216295Ssyrinx/* Pop the last suboid from an asn_oid structure. */ 1325216295Ssyrinxint32_t 1326216295Ssyrinxsnmp_suboid_pop(struct asn_oid *var) 1327216295Ssyrinx{ 1328216295Ssyrinx asn_subid_t suboid; 1329216295Ssyrinx 1330216295Ssyrinx if (var == NULL) 1331216295Ssyrinx return (-1); 1332216295Ssyrinx 1333216295Ssyrinx if (var->len < 1) 1334216295Ssyrinx return (-1); 1335216295Ssyrinx 1336216295Ssyrinx suboid = var->subs[--(var->len)]; 1337216295Ssyrinx var->subs[var->len] = 0; 1338216295Ssyrinx 1339216295Ssyrinx return (suboid); 1340216295Ssyrinx} 1341216295Ssyrinx 1342216295Ssyrinx/* 1343216295Ssyrinx * Parse the command-line provided string into an OID - alocate memory for a new 1344216295Ssyrinx * snmp object, fill in its fields and insert it in the object list. A 1345216295Ssyrinx * (snmp_verify_inoid_f) function must be provided to validate the input string. 1346216295Ssyrinx */ 1347216295Ssyrinxint32_t 1348216295Ssyrinxsnmp_object_add(struct snmp_toolinfo *snmptoolctx, snmp_verify_inoid_f func, 1349216295Ssyrinx char *string) 1350216295Ssyrinx{ 1351216295Ssyrinx struct snmp_object *obj; 1352216295Ssyrinx 1353216295Ssyrinx if (snmptoolctx == NULL) 1354216295Ssyrinx return (-1); 1355216295Ssyrinx 1356216295Ssyrinx /* XXX-BZ does that chack make sense? */ 1357216295Ssyrinx if (snmptoolctx->objects >= SNMP_MAX_BINDINGS) { 1358216295Ssyrinx warnx("Too many bindings in PDU - %u", snmptoolctx->objects + 1); 1359216295Ssyrinx return (-1); 1360216295Ssyrinx } 1361216295Ssyrinx 1362300471Sngie if ((obj = calloc(1, sizeof(struct snmp_object))) == NULL) { 1363216295Ssyrinx syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 1364216295Ssyrinx return (-1); 1365216295Ssyrinx } 1366216295Ssyrinx 1367216295Ssyrinx if (func(snmptoolctx, obj, string) < 0) { 1368216295Ssyrinx warnx("Invalid OID - %s", string); 1369216295Ssyrinx free(obj); 1370216295Ssyrinx return (-1); 1371216295Ssyrinx } 1372216295Ssyrinx 1373216295Ssyrinx snmptoolctx->objects++; 1374216295Ssyrinx SLIST_INSERT_HEAD(&snmptoolctx->snmp_objectlist, obj, link); 1375216295Ssyrinx 1376216295Ssyrinx return (1); 1377216295Ssyrinx} 1378216295Ssyrinx 1379216295Ssyrinx/* Given an OID, find it in the object list and remove it. */ 1380216295Ssyrinxint32_t 1381216295Ssyrinxsnmp_object_remove(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid) 1382216295Ssyrinx{ 1383216295Ssyrinx struct snmp_object *temp; 1384216295Ssyrinx 1385216295Ssyrinx if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) { 1386216295Ssyrinx warnx("Object list already empty"); 1387216295Ssyrinx return (-1); 1388216295Ssyrinx } 1389216295Ssyrinx 1390216295Ssyrinx 1391216295Ssyrinx SLIST_FOREACH(temp, &snmptoolctx->snmp_objectlist, link) 1392216295Ssyrinx if (asn_compare_oid(&(temp->val.var), oid) == 0) 1393216295Ssyrinx break; 1394216295Ssyrinx 1395216295Ssyrinx if (temp == NULL) { 1396216295Ssyrinx warnx("No such object in list"); 1397216295Ssyrinx return (-1); 1398216295Ssyrinx } 1399216295Ssyrinx 1400216295Ssyrinx SLIST_REMOVE(&snmptoolctx->snmp_objectlist, temp, snmp_object, link); 1401216295Ssyrinx if (temp->val.syntax == SNMP_SYNTAX_OCTETSTRING && 1402216295Ssyrinx temp->val.v.octetstring.octets != NULL) 1403216295Ssyrinx free(temp->val.v.octetstring.octets); 1404216295Ssyrinx free(temp); 1405216295Ssyrinx 1406216295Ssyrinx return (1); 1407216295Ssyrinx} 1408216295Ssyrinx 1409216295Ssyrinxstatic void 1410216295Ssyrinxsnmp_object_freeall(struct snmp_toolinfo *snmptoolctx) 1411216295Ssyrinx{ 1412216295Ssyrinx struct snmp_object *o; 1413216295Ssyrinx 1414216295Ssyrinx while ((o = SLIST_FIRST(&snmptoolctx->snmp_objectlist)) != NULL) { 1415216295Ssyrinx SLIST_REMOVE_HEAD(&snmptoolctx->snmp_objectlist, link); 1416216295Ssyrinx 1417216295Ssyrinx if (o->val.syntax == SNMP_SYNTAX_OCTETSTRING && 1418216295Ssyrinx o->val.v.octetstring.octets != NULL) 1419216295Ssyrinx free(o->val.v.octetstring.octets); 1420216295Ssyrinx free(o); 1421216295Ssyrinx } 1422216295Ssyrinx} 1423216295Ssyrinx 1424216295Ssyrinx/* Do all possible memory release before exit. */ 1425216295Ssyrinxvoid 1426216295Ssyrinxsnmp_tool_freeall(struct snmp_toolinfo *snmptoolctx) 1427216295Ssyrinx{ 1428216295Ssyrinx if (snmp_client.chost != NULL) { 1429216295Ssyrinx free(snmp_client.chost); 1430216295Ssyrinx snmp_client.chost = NULL; 1431216295Ssyrinx } 1432216295Ssyrinx 1433216295Ssyrinx if (snmp_client.cport != NULL) { 1434216295Ssyrinx free(snmp_client.cport); 1435216295Ssyrinx snmp_client.cport = NULL; 1436216295Ssyrinx } 1437216295Ssyrinx 1438216295Ssyrinx snmp_mapping_free(snmptoolctx); 1439216295Ssyrinx free_filelist(snmptoolctx); 1440216295Ssyrinx snmp_object_freeall(snmptoolctx); 1441216295Ssyrinx 1442216295Ssyrinx if (snmptoolctx->passwd != NULL) { 1443216295Ssyrinx free(snmptoolctx->passwd); 1444216295Ssyrinx snmptoolctx->passwd = NULL; 1445216295Ssyrinx } 1446216295Ssyrinx} 1447216295Ssyrinx 1448216295Ssyrinx/* 1449216295Ssyrinx * Fill all variables from the object list into a PDU. (snmp_verify_vbind_f) 1450216295Ssyrinx * function should check whether the variable is consistent in this PDU 1451216295Ssyrinx * (e.g do not add non-leaf OIDs to a GET PDU, or OIDs with read access only to 1452216295Ssyrinx * a SET PDU) - might be NULL though. (snmp_add_vbind_f) function is the 1453216295Ssyrinx * function actually adds the variable to the PDU and must not be NULL. 1454216295Ssyrinx */ 1455216295Ssyrinxint32_t 1456216295Ssyrinxsnmp_pdu_add_bindings(struct snmp_toolinfo *snmptoolctx, 1457216295Ssyrinx snmp_verify_vbind_f vfunc, snmp_add_vbind_f afunc, 1458216295Ssyrinx struct snmp_pdu *pdu, int32_t maxcount) 1459216295Ssyrinx{ 1460216295Ssyrinx int32_t nbindings, abind; 1461216295Ssyrinx struct snmp_object *obj; 1462216295Ssyrinx 1463216295Ssyrinx if (pdu == NULL || afunc == NULL) 1464216295Ssyrinx return (-1); 1465216295Ssyrinx 1466216295Ssyrinx /* Return 0 in case of no more work todo. */ 1467216295Ssyrinx if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) 1468216295Ssyrinx return (0); 1469310903Sngie 1470216295Ssyrinx if (maxcount < 0 || maxcount > SNMP_MAX_BINDINGS) { 1471216295Ssyrinx warnx("maxcount out of range: <0 || >SNMP_MAX_BINDINGS"); 1472216295Ssyrinx return (-1); 1473216295Ssyrinx } 1474216295Ssyrinx 1475216295Ssyrinx nbindings = 0; 1476216295Ssyrinx SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) { 1477216295Ssyrinx if ((vfunc != NULL) && (vfunc(snmptoolctx, pdu, obj) < 0)) { 1478216295Ssyrinx nbindings = -1; 1479216295Ssyrinx break; 1480216295Ssyrinx } 1481216295Ssyrinx if ((abind = afunc(pdu, obj)) < 0) { 1482216295Ssyrinx nbindings = -1; 1483216295Ssyrinx break; 1484216295Ssyrinx } 1485216295Ssyrinx 1486216295Ssyrinx if (abind > 0) { 1487216295Ssyrinx /* Do not put more varbindings than requested. */ 1488216295Ssyrinx if (++nbindings >= maxcount) 1489216295Ssyrinx break; 1490216295Ssyrinx } 1491216295Ssyrinx } 1492216295Ssyrinx 1493216295Ssyrinx return (nbindings); 1494216295Ssyrinx} 1495216295Ssyrinx 1496216295Ssyrinx/* 1497216295Ssyrinx * Locate an object in the object list and set a corresponding error status. 1498216295Ssyrinx */ 1499216295Ssyrinxint32_t 1500216295Ssyrinxsnmp_object_seterror(struct snmp_toolinfo *snmptoolctx, 1501216295Ssyrinx struct snmp_value *err_value, int32_t error_status) 1502216295Ssyrinx{ 1503216295Ssyrinx struct snmp_object *obj; 1504216295Ssyrinx 1505216295Ssyrinx if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist) || err_value == NULL) 1506216295Ssyrinx return (-1); 1507216295Ssyrinx 1508216295Ssyrinx SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) 1509216295Ssyrinx if (asn_compare_oid(&(err_value->var), &(obj->val.var)) == 0) { 1510216295Ssyrinx obj->error = error_status; 1511216295Ssyrinx return (1); 1512216295Ssyrinx } 1513216295Ssyrinx 1514216295Ssyrinx return (0); 1515216295Ssyrinx} 1516216295Ssyrinx 1517216295Ssyrinx/* 1518228990Suqs * Check a PDU received in response to a SNMP_PDU_GET/SNMP_PDU_GETBULK request 1519216295Ssyrinx * but don't compare syntaxes - when sending a request PDU they must be null. 1520216295Ssyrinx * This is a (almost) complete copy of snmp_pdu_check() - with matching syntaxes 1521228990Suqs * checks and some other checks skipped. 1522216295Ssyrinx */ 1523216295Ssyrinxint32_t 1524216295Ssyrinxsnmp_parse_get_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1525216295Ssyrinx{ 1526216295Ssyrinx uint32_t i; 1527216295Ssyrinx 1528216295Ssyrinx for (i = 0; i < req->nbindings; i++) { 1529216295Ssyrinx if (asn_compare_oid(&req->bindings[i].var, 1530216295Ssyrinx &resp->bindings[i].var) != 0) { 1531216295Ssyrinx warnx("Bad OID in response"); 1532216295Ssyrinx return (-1); 1533216295Ssyrinx } 1534216295Ssyrinx 1535216295Ssyrinx if (snmp_client.version != SNMP_V1 && (resp->bindings[i].syntax 1536216295Ssyrinx == SNMP_SYNTAX_NOSUCHOBJECT || resp->bindings[i].syntax == 1537216295Ssyrinx SNMP_SYNTAX_NOSUCHINSTANCE)) 1538216295Ssyrinx return (0); 1539216295Ssyrinx } 1540216295Ssyrinx 1541216295Ssyrinx return (1); 1542216295Ssyrinx} 1543216295Ssyrinx 1544216295Ssyrinxint32_t 1545216295Ssyrinxsnmp_parse_getbulk_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1546216295Ssyrinx{ 1547216295Ssyrinx int32_t N, R, M, r; 1548216295Ssyrinx 1549216295Ssyrinx if (req->error_status > (int32_t) resp->nbindings) { 1550216295Ssyrinx warnx("Bad number of bindings in response"); 1551216295Ssyrinx return (-1); 1552216295Ssyrinx } 1553216295Ssyrinx 1554216295Ssyrinx for (N = 0; N < req->error_status; N++) { 1555216295Ssyrinx if (asn_is_suboid(&req->bindings[N].var, 1556216295Ssyrinx &resp->bindings[N].var) == 0) 1557216295Ssyrinx return (0); 1558216295Ssyrinx if (resp->bindings[N].syntax == SNMP_SYNTAX_ENDOFMIBVIEW) 1559216295Ssyrinx return (0); 1560216295Ssyrinx } 1561216295Ssyrinx 1562216295Ssyrinx for (R = N , r = N; R < (int32_t) req->nbindings; R++) { 1563216295Ssyrinx for (M = 0; M < req->error_index && (r + M) < 1564216295Ssyrinx (int32_t) resp->nbindings; M++) { 1565216295Ssyrinx if (asn_is_suboid(&req->bindings[R].var, 1566216295Ssyrinx &resp->bindings[r + M].var) == 0) 1567216295Ssyrinx return (0); 1568216295Ssyrinx 1569216295Ssyrinx if (resp->bindings[r + M].syntax == 1570216295Ssyrinx SNMP_SYNTAX_ENDOFMIBVIEW) { 1571216295Ssyrinx M++; 1572216295Ssyrinx break; 1573216295Ssyrinx } 1574216295Ssyrinx } 1575216295Ssyrinx r += M; 1576216295Ssyrinx } 1577216295Ssyrinx 1578216295Ssyrinx return (0); 1579216295Ssyrinx} 1580216295Ssyrinx 1581216295Ssyrinxint32_t 1582216295Ssyrinxsnmp_parse_getnext_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1583216295Ssyrinx{ 1584216295Ssyrinx uint32_t i; 1585216295Ssyrinx 1586216295Ssyrinx for (i = 0; i < req->nbindings; i++) { 1587216295Ssyrinx if (asn_is_suboid(&req->bindings[i].var, &resp->bindings[i].var) 1588216295Ssyrinx == 0) 1589216295Ssyrinx return (0); 1590216295Ssyrinx 1591216295Ssyrinx if (resp->version != SNMP_V1 && resp->bindings[i].syntax == 1592216295Ssyrinx SNMP_SYNTAX_ENDOFMIBVIEW) 1593216295Ssyrinx return (0); 1594216295Ssyrinx } 1595216295Ssyrinx 1596216295Ssyrinx return (1); 1597216295Ssyrinx} 1598216295Ssyrinx 1599216295Ssyrinx/* 1600228990Suqs * Should be called to check a response to get/getnext/getbulk. 1601216295Ssyrinx */ 1602216295Ssyrinxint32_t 1603216295Ssyrinxsnmp_parse_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1604216295Ssyrinx{ 1605216295Ssyrinx if (resp == NULL || req == NULL) 1606216295Ssyrinx return (-2); 1607216295Ssyrinx 1608216295Ssyrinx if (resp->version != req->version) { 1609216295Ssyrinx warnx("Response has wrong version"); 1610216295Ssyrinx return (-1); 1611216295Ssyrinx } 1612216295Ssyrinx 1613216295Ssyrinx if (resp->error_status == SNMP_ERR_NOSUCHNAME) { 1614216295Ssyrinx warnx("Error - No Such Name"); 1615216295Ssyrinx return (0); 1616216295Ssyrinx } 1617216295Ssyrinx 1618216295Ssyrinx if (resp->error_status != SNMP_ERR_NOERROR) { 1619228990Suqs warnx("Error %d in response", resp->error_status); 1620216295Ssyrinx return (-1); 1621216295Ssyrinx } 1622216295Ssyrinx 1623216295Ssyrinx if (resp->nbindings != req->nbindings && req->type != SNMP_PDU_GETBULK){ 1624216295Ssyrinx warnx("Bad number of bindings in response"); 1625216295Ssyrinx return (-1); 1626216295Ssyrinx } 1627216295Ssyrinx 1628216295Ssyrinx switch (req->type) { 1629216295Ssyrinx case SNMP_PDU_GET: 1630216295Ssyrinx return (snmp_parse_get_resp(resp,req)); 1631216295Ssyrinx case SNMP_PDU_GETBULK: 1632216295Ssyrinx return (snmp_parse_getbulk_resp(resp,req)); 1633216295Ssyrinx case SNMP_PDU_GETNEXT: 1634216295Ssyrinx return (snmp_parse_getnext_resp(resp,req)); 1635216295Ssyrinx default: 1636216295Ssyrinx /* NOTREACHED */ 1637216295Ssyrinx break; 1638216295Ssyrinx } 1639216295Ssyrinx 1640216295Ssyrinx return (-2); 1641216295Ssyrinx} 1642216295Ssyrinx 1643216295Ssyrinxstatic void 1644216295Ssyrinxsnmp_output_octetstring(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc, 1645216295Ssyrinx uint32_t len, uint8_t *octets) 1646216295Ssyrinx{ 1647216295Ssyrinx char *buf; 1648216295Ssyrinx 1649216295Ssyrinx if (len == 0 || octets == NULL) 1650216295Ssyrinx return; 1651216295Ssyrinx 1652216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1653216295Ssyrinx fprintf(stdout, "%s : ", 1654216295Ssyrinx syntax_strings[SNMP_SYNTAX_OCTETSTRING].str); 1655216295Ssyrinx 1656216295Ssyrinx if ((buf = snmp_oct2tc(tc, len, (char *) octets)) != NULL) { 1657216295Ssyrinx fprintf(stdout, "%s", buf); 1658216295Ssyrinx free(buf); 1659216295Ssyrinx } 1660216295Ssyrinx} 1661216295Ssyrinx 1662216295Ssyrinxstatic void 1663216295Ssyrinxsnmp_output_octetindex(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc, 1664216295Ssyrinx struct asn_oid *oid) 1665216295Ssyrinx{ 1666216295Ssyrinx uint32_t i; 1667216295Ssyrinx uint8_t *s; 1668216295Ssyrinx 1669216295Ssyrinx if ((s = malloc(oid->subs[0] + 1)) == NULL) 1670216295Ssyrinx syslog(LOG_ERR, "malloc failed - %s", strerror(errno)); 1671216295Ssyrinx else { 1672216295Ssyrinx for (i = 0; i < oid->subs[0]; i++) 1673216295Ssyrinx s[i] = (u_char) (oid->subs[i + 1]); 1674216295Ssyrinx 1675216295Ssyrinx snmp_output_octetstring(snmptoolctx, tc, oid->subs[0], s); 1676216295Ssyrinx free(s); 1677216295Ssyrinx } 1678216295Ssyrinx} 1679216295Ssyrinx 1680216295Ssyrinx/* 1681216295Ssyrinx * Check and output syntax type and value. 1682216295Ssyrinx */ 1683216295Ssyrinxstatic void 1684216295Ssyrinxsnmp_output_oid_value(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid) 1685216295Ssyrinx{ 1686216295Ssyrinx char oid_string[ASN_OIDSTRLEN]; 1687216295Ssyrinx struct snmp_object obj; 1688216295Ssyrinx 1689216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1690216295Ssyrinx fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_OID].str); 1691216295Ssyrinx 1692216295Ssyrinx if(!ISSET_NUMERIC(snmptoolctx)) { 1693216295Ssyrinx memset(&obj, 0, sizeof(struct snmp_object)); 1694216295Ssyrinx asn_append_oid(&(obj.val.var), oid); 1695216295Ssyrinx 1696216295Ssyrinx if (snmp_lookup_enumstring(snmptoolctx, &obj) > 0) 1697216295Ssyrinx fprintf(stdout, "%s" , obj.info->string); 1698216295Ssyrinx else if (snmp_lookup_oidstring(snmptoolctx, &obj) > 0) 1699216295Ssyrinx fprintf(stdout, "%s" , obj.info->string); 1700216295Ssyrinx else if (snmp_lookup_nodestring(snmptoolctx, &obj) > 0) 1701216295Ssyrinx fprintf(stdout, "%s" , obj.info->string); 1702216295Ssyrinx else { 1703216295Ssyrinx (void) asn_oid2str_r(oid, oid_string); 1704216295Ssyrinx fprintf(stdout, "%s", oid_string); 1705216295Ssyrinx } 1706216295Ssyrinx } else { 1707216295Ssyrinx (void) asn_oid2str_r(oid, oid_string); 1708216295Ssyrinx fprintf(stdout, "%s", oid_string); 1709216295Ssyrinx } 1710216295Ssyrinx} 1711216295Ssyrinx 1712216295Ssyrinxstatic void 1713216295Ssyrinxsnmp_output_int(struct snmp_toolinfo *snmptoolctx, struct enum_pairs *enums, 1714216295Ssyrinx int32_t int_val) 1715216295Ssyrinx{ 1716216295Ssyrinx char *string; 1717216295Ssyrinx 1718216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1719216295Ssyrinx fprintf(stdout, "%s : ", 1720216295Ssyrinx syntax_strings[SNMP_SYNTAX_INTEGER].str); 1721216295Ssyrinx 1722216295Ssyrinx if (enums != NULL && (string = enum_string_lookup(enums, int_val)) 1723216295Ssyrinx != NULL) 1724216295Ssyrinx fprintf(stdout, "%s", string); 1725216295Ssyrinx else 1726216295Ssyrinx fprintf(stdout, "%d", int_val); 1727216295Ssyrinx} 1728216295Ssyrinx 1729216295Ssyrinxstatic void 1730216295Ssyrinxsnmp_output_ipaddress(struct snmp_toolinfo *snmptoolctx, uint8_t *ip) 1731216295Ssyrinx{ 1732216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1733216295Ssyrinx fprintf(stdout, "%s : ", 1734216295Ssyrinx syntax_strings[SNMP_SYNTAX_IPADDRESS].str); 1735216295Ssyrinx 1736216295Ssyrinx fprintf(stdout, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); 1737216295Ssyrinx} 1738216295Ssyrinx 1739216295Ssyrinxstatic void 1740216295Ssyrinxsnmp_output_counter(struct snmp_toolinfo *snmptoolctx, uint32_t counter) 1741216295Ssyrinx{ 1742216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1743216295Ssyrinx fprintf(stdout, "%s : ", 1744216295Ssyrinx syntax_strings[SNMP_SYNTAX_COUNTER].str); 1745216295Ssyrinx 1746216295Ssyrinx fprintf(stdout, "%u", counter); 1747216295Ssyrinx} 1748216295Ssyrinx 1749216295Ssyrinxstatic void 1750216295Ssyrinxsnmp_output_gauge(struct snmp_toolinfo *snmptoolctx, uint32_t gauge) 1751216295Ssyrinx{ 1752216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1753216295Ssyrinx fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_GAUGE].str); 1754216295Ssyrinx 1755216295Ssyrinx fprintf(stdout, "%u", gauge); 1756216295Ssyrinx} 1757216295Ssyrinx 1758216295Ssyrinxstatic void 1759216295Ssyrinxsnmp_output_ticks(struct snmp_toolinfo *snmptoolctx, uint32_t ticks) 1760216295Ssyrinx{ 1761216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1762216295Ssyrinx fprintf(stdout, "%s : ", 1763216295Ssyrinx syntax_strings[SNMP_SYNTAX_TIMETICKS].str); 1764216295Ssyrinx 1765216295Ssyrinx fprintf(stdout, "%u", ticks); 1766216295Ssyrinx} 1767216295Ssyrinx 1768216295Ssyrinxstatic void 1769216295Ssyrinxsnmp_output_counter64(struct snmp_toolinfo *snmptoolctx, uint64_t counter64) 1770216295Ssyrinx{ 1771216295Ssyrinx if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1772216295Ssyrinx fprintf(stdout, "%s : ", 1773216295Ssyrinx syntax_strings[SNMP_SYNTAX_COUNTER64].str); 1774216295Ssyrinx 1775216295Ssyrinx fprintf(stdout,"%ju", counter64); 1776216295Ssyrinx} 1777216295Ssyrinx 1778216295Ssyrinxint32_t 1779216295Ssyrinxsnmp_output_numval(struct snmp_toolinfo *snmptoolctx, struct snmp_value *val, 1780216295Ssyrinx struct snmp_oid2str *entry) 1781216295Ssyrinx{ 1782216295Ssyrinx if (val == NULL) 1783216295Ssyrinx return (-1); 1784216295Ssyrinx 1785216295Ssyrinx if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) 1786216295Ssyrinx fprintf(stdout, " = "); 1787216295Ssyrinx 1788216295Ssyrinx switch (val->syntax) { 1789216295Ssyrinx case SNMP_SYNTAX_INTEGER: 1790216295Ssyrinx if (entry != NULL) 1791216295Ssyrinx snmp_output_int(snmptoolctx, entry->snmp_enum, 1792216295Ssyrinx val->v.integer); 1793216295Ssyrinx else 1794216295Ssyrinx snmp_output_int(snmptoolctx, NULL, val->v.integer); 1795216295Ssyrinx break; 1796216295Ssyrinx 1797216295Ssyrinx case SNMP_SYNTAX_OCTETSTRING: 1798216295Ssyrinx if (entry != NULL) 1799216295Ssyrinx snmp_output_octetstring(snmptoolctx, entry->tc, 1800216295Ssyrinx val->v.octetstring.len, val->v.octetstring.octets); 1801216295Ssyrinx else 1802216295Ssyrinx snmp_output_octetstring(snmptoolctx, SNMP_STRING, 1803216295Ssyrinx val->v.octetstring.len, val->v.octetstring.octets); 1804216295Ssyrinx break; 1805216295Ssyrinx 1806216295Ssyrinx case SNMP_SYNTAX_OID: 1807216295Ssyrinx snmp_output_oid_value(snmptoolctx, &(val->v.oid)); 1808216295Ssyrinx break; 1809216295Ssyrinx 1810216295Ssyrinx case SNMP_SYNTAX_IPADDRESS: 1811216295Ssyrinx snmp_output_ipaddress(snmptoolctx, val->v.ipaddress); 1812216295Ssyrinx break; 1813216295Ssyrinx 1814216295Ssyrinx case SNMP_SYNTAX_COUNTER: 1815216295Ssyrinx snmp_output_counter(snmptoolctx, val->v.uint32); 1816216295Ssyrinx break; 1817216295Ssyrinx 1818216295Ssyrinx case SNMP_SYNTAX_GAUGE: 1819216295Ssyrinx snmp_output_gauge(snmptoolctx, val->v.uint32); 1820216295Ssyrinx break; 1821216295Ssyrinx 1822216295Ssyrinx case SNMP_SYNTAX_TIMETICKS: 1823216295Ssyrinx snmp_output_ticks(snmptoolctx, val->v.uint32); 1824216295Ssyrinx break; 1825216295Ssyrinx 1826216295Ssyrinx case SNMP_SYNTAX_COUNTER64: 1827216295Ssyrinx snmp_output_counter64(snmptoolctx, val->v.counter64); 1828216295Ssyrinx break; 1829216295Ssyrinx 1830216295Ssyrinx case SNMP_SYNTAX_NOSUCHOBJECT: 1831216295Ssyrinx fprintf(stdout, "No Such Object\n"); 1832216295Ssyrinx return (val->syntax); 1833216295Ssyrinx 1834216295Ssyrinx case SNMP_SYNTAX_NOSUCHINSTANCE: 1835216295Ssyrinx fprintf(stdout, "No Such Instance\n"); 1836216295Ssyrinx return (val->syntax); 1837216295Ssyrinx 1838216295Ssyrinx case SNMP_SYNTAX_ENDOFMIBVIEW: 1839216295Ssyrinx fprintf(stdout, "End of Mib View\n"); 1840216295Ssyrinx return (val->syntax); 1841216295Ssyrinx 1842216295Ssyrinx case SNMP_SYNTAX_NULL: 1843216295Ssyrinx /* NOTREACHED */ 1844216295Ssyrinx fprintf(stdout, "agent returned NULL Syntax\n"); 1845216295Ssyrinx return (val->syntax); 1846216295Ssyrinx 1847216295Ssyrinx default: 1848216295Ssyrinx /* NOTREACHED - If here - then all went completely wrong. */ 1849216295Ssyrinx fprintf(stdout, "agent returned unknown syntax\n"); 1850216295Ssyrinx return (-1); 1851216295Ssyrinx } 1852216295Ssyrinx 1853216295Ssyrinx fprintf(stdout, "\n"); 1854216295Ssyrinx 1855216295Ssyrinx return (0); 1856216295Ssyrinx} 1857216295Ssyrinx 1858216295Ssyrinxstatic int32_t 1859216295Ssyrinxsnmp_fill_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *obj, 1860216295Ssyrinx struct snmp_value *val) 1861216295Ssyrinx{ 1862216295Ssyrinx int32_t rc; 1863216295Ssyrinx asn_subid_t suboid; 1864216295Ssyrinx 1865216295Ssyrinx if (obj == NULL || val == NULL) 1866216295Ssyrinx return (-1); 1867216295Ssyrinx 1868216295Ssyrinx if ((suboid = snmp_suboid_pop(&(val->var))) > ASN_MAXID) 1869216295Ssyrinx return (-1); 1870216295Ssyrinx 1871216295Ssyrinx memset(obj, 0, sizeof(struct snmp_object)); 1872216295Ssyrinx asn_append_oid(&(obj->val.var), &(val->var)); 1873216295Ssyrinx obj->val.syntax = val->syntax; 1874216295Ssyrinx 1875216295Ssyrinx if (obj->val.syntax > 0) 1876216295Ssyrinx rc = snmp_lookup_leafstring(snmptoolctx, obj); 1877216295Ssyrinx else 1878216295Ssyrinx rc = snmp_lookup_nonleaf_string(snmptoolctx, obj); 1879216295Ssyrinx 1880216295Ssyrinx (void) snmp_suboid_append(&(val->var), suboid); 1881216295Ssyrinx (void) snmp_suboid_append(&(obj->val.var), suboid); 1882216295Ssyrinx 1883216295Ssyrinx return (rc); 1884216295Ssyrinx} 1885216295Ssyrinx 1886216295Ssyrinxstatic int32_t 1887216295Ssyrinxsnmp_output_index(struct snmp_toolinfo *snmptoolctx, struct index *stx, 1888216295Ssyrinx struct asn_oid *oid) 1889216295Ssyrinx{ 1890216295Ssyrinx uint8_t ip[4]; 1891216295Ssyrinx uint32_t bytes = 1; 1892216295Ssyrinx uint64_t cnt64; 1893216295Ssyrinx struct asn_oid temp, out; 1894216295Ssyrinx 1895216295Ssyrinx if (oid->len < bytes) 1896216295Ssyrinx return (-1); 1897216295Ssyrinx 1898216295Ssyrinx memset(&temp, 0, sizeof(struct asn_oid)); 1899216295Ssyrinx asn_append_oid(&temp, oid); 1900216295Ssyrinx 1901216295Ssyrinx switch (stx->syntax) { 1902216295Ssyrinx case SNMP_SYNTAX_INTEGER: 1903216295Ssyrinx snmp_output_int(snmptoolctx, stx->snmp_enum, temp.subs[0]); 1904216295Ssyrinx break; 1905216295Ssyrinx 1906216295Ssyrinx case SNMP_SYNTAX_OCTETSTRING: 1907216295Ssyrinx if ((temp.subs[0] > temp.len -1 ) || (temp.subs[0] > 1908216295Ssyrinx ASN_MAXOCTETSTRING)) 1909216295Ssyrinx return (-1); 1910216295Ssyrinx snmp_output_octetindex(snmptoolctx, stx->tc, &temp); 1911216295Ssyrinx bytes += temp.subs[0]; 1912216295Ssyrinx break; 1913216295Ssyrinx 1914216295Ssyrinx case SNMP_SYNTAX_OID: 1915216295Ssyrinx if ((temp.subs[0] > temp.len -1) || (temp.subs[0] > 1916216295Ssyrinx ASN_MAXOIDLEN)) 1917216295Ssyrinx return (-1); 1918216295Ssyrinx 1919216295Ssyrinx bytes += temp.subs[0]; 1920216295Ssyrinx memset(&out, 0, sizeof(struct asn_oid)); 1921216295Ssyrinx asn_slice_oid(&out, &temp, 1, bytes); 1922216295Ssyrinx snmp_output_oid_value(snmptoolctx, &out); 1923216295Ssyrinx break; 1924216295Ssyrinx 1925216295Ssyrinx case SNMP_SYNTAX_IPADDRESS: 1926216295Ssyrinx if (temp.len < 4) 1927216295Ssyrinx return (-1); 1928216295Ssyrinx for (bytes = 0; bytes < 4; bytes++) 1929216295Ssyrinx ip[bytes] = temp.subs[bytes]; 1930216295Ssyrinx 1931216295Ssyrinx snmp_output_ipaddress(snmptoolctx, ip); 1932216295Ssyrinx bytes = 4; 1933216295Ssyrinx break; 1934216295Ssyrinx 1935216295Ssyrinx case SNMP_SYNTAX_COUNTER: 1936216295Ssyrinx snmp_output_counter(snmptoolctx, temp.subs[0]); 1937216295Ssyrinx break; 1938216295Ssyrinx 1939216295Ssyrinx case SNMP_SYNTAX_GAUGE: 1940216295Ssyrinx snmp_output_gauge(snmptoolctx, temp.subs[0]); 1941216295Ssyrinx break; 1942216295Ssyrinx 1943216295Ssyrinx case SNMP_SYNTAX_TIMETICKS: 1944216295Ssyrinx snmp_output_ticks(snmptoolctx, temp.subs[0]); 1945216295Ssyrinx break; 1946216295Ssyrinx 1947216295Ssyrinx case SNMP_SYNTAX_COUNTER64: 1948216295Ssyrinx if (oid->len < 2) 1949216295Ssyrinx return (-1); 1950216295Ssyrinx bytes = 2; 1951216295Ssyrinx memcpy(&cnt64, temp.subs, bytes); 1952216295Ssyrinx snmp_output_counter64(snmptoolctx, cnt64); 1953216295Ssyrinx break; 1954216295Ssyrinx 1955216295Ssyrinx default: 1956216295Ssyrinx return (-1); 1957216295Ssyrinx } 1958216295Ssyrinx 1959216295Ssyrinx return (bytes); 1960216295Ssyrinx} 1961216295Ssyrinx 1962216295Ssyrinxstatic int32_t 1963216295Ssyrinxsnmp_output_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *o) 1964216295Ssyrinx{ 1965216295Ssyrinx int32_t i, first, len; 1966216295Ssyrinx struct asn_oid oid; 1967216295Ssyrinx struct index *temp; 1968216295Ssyrinx 1969216295Ssyrinx if (ISSET_NUMERIC(snmptoolctx)) 1970216295Ssyrinx return (-1); 1971216295Ssyrinx 1972216295Ssyrinx if (o->info->table_idx == NULL) { 1973216295Ssyrinx fprintf(stdout,"%s.%d", o->info->string, 1974216295Ssyrinx o->val.var.subs[o->val.var.len - 1]); 1975216295Ssyrinx return (1); 1976216295Ssyrinx } 1977216295Ssyrinx 1978216295Ssyrinx fprintf(stdout,"%s[", o->info->string); 1979216295Ssyrinx memset(&oid, 0, sizeof(struct asn_oid)); 1980216295Ssyrinx 1981216295Ssyrinx len = 1; 1982216295Ssyrinx asn_slice_oid(&oid, &(o->val.var), (o->info->table_idx->var.len + len), 1983216295Ssyrinx o->val.var.len); 1984216295Ssyrinx 1985216295Ssyrinx first = 1; 1986216295Ssyrinx STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(o)), link) { 1987216295Ssyrinx if(first) 1988216295Ssyrinx first = 0; 1989216295Ssyrinx else 1990216295Ssyrinx fprintf(stdout, ", "); 1991216295Ssyrinx if ((i = snmp_output_index(snmptoolctx, temp, &oid)) < 0) 1992216295Ssyrinx break; 1993216295Ssyrinx len += i; 1994216295Ssyrinx memset(&oid, 0, sizeof(struct asn_oid)); 1995216295Ssyrinx asn_slice_oid(&oid, &(o->val.var), 1996216295Ssyrinx (o->info->table_idx->var.len + len), o->val.var.len + 1); 1997216295Ssyrinx } 1998216295Ssyrinx 1999216295Ssyrinx fprintf(stdout,"]"); 2000216295Ssyrinx return (1); 2001216295Ssyrinx} 2002216295Ssyrinx 2003216295Ssyrinxvoid 2004216295Ssyrinxsnmp_output_err_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu) 2005216295Ssyrinx{ 2006311590Sngie struct snmp_object *object; 2007216295Ssyrinx char buf[ASN_OIDSTRLEN]; 2008216295Ssyrinx 2009216295Ssyrinx if (pdu == NULL || (pdu->error_index > (int32_t) pdu->nbindings)) { 2010311590Sngie fprintf(stdout, "Invalid error index in PDU\n"); 2011216295Ssyrinx return; 2012216295Ssyrinx } 2013216295Ssyrinx 2014311590Sngie if ((object = calloc(1, sizeof(struct snmp_object))) == NULL) { 2015311590Sngie fprintf(stdout, "calloc: %s", strerror(errno)); 2016311590Sngie return; 2017311590Sngie } 2018311590Sngie 2019216295Ssyrinx fprintf(stdout, "Agent %s:%s returned error \n", snmp_client.chost, 2020216295Ssyrinx snmp_client.cport); 2021216295Ssyrinx 2022311590Sngie if (!ISSET_NUMERIC(snmptoolctx) && (snmp_fill_object(snmptoolctx, object, 2023216295Ssyrinx &(pdu->bindings[pdu->error_index - 1])) > 0)) 2024311590Sngie snmp_output_object(snmptoolctx, object); 2025216295Ssyrinx else { 2026216295Ssyrinx asn_oid2str_r(&(pdu->bindings[pdu->error_index - 1].var), buf); 2027216295Ssyrinx fprintf(stdout,"%s", buf); 2028216295Ssyrinx } 2029216295Ssyrinx 2030216295Ssyrinx fprintf(stdout," caused error - "); 2031216295Ssyrinx if ((pdu->error_status > 0) && (pdu->error_status <= 2032216295Ssyrinx SNMP_ERR_INCONS_NAME)) 2033216295Ssyrinx fprintf(stdout, "%s\n", error_strings[pdu->error_status].str); 2034216295Ssyrinx else 2035216295Ssyrinx fprintf(stdout,"%s\n", error_strings[SNMP_ERR_UNKNOWN].str); 2036311590Sngie 2037311590Sngie free(object); 2038311590Sngie object = NULL; 2039216295Ssyrinx} 2040216295Ssyrinx 2041216295Ssyrinxint32_t 2042229933Ssyrinxsnmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu, 2043229933Ssyrinx struct asn_oid *root) 2044216295Ssyrinx{ 2045311590Sngie struct snmp_object *object; 2046311153Sngie char p[ASN_OIDSTRLEN]; 2047216295Ssyrinx int32_t error; 2048216295Ssyrinx uint32_t i; 2049216295Ssyrinx 2050311590Sngie if ((object = calloc(1, sizeof(struct snmp_object))) == NULL) 2051311590Sngie return (-1); 2052311590Sngie 2053229933Ssyrinx i = error = 0; 2054229933Ssyrinx while (i < pdu->nbindings) { 2055229933Ssyrinx if (root != NULL && !(asn_is_suboid(root, 2056229933Ssyrinx &(pdu->bindings[i].var)))) 2057229933Ssyrinx break; 2058229933Ssyrinx 2059216295Ssyrinx if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) { 2060216295Ssyrinx if (!ISSET_NUMERIC(snmptoolctx) && 2061311590Sngie (snmp_fill_object(snmptoolctx, object, 2062216295Ssyrinx &(pdu->bindings[i])) > 0)) 2063311590Sngie snmp_output_object(snmptoolctx, object); 2064216295Ssyrinx else { 2065216295Ssyrinx asn_oid2str_r(&(pdu->bindings[i].var), p); 2066216295Ssyrinx fprintf(stdout, "%s", p); 2067216295Ssyrinx } 2068216295Ssyrinx } 2069311590Sngie error |= snmp_output_numval(snmptoolctx, &(pdu->bindings[i]), 2070311590Sngie object->info); 2071229933Ssyrinx i++; 2072216295Ssyrinx } 2073216295Ssyrinx 2074311590Sngie free(object); 2075311590Sngie object = NULL; 2076311590Sngie 2077229933Ssyrinx if (error) 2078229933Ssyrinx return (-1); 2079229933Ssyrinx 2080229933Ssyrinx return (i); 2081216295Ssyrinx} 2082216295Ssyrinx 2083216295Ssyrinxvoid 2084216295Ssyrinxsnmp_output_engine(void) 2085216295Ssyrinx{ 2086216295Ssyrinx uint32_t i; 2087216295Ssyrinx char *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2]; 2088216295Ssyrinx 2089216295Ssyrinx cptr = engine; 2090216295Ssyrinx for (i = 0; i < snmp_client.engine.engine_len; i++) 2091216295Ssyrinx cptr += sprintf(cptr, "%.2x", snmp_client.engine.engine_id[i]); 2092216295Ssyrinx *cptr++ = '\0'; 2093216295Ssyrinx 2094216295Ssyrinx fprintf(stdout, "Engine ID 0x%s\n", engine); 2095216295Ssyrinx fprintf(stdout, "Boots : %u\t\tTime : %d\n", 2096216295Ssyrinx snmp_client.engine.engine_boots, 2097216295Ssyrinx snmp_client.engine.engine_time); 2098216295Ssyrinx} 2099216295Ssyrinx 2100216295Ssyrinxvoid 2101216295Ssyrinxsnmp_output_keys(void) 2102216295Ssyrinx{ 2103216295Ssyrinx uint32_t i, keylen = 0; 2104216295Ssyrinx char *cptr, extkey[2 * SNMP_AUTH_KEY_SIZ + 2]; 2105216295Ssyrinx 2106216295Ssyrinx fprintf(stdout, "Localized keys for %s\n", snmp_client.user.sec_name); 2107216295Ssyrinx if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_MD5) { 2108216295Ssyrinx fprintf(stdout, "MD5 : 0x"); 2109216295Ssyrinx keylen = SNMP_AUTH_HMACMD5_KEY_SIZ; 2110216295Ssyrinx } else if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_SHA) { 2111216295Ssyrinx fprintf(stdout, "SHA : 0x"); 2112216295Ssyrinx keylen = SNMP_AUTH_HMACSHA_KEY_SIZ; 2113216295Ssyrinx } 2114216295Ssyrinx if (snmp_client.user.auth_proto != SNMP_AUTH_NOAUTH) { 2115216295Ssyrinx cptr = extkey; 2116216295Ssyrinx for (i = 0; i < keylen; i++) 2117216295Ssyrinx cptr += sprintf(cptr, "%.2x", 2118216295Ssyrinx snmp_client.user.auth_key[i]); 2119216295Ssyrinx *cptr++ = '\0'; 2120216295Ssyrinx fprintf(stdout, "%s\n", extkey); 2121216295Ssyrinx } 2122216295Ssyrinx 2123216295Ssyrinx if (snmp_client.user.priv_proto == SNMP_PRIV_DES) { 2124216295Ssyrinx fprintf(stdout, "DES : 0x"); 2125216295Ssyrinx keylen = SNMP_PRIV_DES_KEY_SIZ; 2126216295Ssyrinx } else if (snmp_client.user.priv_proto == SNMP_PRIV_AES) { 2127216295Ssyrinx fprintf(stdout, "AES : 0x"); 2128216295Ssyrinx keylen = SNMP_PRIV_AES_KEY_SIZ; 2129216295Ssyrinx } 2130216295Ssyrinx if (snmp_client.user.priv_proto != SNMP_PRIV_NOPRIV) { 2131216295Ssyrinx cptr = extkey; 2132216295Ssyrinx for (i = 0; i < keylen; i++) 2133216295Ssyrinx cptr += sprintf(cptr, "%.2x", 2134216295Ssyrinx snmp_client.user.priv_key[i]); 2135216295Ssyrinx *cptr++ = '\0'; 2136216295Ssyrinx fprintf(stdout, "%s\n", extkey); 2137216295Ssyrinx } 2138216295Ssyrinx} 2139