bsnmptools.c revision 245952
1178825Sdfr/*- 2178825Sdfr * Copyright (c) 2005-2006 The FreeBSD Project 3178825Sdfr * All rights reserved. 4178825Sdfr * 5178825Sdfr * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6178825Sdfr * 7178825Sdfr * Redistribution of this software and documentation and use in source and 8178825Sdfr * binary forms, with or without modification, are permitted provided that 9178825Sdfr * the following conditions are met: 10178825Sdfr * 11233294Sstas * 1. Redistributions of source code or documentation must retain the above 12178825Sdfr * copyright notice, this list of conditions and the following disclaimer. 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27178825Sdfr * SUCH DAMAGE. 28178825Sdfr * 29178825Sdfr * Helper functions for snmp client tools 30178825Sdfr * 31178825Sdfr * $FreeBSD: head/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c 245952 2013-01-26 22:08:21Z pfg $ 32178825Sdfr */ 33233294Sstas 34178825Sdfr#include <sys/param.h> 35178825Sdfr#include <sys/queue.h> 36178825Sdfr#include <sys/uio.h> 37178825Sdfr 38178825Sdfr#include <assert.h> 39178825Sdfr#include <ctype.h> 40178825Sdfr#include <err.h> 41178825Sdfr#include <errno.h> 42178825Sdfr#include <fcntl.h> 43178825Sdfr#include <stdio.h> 44178825Sdfr#include <stdlib.h> 45178825Sdfr#include <string.h> 46178825Sdfr#include <syslog.h> 47178825Sdfr#include <unistd.h> 48178825Sdfr 49178825Sdfr#include <bsnmp/asn1.h> 50178825Sdfr#include <bsnmp/snmp.h> 51178825Sdfr#include <bsnmp/snmpclient.h> 52178825Sdfr#include "bsnmptc.h" 53178825Sdfr#include "bsnmptools.h" 54178825Sdfr 55178825Sdfr/* Internal varibale to turn on library debugging for testing and to 56178825Sdfr * find bugs. It is not exported via the header file. 57178825Sdfr * XXX should we cover it by some #ifdef BSNMPTOOLS_DEBUG? */ 58178825Sdfrint _bsnmptools_debug = 0; 59178825Sdfr 60178825Sdfr/* Default files to import mapping from if none explicitly provided. */ 61178825Sdfr#define bsnmpd_defs "/usr/share/snmp/defs/tree.def" 62178825Sdfr#define mibII_defs "/usr/share/snmp/defs/mibII_tree.def" 63178825Sdfr 64178825Sdfr/* 65178825Sdfr * The .iso.org.dod oid that has to be prepended to every OID when requesting 66178825Sdfr * a value. 67178825Sdfr */ 68178825Sdfrconst struct asn_oid IsoOrgDod_OID = { 69178825Sdfr 3, { 1, 3, 6 } 70178825Sdfr}; 71178825Sdfr 72178825Sdfr 73178825Sdfr#define SNMP_ERR_UNKNOWN 0 74178825Sdfr 75178825Sdfr/* 76178825Sdfr * An array of error strings corresponding to error definitions from libbsnmp. 77178825Sdfr */ 78178825Sdfrstatic const struct { 79178825Sdfr const char *str; 80178825Sdfr int32_t error; 81178825Sdfr} error_strings[] = { 82178825Sdfr { "Unknown", SNMP_ERR_UNKNOWN }, 83178825Sdfr { "Too big ", SNMP_ERR_TOOBIG }, 84178825Sdfr { "No such Name", SNMP_ERR_NOSUCHNAME }, 85178825Sdfr { "Bad Value", SNMP_ERR_BADVALUE }, 86178825Sdfr { "Readonly", SNMP_ERR_READONLY }, 87178825Sdfr { "General error", SNMP_ERR_GENERR }, 88178825Sdfr { "No access", SNMP_ERR_NO_ACCESS }, 89178825Sdfr { "Wrong type", SNMP_ERR_WRONG_TYPE }, 90178825Sdfr { "Wrong length", SNMP_ERR_WRONG_LENGTH }, 91178825Sdfr { "Wrong encoding", SNMP_ERR_WRONG_ENCODING }, 92178825Sdfr { "Wrong value", SNMP_ERR_WRONG_VALUE }, 93178825Sdfr { "No creation", SNMP_ERR_NO_CREATION }, 94178825Sdfr { "Inconsistent value", SNMP_ERR_INCONS_VALUE }, 95178825Sdfr { "Resource unavailable", SNMP_ERR_RES_UNAVAIL }, 96233294Sstas { "Commit failed", SNMP_ERR_COMMIT_FAILED }, 97233294Sstas { "Undo failed", SNMP_ERR_UNDO_FAILED }, 98178825Sdfr { "Authorization error", SNMP_ERR_AUTH_ERR }, 99178825Sdfr { "Not writable", SNMP_ERR_NOT_WRITEABLE }, 100178825Sdfr { "Inconsistent name", SNMP_ERR_INCONS_NAME }, 101233294Sstas { NULL, 0 } 102178825Sdfr}; 103178825Sdfr 104178825Sdfr/* This one and any following are exceptions. */ 105178825Sdfr#define SNMP_SYNTAX_UNKNOWN SNMP_SYNTAX_NOSUCHOBJECT 106178825Sdfr 107178825Sdfrstatic const struct { 108178825Sdfr const char *str; 109178825Sdfr enum snmp_syntax stx; 110178825Sdfr} syntax_strings[] = { 111178825Sdfr { "Null", SNMP_SYNTAX_NULL }, 112178825Sdfr { "Integer", SNMP_SYNTAX_INTEGER }, 113178825Sdfr { "OctetString", SNMP_SYNTAX_OCTETSTRING }, 114178825Sdfr { "OID", SNMP_SYNTAX_OID }, 115178825Sdfr { "IpAddress", SNMP_SYNTAX_IPADDRESS }, 116178825Sdfr { "Counter32", SNMP_SYNTAX_COUNTER }, 117178825Sdfr { "Gauge", SNMP_SYNTAX_GAUGE }, 118178825Sdfr { "TimeTicks", SNMP_SYNTAX_TIMETICKS }, 119178825Sdfr { "Counter64", SNMP_SYNTAX_COUNTER64 }, 120178825Sdfr { "Unknown", SNMP_SYNTAX_UNKNOWN }, 121178825Sdfr}; 122178825Sdfr 123178825Sdfrint 124178825Sdfrsnmptool_init(struct snmp_toolinfo *snmptoolctx) 125178825Sdfr{ 126178825Sdfr char *str; 127178825Sdfr size_t slen; 128178825Sdfr 129178825Sdfr memset(snmptoolctx, 0, sizeof(struct snmp_toolinfo)); 130178825Sdfr snmptoolctx->objects = 0; 131178825Sdfr snmptoolctx->mappings = NULL; 132178825Sdfr snmptoolctx->flags = SNMP_PDU_GET; /* XXX */ 133178825Sdfr SLIST_INIT(&snmptoolctx->filelist); 134178825Sdfr snmp_client_init(&snmp_client); 135178825Sdfr SET_MAXREP(snmptoolctx, SNMP_MAX_REPETITIONS); 136178825Sdfr 137178825Sdfr if (add_filename(snmptoolctx, bsnmpd_defs, &IsoOrgDod_OID, 0) < 0) 138178825Sdfr warnx("Error adding file %s to list", bsnmpd_defs); 139178825Sdfr 140178825Sdfr if (add_filename(snmptoolctx, mibII_defs, &IsoOrgDod_OID, 0) < 0) 141178825Sdfr warnx("Error adding file %s to list", mibII_defs); 142178825Sdfr 143178825Sdfr /* Read the environment */ 144178825Sdfr if ((str = getenv("SNMPAUTH")) != NULL) { 145178825Sdfr slen = strlen(str); 146178825Sdfr if (slen == strlen("md5") && strcasecmp(str, "md5") == 0) 147178825Sdfr snmp_client.user.auth_proto = SNMP_AUTH_HMAC_MD5; 148178825Sdfr else if (slen == strlen("sha")&& strcasecmp(str, "sha") == 0) 149178825Sdfr snmp_client.user.auth_proto = SNMP_AUTH_HMAC_SHA; 150178825Sdfr else if (slen != 0) 151178825Sdfr warnx("Bad authentication type - %s in SNMPAUTH", str); 152178825Sdfr } 153178825Sdfr 154178825Sdfr if ((str = getenv("SNMPPRIV")) != NULL) { 155233294Sstas slen = strlen(str); 156233294Sstas if (slen == strlen("des") && strcasecmp(str, "des") == 0) 157233294Sstas snmp_client.user.priv_proto = SNMP_PRIV_DES; 158233294Sstas else if (slen == strlen("aes")&& strcasecmp(str, "aes") == 0) 159178825Sdfr snmp_client.user.priv_proto = SNMP_PRIV_AES; 160233294Sstas else if (slen != 0) 161233294Sstas warnx("Bad privacy type - %s in SNMPPRIV", str); 162178825Sdfr } 163178825Sdfr 164178825Sdfr if ((str = getenv("SNMPUSER")) != NULL) { 165178825Sdfr if ((slen = strlen(str)) > sizeof(snmp_client.user.sec_name)) { 166178825Sdfr warnx("Username too long - %s in SNMPUSER", str); 167178825Sdfr return (-1); 168178825Sdfr } 169178825Sdfr if (slen > 0) { 170178825Sdfr strlcpy(snmp_client.user.sec_name, str, 171178825Sdfr sizeof(snmp_client.user.sec_name)); 172178825Sdfr snmp_client.version = SNMP_V3; 173178825Sdfr } 174178825Sdfr } 175178825Sdfr 176178825Sdfr if ((str = getenv("SNMPPASSWD")) != NULL) { 177178825Sdfr if ((slen = strlen(str)) > MAXSTR) 178178825Sdfr slen = MAXSTR - 1; 179178825Sdfr if ((snmptoolctx->passwd = malloc(slen + 1)) == NULL) { 180178825Sdfr warnx("malloc() failed - %s", strerror(errno)); 181178825Sdfr return (-1); 182178825Sdfr } 183178825Sdfr if (slen > 0) 184178825Sdfr strlcpy(snmptoolctx->passwd, str, slen + 1); 185178825Sdfr } 186178825Sdfr 187178825Sdfr return (0); 188178825Sdfr} 189178825Sdfr 190178825Sdfr#define OBJECT_IDX_LIST(o) o->info->table_idx->index_list 191178825Sdfr 192178825Sdfr/* 193178825Sdfr * Walk through the file list and import string<->oid mappings from each file. 194178825Sdfr */ 195178825Sdfrint32_t 196178825Sdfrsnmp_import_all(struct snmp_toolinfo *snmptoolctx) 197178825Sdfr{ 198178825Sdfr int32_t fc; 199178825Sdfr struct fname *tmp; 200178825Sdfr 201178825Sdfr if (snmptoolctx == NULL) 202178825Sdfr return (-1); 203233294Sstas 204178825Sdfr if (ISSET_NUMERIC(snmptoolctx)) 205178825Sdfr return (0); 206178825Sdfr 207178825Sdfr if ((snmptoolctx->mappings = snmp_mapping_init()) == NULL) 208178825Sdfr return (-1); 209178825Sdfr 210178825Sdfr fc = 0; 211178825Sdfr if (SLIST_EMPTY(&snmptoolctx->filelist)) { 212178825Sdfr warnx("No files to read OID <-> string conversions from"); 213178825Sdfr return (-1); 214178825Sdfr } else { 215178825Sdfr SLIST_FOREACH(tmp, &snmptoolctx->filelist, link) { 216178825Sdfr if (tmp->done) 217178825Sdfr continue; 218178825Sdfr if (snmp_import_file(snmptoolctx, tmp) < 0) { 219178825Sdfr fc = -1; 220178825Sdfr break; 221178825Sdfr } 222178825Sdfr fc++; 223178825Sdfr } 224178825Sdfr } 225178825Sdfr 226178825Sdfr snmp_mapping_dump(snmptoolctx); 227178825Sdfr return (fc); 228178825Sdfr} 229178825Sdfr 230178825Sdfr/* 231178825Sdfr * Add a filename to the file list - the initial idea of keeping a list with all 232178825Sdfr * files to read OIDs from was that an application might want to have loaded in 233178825Sdfr * memory the OIDs from a single file only and when done with them read the OIDs 234178825Sdfr * from another file. This is not used yet but might be a good idea at some 235178825Sdfr * point. Size argument is number of bytes in string including trailing '\0', 236178825Sdfr * not string length. 237178825Sdfr */ 238178825Sdfrint32_t 239178825Sdfradd_filename(struct snmp_toolinfo *snmptoolctx, const char *filename, 240178825Sdfr const struct asn_oid *cut, int32_t done) 241178825Sdfr{ 242178825Sdfr char *fstring; 243178825Sdfr struct fname *entry; 244178825Sdfr 245178825Sdfr if (snmptoolctx == NULL) 246178825Sdfr return (-1); 247178825Sdfr 248178825Sdfr /* Make sure file was not in list. */ 249178825Sdfr SLIST_FOREACH(entry, &snmptoolctx->filelist, link) { 250178825Sdfr if (strncmp(entry->name, filename, strlen(entry->name)) == 0) 251178825Sdfr return (0); 252178825Sdfr } 253178825Sdfr 254178825Sdfr if ((fstring = malloc(strlen(filename) + 1)) == NULL) { 255178825Sdfr warnx("malloc() failed - %s", strerror(errno)); 256178825Sdfr return (-1); 257178825Sdfr } 258178825Sdfr 259178825Sdfr if ((entry = malloc(sizeof(struct fname))) == NULL) { 260178825Sdfr warnx("malloc() failed - %s", strerror(errno)); 261178825Sdfr free(fstring); 262178825Sdfr return (-1); 263178825Sdfr } 264178825Sdfr 265178825Sdfr memset(entry, 0, sizeof(struct fname)); 266178825Sdfr 267178825Sdfr if (cut != NULL) 268178825Sdfr asn_append_oid(&(entry->cut), cut); 269178825Sdfr strlcpy(fstring, filename, strlen(filename) + 1); 270178825Sdfr entry->name = fstring; 271178825Sdfr entry->done = done; 272178825Sdfr SLIST_INSERT_HEAD(&snmptoolctx->filelist, entry, link); 273233294Sstas 274233294Sstas return (1); 275178825Sdfr} 276178825Sdfr 277178825Sdfrvoid 278178825Sdfrfree_filelist(struct snmp_toolinfo *snmptoolctx) 279178825Sdfr{ 280178825Sdfr struct fname *f; 281178825Sdfr 282178825Sdfr if (snmptoolctx == NULL) 283178825Sdfr return; /* XXX error handling */ 284178825Sdfr 285178825Sdfr while ((f = SLIST_FIRST(&snmptoolctx->filelist)) != NULL) { 286178825Sdfr SLIST_REMOVE_HEAD(&snmptoolctx->filelist, link); 287178825Sdfr if (f->name) 288178825Sdfr free(f->name); 289178825Sdfr free(f); 290178825Sdfr } 291178825Sdfr} 292178825Sdfr 293178825Sdfrstatic char 294178825Sdfrisvalid_fchar(char c, int pos) 295178825Sdfr{ 296178825Sdfr if (isalpha(c)|| c == '/'|| c == '_' || c == '.' || c == '~' || 297178825Sdfr (pos != 0 && isdigit(c))){ 298178825Sdfr return (c); 299178825Sdfr } 300178825Sdfr 301178825Sdfr if (c == '\0') 302233294Sstas return (0); 303178825Sdfr 304178825Sdfr if (!isascii(c) || !isprint(c)) 305178825Sdfr warnx("Unexpected character %#2x", (u_int) c); 306178825Sdfr else 307178825Sdfr warnx("Illegal character '%c'", c); 308178825Sdfr 309178825Sdfr return (-1); 310178825Sdfr} 311178825Sdfr 312178825Sdfr/* 313178825Sdfr * Re-implement getsubopt from scratch, because the second argument is broken 314178825Sdfr * and will not compile with WARNS=5. 315178825Sdfr * Copied from src/contrib/bsnmp/snmpd/main.c. 316178825Sdfr */ 317178825Sdfrstatic int 318178825Sdfrgetsubopt1(char **arg, const char *const *options, char **valp, char **optp) 319178825Sdfr{ 320178825Sdfr static const char *const delim = ",\t "; 321178825Sdfr u_int i; 322178825Sdfr char *ptr; 323178825Sdfr 324178825Sdfr *optp = NULL; 325178825Sdfr 326178825Sdfr /* Skip leading junk. */ 327178825Sdfr for (ptr = *arg; *ptr != '\0'; ptr++) 328178825Sdfr if (strchr(delim, *ptr) == NULL) 329178825Sdfr break; 330178825Sdfr if (*ptr == '\0') { 331178825Sdfr *arg = ptr; 332178825Sdfr return (-1); 333178825Sdfr } 334178825Sdfr *optp = ptr; 335178825Sdfr 336178825Sdfr /* Find the end of the option. */ 337178825Sdfr while (*++ptr != '\0') 338178825Sdfr if (strchr(delim, *ptr) != NULL || *ptr == '=') 339178825Sdfr break; 340178825Sdfr 341178825Sdfr if (*ptr != '\0') { 342178825Sdfr if (*ptr == '=') { 343178825Sdfr *ptr++ = '\0'; 344178825Sdfr *valp = ptr; 345178825Sdfr while (*ptr != '\0' && strchr(delim, *ptr) == NULL) 346178825Sdfr ptr++; 347178825Sdfr if (*ptr != '\0') 348178825Sdfr *ptr++ = '\0'; 349178825Sdfr } else 350178825Sdfr *ptr++ = '\0'; 351178825Sdfr } 352178825Sdfr 353178825Sdfr *arg = ptr; 354178825Sdfr 355178825Sdfr for (i = 0; *options != NULL; options++, i++) 356178825Sdfr if (strcmp(*optp, *options) == 0) 357178825Sdfr return (i); 358178825Sdfr return (-1); 359178825Sdfr} 360178825Sdfr 361178825Sdfrstatic int32_t 362178825Sdfrparse_path(char *value) 363178825Sdfr{ 364178825Sdfr int32_t i, len; 365178825Sdfr 366178825Sdfr if (value == NULL) 367178825Sdfr return (-1); 368178825Sdfr 369178825Sdfr for (len = 0; len < MAXPATHLEN; len++) { 370178825Sdfr i = isvalid_fchar(*(value + len), len) ; 371178825Sdfr 372178825Sdfr if (i == 0) 373178825Sdfr break; 374178825Sdfr else if (i < 0) 375178825Sdfr return (-1); 376178825Sdfr } 377178825Sdfr 378178825Sdfr if (len >= MAXPATHLEN || value[len] != '\0') { 379178825Sdfr warnx("Bad pathname - '%s'", value); 380178825Sdfr return (-1); 381178825Sdfr } 382178825Sdfr 383178825Sdfr return (len); 384178825Sdfr} 385178825Sdfr 386178825Sdfrstatic int32_t 387178825Sdfrparse_flist(struct snmp_toolinfo *snmptoolctx, char *value, char *path, 388178825Sdfr const struct asn_oid *cut) 389178825Sdfr{ 390178825Sdfr int32_t namelen; 391178825Sdfr char filename[MAXPATHLEN + 1]; 392178825Sdfr 393178825Sdfr if (value == NULL) 394178825Sdfr return (-1); 395178825Sdfr 396178825Sdfr do { 397178825Sdfr memset(filename, 0, MAXPATHLEN + 1); 398178825Sdfr 399178825Sdfr if (isalpha(*value) && (path == NULL || path[0] == '\0')) { 400178825Sdfr strlcpy(filename, SNMP_DEFS_DIR, MAXPATHLEN + 1); 401178825Sdfr namelen = strlen(SNMP_DEFS_DIR); 402178825Sdfr } else if (path != NULL){ 403178825Sdfr strlcpy(filename, path, MAXPATHLEN + 1); 404178825Sdfr namelen = strlen(path); 405178825Sdfr } else 406178825Sdfr namelen = 0; 407178825Sdfr 408178825Sdfr for ( ; namelen < MAXPATHLEN; value++) { 409178825Sdfr if (isvalid_fchar(*value, namelen) > 0) { 410178825Sdfr filename[namelen++] = *value; 411178825Sdfr continue; 412178825Sdfr } 413178825Sdfr 414178825Sdfr if (*value == ',' ) 415178825Sdfr value++; 416178825Sdfr else if (*value == '\0') 417178825Sdfr ; 418178825Sdfr else { 419178825Sdfr if (!isascii(*value) || !isprint(*value)) 420178825Sdfr warnx("Unexpected character %#2x in" 421178825Sdfr " filename", (u_int) *value); 422178825Sdfr else 423178825Sdfr warnx("Illegal character '%c' in" 424178825Sdfr " filename", *value); 425178825Sdfr return (-1); 426178825Sdfr } 427178825Sdfr 428178825Sdfr filename[namelen]='\0'; 429178825Sdfr break; 430178825Sdfr } 431178825Sdfr 432178825Sdfr if ((namelen == MAXPATHLEN) && (filename[MAXPATHLEN] != '\0')) { 433178825Sdfr warnx("Filename %s too long", filename); 434178825Sdfr return (-1); 435178825Sdfr } 436178825Sdfr 437178825Sdfr if (add_filename(snmptoolctx, filename, cut, 0) < 0) { 438178825Sdfr warnx("Error adding file %s to list", filename); 439178825Sdfr return (-1); 440178825Sdfr } 441178825Sdfr } while (*value != '\0'); 442178825Sdfr 443178825Sdfr return(1); 444178825Sdfr} 445178825Sdfr 446178825Sdfrstatic int32_t 447178825Sdfrparse_ascii(char *ascii, uint8_t *binstr, size_t binlen) 448178825Sdfr{ 449178825Sdfr int32_t alen, count, saved_errno, i; 450178825Sdfr uint32_t val; 451178825Sdfr char dptr[3]; 452178825Sdfr 453178825Sdfr /* Filter 0x at the beginning */ 454178825Sdfr if ((alen = strlen(ascii)) > 2 && ascii[0] == '0' && ascii[1] == 'x') 455178825Sdfr i = 2; 456178825Sdfr else 457178825Sdfr i = 0; 458178825Sdfr 459178825Sdfr saved_errno = errno; 460178825Sdfr errno = 0; 461178825Sdfr for (count = 0; i < alen; i += 2) { 462178825Sdfr /* XXX: consider strlen(ascii) % 2 != 0 */ 463178825Sdfr dptr[0] = ascii[i]; 464178825Sdfr dptr[1] = ascii[i + 1]; 465178825Sdfr dptr[2] = '\0'; 466178825Sdfr if ((val = strtoul(dptr, NULL, 16)) > 0xFF || errno != 0) { 467178825Sdfr errno = saved_errno; 468178825Sdfr return (-1); 469178825Sdfr } 470178825Sdfr binstr[count] = (uint8_t) val; 471178825Sdfr if (++count >= binlen) { 472178825Sdfr warnx("Key %s too long - truncating to %zu octets", 473178825Sdfr ascii, binlen); 474178825Sdfr break; 475178825Sdfr } 476178825Sdfr } 477178825Sdfr 478178825Sdfr return (count); 479178825Sdfr} 480178825Sdfr 481178825Sdfr/* 482178825Sdfr * Functions to parse common input options for client tools and fill in the 483178825Sdfr * snmp_client structure. 484178825Sdfr */ 485178825Sdfrint32_t 486178825Sdfrparse_authentication(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 487178825Sdfr{ 488178825Sdfr int32_t count, subopt; 489178825Sdfr char *val, *option; 490178825Sdfr const char *const subopts[] = { 491178825Sdfr "proto", 492178825Sdfr "key", 493178825Sdfr NULL 494178825Sdfr }; 495178825Sdfr 496178825Sdfr assert(opt_arg != NULL); 497178825Sdfr count = 1; 498178825Sdfr while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 499178825Sdfr switch (subopt) { 500178825Sdfr case 0: 501178825Sdfr if (val == NULL) { 502178825Sdfr warnx("Suboption 'proto' requires an argument"); 503178825Sdfr return (-1); 504178825Sdfr } 505178825Sdfr if (strlen(val) != 3) { 506178825Sdfr warnx("Unknown auth protocol - %s", val); 507178825Sdfr return (-1); 508178825Sdfr } 509178825Sdfr if (strncasecmp("md5", val, strlen("md5")) == 0) 510178825Sdfr snmp_client.user.auth_proto = 511178825Sdfr SNMP_AUTH_HMAC_MD5; 512178825Sdfr else if (strncasecmp("sha", val, strlen("sha")) == 0) 513178825Sdfr snmp_client.user.auth_proto = 514178825Sdfr SNMP_AUTH_HMAC_SHA; 515178825Sdfr else { 516178825Sdfr warnx("Unknown auth protocol - %s", val); 517178825Sdfr return (-1); 518178825Sdfr } 519178825Sdfr break; 520178825Sdfr case 1: 521178825Sdfr if (val == NULL) { 522178825Sdfr warnx("Suboption 'key' requires an argument"); 523178825Sdfr return (-1); 524178825Sdfr } 525178825Sdfr if (parse_ascii(val, snmp_client.user.auth_key, 526178825Sdfr SNMP_AUTH_KEY_SIZ) < 0) { 527178825Sdfr warnx("Bad authentication key- %s", val); 528178825Sdfr return (-1); 529178825Sdfr } 530178825Sdfr break; 531178825Sdfr default: 532178825Sdfr warnx("Unknown suboption - '%s'", suboptarg); 533178825Sdfr return (-1); 534178825Sdfr } 535178825Sdfr count += 1; 536178825Sdfr } 537178825Sdfr return (2/* count */); 538178825Sdfr} 539178825Sdfr 540178825Sdfrint32_t 541178825Sdfrparse_privacy(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 542178825Sdfr{ 543178825Sdfr int32_t count, subopt; 544178825Sdfr char *val, *option; 545178825Sdfr const char *const subopts[] = { 546178825Sdfr "proto", 547178825Sdfr "key", 548178825Sdfr NULL 549178825Sdfr }; 550178825Sdfr 551178825Sdfr assert(opt_arg != NULL); 552178825Sdfr count = 1; 553178825Sdfr while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 554178825Sdfr switch (subopt) { 555178825Sdfr case 0: 556178825Sdfr if (val == NULL) { 557178825Sdfr warnx("Suboption 'proto' requires an argument"); 558178825Sdfr return (-1); 559178825Sdfr } 560178825Sdfr if (strlen(val) != 3) { 561178825Sdfr warnx("Unknown privacy protocol - %s", val); 562178825Sdfr return (-1); 563178825Sdfr } 564178825Sdfr if (strncasecmp("aes", val, strlen("aes")) == 0) 565178825Sdfr snmp_client.user.priv_proto = SNMP_PRIV_AES; 566178825Sdfr else if (strncasecmp("des", val, strlen("des")) == 0) 567178825Sdfr snmp_client.user.priv_proto = SNMP_PRIV_DES; 568178825Sdfr else { 569178825Sdfr warnx("Unknown privacy protocol - %s", val); 570178825Sdfr return (-1); 571178825Sdfr } 572178825Sdfr break; 573178825Sdfr case 1: 574178825Sdfr if (val == NULL) { 575178825Sdfr warnx("Suboption 'key' requires an argument"); 576178825Sdfr return (-1); 577178825Sdfr } 578178825Sdfr if (parse_ascii(val, snmp_client.user.priv_key, 579178825Sdfr SNMP_PRIV_KEY_SIZ) < 0) { 580178825Sdfr warnx("Bad privacy key- %s", val); 581178825Sdfr return (-1); 582178825Sdfr } 583178825Sdfr break; 584178825Sdfr default: 585178825Sdfr warnx("Unknown suboption - '%s'", suboptarg); 586178825Sdfr return (-1); 587178825Sdfr } 588178825Sdfr count += 1; 589178825Sdfr } 590178825Sdfr return (2/* count */); 591178825Sdfr} 592178825Sdfr 593178825Sdfrint32_t 594178825Sdfrparse_context(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 595178825Sdfr{ 596178825Sdfr int32_t count, subopt; 597178825Sdfr char *val, *option; 598178825Sdfr const char *const subopts[] = { 599178825Sdfr "context", 600178825Sdfr "context-engine", 601178825Sdfr NULL 602178825Sdfr }; 603178825Sdfr 604178825Sdfr assert(opt_arg != NULL); 605178825Sdfr count = 1; 606178825Sdfr while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 607178825Sdfr switch (subopt) { 608178825Sdfr case 0: 609178825Sdfr if (val == NULL) { 610178825Sdfr warnx("Suboption 'context' - no argument"); 611178825Sdfr return (-1); 612178825Sdfr } 613178825Sdfr strlcpy(snmp_client.cname, val, SNMP_CONTEXT_NAME_SIZ); 614178825Sdfr break; 615178825Sdfr case 1: 616178825Sdfr if (val == NULL) { 617178825Sdfr warnx("Suboption 'context-engine' - no argument"); 618178825Sdfr return (-1); 619178825Sdfr } 620178825Sdfr if ((snmp_client.clen = parse_ascii(val, 621178825Sdfr snmp_client.cengine, SNMP_ENGINE_ID_SIZ)) < 0) { 622178825Sdfr warnx("Bad EngineID - %s", val); 623178825Sdfr return (-1); 624178825Sdfr } 625178825Sdfr break; 626178825Sdfr default: 627178825Sdfr warnx("Unknown suboption - '%s'", suboptarg); 628178825Sdfr return (-1); 629178825Sdfr } 630178825Sdfr count += 1; 631178825Sdfr } 632178825Sdfr return (2/* count */); 633178825Sdfr} 634178825Sdfr 635178825Sdfrint32_t 636178825Sdfrparse_user_security(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 637178825Sdfr{ 638178825Sdfr int32_t count, subopt, saved_errno; 639178825Sdfr char *val, *option; 640178825Sdfr const char *const subopts[] = { 641178825Sdfr "engine", 642178825Sdfr "engine-boots", 643178825Sdfr "engine-time", 644178825Sdfr "name", 645178825Sdfr NULL 646178825Sdfr }; 647178825Sdfr 648178825Sdfr assert(opt_arg != NULL); 649178825Sdfr count = 1; 650178825Sdfr while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 651178825Sdfr switch (subopt) { 652178825Sdfr case 0: 653178825Sdfr if (val == NULL) { 654178825Sdfr warnx("Suboption 'engine' - no argument"); 655178825Sdfr return (-1); 656178825Sdfr } 657178825Sdfr snmp_client.engine.engine_len = parse_ascii(val, 658178825Sdfr snmp_client.engine.engine_id, SNMP_ENGINE_ID_SIZ); 659178825Sdfr if (snmp_client.engine.engine_len < 0) { 660178825Sdfr warnx("Bad EngineID - %s", val); 661178825Sdfr return (-1); 662178825Sdfr } 663178825Sdfr break; 664178825Sdfr case 1: 665178825Sdfr if (val == NULL) { 666178825Sdfr warnx("Suboption 'engine-boots' - no argument"); 667178825Sdfr return (-1); 668178825Sdfr } 669178825Sdfr saved_errno = errno; 670178825Sdfr errno = 0; 671178825Sdfr snmp_client.engine.engine_boots = strtoul(val, NULL, 10); 672178825Sdfr if (errno != 0) { 673178825Sdfr warnx("Bad 'engine-boots' value %s - %s", val, 674178825Sdfr strerror(errno)); 675178825Sdfr errno = saved_errno; 676178825Sdfr return (-1); 677178825Sdfr } 678178825Sdfr errno = saved_errno; 679178825Sdfr break; 680178825Sdfr case 2: 681178825Sdfr if (val == NULL) { 682178825Sdfr warnx("Suboption 'engine-time' - no argument"); 683178825Sdfr return (-1); 684178825Sdfr } 685178825Sdfr saved_errno = errno; 686178825Sdfr errno = 0; 687178825Sdfr snmp_client.engine.engine_time = strtoul(val, NULL, 10); 688178825Sdfr if (errno != 0) { 689178825Sdfr warnx("Bad 'engine-time' value %s - %s", val, 690178825Sdfr strerror(errno)); 691178825Sdfr errno = saved_errno; 692178825Sdfr return (-1); 693178825Sdfr } 694178825Sdfr errno = saved_errno; 695178825Sdfr break; 696178825Sdfr case 3: 697178825Sdfr strlcpy(snmp_client.user.sec_name, val, 698178825Sdfr SNMP_ADM_STR32_SIZ); 699178825Sdfr break; 700178825Sdfr default: 701178825Sdfr warnx("Unknown suboption - '%s'", suboptarg); 702178825Sdfr return (-1); 703178825Sdfr } 704178825Sdfr count += 1; 705178825Sdfr } 706178825Sdfr return (2/* count */); 707178825Sdfr} 708178825Sdfr 709178825Sdfrint32_t 710178825Sdfrparse_file(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 711178825Sdfr{ 712178825Sdfr assert(opt_arg != NULL); 713178825Sdfr 714178825Sdfr if (parse_flist(snmptoolctx, opt_arg, NULL, &IsoOrgDod_OID) < 0) 715178825Sdfr return (-1); 716178825Sdfr 717178825Sdfr return (2); 718178825Sdfr} 719178825Sdfr 720178825Sdfrint32_t 721178825Sdfrparse_include(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 722178825Sdfr{ 723178825Sdfr char path[MAXPATHLEN + 1]; 724178825Sdfr int32_t cut_dflt, len, subopt; 725178825Sdfr struct asn_oid cut; 726178825Sdfr char *val, *option; 727178825Sdfr const char *const subopts[] = { 728178825Sdfr "cut", 729178825Sdfr "path", 730178825Sdfr "file", 731178825Sdfr NULL 732178825Sdfr }; 733178825Sdfr 734178825Sdfr#define INC_CUT 0 735178825Sdfr#define INC_PATH 1 736178825Sdfr#define INC_LIST 2 737178825Sdfr 738178825Sdfr assert(opt_arg != NULL); 739178825Sdfr 740178825Sdfr /* if (opt == 'i') 741178825Sdfr free_filelist(snmptoolctx, ); */ 742178825Sdfr /* 743178825Sdfr * This function should be called only after getopt(3) - otherwise if 744178825Sdfr * no previous validation of opt_arg strlen() may not return what is 745178825Sdfr * expected. 746178825Sdfr */ 747178825Sdfr 748178825Sdfr path[0] = '\0'; 749178825Sdfr memset(&cut, 0, sizeof(struct asn_oid)); 750178825Sdfr cut_dflt = -1; 751178825Sdfr 752178825Sdfr while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) { 753178825Sdfr switch (subopt) { 754178825Sdfr case INC_CUT: 755178825Sdfr if (val == NULL) { 756178825Sdfr warnx("Suboption 'cut' requires an argument"); 757178825Sdfr return (-1); 758178825Sdfr } else { 759178825Sdfr if (snmp_parse_numoid(val, &cut) < 0) 760178825Sdfr return (-1); 761178825Sdfr } 762178825Sdfr cut_dflt = 1; 763178825Sdfr break; 764178825Sdfr 765178825Sdfr case INC_PATH: 766178825Sdfr if ((len = parse_path(val)) < 0) 767178825Sdfr return (-1); 768178825Sdfr strlcpy(path, val, len + 1); 769178825Sdfr break; 770178825Sdfr 771178825Sdfr case INC_LIST: 772178825Sdfr if (val == NULL) 773178825Sdfr return (-1); 774178825Sdfr if (cut_dflt == -1) 775178825Sdfr len = parse_flist(snmptoolctx, val, path, &IsoOrgDod_OID); 776178825Sdfr else 777178825Sdfr len = parse_flist(snmptoolctx, val, path, &cut); 778178825Sdfr if (len < 0) 779178825Sdfr return (-1); 780178825Sdfr break; 781178825Sdfr 782178825Sdfr default: 783178825Sdfr warnx("Unknown suboption - '%s'", suboptarg); 784178825Sdfr return (-1); 785178825Sdfr } 786178825Sdfr } 787178825Sdfr 788178825Sdfr /* XXX: Fix me - returning two is wrong here */ 789178825Sdfr return (2); 790178825Sdfr} 791178825Sdfr 792178825Sdfrint32_t 793233294Sstasparse_server(char *opt_arg) 794233294Sstas{ 795233294Sstas assert(opt_arg != NULL); 796178825Sdfr 797233294Sstas if (snmp_parse_server(&snmp_client, opt_arg) < 0) 798233294Sstas return (-1); 799233294Sstas 800178825Sdfr if (snmp_client.trans > SNMP_TRANS_UDP && snmp_client.chost == NULL) { 801233294Sstas if ((snmp_client.chost = malloc(strlen(SNMP_DEFAULT_LOCAL + 1))) 802233294Sstas == NULL) { 803178825Sdfr syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 804233294Sstas return (-1); 805233294Sstas } 806233294Sstas strcpy(snmp_client.chost, SNMP_DEFAULT_LOCAL); 807178825Sdfr } 808233294Sstas 809233294Sstas return (2); 810233294Sstas} 811178825Sdfr 812233294Sstasint32_t 813233294Sstasparse_timeout(char *opt_arg) 814233294Sstas{ 815233294Sstas int32_t v, saved_errno; 816233294Sstas 817233294Sstas assert(opt_arg != NULL); 818233294Sstas 819233294Sstas saved_errno = errno; 820233294Sstas errno = 0; 821233294Sstas 822233294Sstas v = strtol(opt_arg, NULL, 10); 823178825Sdfr if (errno != 0) { 824178825Sdfr warnx( "Error parsing timeout value - %s", strerror(errno)); 825233294Sstas errno = saved_errno; 826178825Sdfr return (-1); 827178825Sdfr } 828178825Sdfr 829178825Sdfr snmp_client.timeout.tv_sec = v; 830178825Sdfr errno = saved_errno; 831178825Sdfr return (2); 832178825Sdfr} 833178825Sdfr 834178825Sdfrint32_t 835178825Sdfrparse_retry(char *opt_arg) 836178825Sdfr{ 837178825Sdfr uint32_t v; 838178825Sdfr int32_t saved_errno; 839233294Sstas 840178825Sdfr assert(opt_arg != NULL); 841178825Sdfr 842178825Sdfr saved_errno = errno; 843178825Sdfr errno = 0; 844178825Sdfr 845178825Sdfr v = strtoul(opt_arg, NULL, 10); 846178825Sdfr if (errno != 0) { 847178825Sdfr warnx("Error parsing retries count - %s", strerror(errno)); 848178825Sdfr errno = saved_errno; 849178825Sdfr return (-1); 850233294Sstas } 851178825Sdfr 852178825Sdfr snmp_client.retries = v; 853178825Sdfr errno = saved_errno; 854178825Sdfr return (2); 855178825Sdfr} 856178825Sdfr 857178825Sdfrint32_t 858178825Sdfrparse_version(char *opt_arg) 859178825Sdfr{ 860178825Sdfr uint32_t v; 861178825Sdfr int32_t saved_errno; 862178825Sdfr 863178825Sdfr assert(opt_arg != NULL); 864178825Sdfr 865178825Sdfr saved_errno = errno; 866178825Sdfr errno = 0; 867178825Sdfr 868233294Sstas v = strtoul(opt_arg, NULL, 10); 869233294Sstas if (errno != 0) { 870233294Sstas warnx("Error parsing version - %s", strerror(errno)); 871233294Sstas errno = saved_errno; 872233294Sstas return (-1); 873233294Sstas } 874233294Sstas 875233294Sstas switch (v) { 876233294Sstas case 1: 877233294Sstas snmp_client.version = SNMP_V1; 878233294Sstas break; 879233294Sstas case 2: 880233294Sstas snmp_client.version = SNMP_V2c; 881233294Sstas break; 882233294Sstas case 3: 883233294Sstas snmp_client.version = SNMP_V3; 884233294Sstas break; 885233294Sstas default: 886233294Sstas warnx("Unsupported SNMP version - %u", v); 887233294Sstas errno = saved_errno; 888233294Sstas return (-1); 889233294Sstas } 890233294Sstas 891233294Sstas errno = saved_errno; 892233294Sstas return (2); 893233294Sstas} 894233294Sstas 895233294Sstasint32_t 896233294Sstasparse_local_path(char *opt_arg) 897178825Sdfr{ 898178825Sdfr assert(opt_arg != NULL); 899178825Sdfr 900178825Sdfr if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) { 901178825Sdfr warnx("Filename too long - %s", opt_arg); 902178825Sdfr return (-1); 903178825Sdfr } 904178825Sdfr 905178825Sdfr strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH)); 906178825Sdfr return (2); 907178825Sdfr} 908178825Sdfr 909178825Sdfrint32_t 910178825Sdfrparse_buflen(char *opt_arg) 911178825Sdfr{ 912178825Sdfr uint32_t size; 913178825Sdfr int32_t saved_errno; 914178825Sdfr 915178825Sdfr assert(opt_arg != NULL); 916178825Sdfr 917178825Sdfr saved_errno = errno; 918178825Sdfr errno = 0; 919178825Sdfr 920178825Sdfr size = strtoul(opt_arg, NULL, 10); 921178825Sdfr if (errno != 0) { 922178825Sdfr warnx("Error parsing buffer size - %s", strerror(errno)); 923178825Sdfr errno = saved_errno; 924178825Sdfr return (-1); 925178825Sdfr } 926178825Sdfr 927178825Sdfr if (size > MAX_BUFF_SIZE) { 928178825Sdfr warnx("Buffer size too big - %d max allowed", MAX_BUFF_SIZE); 929178825Sdfr errno = saved_errno; 930178825Sdfr return (-1); 931178825Sdfr } 932178825Sdfr 933178825Sdfr snmp_client.txbuflen = snmp_client.rxbuflen = size; 934178825Sdfr errno = saved_errno; 935178825Sdfr return (2); 936178825Sdfr} 937178825Sdfr 938178825Sdfrint32_t 939233294Sstasparse_debug(void) 940178825Sdfr{ 941178825Sdfr snmp_client.dump_pdus = 1; 942178825Sdfr return (1); 943178825Sdfr} 944178825Sdfr 945178825Sdfrint32_t 946178825Sdfrparse_discovery(struct snmp_toolinfo *snmptoolctx) 947178825Sdfr{ 948178825Sdfr SET_EDISCOVER(snmptoolctx); 949178825Sdfr snmp_client.version = SNMP_V3; 950233294Sstas return (1); 951178825Sdfr} 952178825Sdfr 953178825Sdfrint32_t 954178825Sdfrparse_local_key(struct snmp_toolinfo *snmptoolctx) 955178825Sdfr{ 956178825Sdfr SET_LOCALKEY(snmptoolctx); 957178825Sdfr snmp_client.version = SNMP_V3; 958178825Sdfr return (1); 959178825Sdfr} 960178825Sdfr 961178825Sdfrint32_t 962178825Sdfrparse_num_oids(struct snmp_toolinfo *snmptoolctx) 963178825Sdfr{ 964178825Sdfr SET_NUMERIC(snmptoolctx); 965178825Sdfr return (1); 966178825Sdfr} 967178825Sdfr 968178825Sdfrint32_t 969178825Sdfrparse_output(struct snmp_toolinfo *snmptoolctx, char *opt_arg) 970178825Sdfr{ 971178825Sdfr assert(opt_arg != NULL); 972178825Sdfr 973178825Sdfr if (strlen(opt_arg) > strlen("verbose")) { 974178825Sdfr warnx( "Invalid output option - %s",opt_arg); 975178825Sdfr return (-1); 976178825Sdfr } 977178825Sdfr 978178825Sdfr if (strncasecmp(opt_arg, "short", strlen(opt_arg)) == 0) 979178825Sdfr SET_OUTPUT(snmptoolctx, OUTPUT_SHORT); 980178825Sdfr else if (strncasecmp(opt_arg, "verbose", strlen(opt_arg)) == 0) 981178825Sdfr SET_OUTPUT(snmptoolctx, OUTPUT_VERBOSE); 982178825Sdfr else if (strncasecmp(opt_arg,"tabular", strlen(opt_arg)) == 0) 983178825Sdfr SET_OUTPUT(snmptoolctx, OUTPUT_TABULAR); 984178825Sdfr else if (strncasecmp(opt_arg, "quiet", strlen(opt_arg)) == 0) 985178825Sdfr SET_OUTPUT(snmptoolctx, OUTPUT_QUIET); 986178825Sdfr else { 987178825Sdfr warnx( "Invalid output option - %s", opt_arg); 988178825Sdfr return (-1); 989178825Sdfr } 990178825Sdfr 991178825Sdfr return (2); 992178825Sdfr} 993178825Sdfr 994178825Sdfrint32_t 995178825Sdfrparse_errors(struct snmp_toolinfo *snmptoolctx) 996178825Sdfr{ 997178825Sdfr SET_RETRY(snmptoolctx); 998178825Sdfr return (1); 999178825Sdfr} 1000178825Sdfr 1001178825Sdfrint32_t 1002178825Sdfrparse_skip_access(struct snmp_toolinfo *snmptoolctx) 1003178825Sdfr{ 1004178825Sdfr SET_ERRIGNORE(snmptoolctx); 1005178825Sdfr return (1); 1006178825Sdfr} 1007178825Sdfr 1008178825Sdfrchar * 1009178825Sdfrsnmp_parse_suboid(char *str, struct asn_oid *oid) 1010178825Sdfr{ 1011178825Sdfr char *endptr; 1012178825Sdfr asn_subid_t suboid; 1013178825Sdfr 1014178825Sdfr if (*str == '.') 1015178825Sdfr str++; 1016178825Sdfr 1017178825Sdfr if (*str < '0' || *str > '9') 1018178825Sdfr return (str); 1019178825Sdfr 1020178825Sdfr do { 1021178825Sdfr suboid = strtoul(str, &endptr, 10); 1022178825Sdfr if ((asn_subid_t) suboid > ASN_MAXID) { 1023178825Sdfr warnx("Suboid %u > ASN_MAXID", suboid); 1024178825Sdfr return (NULL); 1025178825Sdfr } 1026178825Sdfr if (snmp_suboid_append(oid, suboid) < 0) 1027178825Sdfr return (NULL); 1028178825Sdfr str = endptr + 1; 1029178825Sdfr } while (*endptr == '.'); 1030178825Sdfr 1031178825Sdfr return (endptr); 1032178825Sdfr} 1033178825Sdfr 1034233294Sstasstatic char * 1035178825Sdfrsnmp_int2asn_oid(char *str, struct asn_oid *oid) 1036178825Sdfr{ 1037178825Sdfr char *endptr; 1038178825Sdfr int32_t v, saved_errno; 1039178825Sdfr 1040178825Sdfr saved_errno = errno; 1041178825Sdfr errno = 0; 1042178825Sdfr 1043178825Sdfr v = strtol(str, &endptr, 10); 1044178825Sdfr if (errno != 0) { 1045178825Sdfr warnx("Integer value %s not supported - %s", str, 1046178825Sdfr strerror(errno)); 1047178825Sdfr errno = saved_errno; 1048178825Sdfr return (NULL); 1049178825Sdfr } 1050178825Sdfr errno = saved_errno; 1051178825Sdfr 1052178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1053178825Sdfr return (NULL); 1054178825Sdfr 1055178825Sdfr return (endptr); 1056178825Sdfr} 1057178825Sdfr 1058178825Sdfr/* It is a bit weird to have a table indexed by OID but still... */ 1059178825Sdfrstatic char * 1060178825Sdfrsnmp_oid2asn_oid(struct snmp_toolinfo *snmptoolctx, char *str, 1061178825Sdfr struct asn_oid *oid) 1062178825Sdfr{ 1063178825Sdfr int32_t i; 1064178825Sdfr char string[MAXSTR], *endptr; 1065178825Sdfr struct snmp_object obj; 1066178825Sdfr 1067178825Sdfr for (i = 0; i < MAXSTR; i++) 1068178825Sdfr if (isalpha (*(str + i)) == 0) 1069178825Sdfr break; 1070178825Sdfr 1071178825Sdfr endptr = str + i; 1072178825Sdfr memset(&obj, 0, sizeof(struct snmp_object)); 1073178825Sdfr if (i == 0) { 1074178825Sdfr if ((endptr = snmp_parse_suboid(str, &(obj.val.var))) == NULL) 1075178825Sdfr return (NULL); 1076178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) obj.val.var.len) < 0) 1077178825Sdfr return (NULL); 1078178825Sdfr } else { 1079178825Sdfr strlcpy(string, str, i + 1); 1080178825Sdfr string[i] = '\0'; 1081178825Sdfr if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) { 1082178825Sdfr warnx("Unknown string - %s",string); 1083178825Sdfr return (NULL); 1084178825Sdfr } 1085178825Sdfr free(string); 1086178825Sdfr } 1087178825Sdfr 1088178825Sdfr asn_append_oid(oid, &(obj.val.var)); 1089178825Sdfr return (endptr); 1090178825Sdfr} 1091178825Sdfr 1092178825Sdfrstatic char * 1093178825Sdfrsnmp_ip2asn_oid(char *str, struct asn_oid *oid) 1094178825Sdfr{ 1095178825Sdfr uint32_t v; 1096178825Sdfr int32_t i; 1097178825Sdfr char *endptr, *ptr; 1098178825Sdfr 1099178825Sdfr ptr = str; 1100178825Sdfr for (i = 0; i < 4; i++) { 1101178825Sdfr v = strtoul(ptr, &endptr, 10); 1102178825Sdfr if (v > 0xff) 1103178825Sdfr return (NULL); 1104178825Sdfr if (*endptr != '.' && strchr("],\0", *endptr) == NULL && i != 3) 1105178825Sdfr return (NULL); 1106178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1107178825Sdfr return (NULL); 1108178825Sdfr ptr = endptr + 1; 1109178825Sdfr } 1110178825Sdfr 1111178825Sdfr return (endptr); 1112178825Sdfr} 1113178825Sdfr 1114178825Sdfr/* 32-bit counter, gauge, timeticks. */ 1115178825Sdfrstatic char * 1116178825Sdfrsnmp_uint2asn_oid(char *str, struct asn_oid *oid) 1117178825Sdfr{ 1118178825Sdfr char *endptr; 1119178825Sdfr uint32_t v; 1120178825Sdfr int32_t saved_errno; 1121178825Sdfr 1122178825Sdfr saved_errno = errno; 1123178825Sdfr errno = 0; 1124178825Sdfr 1125178825Sdfr v = strtoul(str, &endptr, 10); 1126178825Sdfr if (errno != 0) { 1127178825Sdfr warnx("Integer value %s not supported - %s\n", str, 1128178825Sdfr strerror(errno)); 1129178825Sdfr errno = saved_errno; 1130178825Sdfr return (NULL); 1131178825Sdfr } 1132178825Sdfr errno = saved_errno; 1133178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1134178825Sdfr return (NULL); 1135178825Sdfr 1136178825Sdfr return (endptr); 1137178825Sdfr} 1138178825Sdfr 1139178825Sdfrstatic char * 1140178825Sdfrsnmp_cnt64_2asn_oid(char *str, struct asn_oid *oid) 1141178825Sdfr{ 1142178825Sdfr char *endptr; 1143178825Sdfr uint64_t v; 1144178825Sdfr int32_t saved_errno; 1145178825Sdfr 1146178825Sdfr saved_errno = errno; 1147178825Sdfr errno = 0; 1148178825Sdfr 1149178825Sdfr v = strtoull(str, &endptr, 10); 1150178825Sdfr 1151178825Sdfr if (errno != 0) { 1152178825Sdfr warnx("Integer value %s not supported - %s", str, 1153178825Sdfr strerror(errno)); 1154178825Sdfr errno = saved_errno; 1155178825Sdfr return (NULL); 1156178825Sdfr } 1157178825Sdfr errno = saved_errno; 1158178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xffffffff)) < 0) 1159178825Sdfr return (NULL); 1160178825Sdfr 1161178825Sdfr if (snmp_suboid_append(oid, (asn_subid_t) (v >> 32)) < 0) 1162178825Sdfr return (NULL); 1163178825Sdfr 1164178825Sdfr return (endptr); 1165178825Sdfr} 1166178825Sdfr 1167178825Sdfrenum snmp_syntax 1168178825Sdfrparse_syntax(char *str) 1169178825Sdfr{ 1170178825Sdfr int32_t i; 1171178825Sdfr 1172178825Sdfr for (i = 0; i < SNMP_SYNTAX_UNKNOWN; i++) { 1173178825Sdfr if (strncmp(syntax_strings[i].str, str, 1174178825Sdfr strlen(syntax_strings[i].str)) == 0) 1175178825Sdfr return (syntax_strings[i].stx); 1176178825Sdfr } 1177178825Sdfr 1178178825Sdfr return (SNMP_SYNTAX_NULL); 1179178825Sdfr} 1180178825Sdfr 1181178825Sdfrstatic char * 1182178825Sdfrsnmp_parse_subindex(struct snmp_toolinfo *snmptoolctx, char *str, 1183178825Sdfr struct index *idx, struct snmp_object *object) 1184178825Sdfr{ 1185178825Sdfr char *ptr; 1186178825Sdfr int32_t i; 1187178825Sdfr enum snmp_syntax stx; 1188178825Sdfr char syntax[MAX_CMD_SYNTAX_LEN]; 1189178825Sdfr 1190178825Sdfr ptr = str; 1191178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) { 1192178825Sdfr for (i = 0; i < MAX_CMD_SYNTAX_LEN ; i++) { 1193178825Sdfr if (*(ptr + i) == ':') 1194178825Sdfr break; 1195178825Sdfr } 1196178825Sdfr 1197178825Sdfr if (i >= MAX_CMD_SYNTAX_LEN) { 1198178825Sdfr warnx("Unknown syntax in OID - %s", str); 1199178825Sdfr return (NULL); 1200178825Sdfr } 1201178825Sdfr /* Expect a syntax string here. */ 1202178825Sdfr if ((stx = parse_syntax(str)) <= SNMP_SYNTAX_NULL) { 1203178825Sdfr warnx("Invalid syntax - %s",syntax); 1204178825Sdfr return (NULL); 1205178825Sdfr } 1206178825Sdfr 1207178825Sdfr if (stx != idx->syntax && !ISSET_ERRIGNORE(snmptoolctx)) { 1208178825Sdfr warnx("Syntax mismatch - %d expected, %d given", 1209178825Sdfr idx->syntax, stx); 1210178825Sdfr return (NULL); 1211178825Sdfr } 1212178825Sdfr /* 1213178825Sdfr * That is where the suboid started + the syntax length + one 1214178825Sdfr * character for ':'. 1215178825Sdfr */ 1216178825Sdfr ptr = str + i + 1; 1217178825Sdfr } else 1218178825Sdfr stx = idx->syntax; 1219178825Sdfr 1220178825Sdfr switch (stx) { 1221178825Sdfr case SNMP_SYNTAX_INTEGER: 1222178825Sdfr return (snmp_int2asn_oid(ptr, &(object->val.var))); 1223178825Sdfr case SNMP_SYNTAX_OID: 1224178825Sdfr return (snmp_oid2asn_oid(snmptoolctx, ptr, 1225178825Sdfr &(object->val.var))); 1226178825Sdfr case SNMP_SYNTAX_IPADDRESS: 1227178825Sdfr return (snmp_ip2asn_oid(ptr, &(object->val.var))); 1228178825Sdfr case SNMP_SYNTAX_COUNTER: 1229178825Sdfr /* FALLTHROUGH */ 1230178825Sdfr case SNMP_SYNTAX_GAUGE: 1231178825Sdfr /* FALLTHROUGH */ 1232178825Sdfr case SNMP_SYNTAX_TIMETICKS: 1233178825Sdfr return (snmp_uint2asn_oid(ptr, &(object->val.var))); 1234178825Sdfr case SNMP_SYNTAX_COUNTER64: 1235178825Sdfr return (snmp_cnt64_2asn_oid(ptr, &(object->val.var))); 1236178825Sdfr case SNMP_SYNTAX_OCTETSTRING: 1237178825Sdfr return (snmp_tc2oid(idx->tc, ptr, &(object->val.var))); 1238178825Sdfr default: 1239178825Sdfr /* NOTREACHED */ 1240178825Sdfr break; 1241178825Sdfr } 1242178825Sdfr 1243178825Sdfr return (NULL); 1244178825Sdfr} 1245178825Sdfr 1246178825Sdfrchar * 1247178825Sdfrsnmp_parse_index(struct snmp_toolinfo *snmptoolctx, char *str, 1248178825Sdfr struct snmp_object *object) 1249178825Sdfr{ 1250178825Sdfr char *ptr; 1251178825Sdfr struct index *temp; 1252178825Sdfr 1253178825Sdfr if (object->info->table_idx == NULL) 1254178825Sdfr return (NULL); 1255178825Sdfr 1256178825Sdfr ptr = NULL; 1257178825Sdfr STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(object)), link) { 1258178825Sdfr if ((ptr = snmp_parse_subindex(snmptoolctx, str, temp, object)) 1259178825Sdfr == NULL) 1260178825Sdfr return (NULL); 1261178825Sdfr 1262178825Sdfr if (*ptr != ',' && *ptr != ']') 1263178825Sdfr return (NULL); 1264178825Sdfr str = ptr + 1; 1265178825Sdfr } 1266178825Sdfr 1267178825Sdfr if (ptr == NULL || *ptr != ']') { 1268178825Sdfr warnx("Mismatching index - %s", str); 1269178825Sdfr return (NULL); 1270178825Sdfr } 1271178825Sdfr 1272178825Sdfr return (ptr + 1); 1273178825Sdfr} 1274178825Sdfr 1275178825Sdfr/* 1276178825Sdfr * Fill in the struct asn_oid member of snmp_value with suboids from input. 1277178825Sdfr * If an error occurs - print message on stderr and return (-1). 1278178825Sdfr * If all is ok - return the length of the oid. 1279178825Sdfr */ 1280178825Sdfrint32_t 1281178825Sdfrsnmp_parse_numoid(char *argv, struct asn_oid *var) 1282178825Sdfr{ 1283178825Sdfr char *endptr, *str; 1284178825Sdfr asn_subid_t suboid; 1285178825Sdfr 1286178825Sdfr str = argv; 1287178825Sdfr 1288178825Sdfr if (*str == '.') 1289178825Sdfr str++; 1290178825Sdfr 1291178825Sdfr do { 1292178825Sdfr if (var->len == ASN_MAXOIDLEN) { 1293178825Sdfr warnx("Oid too long - %u", var->len); 1294178825Sdfr return (-1); 1295178825Sdfr } 1296178825Sdfr 1297178825Sdfr suboid = strtoul(str, &endptr, 10); 1298178825Sdfr if (suboid > ASN_MAXID) { 1299178825Sdfr warnx("Oid too long - %u", var->len); 1300178825Sdfr return (-1); 1301178825Sdfr } 1302178825Sdfr 1303178825Sdfr var->subs[var->len++] = suboid; 1304178825Sdfr str = endptr + 1; 1305178825Sdfr } while ( *endptr == '.'); 1306178825Sdfr 1307178825Sdfr if (*endptr != '\0') { 1308178825Sdfr warnx("Invalid oid string - %s", argv); 1309178825Sdfr return (-1); 1310178825Sdfr } 1311178825Sdfr 1312178825Sdfr return (var->len); 1313178825Sdfr} 1314178825Sdfr 1315178825Sdfr/* Append a length 1 suboid to an asn_oid structure. */ 1316178825Sdfrint32_t 1317178825Sdfrsnmp_suboid_append(struct asn_oid *var, asn_subid_t suboid) 1318178825Sdfr{ 1319178825Sdfr if (var == NULL) 1320178825Sdfr return (-1); 1321178825Sdfr 1322178825Sdfr if (var->len >= ASN_MAXOIDLEN) { 1323178825Sdfr warnx("Oid too long - %u", var->len); 1324178825Sdfr return (-1); 1325178825Sdfr } 1326178825Sdfr 1327178825Sdfr var->subs[var->len++] = suboid; 1328178825Sdfr 1329178825Sdfr return (1); 1330178825Sdfr} 1331178825Sdfr 1332178825Sdfr/* Pop the last suboid from an asn_oid structure. */ 1333178825Sdfrint32_t 1334178825Sdfrsnmp_suboid_pop(struct asn_oid *var) 1335178825Sdfr{ 1336178825Sdfr asn_subid_t suboid; 1337178825Sdfr 1338178825Sdfr if (var == NULL) 1339178825Sdfr return (-1); 1340178825Sdfr 1341178825Sdfr if (var->len < 1) 1342178825Sdfr return (-1); 1343178825Sdfr 1344178825Sdfr suboid = var->subs[--(var->len)]; 1345178825Sdfr var->subs[var->len] = 0; 1346178825Sdfr 1347178825Sdfr return (suboid); 1348178825Sdfr} 1349178825Sdfr 1350178825Sdfr/* 1351178825Sdfr * Parse the command-line provided string into an OID - alocate memory for a new 1352178825Sdfr * snmp object, fill in its fields and insert it in the object list. A 1353178825Sdfr * (snmp_verify_inoid_f) function must be provided to validate the input string. 1354178825Sdfr */ 1355178825Sdfrint32_t 1356178825Sdfrsnmp_object_add(struct snmp_toolinfo *snmptoolctx, snmp_verify_inoid_f func, 1357178825Sdfr char *string) 1358178825Sdfr{ 1359178825Sdfr struct snmp_object *obj; 1360178825Sdfr 1361178825Sdfr if (snmptoolctx == NULL) 1362178825Sdfr return (-1); 1363178825Sdfr 1364178825Sdfr /* XXX-BZ does that chack make sense? */ 1365178825Sdfr if (snmptoolctx->objects >= SNMP_MAX_BINDINGS) { 1366178825Sdfr warnx("Too many bindings in PDU - %u", snmptoolctx->objects + 1); 1367178825Sdfr return (-1); 1368178825Sdfr } 1369178825Sdfr 1370178825Sdfr if ((obj = malloc(sizeof(struct snmp_object))) == NULL) { 1371178825Sdfr syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 1372178825Sdfr return (-1); 1373178825Sdfr } 1374178825Sdfr 1375178825Sdfr memset(obj, 0, sizeof(struct snmp_object)); 1376178825Sdfr if (func(snmptoolctx, obj, string) < 0) { 1377178825Sdfr warnx("Invalid OID - %s", string); 1378178825Sdfr free(obj); 1379178825Sdfr return (-1); 1380178825Sdfr } 1381178825Sdfr 1382178825Sdfr snmptoolctx->objects++; 1383178825Sdfr SLIST_INSERT_HEAD(&snmptoolctx->snmp_objectlist, obj, link); 1384178825Sdfr 1385178825Sdfr return (1); 1386178825Sdfr} 1387178825Sdfr 1388178825Sdfr/* Given an OID, find it in the object list and remove it. */ 1389178825Sdfrint32_t 1390178825Sdfrsnmp_object_remove(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid) 1391178825Sdfr{ 1392178825Sdfr struct snmp_object *temp; 1393178825Sdfr 1394178825Sdfr if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) { 1395178825Sdfr warnx("Object list already empty"); 1396178825Sdfr return (-1); 1397178825Sdfr } 1398178825Sdfr 1399178825Sdfr 1400178825Sdfr SLIST_FOREACH(temp, &snmptoolctx->snmp_objectlist, link) 1401178825Sdfr if (asn_compare_oid(&(temp->val.var), oid) == 0) 1402178825Sdfr break; 1403178825Sdfr 1404178825Sdfr if (temp == NULL) { 1405178825Sdfr warnx("No such object in list"); 1406178825Sdfr return (-1); 1407178825Sdfr } 1408178825Sdfr 1409178825Sdfr SLIST_REMOVE(&snmptoolctx->snmp_objectlist, temp, snmp_object, link); 1410178825Sdfr if (temp->val.syntax == SNMP_SYNTAX_OCTETSTRING && 1411178825Sdfr temp->val.v.octetstring.octets != NULL) 1412178825Sdfr free(temp->val.v.octetstring.octets); 1413178825Sdfr free(temp); 1414178825Sdfr 1415178825Sdfr return (1); 1416178825Sdfr} 1417178825Sdfr 1418178825Sdfrstatic void 1419178825Sdfrsnmp_object_freeall(struct snmp_toolinfo *snmptoolctx) 1420178825Sdfr{ 1421178825Sdfr struct snmp_object *o; 1422178825Sdfr 1423178825Sdfr while ((o = SLIST_FIRST(&snmptoolctx->snmp_objectlist)) != NULL) { 1424178825Sdfr SLIST_REMOVE_HEAD(&snmptoolctx->snmp_objectlist, link); 1425178825Sdfr 1426178825Sdfr if (o->val.syntax == SNMP_SYNTAX_OCTETSTRING && 1427178825Sdfr o->val.v.octetstring.octets != NULL) 1428178825Sdfr free(o->val.v.octetstring.octets); 1429178825Sdfr free(o); 1430178825Sdfr } 1431178825Sdfr} 1432178825Sdfr 1433178825Sdfr/* Do all possible memory release before exit. */ 1434178825Sdfrvoid 1435178825Sdfrsnmp_tool_freeall(struct snmp_toolinfo *snmptoolctx) 1436178825Sdfr{ 1437178825Sdfr if (snmp_client.chost != NULL) { 1438178825Sdfr free(snmp_client.chost); 1439178825Sdfr snmp_client.chost = NULL; 1440178825Sdfr } 1441178825Sdfr 1442178825Sdfr if (snmp_client.cport != NULL) { 1443178825Sdfr free(snmp_client.cport); 1444178825Sdfr snmp_client.cport = NULL; 1445178825Sdfr } 1446178825Sdfr 1447178825Sdfr snmp_mapping_free(snmptoolctx); 1448178825Sdfr free_filelist(snmptoolctx); 1449178825Sdfr snmp_object_freeall(snmptoolctx); 1450178825Sdfr 1451178825Sdfr if (snmptoolctx->passwd != NULL) { 1452178825Sdfr free(snmptoolctx->passwd); 1453178825Sdfr snmptoolctx->passwd = NULL; 1454178825Sdfr } 1455178825Sdfr} 1456178825Sdfr 1457178825Sdfr/* 1458178825Sdfr * Fill all variables from the object list into a PDU. (snmp_verify_vbind_f) 1459178825Sdfr * function should check whether the variable is consistent in this PDU 1460178825Sdfr * (e.g do not add non-leaf OIDs to a GET PDU, or OIDs with read access only to 1461178825Sdfr * a SET PDU) - might be NULL though. (snmp_add_vbind_f) function is the 1462178825Sdfr * function actually adds the variable to the PDU and must not be NULL. 1463178825Sdfr */ 1464178825Sdfrint32_t 1465178825Sdfrsnmp_pdu_add_bindings(struct snmp_toolinfo *snmptoolctx, 1466178825Sdfr snmp_verify_vbind_f vfunc, snmp_add_vbind_f afunc, 1467178825Sdfr struct snmp_pdu *pdu, int32_t maxcount) 1468178825Sdfr{ 1469178825Sdfr int32_t nbindings, abind; 1470178825Sdfr struct snmp_object *obj; 1471178825Sdfr 1472178825Sdfr if (pdu == NULL || afunc == NULL) 1473178825Sdfr return (-1); 1474178825Sdfr 1475178825Sdfr /* Return 0 in case of no more work todo. */ 1476178825Sdfr if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) 1477178825Sdfr return (0); 1478178825Sdfr 1479178825Sdfr if (maxcount < 0 || maxcount > SNMP_MAX_BINDINGS) { 1480178825Sdfr warnx("maxcount out of range: <0 || >SNMP_MAX_BINDINGS"); 1481178825Sdfr return (-1); 1482178825Sdfr } 1483178825Sdfr 1484178825Sdfr nbindings = 0; 1485178825Sdfr SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) { 1486178825Sdfr if ((vfunc != NULL) && (vfunc(snmptoolctx, pdu, obj) < 0)) { 1487178825Sdfr nbindings = -1; 1488178825Sdfr break; 1489178825Sdfr } 1490178825Sdfr if ((abind = afunc(pdu, obj)) < 0) { 1491178825Sdfr nbindings = -1; 1492178825Sdfr break; 1493178825Sdfr } 1494178825Sdfr 1495178825Sdfr if (abind > 0) { 1496178825Sdfr /* Do not put more varbindings than requested. */ 1497178825Sdfr if (++nbindings >= maxcount) 1498178825Sdfr break; 1499178825Sdfr } 1500178825Sdfr } 1501178825Sdfr 1502178825Sdfr return (nbindings); 1503178825Sdfr} 1504178825Sdfr 1505178825Sdfr/* 1506178825Sdfr * Locate an object in the object list and set a corresponding error status. 1507178825Sdfr */ 1508178825Sdfrint32_t 1509178825Sdfrsnmp_object_seterror(struct snmp_toolinfo *snmptoolctx, 1510178825Sdfr struct snmp_value *err_value, int32_t error_status) 1511178825Sdfr{ 1512178825Sdfr struct snmp_object *obj; 1513178825Sdfr 1514178825Sdfr if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist) || err_value == NULL) 1515178825Sdfr return (-1); 1516178825Sdfr 1517178825Sdfr SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) 1518178825Sdfr if (asn_compare_oid(&(err_value->var), &(obj->val.var)) == 0) { 1519178825Sdfr obj->error = error_status; 1520178825Sdfr return (1); 1521178825Sdfr } 1522178825Sdfr 1523178825Sdfr return (0); 1524178825Sdfr} 1525178825Sdfr 1526178825Sdfr/* 1527178825Sdfr * Check a PDU received in response to a SNMP_PDU_GET/SNMP_PDU_GETBULK request 1528178825Sdfr * but don't compare syntaxes - when sending a request PDU they must be null. 1529178825Sdfr * This is a (almost) complete copy of snmp_pdu_check() - with matching syntaxes 1530178825Sdfr * checks and some other checks skipped. 1531178825Sdfr */ 1532178825Sdfrint32_t 1533178825Sdfrsnmp_parse_get_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1534178825Sdfr{ 1535178825Sdfr uint32_t i; 1536178825Sdfr 1537178825Sdfr for (i = 0; i < req->nbindings; i++) { 1538178825Sdfr if (asn_compare_oid(&req->bindings[i].var, 1539178825Sdfr &resp->bindings[i].var) != 0) { 1540233294Sstas warnx("Bad OID in response"); 1541178825Sdfr return (-1); 1542178825Sdfr } 1543178825Sdfr 1544178825Sdfr if (snmp_client.version != SNMP_V1 && (resp->bindings[i].syntax 1545178825Sdfr == SNMP_SYNTAX_NOSUCHOBJECT || resp->bindings[i].syntax == 1546178825Sdfr SNMP_SYNTAX_NOSUCHINSTANCE)) 1547178825Sdfr return (0); 1548178825Sdfr } 1549178825Sdfr 1550178825Sdfr return (1); 1551178825Sdfr} 1552178825Sdfr 1553178825Sdfrint32_t 1554178825Sdfrsnmp_parse_getbulk_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1555178825Sdfr{ 1556178825Sdfr int32_t N, R, M, r; 1557178825Sdfr 1558178825Sdfr if (req->error_status > (int32_t) resp->nbindings) { 1559178825Sdfr warnx("Bad number of bindings in response"); 1560178825Sdfr return (-1); 1561178825Sdfr } 1562178825Sdfr 1563233294Sstas for (N = 0; N < req->error_status; N++) { 1564178825Sdfr if (asn_is_suboid(&req->bindings[N].var, 1565178825Sdfr &resp->bindings[N].var) == 0) 1566178825Sdfr return (0); 1567178825Sdfr if (resp->bindings[N].syntax == SNMP_SYNTAX_ENDOFMIBVIEW) 1568178825Sdfr return (0); 1569178825Sdfr } 1570178825Sdfr 1571178825Sdfr for (R = N , r = N; R < (int32_t) req->nbindings; R++) { 1572178825Sdfr for (M = 0; M < req->error_index && (r + M) < 1573178825Sdfr (int32_t) resp->nbindings; M++) { 1574178825Sdfr if (asn_is_suboid(&req->bindings[R].var, 1575178825Sdfr &resp->bindings[r + M].var) == 0) 1576178825Sdfr return (0); 1577178825Sdfr 1578178825Sdfr if (resp->bindings[r + M].syntax == 1579178825Sdfr SNMP_SYNTAX_ENDOFMIBVIEW) { 1580178825Sdfr M++; 1581178825Sdfr break; 1582178825Sdfr } 1583178825Sdfr } 1584178825Sdfr r += M; 1585178825Sdfr } 1586178825Sdfr 1587178825Sdfr return (0); 1588178825Sdfr} 1589178825Sdfr 1590233294Sstasint32_t 1591178825Sdfrsnmp_parse_getnext_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1592178825Sdfr{ 1593178825Sdfr uint32_t i; 1594178825Sdfr 1595178825Sdfr for (i = 0; i < req->nbindings; i++) { 1596178825Sdfr if (asn_is_suboid(&req->bindings[i].var, &resp->bindings[i].var) 1597178825Sdfr == 0) 1598178825Sdfr return (0); 1599178825Sdfr 1600178825Sdfr if (resp->version != SNMP_V1 && resp->bindings[i].syntax == 1601178825Sdfr SNMP_SYNTAX_ENDOFMIBVIEW) 1602178825Sdfr return (0); 1603178825Sdfr } 1604178825Sdfr 1605178825Sdfr return (1); 1606178825Sdfr} 1607233294Sstas 1608178825Sdfr/* 1609178825Sdfr * Should be called to check a response to get/getnext/getbulk. 1610178825Sdfr */ 1611178825Sdfrint32_t 1612178825Sdfrsnmp_parse_resp(struct snmp_pdu *resp, struct snmp_pdu *req) 1613178825Sdfr{ 1614233294Sstas if (resp == NULL || req == NULL) 1615178825Sdfr return (-2); 1616178825Sdfr 1617178825Sdfr if (resp->version != req->version) { 1618178825Sdfr warnx("Response has wrong version"); 1619178825Sdfr return (-1); 1620178825Sdfr } 1621178825Sdfr 1622233294Sstas if (resp->error_status == SNMP_ERR_NOSUCHNAME) { 1623178825Sdfr warnx("Error - No Such Name"); 1624178825Sdfr return (0); 1625178825Sdfr } 1626178825Sdfr 1627178825Sdfr if (resp->error_status != SNMP_ERR_NOERROR) { 1628178825Sdfr warnx("Error %d in response", resp->error_status); 1629178825Sdfr return (-1); 1630178825Sdfr } 1631178825Sdfr 1632178825Sdfr if (resp->nbindings != req->nbindings && req->type != SNMP_PDU_GETBULK){ 1633178825Sdfr warnx("Bad number of bindings in response"); 1634178825Sdfr return (-1); 1635178825Sdfr } 1636178825Sdfr 1637178825Sdfr switch (req->type) { 1638178825Sdfr case SNMP_PDU_GET: 1639178825Sdfr return (snmp_parse_get_resp(resp,req)); 1640178825Sdfr case SNMP_PDU_GETBULK: 1641178825Sdfr return (snmp_parse_getbulk_resp(resp,req)); 1642178825Sdfr case SNMP_PDU_GETNEXT: 1643178825Sdfr return (snmp_parse_getnext_resp(resp,req)); 1644178825Sdfr default: 1645178825Sdfr /* NOTREACHED */ 1646178825Sdfr break; 1647178825Sdfr } 1648178825Sdfr 1649233294Sstas return (-2); 1650178825Sdfr} 1651178825Sdfr 1652178825Sdfrstatic void 1653178825Sdfrsnmp_output_octetstring(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc, 1654178825Sdfr uint32_t len, uint8_t *octets) 1655178825Sdfr{ 1656178825Sdfr char *buf; 1657178825Sdfr 1658233294Sstas if (len == 0 || octets == NULL) 1659233294Sstas return; 1660178825Sdfr 1661178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1662178825Sdfr fprintf(stdout, "%s : ", 1663178825Sdfr syntax_strings[SNMP_SYNTAX_OCTETSTRING].str); 1664178825Sdfr 1665178825Sdfr if ((buf = snmp_oct2tc(tc, len, (char *) octets)) != NULL) { 1666178825Sdfr fprintf(stdout, "%s", buf); 1667178825Sdfr free(buf); 1668178825Sdfr } 1669178825Sdfr} 1670178825Sdfr 1671178825Sdfrstatic void 1672178825Sdfrsnmp_output_octetindex(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc, 1673178825Sdfr struct asn_oid *oid) 1674178825Sdfr{ 1675178825Sdfr uint32_t i; 1676178825Sdfr uint8_t *s; 1677178825Sdfr 1678178825Sdfr if ((s = malloc(oid->subs[0] + 1)) == NULL) 1679178825Sdfr syslog(LOG_ERR, "malloc failed - %s", strerror(errno)); 1680178825Sdfr else { 1681178825Sdfr for (i = 0; i < oid->subs[0]; i++) 1682178825Sdfr s[i] = (u_char) (oid->subs[i + 1]); 1683178825Sdfr 1684178825Sdfr snmp_output_octetstring(snmptoolctx, tc, oid->subs[0], s); 1685178825Sdfr free(s); 1686178825Sdfr } 1687178825Sdfr} 1688178825Sdfr 1689178825Sdfr/* 1690178825Sdfr * Check and output syntax type and value. 1691178825Sdfr */ 1692178825Sdfrstatic void 1693178825Sdfrsnmp_output_oid_value(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid) 1694178825Sdfr{ 1695178825Sdfr char oid_string[ASN_OIDSTRLEN]; 1696233294Sstas struct snmp_object obj; 1697178825Sdfr 1698178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1699178825Sdfr fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_OID].str); 1700178825Sdfr 1701178825Sdfr if(!ISSET_NUMERIC(snmptoolctx)) { 1702178825Sdfr memset(&obj, 0, sizeof(struct snmp_object)); 1703233294Sstas asn_append_oid(&(obj.val.var), oid); 1704178825Sdfr 1705178825Sdfr if (snmp_lookup_enumstring(snmptoolctx, &obj) > 0) 1706178825Sdfr fprintf(stdout, "%s" , obj.info->string); 1707178825Sdfr else if (snmp_lookup_oidstring(snmptoolctx, &obj) > 0) 1708178825Sdfr fprintf(stdout, "%s" , obj.info->string); 1709178825Sdfr else if (snmp_lookup_nodestring(snmptoolctx, &obj) > 0) 1710178825Sdfr fprintf(stdout, "%s" , obj.info->string); 1711178825Sdfr else { 1712178825Sdfr (void) asn_oid2str_r(oid, oid_string); 1713178825Sdfr fprintf(stdout, "%s", oid_string); 1714178825Sdfr } 1715178825Sdfr } else { 1716178825Sdfr (void) asn_oid2str_r(oid, oid_string); 1717178825Sdfr fprintf(stdout, "%s", oid_string); 1718178825Sdfr } 1719178825Sdfr} 1720178825Sdfr 1721178825Sdfrstatic void 1722178825Sdfrsnmp_output_int(struct snmp_toolinfo *snmptoolctx, struct enum_pairs *enums, 1723178825Sdfr int32_t int_val) 1724178825Sdfr{ 1725178825Sdfr char *string; 1726178825Sdfr 1727178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1728178825Sdfr fprintf(stdout, "%s : ", 1729178825Sdfr syntax_strings[SNMP_SYNTAX_INTEGER].str); 1730178825Sdfr 1731178825Sdfr if (enums != NULL && (string = enum_string_lookup(enums, int_val)) 1732178825Sdfr != NULL) 1733178825Sdfr fprintf(stdout, "%s", string); 1734178825Sdfr else 1735178825Sdfr fprintf(stdout, "%d", int_val); 1736178825Sdfr} 1737178825Sdfr 1738178825Sdfrstatic void 1739178825Sdfrsnmp_output_ipaddress(struct snmp_toolinfo *snmptoolctx, uint8_t *ip) 1740178825Sdfr{ 1741178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1742178825Sdfr fprintf(stdout, "%s : ", 1743178825Sdfr syntax_strings[SNMP_SYNTAX_IPADDRESS].str); 1744178825Sdfr 1745178825Sdfr fprintf(stdout, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); 1746178825Sdfr} 1747178825Sdfr 1748178825Sdfrstatic void 1749178825Sdfrsnmp_output_counter(struct snmp_toolinfo *snmptoolctx, uint32_t counter) 1750178825Sdfr{ 1751178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1752178825Sdfr fprintf(stdout, "%s : ", 1753178825Sdfr syntax_strings[SNMP_SYNTAX_COUNTER].str); 1754178825Sdfr 1755178825Sdfr fprintf(stdout, "%u", counter); 1756178825Sdfr} 1757178825Sdfr 1758178825Sdfrstatic void 1759178825Sdfrsnmp_output_gauge(struct snmp_toolinfo *snmptoolctx, uint32_t gauge) 1760178825Sdfr{ 1761178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1762178825Sdfr fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_GAUGE].str); 1763178825Sdfr 1764178825Sdfr fprintf(stdout, "%u", gauge); 1765178825Sdfr} 1766178825Sdfr 1767178825Sdfrstatic void 1768178825Sdfrsnmp_output_ticks(struct snmp_toolinfo *snmptoolctx, uint32_t ticks) 1769178825Sdfr{ 1770178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1771178825Sdfr fprintf(stdout, "%s : ", 1772178825Sdfr syntax_strings[SNMP_SYNTAX_TIMETICKS].str); 1773178825Sdfr 1774178825Sdfr fprintf(stdout, "%u", ticks); 1775178825Sdfr} 1776178825Sdfr 1777178825Sdfrstatic void 1778178825Sdfrsnmp_output_counter64(struct snmp_toolinfo *snmptoolctx, uint64_t counter64) 1779178825Sdfr{ 1780178825Sdfr if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) 1781178825Sdfr fprintf(stdout, "%s : ", 1782178825Sdfr syntax_strings[SNMP_SYNTAX_COUNTER64].str); 1783178825Sdfr 1784178825Sdfr fprintf(stdout,"%ju", counter64); 1785178825Sdfr} 1786178825Sdfr 1787178825Sdfrint32_t 1788178825Sdfrsnmp_output_numval(struct snmp_toolinfo *snmptoolctx, struct snmp_value *val, 1789178825Sdfr struct snmp_oid2str *entry) 1790178825Sdfr{ 1791178825Sdfr if (val == NULL) 1792178825Sdfr return (-1); 1793178825Sdfr 1794178825Sdfr if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) 1795178825Sdfr fprintf(stdout, " = "); 1796178825Sdfr 1797178825Sdfr switch (val->syntax) { 1798178825Sdfr case SNMP_SYNTAX_INTEGER: 1799178825Sdfr if (entry != NULL) 1800178825Sdfr snmp_output_int(snmptoolctx, entry->snmp_enum, 1801178825Sdfr val->v.integer); 1802178825Sdfr else 1803178825Sdfr snmp_output_int(snmptoolctx, NULL, val->v.integer); 1804178825Sdfr break; 1805178825Sdfr 1806178825Sdfr case SNMP_SYNTAX_OCTETSTRING: 1807178825Sdfr if (entry != NULL) 1808178825Sdfr snmp_output_octetstring(snmptoolctx, entry->tc, 1809178825Sdfr val->v.octetstring.len, val->v.octetstring.octets); 1810178825Sdfr else 1811178825Sdfr snmp_output_octetstring(snmptoolctx, SNMP_STRING, 1812178825Sdfr val->v.octetstring.len, val->v.octetstring.octets); 1813178825Sdfr break; 1814178825Sdfr 1815178825Sdfr case SNMP_SYNTAX_OID: 1816178825Sdfr snmp_output_oid_value(snmptoolctx, &(val->v.oid)); 1817178825Sdfr break; 1818178825Sdfr 1819178825Sdfr case SNMP_SYNTAX_IPADDRESS: 1820178825Sdfr snmp_output_ipaddress(snmptoolctx, val->v.ipaddress); 1821178825Sdfr break; 1822178825Sdfr 1823178825Sdfr case SNMP_SYNTAX_COUNTER: 1824178825Sdfr snmp_output_counter(snmptoolctx, val->v.uint32); 1825178825Sdfr break; 1826178825Sdfr 1827178825Sdfr case SNMP_SYNTAX_GAUGE: 1828178825Sdfr snmp_output_gauge(snmptoolctx, val->v.uint32); 1829178825Sdfr break; 1830178825Sdfr 1831178825Sdfr case SNMP_SYNTAX_TIMETICKS: 1832178825Sdfr snmp_output_ticks(snmptoolctx, val->v.uint32); 1833178825Sdfr break; 1834178825Sdfr 1835178825Sdfr case SNMP_SYNTAX_COUNTER64: 1836178825Sdfr snmp_output_counter64(snmptoolctx, val->v.counter64); 1837178825Sdfr break; 1838178825Sdfr 1839178825Sdfr case SNMP_SYNTAX_NOSUCHOBJECT: 1840178825Sdfr fprintf(stdout, "No Such Object\n"); 1841178825Sdfr return (val->syntax); 1842178825Sdfr 1843178825Sdfr case SNMP_SYNTAX_NOSUCHINSTANCE: 1844178825Sdfr fprintf(stdout, "No Such Instance\n"); 1845178825Sdfr return (val->syntax); 1846178825Sdfr 1847178825Sdfr case SNMP_SYNTAX_ENDOFMIBVIEW: 1848178825Sdfr fprintf(stdout, "End of Mib View\n"); 1849178825Sdfr return (val->syntax); 1850178825Sdfr 1851178825Sdfr case SNMP_SYNTAX_NULL: 1852178825Sdfr /* NOTREACHED */ 1853178825Sdfr fprintf(stdout, "agent returned NULL Syntax\n"); 1854178825Sdfr return (val->syntax); 1855178825Sdfr 1856178825Sdfr default: 1857178825Sdfr /* NOTREACHED - If here - then all went completely wrong. */ 1858178825Sdfr fprintf(stdout, "agent returned unknown syntax\n"); 1859178825Sdfr return (-1); 1860178825Sdfr } 1861178825Sdfr 1862178825Sdfr fprintf(stdout, "\n"); 1863178825Sdfr 1864178825Sdfr return (0); 1865178825Sdfr} 1866178825Sdfr 1867178825Sdfrstatic int32_t 1868178825Sdfrsnmp_fill_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *obj, 1869178825Sdfr struct snmp_value *val) 1870178825Sdfr{ 1871178825Sdfr int32_t rc; 1872178825Sdfr asn_subid_t suboid; 1873178825Sdfr 1874178825Sdfr if (obj == NULL || val == NULL) 1875178825Sdfr return (-1); 1876178825Sdfr 1877178825Sdfr if ((suboid = snmp_suboid_pop(&(val->var))) > ASN_MAXID) 1878178825Sdfr return (-1); 1879178825Sdfr 1880178825Sdfr memset(obj, 0, sizeof(struct snmp_object)); 1881178825Sdfr asn_append_oid(&(obj->val.var), &(val->var)); 1882178825Sdfr obj->val.syntax = val->syntax; 1883178825Sdfr 1884178825Sdfr if (obj->val.syntax > 0) 1885178825Sdfr rc = snmp_lookup_leafstring(snmptoolctx, obj); 1886178825Sdfr else 1887178825Sdfr rc = snmp_lookup_nonleaf_string(snmptoolctx, obj); 1888178825Sdfr 1889233294Sstas (void) snmp_suboid_append(&(val->var), suboid); 1890178825Sdfr (void) snmp_suboid_append(&(obj->val.var), suboid); 1891178825Sdfr 1892178825Sdfr return (rc); 1893178825Sdfr} 1894178825Sdfr 1895178825Sdfrstatic int32_t 1896178825Sdfrsnmp_output_index(struct snmp_toolinfo *snmptoolctx, struct index *stx, 1897178825Sdfr struct asn_oid *oid) 1898178825Sdfr{ 1899178825Sdfr uint8_t ip[4]; 1900178825Sdfr uint32_t bytes = 1; 1901178825Sdfr uint64_t cnt64; 1902178825Sdfr struct asn_oid temp, out; 1903233294Sstas 1904178825Sdfr if (oid->len < bytes) 1905178825Sdfr return (-1); 1906178825Sdfr 1907178825Sdfr memset(&temp, 0, sizeof(struct asn_oid)); 1908178825Sdfr asn_append_oid(&temp, oid); 1909178825Sdfr 1910178825Sdfr switch (stx->syntax) { 1911178825Sdfr case SNMP_SYNTAX_INTEGER: 1912178825Sdfr snmp_output_int(snmptoolctx, stx->snmp_enum, temp.subs[0]); 1913178825Sdfr break; 1914178825Sdfr 1915178825Sdfr case SNMP_SYNTAX_OCTETSTRING: 1916178825Sdfr if ((temp.subs[0] > temp.len -1 ) || (temp.subs[0] > 1917178825Sdfr ASN_MAXOCTETSTRING)) 1918178825Sdfr return (-1); 1919178825Sdfr snmp_output_octetindex(snmptoolctx, stx->tc, &temp); 1920178825Sdfr bytes += temp.subs[0]; 1921178825Sdfr break; 1922178825Sdfr 1923178825Sdfr case SNMP_SYNTAX_OID: 1924178825Sdfr if ((temp.subs[0] > temp.len -1) || (temp.subs[0] > 1925178825Sdfr ASN_MAXOIDLEN)) 1926178825Sdfr return (-1); 1927178825Sdfr 1928178825Sdfr bytes += temp.subs[0]; 1929178825Sdfr memset(&out, 0, sizeof(struct asn_oid)); 1930178825Sdfr asn_slice_oid(&out, &temp, 1, bytes); 1931178825Sdfr snmp_output_oid_value(snmptoolctx, &out); 1932178825Sdfr break; 1933178825Sdfr 1934178825Sdfr case SNMP_SYNTAX_IPADDRESS: 1935178825Sdfr if (temp.len < 4) 1936178825Sdfr return (-1); 1937178825Sdfr for (bytes = 0; bytes < 4; bytes++) 1938178825Sdfr ip[bytes] = temp.subs[bytes]; 1939178825Sdfr 1940178825Sdfr snmp_output_ipaddress(snmptoolctx, ip); 1941178825Sdfr bytes = 4; 1942178825Sdfr break; 1943178825Sdfr 1944178825Sdfr case SNMP_SYNTAX_COUNTER: 1945178825Sdfr snmp_output_counter(snmptoolctx, temp.subs[0]); 1946178825Sdfr break; 1947178825Sdfr 1948178825Sdfr case SNMP_SYNTAX_GAUGE: 1949178825Sdfr snmp_output_gauge(snmptoolctx, temp.subs[0]); 1950178825Sdfr break; 1951178825Sdfr 1952178825Sdfr case SNMP_SYNTAX_TIMETICKS: 1953178825Sdfr snmp_output_ticks(snmptoolctx, temp.subs[0]); 1954178825Sdfr break; 1955178825Sdfr 1956178825Sdfr case SNMP_SYNTAX_COUNTER64: 1957178825Sdfr if (oid->len < 2) 1958233294Sstas return (-1); 1959233294Sstas bytes = 2; 1960233294Sstas memcpy(&cnt64, temp.subs, bytes); 1961233294Sstas snmp_output_counter64(snmptoolctx, cnt64); 1962233294Sstas break; 1963233294Sstas 1964233294Sstas default: 1965233294Sstas return (-1); 1966178825Sdfr } 1967178825Sdfr 1968178825Sdfr return (bytes); 1969178825Sdfr} 1970178825Sdfr 1971178825Sdfrstatic int32_t 1972178825Sdfrsnmp_output_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *o) 1973178825Sdfr{ 1974178825Sdfr int32_t i, first, len; 1975178825Sdfr struct asn_oid oid; 1976178825Sdfr struct index *temp; 1977178825Sdfr 1978178825Sdfr if (ISSET_NUMERIC(snmptoolctx)) 1979178825Sdfr return (-1); 1980178825Sdfr 1981178825Sdfr if (o->info->table_idx == NULL) { 1982178825Sdfr fprintf(stdout,"%s.%d", o->info->string, 1983178825Sdfr o->val.var.subs[o->val.var.len - 1]); 1984178825Sdfr return (1); 1985178825Sdfr } 1986178825Sdfr 1987178825Sdfr fprintf(stdout,"%s[", o->info->string); 1988178825Sdfr memset(&oid, 0, sizeof(struct asn_oid)); 1989178825Sdfr 1990178825Sdfr len = 1; 1991178825Sdfr asn_slice_oid(&oid, &(o->val.var), (o->info->table_idx->var.len + len), 1992178825Sdfr o->val.var.len); 1993178825Sdfr 1994178825Sdfr first = 1; 1995178825Sdfr STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(o)), link) { 1996178825Sdfr if(first) 1997178825Sdfr first = 0; 1998178825Sdfr else 1999178825Sdfr fprintf(stdout, ", "); 2000178825Sdfr if ((i = snmp_output_index(snmptoolctx, temp, &oid)) < 0) 2001178825Sdfr break; 2002178825Sdfr len += i; 2003178825Sdfr memset(&oid, 0, sizeof(struct asn_oid)); 2004178825Sdfr asn_slice_oid(&oid, &(o->val.var), 2005178825Sdfr (o->info->table_idx->var.len + len), o->val.var.len + 1); 2006178825Sdfr } 2007178825Sdfr 2008178825Sdfr fprintf(stdout,"]"); 2009178825Sdfr return (1); 2010178825Sdfr} 2011178825Sdfr 2012178825Sdfrvoid 2013178825Sdfrsnmp_output_err_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu) 2014178825Sdfr{ 2015178825Sdfr char buf[ASN_OIDSTRLEN]; 2016178825Sdfr struct snmp_object object; 2017178825Sdfr 2018178825Sdfr if (pdu == NULL || (pdu->error_index > (int32_t) pdu->nbindings)) { 2019178825Sdfr fprintf(stdout,"Invalid error index in PDU\n"); 2020178825Sdfr return; 2021178825Sdfr } 2022178825Sdfr 2023178825Sdfr fprintf(stdout, "Agent %s:%s returned error \n", snmp_client.chost, 2024178825Sdfr snmp_client.cport); 2025178825Sdfr 2026178825Sdfr if (!ISSET_NUMERIC(snmptoolctx) && (snmp_fill_object(snmptoolctx, &object, 2027178825Sdfr &(pdu->bindings[pdu->error_index - 1])) > 0)) 2028178825Sdfr snmp_output_object(snmptoolctx, &object); 2029178825Sdfr else { 2030178825Sdfr asn_oid2str_r(&(pdu->bindings[pdu->error_index - 1].var), buf); 2031178825Sdfr fprintf(stdout,"%s", buf); 2032178825Sdfr } 2033178825Sdfr 2034178825Sdfr fprintf(stdout," caused error - "); 2035178825Sdfr if ((pdu->error_status > 0) && (pdu->error_status <= 2036178825Sdfr SNMP_ERR_INCONS_NAME)) 2037178825Sdfr fprintf(stdout, "%s\n", error_strings[pdu->error_status].str); 2038178825Sdfr else 2039178825Sdfr fprintf(stdout,"%s\n", error_strings[SNMP_ERR_UNKNOWN].str); 2040178825Sdfr} 2041178825Sdfr 2042178825Sdfrint32_t 2043178825Sdfrsnmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu, 2044233294Sstas struct asn_oid *root) 2045178825Sdfr{ 2046178825Sdfr int32_t error; 2047178825Sdfr char p[ASN_OIDSTRLEN]; 2048178825Sdfr uint32_t i; 2049178825Sdfr struct snmp_object object; 2050178825Sdfr 2051178825Sdfr i = error = 0; 2052178825Sdfr while (i < pdu->nbindings) { 2053178825Sdfr if (root != NULL && !(asn_is_suboid(root, 2054178825Sdfr &(pdu->bindings[i].var)))) 2055178825Sdfr break; 2056178825Sdfr 2057178825Sdfr if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) { 2058178825Sdfr if (!ISSET_NUMERIC(snmptoolctx) && 2059178825Sdfr (snmp_fill_object(snmptoolctx, &object, 2060178825Sdfr &(pdu->bindings[i])) > 0)) 2061178825Sdfr snmp_output_object(snmptoolctx, &object); 2062178825Sdfr else { 2063178825Sdfr asn_oid2str_r(&(pdu->bindings[i].var), p); 2064178825Sdfr fprintf(stdout, "%s", p); 2065178825Sdfr } 2066178825Sdfr } 2067178825Sdfr error |= snmp_output_numval(snmptoolctx, &(pdu->bindings[i]), object.info); 2068178825Sdfr i++; 2069178825Sdfr } 2070178825Sdfr 2071178825Sdfr if (error) 2072178825Sdfr return (-1); 2073178825Sdfr 2074178825Sdfr return (i); 2075178825Sdfr} 2076178825Sdfr 2077178825Sdfrvoid 2078178825Sdfrsnmp_output_engine(void) 2079178825Sdfr{ 2080178825Sdfr uint32_t i; 2081178825Sdfr char *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2]; 2082178825Sdfr 2083178825Sdfr cptr = engine; 2084178825Sdfr for (i = 0; i < snmp_client.engine.engine_len; i++) 2085178825Sdfr cptr += sprintf(cptr, "%.2x", snmp_client.engine.engine_id[i]); 2086178825Sdfr *cptr++ = '\0'; 2087178825Sdfr 2088178825Sdfr fprintf(stdout, "Engine ID 0x%s\n", engine); 2089178825Sdfr fprintf(stdout, "Boots : %u\t\tTime : %d\n", 2090178825Sdfr snmp_client.engine.engine_boots, 2091178825Sdfr snmp_client.engine.engine_time); 2092178825Sdfr} 2093233294Sstas 2094178825Sdfrvoid 2095178825Sdfrsnmp_output_keys(void) 2096178825Sdfr{ 2097178825Sdfr uint32_t i, keylen = 0; 2098178825Sdfr char *cptr, extkey[2 * SNMP_AUTH_KEY_SIZ + 2]; 2099178825Sdfr 2100178825Sdfr fprintf(stdout, "Localized keys for %s\n", snmp_client.user.sec_name); 2101178825Sdfr if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_MD5) { 2102178825Sdfr fprintf(stdout, "MD5 : 0x"); 2103178825Sdfr keylen = SNMP_AUTH_HMACMD5_KEY_SIZ; 2104178825Sdfr } else if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_SHA) { 2105178825Sdfr fprintf(stdout, "SHA : 0x"); 2106178825Sdfr keylen = SNMP_AUTH_HMACSHA_KEY_SIZ; 2107178825Sdfr } 2108178825Sdfr if (snmp_client.user.auth_proto != SNMP_AUTH_NOAUTH) { 2109178825Sdfr cptr = extkey; 2110178825Sdfr for (i = 0; i < keylen; i++) 2111178825Sdfr cptr += sprintf(cptr, "%.2x", 2112178825Sdfr snmp_client.user.auth_key[i]); 2113178825Sdfr *cptr++ = '\0'; 2114178825Sdfr fprintf(stdout, "%s\n", extkey); 2115178825Sdfr } 2116178825Sdfr 2117178825Sdfr if (snmp_client.user.priv_proto == SNMP_PRIV_DES) { 2118178825Sdfr fprintf(stdout, "DES : 0x"); 2119178825Sdfr keylen = SNMP_PRIV_DES_KEY_SIZ; 2120178825Sdfr } else if (snmp_client.user.priv_proto == SNMP_PRIV_AES) { 2121178825Sdfr fprintf(stdout, "AES : 0x"); 2122178825Sdfr keylen = SNMP_PRIV_AES_KEY_SIZ; 2123178825Sdfr } 2124178825Sdfr if (snmp_client.user.priv_proto != SNMP_PRIV_NOPRIV) { 2125178825Sdfr cptr = extkey; 2126178825Sdfr for (i = 0; i < keylen; i++) 2127178825Sdfr cptr += sprintf(cptr, "%.2x", 2128178825Sdfr snmp_client.user.priv_key[i]); 2129178825Sdfr *cptr++ = '\0'; 2130178825Sdfr fprintf(stdout, "%s\n", extkey); 2131178825Sdfr } 2132178825Sdfr} 2133178825Sdfr