2 * Copyright (c) 2005-2006 The FreeBSD Project
5 * Author: Shteryana Shopova <syrinx@FreeBSD.org>
7 * Redistribution of this software and documentation and use in source and
8 * binary forms, with or without modification, are permitted provided that
9 * the following conditions are met:
11 * 1. Redistributions of source code or documentation must retain the above
12 * copyright notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Helper functions for snmp client tools
34 #include <sys/param.h>
35 #include <sys/queue.h>
49 #include <bsnmp/asn1.h>
50 #include <bsnmp/snmp.h>
51 #include <bsnmp/snmpclient.h>
53 #include "bsnmptools.h"
55 /* Internal varibale to turn on library debugging for testing and to
56 * find bugs. It is not exported via the header file.
57 * XXX should we cover it by some #ifdef BSNMPTOOLS_DEBUG? */
58 int _bsnmptools_debug = 0;
60 /* Default files to import mapping from if none explicitly provided. */
61 #define bsnmpd_defs "/usr/share/snmp/defs/tree.def"
62 #define mibII_defs "/usr/share/snmp/defs/mibII_tree.def"
65 * The .iso.org.dod oid that has to be prepended to every OID when requesting
68 const struct asn_oid IsoOrgDod_OID = {
73 #define SNMP_ERR_UNKNOWN 0
76 * An array of error strings corresponding to error definitions from libbsnmp.
82 { "Unknown", SNMP_ERR_UNKNOWN },
83 { "Too big ", SNMP_ERR_TOOBIG },
84 { "No such Name", SNMP_ERR_NOSUCHNAME },
85 { "Bad Value", SNMP_ERR_BADVALUE },
86 { "Readonly", SNMP_ERR_READONLY },
87 { "General error", SNMP_ERR_GENERR },
88 { "No access", SNMP_ERR_NO_ACCESS },
89 { "Wrong type", SNMP_ERR_WRONG_TYPE },
90 { "Wrong length", SNMP_ERR_WRONG_LENGTH },
91 { "Wrong encoding", SNMP_ERR_WRONG_ENCODING },
92 { "Wrong value", SNMP_ERR_WRONG_VALUE },
93 { "No creation", SNMP_ERR_NO_CREATION },
94 { "Inconsistent value", SNMP_ERR_INCONS_VALUE },
95 { "Resource unavailable", SNMP_ERR_RES_UNAVAIL },
96 { "Commit failed", SNMP_ERR_COMMIT_FAILED },
97 { "Undo failed", SNMP_ERR_UNDO_FAILED },
98 { "Authorization error", SNMP_ERR_AUTH_ERR },
99 { "Not writable", SNMP_ERR_NOT_WRITEABLE },
100 { "Inconsistent name", SNMP_ERR_INCONS_NAME },
104 /* This one and any following are exceptions. */
105 #define SNMP_SYNTAX_UNKNOWN SNMP_SYNTAX_NOSUCHOBJECT
107 static const struct {
109 enum snmp_syntax stx;
110 } syntax_strings[] = {
111 { "Null", SNMP_SYNTAX_NULL },
112 { "Integer", SNMP_SYNTAX_INTEGER },
113 { "OctetString", SNMP_SYNTAX_OCTETSTRING },
114 { "OID", SNMP_SYNTAX_OID },
115 { "IpAddress", SNMP_SYNTAX_IPADDRESS },
116 { "Counter32", SNMP_SYNTAX_COUNTER },
117 { "Gauge", SNMP_SYNTAX_GAUGE },
118 { "TimeTicks", SNMP_SYNTAX_TIMETICKS },
119 { "Counter64", SNMP_SYNTAX_COUNTER64 },
120 { "Unknown", SNMP_SYNTAX_UNKNOWN },
124 snmptool_init(struct snmp_toolinfo *snmptoolctx)
129 memset(snmptoolctx, 0, sizeof(struct snmp_toolinfo));
130 snmptoolctx->objects = 0;
131 snmptoolctx->mappings = NULL;
132 snmptoolctx->flags = SNMP_PDU_GET; /* XXX */
133 SLIST_INIT(&snmptoolctx->filelist);
134 snmp_client_init(&snmp_client);
135 SET_MAXREP(snmptoolctx, SNMP_MAX_REPETITIONS);
137 if (add_filename(snmptoolctx, bsnmpd_defs, &IsoOrgDod_OID, 0) < 0)
138 warnx("Error adding file %s to list", bsnmpd_defs);
140 if (add_filename(snmptoolctx, mibII_defs, &IsoOrgDod_OID, 0) < 0)
141 warnx("Error adding file %s to list", mibII_defs);
143 /* Read the environment */
144 if ((str = getenv("SNMPAUTH")) != NULL) {
146 if (slen == strlen("md5") && strcasecmp(str, "md5") == 0)
147 snmp_client.user.auth_proto = SNMP_AUTH_HMAC_MD5;
148 else if (slen == strlen("sha")&& strcasecmp(str, "sha") == 0)
149 snmp_client.user.auth_proto = SNMP_AUTH_HMAC_SHA;
151 warnx("Bad authentication type - %s in SNMPAUTH", str);
154 if ((str = getenv("SNMPPRIV")) != NULL) {
156 if (slen == strlen("des") && strcasecmp(str, "des") == 0)
157 snmp_client.user.priv_proto = SNMP_PRIV_DES;
158 else if (slen == strlen("aes")&& strcasecmp(str, "aes") == 0)
159 snmp_client.user.priv_proto = SNMP_PRIV_AES;
161 warnx("Bad privacy type - %s in SNMPPRIV", str);
164 if ((str = getenv("SNMPUSER")) != NULL) {
165 if ((slen = strlen(str)) > sizeof(snmp_client.user.sec_name)) {
166 warnx("Username too long - %s in SNMPUSER", str);
170 strlcpy(snmp_client.user.sec_name, str,
171 sizeof(snmp_client.user.sec_name));
172 snmp_client.version = SNMP_V3;
176 if ((str = getenv("SNMPPASSWD")) != NULL) {
177 if ((slen = strlen(str)) > MAXSTR)
179 if ((snmptoolctx->passwd = malloc(slen + 1)) == NULL) {
180 warnx("malloc() failed - %s", strerror(errno));
184 strlcpy(snmptoolctx->passwd, str, slen + 1);
190 #define OBJECT_IDX_LIST(o) o->info->table_idx->index_list
193 * Walk through the file list and import string<->oid mappings from each file.
196 snmp_import_all(struct snmp_toolinfo *snmptoolctx)
201 if (snmptoolctx == NULL)
204 if (ISSET_NUMERIC(snmptoolctx))
207 if ((snmptoolctx->mappings = snmp_mapping_init()) == NULL)
211 if (SLIST_EMPTY(&snmptoolctx->filelist)) {
212 warnx("No files to read OID <-> string conversions from");
215 SLIST_FOREACH(tmp, &snmptoolctx->filelist, link) {
218 if (snmp_import_file(snmptoolctx, tmp) < 0) {
226 snmp_mapping_dump(snmptoolctx);
231 * Add a filename to the file list - the initial idea of keeping a list with all
232 * files to read OIDs from was that an application might want to have loaded in
233 * memory the OIDs from a single file only and when done with them read the OIDs
234 * from another file. This is not used yet but might be a good idea at some
235 * point. Size argument is number of bytes in string including trailing '\0',
239 add_filename(struct snmp_toolinfo *snmptoolctx, const char *filename,
240 const struct asn_oid *cut, int32_t done)
245 if (snmptoolctx == NULL)
248 /* Make sure file was not in list. */
249 SLIST_FOREACH(entry, &snmptoolctx->filelist, link) {
250 if (strncmp(entry->name, filename, strlen(entry->name)) == 0)
254 if ((fstring = malloc(strlen(filename) + 1)) == NULL) {
255 warnx("malloc() failed - %s", strerror(errno));
259 if ((entry = calloc(1, sizeof(struct fname))) == NULL) {
260 warnx("malloc() failed - %s", strerror(errno));
266 asn_append_oid(&(entry->cut), cut);
267 strlcpy(fstring, filename, strlen(filename) + 1);
268 entry->name = fstring;
270 SLIST_INSERT_HEAD(&snmptoolctx->filelist, entry, link);
276 free_filelist(struct snmp_toolinfo *snmptoolctx)
280 if (snmptoolctx == NULL)
281 return; /* XXX error handling */
283 while ((f = SLIST_FIRST(&snmptoolctx->filelist)) != NULL) {
284 SLIST_REMOVE_HEAD(&snmptoolctx->filelist, link);
292 isvalid_fchar(char c, int pos)
294 if (isalpha(c)|| c == '/'|| c == '_' || c == '.' || c == '~' ||
295 (pos != 0 && isdigit(c))){
302 if (!isascii(c) || !isprint(c))
303 warnx("Unexpected character %#2x", (u_int) c);
305 warnx("Illegal character '%c'", c);
311 * Re-implement getsubopt from scratch, because the second argument is broken
312 * and will not compile with WARNS=5.
313 * Copied from src/contrib/bsnmp/snmpd/main.c.
316 getsubopt1(char **arg, const char *const *options, char **valp, char **optp)
318 static const char *const delim = ",\t ";
324 /* Skip leading junk. */
325 for (ptr = *arg; *ptr != '\0'; ptr++)
326 if (strchr(delim, *ptr) == NULL)
334 /* Find the end of the option. */
335 while (*++ptr != '\0')
336 if (strchr(delim, *ptr) != NULL || *ptr == '=')
343 while (*ptr != '\0' && strchr(delim, *ptr) == NULL)
353 for (i = 0; *options != NULL; options++, i++)
354 if (strcmp(*optp, *options) == 0)
360 parse_path(char *value)
367 for (len = 0; len < MAXPATHLEN; len++) {
368 i = isvalid_fchar(*(value + len), len) ;
376 if (len >= MAXPATHLEN || value[len] != '\0') {
377 warnx("Bad pathname - '%s'", value);
385 parse_flist(struct snmp_toolinfo *snmptoolctx, char *value, char *path,
386 const struct asn_oid *cut)
389 char filename[MAXPATHLEN + 1];
395 memset(filename, 0, MAXPATHLEN + 1);
397 if (isalpha(*value) && (path == NULL || path[0] == '\0')) {
398 strlcpy(filename, SNMP_DEFS_DIR, MAXPATHLEN + 1);
399 namelen = strlen(SNMP_DEFS_DIR);
400 } else if (path != NULL){
401 strlcpy(filename, path, MAXPATHLEN + 1);
402 namelen = strlen(path);
406 for ( ; namelen < MAXPATHLEN; value++) {
407 if (isvalid_fchar(*value, namelen) > 0) {
408 filename[namelen++] = *value;
414 else if (*value == '\0')
417 if (!isascii(*value) || !isprint(*value))
418 warnx("Unexpected character %#2x in"
419 " filename", (u_int) *value);
421 warnx("Illegal character '%c' in"
422 " filename", *value);
426 filename[namelen]='\0';
430 if ((namelen == MAXPATHLEN) && (filename[MAXPATHLEN] != '\0')) {
431 warnx("Filename %s too long", filename);
435 if (add_filename(snmptoolctx, filename, cut, 0) < 0) {
436 warnx("Error adding file %s to list", filename);
439 } while (*value != '\0');
445 parse_ascii(char *ascii, uint8_t *binstr, size_t binlen)
449 int32_t alen, i, saved_errno;
452 /* Filter 0x at the beginning */
453 if ((alen = strlen(ascii)) > 2 && ascii[0] == '0' && ascii[1] == 'x')
460 for (count = 0; i < alen; i += 2) {
461 /* XXX: consider strlen(ascii) % 2 != 0 */
463 dptr[1] = ascii[i + 1];
465 if ((val = strtoul(dptr, NULL, 16)) > 0xFF || errno != 0) {
469 binstr[count] = (uint8_t) val;
470 if (++count >= binlen) {
471 warnx("Key %s too long - truncating to %zu octets",
481 * Functions to parse common input options for client tools and fill in the
482 * snmp_client structure.
485 parse_authentication(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
487 int32_t count, subopt;
489 const char *const subopts[] = {
495 assert(opt_arg != NULL);
497 while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
501 warnx("Suboption 'proto' requires an argument");
504 if (strlen(val) != 3) {
505 warnx("Unknown auth protocol - %s", val);
508 if (strncasecmp("md5", val, strlen("md5")) == 0)
509 snmp_client.user.auth_proto =
511 else if (strncasecmp("sha", val, strlen("sha")) == 0)
512 snmp_client.user.auth_proto =
515 warnx("Unknown auth protocol - %s", val);
521 warnx("Suboption 'key' requires an argument");
524 if (parse_ascii(val, snmp_client.user.auth_key,
525 SNMP_AUTH_KEY_SIZ) < 0) {
526 warnx("Bad authentication key- %s", val);
531 warnx("Unknown suboption - '%s'", suboptarg);
536 return (2/* count */);
540 parse_privacy(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
542 int32_t count, subopt;
544 const char *const subopts[] = {
550 assert(opt_arg != NULL);
552 while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
556 warnx("Suboption 'proto' requires an argument");
559 if (strlen(val) != 3) {
560 warnx("Unknown privacy protocol - %s", val);
563 if (strncasecmp("aes", val, strlen("aes")) == 0)
564 snmp_client.user.priv_proto = SNMP_PRIV_AES;
565 else if (strncasecmp("des", val, strlen("des")) == 0)
566 snmp_client.user.priv_proto = SNMP_PRIV_DES;
568 warnx("Unknown privacy protocol - %s", val);
574 warnx("Suboption 'key' requires an argument");
577 if (parse_ascii(val, snmp_client.user.priv_key,
578 SNMP_PRIV_KEY_SIZ) < 0) {
579 warnx("Bad privacy key- %s", val);
584 warnx("Unknown suboption - '%s'", suboptarg);
589 return (2/* count */);
593 parse_context(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
595 int32_t count, subopt;
597 const char *const subopts[] = {
603 assert(opt_arg != NULL);
605 while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
609 warnx("Suboption 'context' - no argument");
612 strlcpy(snmp_client.cname, val, SNMP_CONTEXT_NAME_SIZ);
616 warnx("Suboption 'context-engine' - no argument");
619 if ((snmp_client.clen = parse_ascii(val,
620 snmp_client.cengine, SNMP_ENGINE_ID_SIZ)) < 0) {
621 warnx("Bad EngineID - %s", val);
626 warnx("Unknown suboption - '%s'", suboptarg);
631 return (2/* count */);
635 parse_user_security(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
637 int32_t count, subopt, saved_errno;
639 const char *const subopts[] = {
647 assert(opt_arg != NULL);
649 while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
653 warnx("Suboption 'engine' - no argument");
656 snmp_client.engine.engine_len = parse_ascii(val,
657 snmp_client.engine.engine_id, SNMP_ENGINE_ID_SIZ);
658 if (snmp_client.engine.engine_len < 0) {
659 warnx("Bad EngineID - %s", val);
665 warnx("Suboption 'engine-boots' - no argument");
670 snmp_client.engine.engine_boots = strtoul(val, NULL, 10);
672 warnx("Bad 'engine-boots' value %s - %s", val,
681 warnx("Suboption 'engine-time' - no argument");
686 snmp_client.engine.engine_time = strtoul(val, NULL, 10);
688 warnx("Bad 'engine-time' value %s - %s", val,
696 strlcpy(snmp_client.user.sec_name, val,
700 warnx("Unknown suboption - '%s'", suboptarg);
705 return (2/* count */);
709 parse_file(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
711 assert(opt_arg != NULL);
713 if (parse_flist(snmptoolctx, opt_arg, NULL, &IsoOrgDod_OID) < 0)
720 parse_include(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
722 char path[MAXPATHLEN + 1];
723 int32_t cut_dflt, len, subopt;
726 const char *const subopts[] = {
737 assert(opt_arg != NULL);
740 free_filelist(snmptoolctx, ); */
742 * This function should be called only after getopt(3) - otherwise if
743 * no previous validation of opt_arg strlen() may not return what is
748 memset(&cut, 0, sizeof(struct asn_oid));
751 while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
755 warnx("Suboption 'cut' requires an argument");
758 if (snmp_parse_numoid(val, &cut) < 0)
765 if ((len = parse_path(val)) < 0)
767 strlcpy(path, val, len + 1);
774 len = parse_flist(snmptoolctx, val, path, &IsoOrgDod_OID);
776 len = parse_flist(snmptoolctx, val, path, &cut);
782 warnx("Unknown suboption - '%s'", suboptarg);
787 /* XXX: Fix me - returning two is wrong here */
792 parse_server(char *opt_arg)
794 assert(opt_arg != NULL);
796 if (snmp_parse_server(&snmp_client, opt_arg) < 0)
799 if (snmp_client.trans > SNMP_TRANS_UDP && snmp_client.chost == NULL) {
800 if ((snmp_client.chost = malloc(strlen(SNMP_DEFAULT_LOCAL) + 1))
802 syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
805 strcpy(snmp_client.chost, SNMP_DEFAULT_LOCAL);
812 parse_timeout(char *opt_arg)
814 int32_t v, saved_errno;
816 assert(opt_arg != NULL);
821 v = strtol(opt_arg, NULL, 10);
823 warnx( "Error parsing timeout value - %s", strerror(errno));
828 snmp_client.timeout.tv_sec = v;
834 parse_retry(char *opt_arg)
839 assert(opt_arg != NULL);
844 v = strtoul(opt_arg, NULL, 10);
846 warnx("Error parsing retries count - %s", strerror(errno));
851 snmp_client.retries = v;
857 parse_version(char *opt_arg)
862 assert(opt_arg != NULL);
867 v = strtoul(opt_arg, NULL, 10);
869 warnx("Error parsing version - %s", strerror(errno));
876 snmp_client.version = SNMP_V1;
879 snmp_client.version = SNMP_V2c;
882 snmp_client.version = SNMP_V3;
885 warnx("Unsupported SNMP version - %u", v);
895 parse_local_path(char *opt_arg)
897 assert(opt_arg != NULL);
899 if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) {
900 warnx("Filename too long - %s", opt_arg);
904 strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH));
909 parse_buflen(char *opt_arg)
914 assert(opt_arg != NULL);
919 size = strtoul(opt_arg, NULL, 10);
921 warnx("Error parsing buffer size - %s", strerror(errno));
926 if (size > MAX_BUFF_SIZE) {
927 warnx("Buffer size too big - %d max allowed", MAX_BUFF_SIZE);
932 snmp_client.txbuflen = snmp_client.rxbuflen = size;
940 snmp_client.dump_pdus = 1;
945 parse_discovery(struct snmp_toolinfo *snmptoolctx)
947 SET_EDISCOVER(snmptoolctx);
948 snmp_client.version = SNMP_V3;
953 parse_local_key(struct snmp_toolinfo *snmptoolctx)
955 SET_LOCALKEY(snmptoolctx);
956 snmp_client.version = SNMP_V3;
961 parse_num_oids(struct snmp_toolinfo *snmptoolctx)
963 SET_NUMERIC(snmptoolctx);
968 parse_output(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
970 assert(opt_arg != NULL);
972 if (strlen(opt_arg) > strlen("verbose")) {
973 warnx( "Invalid output option - %s",opt_arg);
977 if (strncasecmp(opt_arg, "short", strlen(opt_arg)) == 0)
978 SET_OUTPUT(snmptoolctx, OUTPUT_SHORT);
979 else if (strncasecmp(opt_arg, "verbose", strlen(opt_arg)) == 0)
980 SET_OUTPUT(snmptoolctx, OUTPUT_VERBOSE);
981 else if (strncasecmp(opt_arg,"tabular", strlen(opt_arg)) == 0)
982 SET_OUTPUT(snmptoolctx, OUTPUT_TABULAR);
983 else if (strncasecmp(opt_arg, "quiet", strlen(opt_arg)) == 0)
984 SET_OUTPUT(snmptoolctx, OUTPUT_QUIET);
986 warnx( "Invalid output option - %s", opt_arg);
994 parse_errors(struct snmp_toolinfo *snmptoolctx)
996 SET_RETRY(snmptoolctx);
1001 parse_skip_access(struct snmp_toolinfo *snmptoolctx)
1003 SET_ERRIGNORE(snmptoolctx);
1008 snmp_parse_suboid(char *str, struct asn_oid *oid)
1016 if (*str < '0' || *str > '9')
1020 suboid = strtoul(str, &endptr, 10);
1021 if ((asn_subid_t) suboid > ASN_MAXID) {
1022 warnx("Suboid %u > ASN_MAXID", suboid);
1025 if (snmp_suboid_append(oid, suboid) < 0)
1028 } while (*endptr == '.');
1034 snmp_int2asn_oid(char *str, struct asn_oid *oid)
1037 int32_t v, saved_errno;
1039 saved_errno = errno;
1042 v = strtol(str, &endptr, 10);
1044 warnx("Integer value %s not supported - %s", str,
1046 errno = saved_errno;
1049 errno = saved_errno;
1051 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1057 /* It is a bit weird to have a table indexed by OID but still... */
1059 snmp_oid2asn_oid(struct snmp_toolinfo *snmptoolctx, char *str,
1060 struct asn_oid *oid)
1063 char string[MAXSTR], *endptr;
1064 struct snmp_object obj;
1066 for (i = 0; i < MAXSTR; i++)
1067 if (isalpha (*(str + i)) == 0)
1071 memset(&obj, 0, sizeof(struct snmp_object));
1073 if ((endptr = snmp_parse_suboid(str, &(obj.val.var))) == NULL)
1075 if (snmp_suboid_append(oid, (asn_subid_t) obj.val.var.len) < 0)
1078 strlcpy(string, str, i + 1);
1080 if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) {
1081 warnx("Unknown string - %s", string);
1086 asn_append_oid(oid, &(obj.val.var));
1091 snmp_ip2asn_oid(char *str, struct asn_oid *oid)
1098 for (i = 0; i < 4; i++) {
1099 v = strtoul(ptr, &endptr, 10);
1102 if (*endptr != '.' && strchr("],\0", *endptr) == NULL && i != 3)
1104 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1112 /* 32-bit counter, gauge, timeticks. */
1114 snmp_uint2asn_oid(char *str, struct asn_oid *oid)
1118 int32_t saved_errno;
1120 saved_errno = errno;
1123 v = strtoul(str, &endptr, 10);
1125 warnx("Integer value %s not supported - %s\n", str,
1127 errno = saved_errno;
1130 errno = saved_errno;
1131 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1138 snmp_cnt64_2asn_oid(char *str, struct asn_oid *oid)
1142 int32_t saved_errno;
1144 saved_errno = errno;
1147 v = strtoull(str, &endptr, 10);
1150 warnx("Integer value %s not supported - %s", str,
1152 errno = saved_errno;
1155 errno = saved_errno;
1156 if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xffffffff)) < 0)
1159 if (snmp_suboid_append(oid, (asn_subid_t) (v >> 32)) < 0)
1166 parse_syntax(char *str)
1170 for (i = 0; i < SNMP_SYNTAX_UNKNOWN; i++) {
1171 if (strncmp(syntax_strings[i].str, str,
1172 strlen(syntax_strings[i].str)) == 0)
1173 return (syntax_strings[i].stx);
1176 return (SNMP_SYNTAX_NULL);
1180 snmp_parse_subindex(struct snmp_toolinfo *snmptoolctx, char *str,
1181 struct index *idx, struct snmp_object *object)
1185 enum snmp_syntax stx;
1186 char syntax[MAX_CMD_SYNTAX_LEN];
1189 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) {
1190 for (i = 0; i < MAX_CMD_SYNTAX_LEN ; i++) {
1191 if (*(ptr + i) == ':')
1195 if (i >= MAX_CMD_SYNTAX_LEN) {
1196 warnx("Unknown syntax in OID - %s", str);
1199 /* Expect a syntax string here. */
1200 if ((stx = parse_syntax(str)) <= SNMP_SYNTAX_NULL) {
1201 warnx("Invalid syntax - %s",syntax);
1205 if (stx != idx->syntax && !ISSET_ERRIGNORE(snmptoolctx)) {
1206 warnx("Syntax mismatch - %d expected, %d given",
1211 * That is where the suboid started + the syntax length + one
1212 * character for ':'.
1219 case SNMP_SYNTAX_INTEGER:
1220 return (snmp_int2asn_oid(ptr, &(object->val.var)));
1221 case SNMP_SYNTAX_OID:
1222 return (snmp_oid2asn_oid(snmptoolctx, ptr,
1223 &(object->val.var)));
1224 case SNMP_SYNTAX_IPADDRESS:
1225 return (snmp_ip2asn_oid(ptr, &(object->val.var)));
1226 case SNMP_SYNTAX_COUNTER:
1228 case SNMP_SYNTAX_GAUGE:
1230 case SNMP_SYNTAX_TIMETICKS:
1231 return (snmp_uint2asn_oid(ptr, &(object->val.var)));
1232 case SNMP_SYNTAX_COUNTER64:
1233 return (snmp_cnt64_2asn_oid(ptr, &(object->val.var)));
1234 case SNMP_SYNTAX_OCTETSTRING:
1235 return (snmp_tc2oid(idx->tc, ptr, &(object->val.var)));
1245 snmp_parse_index(struct snmp_toolinfo *snmptoolctx, char *str,
1246 struct snmp_object *object)
1251 if (object->info->table_idx == NULL)
1255 STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(object)), link) {
1256 if ((ptr = snmp_parse_subindex(snmptoolctx, str, temp, object))
1260 if (*ptr != ',' && *ptr != ']')
1265 if (ptr == NULL || *ptr != ']') {
1266 warnx("Mismatching index - %s", str);
1274 * Fill in the struct asn_oid member of snmp_value with suboids from input.
1275 * If an error occurs - print message on stderr and return (-1).
1276 * If all is ok - return the length of the oid.
1279 snmp_parse_numoid(char *argv, struct asn_oid *var)
1290 if (var->len == ASN_MAXOIDLEN) {
1291 warnx("Oid too long - %u", var->len);
1295 suboid = strtoul(str, &endptr, 10);
1296 if (suboid > ASN_MAXID) {
1297 warnx("Oid too long - %u", var->len);
1301 var->subs[var->len++] = suboid;
1303 } while ( *endptr == '.');
1305 if (*endptr != '\0') {
1306 warnx("Invalid oid string - %s", argv);
1313 /* Append a length 1 suboid to an asn_oid structure. */
1315 snmp_suboid_append(struct asn_oid *var, asn_subid_t suboid)
1320 if (var->len >= ASN_MAXOIDLEN) {
1321 warnx("Oid too long - %u", var->len);
1325 var->subs[var->len++] = suboid;
1330 /* Pop the last suboid from an asn_oid structure. */
1332 snmp_suboid_pop(struct asn_oid *var)
1342 suboid = var->subs[--(var->len)];
1343 var->subs[var->len] = 0;
1349 * Parse the command-line provided string into an OID - alocate memory for a new
1350 * snmp object, fill in its fields and insert it in the object list. A
1351 * (snmp_verify_inoid_f) function must be provided to validate the input string.
1354 snmp_object_add(struct snmp_toolinfo *snmptoolctx, snmp_verify_inoid_f func,
1357 struct snmp_object *obj;
1359 if (snmptoolctx == NULL)
1362 /* XXX-BZ does that chack make sense? */
1363 if (snmptoolctx->objects >= SNMP_MAX_BINDINGS) {
1364 warnx("Too many bindings in PDU - %u", snmptoolctx->objects + 1);
1368 if ((obj = calloc(1, sizeof(struct snmp_object))) == NULL) {
1369 syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
1373 if (func(snmptoolctx, obj, string) < 0) {
1374 warnx("Invalid OID - %s", string);
1379 snmptoolctx->objects++;
1380 SLIST_INSERT_HEAD(&snmptoolctx->snmp_objectlist, obj, link);
1385 /* Given an OID, find it in the object list and remove it. */
1387 snmp_object_remove(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid)
1389 struct snmp_object *temp;
1391 if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) {
1392 warnx("Object list already empty");
1397 SLIST_FOREACH(temp, &snmptoolctx->snmp_objectlist, link)
1398 if (asn_compare_oid(&(temp->val.var), oid) == 0)
1402 warnx("No such object in list");
1406 SLIST_REMOVE(&snmptoolctx->snmp_objectlist, temp, snmp_object, link);
1407 if (temp->val.syntax == SNMP_SYNTAX_OCTETSTRING &&
1408 temp->val.v.octetstring.octets != NULL)
1409 free(temp->val.v.octetstring.octets);
1416 snmp_object_freeall(struct snmp_toolinfo *snmptoolctx)
1418 struct snmp_object *o;
1420 while ((o = SLIST_FIRST(&snmptoolctx->snmp_objectlist)) != NULL) {
1421 SLIST_REMOVE_HEAD(&snmptoolctx->snmp_objectlist, link);
1423 if (o->val.syntax == SNMP_SYNTAX_OCTETSTRING &&
1424 o->val.v.octetstring.octets != NULL)
1425 free(o->val.v.octetstring.octets);
1430 /* Do all possible memory release before exit. */
1432 snmp_tool_freeall(struct snmp_toolinfo *snmptoolctx)
1434 if (snmp_client.chost != NULL) {
1435 free(snmp_client.chost);
1436 snmp_client.chost = NULL;
1439 if (snmp_client.cport != NULL) {
1440 free(snmp_client.cport);
1441 snmp_client.cport = NULL;
1444 snmp_mapping_free(snmptoolctx);
1445 free_filelist(snmptoolctx);
1446 snmp_object_freeall(snmptoolctx);
1448 if (snmptoolctx->passwd != NULL) {
1449 free(snmptoolctx->passwd);
1450 snmptoolctx->passwd = NULL;
1455 * Fill all variables from the object list into a PDU. (snmp_verify_vbind_f)
1456 * function should check whether the variable is consistent in this PDU
1457 * (e.g do not add non-leaf OIDs to a GET PDU, or OIDs with read access only to
1458 * a SET PDU) - might be NULL though. (snmp_add_vbind_f) function is the
1459 * function actually adds the variable to the PDU and must not be NULL.
1462 snmp_pdu_add_bindings(struct snmp_toolinfo *snmptoolctx,
1463 snmp_verify_vbind_f vfunc, snmp_add_vbind_f afunc,
1464 struct snmp_pdu *pdu, int32_t maxcount)
1466 int32_t nbindings, abind;
1467 struct snmp_object *obj;
1469 if (pdu == NULL || afunc == NULL)
1472 /* Return 0 in case of no more work todo. */
1473 if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist))
1476 if (maxcount < 0 || maxcount > SNMP_MAX_BINDINGS) {
1477 warnx("maxcount out of range: <0 || >SNMP_MAX_BINDINGS");
1482 SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) {
1483 if ((vfunc != NULL) && (vfunc(snmptoolctx, pdu, obj) < 0)) {
1487 if ((abind = afunc(pdu, obj)) < 0) {
1493 /* Do not put more varbindings than requested. */
1494 if (++nbindings >= maxcount)
1503 * Locate an object in the object list and set a corresponding error status.
1506 snmp_object_seterror(struct snmp_toolinfo *snmptoolctx,
1507 struct snmp_value *err_value, int32_t error_status)
1509 struct snmp_object *obj;
1511 if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist) || err_value == NULL)
1514 SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link)
1515 if (asn_compare_oid(&(err_value->var), &(obj->val.var)) == 0) {
1516 obj->error = error_status;
1524 * Check a PDU received in response to a SNMP_PDU_GET/SNMP_PDU_GETBULK request
1525 * but don't compare syntaxes - when sending a request PDU they must be null.
1526 * This is a (almost) complete copy of snmp_pdu_check() - with matching syntaxes
1527 * checks and some other checks skipped.
1530 snmp_parse_get_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1534 for (i = 0; i < req->nbindings; i++) {
1535 if (asn_compare_oid(&req->bindings[i].var,
1536 &resp->bindings[i].var) != 0) {
1537 warnx("Bad OID in response");
1541 if (snmp_client.version != SNMP_V1 && (resp->bindings[i].syntax
1542 == SNMP_SYNTAX_NOSUCHOBJECT || resp->bindings[i].syntax ==
1543 SNMP_SYNTAX_NOSUCHINSTANCE))
1551 snmp_parse_getbulk_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1555 if (req->error_status > (int32_t) resp->nbindings) {
1556 warnx("Bad number of bindings in response");
1560 for (N = 0; N < req->error_status; N++) {
1561 if (asn_is_suboid(&req->bindings[N].var,
1562 &resp->bindings[N].var) == 0)
1564 if (resp->bindings[N].syntax == SNMP_SYNTAX_ENDOFMIBVIEW)
1568 for (R = N , r = N; R < (int32_t) req->nbindings; R++) {
1569 for (M = 0; M < req->error_index && (r + M) <
1570 (int32_t) resp->nbindings; M++) {
1571 if (asn_is_suboid(&req->bindings[R].var,
1572 &resp->bindings[r + M].var) == 0)
1575 if (resp->bindings[r + M].syntax ==
1576 SNMP_SYNTAX_ENDOFMIBVIEW) {
1588 snmp_parse_getnext_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1592 for (i = 0; i < req->nbindings; i++) {
1593 if (asn_is_suboid(&req->bindings[i].var, &resp->bindings[i].var)
1597 if (resp->version != SNMP_V1 && resp->bindings[i].syntax ==
1598 SNMP_SYNTAX_ENDOFMIBVIEW)
1606 * Should be called to check a response to get/getnext/getbulk.
1609 snmp_parse_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1611 if (resp == NULL || req == NULL)
1614 if (resp->version != req->version) {
1615 warnx("Response has wrong version");
1619 if (resp->error_status == SNMP_ERR_NOSUCHNAME) {
1620 warnx("Error - No Such Name");
1624 if (resp->error_status != SNMP_ERR_NOERROR) {
1625 warnx("Error %d in response", resp->error_status);
1629 if (resp->nbindings != req->nbindings && req->type != SNMP_PDU_GETBULK){
1630 warnx("Bad number of bindings in response");
1634 switch (req->type) {
1636 return (snmp_parse_get_resp(resp,req));
1637 case SNMP_PDU_GETBULK:
1638 return (snmp_parse_getbulk_resp(resp,req));
1639 case SNMP_PDU_GETNEXT:
1640 return (snmp_parse_getnext_resp(resp,req));
1650 snmp_output_octetstring(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc,
1651 uint32_t len, uint8_t *octets)
1655 if (len == 0 || octets == NULL)
1658 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1659 fprintf(stdout, "%s : ",
1660 syntax_strings[SNMP_SYNTAX_OCTETSTRING].str);
1662 if ((buf = snmp_oct2tc(tc, len, (char *) octets)) != NULL) {
1663 fprintf(stdout, "%s", buf);
1669 snmp_output_octetindex(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc,
1670 struct asn_oid *oid)
1675 if ((s = malloc(oid->subs[0] + 1)) == NULL)
1676 syslog(LOG_ERR, "malloc failed - %s", strerror(errno));
1678 for (i = 0; i < oid->subs[0]; i++)
1679 s[i] = (u_char) (oid->subs[i + 1]);
1681 snmp_output_octetstring(snmptoolctx, tc, oid->subs[0], s);
1687 * Check and output syntax type and value.
1690 snmp_output_oid_value(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid)
1692 char oid_string[ASN_OIDSTRLEN];
1693 struct snmp_object obj;
1695 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1696 fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_OID].str);
1698 if(!ISSET_NUMERIC(snmptoolctx)) {
1699 memset(&obj, 0, sizeof(struct snmp_object));
1700 asn_append_oid(&(obj.val.var), oid);
1702 if (snmp_lookup_enumstring(snmptoolctx, &obj) > 0)
1703 fprintf(stdout, "%s" , obj.info->string);
1704 else if (snmp_lookup_oidstring(snmptoolctx, &obj) > 0)
1705 fprintf(stdout, "%s" , obj.info->string);
1706 else if (snmp_lookup_nodestring(snmptoolctx, &obj) > 0)
1707 fprintf(stdout, "%s" , obj.info->string);
1709 (void) asn_oid2str_r(oid, oid_string);
1710 fprintf(stdout, "%s", oid_string);
1713 (void) asn_oid2str_r(oid, oid_string);
1714 fprintf(stdout, "%s", oid_string);
1719 snmp_output_int(struct snmp_toolinfo *snmptoolctx, struct enum_pairs *enums,
1724 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1725 fprintf(stdout, "%s : ",
1726 syntax_strings[SNMP_SYNTAX_INTEGER].str);
1728 if (enums != NULL && (string = enum_string_lookup(enums, int_val))
1730 fprintf(stdout, "%s", string);
1732 fprintf(stdout, "%d", int_val);
1736 snmp_output_ipaddress(struct snmp_toolinfo *snmptoolctx, uint8_t *ip)
1738 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1739 fprintf(stdout, "%s : ",
1740 syntax_strings[SNMP_SYNTAX_IPADDRESS].str);
1742 fprintf(stdout, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1746 snmp_output_counter(struct snmp_toolinfo *snmptoolctx, uint32_t counter)
1748 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1749 fprintf(stdout, "%s : ",
1750 syntax_strings[SNMP_SYNTAX_COUNTER].str);
1752 fprintf(stdout, "%u", counter);
1756 snmp_output_gauge(struct snmp_toolinfo *snmptoolctx, uint32_t gauge)
1758 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1759 fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_GAUGE].str);
1761 fprintf(stdout, "%u", gauge);
1765 snmp_output_ticks(struct snmp_toolinfo *snmptoolctx, uint32_t ticks)
1767 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1768 fprintf(stdout, "%s : ",
1769 syntax_strings[SNMP_SYNTAX_TIMETICKS].str);
1771 fprintf(stdout, "%u", ticks);
1775 snmp_output_counter64(struct snmp_toolinfo *snmptoolctx, uint64_t counter64)
1777 if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1778 fprintf(stdout, "%s : ",
1779 syntax_strings[SNMP_SYNTAX_COUNTER64].str);
1781 fprintf(stdout,"%ju", counter64);
1785 snmp_output_numval(struct snmp_toolinfo *snmptoolctx, struct snmp_value *val,
1786 struct snmp_oid2str *entry)
1791 if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET)
1792 fprintf(stdout, " = ");
1794 switch (val->syntax) {
1795 case SNMP_SYNTAX_INTEGER:
1797 snmp_output_int(snmptoolctx, entry->snmp_enum,
1800 snmp_output_int(snmptoolctx, NULL, val->v.integer);
1803 case SNMP_SYNTAX_OCTETSTRING:
1805 snmp_output_octetstring(snmptoolctx, entry->tc,
1806 val->v.octetstring.len, val->v.octetstring.octets);
1808 snmp_output_octetstring(snmptoolctx, SNMP_STRING,
1809 val->v.octetstring.len, val->v.octetstring.octets);
1812 case SNMP_SYNTAX_OID:
1813 snmp_output_oid_value(snmptoolctx, &(val->v.oid));
1816 case SNMP_SYNTAX_IPADDRESS:
1817 snmp_output_ipaddress(snmptoolctx, val->v.ipaddress);
1820 case SNMP_SYNTAX_COUNTER:
1821 snmp_output_counter(snmptoolctx, val->v.uint32);
1824 case SNMP_SYNTAX_GAUGE:
1825 snmp_output_gauge(snmptoolctx, val->v.uint32);
1828 case SNMP_SYNTAX_TIMETICKS:
1829 snmp_output_ticks(snmptoolctx, val->v.uint32);
1832 case SNMP_SYNTAX_COUNTER64:
1833 snmp_output_counter64(snmptoolctx, val->v.counter64);
1836 case SNMP_SYNTAX_NOSUCHOBJECT:
1837 fprintf(stdout, "No Such Object\n");
1838 return (val->syntax);
1840 case SNMP_SYNTAX_NOSUCHINSTANCE:
1841 fprintf(stdout, "No Such Instance\n");
1842 return (val->syntax);
1844 case SNMP_SYNTAX_ENDOFMIBVIEW:
1845 fprintf(stdout, "End of Mib View\n");
1846 return (val->syntax);
1848 case SNMP_SYNTAX_NULL:
1850 fprintf(stdout, "agent returned NULL Syntax\n");
1851 return (val->syntax);
1854 /* NOTREACHED - If here - then all went completely wrong. */
1855 fprintf(stdout, "agent returned unknown syntax\n");
1859 fprintf(stdout, "\n");
1865 snmp_fill_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *obj,
1866 struct snmp_value *val)
1871 if (obj == NULL || val == NULL)
1874 if ((suboid = snmp_suboid_pop(&(val->var))) > ASN_MAXID)
1877 memset(obj, 0, sizeof(struct snmp_object));
1878 asn_append_oid(&(obj->val.var), &(val->var));
1879 obj->val.syntax = val->syntax;
1881 if (obj->val.syntax > 0)
1882 rc = snmp_lookup_leafstring(snmptoolctx, obj);
1884 rc = snmp_lookup_nonleaf_string(snmptoolctx, obj);
1886 (void) snmp_suboid_append(&(val->var), suboid);
1887 (void) snmp_suboid_append(&(obj->val.var), suboid);
1893 snmp_output_index(struct snmp_toolinfo *snmptoolctx, struct index *stx,
1894 struct asn_oid *oid)
1899 struct asn_oid temp, out;
1901 if (oid->len < bytes)
1904 memset(&temp, 0, sizeof(struct asn_oid));
1905 asn_append_oid(&temp, oid);
1907 switch (stx->syntax) {
1908 case SNMP_SYNTAX_INTEGER:
1909 snmp_output_int(snmptoolctx, stx->snmp_enum, temp.subs[0]);
1912 case SNMP_SYNTAX_OCTETSTRING:
1913 if ((temp.subs[0] > temp.len -1 ) || (temp.subs[0] >
1914 ASN_MAXOCTETSTRING))
1916 snmp_output_octetindex(snmptoolctx, stx->tc, &temp);
1917 bytes += temp.subs[0];
1920 case SNMP_SYNTAX_OID:
1921 if ((temp.subs[0] > temp.len -1) || (temp.subs[0] >
1925 bytes += temp.subs[0];
1926 memset(&out, 0, sizeof(struct asn_oid));
1927 asn_slice_oid(&out, &temp, 1, bytes);
1928 snmp_output_oid_value(snmptoolctx, &out);
1931 case SNMP_SYNTAX_IPADDRESS:
1934 for (bytes = 0; bytes < 4; bytes++)
1935 ip[bytes] = temp.subs[bytes];
1937 snmp_output_ipaddress(snmptoolctx, ip);
1941 case SNMP_SYNTAX_COUNTER:
1942 snmp_output_counter(snmptoolctx, temp.subs[0]);
1945 case SNMP_SYNTAX_GAUGE:
1946 snmp_output_gauge(snmptoolctx, temp.subs[0]);
1949 case SNMP_SYNTAX_TIMETICKS:
1950 snmp_output_ticks(snmptoolctx, temp.subs[0]);
1953 case SNMP_SYNTAX_COUNTER64:
1957 memcpy(&cnt64, temp.subs, bytes);
1958 snmp_output_counter64(snmptoolctx, cnt64);
1969 snmp_output_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *o)
1971 int32_t i, first, len;
1975 if (ISSET_NUMERIC(snmptoolctx))
1978 if (o->info->table_idx == NULL) {
1979 fprintf(stdout,"%s.%d", o->info->string,
1980 o->val.var.subs[o->val.var.len - 1]);
1984 fprintf(stdout,"%s[", o->info->string);
1985 memset(&oid, 0, sizeof(struct asn_oid));
1988 asn_slice_oid(&oid, &(o->val.var), (o->info->table_idx->var.len + len),
1992 STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(o)), link) {
1996 fprintf(stdout, ", ");
1997 if ((i = snmp_output_index(snmptoolctx, temp, &oid)) < 0)
2000 memset(&oid, 0, sizeof(struct asn_oid));
2001 asn_slice_oid(&oid, &(o->val.var),
2002 (o->info->table_idx->var.len + len), o->val.var.len + 1);
2005 fprintf(stdout,"]");
2010 snmp_output_err_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu)
2012 char buf[ASN_OIDSTRLEN];
2013 struct snmp_object object;
2015 if (pdu == NULL || (pdu->error_index > (int32_t) pdu->nbindings)) {
2016 fprintf(stdout,"Invalid error index in PDU\n");
2020 fprintf(stdout, "Agent %s:%s returned error \n", snmp_client.chost,
2023 if (!ISSET_NUMERIC(snmptoolctx) && (snmp_fill_object(snmptoolctx, &object,
2024 &(pdu->bindings[pdu->error_index - 1])) > 0))
2025 snmp_output_object(snmptoolctx, &object);
2027 asn_oid2str_r(&(pdu->bindings[pdu->error_index - 1].var), buf);
2028 fprintf(stdout,"%s", buf);
2031 fprintf(stdout," caused error - ");
2032 if ((pdu->error_status > 0) && (pdu->error_status <=
2033 SNMP_ERR_INCONS_NAME))
2034 fprintf(stdout, "%s\n", error_strings[pdu->error_status].str);
2036 fprintf(stdout,"%s\n", error_strings[SNMP_ERR_UNKNOWN].str);
2040 snmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu,
2041 struct asn_oid *root)
2044 char p[ASN_OIDSTRLEN];
2046 struct snmp_object object;
2049 while (i < pdu->nbindings) {
2050 if (root != NULL && !(asn_is_suboid(root,
2051 &(pdu->bindings[i].var))))
2054 if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) {
2055 if (!ISSET_NUMERIC(snmptoolctx) &&
2056 (snmp_fill_object(snmptoolctx, &object,
2057 &(pdu->bindings[i])) > 0))
2058 snmp_output_object(snmptoolctx, &object);
2060 asn_oid2str_r(&(pdu->bindings[i].var), p);
2061 fprintf(stdout, "%s", p);
2064 error |= snmp_output_numval(snmptoolctx, &(pdu->bindings[i]), object.info);
2075 snmp_output_engine(void)
2078 char *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
2081 for (i = 0; i < snmp_client.engine.engine_len; i++)
2082 cptr += sprintf(cptr, "%.2x", snmp_client.engine.engine_id[i]);
2085 fprintf(stdout, "Engine ID 0x%s\n", engine);
2086 fprintf(stdout, "Boots : %u\t\tTime : %d\n",
2087 snmp_client.engine.engine_boots,
2088 snmp_client.engine.engine_time);
2092 snmp_output_keys(void)
2094 uint32_t i, keylen = 0;
2095 char *cptr, extkey[2 * SNMP_AUTH_KEY_SIZ + 2];
2097 fprintf(stdout, "Localized keys for %s\n", snmp_client.user.sec_name);
2098 if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_MD5) {
2099 fprintf(stdout, "MD5 : 0x");
2100 keylen = SNMP_AUTH_HMACMD5_KEY_SIZ;
2101 } else if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_SHA) {
2102 fprintf(stdout, "SHA : 0x");
2103 keylen = SNMP_AUTH_HMACSHA_KEY_SIZ;
2105 if (snmp_client.user.auth_proto != SNMP_AUTH_NOAUTH) {
2107 for (i = 0; i < keylen; i++)
2108 cptr += sprintf(cptr, "%.2x",
2109 snmp_client.user.auth_key[i]);
2111 fprintf(stdout, "%s\n", extkey);
2114 if (snmp_client.user.priv_proto == SNMP_PRIV_DES) {
2115 fprintf(stdout, "DES : 0x");
2116 keylen = SNMP_PRIV_DES_KEY_SIZ;
2117 } else if (snmp_client.user.priv_proto == SNMP_PRIV_AES) {
2118 fprintf(stdout, "AES : 0x");
2119 keylen = SNMP_PRIV_AES_KEY_SIZ;
2121 if (snmp_client.user.priv_proto != SNMP_PRIV_NOPRIV) {
2123 for (i = 0; i < keylen; i++)
2124 cptr += sprintf(cptr, "%.2x",
2125 snmp_client.user.priv_key[i]);
2127 fprintf(stdout, "%s\n", extkey);