xref: /openbsd-src/usr.bin/snmp/snmpc.c (revision e6c7c102cf5d9891f32552a42895134a59937045)
1*e6c7c102Sjsg /*	$OpenBSD: snmpc.c,v 1.41 2024/04/23 13:34:50 jsg Exp $	*/
2442e4f4fSmartijn 
3442e4f4fSmartijn /*
4442e4f4fSmartijn  * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
5442e4f4fSmartijn  * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org>
6442e4f4fSmartijn  *
7442e4f4fSmartijn  * Permission to use, copy, modify, and distribute this software for any
8442e4f4fSmartijn  * purpose with or without fee is hereby granted, provided that the above
9442e4f4fSmartijn  * copyright notice and this permission notice appear in all copies.
10442e4f4fSmartijn  *
11442e4f4fSmartijn  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12442e4f4fSmartijn  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13442e4f4fSmartijn  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14442e4f4fSmartijn  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15442e4f4fSmartijn  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16442e4f4fSmartijn  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17442e4f4fSmartijn  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18442e4f4fSmartijn  */
19442e4f4fSmartijn 
20442e4f4fSmartijn #include <sys/limits.h>
21442e4f4fSmartijn #include <sys/types.h>
22442e4f4fSmartijn #include <sys/socket.h>
23442e4f4fSmartijn #include <sys/un.h>
24442e4f4fSmartijn 
25442e4f4fSmartijn #include <arpa/inet.h>
264f098f75Smartijn #include <openssl/evp.h>
27442e4f4fSmartijn 
28442e4f4fSmartijn #include <ber.h>
29b89ba26fSmartijn #include <ctype.h>
30442e4f4fSmartijn #include <err.h>
31442e4f4fSmartijn #include <errno.h>
321248928aSmartijn #include <locale.h>
33442e4f4fSmartijn #include <netdb.h>
34442e4f4fSmartijn #include <poll.h>
35442e4f4fSmartijn #include <stdio.h>
36442e4f4fSmartijn #include <stdlib.h>
37442e4f4fSmartijn #include <stdint.h>
38442e4f4fSmartijn #include <string.h>
39442e4f4fSmartijn #include <time.h>
40442e4f4fSmartijn #include <unistd.h>
416659eda6Smartijn #include <util.h>
421d333c94Smartijn #include <wchar.h>
43442e4f4fSmartijn 
44442e4f4fSmartijn #include "smi.h"
45442e4f4fSmartijn #include "snmp.h"
46b89ba26fSmartijn #include "usm.h"
47442e4f4fSmartijn 
48f5e30c24Smartijn #define GETOPT_COMMON		"A:a:c:E:e:K:k:l:n:O:r:t:u:v:X:x:Z:"
49442e4f4fSmartijn 
50442e4f4fSmartijn int snmpc_get(int, char *[]);
51442e4f4fSmartijn int snmpc_walk(int, char *[]);
52ecb1f8acSmartijn int snmpc_set(int, char *[]);
53442e4f4fSmartijn int snmpc_trap(int, char *[]);
546659eda6Smartijn int snmpc_df(int, char *[]);
55442e4f4fSmartijn int snmpc_mibtree(int, char *[]);
56e13f0058Smartijn struct snmp_agent *snmpc_connect(char *, char *);
57442e4f4fSmartijn int snmpc_parseagent(char *, char *);
58442e4f4fSmartijn int snmpc_print(struct ber_element *);
594ac39592Smartijn __dead void snmpc_printerror(enum snmp_error, struct ber_element *, int,
604ac39592Smartijn     const char *);
61b89ba26fSmartijn char *snmpc_hex2bin(char *, size_t *);
621d333c94Smartijn ssize_t snmpc_mbswidth(char *);
63ecb1f8acSmartijn struct ber_element *snmpc_varbindparse(int, char *[]);
64442e4f4fSmartijn void usage(void);
65442e4f4fSmartijn 
66442e4f4fSmartijn struct snmp_app {
67442e4f4fSmartijn 	const char *name;
68442e4f4fSmartijn 	const int usecommonopt;
69442e4f4fSmartijn 	const char *optstring;
70442e4f4fSmartijn 	const char *usage;
71442e4f4fSmartijn 	int (*exec)(int, char *[]);
72442e4f4fSmartijn };
73442e4f4fSmartijn 
74442e4f4fSmartijn struct snmp_app snmp_apps[] = {
75442e4f4fSmartijn 	{ "get", 1, NULL, "agent oid ...", snmpc_get },
76442e4f4fSmartijn 	{ "getnext", 1, NULL, "agent oid ...", snmpc_get },
77a154891cSmartijn 	{ "walk", 1, "C:", "[-C cIipt] [-C E endoid] [-C s skipoid] agent [oid]", snmpc_walk },
78442e4f4fSmartijn 	{ "bulkget", 1, "C:", "[-C n<nonrep>r<maxrep>] agent oid ...", snmpc_get },
79a154891cSmartijn 	{ "bulkwalk", 1, "C:", "[-C cipn<nonrep>r<maxrep>] [-C s skipoid] agent [oid]", snmpc_walk },
80ecb1f8acSmartijn 	{ "set", 1, NULL, "agent oid type value [oid type value] ...", snmpc_set },
81442e4f4fSmartijn 	{ "trap", 1, NULL, "agent uptime oid [oid type value] ...", snmpc_trap },
82a154891cSmartijn 	{ "df", 1, "C:", "[-Ch] [-Cr<maxrep>] agent", snmpc_df },
83f938cef3Smartijn 	{ "mibtree", 0, "O:", "[-O fnS] [oid ...]", snmpc_mibtree }
84442e4f4fSmartijn };
85442e4f4fSmartijn struct snmp_app *snmp_app = NULL;
86442e4f4fSmartijn 
8712022910Smartijn char *community = NULL;
88b89ba26fSmartijn struct snmp_v3 *v3;
89442e4f4fSmartijn char *mib = "mib_2";
90442e4f4fSmartijn int retries = 5;
91442e4f4fSmartijn int timeout = 1;
9212022910Smartijn enum snmp_version version = SNMP_V3;
93442e4f4fSmartijn int print_equals = 1;
94442e4f4fSmartijn int print_varbind_only = 0;
95442e4f4fSmartijn int print_summary = 0;
96442e4f4fSmartijn int print_time = 0;
976659eda6Smartijn int print_human = 0;
98442e4f4fSmartijn int walk_check_increase = 1;
99442e4f4fSmartijn int walk_fallback_oid = 1;
100442e4f4fSmartijn int walk_include_oid = 0;
101442e4f4fSmartijn int smi_print_hint = 1;
102442e4f4fSmartijn int non_repeaters = 0;
103442e4f4fSmartijn int max_repetitions = 10;
104442e4f4fSmartijn struct ber_oid walk_end = {{0}, 0};
105bf54189fSmartijn struct ber_oid *walk_skip = NULL;
106bf54189fSmartijn size_t walk_skip_len = 0;
107442e4f4fSmartijn enum smi_oid_lookup oid_lookup = smi_oidl_short;
108442e4f4fSmartijn enum smi_output_string output_string = smi_os_default;
1091248928aSmartijn int utf8 = 0;
110442e4f4fSmartijn 
111442e4f4fSmartijn int
main(int argc,char * argv[])112442e4f4fSmartijn main(int argc, char *argv[])
113442e4f4fSmartijn {
1144f098f75Smartijn 	const EVP_MD *md = NULL;
115f5e30c24Smartijn 	const EVP_CIPHER *cipher = NULL;
116b89ba26fSmartijn 	struct snmp_sec *sec;
117b89ba26fSmartijn 	char *user = NULL;
118141b3f16Smartijn 	enum usm_key_level authkeylevel = USM_KEY_UNSET;
1194f098f75Smartijn 	char *authkey = NULL;
1204f098f75Smartijn 	size_t authkeylen = 0;
121141b3f16Smartijn 	enum usm_key_level privkeylevel = USM_KEY_UNSET;
122f5e30c24Smartijn 	char *privkey = NULL;
123f5e30c24Smartijn 	size_t privkeylen = 0;
124b89ba26fSmartijn 	int seclevel = SNMP_MSGFLAG_REPORT;
125b89ba26fSmartijn 	char *ctxname = NULL;
126b89ba26fSmartijn 	char *ctxengineid = NULL, *secengineid = NULL;
127b89ba26fSmartijn 	size_t ctxengineidlen, secengineidlen;
128b89ba26fSmartijn 	int zflag = 0;
129141b3f16Smartijn 	long long boots = 0, time = 0;
130442e4f4fSmartijn 	char optstr[BUFSIZ];
131442e4f4fSmartijn 	const char *errstr;
132442e4f4fSmartijn 	char *strtolp;
133442e4f4fSmartijn 	int ch;
134442e4f4fSmartijn 	size_t i;
135442e4f4fSmartijn 
1361248928aSmartijn 	/*
1371248928aSmartijn 	 * Determine if output can handle UTF-8 based on locale.
1381248928aSmartijn 	 */
1391248928aSmartijn 	setlocale(LC_CTYPE, "");
1401248928aSmartijn 	utf8 = MB_CUR_MAX > 1;
1411248928aSmartijn 	/*
1421248928aSmartijn 	 * SMIv2 allows for UTF-8 text at some locations.
1431248928aSmartijn 	 * Set it explicitly so we can handle it on the input side.
1441248928aSmartijn 	 */
1451248928aSmartijn 	if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL)
1461248928aSmartijn 		errx(1, "setlocale(LC_CTYPE, \"en_US.UTF-8\") failed");
1471248928aSmartijn 
1486dd7164bSmartijn 	if (pledge("stdio inet dns unix", NULL) == -1)
149442e4f4fSmartijn 		err(1, "pledge");
150442e4f4fSmartijn 
151442e4f4fSmartijn 	if (argc <= 1)
152442e4f4fSmartijn 		usage();
153442e4f4fSmartijn 
1540b8bc7a5Sbluhm 	optstr[0] = '\0';
155442e4f4fSmartijn 	for (i = 0; i < sizeof(snmp_apps)/sizeof(*snmp_apps); i++) {
156442e4f4fSmartijn 		if (strcmp(snmp_apps[i].name, argv[1]) == 0) {
157442e4f4fSmartijn 			snmp_app = &snmp_apps[i];
158442e4f4fSmartijn 			if (snmp_app->optstring != NULL) {
159442e4f4fSmartijn 				if (strlcpy(optstr, snmp_app->optstring,
160442e4f4fSmartijn 				    sizeof(optstr)) > sizeof(optstr))
161442e4f4fSmartijn 					errx(1, "strlcat");
162442e4f4fSmartijn 			}
163442e4f4fSmartijn 			break;
164442e4f4fSmartijn 		}
165442e4f4fSmartijn 	}
166442e4f4fSmartijn 	if (snmp_app == NULL)
167442e4f4fSmartijn 		usage();
168442e4f4fSmartijn 
169442e4f4fSmartijn 	if (snmp_app->usecommonopt) {
170442e4f4fSmartijn 		if (strlcat(optstr, GETOPT_COMMON, sizeof(optstr)) >
171442e4f4fSmartijn 		    sizeof(optstr))
172442e4f4fSmartijn 			errx(1, "strlcpy");
173442e4f4fSmartijn 	}
174442e4f4fSmartijn 
175442e4f4fSmartijn 	argc--;
176442e4f4fSmartijn 	argv++;
177442e4f4fSmartijn 
178442e4f4fSmartijn 	smi_init();
179442e4f4fSmartijn 
180442e4f4fSmartijn 	while ((ch = getopt(argc, argv, optstr)) != -1) {
181442e4f4fSmartijn 		switch (ch) {
1824f098f75Smartijn 		case 'A':
1834f098f75Smartijn 			authkey = optarg;
1844f098f75Smartijn 			authkeylen = strlen(authkey);
1854f098f75Smartijn 			authkeylevel = USM_KEY_PASSWORD;
1864f098f75Smartijn 			break;
1874f098f75Smartijn 		case 'a':
1884f098f75Smartijn 			if (strcasecmp(optarg, "MD5") == 0)
1894f098f75Smartijn 				md = EVP_md5();
1904f098f75Smartijn 			else if (strcasecmp(optarg, "SHA") == 0)
1914f098f75Smartijn 				md = EVP_sha1();
1924f098f75Smartijn 			else if (strcasecmp(optarg, "SHA-224") == 0)
1934f098f75Smartijn 				md = EVP_sha224();
1944f098f75Smartijn 			else if (strcasecmp(optarg, "SHA-256") == 0)
1954f098f75Smartijn 				md = EVP_sha256();
1964f098f75Smartijn 			else if (strcasecmp(optarg, "SHA-384") == 0)
1974f098f75Smartijn 				md = EVP_sha384();
1984f098f75Smartijn 			else if (strcasecmp(optarg, "SHA-512") == 0)
1994f098f75Smartijn 				md = EVP_sha512();
2004f098f75Smartijn 			else
2014f098f75Smartijn 				errx(1, "Invalid authentication protocol "
2024f098f75Smartijn 				    "specified after -a flag: %s", optarg);
2034f098f75Smartijn 			break;
204442e4f4fSmartijn 		case 'c':
205442e4f4fSmartijn 			community = optarg;
206442e4f4fSmartijn 			break;
207b89ba26fSmartijn 		case 'E':
208b89ba26fSmartijn 			ctxengineid = snmpc_hex2bin(optarg,
209b89ba26fSmartijn 			    &ctxengineidlen);
210b89ba26fSmartijn 			if (ctxengineid == NULL) {
211b89ba26fSmartijn 				if (errno == EINVAL)
212b89ba26fSmartijn 					errx(1, "Bad engine ID value "
213b89ba26fSmartijn 					    "after -3E flag.");
214b89ba26fSmartijn 				err(1, "-3E");
215b89ba26fSmartijn 			}
216b89ba26fSmartijn 			break;
217b89ba26fSmartijn 		case 'e':
218b89ba26fSmartijn 			secengineid = snmpc_hex2bin(optarg,
219b89ba26fSmartijn 			    &secengineidlen);
220b89ba26fSmartijn 			if (secengineid == NULL) {
221b89ba26fSmartijn 				if (errno == EINVAL)
222b89ba26fSmartijn 					errx(1, "Bad engine ID value "
223b89ba26fSmartijn 					    "after -3e flag.");
224b89ba26fSmartijn 				err(1, "-3e");
225b89ba26fSmartijn 			}
226b89ba26fSmartijn 			break;
227f5e30c24Smartijn 		case 'K':
228f5e30c24Smartijn 			privkey = snmpc_hex2bin(optarg, &privkeylen);
229f5e30c24Smartijn 			if (privkey == NULL) {
230f5e30c24Smartijn 				if (errno == EINVAL)
231f5e30c24Smartijn 					errx(1, "Bad key value after "
232f5e30c24Smartijn 					    "-3K flag.");
233f5e30c24Smartijn 				errx(1, "-3K");
234f5e30c24Smartijn 			}
235f5e30c24Smartijn 			privkeylevel = USM_KEY_LOCALIZED;
236f5e30c24Smartijn 			break;
2374f098f75Smartijn 		case 'k':
2384f098f75Smartijn 			authkey = snmpc_hex2bin(optarg, &authkeylen);
2394f098f75Smartijn 			if (authkey == NULL) {
2404f098f75Smartijn 				if (errno == EINVAL)
2414f098f75Smartijn 					errx(1, "Bad key value after -k flag.");
2424f098f75Smartijn 				err(1, "-k");
2434f098f75Smartijn 			}
2444f098f75Smartijn 			authkeylevel = USM_KEY_LOCALIZED;
2454f098f75Smartijn 			break;
2464f098f75Smartijn 		case 'l':
2474f098f75Smartijn 			if (strcasecmp(optarg, "noAuthNoPriv") == 0)
2484f098f75Smartijn 				seclevel = SNMP_MSGFLAG_REPORT;
2494f098f75Smartijn 			else if (strcasecmp(optarg, "authNoPriv") == 0)
2504f098f75Smartijn 				seclevel = SNMP_MSGFLAG_AUTH |
2514f098f75Smartijn 				    SNMP_MSGFLAG_REPORT;
252f5e30c24Smartijn 			else if (strcasecmp(optarg, "authPriv") == 0)
253f5e30c24Smartijn 				seclevel = SNMP_MSGFLAG_AUTH |
254f5e30c24Smartijn 				    SNMP_MSGFLAG_PRIV | SNMP_MSGFLAG_REPORT;
2554f098f75Smartijn 			else
2564f098f75Smartijn 				errx(1, "Invalid security level specified "
2574f098f75Smartijn 				    "after -l flag: %s", optarg);
2584f098f75Smartijn 			break;
259b89ba26fSmartijn 		case 'n':
260b89ba26fSmartijn 			ctxname = optarg;
261b89ba26fSmartijn 			break;
262442e4f4fSmartijn 		case 'r':
263442e4f4fSmartijn 			if ((retries = strtonum(optarg, 0, INT_MAX,
264442e4f4fSmartijn 			    &errstr)) == 0) {
265442e4f4fSmartijn 				if (errstr != NULL)
266442e4f4fSmartijn 					errx(1, "-r: %s argument", errstr);
267442e4f4fSmartijn 			}
268442e4f4fSmartijn 			break;
269442e4f4fSmartijn 		case 't':
270442e4f4fSmartijn 			if ((timeout = strtonum(optarg, 1, INT_MAX,
271442e4f4fSmartijn 			    &errstr)) == 0) {
272442e4f4fSmartijn 				if (errstr != NULL)
273442e4f4fSmartijn 					errx(1, "-t: %s argument", errstr);
274442e4f4fSmartijn 			}
275442e4f4fSmartijn 			break;
276b89ba26fSmartijn 		case 'u':
277b89ba26fSmartijn 			user = optarg;
278b89ba26fSmartijn 			break;
279442e4f4fSmartijn 		case 'v':
280442e4f4fSmartijn 			if (strcmp(optarg, "1") == 0)
281442e4f4fSmartijn 				version = SNMP_V1;
282442e4f4fSmartijn 			else if (strcmp(optarg, "2c") == 0)
283442e4f4fSmartijn 				version = SNMP_V2C;
284b89ba26fSmartijn 			else if (strcmp(optarg, "3") == 0)
285b89ba26fSmartijn 				version = SNMP_V3;
286442e4f4fSmartijn 			else
287442e4f4fSmartijn 				errc(1, EINVAL, "-v");
288442e4f4fSmartijn 			break;
289442e4f4fSmartijn 		case 'C':
290442e4f4fSmartijn 			for (i = 0; i < strlen(optarg); i++) {
291442e4f4fSmartijn 				switch (optarg[i]) {
292442e4f4fSmartijn 				case 'c':
293442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk") &&
294442e4f4fSmartijn 					    strcmp(snmp_app->name, "bulkwalk"))
295442e4f4fSmartijn 						usage();
296442e4f4fSmartijn 					walk_check_increase = 0;
297442e4f4fSmartijn 					break;
2986659eda6Smartijn 				case 'h':
2996659eda6Smartijn 					if (strcmp(snmp_app->name, "df"))
3006659eda6Smartijn 						usage();
3016659eda6Smartijn 					print_human = 1;
3026659eda6Smartijn 					break;
303442e4f4fSmartijn 				case 'i':
304442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk") &&
305442e4f4fSmartijn 					    strcmp(snmp_app->name, "bulkwalk"))
306442e4f4fSmartijn 						usage();
307442e4f4fSmartijn 					walk_include_oid = 1;
308442e4f4fSmartijn 					break;
309442e4f4fSmartijn 				case 'n':
310442e4f4fSmartijn 					if (strcmp(snmp_app->name, "bulkget") &&
311442e4f4fSmartijn 					    strcmp(snmp_app->name, "bulkwalk"))
312442e4f4fSmartijn 						usage();
313442e4f4fSmartijn 					errno = 0;
314442e4f4fSmartijn 					non_repeaters = strtol(&optarg[i + 1],
315442e4f4fSmartijn 					    &strtolp, 10);
316442e4f4fSmartijn 					if (non_repeaters < 0 ||
317442e4f4fSmartijn 					    errno == ERANGE) {
318442e4f4fSmartijn 						if (non_repeaters < 0)
319442e4f4fSmartijn 							errx(1, "%s%s",
320442e4f4fSmartijn 							    "-Cn: too small ",
321442e4f4fSmartijn 							    "argument");
322442e4f4fSmartijn 						else
323442e4f4fSmartijn 							errx(1, "%s%s",
324442e4f4fSmartijn 							    "-Cn: too large",
325442e4f4fSmartijn 							    "argument");
326442e4f4fSmartijn 					} else if (&optarg[i + 1] == strtolp)
327442e4f4fSmartijn 						errx(1, "-Cn invalid argument");
328442e4f4fSmartijn 					i = strtolp - optarg - 1;
329442e4f4fSmartijn 					break;
330442e4f4fSmartijn 				case 'p':
331442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk") &&
332442e4f4fSmartijn 					    strcmp(snmp_app->name, "bulkwalk"))
333442e4f4fSmartijn 						usage();
334442e4f4fSmartijn 					print_summary = 1;
335442e4f4fSmartijn 					break;
336442e4f4fSmartijn 				case 'r':
337442e4f4fSmartijn 					if (strcmp(snmp_app->name, "bulkget") &&
3386659eda6Smartijn 					    strcmp(snmp_app->name, "bulkwalk") &&
3396659eda6Smartijn 					    strcmp(snmp_app->name, "df"))
340442e4f4fSmartijn 						usage();
341442e4f4fSmartijn 					errno = 0;
342442e4f4fSmartijn 					max_repetitions = strtol(&optarg[i + 1],
343442e4f4fSmartijn 					    &strtolp, 10);
344442e4f4fSmartijn 					if (max_repetitions < 0 ||
345442e4f4fSmartijn 					    errno == ERANGE) {
346442e4f4fSmartijn 						if (max_repetitions < 0)
347442e4f4fSmartijn 							errx(1, "%s%s",
348442e4f4fSmartijn 							    "-Cr: too small ",
349442e4f4fSmartijn 							    "argument");
350442e4f4fSmartijn 						else
351442e4f4fSmartijn 							errx(1, "%s%s",
352442e4f4fSmartijn 							    "-Cr: too large",
353442e4f4fSmartijn 							    "argument");
354442e4f4fSmartijn 					} else if (&optarg[i + 1] == strtolp)
355442e4f4fSmartijn 						errx(1, "-Cr invalid argument");
356442e4f4fSmartijn 					i = strtolp - optarg - 1;
357442e4f4fSmartijn 					break;
358bf54189fSmartijn 				case 's':
359bf54189fSmartijn 					if (strcmp(snmp_app->name, "walk") &&
360bf54189fSmartijn 					    strcmp(snmp_app->name, "bulkwalk"))
361bf54189fSmartijn 						usage();
362bf54189fSmartijn 					if ((walk_skip = recallocarray(
363bf54189fSmartijn 					    walk_skip, walk_skip_len,
364bf54189fSmartijn 					    walk_skip_len + 1,
365bf54189fSmartijn 					    sizeof(*walk_skip))) == NULL)
366bf54189fSmartijn 						errx(1, "malloc");
367bf54189fSmartijn 					if (smi_string2oid(argv[optind],
368bf54189fSmartijn 					    &(walk_skip[walk_skip_len])) != 0)
369bf54189fSmartijn 						errx(1, "%s: %s",
370bf54189fSmartijn 						    "Unknown Object Identifier",
371bf54189fSmartijn 						    argv[optind]);
372bf54189fSmartijn 					walk_skip_len++;
373bf54189fSmartijn 					optind++;
374bf54189fSmartijn 					break;
375442e4f4fSmartijn 				case 't':
376442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk"))
377442e4f4fSmartijn 						usage();
378442e4f4fSmartijn 					print_time = 1;
379442e4f4fSmartijn 					break;
380442e4f4fSmartijn 				case 'E':
381442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk"))
382442e4f4fSmartijn 						usage();
383442e4f4fSmartijn 					if (smi_string2oid(argv[optind],
384442e4f4fSmartijn 					    &walk_end) != 0)
385442e4f4fSmartijn 						errx(1, "%s: %s",
386442e4f4fSmartijn 						    "Unknown Object Identifier",
387442e4f4fSmartijn 						    argv[optind]);
388442e4f4fSmartijn 					optind++;
389442e4f4fSmartijn 					continue;
390442e4f4fSmartijn 				case 'I':
391442e4f4fSmartijn 					if (strcmp(snmp_app->name, "walk"))
392442e4f4fSmartijn 						usage();
393442e4f4fSmartijn 					walk_fallback_oid = 0;
394442e4f4fSmartijn 					break;
395442e4f4fSmartijn 				default:
396442e4f4fSmartijn 					usage();
397442e4f4fSmartijn 				}
398442e4f4fSmartijn 				if (optarg[i] == 'E')
399442e4f4fSmartijn 					break;
400442e4f4fSmartijn 			}
401442e4f4fSmartijn 			break;
402442e4f4fSmartijn 		case 'O':
403442e4f4fSmartijn 			for (i = 0; i < strlen(optarg); i++) {
404442e4f4fSmartijn 				if (strcmp(snmp_app->name, "mibtree") == 0 &&
405442e4f4fSmartijn 				    optarg[i] != 'f' && optarg[i] != 'n' &&
406442e4f4fSmartijn 				    optarg[i] != 'S')
407442e4f4fSmartijn 						usage();
408442e4f4fSmartijn 				switch (optarg[i]) {
409442e4f4fSmartijn 				case 'a':
410442e4f4fSmartijn 					output_string = smi_os_ascii;
411442e4f4fSmartijn 					break;
412442e4f4fSmartijn 				case 'f':
413442e4f4fSmartijn 					oid_lookup = smi_oidl_full;
414442e4f4fSmartijn 					break;
415442e4f4fSmartijn 				case 'n':
416442e4f4fSmartijn 					oid_lookup = smi_oidl_numeric;
417442e4f4fSmartijn 					break;
418442e4f4fSmartijn 				case 'q':
419442e4f4fSmartijn 					print_equals = 0;
420442e4f4fSmartijn 					smi_print_hint = 0;
421442e4f4fSmartijn 					break;
422442e4f4fSmartijn 				case 'v':
423442e4f4fSmartijn 					print_varbind_only = 1;
424442e4f4fSmartijn 					break;
425442e4f4fSmartijn 				case 'x':
426442e4f4fSmartijn 					output_string = smi_os_hex;
427442e4f4fSmartijn 					break;
428442e4f4fSmartijn 				case 'S':
429442e4f4fSmartijn 					oid_lookup = smi_oidl_short;
430442e4f4fSmartijn 					break;
431442e4f4fSmartijn 				case 'Q':
432442e4f4fSmartijn 					smi_print_hint = 0;
433442e4f4fSmartijn 					break;
434442e4f4fSmartijn 				default:
435442e4f4fSmartijn 					usage();
436442e4f4fSmartijn 				}
437442e4f4fSmartijn 			}
438442e4f4fSmartijn 			break;
439f5e30c24Smartijn 		case 'X':
440f5e30c24Smartijn 			privkey = optarg;
441f5e30c24Smartijn 			privkeylen = strlen(privkey);
442f5e30c24Smartijn 			privkeylevel = USM_KEY_PASSWORD;
443f5e30c24Smartijn 			break;
444f5e30c24Smartijn 		case 'x':
445f5e30c24Smartijn 			if (strcasecmp(optarg, "DES") == 0)
446f5e30c24Smartijn 				cipher = EVP_des_cbc();
447f5e30c24Smartijn 			else if (strcasecmp(optarg, "AES") == 0)
448f5e30c24Smartijn 				cipher = EVP_aes_128_cfb128();
449f5e30c24Smartijn 			else
450f5e30c24Smartijn 				errx(1, "Invalid privacy protocol "
451f5e30c24Smartijn 				    "specified after -3x flag: %s",
452f5e30c24Smartijn 				    optarg);
453f5e30c24Smartijn 			break;
454b89ba26fSmartijn 		case 'Z':
455b89ba26fSmartijn 			boots = strtoll(optarg, &strtolp, 10);
456b89ba26fSmartijn 			if (boots < 0 || strtolp == optarg || strtolp[0] != ',')
457b89ba26fSmartijn 				usage();
458b89ba26fSmartijn 			strtolp++;
459b89ba26fSmartijn 			time = strtoll(strtolp, &strtolp, 10);
460b89ba26fSmartijn 			if (boots < 0 || strtolp == optarg)
461b89ba26fSmartijn 				usage();
462b89ba26fSmartijn 			zflag = 1;
463b89ba26fSmartijn 			break;
464442e4f4fSmartijn 		default:
465442e4f4fSmartijn 			usage();
466442e4f4fSmartijn 		}
467442e4f4fSmartijn 	}
468442e4f4fSmartijn 	argc -= optind;
469442e4f4fSmartijn 	argv += optind;
470442e4f4fSmartijn 
471697caf84Smartijn 	if (!snmp_app->usecommonopt) {
472697caf84Smartijn 		/* No SNMP protocol settings */
473697caf84Smartijn 	} else if (version == SNMP_V1 || version == SNMP_V2C) {
47412022910Smartijn 		if (community == NULL || community[0] == '\0')
47512022910Smartijn 			errx(1, "No community name specified.");
47612022910Smartijn 	} else if (version == SNMP_V3) {
477b89ba26fSmartijn 		/* Setup USM */
478b89ba26fSmartijn 		if (user == NULL || user[0] == '\0')
479b89ba26fSmartijn 			errx(1, "No securityName specified");
480b89ba26fSmartijn 		if ((sec = usm_init(user, strlen(user))) == NULL)
481b89ba26fSmartijn 			err(1, "usm_init");
4824f098f75Smartijn 		if (seclevel & SNMP_MSGFLAG_AUTH) {
4834f098f75Smartijn 			if (md == NULL)
484808130e6Ssthen 				md = EVP_sha1();
4854f098f75Smartijn 			if (authkey == NULL)
4864f098f75Smartijn 				errx(1, "No authKey or authPassword specified");
4874f098f75Smartijn 			if (usm_setauth(sec, md, authkey, authkeylen,
4884f098f75Smartijn 			    authkeylevel) == -1)
4894f098f75Smartijn 				err(1, "Can't set authkey");
4904f098f75Smartijn 		}
491f5e30c24Smartijn 		if (seclevel & SNMP_MSGFLAG_PRIV) {
492f5e30c24Smartijn 			if (cipher == NULL)
4937b1c74a6Smartijn 				cipher = EVP_aes_128_cfb128();
494f5e30c24Smartijn 			if (privkey == NULL)
495f5e30c24Smartijn 				errx(1, "No privKey or privPassword specified");
496f5e30c24Smartijn 			if (usm_setpriv(sec, cipher, privkey, privkeylen,
497f5e30c24Smartijn 			    privkeylevel) == -1)
498f5e30c24Smartijn 				err(1, "Can't set authkey");
499f5e30c24Smartijn 		}
500b89ba26fSmartijn 		if (secengineid != NULL) {
501b89ba26fSmartijn 			if (usm_setengineid(sec, secengineid,
502b89ba26fSmartijn 			    secengineidlen) == -1)
503b89ba26fSmartijn 				err(1, "Can't set secengineid");
504b89ba26fSmartijn 		}
505b89ba26fSmartijn 		if (zflag)
506b89ba26fSmartijn 			if (usm_setbootstime(sec, boots, time) == -1)
507b89ba26fSmartijn 				err(1, "Can't set boots/time");
508b89ba26fSmartijn 		v3 = snmp_v3_init(seclevel, ctxname, ctxname == NULL ? 0 :
509b89ba26fSmartijn 		    strlen(ctxname), sec);
510b89ba26fSmartijn 		if (v3 == NULL)
511b89ba26fSmartijn 			err(1, "snmp_v3_init");
512b89ba26fSmartijn 		if (ctxengineid != NULL) {
513b89ba26fSmartijn 			if (snmp_v3_setengineid(v3, ctxengineid,
514b89ba26fSmartijn 			    ctxengineidlen) == -1)
515b89ba26fSmartijn 				err(1, "Can't set ctxengineid");
516b89ba26fSmartijn 		}
517b89ba26fSmartijn 	}
518b89ba26fSmartijn 
519b89ba26fSmartijn 
520442e4f4fSmartijn 	return snmp_app->exec(argc, argv);
521442e4f4fSmartijn }
522442e4f4fSmartijn 
523442e4f4fSmartijn int
snmpc_get(int argc,char * argv[])524442e4f4fSmartijn snmpc_get(int argc, char *argv[])
525442e4f4fSmartijn {
526442e4f4fSmartijn 	struct ber_oid *oid;
527442e4f4fSmartijn 	struct ber_element *pdu, *varbind;
528442e4f4fSmartijn 	struct snmp_agent *agent;
529442e4f4fSmartijn 	int errorstatus, errorindex;
530442e4f4fSmartijn 	int i;
531b89ba26fSmartijn 	int class;
532b89ba26fSmartijn 	unsigned type;
5334ac39592Smartijn 	char *hint = NULL;
534442e4f4fSmartijn 
535442e4f4fSmartijn 	if (argc < 2)
536442e4f4fSmartijn 		usage();
537442e4f4fSmartijn 
538e13f0058Smartijn 	if ((agent = snmpc_connect(argv[0], "161")) == NULL)
539442e4f4fSmartijn 		err(1, "%s", snmp_app->name);
540442e4f4fSmartijn 	agent->timeout = timeout;
541442e4f4fSmartijn 	agent->retries = retries;
542442e4f4fSmartijn 
543442e4f4fSmartijn 	if (pledge("stdio", NULL) == -1)
544442e4f4fSmartijn 		err(1, "pledge");
545442e4f4fSmartijn 	argc--;
546442e4f4fSmartijn 	argv++;
547442e4f4fSmartijn 
548442e4f4fSmartijn 	oid = reallocarray(NULL, argc, sizeof(*oid));
5495b1b430eSderaadt 	if (oid == NULL)
5505b1b430eSderaadt 		err(1, "malloc");
551442e4f4fSmartijn 	for (i = 0; i < argc; i++) {
552442e4f4fSmartijn 		if (smi_string2oid(argv[i], &oid[i]) == -1)
553cf9b7475Ssemarie 			errx(1, "%s: Unknown object identifier", argv[i]);
554442e4f4fSmartijn 	}
555442e4f4fSmartijn 	if (strcmp(snmp_app->name, "getnext") == 0) {
556442e4f4fSmartijn 		if ((pdu = snmp_getnext(agent, oid, argc)) == NULL)
557442e4f4fSmartijn 			err(1, "getnext");
558442e4f4fSmartijn 	} else if (strcmp(snmp_app->name, "bulkget") == 0) {
559442e4f4fSmartijn 		if (version < SNMP_V2C)
560442e4f4fSmartijn 			errx(1, "Cannot send V2 PDU on V1 session");
561442e4f4fSmartijn 		if (non_repeaters > argc)
562442e4f4fSmartijn 			errx(1, "need more objects than -Cn<num>");
563442e4f4fSmartijn 		if ((pdu = snmp_getbulk(agent, oid, argc, non_repeaters,
564442e4f4fSmartijn 		    max_repetitions)) == NULL)
565442e4f4fSmartijn 			err(1, "bulkget");
566442e4f4fSmartijn 	} else {
567442e4f4fSmartijn 		if ((pdu = snmp_get(agent, oid, argc)) == NULL)
568442e4f4fSmartijn 			err(1, "get");
569442e4f4fSmartijn 	}
570442e4f4fSmartijn 
571696b5899Stb 	(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
572b89ba26fSmartijn 	    &errorindex, &varbind);
5734ac39592Smartijn 	if (errorstatus != 0) {
5744ac39592Smartijn 		if (errorindex >= 1 && errorindex <= argc)
5754ac39592Smartijn 			hint = argv[errorindex - 1];
5764ac39592Smartijn 		snmpc_printerror((enum snmp_error) errorstatus, varbind,
5774ac39592Smartijn 		    errorindex, hint);
5784ac39592Smartijn 	}
579442e4f4fSmartijn 
580b89ba26fSmartijn 	if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
581b89ba26fSmartijn 		printf("Received report:\n");
582442e4f4fSmartijn 	for (; varbind != NULL; varbind = varbind->be_next) {
583442e4f4fSmartijn 		if (!snmpc_print(varbind))
584442e4f4fSmartijn 			err(1, "Can't print response");
585442e4f4fSmartijn 	}
586696b5899Stb 	ober_free_elements(pdu);
587442e4f4fSmartijn 	snmp_free_agent(agent);
588442e4f4fSmartijn 	return 0;
589442e4f4fSmartijn }
590442e4f4fSmartijn 
591442e4f4fSmartijn int
snmpc_walk(int argc,char * argv[])592442e4f4fSmartijn snmpc_walk(int argc, char *argv[])
593442e4f4fSmartijn {
594442e4f4fSmartijn 	struct ber_oid oid, loid, noid;
595442e4f4fSmartijn 	struct ber_element *pdu, *varbind, *value;
596442e4f4fSmartijn 	struct timespec start, finish;
597442e4f4fSmartijn 	struct snmp_agent *agent;
598442e4f4fSmartijn 	const char *oids;
599bf54189fSmartijn 	int n = 0, prev_cmp, skip_cmp;
600442e4f4fSmartijn 	int errorstatus, errorindex;
601b89ba26fSmartijn 	int class;
602bf54189fSmartijn 	size_t i;
603b89ba26fSmartijn 	unsigned type;
604442e4f4fSmartijn 
605442e4f4fSmartijn 	if (strcmp(snmp_app->name, "bulkwalk") == 0 && version < SNMP_V2C)
606442e4f4fSmartijn 		errx(1, "Cannot send V2 PDU on V1 session");
607442e4f4fSmartijn 	if (argc < 1 || argc > 2)
608442e4f4fSmartijn 		usage();
609442e4f4fSmartijn 	oids = argc == 1 ? mib : argv[1];
610442e4f4fSmartijn 
611e13f0058Smartijn 	if ((agent = snmpc_connect(argv[0], "161"))== NULL)
612442e4f4fSmartijn 		err(1, "%s", snmp_app->name);
613442e4f4fSmartijn 	agent->timeout = timeout;
614442e4f4fSmartijn 	agent->retries = retries;
615442e4f4fSmartijn 	if (pledge("stdio", NULL) == -1)
616442e4f4fSmartijn 		err(1, "pledge");
617442e4f4fSmartijn 
618442e4f4fSmartijn 	if (smi_string2oid(oids, &oid) == -1)
619442e4f4fSmartijn 		errx(1, "%s: Unknown object identifier", oids);
620442e4f4fSmartijn 	bcopy(&oid, &noid, sizeof(noid));
621442e4f4fSmartijn 	if (print_time)
622442e4f4fSmartijn 		clock_gettime(CLOCK_MONOTONIC, &start);
623442e4f4fSmartijn 
624442e4f4fSmartijn 	if (walk_include_oid) {
625442e4f4fSmartijn 		if ((pdu = snmp_get(agent, &oid, 1)) == NULL)
626442e4f4fSmartijn 			err(1, "%s", snmp_app->name);
627442e4f4fSmartijn 
628696b5899Stb 		(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
629b89ba26fSmartijn 		    &errorstatus, &errorindex, &varbind);
630442e4f4fSmartijn 		if (errorstatus != 0)
6314ac39592Smartijn 			snmpc_printerror((enum snmp_error) errorstatus, varbind,
6324ac39592Smartijn 			    errorindex, oids);
633442e4f4fSmartijn 
634b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
635b89ba26fSmartijn 			printf("Received report:\n");
636442e4f4fSmartijn 		if (!snmpc_print(varbind))
637442e4f4fSmartijn 			err(1, "Can't print response");
638696b5899Stb 		ober_free_element(pdu);
639b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
640b89ba26fSmartijn 			return 1;
641442e4f4fSmartijn 		n++;
642442e4f4fSmartijn 	}
643442e4f4fSmartijn 	while (1) {
644bf54189fSmartijn 		for (i = 0; i < walk_skip_len; i++) {
645893ac8ceSmartijn 			skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
646bf54189fSmartijn 			if (skip_cmp == 0 || skip_cmp == 2) {
647bf54189fSmartijn 				bcopy(&(walk_skip[i]), &noid, sizeof(noid));
648bf54189fSmartijn 				noid.bo_id[noid.bo_n -1]++;
649bf54189fSmartijn 				break;
650bf54189fSmartijn 			}
651bf54189fSmartijn 		}
652442e4f4fSmartijn 		bcopy(&noid, &loid, sizeof(loid));
653442e4f4fSmartijn 		if (strcmp(snmp_app->name, "bulkwalk") == 0) {
654442e4f4fSmartijn 			if ((pdu = snmp_getbulk(agent, &noid, 1,
655442e4f4fSmartijn 			    non_repeaters, max_repetitions)) == NULL)
656442e4f4fSmartijn 				err(1, "bulkwalk");
657442e4f4fSmartijn 		} else {
658442e4f4fSmartijn 			if ((pdu = snmp_getnext(agent, &noid, 1)) == NULL)
659442e4f4fSmartijn 				err(1, "walk");
660442e4f4fSmartijn 		}
661442e4f4fSmartijn 
662696b5899Stb 		(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
663b89ba26fSmartijn 		    &errorstatus, &errorindex, &varbind);
664442e4f4fSmartijn 		if (errorstatus != 0) {
6654ac39592Smartijn 			snmpc_printerror((enum snmp_error) errorstatus, varbind,
6664ac39592Smartijn 			    errorindex, NULL);
667442e4f4fSmartijn 		}
668442e4f4fSmartijn 
669b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
670b89ba26fSmartijn 			printf("Received report:\n");
671442e4f4fSmartijn 		for (; varbind != NULL; varbind = varbind->be_next) {
672696b5899Stb 			(void) ober_scanf_elements(varbind, "{oe}", &noid,
673442e4f4fSmartijn 			    &value);
674442e4f4fSmartijn 			if (value->be_class == BER_CLASS_CONTEXT &&
675442e4f4fSmartijn 			    value->be_type == BER_TYPE_EOC)
676442e4f4fSmartijn 				break;
677bf54189fSmartijn 			for (i = 0; i < walk_skip_len; i++) {
678893ac8ceSmartijn 				skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
679bf54189fSmartijn 				if (skip_cmp == 0 || skip_cmp == 2)
680bf54189fSmartijn 					break;
681bf54189fSmartijn 			}
682bf54189fSmartijn 			if (i < walk_skip_len)
683bf54189fSmartijn 				continue;
684893ac8ceSmartijn 			prev_cmp = ober_oid_cmp(&noid, &loid);
685442e4f4fSmartijn 			if (walk_check_increase && prev_cmp == -1)
686442e4f4fSmartijn 				errx(1, "OID not increasing");
687893ac8ceSmartijn 			if (prev_cmp == 0 || ober_oid_cmp(&noid, &oid) != 2)
688442e4f4fSmartijn 				break;
689442e4f4fSmartijn 			if (walk_end.bo_n != 0 &&
690893ac8ceSmartijn 			    ober_oid_cmp(&noid, &walk_end) != -1)
691442e4f4fSmartijn 				break;
692442e4f4fSmartijn 
693442e4f4fSmartijn 			if (!snmpc_print(varbind))
694442e4f4fSmartijn 				err(1, "Can't print response");
695442e4f4fSmartijn 			n++;
696442e4f4fSmartijn 		}
697696b5899Stb 		ober_free_elements(pdu);
698b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
699b89ba26fSmartijn 			return 1;
700442e4f4fSmartijn 		if (varbind != NULL)
701442e4f4fSmartijn 			break;
702442e4f4fSmartijn 	}
703442e4f4fSmartijn 	if (walk_fallback_oid && n == 0) {
704442e4f4fSmartijn 		if ((pdu = snmp_get(agent, &oid, 1)) == NULL)
705442e4f4fSmartijn 			err(1, "%s", snmp_app->name);
706442e4f4fSmartijn 
707696b5899Stb 		(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
708b89ba26fSmartijn 		    &errorstatus, &errorindex, &varbind);
709442e4f4fSmartijn 		if (errorstatus != 0)
7104ac39592Smartijn 			snmpc_printerror((enum snmp_error) errorstatus, varbind,
7114ac39592Smartijn 			    errorindex, oids);
712442e4f4fSmartijn 
713b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
714b89ba26fSmartijn 			printf("Received report:\n");
715442e4f4fSmartijn 		if (!snmpc_print(varbind))
716442e4f4fSmartijn 			err(1, "Can't print response");
717696b5899Stb 		ober_free_element(pdu);
718b89ba26fSmartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
719b89ba26fSmartijn 			return 1;
720442e4f4fSmartijn 		n++;
721442e4f4fSmartijn 	}
722442e4f4fSmartijn 	if (print_time)
723442e4f4fSmartijn 		clock_gettime(CLOCK_MONOTONIC, &finish);
724442e4f4fSmartijn 	if (print_summary)
725442e4f4fSmartijn 		printf("Variables found: %d\n", n);
726442e4f4fSmartijn 	if (print_time) {
727442e4f4fSmartijn 		if ((finish.tv_nsec -= start.tv_nsec) < 0) {
728442e4f4fSmartijn 			finish.tv_sec -= 1;
729442e4f4fSmartijn 			finish.tv_nsec += 1000000000;
730442e4f4fSmartijn 		}
731442e4f4fSmartijn 		finish.tv_sec -= start.tv_sec;
732442e4f4fSmartijn 		fprintf(stderr, "Total traversal time: %lld.%09ld seconds\n",
733442e4f4fSmartijn 		    finish.tv_sec, finish.tv_nsec);
734442e4f4fSmartijn 	}
735442e4f4fSmartijn 	snmp_free_agent(agent);
736442e4f4fSmartijn 	return 0;
737442e4f4fSmartijn }
738442e4f4fSmartijn 
739442e4f4fSmartijn int
snmpc_set(int argc,char * argv[])740ecb1f8acSmartijn snmpc_set(int argc, char *argv[])
741ecb1f8acSmartijn {
742ecb1f8acSmartijn 	struct snmp_agent *agent;
743ecb1f8acSmartijn 	struct ber_element *pdu, *varbind;
744ecb1f8acSmartijn 	int errorstatus, errorindex;
745ecb1f8acSmartijn 	int class;
746ecb1f8acSmartijn 	unsigned type;
7474ac39592Smartijn 	char *hint = NULL;
748ecb1f8acSmartijn 
749ecb1f8acSmartijn 	if (argc < 4)
750ecb1f8acSmartijn 		usage();
751ecb1f8acSmartijn 	if ((agent = snmpc_connect(argv[0], "161")) == NULL)
752ecb1f8acSmartijn 		err(1, "%s", snmp_app->name);
753ecb1f8acSmartijn 	argc--;
754ecb1f8acSmartijn 	argv++;
755ecb1f8acSmartijn 
756ecb1f8acSmartijn 	if (pledge("stdio", NULL) == -1)
757ecb1f8acSmartijn 		err(1, "pledge");
758ecb1f8acSmartijn 
7594ac39592Smartijn 	if ((pdu = snmp_set(agent, snmpc_varbindparse(argc, argv))) == NULL)
7604ac39592Smartijn 		err(1, "set");
761ecb1f8acSmartijn 
762696b5899Stb 	(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
763ecb1f8acSmartijn 	    &errorindex, &varbind);
7644ac39592Smartijn 	if (errorstatus != 0) {
7654ac39592Smartijn 		if (errorindex >= 1 && errorindex <= argc / 3)
7664ac39592Smartijn 			hint = argv[(errorindex - 1) * 3];
7674ac39592Smartijn 		snmpc_printerror((enum snmp_error) errorstatus, varbind,
7684ac39592Smartijn 		    errorindex, hint);
7694ac39592Smartijn 	}
770ecb1f8acSmartijn 
771ecb1f8acSmartijn 	if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT)
772ecb1f8acSmartijn 		printf("Received report:\n");
773ecb1f8acSmartijn 	for (; varbind != NULL; varbind = varbind->be_next) {
774ecb1f8acSmartijn 		if (!snmpc_print(varbind))
775ecb1f8acSmartijn 			err(1, "Can't print response");
776ecb1f8acSmartijn 	}
777696b5899Stb 	ober_free_elements(pdu);
778ecb1f8acSmartijn 	snmp_free_agent(agent);
779ecb1f8acSmartijn 	return 0;
780ecb1f8acSmartijn }
781ecb1f8acSmartijn 
782ecb1f8acSmartijn int
snmpc_trap(int argc,char * argv[])783442e4f4fSmartijn snmpc_trap(int argc, char *argv[])
784442e4f4fSmartijn {
785442e4f4fSmartijn 	struct snmp_agent *agent;
786442e4f4fSmartijn 	struct timespec ts;
787ecb1f8acSmartijn 	struct ber_oid trapoid;
788442e4f4fSmartijn 	const char *errstr = NULL;
789442e4f4fSmartijn 	long long lval;
790442e4f4fSmartijn 
791442e4f4fSmartijn 	if (version == SNMP_V1)
792442e4f4fSmartijn 		errx(1, "trap is not supported for snmp v1");
793442e4f4fSmartijn 
7946c8737d7Smartijn 	if (argc < 3)
7956c8737d7Smartijn 		usage();
7966c8737d7Smartijn 
797e13f0058Smartijn 	if ((agent = snmpc_connect(argv[0], "162")) == NULL)
798442e4f4fSmartijn 		err(1, "%s", snmp_app->name);
799442e4f4fSmartijn 
800442e4f4fSmartijn 	if (pledge("stdio", NULL) == -1)
801442e4f4fSmartijn 		err(1, "pledge");
802442e4f4fSmartijn 
803442e4f4fSmartijn 	if (argv[1][0] == '\0') {
804442e4f4fSmartijn 		if (clock_gettime(CLOCK_UPTIME, &ts) == -1)
805442e4f4fSmartijn 			err(1, "clock_gettime");
806442e4f4fSmartijn 	} else {
807928fb303Smartijn 		lval = strtonum(argv[1], 0, UINT32_MAX, &errstr);
808442e4f4fSmartijn 		if (errstr != NULL)
809442e4f4fSmartijn 			errx(1, "Bad value notation (%s)", argv[1]);
810442e4f4fSmartijn 		ts.tv_sec = lval / 100;
811442e4f4fSmartijn 		ts.tv_nsec = (lval % 100) * 10000000;
812442e4f4fSmartijn 	}
813442e4f4fSmartijn 	if (smi_string2oid(argv[2], &trapoid) == -1)
814442e4f4fSmartijn 		errx(1, "Invalid oid: %s\n", argv[2]);
815442e4f4fSmartijn 
816442e4f4fSmartijn 	argc -= 3;
817442e4f4fSmartijn 	argv += 3;
818442e4f4fSmartijn 
819ecb1f8acSmartijn 	snmp_trap(agent, &ts, &trapoid, snmpc_varbindparse(argc, argv));
820442e4f4fSmartijn 
821442e4f4fSmartijn 	return 0;
822442e4f4fSmartijn }
823442e4f4fSmartijn 
8246659eda6Smartijn #define INCR_NEXTTAB(x) ((x + 8) & ~7)
8256659eda6Smartijn #define NEXTTAB(x) (8 - (x & 7))
8266659eda6Smartijn int
snmpc_df(int argc,char * argv[])8276659eda6Smartijn snmpc_df(int argc, char *argv[])
8286659eda6Smartijn {
8296659eda6Smartijn 	struct snmpc_df {
8306659eda6Smartijn 		uint32_t index;
8311d333c94Smartijn 		char *descr;
8321d333c94Smartijn 		int descrwidth;
8336659eda6Smartijn 		/* Theoretical maximum for 2 32 bit values multiplied */
8346659eda6Smartijn 		char size[21];
8356659eda6Smartijn 		char used[21];
8366659eda6Smartijn 		char avail[21];
8376659eda6Smartijn 		char proc[5];
8386659eda6Smartijn 	} *df = NULL;
8396659eda6Smartijn 	struct ber_oid descroid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 3 }, 11};
8406659eda6Smartijn 	struct ber_oid unitsoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 4 }, 11};
8416659eda6Smartijn 	struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11};
8426659eda6Smartijn 	struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11};
8436659eda6Smartijn 	struct ber_oid oid, *reqoid;
8441d333c94Smartijn 	char oids[SNMP_MAX_OID_STRLEN];
8451d333c94Smartijn 	struct ber_element *pdu, *varbind, *elm;
8466659eda6Smartijn 	struct snmp_agent *agent;
8476659eda6Smartijn 	int errorstatus, errorindex;
8486659eda6Smartijn 	int class;
8496659eda6Smartijn 	size_t i, j, rows = 0;
8506659eda6Smartijn 	unsigned type;
8516659eda6Smartijn 	char *string;
8526659eda6Smartijn 	int descrlen = 0, sizelen = 0, usedlen = 0, availlen = 0, proclen = 0;
8536659eda6Smartijn 	int len;
8546659eda6Smartijn 	long long units, size, used;
8556659eda6Smartijn 	int fmtret;
8566659eda6Smartijn 
8576659eda6Smartijn 	if (argc != 1)
8586659eda6Smartijn 		usage();
8596659eda6Smartijn 
8606659eda6Smartijn 	if ((agent = snmpc_connect(argv[0], "161")) == NULL)
8616659eda6Smartijn 		err(1, "%s", snmp_app->name);
8626659eda6Smartijn 	agent->timeout = timeout;
8636659eda6Smartijn 	agent->retries = retries;
8646659eda6Smartijn 
8656659eda6Smartijn 	if (pledge("stdio", NULL) == -1)
8666659eda6Smartijn 		err(1, "pledge");
8676659eda6Smartijn 
8686659eda6Smartijn 	descrlen = sizeof("Description") - 1;
8696659eda6Smartijn 	sizelen = sizeof("Size") - 1;
8706659eda6Smartijn 	usedlen = sizeof("Used") - 1;
8716659eda6Smartijn 	availlen = sizeof("Available") - 1;
8726659eda6Smartijn 	proclen = sizeof("Used%") - 1;
8736659eda6Smartijn 
8746659eda6Smartijn 	bcopy(&descroid, &oid, sizeof(descroid));
8756659eda6Smartijn 
8766659eda6Smartijn 	i = 0;
8776659eda6Smartijn 	while(1) {
8786659eda6Smartijn 		if (version < SNMP_V2C) {
8796659eda6Smartijn 			if ((pdu = snmp_getnext(agent, &oid, 1)) == NULL)
8806659eda6Smartijn 				err(1, "df");
8816659eda6Smartijn 		} else {
8826659eda6Smartijn 			if ((pdu = snmp_getbulk(agent, &oid, 1, 0,
8836659eda6Smartijn 			    max_repetitions)) == NULL)
8846659eda6Smartijn 				err(1, "df");
8856659eda6Smartijn 		}
8866659eda6Smartijn 
8876659eda6Smartijn 		(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
8886659eda6Smartijn 		    &errorstatus, &errorindex, &varbind);
8896659eda6Smartijn 		if (errorstatus != 0)
8906659eda6Smartijn 			snmpc_printerror((enum snmp_error) errorstatus, varbind,
8916659eda6Smartijn 			    errorindex, NULL);
8926659eda6Smartijn 
8936659eda6Smartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT) {
8946659eda6Smartijn 			printf("Received report:\n");
8956659eda6Smartijn 			for (; varbind != NULL; varbind = varbind->be_next) {
8966659eda6Smartijn 				if (!snmpc_print(varbind))
8976659eda6Smartijn 					err(1, "Can't print response");
8986659eda6Smartijn 			}
8996659eda6Smartijn 			return 1;
9006659eda6Smartijn 		}
9016659eda6Smartijn 		for (; varbind != NULL; varbind = varbind->be_next) {
9021d333c94Smartijn 			if (ober_scanf_elements(varbind, "{os", &oid,
9031d333c94Smartijn 			    &string) == -1 ||
904893ac8ceSmartijn 			    ober_oid_cmp(&oid, &descroid) != 2)
9056659eda6Smartijn 				break;
9066659eda6Smartijn 			rows++;
9076659eda6Smartijn 		}
9086659eda6Smartijn 		if ((df = reallocarray(df, rows, sizeof(*df))) == NULL)
9096659eda6Smartijn 			err(1, "malloc");
9106659eda6Smartijn 		(void) ober_scanf_elements(pdu, "{SSS{e", &varbind);
9116659eda6Smartijn 		for (; i < rows; varbind = varbind->be_next, i++) {
9121d333c94Smartijn 			if (ober_scanf_elements(varbind, "{oe", &oid,
9131d333c94Smartijn 			    &elm) == -1) {
9146659eda6Smartijn 				i--;
9156659eda6Smartijn 				rows--;
9166659eda6Smartijn 				continue;
9176659eda6Smartijn 			}
918893ac8ceSmartijn 			if (ober_oid_cmp(&oid, &descroid) != 2)
9191d333c94Smartijn 				break;
9206659eda6Smartijn 			df[i].index = oid.bo_id[oid.bo_n - 1];
9211d333c94Smartijn 			if ((df[i].descr = smi_print_element(&oid, elm, 0,
9221d333c94Smartijn 			    smi_os_ascii, 0, utf8)) == NULL) {
9231d333c94Smartijn 				smi_oid2string(&oid, oids, sizeof(oids),
9241d333c94Smartijn 				    oid_lookup);
9251d333c94Smartijn 				warn("df: can't print oid %s", oids);
9261d333c94Smartijn 				i--;
9271d333c94Smartijn 				rows--;
9281d333c94Smartijn 				continue;
9291d333c94Smartijn 			}
9301d333c94Smartijn 			if ((df[i].descrwidth =
9311d333c94Smartijn 			    (int) snmpc_mbswidth(df[i].descr)) == -1)
9321d333c94Smartijn 				err(1, "df: invalid hrStorageDescr");
9331d333c94Smartijn 			if (df[i].descrwidth > descrlen)
9341d333c94Smartijn 				descrlen = df[i].descrwidth;
9356659eda6Smartijn 		}
9366659eda6Smartijn 		ober_free_elements(pdu);
9376659eda6Smartijn 		if (varbind != NULL)
9386659eda6Smartijn 			break;
9396659eda6Smartijn 	}
9406659eda6Smartijn 
9416659eda6Smartijn 	if (max_repetitions < 3)
9426659eda6Smartijn 		max_repetitions = 3;
9436659eda6Smartijn 	if ((reqoid = reallocarray(NULL, max_repetitions, sizeof(*reqoid))) == NULL)
9446659eda6Smartijn 		err(1, "malloc");
9456659eda6Smartijn 	for (i = 0; i < rows;) {
9466659eda6Smartijn 		for (j = 0; i + j < rows && j < (size_t)max_repetitions / 3;
9476659eda6Smartijn 		    j++) {
9486659eda6Smartijn 			bcopy(&unitsoid, &(reqoid[(j * 3) + 0]),
9496659eda6Smartijn 			    sizeof(unitsoid));
9506659eda6Smartijn 			reqoid[(j * 3) + 0].bo_id[
9516659eda6Smartijn 			    reqoid[(j * 3) + 0].bo_n++] = df[i + j].index;
9526659eda6Smartijn 			bcopy(&sizeoid, &(reqoid[(j * 3) + 1]),
9536659eda6Smartijn 			    sizeof(sizeoid));
9546659eda6Smartijn 			reqoid[(j * 3) + 1].bo_id[
9556659eda6Smartijn 			    reqoid[(j * 3) + 1].bo_n++] = df[i + j].index;
9566659eda6Smartijn 			bcopy(&usedoid, &(reqoid[(j * 3) + 2]),
9576659eda6Smartijn 			    sizeof(usedoid));
9586659eda6Smartijn 			reqoid[(j * 3) + 2].bo_id[
9596659eda6Smartijn 			    reqoid[(j * 3) + 2].bo_n++] = df[i + j].index;
9606659eda6Smartijn 		}
9616659eda6Smartijn 		if ((pdu = snmp_get(agent, reqoid, j * 3)) == NULL)
9626659eda6Smartijn 			err(1, "df");
9636659eda6Smartijn 		(void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
9646659eda6Smartijn 		    &errorstatus, &errorindex, &varbind);
9656659eda6Smartijn 		if (errorstatus != 0)
9666659eda6Smartijn 			snmpc_printerror((enum snmp_error) errorstatus, varbind,
9676659eda6Smartijn 			    errorindex, NULL);
9686659eda6Smartijn 		if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT) {
9696659eda6Smartijn 			printf("Received report:\n");
9706659eda6Smartijn 			for (; varbind != NULL; varbind = varbind->be_next) {
9716659eda6Smartijn 				if (!snmpc_print(varbind))
9726659eda6Smartijn 					err(1, "Can't print response");
9736659eda6Smartijn 			}
9746659eda6Smartijn 		}
9756659eda6Smartijn 		for (j = 0; varbind != NULL; i++) {
9766659eda6Smartijn 			if (ober_scanf_elements(varbind, "{oi}{oi}{oi}",
9776659eda6Smartijn 			    &(reqoid[0]), &units, &(reqoid[1]), &size,
9786659eda6Smartijn 			    &(reqoid[2]), &used, &varbind) == -1) {
9796659eda6Smartijn 				break;
9806659eda6Smartijn 			}
9816659eda6Smartijn 			varbind = varbind->be_next->be_next->be_next;
9826659eda6Smartijn 
9836659eda6Smartijn 			unitsoid.bo_id[unitsoid.bo_n++] = df[i].index;
9846659eda6Smartijn 			if (ober_oid_cmp(&unitsoid, &(reqoid[0])) != 0) {
9856659eda6Smartijn 				warnx("df: received invalid object");
9866659eda6Smartijn 				break;
9876659eda6Smartijn 			}
9886659eda6Smartijn 			unitsoid.bo_n--;
9896659eda6Smartijn 			sizeoid.bo_id[sizeoid.bo_n++] = df[i].index;
9906659eda6Smartijn 			if (ober_oid_cmp(&sizeoid, &(reqoid[1])) != 0) {
9916659eda6Smartijn 				warnx("df: received invalid object");
9926659eda6Smartijn 				break;
9936659eda6Smartijn 			}
9946659eda6Smartijn 			sizeoid.bo_n--;
9956659eda6Smartijn 			usedoid.bo_id[usedoid.bo_n++] = df[i].index;
9966659eda6Smartijn 			if (ober_oid_cmp(&usedoid, &(reqoid[2])) != 0) {
9976659eda6Smartijn 				warnx("df: received invalid object");
9986659eda6Smartijn 				break;
9996659eda6Smartijn 			}
10006659eda6Smartijn 			usedoid.bo_n--;
10016659eda6Smartijn 			if (print_human)
10026659eda6Smartijn 				fmtret = fmt_scaled((units * size), df[i].size);
10036659eda6Smartijn 			if (!print_human || fmtret == -1)
10046659eda6Smartijn 				snprintf(df[i].size, sizeof(df[i].size), "%lld",
10056659eda6Smartijn 				    (units * size) / 1024);
10066659eda6Smartijn 			len = (int) strlen(df[i].size);
10076659eda6Smartijn 			if (len > sizelen)
10086659eda6Smartijn 				sizelen = len;
10096659eda6Smartijn 			if (print_human)
10106659eda6Smartijn 				fmtret = fmt_scaled(units * used, df[i].used);
10116659eda6Smartijn 			if (!print_human || fmtret == -1)
10126659eda6Smartijn 				snprintf(df[i].used, sizeof(df[i].used), "%lld",
10136659eda6Smartijn 				    (units * used) / 1024);
10146659eda6Smartijn 			len = (int) strlen(df[i].used);
10156659eda6Smartijn 			if (len > usedlen)
10166659eda6Smartijn 				usedlen = len;
10176659eda6Smartijn 			if (print_human)
10186659eda6Smartijn 				fmtret = fmt_scaled(units * (size - used),
10196659eda6Smartijn 				    df[i].avail);
10206659eda6Smartijn 			if (!print_human || fmtret == -1)
10216659eda6Smartijn 				snprintf(df[i].avail, sizeof(df[i].avail),
10226659eda6Smartijn 				    "%lld", (units * (size - used)) / 1024);
10236659eda6Smartijn 			len = (int) strlen(df[i].avail);
102434185dddSmartijn 			if (len > availlen)
10256659eda6Smartijn 				availlen = len;
10266659eda6Smartijn 			if (size == 0)
10276659eda6Smartijn 				strlcpy(df[i].proc, "0%", sizeof(df[i].proc));
10286659eda6Smartijn 			else {
10296659eda6Smartijn 				snprintf(df[i].proc, sizeof(df[i].proc),
10306659eda6Smartijn 				    "%lld%%", (used * 100) / size);
10316659eda6Smartijn 			}
10326659eda6Smartijn 			len = (int) strlen(df[i].proc);
10336659eda6Smartijn 			if (len > proclen)
10346659eda6Smartijn 				proclen = len;
10356659eda6Smartijn 			j++;
10366659eda6Smartijn 		}
10376659eda6Smartijn 		if (j == 0) {
10386659eda6Smartijn 			warnx("Failed to retrieve information for %s",
10396659eda6Smartijn 			    df[i].descr);
10406659eda6Smartijn 			memmove(df + i, df + i + 1,
10416659eda6Smartijn 			    (rows - i - 1) * sizeof(*df));
10426659eda6Smartijn 			rows--;
10436659eda6Smartijn 			i--;
10446659eda6Smartijn 		}
10456659eda6Smartijn 	}
10466659eda6Smartijn 
10476659eda6Smartijn 	printf("%-*s%*s%*s%*s%*s\n",
10486659eda6Smartijn 	    descrlen, "Description",
10496659eda6Smartijn 	    NEXTTAB(descrlen) + sizelen, "Size",
10506659eda6Smartijn 	    NEXTTAB(sizelen) + usedlen, "Used",
10516659eda6Smartijn 	    NEXTTAB(usedlen) + availlen, "Available",
10526659eda6Smartijn 	    NEXTTAB(availlen) + proclen, "Used%");
10536659eda6Smartijn 	for (i = 0; i < rows; i++) {
10541d333c94Smartijn 		printf("%s%*s%*s%*s%*s%*s\n",
10551d333c94Smartijn 		    df[i].descr, descrlen - df[i].descrwidth, "",
10566659eda6Smartijn 		    NEXTTAB(descrlen) + sizelen, df[i].size,
10576659eda6Smartijn 		    NEXTTAB(sizelen) + usedlen, df[i].used,
10586659eda6Smartijn 		    NEXTTAB(usedlen) + availlen, df[i].avail,
10596659eda6Smartijn 		    NEXTTAB(availlen) + proclen, df[i].proc);
10606659eda6Smartijn 	}
10616659eda6Smartijn 
10626659eda6Smartijn 	return 0;
10636659eda6Smartijn }
10646659eda6Smartijn 
1065442e4f4fSmartijn int
snmpc_mibtree(int argc,char * argv[])1066442e4f4fSmartijn snmpc_mibtree(int argc, char *argv[])
1067442e4f4fSmartijn {
1068442e4f4fSmartijn 	struct oid *oid;
1069f938cef3Smartijn 	struct ber_oid soid;
1070442e4f4fSmartijn 	char buf[BUFSIZ];
1071f938cef3Smartijn 	int i;
1072442e4f4fSmartijn 
1073f938cef3Smartijn 	if (argc == 0) {
10749265c3a7Smartijn 		for (oid = NULL; (oid = smi_foreach(oid)) != NULL;) {
1075f938cef3Smartijn 			smi_oid2string(&oid->o_id, buf, sizeof(buf),
1076f938cef3Smartijn 			    oid_lookup);
1077442e4f4fSmartijn 			printf("%s\n", buf);
1078442e4f4fSmartijn 		}
1079f938cef3Smartijn 	} else {
1080f938cef3Smartijn 		for (i = 0; i < argc; i++) {
1081f938cef3Smartijn 			if (smi_string2oid(argv[i], &soid) == -1) {
1082f938cef3Smartijn 				warnx("%s: Unknown object identifier", argv[i]);
1083f938cef3Smartijn 				continue;
1084f938cef3Smartijn 			}
1085f938cef3Smartijn 			smi_oid2string(&soid, buf, sizeof(buf), oid_lookup);
1086f938cef3Smartijn 			printf("%s\n", buf);
1087f938cef3Smartijn 		}
1088f938cef3Smartijn 	}
1089442e4f4fSmartijn 	return 0;
1090442e4f4fSmartijn }
1091442e4f4fSmartijn 
1092e13f0058Smartijn struct snmp_agent *
snmpc_connect(char * host,char * port)1093e13f0058Smartijn snmpc_connect(char *host, char *port)
1094e13f0058Smartijn {
1095e13f0058Smartijn 	switch (version) {
1096e13f0058Smartijn 	case SNMP_V1:
1097e13f0058Smartijn 	case SNMP_V2C:
1098e13f0058Smartijn 		return snmp_connect_v12(snmpc_parseagent(host, port), version,
1099e13f0058Smartijn 		    community);
1100b89ba26fSmartijn 	case SNMP_V3:
1101b89ba26fSmartijn 		return snmp_connect_v3(snmpc_parseagent(host, port), v3);
1102e13f0058Smartijn 	}
1103e13f0058Smartijn 	return NULL;
1104e13f0058Smartijn }
1105e13f0058Smartijn 
1106442e4f4fSmartijn int
snmpc_print(struct ber_element * elm)1107442e4f4fSmartijn snmpc_print(struct ber_element *elm)
1108442e4f4fSmartijn {
1109442e4f4fSmartijn 	struct ber_oid oid;
1110442e4f4fSmartijn 	char oids[SNMP_MAX_OID_STRLEN];
1111442e4f4fSmartijn 	char *value;
1112442e4f4fSmartijn 
1113442e4f4fSmartijn 	elm = elm->be_sub;
1114696b5899Stb 	if (ober_get_oid(elm, &oid) != 0) {
1115442e4f4fSmartijn 		errno = EINVAL;
1116442e4f4fSmartijn 		return 0;
1117442e4f4fSmartijn 	}
1118442e4f4fSmartijn 
1119442e4f4fSmartijn 	elm = elm->be_next;
11201248928aSmartijn 	value = smi_print_element(&oid, elm, smi_print_hint, output_string,
11211248928aSmartijn 	    oid_lookup, utf8);
1122442e4f4fSmartijn 	if (value == NULL)
1123442e4f4fSmartijn 		return 0;
1124442e4f4fSmartijn 
1125442e4f4fSmartijn 	if (print_varbind_only)
1126442e4f4fSmartijn 		printf("%s\n", value);
1127442e4f4fSmartijn 	else if (print_equals) {
1128442e4f4fSmartijn 		smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1129442e4f4fSmartijn 		printf("%s = %s\n", oids, value);
1130442e4f4fSmartijn 	} else {
1131442e4f4fSmartijn 		smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1132442e4f4fSmartijn 		printf("%s %s\n", oids, value);
1133442e4f4fSmartijn 	}
1134442e4f4fSmartijn 	free(value);
1135442e4f4fSmartijn 
1136442e4f4fSmartijn 	return 1;
1137442e4f4fSmartijn }
1138442e4f4fSmartijn 
1139442e4f4fSmartijn __dead void
snmpc_printerror(enum snmp_error error,struct ber_element * varbind,int index,const char * hint)11404ac39592Smartijn snmpc_printerror(enum snmp_error error, struct ber_element *varbind,
11414ac39592Smartijn     int index, const char *hint)
1142442e4f4fSmartijn {
11434ac39592Smartijn 	struct ber_oid hoid, vboid;
11444ac39592Smartijn 	char oids[SNMP_MAX_OID_STRLEN];
11454ac39592Smartijn 	const char *oid = NULL;
11464ac39592Smartijn 	int i;
11474ac39592Smartijn 
11484ac39592Smartijn 	if (index >= 1) {
11494ac39592Smartijn 		/* Only print if the index is in the reply */
1150aa37fc65Smartijn 		for (i = 1; varbind != NULL && i < index;
11514ac39592Smartijn 		    varbind = varbind->be_next)
11524ac39592Smartijn 			i++;
11534ac39592Smartijn 		if (varbind != NULL &&
1154696b5899Stb 		    ober_get_oid(varbind->be_sub, &vboid) == 0) {
11554ac39592Smartijn 			/* If user and reply conform print user input */
11564ac39592Smartijn 			if (hint != NULL &&
11574ac39592Smartijn 			    smi_string2oid(hint, &hoid) == 0 &&
1158696b5899Stb 			    ober_oid_cmp(&hoid, &vboid) == 0)
11594ac39592Smartijn 				oid = hint;
11604ac39592Smartijn 			else
11614ac39592Smartijn 				oid = smi_oid2string(&vboid, oids,
11624ac39592Smartijn 				    sizeof(oids), oid_lookup);
11634ac39592Smartijn 		}
11644ac39592Smartijn 	}
11654ac39592Smartijn 	if (oid == NULL)
11664ac39592Smartijn 		oid = "?";
11674ac39592Smartijn 
116824e1e325Sderaadt 	switch (error) {
1169442e4f4fSmartijn 	case SNMP_ERROR_NONE:
1170442e4f4fSmartijn 		errx(1, "No error, how did I get here?");
1171442e4f4fSmartijn 	case SNMP_ERROR_TOOBIG:
1172442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Response too big", oid);
1173442e4f4fSmartijn 	case SNMP_ERROR_NOSUCHNAME:
1174442e4f4fSmartijn 		errx(1, "Can't parse oid %s: No such object", oid);
1175442e4f4fSmartijn 	case SNMP_ERROR_BADVALUE:
1176442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Bad value", oid);
1177442e4f4fSmartijn 	case SNMP_ERROR_READONLY:
1178442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Read only", oid);
1179442e4f4fSmartijn 	case SNMP_ERROR_GENERR:
1180442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Generic error", oid);
1181442e4f4fSmartijn 	case SNMP_ERROR_NOACCESS:
1182442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Access denied", oid);
1183442e4f4fSmartijn 	case SNMP_ERROR_WRONGTYPE:
1184442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Wrong type", oid);
1185442e4f4fSmartijn 	case SNMP_ERROR_WRONGLENGTH:
1186442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Wrong length", oid);
1187442e4f4fSmartijn 	case SNMP_ERROR_WRONGENC:
1188442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Wrong encoding", oid);
1189442e4f4fSmartijn 	case SNMP_ERROR_WRONGVALUE:
1190442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Wrong value", oid);
1191442e4f4fSmartijn 	case SNMP_ERROR_NOCREATION:
1192442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Can't be created", oid);
1193442e4f4fSmartijn 	case SNMP_ERROR_INCONVALUE:
1194442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Inconsistent value", oid);
1195442e4f4fSmartijn 	case SNMP_ERROR_RESUNAVAIL:
1196442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Resource unavailable", oid);
1197442e4f4fSmartijn 	case SNMP_ERROR_COMMITFAILED:
1198442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Commit failed", oid);
1199442e4f4fSmartijn 	case SNMP_ERROR_UNDOFAILED:
1200d9a51c35Sjmc 		errx(1, "Can't parse oid %s: Undo failed", oid);
1201442e4f4fSmartijn 	case SNMP_ERROR_AUTHERROR:
1202442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Authorization error", oid);
1203442e4f4fSmartijn 	case SNMP_ERROR_NOTWRITABLE:
1204442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Not writable", oid);
1205442e4f4fSmartijn 	case SNMP_ERROR_INCONNAME:
1206442e4f4fSmartijn 		errx(1, "Can't parse oid %s: Inconsistent name", oid);
1207442e4f4fSmartijn 	}
1208442e4f4fSmartijn 	errx(1, "Can't parse oid %s: Unknown error (%d)", oid, error);
1209442e4f4fSmartijn }
1210442e4f4fSmartijn 
1211442e4f4fSmartijn int
snmpc_parseagent(char * agent,char * defaultport)1212442e4f4fSmartijn snmpc_parseagent(char *agent, char *defaultport)
1213442e4f4fSmartijn {
1214442e4f4fSmartijn 	struct addrinfo hints, *ai, *ai0 = NULL;
1215442e4f4fSmartijn 	struct sockaddr_un saddr;
1216442e4f4fSmartijn 	char *agentdup, *specifier, *hostname, *port = NULL;
1217442e4f4fSmartijn 	int error;
1218442e4f4fSmartijn 	int s;
1219442e4f4fSmartijn 
1220442e4f4fSmartijn 	if ((agentdup = specifier = strdup(agent)) == NULL)
1221442e4f4fSmartijn 		err(1, NULL);
1222442e4f4fSmartijn 
1223442e4f4fSmartijn 	bzero(&hints, sizeof(hints));
1224442e4f4fSmartijn 	if ((hostname = strchr(specifier, ':')) != NULL) {
1225442e4f4fSmartijn 		*hostname++ = '\0';
1226442e4f4fSmartijn 		if (strcasecmp(specifier, "udp") == 0) {
1227442e4f4fSmartijn 			hints.ai_family = AF_INET;
1228442e4f4fSmartijn 			hints.ai_socktype = SOCK_DGRAM;
1229442e4f4fSmartijn 		} else if (strcasecmp(specifier, "tcp") == 0) {
1230442e4f4fSmartijn 			hints.ai_family = AF_INET;
1231442e4f4fSmartijn 			hints.ai_socktype = SOCK_STREAM;
1232442e4f4fSmartijn 		} else if (strcasecmp(specifier, "udp6") == 0 ||
1233442e4f4fSmartijn 		    strcasecmp(specifier, "udpv6") == 0 ||
1234442e4f4fSmartijn 		    strcasecmp(specifier, "udpipv6") == 0) {
1235442e4f4fSmartijn 			hints.ai_family = AF_INET6;
1236442e4f4fSmartijn 			hints.ai_socktype = SOCK_DGRAM;
1237442e4f4fSmartijn 		} else if (strcasecmp(specifier, "tcp6") == 0 ||
1238442e4f4fSmartijn 		    strcasecmp(specifier, "tcpv6") == 0 ||
1239442e4f4fSmartijn 		    strcasecmp(specifier, "tcpipv6") == 0) {
1240442e4f4fSmartijn 			hints.ai_family = AF_INET6;
1241442e4f4fSmartijn 			hints.ai_socktype = SOCK_STREAM;
1242442e4f4fSmartijn 		} else if (strcasecmp(specifier, "unix") == 0) {
1243442e4f4fSmartijn 			hints.ai_family = AF_UNIX;
1244442e4f4fSmartijn 			hints.ai_addr = (struct sockaddr *)&saddr;
1245442e4f4fSmartijn 			hints.ai_addrlen = sizeof(saddr);
1246442e4f4fSmartijn 			saddr.sun_len = sizeof(saddr);
1247442e4f4fSmartijn 			saddr.sun_family = AF_UNIX;
1248442e4f4fSmartijn 			if (strlcpy(saddr.sun_path, hostname,
1249442e4f4fSmartijn 			    sizeof(saddr.sun_path)) > sizeof(saddr.sun_path))
1250442e4f4fSmartijn 				errx(1, "Hostname path too long");
1251442e4f4fSmartijn 			ai = &hints;
1252442e4f4fSmartijn 		} else {
12536dd7164bSmartijn 			*--hostname = ':';
1254442e4f4fSmartijn 			hostname = specifier;
1255442e4f4fSmartijn 		}
12566dd7164bSmartijn 	} else {
12576dd7164bSmartijn 		hostname = specifier;
12586dd7164bSmartijn 	}
12596dd7164bSmartijn 
1260442e4f4fSmartijn 	if (hints.ai_family == AF_INET) {
1261442e4f4fSmartijn 		if ((port = strchr(hostname, ':')) != NULL)
1262442e4f4fSmartijn 			*port++ = '\0';
12636dd7164bSmartijn 	} else if (hints.ai_family == AF_INET6 || hints.ai_family == 0) {
1264442e4f4fSmartijn 		if (hostname[0] == '[') {
12656dd7164bSmartijn 			hints.ai_family = AF_INET6;
1266442e4f4fSmartijn 			hostname++;
1267442e4f4fSmartijn 			if ((port = strchr(hostname, ']')) == NULL)
1268442e4f4fSmartijn 				errx(1, "invalid agent");
1269442e4f4fSmartijn 			*port++ = '\0';
1270442e4f4fSmartijn 			if (port[0] == ':')
1271442e4f4fSmartijn 				*port++ = '\0';
12726dd7164bSmartijn 			else if (port[0] == '\0')
1273442e4f4fSmartijn 				port = NULL;
12746dd7164bSmartijn 			else
1275442e4f4fSmartijn 				errx(1, "invalid agent");
12766dd7164bSmartijn 		} else {
12776dd7164bSmartijn 			if ((port = strrchr(hostname, ':')) != NULL)
1278442e4f4fSmartijn 				*port++ = '\0';
1279442e4f4fSmartijn 		}
1280442e4f4fSmartijn 	}
1281442e4f4fSmartijn 
1282442e4f4fSmartijn 	if (hints.ai_family != AF_UNIX) {
12836dd7164bSmartijn 		if (hints.ai_socktype == 0)
12846dd7164bSmartijn 			hints.ai_socktype = SOCK_DGRAM;
1285442e4f4fSmartijn 		if (port == NULL)
1286442e4f4fSmartijn 			port = defaultport;
1287442e4f4fSmartijn 		error = getaddrinfo(hostname, port, &hints, &ai0);
12886dd7164bSmartijn 		if (error) {
12899b9b25beSmartijn 			if (error != EAI_NODATA || port == defaultport)
12906dd7164bSmartijn 				errx(1, "%s", gai_strerror(error));
12916dd7164bSmartijn 			*--port = ':';
12926dd7164bSmartijn 			error = getaddrinfo(hostname, defaultport, &hints,
12936dd7164bSmartijn 			    &ai0);
1294442e4f4fSmartijn 			if (error)
1295442e4f4fSmartijn 				errx(1, "%s", gai_strerror(error));
12966dd7164bSmartijn 		}
1297442e4f4fSmartijn 		s = -1;
1298442e4f4fSmartijn 		for (ai = ai0; ai != NULL; ai = ai->ai_next) {
1299442e4f4fSmartijn 			if ((s = socket(ai->ai_family, ai->ai_socktype,
13006dd7164bSmartijn 			    ai->ai_protocol)) != -1 &&
13016dd7164bSmartijn 			    connect(s, (struct sockaddr *)ai->ai_addr,
13026dd7164bSmartijn 			    ai->ai_addrlen) != -1)
1303442e4f4fSmartijn 				break;
13049b9b25beSmartijn 			close(s);
13059b9b25beSmartijn 			s = -1;
1306442e4f4fSmartijn 		}
13076dd7164bSmartijn 	} else {
13086dd7164bSmartijn 		s = socket(AF_UNIX, SOCK_STREAM, 0);
13096dd7164bSmartijn 		if (connect(s, (struct sockaddr *)ai->ai_addr,
13106dd7164bSmartijn 		    ai->ai_addrlen) == -1)
1311442e4f4fSmartijn 			err(1, "Can't connect to %s", agent);
13126dd7164bSmartijn 	}
13136dd7164bSmartijn 	if (s == -1)
13146dd7164bSmartijn 		err(1, "Can't connect to agent %s", agent);
13156dd7164bSmartijn 
1316442e4f4fSmartijn 
1317442e4f4fSmartijn 	if (ai0 != NULL)
1318442e4f4fSmartijn 		freeaddrinfo(ai0);
1319442e4f4fSmartijn 	free(agentdup);
1320442e4f4fSmartijn 	return s;
1321442e4f4fSmartijn }
1322442e4f4fSmartijn 
1323b89ba26fSmartijn char *
snmpc_hex2bin(char * hexstr,size_t * binlen)1324b89ba26fSmartijn snmpc_hex2bin(char *hexstr, size_t *binlen)
1325b89ba26fSmartijn {
1326b89ba26fSmartijn 	char *decstr;
1327b89ba26fSmartijn 
1328b89ba26fSmartijn 	if (hexstr[0] == '0' && hexstr[1] == 'x')
1329b89ba26fSmartijn 		hexstr += 2;
1330b89ba26fSmartijn 	while (hexstr[0] == ' ' || hexstr[0] == '\t')
1331b89ba26fSmartijn 		hexstr++;
1332b89ba26fSmartijn 
1333b89ba26fSmartijn 	if ((decstr = malloc((strlen(hexstr) / 2) + 1)) == NULL)
1334b89ba26fSmartijn 		return NULL;
1335b89ba26fSmartijn 
1336b89ba26fSmartijn 	for (*binlen = 0; hexstr[0] != '\0'; (*binlen)++) {
1337b89ba26fSmartijn 		hexstr[0] = toupper(hexstr[0]);
1338b89ba26fSmartijn 		hexstr[1] = toupper(hexstr[1]);
1339b89ba26fSmartijn 		if (hexstr[0] >= '0' && hexstr[0] <= '9')
1340b89ba26fSmartijn 			decstr[*binlen] = (hexstr[0] - '0') << 4;
1341b89ba26fSmartijn 		else if (hexstr[0] >= 'A' && hexstr[0] <= 'F')
1342b89ba26fSmartijn 			decstr[*binlen] = ((hexstr[0] - 'A') + 10) << 4;
1343b89ba26fSmartijn 		else
1344b89ba26fSmartijn 			goto fail;
1345b89ba26fSmartijn 		if (hexstr[1] >= '0' && hexstr[1] <= '9')
1346b89ba26fSmartijn 			decstr[*binlen] |= (hexstr[1] - '0');
1347b89ba26fSmartijn 		else if (hexstr[1] >= 'A' && hexstr[1] <= 'F')
1348b89ba26fSmartijn 			decstr[*binlen] |= (hexstr[1] - 'A') + 10;
1349b89ba26fSmartijn 		else
1350b89ba26fSmartijn 			goto fail;
1351b89ba26fSmartijn 
1352b89ba26fSmartijn 		hexstr += 2;
1353b89ba26fSmartijn 		while (hexstr[0] == ' ' || hexstr[0] == '\t')
1354b89ba26fSmartijn 			hexstr++;
1355b89ba26fSmartijn 	}
1356b89ba26fSmartijn 
1357b89ba26fSmartijn 	return decstr;
1358b89ba26fSmartijn fail:
1359b89ba26fSmartijn 	errno = EINVAL;
1360b89ba26fSmartijn 	free(decstr);
1361b89ba26fSmartijn 	return NULL;
1362b89ba26fSmartijn }
1363b89ba26fSmartijn 
13641d333c94Smartijn ssize_t
snmpc_mbswidth(char * str)13651d333c94Smartijn snmpc_mbswidth(char *str)
13661d333c94Smartijn {
13671d333c94Smartijn 	wchar_t wc;
13681d333c94Smartijn 	size_t width = 0;
13691d333c94Smartijn 	size_t i;
13701d333c94Smartijn 	int len;
13711d333c94Smartijn 
13721d333c94Smartijn 	for (i = 0; (len = mbtowc(&wc, &(str[i]), MB_CUR_MAX)) != 0; i += len) {
13731d333c94Smartijn 		if (len == -1) {
13741d333c94Smartijn 			mbtowc(NULL, NULL, MB_CUR_MAX);
13751d333c94Smartijn 			return -1;
13761d333c94Smartijn 		}
13771d333c94Smartijn 		width += wcwidth(wc);
13781d333c94Smartijn 	}
13791d333c94Smartijn 	return width;
13801d333c94Smartijn }
13811d333c94Smartijn 
1382ecb1f8acSmartijn struct ber_element *
snmpc_varbindparse(int argc,char * argv[])1383ecb1f8acSmartijn snmpc_varbindparse(int argc, char *argv[])
1384ecb1f8acSmartijn {
1385ecb1f8acSmartijn 	struct ber_oid oid, oidval;
1386ecb1f8acSmartijn 	struct in_addr addr4;
1387ecb1f8acSmartijn 	char *addr = (char *)&addr4;
1388ecb1f8acSmartijn 	char *str = NULL, *tmpstr, *endstr;
1389ecb1f8acSmartijn 	const char *errstr = NULL;
1390ecb1f8acSmartijn 	struct ber_element *varbind = NULL, *vblist = NULL;
1391ecb1f8acSmartijn 	int i, ret;
1392ecb1f8acSmartijn 	size_t strl, byte;
1393ecb1f8acSmartijn 	long long lval;
1394ecb1f8acSmartijn 
1395ecb1f8acSmartijn 	if (argc % 3 != 0)
1396ecb1f8acSmartijn 		usage();
1397ecb1f8acSmartijn 	for (i = 0; i < argc; i += 3) {
1398ecb1f8acSmartijn 		if (smi_string2oid(argv[i], &oid) == -1)
1399ecb1f8acSmartijn 			errx(1, "Invalid oid: %s\n", argv[i]);
1400ecb1f8acSmartijn 		switch (argv[i + 1][0]) {
1401ecb1f8acSmartijn 		case 'a':
1402ecb1f8acSmartijn 			ret = inet_pton(AF_INET, argv[i + 2], &addr4);
1403ecb1f8acSmartijn 			if (ret == -1)
1404ecb1f8acSmartijn 				err(1, "inet_pton");
1405ecb1f8acSmartijn 			if (ret == 0)
1406ecb1f8acSmartijn 				errx(1, "%s: Bad value notation (%s)", argv[i],
1407ecb1f8acSmartijn 				    argv[i + 2]);
1408696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{Oxt}",
1409ecb1f8acSmartijn 			    &oid, addr, sizeof(addr4), BER_CLASS_APPLICATION,
1410ecb1f8acSmartijn 			    SNMP_T_IPADDR)) == NULL)
1411696b5899Stb 				err(1, "ober_printf_elements");
1412ecb1f8acSmartijn 			break;
1413ecb1f8acSmartijn 		case 'b':
1414ecb1f8acSmartijn 			tmpstr = argv[i + 2];
1415ecb1f8acSmartijn 			strl = 0;
1416ecb1f8acSmartijn 			do {
1417ecb1f8acSmartijn 				lval = strtoll(tmpstr, &endstr, 10);
1418ecb1f8acSmartijn 				if (endstr[0] != ' ' && endstr[0] != '\t' &&
1419ecb1f8acSmartijn 				    endstr[0] != ',' && endstr[0] != '\0')
1420ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1421ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1422ecb1f8acSmartijn 				if (tmpstr == endstr) {
1423ecb1f8acSmartijn 					tmpstr++;
1424ecb1f8acSmartijn 					continue;
1425ecb1f8acSmartijn 				}
1426ecb1f8acSmartijn 				if (lval < 0)
1427ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1428ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1429ecb1f8acSmartijn 				byte = lval / 8;
1430ecb1f8acSmartijn 				if (byte >= strl) {
1431ecb1f8acSmartijn 					if ((str = recallocarray(str, strl,
1432ecb1f8acSmartijn 					    byte + 1, 1)) == NULL)
1433ecb1f8acSmartijn 						err(1, "malloc");
1434ecb1f8acSmartijn 					strl = byte + 1;
1435ecb1f8acSmartijn 				}
1436ecb1f8acSmartijn 				str[byte] |= 0x80 >> (lval % 8);
1437ecb1f8acSmartijn 				tmpstr = endstr + 1;
1438ecb1f8acSmartijn 			} while (endstr[0] != '\0');
1439ecb1f8acSmartijn 			/*
1440ecb1f8acSmartijn 			 * RFC3416 Section 2.5
1441ecb1f8acSmartijn 			 * A BITS value is encoded as an OCTET STRING
1442ecb1f8acSmartijn 			 */
1443ecb1f8acSmartijn 			goto pastestring;
1444ecb1f8acSmartijn 		case 'c':
1445928fb303Smartijn 			lval = strtonum(argv[i + 2], 0, UINT32_MAX,
1446ecb1f8acSmartijn 			    &errstr);
1447ecb1f8acSmartijn 			if (errstr != NULL)
1448ecb1f8acSmartijn 				errx(1, "%s: Bad value notation (%s)", argv[i],
1449ecb1f8acSmartijn 				    argv[i + 2]);
1450696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{Oit}",
1451ecb1f8acSmartijn 			    &oid, lval, BER_CLASS_APPLICATION,
1452ecb1f8acSmartijn 			    SNMP_T_COUNTER32)) == NULL)
1453696b5899Stb 				err(1, "ober_printf_elements");
1454ecb1f8acSmartijn 			break;
1455ecb1f8acSmartijn 		case 'd':
1456ecb1f8acSmartijn 			/* String always shrinks */
1457ecb1f8acSmartijn 			if ((str = malloc(strlen(argv[i + 2]))) == NULL)
1458ecb1f8acSmartijn 				err(1, "malloc");
1459ecb1f8acSmartijn 			tmpstr = argv[i + 2];
1460ecb1f8acSmartijn 			strl = 0;
1461ecb1f8acSmartijn 			do {
1462ecb1f8acSmartijn 				lval = strtoll(tmpstr, &endstr, 10);
1463ecb1f8acSmartijn 				if (endstr[0] != ' ' && endstr[0] != '\t' &&
1464ecb1f8acSmartijn 				    endstr[0] != '\0')
1465ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1466ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1467ecb1f8acSmartijn 				if (tmpstr == endstr) {
1468ecb1f8acSmartijn 					tmpstr++;
1469ecb1f8acSmartijn 					continue;
1470ecb1f8acSmartijn 				}
1471ecb1f8acSmartijn 				if (lval < 0 || lval > 0xff)
1472ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1473ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1474ecb1f8acSmartijn 				str[strl++] = (unsigned char) lval;
1475ecb1f8acSmartijn 				tmpstr = endstr + 1;
1476ecb1f8acSmartijn 			} while (endstr[0] != '\0');
1477ecb1f8acSmartijn 			goto pastestring;
1478ecb1f8acSmartijn 		case 'i':
1479928fb303Smartijn 			lval = strtonum(argv[i + 2], INT32_MIN, INT32_MAX,
1480ecb1f8acSmartijn 			    &errstr);
1481ecb1f8acSmartijn 			if (errstr != NULL)
1482ecb1f8acSmartijn 				errx(1, "%s: Bad value notation (%s)", argv[i],
1483ecb1f8acSmartijn 				    argv[i + 2]);
1484696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{Oi}",
1485ecb1f8acSmartijn 			    &oid, lval)) == NULL)
1486696b5899Stb 				err(1, "ober_printf_elements");
1487ecb1f8acSmartijn 			break;
1488ecb1f8acSmartijn 		case 'n':
1489696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{O0}",
1490ecb1f8acSmartijn 			    &oid)) == NULL)
1491696b5899Stb 				err(1, "ober_printf_elements");
1492ecb1f8acSmartijn 			break;
1493ecb1f8acSmartijn 		case 'o':
1494ecb1f8acSmartijn 			if (smi_string2oid(argv[i + 2], &oidval) == -1)
1495ecb1f8acSmartijn 				errx(1, "%s: Unknown Object Identifier (Sub-id "
1496ecb1f8acSmartijn 				    "not found: (top) -> %s)", argv[i],
1497ecb1f8acSmartijn 				    argv[i + 2]);
1498696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{OO}",
1499ecb1f8acSmartijn 			    &oid, &oidval)) == NULL)
1500696b5899Stb 				err(1, "ober_printf_elements");
1501ecb1f8acSmartijn 			break;
1502ecb1f8acSmartijn 		case 's':
1503ecb1f8acSmartijn 			if ((str = strdup(argv[i + 2])) == NULL)
1504ecb1f8acSmartijn 				err(1, NULL);
1505ecb1f8acSmartijn 			strl = strlen(argv[i + 2]);
1506ecb1f8acSmartijn pastestring:
1507696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{Ox}",
1508ecb1f8acSmartijn 			    &oid, str, strl)) == NULL)
1509696b5899Stb 				err(1, "ober_printf_elements");
1510ecb1f8acSmartijn 			free(str);
1511ecb1f8acSmartijn 			break;
1512ecb1f8acSmartijn 		case 't':
1513928fb303Smartijn 			lval = strtonum(argv[i + 2], 0, UINT32_MAX,
1514ecb1f8acSmartijn 			    &errstr);
1515ecb1f8acSmartijn 			if (errstr != NULL)
1516ecb1f8acSmartijn 				errx(1, "%s: Bad value notation (%s)", argv[i],
1517ecb1f8acSmartijn 				    argv[i + 2]);
1518696b5899Stb 			if ((varbind = ober_printf_elements(varbind, "{Oit}",
1519ecb1f8acSmartijn 			    &oid, lval, BER_CLASS_APPLICATION,
1520ecb1f8acSmartijn 			    SNMP_T_TIMETICKS)) == NULL)
1521696b5899Stb 				err(1, "ober_printf_elements");
1522ecb1f8acSmartijn 			break;
1523928fb303Smartijn 		case 'u':
1524928fb303Smartijn 			lval = strtonum(argv[i + 2], 0, UINT32_MAX,
1525928fb303Smartijn 			    &errstr);
1526928fb303Smartijn 			if (errstr != NULL)
1527928fb303Smartijn 				errx(1, "%s: Bad value notation (%s)", argv[i],
1528928fb303Smartijn 				    argv[i + 2]);
1529928fb303Smartijn 			if ((varbind = ober_printf_elements(varbind, "{Oit}",
1530928fb303Smartijn 			    &oid, lval, BER_CLASS_APPLICATION,
1531928fb303Smartijn 			    SNMP_T_GAUGE32)) == NULL)
1532928fb303Smartijn 				err(1, "ober_printf_elements");
1533928fb303Smartijn 			break;
1534ecb1f8acSmartijn 		case 'x':
1535ecb1f8acSmartijn 			/* String always shrinks */
1536ecb1f8acSmartijn 			if ((str = malloc(strlen(argv[i + 2]))) == NULL)
1537ecb1f8acSmartijn 				err(1, "malloc");
1538ecb1f8acSmartijn 			tmpstr = argv[i + 2];
1539ecb1f8acSmartijn 			strl = 0;
1540ecb1f8acSmartijn 			do {
1541ecb1f8acSmartijn 				lval = strtoll(tmpstr, &endstr, 16);
1542ecb1f8acSmartijn 				if (endstr[0] != ' ' && endstr[0] != '\t' &&
1543ecb1f8acSmartijn 				    endstr[0] != '\0')
1544ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1545ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1546ecb1f8acSmartijn 				if (tmpstr == endstr) {
1547ecb1f8acSmartijn 					tmpstr++;
1548ecb1f8acSmartijn 					continue;
1549ecb1f8acSmartijn 				}
1550ecb1f8acSmartijn 				if (lval < 0 || lval > 0xff)
1551ecb1f8acSmartijn 					errx(1, "%s: Bad value notation (%s)",
1552ecb1f8acSmartijn 					    argv[i], argv[i + 2]);
1553ecb1f8acSmartijn 				str[strl++] = (unsigned char) lval;
1554ecb1f8acSmartijn 				tmpstr = endstr + 1;
1555ecb1f8acSmartijn 			} while (endstr[0] != '\0');
1556ecb1f8acSmartijn 			goto pastestring;
1557ecb1f8acSmartijn 		default:
1558ecb1f8acSmartijn 			usage();
1559ecb1f8acSmartijn 		}
1560ecb1f8acSmartijn 		if (vblist == NULL)
1561ecb1f8acSmartijn 			vblist = varbind;
1562ecb1f8acSmartijn 	}
1563ecb1f8acSmartijn 
1564ecb1f8acSmartijn 	return vblist;
1565ecb1f8acSmartijn }
1566ecb1f8acSmartijn 
1567442e4f4fSmartijn __dead void
usage(void)1568442e4f4fSmartijn usage(void)
1569442e4f4fSmartijn {
1570442e4f4fSmartijn 	size_t i;
1571442e4f4fSmartijn 
1572442e4f4fSmartijn 	if (snmp_app != NULL) {
1573b89ba26fSmartijn 		fprintf(stderr, "usage: snmp %s%s%s\n",
15740952f62dSmartijn 		    snmp_app->name,
1575442e4f4fSmartijn 		    snmp_app->usecommonopt ?
15764f098f75Smartijn 		    " [-A authpass] [-a digest] [-c community] [-e secengineid]\n"
1577f5e30c24Smartijn 		    "            [-E ctxengineid] [-K localpriv] [-k localauth] [-l seclevel]\n"
1578f5e30c24Smartijn 		    "            [-n ctxname] [-O afnqvxSQ] [-r retries] [-t timeout] [-u user]\n"
1579f5e30c24Smartijn 		    "            [-v version] [-X privpass] [-x cipher] [-Z boots,time]\n"
1580b89ba26fSmartijn 		    "            " : "",
1581442e4f4fSmartijn 		    snmp_app->usage == NULL ? " " : snmp_app->usage);
1582442e4f4fSmartijn 		exit(1);
1583442e4f4fSmartijn 	}
1584442e4f4fSmartijn 	for (i = 0; i < (sizeof(snmp_apps)/sizeof(*snmp_apps)); i++) {
15850952f62dSmartijn 		if (i == 0)
15860952f62dSmartijn 			fprintf(stderr, "usage: ");
15870952f62dSmartijn 		else
15880952f62dSmartijn 			fprintf(stderr, "       ");
15890952f62dSmartijn 		fprintf(stderr, "snmp %s%s %s\n",
15900952f62dSmartijn 		    snmp_apps[i].name,
1591442e4f4fSmartijn 		    snmp_apps[i].usecommonopt ?
15920d36e06eSmartijn 		    " [options]" : "",
15930952f62dSmartijn 		    snmp_apps[i].usage ? snmp_apps[i].usage : "");
1594442e4f4fSmartijn 	}
1595442e4f4fSmartijn 	exit(1);
1596442e4f4fSmartijn }
1597