1a7398723SShteryana Shopova /*-
2a7398723SShteryana Shopova  * Copyright (c) 2005-2006 The FreeBSD Project
3a7398723SShteryana Shopova  * All rights reserved.
4a7398723SShteryana Shopova  *
5a7398723SShteryana Shopova  * Author: Shteryana Shopova <syrinx@FreeBSD.org>
6a7398723SShteryana Shopova  *
7a7398723SShteryana Shopova  * Redistribution of this software and documentation and use in source and
8a7398723SShteryana Shopova  * binary forms, with or without modification, are permitted provided that
9a7398723SShteryana Shopova  * the following conditions are met:
10a7398723SShteryana Shopova  *
11a7398723SShteryana Shopova  * 1. Redistributions of source code or documentation must retain the above
12a7398723SShteryana Shopova  *    copyright notice, this list of conditions and the following disclaimer.
13a7398723SShteryana Shopova  * 2. Redistributions in binary form must reproduce the above copyright
14a7398723SShteryana Shopova  *    notice, this list of conditions and the following disclaimer in the
15a7398723SShteryana Shopova  *    documentation and/or other materials provided with the distribution.
16a7398723SShteryana Shopova  *
17a7398723SShteryana Shopova  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18a7398723SShteryana Shopova  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19a7398723SShteryana Shopova  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20a7398723SShteryana Shopova  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21a7398723SShteryana Shopova  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22a7398723SShteryana Shopova  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23a7398723SShteryana Shopova  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a7398723SShteryana Shopova  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25a7398723SShteryana Shopova  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26a7398723SShteryana Shopova  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27a7398723SShteryana Shopova  * SUCH DAMAGE.
28a7398723SShteryana Shopova  *
29a7398723SShteryana Shopova  * Helper functions for snmp client tools
30a7398723SShteryana Shopova  */
31a7398723SShteryana Shopova 
32a7398723SShteryana Shopova #include <sys/param.h>
33a7398723SShteryana Shopova #include <sys/queue.h>
34a7398723SShteryana Shopova #include <sys/uio.h>
35a7398723SShteryana Shopova 
36a7398723SShteryana Shopova #include <assert.h>
37a7398723SShteryana Shopova #include <ctype.h>
38a7398723SShteryana Shopova #include <err.h>
39a7398723SShteryana Shopova #include <errno.h>
40a7398723SShteryana Shopova #include <fcntl.h>
41a7398723SShteryana Shopova #include <stdio.h>
42a7398723SShteryana Shopova #include <stdlib.h>
43a7398723SShteryana Shopova #include <string.h>
44a7398723SShteryana Shopova #include <syslog.h>
45a7398723SShteryana Shopova #include <unistd.h>
46a7398723SShteryana Shopova 
47a7398723SShteryana Shopova #include <bsnmp/asn1.h>
48a7398723SShteryana Shopova #include <bsnmp/snmp.h>
49a7398723SShteryana Shopova #include <bsnmp/snmpclient.h>
50a7398723SShteryana Shopova #include "bsnmptc.h"
51a7398723SShteryana Shopova #include "bsnmptools.h"
52a7398723SShteryana Shopova 
538b223768SElyes Haouas /* Internal variable to turn on library debugging for testing and to
54a7398723SShteryana Shopova  * find bugs. It is not exported via the header file.
55a7398723SShteryana Shopova  * XXX should we cover it by some #ifdef BSNMPTOOLS_DEBUG? */
56a7398723SShteryana Shopova int _bsnmptools_debug = 0;
57a7398723SShteryana Shopova 
58a7398723SShteryana Shopova /* Default files to import mapping from if none explicitly provided. */
59a7398723SShteryana Shopova #define	bsnmpd_defs		"/usr/share/snmp/defs/tree.def"
60a7398723SShteryana Shopova #define	mibII_defs		"/usr/share/snmp/defs/mibII_tree.def"
61a7398723SShteryana Shopova 
62a7398723SShteryana Shopova /*
63a7398723SShteryana Shopova  * The .iso.org.dod oid that has to be prepended to every OID when requesting
64a7398723SShteryana Shopova  * a value.
65a7398723SShteryana Shopova  */
66a7398723SShteryana Shopova const struct asn_oid IsoOrgDod_OID = {
67a7398723SShteryana Shopova 	3, { 1, 3, 6 }
68a7398723SShteryana Shopova };
69a7398723SShteryana Shopova 
70a7398723SShteryana Shopova 
71a7398723SShteryana Shopova #define	SNMP_ERR_UNKNOWN	0
72a7398723SShteryana Shopova 
73a7398723SShteryana Shopova /*
74a7398723SShteryana Shopova  * An array of error strings corresponding to error definitions from libbsnmp.
75a7398723SShteryana Shopova  */
76a7398723SShteryana Shopova static const struct {
77a7398723SShteryana Shopova 	const char *str;
78a7398723SShteryana Shopova 	int32_t error;
79a7398723SShteryana Shopova } error_strings[] = {
80a7398723SShteryana Shopova 	{ "Unknown", SNMP_ERR_UNKNOWN },
81a7398723SShteryana Shopova 	{ "Too big ", SNMP_ERR_TOOBIG },
82a7398723SShteryana Shopova 	{ "No such Name", SNMP_ERR_NOSUCHNAME },
83a7398723SShteryana Shopova 	{ "Bad Value", SNMP_ERR_BADVALUE },
84a7398723SShteryana Shopova 	{ "Readonly", SNMP_ERR_READONLY },
85a7398723SShteryana Shopova 	{ "General error", SNMP_ERR_GENERR },
86a7398723SShteryana Shopova 	{ "No access", SNMP_ERR_NO_ACCESS },
87a7398723SShteryana Shopova 	{ "Wrong type", SNMP_ERR_WRONG_TYPE },
883df5ecacSUlrich Spörlein 	{ "Wrong length", SNMP_ERR_WRONG_LENGTH },
89a7398723SShteryana Shopova 	{ "Wrong encoding", SNMP_ERR_WRONG_ENCODING },
90a7398723SShteryana Shopova 	{ "Wrong value", SNMP_ERR_WRONG_VALUE },
91a7398723SShteryana Shopova 	{ "No creation", SNMP_ERR_NO_CREATION },
92a7398723SShteryana Shopova 	{ "Inconsistent value", SNMP_ERR_INCONS_VALUE },
93a7398723SShteryana Shopova 	{ "Resource unavailable", SNMP_ERR_RES_UNAVAIL },
94a7398723SShteryana Shopova 	{ "Commit failed", SNMP_ERR_COMMIT_FAILED },
95a7398723SShteryana Shopova 	{ "Undo failed", SNMP_ERR_UNDO_FAILED },
96a7398723SShteryana Shopova 	{ "Authorization error", SNMP_ERR_AUTH_ERR },
97a7398723SShteryana Shopova 	{ "Not writable", SNMP_ERR_NOT_WRITEABLE },
98a7398723SShteryana Shopova 	{ "Inconsistent name", SNMP_ERR_INCONS_NAME },
99a7398723SShteryana Shopova 	{ NULL, 0 }
100a7398723SShteryana Shopova };
101a7398723SShteryana Shopova 
102a7398723SShteryana Shopova /* This one and any following are exceptions. */
103a7398723SShteryana Shopova #define	SNMP_SYNTAX_UNKNOWN	SNMP_SYNTAX_NOSUCHOBJECT
104a7398723SShteryana Shopova 
105a7398723SShteryana Shopova static const struct {
106a7398723SShteryana Shopova 	const char *str;
107a7398723SShteryana Shopova 	enum snmp_syntax stx;
108a7398723SShteryana Shopova } syntax_strings[] = {
109a7398723SShteryana Shopova 	{ "Null", SNMP_SYNTAX_NULL },
110a7398723SShteryana Shopova 	{ "Integer", SNMP_SYNTAX_INTEGER },
111a7398723SShteryana Shopova 	{ "OctetString", SNMP_SYNTAX_OCTETSTRING },
112a7398723SShteryana Shopova 	{ "OID", SNMP_SYNTAX_OID },
113a7398723SShteryana Shopova 	{ "IpAddress", SNMP_SYNTAX_IPADDRESS },
114a7398723SShteryana Shopova 	{ "Counter32", SNMP_SYNTAX_COUNTER },
115a7398723SShteryana Shopova 	{ "Gauge", SNMP_SYNTAX_GAUGE },
116a7398723SShteryana Shopova 	{ "TimeTicks", SNMP_SYNTAX_TIMETICKS },
117a7398723SShteryana Shopova 	{ "Counter64", SNMP_SYNTAX_COUNTER64 },
118a7398723SShteryana Shopova 	{ "Unknown", SNMP_SYNTAX_UNKNOWN },
119a7398723SShteryana Shopova };
120a7398723SShteryana Shopova 
121a7398723SShteryana Shopova int
snmptool_init(struct snmp_toolinfo * snmptoolctx)122a7398723SShteryana Shopova snmptool_init(struct snmp_toolinfo *snmptoolctx)
123a7398723SShteryana Shopova {
124a7398723SShteryana Shopova 	char *str;
125a7398723SShteryana Shopova 	size_t slen;
126a7398723SShteryana Shopova 
127a7398723SShteryana Shopova 	memset(snmptoolctx, 0, sizeof(struct snmp_toolinfo));
128a7398723SShteryana Shopova 	snmptoolctx->objects = 0;
129a7398723SShteryana Shopova 	snmptoolctx->mappings = NULL;
130a7398723SShteryana Shopova 	snmptoolctx->flags = SNMP_PDU_GET;	/* XXX */
131a7398723SShteryana Shopova 	SLIST_INIT(&snmptoolctx->filelist);
132a7398723SShteryana Shopova 	snmp_client_init(&snmp_client);
133b9288caaSShteryana Shopova 	SET_MAXREP(snmptoolctx, SNMP_MAX_REPETITIONS);
134a7398723SShteryana Shopova 
135a7398723SShteryana Shopova 	if (add_filename(snmptoolctx, bsnmpd_defs, &IsoOrgDod_OID, 0) < 0)
136a7398723SShteryana Shopova 		warnx("Error adding file %s to list", bsnmpd_defs);
137a7398723SShteryana Shopova 
138a7398723SShteryana Shopova 	if (add_filename(snmptoolctx, mibII_defs, &IsoOrgDod_OID, 0) < 0)
139a7398723SShteryana Shopova 		warnx("Error adding file %s to list", mibII_defs);
140a7398723SShteryana Shopova 
141a7398723SShteryana Shopova 	/* Read the environment */
142a7398723SShteryana Shopova 	if ((str = getenv("SNMPAUTH")) != NULL) {
143a7398723SShteryana Shopova 		slen = strlen(str);
144a7398723SShteryana Shopova 		if (slen == strlen("md5") && strcasecmp(str, "md5") == 0)
145a7398723SShteryana Shopova 			snmp_client.user.auth_proto = SNMP_AUTH_HMAC_MD5;
146a7398723SShteryana Shopova 		else if (slen == strlen("sha")&& strcasecmp(str, "sha") == 0)
147a7398723SShteryana Shopova 			snmp_client.user.auth_proto = SNMP_AUTH_HMAC_SHA;
148a7398723SShteryana Shopova 		else if (slen != 0)
149a7398723SShteryana Shopova 			warnx("Bad authentication type - %s in SNMPAUTH", str);
150a7398723SShteryana Shopova 	}
151a7398723SShteryana Shopova 
152a7398723SShteryana Shopova 	if ((str = getenv("SNMPPRIV")) != NULL) {
153a7398723SShteryana Shopova 		slen = strlen(str);
154a7398723SShteryana Shopova 		if (slen == strlen("des") && strcasecmp(str, "des") == 0)
155a7398723SShteryana Shopova 			snmp_client.user.priv_proto = SNMP_PRIV_DES;
156a7398723SShteryana Shopova 		else if (slen == strlen("aes")&& strcasecmp(str, "aes") == 0)
157a7398723SShteryana Shopova 			snmp_client.user.priv_proto = SNMP_PRIV_AES;
158a7398723SShteryana Shopova 		else if (slen != 0)
159a7398723SShteryana Shopova 			warnx("Bad privacy type - %s in SNMPPRIV", str);
160a7398723SShteryana Shopova 	}
161a7398723SShteryana Shopova 
162a7398723SShteryana Shopova 	if ((str = getenv("SNMPUSER")) != NULL) {
163a7398723SShteryana Shopova 		if ((slen = strlen(str)) > sizeof(snmp_client.user.sec_name)) {
164a7398723SShteryana Shopova 			warnx("Username too long - %s in SNMPUSER", str);
165a7398723SShteryana Shopova 			return (-1);
166a7398723SShteryana Shopova 		}
167a7398723SShteryana Shopova 		if (slen > 0) {
168a7398723SShteryana Shopova 			strlcpy(snmp_client.user.sec_name, str,
169a7398723SShteryana Shopova 			    sizeof(snmp_client.user.sec_name));
170a7398723SShteryana Shopova 			snmp_client.version = SNMP_V3;
171a7398723SShteryana Shopova 		}
172a7398723SShteryana Shopova 	}
173a7398723SShteryana Shopova 
174a7398723SShteryana Shopova 	if ((str = getenv("SNMPPASSWD")) != NULL) {
175a7398723SShteryana Shopova 		if ((slen = strlen(str)) > MAXSTR)
176a7398723SShteryana Shopova 			slen = MAXSTR - 1;
177a7398723SShteryana Shopova 		if ((snmptoolctx->passwd = malloc(slen + 1)) == NULL) {
1787c933da6SEnji Cooper 			warn("malloc() failed");
179a7398723SShteryana Shopova 			return (-1);
180a7398723SShteryana Shopova 		}
181a7398723SShteryana Shopova 		if (slen > 0)
182a7398723SShteryana Shopova 			strlcpy(snmptoolctx->passwd, str, slen + 1);
183a7398723SShteryana Shopova 	}
184a7398723SShteryana Shopova 
185a7398723SShteryana Shopova 	return (0);
186a7398723SShteryana Shopova }
187a7398723SShteryana Shopova 
188a7398723SShteryana Shopova #define	OBJECT_IDX_LIST(o)	o->info->table_idx->index_list
189a7398723SShteryana Shopova 
190a7398723SShteryana Shopova /*
191a7398723SShteryana Shopova  * Walk through the file list and import string<->oid mappings from each file.
192a7398723SShteryana Shopova  */
193a7398723SShteryana Shopova int32_t
snmp_import_all(struct snmp_toolinfo * snmptoolctx)194a7398723SShteryana Shopova snmp_import_all(struct snmp_toolinfo *snmptoolctx)
195a7398723SShteryana Shopova {
196a7398723SShteryana Shopova 	int32_t fc;
197a7398723SShteryana Shopova 	struct fname *tmp;
198a7398723SShteryana Shopova 
199a7398723SShteryana Shopova 	if (snmptoolctx == NULL)
200a7398723SShteryana Shopova 		return (-1);
201a7398723SShteryana Shopova 
202a7398723SShteryana Shopova 	if (ISSET_NUMERIC(snmptoolctx))
203a7398723SShteryana Shopova 		return (0);
204a7398723SShteryana Shopova 
205a7398723SShteryana Shopova 	if ((snmptoolctx->mappings = snmp_mapping_init()) == NULL)
206a7398723SShteryana Shopova 		return (-1);
207a7398723SShteryana Shopova 
208a7398723SShteryana Shopova 	fc = 0;
209a7398723SShteryana Shopova 	if (SLIST_EMPTY(&snmptoolctx->filelist)) {
210a7398723SShteryana Shopova 		warnx("No files to read OID <-> string conversions from");
211a7398723SShteryana Shopova 		return (-1);
212a7398723SShteryana Shopova 	} else {
213a7398723SShteryana Shopova 		SLIST_FOREACH(tmp, &snmptoolctx->filelist, link) {
214a7398723SShteryana Shopova 			if (tmp->done)
215a7398723SShteryana Shopova 				continue;
216a7398723SShteryana Shopova 			if (snmp_import_file(snmptoolctx, tmp) < 0) {
217a7398723SShteryana Shopova 				fc = -1;
218a7398723SShteryana Shopova 				break;
219a7398723SShteryana Shopova 			}
220a7398723SShteryana Shopova 			fc++;
221a7398723SShteryana Shopova 		}
222a7398723SShteryana Shopova 	}
223a7398723SShteryana Shopova 
224a7398723SShteryana Shopova 	snmp_mapping_dump(snmptoolctx);
225a7398723SShteryana Shopova 	return (fc);
226a7398723SShteryana Shopova }
227a7398723SShteryana Shopova 
228a7398723SShteryana Shopova /*
2293df5ecacSUlrich Spörlein  * Add a filename to the file list - the initial idea of keeping a list with all
230a7398723SShteryana Shopova  * files to read OIDs from was that an application might want to have loaded in
231a7398723SShteryana Shopova  * memory the OIDs from a single file only and when done with them read the OIDs
232a7398723SShteryana Shopova  * from another file. This is not used yet but might be a good idea at some
233a7398723SShteryana Shopova  * point. Size argument is number of bytes in string including trailing '\0',
2343df5ecacSUlrich Spörlein  * not string length.
235a7398723SShteryana Shopova  */
236a7398723SShteryana Shopova int32_t
add_filename(struct snmp_toolinfo * snmptoolctx,const char * filename,const struct asn_oid * cut,int32_t done)237a7398723SShteryana Shopova add_filename(struct snmp_toolinfo *snmptoolctx, const char *filename,
238a7398723SShteryana Shopova     const struct asn_oid *cut, int32_t done)
239a7398723SShteryana Shopova {
240a7398723SShteryana Shopova 	char *fstring;
241a7398723SShteryana Shopova 	struct fname *entry;
242a7398723SShteryana Shopova 
243a7398723SShteryana Shopova 	if (snmptoolctx == NULL)
244a7398723SShteryana Shopova 		return (-1);
245a7398723SShteryana Shopova 
246a7398723SShteryana Shopova 	/* Make sure file was not in list. */
247a7398723SShteryana Shopova 	SLIST_FOREACH(entry, &snmptoolctx->filelist, link) {
248a7398723SShteryana Shopova 		if (strncmp(entry->name, filename, strlen(entry->name)) == 0)
249a7398723SShteryana Shopova 			return (0);
250a7398723SShteryana Shopova 	}
251a7398723SShteryana Shopova 
25225014372SEnji Cooper 	if ((fstring = strdup(filename)) == NULL) {
2537c933da6SEnji Cooper 		warn("strdup() failed");
254a7398723SShteryana Shopova 		return (-1);
255a7398723SShteryana Shopova 	}
256a7398723SShteryana Shopova 
257031987d9SEnji Cooper 	if ((entry = calloc(1, sizeof(struct fname))) == NULL) {
2587c933da6SEnji Cooper 		warn("calloc() failed");
259a7398723SShteryana Shopova 		free(fstring);
260a7398723SShteryana Shopova 		return (-1);
261a7398723SShteryana Shopova 	}
262a7398723SShteryana Shopova 
263a7398723SShteryana Shopova 	if (cut != NULL)
264a7398723SShteryana Shopova 		asn_append_oid(&(entry->cut), cut);
265a7398723SShteryana Shopova 	entry->name = fstring;
266a7398723SShteryana Shopova 	entry->done = done;
267a7398723SShteryana Shopova 	SLIST_INSERT_HEAD(&snmptoolctx->filelist, entry, link);
268a7398723SShteryana Shopova 
269a7398723SShteryana Shopova 	return (1);
270a7398723SShteryana Shopova }
271a7398723SShteryana Shopova 
272a7398723SShteryana Shopova void
free_filelist(struct snmp_toolinfo * snmptoolctx)273a7398723SShteryana Shopova free_filelist(struct snmp_toolinfo *snmptoolctx)
274a7398723SShteryana Shopova {
275a7398723SShteryana Shopova 	struct fname *f;
276a7398723SShteryana Shopova 
277a7398723SShteryana Shopova 	if (snmptoolctx == NULL)
278a7398723SShteryana Shopova 		return; /* XXX error handling */
279a7398723SShteryana Shopova 
280a7398723SShteryana Shopova 	while ((f = SLIST_FIRST(&snmptoolctx->filelist)) != NULL) {
281a7398723SShteryana Shopova 		SLIST_REMOVE_HEAD(&snmptoolctx->filelist, link);
282a7398723SShteryana Shopova 		if (f->name)
283a7398723SShteryana Shopova 			free(f->name);
284a7398723SShteryana Shopova 		free(f);
285a7398723SShteryana Shopova 	}
286a7398723SShteryana Shopova }
287a7398723SShteryana Shopova 
288a7398723SShteryana Shopova static char
isvalid_fchar(char c,int pos)289a7398723SShteryana Shopova isvalid_fchar(char c, int pos)
290a7398723SShteryana Shopova {
291a7398723SShteryana Shopova 	if (isalpha(c)|| c == '/'|| c == '_' || c == '.' || c == '~' ||
292a7398723SShteryana Shopova 	    (pos != 0 && isdigit(c))){
293a7398723SShteryana Shopova 		return (c);
294a7398723SShteryana Shopova 	}
295a7398723SShteryana Shopova 
296a7398723SShteryana Shopova 	if (c == '\0')
297a7398723SShteryana Shopova 		return (0);
298a7398723SShteryana Shopova 
299a7398723SShteryana Shopova 	if (!isascii(c) || !isprint(c))
300a7398723SShteryana Shopova 		warnx("Unexpected character %#2x", (u_int) c);
301a7398723SShteryana Shopova 	else
302a7398723SShteryana Shopova 		warnx("Illegal character '%c'", c);
303a7398723SShteryana Shopova 
304a7398723SShteryana Shopova 	return (-1);
305a7398723SShteryana Shopova }
306a7398723SShteryana Shopova 
307a7398723SShteryana Shopova /*
308a7398723SShteryana Shopova  * Re-implement getsubopt from scratch, because the second argument is broken
309a7398723SShteryana Shopova  * and will not compile with WARNS=5.
310a7398723SShteryana Shopova  * Copied from src/contrib/bsnmp/snmpd/main.c.
311a7398723SShteryana Shopova  */
312a7398723SShteryana Shopova static int
getsubopt1(char ** arg,const char * const * options,char ** valp,char ** optp)313a7398723SShteryana Shopova getsubopt1(char **arg, const char *const *options, char **valp, char **optp)
314a7398723SShteryana Shopova {
315a7398723SShteryana Shopova 	static const char *const delim = ",\t ";
316a7398723SShteryana Shopova 	u_int i;
317a7398723SShteryana Shopova 	char *ptr;
318a7398723SShteryana Shopova 
319a7398723SShteryana Shopova 	*optp = NULL;
320a7398723SShteryana Shopova 
321a7398723SShteryana Shopova 	/* Skip leading junk. */
322a7398723SShteryana Shopova 	for (ptr = *arg; *ptr != '\0'; ptr++)
323a7398723SShteryana Shopova 		if (strchr(delim, *ptr) == NULL)
324a7398723SShteryana Shopova 			break;
325a7398723SShteryana Shopova 	if (*ptr == '\0') {
326a7398723SShteryana Shopova 		*arg = ptr;
327a7398723SShteryana Shopova 		return (-1);
328a7398723SShteryana Shopova 	}
329a7398723SShteryana Shopova 	*optp = ptr;
330a7398723SShteryana Shopova 
331a7398723SShteryana Shopova 	/* Find the end of the option. */
332a7398723SShteryana Shopova 	while (*++ptr != '\0')
333a7398723SShteryana Shopova 		if (strchr(delim, *ptr) != NULL || *ptr == '=')
334a7398723SShteryana Shopova 			break;
335a7398723SShteryana Shopova 
336a7398723SShteryana Shopova 	if (*ptr != '\0') {
337a7398723SShteryana Shopova 		if (*ptr == '=') {
338a7398723SShteryana Shopova 			*ptr++ = '\0';
339a7398723SShteryana Shopova 			*valp = ptr;
340a7398723SShteryana Shopova 			while (*ptr != '\0' && strchr(delim, *ptr) == NULL)
341a7398723SShteryana Shopova 				ptr++;
342a7398723SShteryana Shopova 			if (*ptr != '\0')
343a7398723SShteryana Shopova 				*ptr++ = '\0';
344a7398723SShteryana Shopova 		} else
345a7398723SShteryana Shopova 			*ptr++ = '\0';
346a7398723SShteryana Shopova 	}
347a7398723SShteryana Shopova 
348a7398723SShteryana Shopova 	*arg = ptr;
349a7398723SShteryana Shopova 
350a7398723SShteryana Shopova 	for (i = 0; *options != NULL; options++, i++)
351a7398723SShteryana Shopova 		if (strcmp(*optp, *options) == 0)
352a7398723SShteryana Shopova 			return (i);
353a7398723SShteryana Shopova 	return (-1);
354a7398723SShteryana Shopova }
355a7398723SShteryana Shopova 
356a7398723SShteryana Shopova static int32_t
parse_path(char * value)357a7398723SShteryana Shopova parse_path(char *value)
358a7398723SShteryana Shopova {
359a7398723SShteryana Shopova 	int32_t i, len;
360a7398723SShteryana Shopova 
361a7398723SShteryana Shopova 	if (value == NULL)
362a7398723SShteryana Shopova 		return (-1);
363a7398723SShteryana Shopova 
364a7398723SShteryana Shopova 	for (len = 0; len < MAXPATHLEN; len++) {
365a7398723SShteryana Shopova 		i = isvalid_fchar(*(value + len), len) ;
366a7398723SShteryana Shopova 
367a7398723SShteryana Shopova 		if (i == 0)
368a7398723SShteryana Shopova 			break;
369a7398723SShteryana Shopova 		else if (i < 0)
370a7398723SShteryana Shopova 			return (-1);
371a7398723SShteryana Shopova 	}
372a7398723SShteryana Shopova 
373a7398723SShteryana Shopova 	if (len >= MAXPATHLEN || value[len] != '\0') {
374a7398723SShteryana Shopova 		warnx("Bad pathname - '%s'", value);
375a7398723SShteryana Shopova 		return (-1);
376a7398723SShteryana Shopova 	}
377a7398723SShteryana Shopova 
378a7398723SShteryana Shopova 	return (len);
379a7398723SShteryana Shopova }
380a7398723SShteryana Shopova 
381a7398723SShteryana Shopova static int32_t
parse_flist(struct snmp_toolinfo * snmptoolctx,char * value,char * path,const struct asn_oid * cut)382a7398723SShteryana Shopova parse_flist(struct snmp_toolinfo *snmptoolctx, char *value, char *path,
383a7398723SShteryana Shopova     const struct asn_oid *cut)
384a7398723SShteryana Shopova {
385a7398723SShteryana Shopova 	int32_t namelen;
386a7398723SShteryana Shopova 	char filename[MAXPATHLEN + 1];
387a7398723SShteryana Shopova 
388a7398723SShteryana Shopova 	if (value == NULL)
389a7398723SShteryana Shopova 		return (-1);
390a7398723SShteryana Shopova 
391a7398723SShteryana Shopova 	do {
392a7398723SShteryana Shopova 		memset(filename, 0, MAXPATHLEN + 1);
393a7398723SShteryana Shopova 
394a7398723SShteryana Shopova 		if (isalpha(*value) && (path == NULL || path[0] == '\0')) {
395a7398723SShteryana Shopova 			strlcpy(filename, SNMP_DEFS_DIR, MAXPATHLEN + 1);
396a7398723SShteryana Shopova 			namelen = strlen(SNMP_DEFS_DIR);
397a7398723SShteryana Shopova 		} else if (path != NULL){
398a7398723SShteryana Shopova 			strlcpy(filename, path, MAXPATHLEN + 1);
399a7398723SShteryana Shopova 			namelen = strlen(path);
400a7398723SShteryana Shopova 		} else
401a7398723SShteryana Shopova 			namelen = 0;
402a7398723SShteryana Shopova 
403a7398723SShteryana Shopova 		for ( ; namelen < MAXPATHLEN; value++) {
404a7398723SShteryana Shopova 			if (isvalid_fchar(*value, namelen) > 0) {
405a7398723SShteryana Shopova 				filename[namelen++] = *value;
406a7398723SShteryana Shopova 				continue;
407a7398723SShteryana Shopova 			}
408a7398723SShteryana Shopova 
409a7398723SShteryana Shopova 			if (*value == ',' )
410a7398723SShteryana Shopova 				value++;
411a7398723SShteryana Shopova 			else if (*value == '\0')
412a7398723SShteryana Shopova 				;
413a7398723SShteryana Shopova 			else {
414a7398723SShteryana Shopova 				if (!isascii(*value) || !isprint(*value))
415a7398723SShteryana Shopova 					warnx("Unexpected character %#2x in"
416a7398723SShteryana Shopova 					    " filename", (u_int) *value);
417a7398723SShteryana Shopova 				else
418a7398723SShteryana Shopova 					warnx("Illegal character '%c' in"
419a7398723SShteryana Shopova 					    " filename", *value);
420a7398723SShteryana Shopova 				return (-1);
421a7398723SShteryana Shopova 			}
422a7398723SShteryana Shopova 
423a7398723SShteryana Shopova 			filename[namelen]='\0';
424a7398723SShteryana Shopova 			break;
425a7398723SShteryana Shopova 		}
426a7398723SShteryana Shopova 
427a7398723SShteryana Shopova 		if ((namelen == MAXPATHLEN) && (filename[MAXPATHLEN] != '\0')) {
428a7398723SShteryana Shopova 			warnx("Filename %s too long", filename);
429a7398723SShteryana Shopova 			return (-1);
430a7398723SShteryana Shopova 		}
431a7398723SShteryana Shopova 
432a7398723SShteryana Shopova 		if (add_filename(snmptoolctx, filename, cut, 0) < 0) {
433a7398723SShteryana Shopova 			warnx("Error adding file %s to list", filename);
434a7398723SShteryana Shopova 			return (-1);
435a7398723SShteryana Shopova 		}
436a7398723SShteryana Shopova 	} while (*value != '\0');
437a7398723SShteryana Shopova 
438a7398723SShteryana Shopova 	return(1);
439a7398723SShteryana Shopova }
440a7398723SShteryana Shopova 
441a7398723SShteryana Shopova static int32_t
parse_ascii(char * ascii,uint8_t * binstr,size_t binlen)442a7398723SShteryana Shopova parse_ascii(char *ascii, uint8_t *binstr, size_t binlen)
443a7398723SShteryana Shopova {
444a7398723SShteryana Shopova 	char dptr[3];
4454a8c12cdSEnji Cooper 	size_t count;
4464a8c12cdSEnji Cooper 	int32_t alen, i, saved_errno;
4479a3ebeefSEnji Cooper 	uint32_t val;
448a7398723SShteryana Shopova 
4493df5ecacSUlrich Spörlein 	/* Filter 0x at the beginning */
450a7398723SShteryana Shopova 	if ((alen = strlen(ascii)) > 2 && ascii[0] == '0' && ascii[1] == 'x')
451a7398723SShteryana Shopova 		i = 2;
452a7398723SShteryana Shopova 	else
453a7398723SShteryana Shopova 		i = 0;
454a7398723SShteryana Shopova 
455a7398723SShteryana Shopova 	saved_errno = errno;
456a7398723SShteryana Shopova 	errno = 0;
457a7398723SShteryana Shopova 	for (count = 0; i < alen; i += 2) {
458a7398723SShteryana Shopova 		/* XXX: consider strlen(ascii) % 2 != 0 */
459a7398723SShteryana Shopova 		dptr[0] = ascii[i];
460a7398723SShteryana Shopova 		dptr[1] = ascii[i + 1];
461a7398723SShteryana Shopova 		dptr[2] = '\0';
462a7398723SShteryana Shopova 		if ((val = strtoul(dptr, NULL, 16)) > 0xFF || errno != 0) {
463a7398723SShteryana Shopova 			errno = saved_errno;
464a7398723SShteryana Shopova 			return (-1);
465a7398723SShteryana Shopova 		}
466a7398723SShteryana Shopova 		binstr[count] = (uint8_t) val;
467a7398723SShteryana Shopova 		if (++count >= binlen) {
4683df5ecacSUlrich Spörlein 			warnx("Key %s too long - truncating to %zu octets",
469a7398723SShteryana Shopova 			    ascii, binlen);
470a7398723SShteryana Shopova 			break;
471a7398723SShteryana Shopova 		}
472a7398723SShteryana Shopova 	}
473a7398723SShteryana Shopova 
474a7398723SShteryana Shopova 	return (count);
475a7398723SShteryana Shopova }
476a7398723SShteryana Shopova 
477a7398723SShteryana Shopova /*
478a7398723SShteryana Shopova  * Functions to parse common input options for client tools and fill in the
479a7398723SShteryana Shopova  * snmp_client structure.
480a7398723SShteryana Shopova  */
481a7398723SShteryana Shopova int32_t
parse_authentication(struct snmp_toolinfo * snmptoolctx __unused,char * opt_arg)482444991f1SEnji Cooper parse_authentication(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
483a7398723SShteryana Shopova {
484eca9714eSJohn Baldwin 	int32_t /* count, */ subopt;
485a7398723SShteryana Shopova 	char *val, *option;
486a7398723SShteryana Shopova 	const char *const subopts[] = {
487a7398723SShteryana Shopova 		"proto",
488a7398723SShteryana Shopova 		"key",
489a7398723SShteryana Shopova 		NULL
490a7398723SShteryana Shopova 	};
491a7398723SShteryana Shopova 
492a7398723SShteryana Shopova 	assert(opt_arg != NULL);
493eca9714eSJohn Baldwin 	/* count = 1; */
494a7398723SShteryana Shopova 	while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
495a7398723SShteryana Shopova 		switch (subopt) {
496a7398723SShteryana Shopova 		case 0:
497a7398723SShteryana Shopova 			if (val == NULL) {
498a7398723SShteryana Shopova 				warnx("Suboption 'proto' requires an argument");
499a7398723SShteryana Shopova 				return (-1);
500a7398723SShteryana Shopova 			}
501a7398723SShteryana Shopova 			if (strlen(val) != 3) {
502a7398723SShteryana Shopova 				warnx("Unknown auth protocol - %s", val);
503a7398723SShteryana Shopova 				return (-1);
504a7398723SShteryana Shopova 			}
505a7398723SShteryana Shopova 			if (strncasecmp("md5", val, strlen("md5")) == 0)
506a7398723SShteryana Shopova 				snmp_client.user.auth_proto =
507a7398723SShteryana Shopova 				    SNMP_AUTH_HMAC_MD5;
508a7398723SShteryana Shopova 			else if (strncasecmp("sha", val, strlen("sha")) == 0)
509a7398723SShteryana Shopova 				snmp_client.user.auth_proto =
510a7398723SShteryana Shopova 				    SNMP_AUTH_HMAC_SHA;
511a7398723SShteryana Shopova 			else {
512a7398723SShteryana Shopova 				warnx("Unknown auth protocol - %s", val);
513a7398723SShteryana Shopova 				return (-1);
514a7398723SShteryana Shopova 			}
515a7398723SShteryana Shopova 			break;
516a7398723SShteryana Shopova 		case 1:
517a7398723SShteryana Shopova 			if (val == NULL) {
518a7398723SShteryana Shopova 				warnx("Suboption 'key' requires an argument");
519a7398723SShteryana Shopova 				return (-1);
520a7398723SShteryana Shopova 			}
521a7398723SShteryana Shopova 			if (parse_ascii(val, snmp_client.user.auth_key,
522a7398723SShteryana Shopova 			    SNMP_AUTH_KEY_SIZ) < 0) {
523a7398723SShteryana Shopova 				warnx("Bad authentication key- %s", val);
524a7398723SShteryana Shopova 				return (-1);
525a7398723SShteryana Shopova 			}
526a7398723SShteryana Shopova 			break;
527a7398723SShteryana Shopova 		default:
528a7398723SShteryana Shopova 			warnx("Unknown suboption - '%s'", suboptarg);
529a7398723SShteryana Shopova 			return (-1);
530a7398723SShteryana Shopova 		}
531eca9714eSJohn Baldwin 		/* count += 1; */
532a7398723SShteryana Shopova 	}
533a7398723SShteryana Shopova 	return (2/* count */);
534a7398723SShteryana Shopova }
535a7398723SShteryana Shopova 
536a7398723SShteryana Shopova int32_t
parse_privacy(struct snmp_toolinfo * snmptoolctx __unused,char * opt_arg)537444991f1SEnji Cooper parse_privacy(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
538a7398723SShteryana Shopova {
539eca9714eSJohn Baldwin 	int32_t /* count, */ subopt;
540a7398723SShteryana Shopova 	char *val, *option;
541a7398723SShteryana Shopova 	const char *const subopts[] = {
542a7398723SShteryana Shopova 		"proto",
543a7398723SShteryana Shopova 		"key",
544a7398723SShteryana Shopova 		NULL
545a7398723SShteryana Shopova 	};
546a7398723SShteryana Shopova 
547a7398723SShteryana Shopova 	assert(opt_arg != NULL);
548eca9714eSJohn Baldwin 	/* count = 1; */
549a7398723SShteryana Shopova 	while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
550a7398723SShteryana Shopova 		switch (subopt) {
551a7398723SShteryana Shopova 		case 0:
552a7398723SShteryana Shopova 			if (val == NULL) {
553a7398723SShteryana Shopova 				warnx("Suboption 'proto' requires an argument");
554a7398723SShteryana Shopova 				return (-1);
555a7398723SShteryana Shopova 			}
556a7398723SShteryana Shopova 			if (strlen(val) != 3) {
557a7398723SShteryana Shopova 				warnx("Unknown privacy protocol - %s", val);
558a7398723SShteryana Shopova 				return (-1);
559a7398723SShteryana Shopova 			}
560a7398723SShteryana Shopova 			if (strncasecmp("aes", val, strlen("aes")) == 0)
561a7398723SShteryana Shopova 				snmp_client.user.priv_proto = SNMP_PRIV_AES;
562a7398723SShteryana Shopova 			else if (strncasecmp("des", val, strlen("des")) == 0)
563a7398723SShteryana Shopova 				snmp_client.user.priv_proto = SNMP_PRIV_DES;
564a7398723SShteryana Shopova 			else {
565a7398723SShteryana Shopova 				warnx("Unknown privacy protocol - %s", val);
566a7398723SShteryana Shopova 				return (-1);
567a7398723SShteryana Shopova 			}
568a7398723SShteryana Shopova 			break;
569a7398723SShteryana Shopova 		case 1:
570a7398723SShteryana Shopova 			if (val == NULL) {
571a7398723SShteryana Shopova 				warnx("Suboption 'key' requires an argument");
572a7398723SShteryana Shopova 				return (-1);
573a7398723SShteryana Shopova 			}
574a7398723SShteryana Shopova 			if (parse_ascii(val, snmp_client.user.priv_key,
575a7398723SShteryana Shopova 			    SNMP_PRIV_KEY_SIZ) < 0) {
576a7398723SShteryana Shopova 				warnx("Bad privacy key- %s", val);
577a7398723SShteryana Shopova 				return (-1);
578a7398723SShteryana Shopova 			}
579a7398723SShteryana Shopova 			break;
580a7398723SShteryana Shopova 		default:
581a7398723SShteryana Shopova 			warnx("Unknown suboption - '%s'", suboptarg);
582a7398723SShteryana Shopova 			return (-1);
583a7398723SShteryana Shopova 		}
584eca9714eSJohn Baldwin 		/* count += 1; */
585a7398723SShteryana Shopova 	}
586a7398723SShteryana Shopova 	return (2/* count */);
587a7398723SShteryana Shopova }
588a7398723SShteryana Shopova 
589a7398723SShteryana Shopova int32_t
parse_context(struct snmp_toolinfo * snmptoolctx __unused,char * opt_arg)590444991f1SEnji Cooper parse_context(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
591a7398723SShteryana Shopova {
592eca9714eSJohn Baldwin 	int32_t /* count, */ subopt;
593a7398723SShteryana Shopova 	char *val, *option;
594a7398723SShteryana Shopova 	const char *const subopts[] = {
595a7398723SShteryana Shopova 		"context",
596a7398723SShteryana Shopova 		"context-engine",
597a7398723SShteryana Shopova 		NULL
598a7398723SShteryana Shopova 	};
599a7398723SShteryana Shopova 
600a7398723SShteryana Shopova 	assert(opt_arg != NULL);
601eca9714eSJohn Baldwin 	/* count = 1; */
602a7398723SShteryana Shopova 	while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
603a7398723SShteryana Shopova 		switch (subopt) {
604a7398723SShteryana Shopova 		case 0:
605a7398723SShteryana Shopova 			if (val == NULL) {
606a7398723SShteryana Shopova 				warnx("Suboption 'context' - no argument");
607a7398723SShteryana Shopova 				return (-1);
608a7398723SShteryana Shopova 			}
609a7398723SShteryana Shopova 			strlcpy(snmp_client.cname, val, SNMP_CONTEXT_NAME_SIZ);
610a7398723SShteryana Shopova 			break;
611a7398723SShteryana Shopova 		case 1:
612a7398723SShteryana Shopova 			if (val == NULL) {
613a7398723SShteryana Shopova 				warnx("Suboption 'context-engine' - no argument");
614a7398723SShteryana Shopova 				return (-1);
615a7398723SShteryana Shopova 			}
616715e3b39SEnji Cooper 			if ((int32_t)(snmp_client.clen = parse_ascii(val,
617715e3b39SEnji Cooper 			    snmp_client.cengine, SNMP_ENGINE_ID_SIZ)) == -1) {
618a7398723SShteryana Shopova 				warnx("Bad EngineID - %s", val);
619a7398723SShteryana Shopova 				return (-1);
620a7398723SShteryana Shopova 			}
621a7398723SShteryana Shopova 			break;
622a7398723SShteryana Shopova 		default:
623a7398723SShteryana Shopova 			warnx("Unknown suboption - '%s'", suboptarg);
624a7398723SShteryana Shopova 			return (-1);
625a7398723SShteryana Shopova 		}
626eca9714eSJohn Baldwin 		/* count += 1; */
627a7398723SShteryana Shopova 	}
628a7398723SShteryana Shopova 	return (2/* count */);
629a7398723SShteryana Shopova }
630a7398723SShteryana Shopova 
631a7398723SShteryana Shopova int32_t
parse_user_security(struct snmp_toolinfo * snmptoolctx __unused,char * opt_arg)632444991f1SEnji Cooper parse_user_security(struct snmp_toolinfo *snmptoolctx __unused, char *opt_arg)
633a7398723SShteryana Shopova {
634eca9714eSJohn Baldwin 	int32_t /* count, */ subopt, saved_errno;
635a7398723SShteryana Shopova 	char *val, *option;
636a7398723SShteryana Shopova 	const char *const subopts[] = {
637a7398723SShteryana Shopova 		"engine",
638a7398723SShteryana Shopova 		"engine-boots",
639a7398723SShteryana Shopova 		"engine-time",
640a7398723SShteryana Shopova 		"name",
641a7398723SShteryana Shopova 		NULL
642a7398723SShteryana Shopova 	};
643a7398723SShteryana Shopova 
644a7398723SShteryana Shopova 	assert(opt_arg != NULL);
645eca9714eSJohn Baldwin 	/* count = 1; */
646a7398723SShteryana Shopova 	while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
647a7398723SShteryana Shopova 		switch (subopt) {
648a7398723SShteryana Shopova 		case 0:
649a7398723SShteryana Shopova 			if (val == NULL) {
650a7398723SShteryana Shopova 				warnx("Suboption 'engine' - no argument");
651a7398723SShteryana Shopova 				return (-1);
652a7398723SShteryana Shopova 			}
653a7398723SShteryana Shopova 			snmp_client.engine.engine_len = parse_ascii(val,
654a7398723SShteryana Shopova 			    snmp_client.engine.engine_id, SNMP_ENGINE_ID_SIZ);
655715e3b39SEnji Cooper 			if ((int32_t)snmp_client.engine.engine_len == -1) {
656a7398723SShteryana Shopova 				warnx("Bad EngineID - %s", val);
657a7398723SShteryana Shopova 				return (-1);
658a7398723SShteryana Shopova 			}
659a7398723SShteryana Shopova 			break;
660a7398723SShteryana Shopova 		case 1:
661a7398723SShteryana Shopova 			if (val == NULL) {
662a7398723SShteryana Shopova 				warnx("Suboption 'engine-boots' - no argument");
663a7398723SShteryana Shopova 				return (-1);
664a7398723SShteryana Shopova 			}
665a7398723SShteryana Shopova 			saved_errno = errno;
666a7398723SShteryana Shopova 			errno = 0;
667a7398723SShteryana Shopova 			snmp_client.engine.engine_boots = strtoul(val, NULL, 10);
668a7398723SShteryana Shopova 			if (errno != 0) {
6697c933da6SEnji Cooper 				warn("Bad 'engine-boots' value %s", val);
670a7398723SShteryana Shopova 				errno = saved_errno;
671a7398723SShteryana Shopova 				return (-1);
672a7398723SShteryana Shopova 			}
673a7398723SShteryana Shopova 			errno = saved_errno;
674a7398723SShteryana Shopova 			break;
675a7398723SShteryana Shopova 		case 2:
676a7398723SShteryana Shopova 			if (val == NULL) {
677a7398723SShteryana Shopova 				warnx("Suboption 'engine-time' - no argument");
678a7398723SShteryana Shopova 				return (-1);
679a7398723SShteryana Shopova 			}
680a7398723SShteryana Shopova 			saved_errno = errno;
681a7398723SShteryana Shopova 			errno = 0;
682a7398723SShteryana Shopova 			snmp_client.engine.engine_time = strtoul(val, NULL, 10);
683a7398723SShteryana Shopova 			if (errno != 0) {
6847c933da6SEnji Cooper 				warn("Bad 'engine-time' value %s", val);
685a7398723SShteryana Shopova 				errno = saved_errno;
686a7398723SShteryana Shopova 				return (-1);
687a7398723SShteryana Shopova 			}
688a7398723SShteryana Shopova 			errno = saved_errno;
689a7398723SShteryana Shopova 			break;
690a7398723SShteryana Shopova 		case 3:
691a7398723SShteryana Shopova 			strlcpy(snmp_client.user.sec_name, val,
692a7398723SShteryana Shopova 			    SNMP_ADM_STR32_SIZ);
693a7398723SShteryana Shopova 			break;
694a7398723SShteryana Shopova 		default:
695a7398723SShteryana Shopova 			warnx("Unknown suboption - '%s'", suboptarg);
696a7398723SShteryana Shopova 			return (-1);
697a7398723SShteryana Shopova 		}
698eca9714eSJohn Baldwin 		/* count += 1; */
699a7398723SShteryana Shopova 	}
700a7398723SShteryana Shopova 	return (2/* count */);
701a7398723SShteryana Shopova }
702a7398723SShteryana Shopova 
703a7398723SShteryana Shopova int32_t
parse_file(struct snmp_toolinfo * snmptoolctx,char * opt_arg)704a7398723SShteryana Shopova parse_file(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
705a7398723SShteryana Shopova {
706a7398723SShteryana Shopova 	assert(opt_arg != NULL);
707a7398723SShteryana Shopova 
708a7398723SShteryana Shopova 	if (parse_flist(snmptoolctx, opt_arg, NULL, &IsoOrgDod_OID) < 0)
709a7398723SShteryana Shopova 		return (-1);
710a7398723SShteryana Shopova 
711a7398723SShteryana Shopova 	return (2);
712a7398723SShteryana Shopova }
713a7398723SShteryana Shopova 
714a7398723SShteryana Shopova int32_t
parse_include(struct snmp_toolinfo * snmptoolctx,char * opt_arg)715a7398723SShteryana Shopova parse_include(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
716a7398723SShteryana Shopova {
717a7398723SShteryana Shopova 	char path[MAXPATHLEN + 1];
718a7398723SShteryana Shopova 	int32_t cut_dflt, len, subopt;
719a7398723SShteryana Shopova 	struct asn_oid cut;
720a7398723SShteryana Shopova 	char *val, *option;
721a7398723SShteryana Shopova 	const char *const subopts[] = {
722a7398723SShteryana Shopova 		"cut",
723a7398723SShteryana Shopova 		"path",
724a7398723SShteryana Shopova 		"file",
725a7398723SShteryana Shopova 		NULL
726a7398723SShteryana Shopova 	};
727a7398723SShteryana Shopova 
728a7398723SShteryana Shopova #define	INC_CUT		0
729a7398723SShteryana Shopova #define	INC_PATH	1
730a7398723SShteryana Shopova #define	INC_LIST	2
731a7398723SShteryana Shopova 
732a7398723SShteryana Shopova 	assert(opt_arg != NULL);
733a7398723SShteryana Shopova 
734a7398723SShteryana Shopova 	/* if (opt == 'i')
735a7398723SShteryana Shopova 		free_filelist(snmptoolctx, ); */
736a7398723SShteryana Shopova 	/*
737a7398723SShteryana Shopova 	 * This function should be called only after getopt(3) - otherwise if
738a7398723SShteryana Shopova 	 * no previous validation of opt_arg strlen() may not return what is
739a7398723SShteryana Shopova 	 * expected.
740a7398723SShteryana Shopova 	 */
741a7398723SShteryana Shopova 
742a7398723SShteryana Shopova 	path[0] = '\0';
743a7398723SShteryana Shopova 	memset(&cut, 0, sizeof(struct asn_oid));
744a7398723SShteryana Shopova 	cut_dflt = -1;
745a7398723SShteryana Shopova 
746a7398723SShteryana Shopova 	while ((subopt = getsubopt1(&opt_arg, subopts, &val, &option)) != EOF) {
747a7398723SShteryana Shopova 		switch (subopt) {
748a7398723SShteryana Shopova 		    case INC_CUT:
749a7398723SShteryana Shopova 			if (val == NULL) {
750a7398723SShteryana Shopova 				warnx("Suboption 'cut' requires an argument");
751a7398723SShteryana Shopova 				return (-1);
752a7398723SShteryana Shopova 			} else {
753a7398723SShteryana Shopova 				if (snmp_parse_numoid(val, &cut) < 0)
754a7398723SShteryana Shopova 					return (-1);
755a7398723SShteryana Shopova 			}
756a7398723SShteryana Shopova 			cut_dflt = 1;
757a7398723SShteryana Shopova 			break;
758a7398723SShteryana Shopova 
759a7398723SShteryana Shopova 		    case INC_PATH:
760a7398723SShteryana Shopova 			if ((len = parse_path(val)) < 0)
761a7398723SShteryana Shopova 				return (-1);
762a7398723SShteryana Shopova 			strlcpy(path, val, len + 1);
763a7398723SShteryana Shopova 			break;
764a7398723SShteryana Shopova 
765a7398723SShteryana Shopova 		    case INC_LIST:
766a7398723SShteryana Shopova 			if (val == NULL)
767a7398723SShteryana Shopova 				return (-1);
768a7398723SShteryana Shopova 			if (cut_dflt == -1)
769a7398723SShteryana Shopova 				len = parse_flist(snmptoolctx, val, path, &IsoOrgDod_OID);
770a7398723SShteryana Shopova 			else
771a7398723SShteryana Shopova 				len = parse_flist(snmptoolctx, val, path, &cut);
772a7398723SShteryana Shopova 			if (len < 0)
773a7398723SShteryana Shopova 				return (-1);
774a7398723SShteryana Shopova 			break;
775a7398723SShteryana Shopova 
776a7398723SShteryana Shopova 		    default:
777a7398723SShteryana Shopova 			warnx("Unknown suboption - '%s'", suboptarg);
778a7398723SShteryana Shopova 			return (-1);
779a7398723SShteryana Shopova 		}
780a7398723SShteryana Shopova 	}
781a7398723SShteryana Shopova 
782a7398723SShteryana Shopova 	/* XXX: Fix me - returning two is wrong here */
783a7398723SShteryana Shopova 	return (2);
784a7398723SShteryana Shopova }
785a7398723SShteryana Shopova 
786a7398723SShteryana Shopova int32_t
parse_server(char * opt_arg)787a7398723SShteryana Shopova parse_server(char *opt_arg)
788a7398723SShteryana Shopova {
789a7398723SShteryana Shopova 	assert(opt_arg != NULL);
790a7398723SShteryana Shopova 
791a7398723SShteryana Shopova 	if (snmp_parse_server(&snmp_client, opt_arg) < 0)
792a7398723SShteryana Shopova 		return (-1);
793a7398723SShteryana Shopova 
794a7398723SShteryana Shopova 	if (snmp_client.trans > SNMP_TRANS_UDP && snmp_client.chost == NULL) {
7957a7c07efSDon Lewis 		if ((snmp_client.chost = malloc(strlen(SNMP_DEFAULT_LOCAL) + 1))
796a7398723SShteryana Shopova 		    == NULL) {
797a7398723SShteryana Shopova 			syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
798a7398723SShteryana Shopova 			return (-1);
799a7398723SShteryana Shopova 		}
800a7398723SShteryana Shopova 		strcpy(snmp_client.chost, SNMP_DEFAULT_LOCAL);
801a7398723SShteryana Shopova 	}
802a7398723SShteryana Shopova 
803a7398723SShteryana Shopova 	return (2);
804a7398723SShteryana Shopova }
805a7398723SShteryana Shopova 
806a7398723SShteryana Shopova int32_t
parse_timeout(char * opt_arg)807a7398723SShteryana Shopova parse_timeout(char *opt_arg)
808a7398723SShteryana Shopova {
809a7398723SShteryana Shopova 	int32_t v, saved_errno;
810a7398723SShteryana Shopova 
811a7398723SShteryana Shopova 	assert(opt_arg != NULL);
812a7398723SShteryana Shopova 
813a7398723SShteryana Shopova 	saved_errno = errno;
814a7398723SShteryana Shopova 	errno = 0;
815a7398723SShteryana Shopova 
816a7398723SShteryana Shopova 	v = strtol(opt_arg, NULL, 10);
817a7398723SShteryana Shopova 	if (errno != 0) {
8187c933da6SEnji Cooper 		warn("Error parsing timeout value");
819a7398723SShteryana Shopova 		errno = saved_errno;
820a7398723SShteryana Shopova 		return (-1);
821a7398723SShteryana Shopova 	}
822a7398723SShteryana Shopova 
823a7398723SShteryana Shopova 	snmp_client.timeout.tv_sec = v;
824a7398723SShteryana Shopova 	errno = saved_errno;
825a7398723SShteryana Shopova 	return (2);
826a7398723SShteryana Shopova }
827a7398723SShteryana Shopova 
828a7398723SShteryana Shopova int32_t
parse_retry(char * opt_arg)829a7398723SShteryana Shopova parse_retry(char *opt_arg)
830a7398723SShteryana Shopova {
831a7398723SShteryana Shopova 	uint32_t v;
832a7398723SShteryana Shopova 	int32_t saved_errno;
833a7398723SShteryana Shopova 
834a7398723SShteryana Shopova 	assert(opt_arg != NULL);
835a7398723SShteryana Shopova 
836a7398723SShteryana Shopova 	saved_errno = errno;
837a7398723SShteryana Shopova 	errno = 0;
838a7398723SShteryana Shopova 
839a7398723SShteryana Shopova 	v = strtoul(opt_arg, NULL, 10);
840a7398723SShteryana Shopova 	if (errno != 0) {
8417c933da6SEnji Cooper 		warn("Error parsing retries count");
842a7398723SShteryana Shopova 		errno = saved_errno;
843a7398723SShteryana Shopova 		return (-1);
844a7398723SShteryana Shopova 	}
845a7398723SShteryana Shopova 
846a7398723SShteryana Shopova 	snmp_client.retries = v;
847a7398723SShteryana Shopova 	errno = saved_errno;
848a7398723SShteryana Shopova 	return (2);
849a7398723SShteryana Shopova }
850a7398723SShteryana Shopova 
851a7398723SShteryana Shopova int32_t
parse_version(char * opt_arg)852a7398723SShteryana Shopova parse_version(char *opt_arg)
853a7398723SShteryana Shopova {
854a7398723SShteryana Shopova 	uint32_t v;
855a7398723SShteryana Shopova 	int32_t saved_errno;
856a7398723SShteryana Shopova 
857a7398723SShteryana Shopova 	assert(opt_arg != NULL);
858a7398723SShteryana Shopova 
859a7398723SShteryana Shopova 	saved_errno = errno;
860a7398723SShteryana Shopova 	errno = 0;
861a7398723SShteryana Shopova 
862a7398723SShteryana Shopova 	v = strtoul(opt_arg, NULL, 10);
863a7398723SShteryana Shopova 	if (errno != 0) {
8647c933da6SEnji Cooper 		warn("Error parsing version");
865a7398723SShteryana Shopova 		errno = saved_errno;
866a7398723SShteryana Shopova 		return (-1);
867a7398723SShteryana Shopova 	}
868a7398723SShteryana Shopova 
869a7398723SShteryana Shopova 	switch (v) {
870a7398723SShteryana Shopova 		case 1:
871a7398723SShteryana Shopova 			snmp_client.version = SNMP_V1;
872a7398723SShteryana Shopova 			break;
873a7398723SShteryana Shopova 		case 2:
874a7398723SShteryana Shopova 			snmp_client.version = SNMP_V2c;
875a7398723SShteryana Shopova 			break;
876a7398723SShteryana Shopova 		case 3:
877a7398723SShteryana Shopova 			snmp_client.version = SNMP_V3;
878a7398723SShteryana Shopova 			break;
879a7398723SShteryana Shopova 		default:
880a7398723SShteryana Shopova 			warnx("Unsupported SNMP version - %u", v);
881a7398723SShteryana Shopova 			errno = saved_errno;
882a7398723SShteryana Shopova 			return (-1);
883a7398723SShteryana Shopova 	}
884a7398723SShteryana Shopova 
885a7398723SShteryana Shopova 	errno = saved_errno;
886a7398723SShteryana Shopova 	return (2);
887a7398723SShteryana Shopova }
888a7398723SShteryana Shopova 
889a7398723SShteryana Shopova int32_t
parse_local_path(char * opt_arg)890a7398723SShteryana Shopova parse_local_path(char *opt_arg)
891a7398723SShteryana Shopova {
892a7398723SShteryana Shopova 	assert(opt_arg != NULL);
893a7398723SShteryana Shopova 
894a7398723SShteryana Shopova 	if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) {
895a7398723SShteryana Shopova 		warnx("Filename too long - %s", opt_arg);
896a7398723SShteryana Shopova 		return (-1);
897a7398723SShteryana Shopova 	}
898a7398723SShteryana Shopova 
899a7398723SShteryana Shopova 	strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH));
900a7398723SShteryana Shopova 	return (2);
901a7398723SShteryana Shopova }
902a7398723SShteryana Shopova 
903a7398723SShteryana Shopova int32_t
parse_buflen(char * opt_arg)904a7398723SShteryana Shopova parse_buflen(char *opt_arg)
905a7398723SShteryana Shopova {
906a7398723SShteryana Shopova 	uint32_t size;
907a7398723SShteryana Shopova 	int32_t saved_errno;
908a7398723SShteryana Shopova 
909a7398723SShteryana Shopova 	assert(opt_arg != NULL);
910a7398723SShteryana Shopova 
911a7398723SShteryana Shopova 	saved_errno = errno;
912a7398723SShteryana Shopova 	errno = 0;
913a7398723SShteryana Shopova 
914a7398723SShteryana Shopova 	size = strtoul(opt_arg, NULL, 10);
915a7398723SShteryana Shopova 	if (errno != 0) {
9167c933da6SEnji Cooper 		warn("Error parsing buffer size");
917a7398723SShteryana Shopova 		errno = saved_errno;
918a7398723SShteryana Shopova 		return (-1);
919a7398723SShteryana Shopova 	}
920a7398723SShteryana Shopova 
921a7398723SShteryana Shopova 	if (size > MAX_BUFF_SIZE) {
922a7398723SShteryana Shopova 		warnx("Buffer size too big - %d max allowed", MAX_BUFF_SIZE);
923a7398723SShteryana Shopova 		errno = saved_errno;
924a7398723SShteryana Shopova 		return (-1);
925a7398723SShteryana Shopova 	}
926a7398723SShteryana Shopova 
927a7398723SShteryana Shopova 	snmp_client.txbuflen = snmp_client.rxbuflen = size;
928a7398723SShteryana Shopova 	errno = saved_errno;
929a7398723SShteryana Shopova 	return (2);
930a7398723SShteryana Shopova }
931a7398723SShteryana Shopova 
932a7398723SShteryana Shopova int32_t
parse_debug(void)933a7398723SShteryana Shopova parse_debug(void)
934a7398723SShteryana Shopova {
935a7398723SShteryana Shopova 	snmp_client.dump_pdus = 1;
936a7398723SShteryana Shopova 	return (1);
937a7398723SShteryana Shopova }
938a7398723SShteryana Shopova 
939a7398723SShteryana Shopova int32_t
parse_discovery(struct snmp_toolinfo * snmptoolctx)940a7398723SShteryana Shopova parse_discovery(struct snmp_toolinfo *snmptoolctx)
941a7398723SShteryana Shopova {
942a7398723SShteryana Shopova 	SET_EDISCOVER(snmptoolctx);
943a7398723SShteryana Shopova 	snmp_client.version = SNMP_V3;
944a7398723SShteryana Shopova 	return (1);
945a7398723SShteryana Shopova }
946a7398723SShteryana Shopova 
947a7398723SShteryana Shopova int32_t
parse_local_key(struct snmp_toolinfo * snmptoolctx)948a7398723SShteryana Shopova parse_local_key(struct snmp_toolinfo *snmptoolctx)
949a7398723SShteryana Shopova {
950a7398723SShteryana Shopova 	SET_LOCALKEY(snmptoolctx);
951a7398723SShteryana Shopova 	snmp_client.version = SNMP_V3;
952a7398723SShteryana Shopova 	return (1);
953a7398723SShteryana Shopova }
954a7398723SShteryana Shopova 
955a7398723SShteryana Shopova int32_t
parse_num_oids(struct snmp_toolinfo * snmptoolctx)956a7398723SShteryana Shopova parse_num_oids(struct snmp_toolinfo *snmptoolctx)
957a7398723SShteryana Shopova {
958a7398723SShteryana Shopova 	SET_NUMERIC(snmptoolctx);
959a7398723SShteryana Shopova 	return (1);
960a7398723SShteryana Shopova }
961a7398723SShteryana Shopova 
962a7398723SShteryana Shopova int32_t
parse_output(struct snmp_toolinfo * snmptoolctx,char * opt_arg)963a7398723SShteryana Shopova parse_output(struct snmp_toolinfo *snmptoolctx, char *opt_arg)
964a7398723SShteryana Shopova {
965a7398723SShteryana Shopova 	assert(opt_arg != NULL);
966a7398723SShteryana Shopova 
967a7398723SShteryana Shopova 	if (strlen(opt_arg) > strlen("verbose")) {
968a7398723SShteryana Shopova 		warnx( "Invalid output option - %s",opt_arg);
969a7398723SShteryana Shopova 		return (-1);
970a7398723SShteryana Shopova 	}
971a7398723SShteryana Shopova 
972a7398723SShteryana Shopova 	if (strncasecmp(opt_arg, "short", strlen(opt_arg)) == 0)
973a7398723SShteryana Shopova 		SET_OUTPUT(snmptoolctx, OUTPUT_SHORT);
974a7398723SShteryana Shopova 	else if (strncasecmp(opt_arg, "verbose", strlen(opt_arg)) == 0)
975a7398723SShteryana Shopova 		SET_OUTPUT(snmptoolctx, OUTPUT_VERBOSE);
976a7398723SShteryana Shopova 	else if (strncasecmp(opt_arg,"tabular", strlen(opt_arg)) == 0)
977a7398723SShteryana Shopova 		SET_OUTPUT(snmptoolctx, OUTPUT_TABULAR);
978a7398723SShteryana Shopova 	else if (strncasecmp(opt_arg, "quiet", strlen(opt_arg)) == 0)
979a7398723SShteryana Shopova 		SET_OUTPUT(snmptoolctx, OUTPUT_QUIET);
980a7398723SShteryana Shopova 	else {
981a7398723SShteryana Shopova 		warnx( "Invalid output option - %s", opt_arg);
982a7398723SShteryana Shopova 		return (-1);
983a7398723SShteryana Shopova 	}
984a7398723SShteryana Shopova 
985a7398723SShteryana Shopova 	return (2);
986a7398723SShteryana Shopova }
987a7398723SShteryana Shopova 
988a7398723SShteryana Shopova int32_t
parse_errors(struct snmp_toolinfo * snmptoolctx)989a7398723SShteryana Shopova parse_errors(struct snmp_toolinfo *snmptoolctx)
990a7398723SShteryana Shopova {
991a7398723SShteryana Shopova 	SET_RETRY(snmptoolctx);
992a7398723SShteryana Shopova 	return (1);
993a7398723SShteryana Shopova }
994a7398723SShteryana Shopova 
995a7398723SShteryana Shopova int32_t
parse_skip_access(struct snmp_toolinfo * snmptoolctx)996a7398723SShteryana Shopova parse_skip_access(struct snmp_toolinfo *snmptoolctx)
997a7398723SShteryana Shopova {
998a7398723SShteryana Shopova 	SET_ERRIGNORE(snmptoolctx);
999a7398723SShteryana Shopova 	return (1);
1000a7398723SShteryana Shopova }
1001a7398723SShteryana Shopova 
1002a7398723SShteryana Shopova char *
snmp_parse_suboid(char * str,struct asn_oid * oid)1003a7398723SShteryana Shopova snmp_parse_suboid(char *str, struct asn_oid *oid)
1004a7398723SShteryana Shopova {
1005a7398723SShteryana Shopova 	char *endptr;
1006a7398723SShteryana Shopova 	asn_subid_t suboid;
1007a7398723SShteryana Shopova 
1008a7398723SShteryana Shopova 	if (*str == '.')
1009a7398723SShteryana Shopova 		str++;
1010a7398723SShteryana Shopova 
1011a7398723SShteryana Shopova 	if (*str < '0' || *str > '9')
1012a7398723SShteryana Shopova 		return (str);
1013a7398723SShteryana Shopova 
1014a7398723SShteryana Shopova 	do {
1015a7398723SShteryana Shopova 		suboid = strtoul(str, &endptr, 10);
1016a7398723SShteryana Shopova 		if ((asn_subid_t) suboid > ASN_MAXID) {
1017a7398723SShteryana Shopova 			warnx("Suboid %u > ASN_MAXID", suboid);
1018a7398723SShteryana Shopova 			return (NULL);
1019a7398723SShteryana Shopova 		}
1020a7398723SShteryana Shopova 		if (snmp_suboid_append(oid, suboid) < 0)
1021a7398723SShteryana Shopova 			return (NULL);
1022a7398723SShteryana Shopova 		str = endptr + 1;
1023a7398723SShteryana Shopova 	} while (*endptr == '.');
1024a7398723SShteryana Shopova 
1025a7398723SShteryana Shopova 	return (endptr);
1026a7398723SShteryana Shopova }
1027a7398723SShteryana Shopova 
1028a7398723SShteryana Shopova static char *
snmp_int2asn_oid(char * str,struct asn_oid * oid)1029a7398723SShteryana Shopova snmp_int2asn_oid(char *str, struct asn_oid *oid)
1030a7398723SShteryana Shopova {
1031a7398723SShteryana Shopova 	char *endptr;
1032a7398723SShteryana Shopova 	int32_t v, saved_errno;
1033a7398723SShteryana Shopova 
1034a7398723SShteryana Shopova 	saved_errno = errno;
1035a7398723SShteryana Shopova 	errno = 0;
1036a7398723SShteryana Shopova 
1037a7398723SShteryana Shopova 	v = strtol(str, &endptr, 10);
1038a7398723SShteryana Shopova 	if (errno != 0) {
10397c933da6SEnji Cooper 		warn("Integer value %s not supported", str);
1040a7398723SShteryana Shopova 		errno = saved_errno;
1041a7398723SShteryana Shopova 		return (NULL);
1042a7398723SShteryana Shopova 	}
1043a7398723SShteryana Shopova 	errno = saved_errno;
1044a7398723SShteryana Shopova 
1045a7398723SShteryana Shopova 	if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1046a7398723SShteryana Shopova 		return (NULL);
1047a7398723SShteryana Shopova 
1048a7398723SShteryana Shopova 	return (endptr);
1049a7398723SShteryana Shopova }
1050a7398723SShteryana Shopova 
1051a7398723SShteryana Shopova /* It is a bit weird to have a table indexed by OID but still... */
1052a7398723SShteryana Shopova static char *
snmp_oid2asn_oid(struct snmp_toolinfo * snmptoolctx,char * str,struct asn_oid * oid)1053a7398723SShteryana Shopova snmp_oid2asn_oid(struct snmp_toolinfo *snmptoolctx, char *str,
1054a7398723SShteryana Shopova     struct asn_oid *oid)
1055a7398723SShteryana Shopova {
1056a7398723SShteryana Shopova 	int32_t i;
105781910adfSEnji Cooper 	char string[MAXSTR + 1], *endptr;
1058a7398723SShteryana Shopova 	struct snmp_object obj;
1059a7398723SShteryana Shopova 
1060a7398723SShteryana Shopova 	for (i = 0; i < MAXSTR; i++)
1061a7398723SShteryana Shopova 		if (isalpha (*(str + i)) == 0)
1062a7398723SShteryana Shopova 			break;
1063a7398723SShteryana Shopova 
1064a7398723SShteryana Shopova 	endptr = str + i;
1065a7398723SShteryana Shopova 	memset(&obj, 0, sizeof(struct snmp_object));
1066a7398723SShteryana Shopova 	if (i == 0) {
1067a7398723SShteryana Shopova 		if ((endptr = snmp_parse_suboid(str, &(obj.val.var))) == NULL)
1068a7398723SShteryana Shopova 			return (NULL);
1069a7398723SShteryana Shopova 		if (snmp_suboid_append(oid, (asn_subid_t) obj.val.var.len) < 0)
1070a7398723SShteryana Shopova 			return (NULL);
1071a7398723SShteryana Shopova 	} else {
1072a7398723SShteryana Shopova 		strlcpy(string, str, i + 1);
1073a7398723SShteryana Shopova 		if (snmp_lookup_enumoid(snmptoolctx, &obj, string) < 0) {
1074a7398723SShteryana Shopova 			warnx("Unknown string - %s", string);
1075a7398723SShteryana Shopova 			return (NULL);
1076a7398723SShteryana Shopova 		}
1077a7398723SShteryana Shopova 	}
1078a7398723SShteryana Shopova 
1079a7398723SShteryana Shopova 	asn_append_oid(oid, &(obj.val.var));
1080a7398723SShteryana Shopova 	return (endptr);
1081a7398723SShteryana Shopova }
1082a7398723SShteryana Shopova 
1083a7398723SShteryana Shopova static char *
snmp_ip2asn_oid(char * str,struct asn_oid * oid)1084a7398723SShteryana Shopova snmp_ip2asn_oid(char *str, struct asn_oid *oid)
1085a7398723SShteryana Shopova {
1086a7398723SShteryana Shopova 	uint32_t v;
1087a7398723SShteryana Shopova 	int32_t i;
1088a7398723SShteryana Shopova 	char *endptr, *ptr;
1089a7398723SShteryana Shopova 
1090a7398723SShteryana Shopova 	ptr = str;
10912229fa01SEnji Cooper 
1092a7398723SShteryana Shopova 	for (i = 0; i < 4; i++) {
1093a7398723SShteryana Shopova 		v = strtoul(ptr, &endptr, 10);
1094a7398723SShteryana Shopova 		if (v > 0xff)
1095a7398723SShteryana Shopova 			return (NULL);
1096a7398723SShteryana Shopova 		if (*endptr != '.' && strchr("],\0", *endptr) == NULL && i != 3)
1097a7398723SShteryana Shopova 			return (NULL);
1098a7398723SShteryana Shopova 		if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1099a7398723SShteryana Shopova 			return (NULL);
1100a7398723SShteryana Shopova 		ptr = endptr + 1;
1101a7398723SShteryana Shopova 	}
1102a7398723SShteryana Shopova 
1103a7398723SShteryana Shopova 	return (endptr);
1104a7398723SShteryana Shopova }
1105a7398723SShteryana Shopova 
1106a7398723SShteryana Shopova /* 32-bit counter, gauge, timeticks. */
1107a7398723SShteryana Shopova static char *
snmp_uint2asn_oid(char * str,struct asn_oid * oid)1108a7398723SShteryana Shopova snmp_uint2asn_oid(char *str, struct asn_oid *oid)
1109a7398723SShteryana Shopova {
1110a7398723SShteryana Shopova 	char *endptr;
1111a7398723SShteryana Shopova 	uint32_t v;
1112a7398723SShteryana Shopova 	int32_t saved_errno;
1113a7398723SShteryana Shopova 
1114a7398723SShteryana Shopova 	saved_errno = errno;
1115a7398723SShteryana Shopova 	errno = 0;
1116a7398723SShteryana Shopova 
1117a7398723SShteryana Shopova 	v = strtoul(str, &endptr, 10);
1118a7398723SShteryana Shopova 	if (errno != 0) {
11197c933da6SEnji Cooper 		warn("Integer value %s not supported", str);
1120a7398723SShteryana Shopova 		errno = saved_errno;
1121a7398723SShteryana Shopova 		return (NULL);
1122a7398723SShteryana Shopova 	}
1123a7398723SShteryana Shopova 	errno = saved_errno;
1124a7398723SShteryana Shopova 	if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1125a7398723SShteryana Shopova 		return (NULL);
1126a7398723SShteryana Shopova 
1127a7398723SShteryana Shopova 	return (endptr);
1128a7398723SShteryana Shopova }
1129a7398723SShteryana Shopova 
1130a7398723SShteryana Shopova static char *
snmp_cnt64_2asn_oid(char * str,struct asn_oid * oid)1131a7398723SShteryana Shopova snmp_cnt64_2asn_oid(char *str, struct asn_oid *oid)
1132a7398723SShteryana Shopova {
1133a7398723SShteryana Shopova 	char *endptr;
1134a7398723SShteryana Shopova 	uint64_t v;
1135a7398723SShteryana Shopova 	int32_t saved_errno;
1136a7398723SShteryana Shopova 
1137a7398723SShteryana Shopova 	saved_errno = errno;
1138a7398723SShteryana Shopova 	errno = 0;
1139a7398723SShteryana Shopova 
1140a7398723SShteryana Shopova 	v = strtoull(str, &endptr, 10);
1141a7398723SShteryana Shopova 
1142a7398723SShteryana Shopova 	if (errno != 0) {
11437c933da6SEnji Cooper 		warn("Integer value %s not supported", str);
1144a7398723SShteryana Shopova 		errno = saved_errno;
1145a7398723SShteryana Shopova 		return (NULL);
1146a7398723SShteryana Shopova 	}
1147a7398723SShteryana Shopova 	errno = saved_errno;
1148a7398723SShteryana Shopova 	if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xffffffff)) < 0)
1149a7398723SShteryana Shopova 		return (NULL);
1150a7398723SShteryana Shopova 
1151a7398723SShteryana Shopova 	if (snmp_suboid_append(oid, (asn_subid_t) (v >> 32)) < 0)
1152a7398723SShteryana Shopova 		return (NULL);
1153a7398723SShteryana Shopova 
1154a7398723SShteryana Shopova 	return (endptr);
1155a7398723SShteryana Shopova }
1156a7398723SShteryana Shopova 
1157a7398723SShteryana Shopova enum snmp_syntax
parse_syntax(char * str)1158a7398723SShteryana Shopova parse_syntax(char *str)
1159a7398723SShteryana Shopova {
1160a7398723SShteryana Shopova 	int32_t i;
1161a7398723SShteryana Shopova 
1162a7398723SShteryana Shopova 	for (i = 0; i < SNMP_SYNTAX_UNKNOWN; i++) {
1163a7398723SShteryana Shopova 		if (strncmp(syntax_strings[i].str, str,
1164a7398723SShteryana Shopova 		    strlen(syntax_strings[i].str)) == 0)
1165a7398723SShteryana Shopova 			return (syntax_strings[i].stx);
1166a7398723SShteryana Shopova 	}
1167a7398723SShteryana Shopova 
1168a7398723SShteryana Shopova 	return (SNMP_SYNTAX_NULL);
1169a7398723SShteryana Shopova }
1170a7398723SShteryana Shopova 
1171a7398723SShteryana Shopova static char *
snmp_parse_subindex(struct snmp_toolinfo * snmptoolctx,char * str,struct index * idx,struct snmp_object * object)1172a7398723SShteryana Shopova snmp_parse_subindex(struct snmp_toolinfo *snmptoolctx, char *str,
1173a7398723SShteryana Shopova     struct index *idx, struct snmp_object *object)
1174a7398723SShteryana Shopova {
1175a7398723SShteryana Shopova 	char *ptr;
1176a7398723SShteryana Shopova 	int32_t i;
1177a7398723SShteryana Shopova 	enum snmp_syntax stx;
1178a7398723SShteryana Shopova 	char syntax[MAX_CMD_SYNTAX_LEN];
1179a7398723SShteryana Shopova 
1180a7398723SShteryana Shopova 	ptr = str;
1181a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE) {
1182a7398723SShteryana Shopova 		for (i = 0; i < MAX_CMD_SYNTAX_LEN ; i++) {
1183a7398723SShteryana Shopova 			if (*(ptr + i) == ':')
1184a7398723SShteryana Shopova 				break;
1185a7398723SShteryana Shopova 		}
1186a7398723SShteryana Shopova 
1187a7398723SShteryana Shopova 		if (i >= MAX_CMD_SYNTAX_LEN) {
1188a7398723SShteryana Shopova 			warnx("Unknown syntax in OID - %s", str);
1189a7398723SShteryana Shopova 			return (NULL);
1190a7398723SShteryana Shopova 		}
1191a7398723SShteryana Shopova 		/* Expect a syntax string here. */
1192a7398723SShteryana Shopova 		if ((stx = parse_syntax(str)) <= SNMP_SYNTAX_NULL) {
1193a7398723SShteryana Shopova 			warnx("Invalid  syntax - %s",syntax);
1194a7398723SShteryana Shopova 			return (NULL);
1195a7398723SShteryana Shopova 		}
1196a7398723SShteryana Shopova 
1197a7398723SShteryana Shopova 		if (stx != idx->syntax && !ISSET_ERRIGNORE(snmptoolctx)) {
1198a7398723SShteryana Shopova 			warnx("Syntax mismatch - %d expected, %d given",
1199a7398723SShteryana Shopova 			    idx->syntax, stx);
1200a7398723SShteryana Shopova 			return (NULL);
1201a7398723SShteryana Shopova 		}
1202a7398723SShteryana Shopova 		/*
1203a7398723SShteryana Shopova 		 * That is where the suboid started + the syntax length + one
1204a7398723SShteryana Shopova 		 * character for ':'.
1205a7398723SShteryana Shopova 		 */
1206a7398723SShteryana Shopova 		ptr = str + i + 1;
1207a7398723SShteryana Shopova 	} else
1208a7398723SShteryana Shopova 		stx = idx->syntax;
1209a7398723SShteryana Shopova 
1210a7398723SShteryana Shopova 	switch (stx) {
1211a7398723SShteryana Shopova 		case SNMP_SYNTAX_INTEGER:
1212a7398723SShteryana Shopova 			return (snmp_int2asn_oid(ptr, &(object->val.var)));
1213a7398723SShteryana Shopova 		case SNMP_SYNTAX_OID:
1214a7398723SShteryana Shopova 			return (snmp_oid2asn_oid(snmptoolctx, ptr,
1215a7398723SShteryana Shopova 			    &(object->val.var)));
1216a7398723SShteryana Shopova 		case SNMP_SYNTAX_IPADDRESS:
1217a7398723SShteryana Shopova 			return (snmp_ip2asn_oid(ptr, &(object->val.var)));
1218a7398723SShteryana Shopova 		case SNMP_SYNTAX_COUNTER:
1219a7398723SShteryana Shopova 			/* FALLTHROUGH */
1220a7398723SShteryana Shopova 		case SNMP_SYNTAX_GAUGE:
1221a7398723SShteryana Shopova 			/* FALLTHROUGH */
1222a7398723SShteryana Shopova 		case SNMP_SYNTAX_TIMETICKS:
1223a7398723SShteryana Shopova 			return (snmp_uint2asn_oid(ptr, &(object->val.var)));
1224a7398723SShteryana Shopova 		case SNMP_SYNTAX_COUNTER64:
1225a7398723SShteryana Shopova 			return (snmp_cnt64_2asn_oid(ptr, &(object->val.var)));
1226a7398723SShteryana Shopova 		case SNMP_SYNTAX_OCTETSTRING:
1227a7398723SShteryana Shopova 			return (snmp_tc2oid(idx->tc, ptr, &(object->val.var)));
1228a7398723SShteryana Shopova 		default:
1229a7398723SShteryana Shopova 			/* NOTREACHED */
1230a7398723SShteryana Shopova 			break;
1231a7398723SShteryana Shopova 	}
1232a7398723SShteryana Shopova 
1233a7398723SShteryana Shopova 	return (NULL);
1234a7398723SShteryana Shopova }
1235a7398723SShteryana Shopova 
1236a7398723SShteryana Shopova char *
snmp_parse_index(struct snmp_toolinfo * snmptoolctx,char * str,struct snmp_object * object)1237a7398723SShteryana Shopova snmp_parse_index(struct snmp_toolinfo *snmptoolctx, char *str,
1238a7398723SShteryana Shopova     struct snmp_object *object)
1239a7398723SShteryana Shopova {
1240a7398723SShteryana Shopova 	char *ptr;
1241a7398723SShteryana Shopova 	struct index *temp;
1242a7398723SShteryana Shopova 
1243a7398723SShteryana Shopova 	if (object->info->table_idx == NULL)
1244a7398723SShteryana Shopova 		return (NULL);
1245a7398723SShteryana Shopova 
1246a7398723SShteryana Shopova 	ptr = NULL;
1247a7398723SShteryana Shopova 	STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(object)), link) {
1248a7398723SShteryana Shopova 		if ((ptr = snmp_parse_subindex(snmptoolctx, str, temp, object))
1249a7398723SShteryana Shopova 		    == NULL)
1250a7398723SShteryana Shopova 			return (NULL);
1251a7398723SShteryana Shopova 
1252a7398723SShteryana Shopova 		if (*ptr != ',' && *ptr != ']')
1253a7398723SShteryana Shopova 			return (NULL);
1254a7398723SShteryana Shopova 		str = ptr + 1;
1255a7398723SShteryana Shopova 	}
1256a7398723SShteryana Shopova 
1257a7398723SShteryana Shopova 	if (ptr == NULL || *ptr != ']') {
1258a7398723SShteryana Shopova 		warnx("Mismatching index - %s", str);
1259a7398723SShteryana Shopova 		return (NULL);
1260a7398723SShteryana Shopova 	}
1261a7398723SShteryana Shopova 
1262a7398723SShteryana Shopova 	return (ptr + 1);
1263a7398723SShteryana Shopova }
1264a7398723SShteryana Shopova 
1265a7398723SShteryana Shopova /*
1266a7398723SShteryana Shopova  * Fill in the struct asn_oid member of snmp_value with suboids from input.
1267a7398723SShteryana Shopova  * If an error occurs - print message on stderr and return (-1).
1268a7398723SShteryana Shopova  * If all is ok - return the length of the oid.
1269a7398723SShteryana Shopova  */
1270a7398723SShteryana Shopova int32_t
snmp_parse_numoid(char * argv,struct asn_oid * var)1271a7398723SShteryana Shopova snmp_parse_numoid(char *argv, struct asn_oid *var)
1272a7398723SShteryana Shopova {
1273a7398723SShteryana Shopova 	char *endptr, *str;
1274a7398723SShteryana Shopova 	asn_subid_t suboid;
1275a7398723SShteryana Shopova 
1276a7398723SShteryana Shopova 	str = argv;
1277a7398723SShteryana Shopova 
1278a7398723SShteryana Shopova 	if (*str == '.')
1279a7398723SShteryana Shopova 		str++;
1280a7398723SShteryana Shopova 
1281a7398723SShteryana Shopova 	do {
1282a7398723SShteryana Shopova 		if (var->len == ASN_MAXOIDLEN) {
1283a7398723SShteryana Shopova 			warnx("Oid too long - %u", var->len);
1284a7398723SShteryana Shopova 			return (-1);
1285a7398723SShteryana Shopova 		}
1286a7398723SShteryana Shopova 
1287a7398723SShteryana Shopova 		suboid = strtoul(str, &endptr, 10);
1288a7398723SShteryana Shopova 		if (suboid > ASN_MAXID) {
1289a7398723SShteryana Shopova 			warnx("Oid too long - %u", var->len);
1290a7398723SShteryana Shopova 			return (-1);
1291a7398723SShteryana Shopova 		}
1292a7398723SShteryana Shopova 
1293a7398723SShteryana Shopova 		var->subs[var->len++] = suboid;
1294a7398723SShteryana Shopova 		str = endptr + 1;
1295a7398723SShteryana Shopova 	} while ( *endptr == '.');
1296a7398723SShteryana Shopova 
1297a7398723SShteryana Shopova 	if (*endptr != '\0') {
1298a7398723SShteryana Shopova 		warnx("Invalid oid string - %s", argv);
1299a7398723SShteryana Shopova 		return (-1);
1300a7398723SShteryana Shopova 	}
1301a7398723SShteryana Shopova 
1302a7398723SShteryana Shopova 	return (var->len);
1303a7398723SShteryana Shopova }
1304a7398723SShteryana Shopova 
1305a7398723SShteryana Shopova /* Append a length 1 suboid to an asn_oid structure. */
1306a7398723SShteryana Shopova int32_t
snmp_suboid_append(struct asn_oid * var,asn_subid_t suboid)1307a7398723SShteryana Shopova snmp_suboid_append(struct asn_oid *var, asn_subid_t suboid)
1308a7398723SShteryana Shopova {
1309a7398723SShteryana Shopova 	if (var == NULL)
1310a7398723SShteryana Shopova 		return (-1);
1311a7398723SShteryana Shopova 
1312a7398723SShteryana Shopova 	if (var->len >= ASN_MAXOIDLEN) {
1313a7398723SShteryana Shopova 		warnx("Oid too long - %u", var->len);
1314a7398723SShteryana Shopova 		return (-1);
1315a7398723SShteryana Shopova 	}
1316a7398723SShteryana Shopova 
1317a7398723SShteryana Shopova 	var->subs[var->len++] = suboid;
1318a7398723SShteryana Shopova 
1319a7398723SShteryana Shopova 	return (1);
1320a7398723SShteryana Shopova }
1321a7398723SShteryana Shopova 
1322a7398723SShteryana Shopova /* Pop the last suboid from an asn_oid structure. */
1323a7398723SShteryana Shopova int32_t
snmp_suboid_pop(struct asn_oid * var)1324a7398723SShteryana Shopova snmp_suboid_pop(struct asn_oid *var)
1325a7398723SShteryana Shopova {
1326a7398723SShteryana Shopova 	asn_subid_t suboid;
1327a7398723SShteryana Shopova 
1328a7398723SShteryana Shopova 	if (var == NULL)
1329a7398723SShteryana Shopova 		return (-1);
1330a7398723SShteryana Shopova 
1331a7398723SShteryana Shopova 	if (var->len < 1)
1332a7398723SShteryana Shopova 		return (-1);
1333a7398723SShteryana Shopova 
1334a7398723SShteryana Shopova 	suboid = var->subs[--(var->len)];
1335a7398723SShteryana Shopova 	var->subs[var->len] = 0;
1336a7398723SShteryana Shopova 
1337a7398723SShteryana Shopova 	return (suboid);
1338a7398723SShteryana Shopova }
1339a7398723SShteryana Shopova 
1340a7398723SShteryana Shopova /*
13418b223768SElyes Haouas  * Parse the command-line provided string into an OID - allocate memory for a new
1342a7398723SShteryana Shopova  * snmp object, fill in its fields and insert it in the object list. A
1343a7398723SShteryana Shopova  * (snmp_verify_inoid_f) function must be provided to validate the input string.
1344a7398723SShteryana Shopova  */
1345a7398723SShteryana Shopova int32_t
snmp_object_add(struct snmp_toolinfo * snmptoolctx,snmp_verify_inoid_f func,char * string)1346a7398723SShteryana Shopova snmp_object_add(struct snmp_toolinfo *snmptoolctx, snmp_verify_inoid_f func,
1347a7398723SShteryana Shopova     char *string)
1348a7398723SShteryana Shopova {
1349a7398723SShteryana Shopova 	struct snmp_object *obj;
1350a7398723SShteryana Shopova 
1351a7398723SShteryana Shopova 	if (snmptoolctx == NULL)
1352a7398723SShteryana Shopova 		return (-1);
1353a7398723SShteryana Shopova 
1354a7398723SShteryana Shopova 	/* XXX-BZ does that chack make sense? */
1355a7398723SShteryana Shopova 	if (snmptoolctx->objects >= SNMP_MAX_BINDINGS) {
1356a7398723SShteryana Shopova 		warnx("Too many bindings in PDU - %u", snmptoolctx->objects + 1);
1357a7398723SShteryana Shopova 		return (-1);
1358a7398723SShteryana Shopova 	}
1359a7398723SShteryana Shopova 
1360031987d9SEnji Cooper 	if ((obj = calloc(1, sizeof(struct snmp_object))) == NULL) {
1361a7398723SShteryana Shopova 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
1362a7398723SShteryana Shopova 		return (-1);
1363a7398723SShteryana Shopova 	}
1364a7398723SShteryana Shopova 
1365a7398723SShteryana Shopova 	if (func(snmptoolctx, obj, string) < 0) {
1366a7398723SShteryana Shopova 		warnx("Invalid OID - %s", string);
1367a7398723SShteryana Shopova 		free(obj);
1368a7398723SShteryana Shopova 		return (-1);
1369a7398723SShteryana Shopova 	}
1370a7398723SShteryana Shopova 
1371a7398723SShteryana Shopova 	snmptoolctx->objects++;
1372a7398723SShteryana Shopova 	SLIST_INSERT_HEAD(&snmptoolctx->snmp_objectlist, obj, link);
1373a7398723SShteryana Shopova 
1374a7398723SShteryana Shopova 	return (1);
1375a7398723SShteryana Shopova }
1376a7398723SShteryana Shopova 
1377a7398723SShteryana Shopova /* Given an OID, find it in the object list and remove it. */
1378a7398723SShteryana Shopova int32_t
snmp_object_remove(struct snmp_toolinfo * snmptoolctx,struct asn_oid * oid)1379a7398723SShteryana Shopova snmp_object_remove(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid)
1380a7398723SShteryana Shopova {
1381a7398723SShteryana Shopova 	struct snmp_object *temp;
1382a7398723SShteryana Shopova 
1383a7398723SShteryana Shopova 	if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist)) {
1384a7398723SShteryana Shopova 		warnx("Object list already empty");
1385a7398723SShteryana Shopova 		return (-1);
1386a7398723SShteryana Shopova 	}
1387a7398723SShteryana Shopova 
1388a7398723SShteryana Shopova 
1389a7398723SShteryana Shopova 	SLIST_FOREACH(temp, &snmptoolctx->snmp_objectlist, link)
1390a7398723SShteryana Shopova 		if (asn_compare_oid(&(temp->val.var), oid) == 0)
1391a7398723SShteryana Shopova 			break;
1392a7398723SShteryana Shopova 
1393a7398723SShteryana Shopova 	if (temp == NULL) {
1394a7398723SShteryana Shopova 		warnx("No such object in list");
1395a7398723SShteryana Shopova 		return (-1);
1396a7398723SShteryana Shopova 	}
1397a7398723SShteryana Shopova 
1398a7398723SShteryana Shopova 	SLIST_REMOVE(&snmptoolctx->snmp_objectlist, temp, snmp_object, link);
1399a7398723SShteryana Shopova 	if (temp->val.syntax == SNMP_SYNTAX_OCTETSTRING &&
1400a7398723SShteryana Shopova 	    temp->val.v.octetstring.octets != NULL)
1401a7398723SShteryana Shopova 		free(temp->val.v.octetstring.octets);
1402a7398723SShteryana Shopova 	free(temp);
1403a7398723SShteryana Shopova 
1404a7398723SShteryana Shopova 	return (1);
1405a7398723SShteryana Shopova }
1406a7398723SShteryana Shopova 
1407a7398723SShteryana Shopova static void
snmp_object_freeall(struct snmp_toolinfo * snmptoolctx)1408a7398723SShteryana Shopova snmp_object_freeall(struct snmp_toolinfo *snmptoolctx)
1409a7398723SShteryana Shopova {
1410a7398723SShteryana Shopova 	struct snmp_object *o;
1411a7398723SShteryana Shopova 
1412a7398723SShteryana Shopova 	while ((o = SLIST_FIRST(&snmptoolctx->snmp_objectlist)) != NULL) {
1413a7398723SShteryana Shopova 		SLIST_REMOVE_HEAD(&snmptoolctx->snmp_objectlist, link);
1414a7398723SShteryana Shopova 
1415a7398723SShteryana Shopova 		if (o->val.syntax == SNMP_SYNTAX_OCTETSTRING &&
1416a7398723SShteryana Shopova 		    o->val.v.octetstring.octets != NULL)
1417a7398723SShteryana Shopova 			free(o->val.v.octetstring.octets);
1418a7398723SShteryana Shopova 		free(o);
1419a7398723SShteryana Shopova 	}
1420a7398723SShteryana Shopova }
1421a7398723SShteryana Shopova 
1422a7398723SShteryana Shopova /* Do all possible memory release before exit. */
1423a7398723SShteryana Shopova void
snmp_tool_freeall(struct snmp_toolinfo * snmptoolctx)1424a7398723SShteryana Shopova snmp_tool_freeall(struct snmp_toolinfo *snmptoolctx)
1425a7398723SShteryana Shopova {
1426a7398723SShteryana Shopova 	if (snmp_client.chost != NULL) {
1427a7398723SShteryana Shopova 		free(snmp_client.chost);
1428a7398723SShteryana Shopova 		snmp_client.chost = NULL;
1429a7398723SShteryana Shopova 	}
1430a7398723SShteryana Shopova 
1431a7398723SShteryana Shopova 	if (snmp_client.cport != NULL) {
1432a7398723SShteryana Shopova 		free(snmp_client.cport);
1433a7398723SShteryana Shopova 		snmp_client.cport = NULL;
1434a7398723SShteryana Shopova 	}
1435a7398723SShteryana Shopova 
1436a7398723SShteryana Shopova 	snmp_mapping_free(snmptoolctx);
1437a7398723SShteryana Shopova 	free_filelist(snmptoolctx);
1438a7398723SShteryana Shopova 	snmp_object_freeall(snmptoolctx);
1439a7398723SShteryana Shopova 
1440a7398723SShteryana Shopova 	if (snmptoolctx->passwd != NULL) {
1441a7398723SShteryana Shopova 		free(snmptoolctx->passwd);
1442a7398723SShteryana Shopova 		snmptoolctx->passwd = NULL;
1443a7398723SShteryana Shopova 	}
1444a7398723SShteryana Shopova }
1445a7398723SShteryana Shopova 
1446a7398723SShteryana Shopova /*
1447a7398723SShteryana Shopova  * Fill all variables from the object list into a PDU. (snmp_verify_vbind_f)
1448a7398723SShteryana Shopova  * function should check whether the variable is consistent in this PDU
1449a7398723SShteryana Shopova  * (e.g do not add non-leaf OIDs to a GET PDU, or OIDs with read access only to
1450a7398723SShteryana Shopova  * a SET PDU) - might be NULL though. (snmp_add_vbind_f) function is the
1451a7398723SShteryana Shopova  * function actually adds the variable to the PDU and must not be NULL.
1452a7398723SShteryana Shopova  */
1453a7398723SShteryana Shopova int32_t
snmp_pdu_add_bindings(struct snmp_toolinfo * snmptoolctx,snmp_verify_vbind_f vfunc,snmp_add_vbind_f afunc,struct snmp_pdu * pdu,int32_t maxcount)1454a7398723SShteryana Shopova snmp_pdu_add_bindings(struct snmp_toolinfo *snmptoolctx,
1455a7398723SShteryana Shopova     snmp_verify_vbind_f vfunc, snmp_add_vbind_f afunc,
1456a7398723SShteryana Shopova     struct snmp_pdu *pdu, int32_t maxcount)
1457a7398723SShteryana Shopova {
1458a7398723SShteryana Shopova 	int32_t nbindings, abind;
1459a7398723SShteryana Shopova 	struct snmp_object *obj;
1460a7398723SShteryana Shopova 
1461a7398723SShteryana Shopova 	if (pdu == NULL || afunc == NULL)
1462a7398723SShteryana Shopova 		return (-1);
1463a7398723SShteryana Shopova 
1464a7398723SShteryana Shopova 	/* Return 0 in case of no more work todo. */
1465a7398723SShteryana Shopova 	if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist))
1466a7398723SShteryana Shopova 		return (0);
1467a7398723SShteryana Shopova 
1468a7398723SShteryana Shopova 	if (maxcount < 0 || maxcount > SNMP_MAX_BINDINGS) {
1469a7398723SShteryana Shopova 		warnx("maxcount out of range: <0 || >SNMP_MAX_BINDINGS");
1470a7398723SShteryana Shopova 		return (-1);
1471a7398723SShteryana Shopova 	}
1472a7398723SShteryana Shopova 
1473a7398723SShteryana Shopova 	nbindings = 0;
1474a7398723SShteryana Shopova 	SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link) {
1475a7398723SShteryana Shopova 		if ((vfunc != NULL) && (vfunc(snmptoolctx, pdu, obj) < 0)) {
1476a7398723SShteryana Shopova 			nbindings = -1;
1477a7398723SShteryana Shopova 			break;
1478a7398723SShteryana Shopova 		}
1479a7398723SShteryana Shopova 		if ((abind = afunc(pdu, obj)) < 0) {
1480a7398723SShteryana Shopova 			nbindings = -1;
1481a7398723SShteryana Shopova 			break;
1482a7398723SShteryana Shopova 		}
1483a7398723SShteryana Shopova 
1484a7398723SShteryana Shopova 		if (abind > 0) {
1485a7398723SShteryana Shopova 			/* Do not put more varbindings than requested. */
1486a7398723SShteryana Shopova 			if (++nbindings >= maxcount)
1487a7398723SShteryana Shopova 				break;
1488a7398723SShteryana Shopova 		}
1489a7398723SShteryana Shopova 	}
1490a7398723SShteryana Shopova 
1491a7398723SShteryana Shopova 	return (nbindings);
1492a7398723SShteryana Shopova }
1493a7398723SShteryana Shopova 
1494a7398723SShteryana Shopova /*
1495a7398723SShteryana Shopova  * Locate an object in the object list and set a corresponding error status.
1496a7398723SShteryana Shopova  */
1497a7398723SShteryana Shopova int32_t
snmp_object_seterror(struct snmp_toolinfo * snmptoolctx,struct snmp_value * err_value,int32_t error_status)1498a7398723SShteryana Shopova snmp_object_seterror(struct snmp_toolinfo *snmptoolctx,
1499a7398723SShteryana Shopova     struct snmp_value *err_value, int32_t error_status)
1500a7398723SShteryana Shopova {
1501a7398723SShteryana Shopova 	struct snmp_object *obj;
1502a7398723SShteryana Shopova 
1503a7398723SShteryana Shopova 	if (SLIST_EMPTY(&snmptoolctx->snmp_objectlist) || err_value == NULL)
1504a7398723SShteryana Shopova 		return (-1);
1505a7398723SShteryana Shopova 
1506a7398723SShteryana Shopova 	SLIST_FOREACH(obj, &snmptoolctx->snmp_objectlist, link)
1507a7398723SShteryana Shopova 		if (asn_compare_oid(&(err_value->var), &(obj->val.var)) == 0) {
1508a7398723SShteryana Shopova 			obj->error = error_status;
1509a7398723SShteryana Shopova 			return (1);
1510a7398723SShteryana Shopova 		}
1511a7398723SShteryana Shopova 
1512a7398723SShteryana Shopova 	return (0);
1513a7398723SShteryana Shopova }
1514a7398723SShteryana Shopova 
1515a7398723SShteryana Shopova /*
15163df5ecacSUlrich Spörlein  * Check a PDU received in response to a SNMP_PDU_GET/SNMP_PDU_GETBULK request
1517a7398723SShteryana Shopova  * but don't compare syntaxes - when sending a request PDU they must be null.
1518a7398723SShteryana Shopova  * This is a (almost) complete copy of snmp_pdu_check() - with matching syntaxes
15193df5ecacSUlrich Spörlein  * checks and some other checks skipped.
1520a7398723SShteryana Shopova  */
1521a7398723SShteryana Shopova int32_t
snmp_parse_get_resp(struct snmp_pdu * resp,struct snmp_pdu * req)1522a7398723SShteryana Shopova snmp_parse_get_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1523a7398723SShteryana Shopova {
1524a7398723SShteryana Shopova 	uint32_t i;
1525a7398723SShteryana Shopova 
1526a7398723SShteryana Shopova 	for (i = 0; i < req->nbindings; i++) {
1527a7398723SShteryana Shopova 		if (asn_compare_oid(&req->bindings[i].var,
1528a7398723SShteryana Shopova 		    &resp->bindings[i].var) != 0) {
1529a7398723SShteryana Shopova 			warnx("Bad OID in response");
1530a7398723SShteryana Shopova 			return (-1);
1531a7398723SShteryana Shopova 		}
1532a7398723SShteryana Shopova 
1533a7398723SShteryana Shopova 		if (snmp_client.version != SNMP_V1 && (resp->bindings[i].syntax
1534a7398723SShteryana Shopova 		    == SNMP_SYNTAX_NOSUCHOBJECT || resp->bindings[i].syntax ==
1535a7398723SShteryana Shopova 		    SNMP_SYNTAX_NOSUCHINSTANCE))
1536a7398723SShteryana Shopova 			return (0);
1537a7398723SShteryana Shopova 	}
1538a7398723SShteryana Shopova 
1539a7398723SShteryana Shopova 	return (1);
1540a7398723SShteryana Shopova }
1541a7398723SShteryana Shopova 
1542a7398723SShteryana Shopova int32_t
snmp_parse_getbulk_resp(struct snmp_pdu * resp,struct snmp_pdu * req)1543a7398723SShteryana Shopova snmp_parse_getbulk_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1544a7398723SShteryana Shopova {
1545a7398723SShteryana Shopova 	int32_t N, R, M, r;
1546a7398723SShteryana Shopova 
1547a7398723SShteryana Shopova 	if (req->error_status > (int32_t) resp->nbindings) {
1548a7398723SShteryana Shopova 		warnx("Bad number of bindings in response");
1549a7398723SShteryana Shopova 		return (-1);
1550a7398723SShteryana Shopova 	}
1551a7398723SShteryana Shopova 
1552a7398723SShteryana Shopova 	for (N = 0; N < req->error_status; N++) {
1553a7398723SShteryana Shopova 		if (asn_is_suboid(&req->bindings[N].var,
1554a7398723SShteryana Shopova 		    &resp->bindings[N].var) == 0)
1555a7398723SShteryana Shopova 			return (0);
1556a7398723SShteryana Shopova 		if (resp->bindings[N].syntax == SNMP_SYNTAX_ENDOFMIBVIEW)
1557a7398723SShteryana Shopova 			return (0);
1558a7398723SShteryana Shopova 	}
1559a7398723SShteryana Shopova 
1560a7398723SShteryana Shopova 	for (R = N , r = N; R  < (int32_t) req->nbindings; R++) {
1561a7398723SShteryana Shopova 		for (M = 0; M < req->error_index && (r + M) <
1562a7398723SShteryana Shopova 		    (int32_t) resp->nbindings; M++) {
1563a7398723SShteryana Shopova 			if (asn_is_suboid(&req->bindings[R].var,
1564a7398723SShteryana Shopova 			    &resp->bindings[r + M].var) == 0)
1565a7398723SShteryana Shopova 				return (0);
1566a7398723SShteryana Shopova 
1567a7398723SShteryana Shopova 			if (resp->bindings[r + M].syntax ==
1568a7398723SShteryana Shopova 			    SNMP_SYNTAX_ENDOFMIBVIEW) {
1569a7398723SShteryana Shopova 				M++;
1570a7398723SShteryana Shopova 				break;
1571a7398723SShteryana Shopova 			}
1572a7398723SShteryana Shopova 		}
1573a7398723SShteryana Shopova 		r += M;
1574a7398723SShteryana Shopova 	}
1575a7398723SShteryana Shopova 
1576a7398723SShteryana Shopova 	return (0);
1577a7398723SShteryana Shopova }
1578a7398723SShteryana Shopova 
1579a7398723SShteryana Shopova int32_t
snmp_parse_getnext_resp(struct snmp_pdu * resp,struct snmp_pdu * req)1580a7398723SShteryana Shopova snmp_parse_getnext_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1581a7398723SShteryana Shopova {
1582a7398723SShteryana Shopova 	uint32_t i;
1583a7398723SShteryana Shopova 
1584a7398723SShteryana Shopova 	for (i = 0; i < req->nbindings; i++) {
1585a7398723SShteryana Shopova 		if (asn_is_suboid(&req->bindings[i].var, &resp->bindings[i].var)
1586a7398723SShteryana Shopova 		    == 0)
1587a7398723SShteryana Shopova 			return (0);
1588a7398723SShteryana Shopova 
1589a7398723SShteryana Shopova 		if (resp->version != SNMP_V1 && resp->bindings[i].syntax ==
1590a7398723SShteryana Shopova 		    SNMP_SYNTAX_ENDOFMIBVIEW)
1591a7398723SShteryana Shopova 			return (0);
1592a7398723SShteryana Shopova 	}
1593a7398723SShteryana Shopova 
1594a7398723SShteryana Shopova 	return (1);
1595a7398723SShteryana Shopova }
1596a7398723SShteryana Shopova 
1597a7398723SShteryana Shopova /*
15983df5ecacSUlrich Spörlein  * Should be called to check a response to get/getnext/getbulk.
1599a7398723SShteryana Shopova  */
1600a7398723SShteryana Shopova int32_t
snmp_parse_resp(struct snmp_pdu * resp,struct snmp_pdu * req)1601a7398723SShteryana Shopova snmp_parse_resp(struct snmp_pdu *resp, struct snmp_pdu *req)
1602a7398723SShteryana Shopova {
1603a7398723SShteryana Shopova 	if (resp == NULL || req == NULL)
1604a7398723SShteryana Shopova 		return (-2);
1605a7398723SShteryana Shopova 
1606a7398723SShteryana Shopova 	if (resp->version != req->version) {
1607a7398723SShteryana Shopova 		warnx("Response has wrong version");
1608a7398723SShteryana Shopova 		return (-1);
1609a7398723SShteryana Shopova 	}
1610a7398723SShteryana Shopova 
1611a7398723SShteryana Shopova 	if (resp->error_status == SNMP_ERR_NOSUCHNAME) {
1612a7398723SShteryana Shopova 		warnx("Error - No Such Name");
1613a7398723SShteryana Shopova 		return (0);
1614a7398723SShteryana Shopova 	}
1615a7398723SShteryana Shopova 
1616a7398723SShteryana Shopova 	if (resp->error_status != SNMP_ERR_NOERROR) {
16173df5ecacSUlrich Spörlein 		warnx("Error %d in response", resp->error_status);
1618a7398723SShteryana Shopova 		return (-1);
1619a7398723SShteryana Shopova 	}
1620a7398723SShteryana Shopova 
1621a7398723SShteryana Shopova 	if (resp->nbindings != req->nbindings && req->type != SNMP_PDU_GETBULK){
1622a7398723SShteryana Shopova 		warnx("Bad number of bindings in response");
1623a7398723SShteryana Shopova 		return (-1);
1624a7398723SShteryana Shopova 	}
1625a7398723SShteryana Shopova 
1626a7398723SShteryana Shopova 	switch (req->type) {
1627a7398723SShteryana Shopova 		case SNMP_PDU_GET:
1628a7398723SShteryana Shopova 			return (snmp_parse_get_resp(resp,req));
1629a7398723SShteryana Shopova 		case SNMP_PDU_GETBULK:
1630a7398723SShteryana Shopova 			return (snmp_parse_getbulk_resp(resp,req));
1631a7398723SShteryana Shopova 		case SNMP_PDU_GETNEXT:
1632a7398723SShteryana Shopova 			return (snmp_parse_getnext_resp(resp,req));
1633a7398723SShteryana Shopova 		default:
1634a7398723SShteryana Shopova 			/* NOTREACHED */
1635a7398723SShteryana Shopova 			break;
1636a7398723SShteryana Shopova 	}
1637a7398723SShteryana Shopova 
1638a7398723SShteryana Shopova 	return (-2);
1639a7398723SShteryana Shopova }
1640a7398723SShteryana Shopova 
1641a7398723SShteryana Shopova static void
snmp_output_octetstring(struct snmp_toolinfo * snmptoolctx,enum snmp_tc tc,uint32_t len,uint8_t * octets)1642a7398723SShteryana Shopova snmp_output_octetstring(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc,
1643a7398723SShteryana Shopova     uint32_t len, uint8_t *octets)
1644a7398723SShteryana Shopova {
1645a7398723SShteryana Shopova 	char *buf;
1646a7398723SShteryana Shopova 
1647a7398723SShteryana Shopova 	if (len == 0 || octets == NULL)
1648a7398723SShteryana Shopova 		return;
1649a7398723SShteryana Shopova 
1650a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1651a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1652a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_OCTETSTRING].str);
1653a7398723SShteryana Shopova 
1654a7398723SShteryana Shopova 	if ((buf = snmp_oct2tc(tc, len, (char *) octets)) != NULL) {
1655a7398723SShteryana Shopova 		fprintf(stdout, "%s", buf);
1656a7398723SShteryana Shopova 		free(buf);
1657a7398723SShteryana Shopova 	}
1658a7398723SShteryana Shopova }
1659a7398723SShteryana Shopova 
1660a7398723SShteryana Shopova static void
snmp_output_octetindex(struct snmp_toolinfo * snmptoolctx,enum snmp_tc tc,struct asn_oid * oid)1661a7398723SShteryana Shopova snmp_output_octetindex(struct snmp_toolinfo *snmptoolctx, enum snmp_tc tc,
1662a7398723SShteryana Shopova     struct asn_oid *oid)
1663a7398723SShteryana Shopova {
1664a7398723SShteryana Shopova 	uint32_t i;
1665a7398723SShteryana Shopova 	uint8_t *s;
1666a7398723SShteryana Shopova 
1667a7398723SShteryana Shopova 	if ((s = malloc(oid->subs[0] + 1)) == NULL)
1668a7398723SShteryana Shopova 		syslog(LOG_ERR, "malloc failed - %s", strerror(errno));
1669a7398723SShteryana Shopova 	else {
1670a7398723SShteryana Shopova 		for (i = 0; i < oid->subs[0]; i++)
1671a7398723SShteryana Shopova 			s[i] = (u_char) (oid->subs[i + 1]);
1672a7398723SShteryana Shopova 
1673a7398723SShteryana Shopova 		snmp_output_octetstring(snmptoolctx, tc, oid->subs[0], s);
1674a7398723SShteryana Shopova 		free(s);
1675a7398723SShteryana Shopova 	}
1676a7398723SShteryana Shopova }
1677a7398723SShteryana Shopova 
1678a7398723SShteryana Shopova /*
1679a7398723SShteryana Shopova  * Check and output syntax type and value.
1680a7398723SShteryana Shopova  */
1681a7398723SShteryana Shopova static void
snmp_output_oid_value(struct snmp_toolinfo * snmptoolctx,struct asn_oid * oid)1682a7398723SShteryana Shopova snmp_output_oid_value(struct snmp_toolinfo *snmptoolctx, struct asn_oid *oid)
1683a7398723SShteryana Shopova {
1684a7398723SShteryana Shopova 	char oid_string[ASN_OIDSTRLEN];
1685a7398723SShteryana Shopova 	struct snmp_object obj;
1686a7398723SShteryana Shopova 
1687a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1688a7398723SShteryana Shopova 		fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_OID].str);
1689a7398723SShteryana Shopova 
1690a7398723SShteryana Shopova 	if(!ISSET_NUMERIC(snmptoolctx)) {
1691a7398723SShteryana Shopova 		memset(&obj, 0, sizeof(struct snmp_object));
1692a7398723SShteryana Shopova 		asn_append_oid(&(obj.val.var), oid);
1693a7398723SShteryana Shopova 
1694a7398723SShteryana Shopova 		if (snmp_lookup_enumstring(snmptoolctx, &obj) > 0)
1695a7398723SShteryana Shopova 			fprintf(stdout, "%s" , obj.info->string);
1696a7398723SShteryana Shopova 		else if (snmp_lookup_oidstring(snmptoolctx, &obj) > 0)
1697a7398723SShteryana Shopova 			fprintf(stdout, "%s" , obj.info->string);
1698a7398723SShteryana Shopova 		else if (snmp_lookup_nodestring(snmptoolctx, &obj) > 0)
1699a7398723SShteryana Shopova 			fprintf(stdout, "%s" , obj.info->string);
1700a7398723SShteryana Shopova 		else {
1701a7398723SShteryana Shopova 			(void) asn_oid2str_r(oid, oid_string);
1702a7398723SShteryana Shopova 			fprintf(stdout, "%s", oid_string);
1703a7398723SShteryana Shopova 		}
1704a7398723SShteryana Shopova 	} else {
1705a7398723SShteryana Shopova 		(void) asn_oid2str_r(oid, oid_string);
1706a7398723SShteryana Shopova 		fprintf(stdout, "%s", oid_string);
1707a7398723SShteryana Shopova 	}
1708a7398723SShteryana Shopova }
1709a7398723SShteryana Shopova 
1710a7398723SShteryana Shopova static void
snmp_output_int(struct snmp_toolinfo * snmptoolctx,struct enum_pairs * enums,int32_t int_val)1711a7398723SShteryana Shopova snmp_output_int(struct snmp_toolinfo *snmptoolctx, struct enum_pairs *enums,
1712a7398723SShteryana Shopova     int32_t int_val)
1713a7398723SShteryana Shopova {
1714a7398723SShteryana Shopova 	char *string;
1715a7398723SShteryana Shopova 
1716a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1717a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1718a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_INTEGER].str);
1719a7398723SShteryana Shopova 
1720a7398723SShteryana Shopova 	if (enums != NULL && (string = enum_string_lookup(enums, int_val))
1721a7398723SShteryana Shopova 	    != NULL)
1722a7398723SShteryana Shopova 		fprintf(stdout, "%s", string);
1723a7398723SShteryana Shopova 	else
1724a7398723SShteryana Shopova 		fprintf(stdout, "%d", int_val);
1725a7398723SShteryana Shopova }
1726a7398723SShteryana Shopova 
1727a7398723SShteryana Shopova static void
snmp_output_ipaddress(struct snmp_toolinfo * snmptoolctx,uint8_t * ip)1728a7398723SShteryana Shopova snmp_output_ipaddress(struct snmp_toolinfo *snmptoolctx, uint8_t *ip)
1729a7398723SShteryana Shopova {
1730a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1731a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1732a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_IPADDRESS].str);
1733a7398723SShteryana Shopova 
1734a7398723SShteryana Shopova 	fprintf(stdout, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1735a7398723SShteryana Shopova }
1736a7398723SShteryana Shopova 
1737a7398723SShteryana Shopova static void
snmp_output_counter(struct snmp_toolinfo * snmptoolctx,uint32_t counter)1738a7398723SShteryana Shopova snmp_output_counter(struct snmp_toolinfo *snmptoolctx, uint32_t counter)
1739a7398723SShteryana Shopova {
1740a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1741a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1742a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_COUNTER].str);
1743a7398723SShteryana Shopova 
1744a7398723SShteryana Shopova 	fprintf(stdout, "%u", counter);
1745a7398723SShteryana Shopova }
1746a7398723SShteryana Shopova 
1747a7398723SShteryana Shopova static void
snmp_output_gauge(struct snmp_toolinfo * snmptoolctx,uint32_t gauge)1748a7398723SShteryana Shopova snmp_output_gauge(struct snmp_toolinfo *snmptoolctx, uint32_t gauge)
1749a7398723SShteryana Shopova {
1750a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1751a7398723SShteryana Shopova 		fprintf(stdout, "%s : ", syntax_strings[SNMP_SYNTAX_GAUGE].str);
1752a7398723SShteryana Shopova 
1753a7398723SShteryana Shopova 	fprintf(stdout, "%u", gauge);
1754a7398723SShteryana Shopova }
1755a7398723SShteryana Shopova 
1756a7398723SShteryana Shopova static void
snmp_output_ticks(struct snmp_toolinfo * snmptoolctx,uint32_t ticks)1757a7398723SShteryana Shopova snmp_output_ticks(struct snmp_toolinfo *snmptoolctx, uint32_t ticks)
1758a7398723SShteryana Shopova {
1759a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1760a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1761a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_TIMETICKS].str);
1762a7398723SShteryana Shopova 
1763a7398723SShteryana Shopova 	fprintf(stdout, "%u", ticks);
1764a7398723SShteryana Shopova }
1765a7398723SShteryana Shopova 
1766a7398723SShteryana Shopova static void
snmp_output_counter64(struct snmp_toolinfo * snmptoolctx,uint64_t counter64)1767a7398723SShteryana Shopova snmp_output_counter64(struct snmp_toolinfo *snmptoolctx, uint64_t counter64)
1768a7398723SShteryana Shopova {
1769a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) == OUTPUT_VERBOSE)
1770a7398723SShteryana Shopova 		fprintf(stdout, "%s : ",
1771a7398723SShteryana Shopova 		    syntax_strings[SNMP_SYNTAX_COUNTER64].str);
1772a7398723SShteryana Shopova 
1773a7398723SShteryana Shopova 	fprintf(stdout,"%ju", counter64);
1774a7398723SShteryana Shopova }
1775a7398723SShteryana Shopova 
1776a7398723SShteryana Shopova int32_t
snmp_output_numval(struct snmp_toolinfo * snmptoolctx,struct snmp_value * val,struct snmp_oid2str * entry)1777a7398723SShteryana Shopova snmp_output_numval(struct snmp_toolinfo *snmptoolctx, struct snmp_value *val,
1778a7398723SShteryana Shopova     struct snmp_oid2str *entry)
1779a7398723SShteryana Shopova {
1780a7398723SShteryana Shopova 	if (val == NULL)
1781a7398723SShteryana Shopova 		return (-1);
1782a7398723SShteryana Shopova 
1783a7398723SShteryana Shopova 	if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET)
1784a7398723SShteryana Shopova 		fprintf(stdout, " = ");
1785a7398723SShteryana Shopova 
1786a7398723SShteryana Shopova 	switch (val->syntax) {
1787a7398723SShteryana Shopova 	    case SNMP_SYNTAX_INTEGER:
1788a7398723SShteryana Shopova 		if (entry != NULL)
1789a7398723SShteryana Shopova 			snmp_output_int(snmptoolctx, entry->snmp_enum,
1790a7398723SShteryana Shopova 			    val->v.integer);
1791a7398723SShteryana Shopova 		else
1792a7398723SShteryana Shopova 			snmp_output_int(snmptoolctx, NULL, val->v.integer);
1793a7398723SShteryana Shopova 		break;
1794a7398723SShteryana Shopova 
1795a7398723SShteryana Shopova 	    case SNMP_SYNTAX_OCTETSTRING:
1796a7398723SShteryana Shopova 		if (entry != NULL)
1797a7398723SShteryana Shopova 			snmp_output_octetstring(snmptoolctx, entry->tc,
1798a7398723SShteryana Shopova 			    val->v.octetstring.len, val->v.octetstring.octets);
1799a7398723SShteryana Shopova 		else
1800a7398723SShteryana Shopova 			snmp_output_octetstring(snmptoolctx, SNMP_STRING,
1801a7398723SShteryana Shopova 			    val->v.octetstring.len, val->v.octetstring.octets);
1802a7398723SShteryana Shopova 		break;
1803a7398723SShteryana Shopova 
1804a7398723SShteryana Shopova 	    case SNMP_SYNTAX_OID:
1805a7398723SShteryana Shopova 		snmp_output_oid_value(snmptoolctx, &(val->v.oid));
1806a7398723SShteryana Shopova 		break;
1807a7398723SShteryana Shopova 
1808a7398723SShteryana Shopova 	    case SNMP_SYNTAX_IPADDRESS:
1809a7398723SShteryana Shopova 		snmp_output_ipaddress(snmptoolctx, val->v.ipaddress);
1810a7398723SShteryana Shopova 		break;
1811a7398723SShteryana Shopova 
1812a7398723SShteryana Shopova 	    case SNMP_SYNTAX_COUNTER:
1813a7398723SShteryana Shopova 		snmp_output_counter(snmptoolctx, val->v.uint32);
1814a7398723SShteryana Shopova 		break;
1815a7398723SShteryana Shopova 
1816a7398723SShteryana Shopova 	    case SNMP_SYNTAX_GAUGE:
1817a7398723SShteryana Shopova 		snmp_output_gauge(snmptoolctx, val->v.uint32);
1818a7398723SShteryana Shopova 		break;
1819a7398723SShteryana Shopova 
1820a7398723SShteryana Shopova 	    case SNMP_SYNTAX_TIMETICKS:
1821a7398723SShteryana Shopova 		snmp_output_ticks(snmptoolctx, val->v.uint32);
1822a7398723SShteryana Shopova 		break;
1823a7398723SShteryana Shopova 
1824a7398723SShteryana Shopova 	    case SNMP_SYNTAX_COUNTER64:
1825a7398723SShteryana Shopova 		snmp_output_counter64(snmptoolctx, val->v.counter64);
1826a7398723SShteryana Shopova 		break;
1827a7398723SShteryana Shopova 
1828a7398723SShteryana Shopova 	    case SNMP_SYNTAX_NOSUCHOBJECT:
1829dca51295SEugene Grosbein 		fprintf(stderr, "No Such Object\n");
1830a7398723SShteryana Shopova 		return (val->syntax);
1831a7398723SShteryana Shopova 
1832a7398723SShteryana Shopova 	    case SNMP_SYNTAX_NOSUCHINSTANCE:
1833dca51295SEugene Grosbein 		fprintf(stderr, "No Such Instance\n");
1834a7398723SShteryana Shopova 		return (val->syntax);
1835a7398723SShteryana Shopova 
1836a7398723SShteryana Shopova 	    case SNMP_SYNTAX_ENDOFMIBVIEW:
1837a7398723SShteryana Shopova 		fprintf(stdout, "End of Mib View\n");
1838a7398723SShteryana Shopova 		return (val->syntax);
1839a7398723SShteryana Shopova 
1840a7398723SShteryana Shopova 	    case SNMP_SYNTAX_NULL:
1841a7398723SShteryana Shopova 		/* NOTREACHED */
1842dca51295SEugene Grosbein 		fprintf(stderr, "agent returned NULL Syntax\n");
1843a7398723SShteryana Shopova 		return (val->syntax);
1844a7398723SShteryana Shopova 
1845a7398723SShteryana Shopova 	    default:
1846a7398723SShteryana Shopova 		/* NOTREACHED - If here - then all went completely wrong. */
1847dca51295SEugene Grosbein 		fprintf(stderr, "agent returned unknown syntax\n");
1848a7398723SShteryana Shopova 		return (-1);
1849a7398723SShteryana Shopova 	}
1850a7398723SShteryana Shopova 
1851a7398723SShteryana Shopova 	fprintf(stdout, "\n");
1852a7398723SShteryana Shopova 
1853a7398723SShteryana Shopova 	return (0);
1854a7398723SShteryana Shopova }
1855a7398723SShteryana Shopova 
1856a7398723SShteryana Shopova static int32_t
snmp_fill_object(struct snmp_toolinfo * snmptoolctx,struct snmp_object * obj,struct snmp_value * val)1857a7398723SShteryana Shopova snmp_fill_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *obj,
1858a7398723SShteryana Shopova     struct snmp_value *val)
1859a7398723SShteryana Shopova {
1860a7398723SShteryana Shopova 	int32_t rc;
1861a7398723SShteryana Shopova 	asn_subid_t suboid;
1862a7398723SShteryana Shopova 
1863a7398723SShteryana Shopova 	if (obj == NULL || val == NULL)
1864a7398723SShteryana Shopova 		return (-1);
1865a7398723SShteryana Shopova 
1866a7398723SShteryana Shopova 	if ((suboid = snmp_suboid_pop(&(val->var))) > ASN_MAXID)
1867a7398723SShteryana Shopova 		return (-1);
1868a7398723SShteryana Shopova 
1869a7398723SShteryana Shopova 	memset(obj, 0, sizeof(struct snmp_object));
1870a7398723SShteryana Shopova 	asn_append_oid(&(obj->val.var), &(val->var));
1871a7398723SShteryana Shopova 	obj->val.syntax = val->syntax;
1872a7398723SShteryana Shopova 
1873a7398723SShteryana Shopova 	if (obj->val.syntax > 0)
1874a7398723SShteryana Shopova 		rc = snmp_lookup_leafstring(snmptoolctx, obj);
1875a7398723SShteryana Shopova 	else
1876a7398723SShteryana Shopova 		rc = snmp_lookup_nonleaf_string(snmptoolctx, obj);
1877a7398723SShteryana Shopova 
1878a7398723SShteryana Shopova 	(void) snmp_suboid_append(&(val->var), suboid);
1879a7398723SShteryana Shopova 	(void) snmp_suboid_append(&(obj->val.var), suboid);
1880a7398723SShteryana Shopova 
1881a7398723SShteryana Shopova 	return (rc);
1882a7398723SShteryana Shopova }
1883a7398723SShteryana Shopova 
1884a7398723SShteryana Shopova static int32_t
snmp_output_index(struct snmp_toolinfo * snmptoolctx,struct index * stx,struct asn_oid * oid)1885a7398723SShteryana Shopova snmp_output_index(struct snmp_toolinfo *snmptoolctx, struct index *stx,
1886a7398723SShteryana Shopova     struct asn_oid *oid)
1887a7398723SShteryana Shopova {
1888a7398723SShteryana Shopova 	uint8_t ip[4];
1889a7398723SShteryana Shopova 	uint32_t bytes = 1;
1890a7398723SShteryana Shopova 	uint64_t cnt64;
1891a7398723SShteryana Shopova 	struct asn_oid temp, out;
1892a7398723SShteryana Shopova 
1893a7398723SShteryana Shopova 	if (oid->len < bytes)
1894a7398723SShteryana Shopova 		return (-1);
1895a7398723SShteryana Shopova 
1896a7398723SShteryana Shopova 	memset(&temp, 0, sizeof(struct asn_oid));
1897a7398723SShteryana Shopova 	asn_append_oid(&temp, oid);
1898a7398723SShteryana Shopova 
1899a7398723SShteryana Shopova 	switch (stx->syntax) {
1900a7398723SShteryana Shopova 	    case SNMP_SYNTAX_INTEGER:
1901a7398723SShteryana Shopova 		snmp_output_int(snmptoolctx, stx->snmp_enum, temp.subs[0]);
1902a7398723SShteryana Shopova 		break;
1903a7398723SShteryana Shopova 
1904a7398723SShteryana Shopova 	    case SNMP_SYNTAX_OCTETSTRING:
1905a7398723SShteryana Shopova 		if ((temp.subs[0] > temp.len -1 ) || (temp.subs[0] >
1906a7398723SShteryana Shopova 		    ASN_MAXOCTETSTRING))
1907a7398723SShteryana Shopova 			return (-1);
1908a7398723SShteryana Shopova 		snmp_output_octetindex(snmptoolctx, stx->tc, &temp);
1909a7398723SShteryana Shopova 		bytes += temp.subs[0];
1910a7398723SShteryana Shopova 		break;
1911a7398723SShteryana Shopova 
1912a7398723SShteryana Shopova 	    case SNMP_SYNTAX_OID:
1913a7398723SShteryana Shopova 		if ((temp.subs[0] > temp.len -1) || (temp.subs[0] >
1914a7398723SShteryana Shopova 		    ASN_MAXOIDLEN))
1915a7398723SShteryana Shopova 			return (-1);
1916a7398723SShteryana Shopova 
1917a7398723SShteryana Shopova 		bytes += temp.subs[0];
1918a7398723SShteryana Shopova 		memset(&out, 0, sizeof(struct asn_oid));
1919a7398723SShteryana Shopova 		asn_slice_oid(&out, &temp, 1, bytes);
1920a7398723SShteryana Shopova 		snmp_output_oid_value(snmptoolctx, &out);
1921a7398723SShteryana Shopova 		break;
1922a7398723SShteryana Shopova 
1923a7398723SShteryana Shopova 	    case SNMP_SYNTAX_IPADDRESS:
1924a7398723SShteryana Shopova 		if (temp.len < 4)
1925a7398723SShteryana Shopova 			return (-1);
1926a7398723SShteryana Shopova 		for (bytes = 0; bytes < 4; bytes++)
1927a7398723SShteryana Shopova 			ip[bytes] = temp.subs[bytes];
1928a7398723SShteryana Shopova 
1929a7398723SShteryana Shopova 		snmp_output_ipaddress(snmptoolctx, ip);
1930a7398723SShteryana Shopova 		bytes = 4;
1931a7398723SShteryana Shopova 		break;
1932a7398723SShteryana Shopova 
1933a7398723SShteryana Shopova 	    case SNMP_SYNTAX_COUNTER:
1934a7398723SShteryana Shopova 		snmp_output_counter(snmptoolctx, temp.subs[0]);
1935a7398723SShteryana Shopova 		break;
1936a7398723SShteryana Shopova 
1937a7398723SShteryana Shopova 	    case SNMP_SYNTAX_GAUGE:
1938a7398723SShteryana Shopova 		snmp_output_gauge(snmptoolctx, temp.subs[0]);
1939a7398723SShteryana Shopova 		break;
1940a7398723SShteryana Shopova 
1941a7398723SShteryana Shopova 	    case SNMP_SYNTAX_TIMETICKS:
1942a7398723SShteryana Shopova 		snmp_output_ticks(snmptoolctx, temp.subs[0]);
1943a7398723SShteryana Shopova 		break;
1944a7398723SShteryana Shopova 
1945a7398723SShteryana Shopova 	    case SNMP_SYNTAX_COUNTER64:
1946a7398723SShteryana Shopova 		if (oid->len < 2)
1947a7398723SShteryana Shopova 			return (-1);
1948a7398723SShteryana Shopova 		bytes = 2;
1949a7398723SShteryana Shopova 		memcpy(&cnt64, temp.subs, bytes);
1950a7398723SShteryana Shopova 		snmp_output_counter64(snmptoolctx, cnt64);
1951a7398723SShteryana Shopova 		break;
1952a7398723SShteryana Shopova 
1953a7398723SShteryana Shopova 	    default:
1954a7398723SShteryana Shopova 		return (-1);
1955a7398723SShteryana Shopova 	}
1956a7398723SShteryana Shopova 
1957a7398723SShteryana Shopova 	return (bytes);
1958a7398723SShteryana Shopova }
1959a7398723SShteryana Shopova 
1960a7398723SShteryana Shopova static int32_t
snmp_output_object(struct snmp_toolinfo * snmptoolctx,struct snmp_object * o)1961a7398723SShteryana Shopova snmp_output_object(struct snmp_toolinfo *snmptoolctx, struct snmp_object *o)
1962a7398723SShteryana Shopova {
1963a7398723SShteryana Shopova 	int32_t i, first, len;
1964a7398723SShteryana Shopova 	struct asn_oid oid;
1965a7398723SShteryana Shopova 	struct index *temp;
1966a7398723SShteryana Shopova 
1967a7398723SShteryana Shopova 	if (ISSET_NUMERIC(snmptoolctx))
1968a7398723SShteryana Shopova 		return (-1);
1969a7398723SShteryana Shopova 
1970a7398723SShteryana Shopova 	if (o->info->table_idx == NULL) {
1971a7398723SShteryana Shopova 		fprintf(stdout,"%s.%d", o->info->string,
1972a7398723SShteryana Shopova 		    o->val.var.subs[o->val.var.len - 1]);
1973a7398723SShteryana Shopova 		return (1);
1974a7398723SShteryana Shopova 	}
1975a7398723SShteryana Shopova 
1976a7398723SShteryana Shopova 	fprintf(stdout,"%s[", o->info->string);
1977a7398723SShteryana Shopova 	memset(&oid, 0, sizeof(struct asn_oid));
1978a7398723SShteryana Shopova 
1979a7398723SShteryana Shopova 	len = 1;
1980a7398723SShteryana Shopova 	asn_slice_oid(&oid, &(o->val.var), (o->info->table_idx->var.len + len),
1981a7398723SShteryana Shopova 	    o->val.var.len);
1982a7398723SShteryana Shopova 
1983a7398723SShteryana Shopova 	first = 1;
1984a7398723SShteryana Shopova 	STAILQ_FOREACH(temp, &(OBJECT_IDX_LIST(o)), link) {
1985a7398723SShteryana Shopova 		if(first)
1986a7398723SShteryana Shopova 			first = 0;
1987a7398723SShteryana Shopova 		else
1988a7398723SShteryana Shopova 			fprintf(stdout, ", ");
1989a7398723SShteryana Shopova 		if ((i = snmp_output_index(snmptoolctx, temp, &oid)) < 0)
1990a7398723SShteryana Shopova 			break;
1991a7398723SShteryana Shopova 		len += i;
1992a7398723SShteryana Shopova 		memset(&oid, 0, sizeof(struct asn_oid));
1993a7398723SShteryana Shopova 		asn_slice_oid(&oid, &(o->val.var),
1994a7398723SShteryana Shopova 		    (o->info->table_idx->var.len + len), o->val.var.len + 1);
1995a7398723SShteryana Shopova 	}
1996a7398723SShteryana Shopova 
1997a7398723SShteryana Shopova 	fprintf(stdout,"]");
1998a7398723SShteryana Shopova 	return (1);
1999a7398723SShteryana Shopova }
2000a7398723SShteryana Shopova 
2001a7398723SShteryana Shopova void
snmp_output_err_resp(struct snmp_toolinfo * snmptoolctx,struct snmp_pdu * pdu)2002a7398723SShteryana Shopova snmp_output_err_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu)
2003a7398723SShteryana Shopova {
200486b3c169SEnji Cooper 	struct snmp_object *object;
2005a7398723SShteryana Shopova 	char buf[ASN_OIDSTRLEN];
2006a7398723SShteryana Shopova 
2007a7398723SShteryana Shopova 	if (pdu == NULL || (pdu->error_index > (int32_t) pdu->nbindings)) {
2008a7398723SShteryana Shopova 		fprintf(stdout, "Invalid error index in PDU\n");
2009a7398723SShteryana Shopova 		return;
2010a7398723SShteryana Shopova 	}
2011a7398723SShteryana Shopova 
2012b85e09dbSEnji Cooper 	if ((object = calloc(1, sizeof(struct snmp_object))) == NULL) {
201386b3c169SEnji Cooper 		fprintf(stdout, "calloc: %s", strerror(errno));
201486b3c169SEnji Cooper 		return;
201586b3c169SEnji Cooper 	}
201686b3c169SEnji Cooper 
2017a7398723SShteryana Shopova 	fprintf(stdout, "Agent %s:%s returned error \n", snmp_client.chost,
2018a7398723SShteryana Shopova 	    snmp_client.cport);
2019a7398723SShteryana Shopova 
202086b3c169SEnji Cooper 	if (!ISSET_NUMERIC(snmptoolctx) && (snmp_fill_object(snmptoolctx, object,
2021a7398723SShteryana Shopova 	    &(pdu->bindings[pdu->error_index - 1])) > 0))
202286b3c169SEnji Cooper 		snmp_output_object(snmptoolctx, object);
2023a7398723SShteryana Shopova 	else {
2024a7398723SShteryana Shopova 		asn_oid2str_r(&(pdu->bindings[pdu->error_index - 1].var), buf);
2025a7398723SShteryana Shopova 		fprintf(stdout,"%s", buf);
2026a7398723SShteryana Shopova 	}
2027a7398723SShteryana Shopova 
2028a7398723SShteryana Shopova 	fprintf(stdout," caused error - ");
2029a7398723SShteryana Shopova 	if ((pdu->error_status > 0) && (pdu->error_status <=
2030a7398723SShteryana Shopova 	    SNMP_ERR_INCONS_NAME))
2031a7398723SShteryana Shopova 		fprintf(stdout, "%s\n", error_strings[pdu->error_status].str);
2032a7398723SShteryana Shopova 	else
2033a7398723SShteryana Shopova 		fprintf(stdout,"%s\n", error_strings[SNMP_ERR_UNKNOWN].str);
203486b3c169SEnji Cooper 
203586b3c169SEnji Cooper 	free(object);
203686b3c169SEnji Cooper 	object = NULL;
2037a7398723SShteryana Shopova }
2038a7398723SShteryana Shopova 
2039a7398723SShteryana Shopova int32_t
snmp_output_resp(struct snmp_toolinfo * snmptoolctx,struct snmp_pdu * pdu,struct asn_oid * root)2040b9288caaSShteryana Shopova snmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu,
2041b9288caaSShteryana Shopova     struct asn_oid *root)
2042a7398723SShteryana Shopova {
204386b3c169SEnji Cooper 	struct snmp_object *object;
204409fe010eSEnji Cooper 	char p[ASN_OIDSTRLEN];
204509fe010eSEnji Cooper 	int32_t error;
204609fe010eSEnji Cooper 	uint32_t i;
2047a7398723SShteryana Shopova 
204886b3c169SEnji Cooper 	if ((object = calloc(1, sizeof(struct snmp_object))) == NULL)
204986b3c169SEnji Cooper 		return (-1);
205086b3c169SEnji Cooper 
2051b9288caaSShteryana Shopova 	i = error = 0;
2052b9288caaSShteryana Shopova 	while (i < pdu->nbindings) {
2053b9288caaSShteryana Shopova 		if (root != NULL && !(asn_is_suboid(root,
2054b9288caaSShteryana Shopova 		    &(pdu->bindings[i].var))))
2055b9288caaSShteryana Shopova 			break;
2056b9288caaSShteryana Shopova 
2057a7398723SShteryana Shopova 		if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) {
2058a7398723SShteryana Shopova 			if (!ISSET_NUMERIC(snmptoolctx) &&
205986b3c169SEnji Cooper 			    (snmp_fill_object(snmptoolctx, object,
2060a7398723SShteryana Shopova 			    &(pdu->bindings[i])) > 0))
206186b3c169SEnji Cooper 				snmp_output_object(snmptoolctx, object);
2062a7398723SShteryana Shopova 			else {
2063a7398723SShteryana Shopova 				asn_oid2str_r(&(pdu->bindings[i].var), p);
2064a7398723SShteryana Shopova 				fprintf(stdout, "%s", p);
2065a7398723SShteryana Shopova 			}
2066a7398723SShteryana Shopova 		}
206786b3c169SEnji Cooper 		error |= snmp_output_numval(snmptoolctx, &(pdu->bindings[i]),
206886b3c169SEnji Cooper 		    object->info);
2069b9288caaSShteryana Shopova 		i++;
2070a7398723SShteryana Shopova 	}
2071a7398723SShteryana Shopova 
207286b3c169SEnji Cooper 	free(object);
207386b3c169SEnji Cooper 	object = NULL;
207486b3c169SEnji Cooper 
2075b9288caaSShteryana Shopova 	if (error)
2076b9288caaSShteryana Shopova 		return (-1);
2077b9288caaSShteryana Shopova 
2078b9288caaSShteryana Shopova 	return (i);
2079a7398723SShteryana Shopova }
2080a7398723SShteryana Shopova 
2081a7398723SShteryana Shopova void
snmp_output_engine(void)2082a7398723SShteryana Shopova snmp_output_engine(void)
2083a7398723SShteryana Shopova {
2084a7398723SShteryana Shopova 	uint32_t i;
2085a7398723SShteryana Shopova 	char *cptr, engine[2 * SNMP_ENGINE_ID_SIZ + 2];
2086a7398723SShteryana Shopova 
2087a7398723SShteryana Shopova 	cptr = engine;
2088a7398723SShteryana Shopova 	for (i = 0; i < snmp_client.engine.engine_len; i++)
2089a7398723SShteryana Shopova 		cptr += sprintf(cptr, "%.2x", snmp_client.engine.engine_id[i]);
2090a7398723SShteryana Shopova 	*cptr++ = '\0';
2091a7398723SShteryana Shopova 
2092a7398723SShteryana Shopova 	fprintf(stdout, "Engine ID 0x%s\n", engine);
2093a7398723SShteryana Shopova 	fprintf(stdout, "Boots : %u\t\tTime : %d\n",
2094a7398723SShteryana Shopova 	    snmp_client.engine.engine_boots,
2095a7398723SShteryana Shopova 	    snmp_client.engine.engine_time);
2096a7398723SShteryana Shopova }
2097a7398723SShteryana Shopova 
2098a7398723SShteryana Shopova void
snmp_output_keys(void)2099a7398723SShteryana Shopova snmp_output_keys(void)
2100a7398723SShteryana Shopova {
2101a7398723SShteryana Shopova 	uint32_t i, keylen = 0;
2102a7398723SShteryana Shopova 	char *cptr, extkey[2 * SNMP_AUTH_KEY_SIZ + 2];
2103a7398723SShteryana Shopova 
2104a7398723SShteryana Shopova 	fprintf(stdout, "Localized keys for %s\n", snmp_client.user.sec_name);
2105a7398723SShteryana Shopova 	if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_MD5) {
2106a7398723SShteryana Shopova 		fprintf(stdout, "MD5 : 0x");
2107a7398723SShteryana Shopova 		keylen = SNMP_AUTH_HMACMD5_KEY_SIZ;
2108a7398723SShteryana Shopova 	} else if (snmp_client.user.auth_proto == SNMP_AUTH_HMAC_SHA) {
2109a7398723SShteryana Shopova 		fprintf(stdout, "SHA : 0x");
2110a7398723SShteryana Shopova 		keylen = SNMP_AUTH_HMACSHA_KEY_SIZ;
2111a7398723SShteryana Shopova 	}
2112a7398723SShteryana Shopova 	if (snmp_client.user.auth_proto != SNMP_AUTH_NOAUTH) {
2113a7398723SShteryana Shopova 		cptr = extkey;
2114a7398723SShteryana Shopova 		for (i = 0; i < keylen; i++)
2115a7398723SShteryana Shopova 			cptr += sprintf(cptr, "%.2x",
2116a7398723SShteryana Shopova 			    snmp_client.user.auth_key[i]);
2117a7398723SShteryana Shopova 		*cptr++ = '\0';
2118a7398723SShteryana Shopova 		fprintf(stdout, "%s\n", extkey);
2119a7398723SShteryana Shopova 	}
2120a7398723SShteryana Shopova 
2121a7398723SShteryana Shopova 	if (snmp_client.user.priv_proto == SNMP_PRIV_DES) {
2122a7398723SShteryana Shopova 		fprintf(stdout, "DES : 0x");
2123a7398723SShteryana Shopova 		keylen = SNMP_PRIV_DES_KEY_SIZ;
2124a7398723SShteryana Shopova 	} else if (snmp_client.user.priv_proto == SNMP_PRIV_AES) {
2125a7398723SShteryana Shopova 		fprintf(stdout, "AES : 0x");
2126a7398723SShteryana Shopova 		keylen = SNMP_PRIV_AES_KEY_SIZ;
2127a7398723SShteryana Shopova 	}
2128a7398723SShteryana Shopova 	if (snmp_client.user.priv_proto != SNMP_PRIV_NOPRIV) {
2129a7398723SShteryana Shopova 		cptr = extkey;
2130a7398723SShteryana Shopova 		for (i = 0; i < keylen; i++)
2131a7398723SShteryana Shopova 			cptr += sprintf(cptr, "%.2x",
2132a7398723SShteryana Shopova 			    snmp_client.user.priv_key[i]);
2133a7398723SShteryana Shopova 		*cptr++ = '\0';
2134a7398723SShteryana Shopova 		fprintf(stdout, "%s\n", extkey);
2135a7398723SShteryana Shopova 	}
2136a7398723SShteryana Shopova }
2137