Bug Summary

File:src/usr.bin/snmp/snmpc.c
Warning:line 472, column 7
Potential leak of memory pointed to by 'ctxengineid'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name snmpc.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/snmp/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/snmp -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/snmp/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/snmp/snmpc.c
1/* $OpenBSD: snmpc.c,v 1.38 2021/10/21 08:17:34 martijn Exp $ */
2
3/*
4 * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
5 * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/limits.h>
21#include <sys/types.h>
22#include <sys/socket.h>
23#include <sys/un.h>
24
25#include <arpa/inet.h>
26#include <openssl/evp.h>
27
28#include <ber.h>
29#include <ctype.h>
30#include <err.h>
31#include <errno(*__errno()).h>
32#include <locale.h>
33#include <netdb.h>
34#include <poll.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <stdint.h>
38#include <string.h>
39#include <time.h>
40#include <unistd.h>
41#include <util.h>
42#include <wchar.h>
43
44#include "smi.h"
45#include "snmp.h"
46#include "usm.h"
47
48#define GETOPT_COMMON"A:a:c:E:e:K:k:l:n:O:r:t:u:v:X:x:Z:" "A:a:c:E:e:K:k:l:n:O:r:t:u:v:X:x:Z:"
49
50int snmpc_get(int, char *[]);
51int snmpc_walk(int, char *[]);
52int snmpc_set(int, char *[]);
53int snmpc_trap(int, char *[]);
54int snmpc_df(int, char *[]);
55int snmpc_mibtree(int, char *[]);
56struct snmp_agent *snmpc_connect(char *, char *);
57int snmpc_parseagent(char *, char *);
58int snmpc_print(struct ber_element *);
59__dead__attribute__((__noreturn__)) void snmpc_printerror(enum snmp_error, struct ber_element *, int,
60 const char *);
61char *snmpc_hex2bin(char *, size_t *);
62ssize_t snmpc_mbswidth(char *);
63struct ber_element *snmpc_varbindparse(int, char *[]);
64void usage(void);
65
66struct snmp_app {
67 const char *name;
68 const int usecommonopt;
69 const char *optstring;
70 const char *usage;
71 int (*exec)(int, char *[]);
72};
73
74struct snmp_app snmp_apps[] = {
75 { "get", 1, NULL((void *)0), "agent oid ...", snmpc_get },
76 { "getnext", 1, NULL((void *)0), "agent oid ...", snmpc_get },
77 { "walk", 1, "C:", "[-C cIipt] [-C E endoid] [-C s skipoid] agent [oid]", snmpc_walk },
78 { "bulkget", 1, "C:", "[-C n<nonrep>r<maxrep>] agent oid ...", snmpc_get },
79 { "bulkwalk", 1, "C:", "[-C cipn<nonrep>r<maxrep>] [-C s skipoid] agent [oid]", snmpc_walk },
80 { "set", 1, NULL((void *)0), "agent oid type value [oid type value] ...", snmpc_set },
81 { "trap", 1, NULL((void *)0), "agent uptime oid [oid type value] ...", snmpc_trap },
82 { "df", 1, "C:", "[-Ch] [-Cr<maxrep>] agent", snmpc_df },
83 { "mibtree", 0, "O:", "[-O fnS] [oid ...]", snmpc_mibtree }
84};
85struct snmp_app *snmp_app = NULL((void *)0);
86
87char *community = NULL((void *)0);
88struct snmp_v3 *v3;
89char *mib = "mib_2";
90int retries = 5;
91int timeout = 1;
92enum snmp_version version = SNMP_V3;
93int print_equals = 1;
94int print_varbind_only = 0;
95int print_summary = 0;
96int print_time = 0;
97int print_human = 0;
98int walk_check_increase = 1;
99int walk_fallback_oid = 1;
100int walk_include_oid = 0;
101int smi_print_hint = 1;
102int non_repeaters = 0;
103int max_repetitions = 10;
104struct ber_oid walk_end = {{0}, 0};
105struct ber_oid *walk_skip = NULL((void *)0);
106size_t walk_skip_len = 0;
107enum smi_oid_lookup oid_lookup = smi_oidl_short;
108enum smi_output_string output_string = smi_os_default;
109int utf8 = 0;
110
111int
112main(int argc, char *argv[])
113{
114 const EVP_MD *md = NULL((void *)0);
115 const EVP_CIPHER *cipher = NULL((void *)0);
116 struct snmp_sec *sec;
117 char *user = NULL((void *)0);
118 enum usm_key_level authkeylevel = USM_KEY_UNSET;
119 char *authkey = NULL((void *)0);
120 size_t authkeylen = 0;
121 enum usm_key_level privkeylevel = USM_KEY_UNSET;
122 char *privkey = NULL((void *)0);
123 size_t privkeylen = 0;
124 int seclevel = SNMP_MSGFLAG_REPORT0x04;
125 char *ctxname = NULL((void *)0);
126 char *ctxengineid = NULL((void *)0), *secengineid = NULL((void *)0);
127 size_t ctxengineidlen, secengineidlen;
128 int zflag = 0;
129 long long boots = 0, time = 0;
130 char optstr[BUFSIZ1024];
131 const char *errstr;
132 char *strtolp;
133 int ch;
134 size_t i;
135
136 /*
137 * Determine if output can handle UTF-8 based on locale.
138 */
139 setlocale(LC_CTYPE2, "");
140 utf8 = MB_CUR_MAX__mb_cur_max() > 1;
1
Assuming the condition is false
141 /*
142 * SMIv2 allows for UTF-8 text at some locations.
143 * Set it explicitly so we can handle it on the input side.
144 */
145 if (setlocale(LC_CTYPE2, "en_US.UTF-8") == NULL((void *)0))
2
Assuming the condition is false
3
Taking false branch
146 errx(1, "setlocale(LC_CTYPE, \"en_US.UTF-8\") failed");
147
148 if (pledge("stdio inet dns unix", NULL((void *)0)) == -1)
4
Assuming the condition is false
5
Taking false branch
149 err(1, "pledge");
150
151 if (argc <= 1)
6
Assuming 'argc' is > 1
7
Taking false branch
152 usage();
153
154 optstr[0] = '\0';
155 for (i = 0; i < sizeof(snmp_apps)/sizeof(*snmp_apps); i++) {
8
Loop condition is true. Entering loop body
156 if (strcmp(snmp_apps[i].name, argv[1]) == 0) {
9
Assuming the condition is true
10
Taking true branch
157 snmp_app = &snmp_apps[i];
158 if (snmp_app->optstring != NULL((void *)0)) {
11
Assuming field 'optstring' is equal to NULL
12
Taking false branch
159 if (strlcpy(optstr, snmp_app->optstring,
160 sizeof(optstr)) > sizeof(optstr))
161 errx(1, "strlcat");
162 }
163 break;
13
Execution continues on line 166
164 }
165 }
166 if (snmp_app
13.1
'snmp_app' is not equal to NULL
== NULL((void *)0))
14
Taking false branch
167 usage();
168
169 if (snmp_app->usecommonopt) {
15
Assuming field 'usecommonopt' is 0
16
Taking false branch
170 if (strlcat(optstr, GETOPT_COMMON"A:a:c:E:e:K:k:l:n:O:r:t:u:v:X:x:Z:", sizeof(optstr)) >
171 sizeof(optstr))
172 errx(1, "strlcpy");
173 }
174
175 argc--;
176 argv++;
177
178 smi_init();
179
180 while ((ch = getopt(argc, argv, optstr)) != -1) {
17
Assuming the condition is true
18
Loop condition is true. Entering loop body
33
Assuming the condition is false
34
Loop condition is false. Execution continues on line 468
181 switch (ch) {
19
Control jumps to 'case 69:' at line 207
182 case 'A':
183 authkey = optarg;
184 authkeylen = strlen(authkey);
185 authkeylevel = USM_KEY_PASSWORD;
186 break;
187 case 'a':
188 if (strcasecmp(optarg, "MD5") == 0)
189 md = EVP_md5();
190 else if (strcasecmp(optarg, "SHA") == 0)
191 md = EVP_sha1();
192 else if (strcasecmp(optarg, "SHA-224") == 0)
193 md = EVP_sha224();
194 else if (strcasecmp(optarg, "SHA-256") == 0)
195 md = EVP_sha256();
196 else if (strcasecmp(optarg, "SHA-384") == 0)
197 md = EVP_sha384();
198 else if (strcasecmp(optarg, "SHA-512") == 0)
199 md = EVP_sha512();
200 else
201 errx(1, "Invalid authentication protocol "
202 "specified after -a flag: %s", optarg);
203 break;
204 case 'c':
205 community = optarg;
206 break;
207 case 'E':
208 ctxengineid = snmpc_hex2bin(optarg,
20
Calling 'snmpc_hex2bin'
30
Returned allocated memory
209 &ctxengineidlen);
210 if (ctxengineid
30.1
'ctxengineid' is not equal to NULL
== NULL((void *)0)) {
31
Taking false branch
211 if (errno(*__errno()) == EINVAL22)
212 errx(1, "Bad engine ID value "
213 "after -3E flag.");
214 err(1, "-3E");
215 }
216 break;
32
Execution continues on line 180
217 case 'e':
218 secengineid = snmpc_hex2bin(optarg,
219 &secengineidlen);
220 if (secengineid == NULL((void *)0)) {
221 if (errno(*__errno()) == EINVAL22)
222 errx(1, "Bad engine ID value "
223 "after -3e flag.");
224 err(1, "-3e");
225 }
226 break;
227 case 'K':
228 privkey = snmpc_hex2bin(optarg, &privkeylen);
229 if (privkey == NULL((void *)0)) {
230 if (errno(*__errno()) == EINVAL22)
231 errx(1, "Bad key value after "
232 "-3K flag.");
233 errx(1, "-3K");
234 }
235 privkeylevel = USM_KEY_LOCALIZED;
236 break;
237 case 'k':
238 authkey = snmpc_hex2bin(optarg, &authkeylen);
239 if (authkey == NULL((void *)0)) {
240 if (errno(*__errno()) == EINVAL22)
241 errx(1, "Bad key value after -k flag.");
242 err(1, "-k");
243 }
244 authkeylevel = USM_KEY_LOCALIZED;
245 break;
246 case 'l':
247 if (strcasecmp(optarg, "noAuthNoPriv") == 0)
248 seclevel = SNMP_MSGFLAG_REPORT0x04;
249 else if (strcasecmp(optarg, "authNoPriv") == 0)
250 seclevel = SNMP_MSGFLAG_AUTH0x01 |
251 SNMP_MSGFLAG_REPORT0x04;
252 else if (strcasecmp(optarg, "authPriv") == 0)
253 seclevel = SNMP_MSGFLAG_AUTH0x01 |
254 SNMP_MSGFLAG_PRIV0x02 | SNMP_MSGFLAG_REPORT0x04;
255 else
256 errx(1, "Invalid security level specified "
257 "after -l flag: %s", optarg);
258 break;
259 case 'n':
260 ctxname = optarg;
261 break;
262 case 'r':
263 if ((retries = strtonum(optarg, 0, INT_MAX0x7fffffff,
264 &errstr)) == 0) {
265 if (errstr != NULL((void *)0))
266 errx(1, "-r: %s argument", errstr);
267 }
268 break;
269 case 't':
270 if ((timeout = strtonum(optarg, 1, INT_MAX0x7fffffff,
271 &errstr)) == 0) {
272 if (errstr != NULL((void *)0))
273 errx(1, "-t: %s argument", errstr);
274 }
275 break;
276 case 'u':
277 user = optarg;
278 break;
279 case 'v':
280 if (strcmp(optarg, "1") == 0)
281 version = SNMP_V1;
282 else if (strcmp(optarg, "2c") == 0)
283 version = SNMP_V2C;
284 else if (strcmp(optarg, "3") == 0)
285 version = SNMP_V3;
286 else
287 errc(1, EINVAL22, "-v");
288 break;
289 case 'C':
290 for (i = 0; i < strlen(optarg); i++) {
291 switch (optarg[i]) {
292 case 'c':
293 if (strcmp(snmp_app->name, "walk") &&
294 strcmp(snmp_app->name, "bulkwalk"))
295 usage();
296 walk_check_increase = 0;
297 break;
298 case 'h':
299 if (strcmp(snmp_app->name, "df"))
300 usage();
301 print_human = 1;
302 break;
303 case 'i':
304 if (strcmp(snmp_app->name, "walk") &&
305 strcmp(snmp_app->name, "bulkwalk"))
306 usage();
307 walk_include_oid = 1;
308 break;
309 case 'n':
310 if (strcmp(snmp_app->name, "bulkget") &&
311 strcmp(snmp_app->name, "bulkwalk"))
312 usage();
313 errno(*__errno()) = 0;
314 non_repeaters = strtol(&optarg[i + 1],
315 &strtolp, 10);
316 if (non_repeaters < 0 ||
317 errno(*__errno()) == ERANGE34) {
318 if (non_repeaters < 0)
319 errx(1, "%s%s",
320 "-Cn: too small ",
321 "argument");
322 else
323 errx(1, "%s%s",
324 "-Cn: too large",
325 "argument");
326 } else if (&optarg[i + 1] == strtolp)
327 errx(1, "-Cn invalid argument");
328 i = strtolp - optarg - 1;
329 break;
330 case 'p':
331 if (strcmp(snmp_app->name, "walk") &&
332 strcmp(snmp_app->name, "bulkwalk"))
333 usage();
334 print_summary = 1;
335 break;
336 case 'r':
337 if (strcmp(snmp_app->name, "bulkget") &&
338 strcmp(snmp_app->name, "bulkwalk") &&
339 strcmp(snmp_app->name, "df"))
340 usage();
341 errno(*__errno()) = 0;
342 max_repetitions = strtol(&optarg[i + 1],
343 &strtolp, 10);
344 if (max_repetitions < 0 ||
345 errno(*__errno()) == ERANGE34) {
346 if (max_repetitions < 0)
347 errx(1, "%s%s",
348 "-Cr: too small ",
349 "argument");
350 else
351 errx(1, "%s%s",
352 "-Cr: too large",
353 "argument");
354 } else if (&optarg[i + 1] == strtolp)
355 errx(1, "-Cr invalid argument");
356 i = strtolp - optarg - 1;
357 break;
358 case 's':
359 if (strcmp(snmp_app->name, "walk") &&
360 strcmp(snmp_app->name, "bulkwalk"))
361 usage();
362 if ((walk_skip = recallocarray(
363 walk_skip, walk_skip_len,
364 walk_skip_len + 1,
365 sizeof(*walk_skip))) == NULL((void *)0))
366 errx(1, "malloc");
367 if (smi_string2oid(argv[optind],
368 &(walk_skip[walk_skip_len])) != 0)
369 errx(1, "%s: %s",
370 "Unknown Object Identifier",
371 argv[optind]);
372 walk_skip_len++;
373 optind++;
374 break;
375 case 't':
376 if (strcmp(snmp_app->name, "walk"))
377 usage();
378 print_time = 1;
379 break;
380 case 'E':
381 if (strcmp(snmp_app->name, "walk"))
382 usage();
383 if (smi_string2oid(argv[optind],
384 &walk_end) != 0)
385 errx(1, "%s: %s",
386 "Unknown Object Identifier",
387 argv[optind]);
388 optind++;
389 continue;
390 case 'I':
391 if (strcmp(snmp_app->name, "walk"))
392 usage();
393 walk_fallback_oid = 0;
394 break;
395 default:
396 usage();
397 }
398 if (optarg[i] == 'E')
399 break;
400 }
401 break;
402 case 'O':
403 for (i = 0; i < strlen(optarg); i++) {
404 if (strcmp(snmp_app->name, "mibtree") == 0 &&
405 optarg[i] != 'f' && optarg[i] != 'n' &&
406 optarg[i] != 'S')
407 usage();
408 switch (optarg[i]) {
409 case 'a':
410 output_string = smi_os_ascii;
411 break;
412 case 'f':
413 oid_lookup = smi_oidl_full;
414 break;
415 case 'n':
416 oid_lookup = smi_oidl_numeric;
417 break;
418 case 'q':
419 print_equals = 0;
420 smi_print_hint = 0;
421 break;
422 case 'v':
423 print_varbind_only = 1;
424 break;
425 case 'x':
426 output_string = smi_os_hex;
427 break;
428 case 'S':
429 oid_lookup = smi_oidl_short;
430 break;
431 case 'Q':
432 smi_print_hint = 0;
433 break;
434 default:
435 usage();
436 }
437 }
438 break;
439 case 'X':
440 privkey = optarg;
441 privkeylen = strlen(privkey);
442 privkeylevel = USM_KEY_PASSWORD;
443 break;
444 case 'x':
445 if (strcasecmp(optarg, "DES") == 0)
446 cipher = EVP_des_cbc();
447 else if (strcasecmp(optarg, "AES") == 0)
448 cipher = EVP_aes_128_cfb128();
449 else
450 errx(1, "Invalid privacy protocol "
451 "specified after -3x flag: %s",
452 optarg);
453 break;
454 case 'Z':
455 boots = strtoll(optarg, &strtolp, 10);
456 if (boots < 0 || strtolp == optarg || strtolp[0] != ',')
457 usage();
458 strtolp++;
459 time = strtoll(strtolp, &strtolp, 10);
460 if (boots < 0 || strtolp == optarg)
461 usage();
462 zflag = 1;
463 break;
464 default:
465 usage();
466 }
467 }
468 argc -= optind;
469 argv += optind;
470
471 if (version == SNMP_V1 || version == SNMP_V2C) {
35
Assuming 'version' is equal to SNMP_V1
472 if (community == NULL((void *)0) || community[0] == '\0')
36
Potential leak of memory pointed to by 'ctxengineid'
473 errx(1, "No community name specified.");
474 } else if (version == SNMP_V3) {
475 /* Setup USM */
476 if (user == NULL((void *)0) || user[0] == '\0')
477 errx(1, "No securityName specified");
478 if ((sec = usm_init(user, strlen(user))) == NULL((void *)0))
479 err(1, "usm_init");
480 if (seclevel & SNMP_MSGFLAG_AUTH0x01) {
481 if (md == NULL((void *)0))
482 md = EVP_sha1();
483 if (authkey == NULL((void *)0))
484 errx(1, "No authKey or authPassword specified");
485 if (usm_setauth(sec, md, authkey, authkeylen,
486 authkeylevel) == -1)
487 err(1, "Can't set authkey");
488 }
489 if (seclevel & SNMP_MSGFLAG_PRIV0x02) {
490 if (cipher == NULL((void *)0))
491 cipher = EVP_aes_128_cfb128();
492 if (privkey == NULL((void *)0))
493 errx(1, "No privKey or privPassword specified");
494 if (usm_setpriv(sec, cipher, privkey, privkeylen,
495 privkeylevel) == -1)
496 err(1, "Can't set authkey");
497 }
498 if (secengineid != NULL((void *)0)) {
499 if (usm_setengineid(sec, secengineid,
500 secengineidlen) == -1)
501 err(1, "Can't set secengineid");
502 }
503 if (zflag)
504 if (usm_setbootstime(sec, boots, time) == -1)
505 err(1, "Can't set boots/time");
506 v3 = snmp_v3_init(seclevel, ctxname, ctxname == NULL((void *)0) ? 0 :
507 strlen(ctxname), sec);
508 if (v3 == NULL((void *)0))
509 err(1, "snmp_v3_init");
510 if (ctxengineid != NULL((void *)0)) {
511 if (snmp_v3_setengineid(v3, ctxengineid,
512 ctxengineidlen) == -1)
513 err(1, "Can't set ctxengineid");
514 }
515 }
516
517
518 return snmp_app->exec(argc, argv);
519}
520
521int
522snmpc_get(int argc, char *argv[])
523{
524 struct ber_oid *oid;
525 struct ber_element *pdu, *varbind;
526 struct snmp_agent *agent;
527 int errorstatus, errorindex;
528 int i;
529 int class;
530 unsigned type;
531 char *hint = NULL((void *)0);
532
533 if (argc < 2)
534 usage();
535
536 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
537 err(1, "%s", snmp_app->name);
538 agent->timeout = timeout;
539 agent->retries = retries;
540
541 if (pledge("stdio", NULL((void *)0)) == -1)
542 err(1, "pledge");
543 argc--;
544 argv++;
545
546 oid = reallocarray(NULL((void *)0), argc, sizeof(*oid));
547 if (oid == NULL((void *)0))
548 err(1, "malloc");
549 for (i = 0; i < argc; i++) {
550 if (smi_string2oid(argv[i], &oid[i]) == -1)
551 errx(1, "%s: Unknown object identifier", argv[i]);
552 }
553 if (strcmp(snmp_app->name, "getnext") == 0) {
554 if ((pdu = snmp_getnext(agent, oid, argc)) == NULL((void *)0))
555 err(1, "getnext");
556 } else if (strcmp(snmp_app->name, "bulkget") == 0) {
557 if (version < SNMP_V2C)
558 errx(1, "Cannot send V2 PDU on V1 session");
559 if (non_repeaters > argc)
560 errx(1, "need more objects than -Cn<num>");
561 if ((pdu = snmp_getbulk(agent, oid, argc, non_repeaters,
562 max_repetitions)) == NULL((void *)0))
563 err(1, "bulkget");
564 } else {
565 if ((pdu = snmp_get(agent, oid, argc)) == NULL((void *)0))
566 err(1, "get");
567 }
568
569 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
570 &errorindex, &varbind);
571 if (errorstatus != 0) {
572 if (errorindex >= 1 && errorindex <= argc)
573 hint = argv[errorindex - 1];
574 snmpc_printerror((enum snmp_error) errorstatus, varbind,
575 errorindex, hint);
576 }
577
578 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
579 printf("Received report:\n");
580 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
581 if (!snmpc_print(varbind))
582 err(1, "Can't print response");
583 }
584 ober_free_elements(pdu);
585 snmp_free_agent(agent);
586 return 0;
587}
588
589int
590snmpc_walk(int argc, char *argv[])
591{
592 struct ber_oid oid, loid, noid;
593 struct ber_element *pdu, *varbind, *value;
594 struct timespec start, finish;
595 struct snmp_agent *agent;
596 const char *oids;
597 int n = 0, prev_cmp, skip_cmp;
598 int errorstatus, errorindex;
599 int class;
600 size_t i;
601 unsigned type;
602
603 if (strcmp(snmp_app->name, "bulkwalk") == 0 && version < SNMP_V2C)
604 errx(1, "Cannot send V2 PDU on V1 session");
605 if (argc < 1 || argc > 2)
606 usage();
607 oids = argc == 1 ? mib : argv[1];
608
609 if ((agent = snmpc_connect(argv[0], "161"))== NULL((void *)0))
610 err(1, "%s", snmp_app->name);
611 agent->timeout = timeout;
612 agent->retries = retries;
613 if (pledge("stdio", NULL((void *)0)) == -1)
614 err(1, "pledge");
615
616 if (smi_string2oid(oids, &oid) == -1)
617 errx(1, "%s: Unknown object identifier", oids);
618 bcopy(&oid, &noid, sizeof(noid));
619 if (print_time)
620 clock_gettime(CLOCK_MONOTONIC3, &start);
621
622 if (walk_include_oid) {
623 if ((pdu = snmp_get(agent, &oid, 1)) == NULL((void *)0))
624 err(1, "%s", snmp_app->name);
625
626 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
627 &errorstatus, &errorindex, &varbind);
628 if (errorstatus != 0)
629 snmpc_printerror((enum snmp_error) errorstatus, varbind,
630 errorindex, oids);
631
632 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
633 printf("Received report:\n");
634 if (!snmpc_print(varbind))
635 err(1, "Can't print response");
636 ober_free_element(pdu);
637 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
638 return 1;
639 n++;
640 }
641 while (1) {
642 for (i = 0; i < walk_skip_len; i++) {
643 skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
644 if (skip_cmp == 0 || skip_cmp == 2) {
645 bcopy(&(walk_skip[i]), &noid, sizeof(noid));
646 noid.bo_id[noid.bo_n -1]++;
647 break;
648 }
649 }
650 bcopy(&noid, &loid, sizeof(loid));
651 if (strcmp(snmp_app->name, "bulkwalk") == 0) {
652 if ((pdu = snmp_getbulk(agent, &noid, 1,
653 non_repeaters, max_repetitions)) == NULL((void *)0))
654 err(1, "bulkwalk");
655 } else {
656 if ((pdu = snmp_getnext(agent, &noid, 1)) == NULL((void *)0))
657 err(1, "walk");
658 }
659
660 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
661 &errorstatus, &errorindex, &varbind);
662 if (errorstatus != 0) {
663 snmpc_printerror((enum snmp_error) errorstatus, varbind,
664 errorindex, NULL((void *)0));
665 }
666
667 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
668 printf("Received report:\n");
669 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
670 (void) ober_scanf_elements(varbind, "{oe}", &noid,
671 &value);
672 if (value->be_class == BER_CLASS_CONTEXT0x2 &&
673 value->be_type == BER_TYPE_EOC0)
674 break;
675 for (i = 0; i < walk_skip_len; i++) {
676 skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
677 if (skip_cmp == 0 || skip_cmp == 2)
678 break;
679 }
680 if (i < walk_skip_len)
681 continue;
682 prev_cmp = ober_oid_cmp(&noid, &loid);
683 if (walk_check_increase && prev_cmp == -1)
684 errx(1, "OID not increasing");
685 if (prev_cmp == 0 || ober_oid_cmp(&noid, &oid) != 2)
686 break;
687 if (walk_end.bo_n != 0 &&
688 ober_oid_cmp(&noid, &walk_end) != -1)
689 break;
690
691 if (!snmpc_print(varbind))
692 err(1, "Can't print response");
693 n++;
694 }
695 ober_free_elements(pdu);
696 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
697 return 1;
698 if (varbind != NULL((void *)0))
699 break;
700 }
701 if (walk_fallback_oid && n == 0) {
702 if ((pdu = snmp_get(agent, &oid, 1)) == NULL((void *)0))
703 err(1, "%s", snmp_app->name);
704
705 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
706 &errorstatus, &errorindex, &varbind);
707 if (errorstatus != 0)
708 snmpc_printerror((enum snmp_error) errorstatus, varbind,
709 errorindex, oids);
710
711 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
712 printf("Received report:\n");
713 if (!snmpc_print(varbind))
714 err(1, "Can't print response");
715 ober_free_element(pdu);
716 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
717 return 1;
718 n++;
719 }
720 if (print_time)
721 clock_gettime(CLOCK_MONOTONIC3, &finish);
722 if (print_summary)
723 printf("Variables found: %d\n", n);
724 if (print_time) {
725 if ((finish.tv_nsec -= start.tv_nsec) < 0) {
726 finish.tv_sec -= 1;
727 finish.tv_nsec += 1000000000;
728 }
729 finish.tv_sec -= start.tv_sec;
730 fprintf(stderr(&__sF[2]), "Total traversal time: %lld.%09ld seconds\n",
731 finish.tv_sec, finish.tv_nsec);
732 }
733 snmp_free_agent(agent);
734 return 0;
735}
736
737int
738snmpc_set(int argc, char *argv[])
739{
740 struct snmp_agent *agent;
741 struct ber_element *pdu, *varbind;
742 int errorstatus, errorindex;
743 int class;
744 unsigned type;
745 char *hint = NULL((void *)0);
746
747 if (argc < 4)
748 usage();
749 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
750 err(1, "%s", snmp_app->name);
751 argc--;
752 argv++;
753
754 if (pledge("stdio", NULL((void *)0)) == -1)
755 err(1, "pledge");
756
757 if ((pdu = snmp_set(agent, snmpc_varbindparse(argc, argv))) == NULL((void *)0))
758 err(1, "set");
759
760 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
761 &errorindex, &varbind);
762 if (errorstatus != 0) {
763 if (errorindex >= 1 && errorindex <= argc / 3)
764 hint = argv[(errorindex - 1) * 3];
765 snmpc_printerror((enum snmp_error) errorstatus, varbind,
766 errorindex, hint);
767 }
768
769 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
770 printf("Received report:\n");
771 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
772 if (!snmpc_print(varbind))
773 err(1, "Can't print response");
774 }
775 ober_free_elements(pdu);
776 snmp_free_agent(agent);
777 return 0;
778}
779
780int
781snmpc_trap(int argc, char *argv[])
782{
783 struct snmp_agent *agent;
784 struct timespec ts;
785 struct ber_oid trapoid;
786 const char *errstr = NULL((void *)0);
787 long long lval;
788
789 if (version == SNMP_V1)
790 errx(1, "trap is not supported for snmp v1");
791
792 if (argc < 3)
793 usage();
794
795 if ((agent = snmpc_connect(argv[0], "162")) == NULL((void *)0))
796 err(1, "%s", snmp_app->name);
797
798 if (pledge("stdio", NULL((void *)0)) == -1)
799 err(1, "pledge");
800
801 if (argv[1][0] == '\0') {
802 if (clock_gettime(CLOCK_UPTIME5, &ts) == -1)
803 err(1, "clock_gettime");
804 } else {
805 lval = strtonum(argv[1], 0, UINT32_MAX0xffffffffU, &errstr);
806 if (errstr != NULL((void *)0))
807 errx(1, "Bad value notation (%s)", argv[1]);
808 ts.tv_sec = lval / 100;
809 ts.tv_nsec = (lval % 100) * 10000000;
810 }
811 if (smi_string2oid(argv[2], &trapoid) == -1)
812 errx(1, "Invalid oid: %s\n", argv[2]);
813
814 argc -= 3;
815 argv += 3;
816
817 snmp_trap(agent, &ts, &trapoid, snmpc_varbindparse(argc, argv));
818
819 return 0;
820}
821
822#define INCR_NEXTTAB(x)((x + 8) & ~7) ((x + 8) & ~7)
823#define NEXTTAB(x)(8 - (x & 7)) (8 - (x & 7))
824int
825snmpc_df(int argc, char *argv[])
826{
827 struct snmpc_df {
828 uint32_t index;
829 char *descr;
830 int descrwidth;
831 /* Theoretical maximum for 2 32 bit values multiplied */
832 char size[21];
833 char used[21];
834 char avail[21];
835 char proc[5];
836 } *df = NULL((void *)0);
837 struct ber_oid descroid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 3 }, 11};
838 struct ber_oid unitsoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 4 }, 11};
839 struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11};
840 struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11};
841 struct ber_oid oid, *reqoid;
842 char oids[SNMP_MAX_OID_STRLEN128];
843 struct ber_element *pdu, *varbind, *elm;
844 struct snmp_agent *agent;
845 int errorstatus, errorindex;
846 int class;
847 size_t i, j, rows = 0;
848 unsigned type;
849 char *string;
850 int descrlen = 0, sizelen = 0, usedlen = 0, availlen = 0, proclen = 0;
851 int len;
852 long long units, size, used;
853 int fmtret;
854
855 if (argc != 1)
856 usage();
857
858 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
859 err(1, "%s", snmp_app->name);
860 agent->timeout = timeout;
861 agent->retries = retries;
862
863 if (pledge("stdio", NULL((void *)0)) == -1)
864 err(1, "pledge");
865
866 descrlen = sizeof("Description") - 1;
867 sizelen = sizeof("Size") - 1;
868 usedlen = sizeof("Used") - 1;
869 availlen = sizeof("Available") - 1;
870 proclen = sizeof("Used%") - 1;
871
872 bcopy(&descroid, &oid, sizeof(descroid));
873
874 i = 0;
875 while(1) {
876 if (version < SNMP_V2C) {
877 if ((pdu = snmp_getnext(agent, &oid, 1)) == NULL((void *)0))
878 err(1, "df");
879 } else {
880 if ((pdu = snmp_getbulk(agent, &oid, 1, 0,
881 max_repetitions)) == NULL((void *)0))
882 err(1, "df");
883 }
884
885 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
886 &errorstatus, &errorindex, &varbind);
887 if (errorstatus != 0)
888 snmpc_printerror((enum snmp_error) errorstatus, varbind,
889 errorindex, NULL((void *)0));
890
891 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT) {
892 printf("Received report:\n");
893 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
894 if (!snmpc_print(varbind))
895 err(1, "Can't print response");
896 }
897 return 1;
898 }
899 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
900 if (ober_scanf_elements(varbind, "{os", &oid,
901 &string) == -1 ||
902 ober_oid_cmp(&oid, &descroid) != 2)
903 break;
904 rows++;
905 }
906 if ((df = reallocarray(df, rows, sizeof(*df))) == NULL((void *)0))
907 err(1, "malloc");
908 (void) ober_scanf_elements(pdu, "{SSS{e", &varbind);
909 for (; i < rows; varbind = varbind->be_next, i++) {
910 if (ober_scanf_elements(varbind, "{oe", &oid,
911 &elm) == -1) {
912 i--;
913 rows--;
914 continue;
915 }
916 if (ober_oid_cmp(&oid, &descroid) != 2)
917 break;
918 df[i].index = oid.bo_id[oid.bo_n - 1];
919 if ((df[i].descr = smi_print_element(&oid, elm, 0,
920 smi_os_ascii, 0, utf8)) == NULL((void *)0)) {
921 smi_oid2string(&oid, oids, sizeof(oids),
922 oid_lookup);
923 warn("df: can't print oid %s", oids);
924 i--;
925 rows--;
926 continue;
927 }
928 if ((df[i].descrwidth =
929 (int) snmpc_mbswidth(df[i].descr)) == -1)
930 err(1, "df: invalid hrStorageDescr");
931 if (df[i].descrwidth > descrlen)
932 descrlen = df[i].descrwidth;
933 }
934 ober_free_elements(pdu);
935 if (varbind != NULL((void *)0))
936 break;
937 }
938
939 if (max_repetitions < 3)
940 max_repetitions = 3;
941 if ((reqoid = reallocarray(NULL((void *)0), max_repetitions, sizeof(*reqoid))) == NULL((void *)0))
942 err(1, "malloc");
943 for (i = 0; i < rows;) {
944 for (j = 0; i + j < rows && j < (size_t)max_repetitions / 3;
945 j++) {
946 bcopy(&unitsoid, &(reqoid[(j * 3) + 0]),
947 sizeof(unitsoid));
948 reqoid[(j * 3) + 0].bo_id[
949 reqoid[(j * 3) + 0].bo_n++] = df[i + j].index;
950 bcopy(&sizeoid, &(reqoid[(j * 3) + 1]),
951 sizeof(sizeoid));
952 reqoid[(j * 3) + 1].bo_id[
953 reqoid[(j * 3) + 1].bo_n++] = df[i + j].index;
954 bcopy(&usedoid, &(reqoid[(j * 3) + 2]),
955 sizeof(usedoid));
956 reqoid[(j * 3) + 2].bo_id[
957 reqoid[(j * 3) + 2].bo_n++] = df[i + j].index;
958 }
959 if ((pdu = snmp_get(agent, reqoid, j * 3)) == NULL((void *)0))
960 err(1, "df");
961 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
962 &errorstatus, &errorindex, &varbind);
963 if (errorstatus != 0)
964 snmpc_printerror((enum snmp_error) errorstatus, varbind,
965 errorindex, NULL((void *)0));
966 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT) {
967 printf("Received report:\n");
968 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
969 if (!snmpc_print(varbind))
970 err(1, "Can't print response");
971 }
972 }
973 for (j = 0; varbind != NULL((void *)0); i++) {
974 if (ober_scanf_elements(varbind, "{oi}{oi}{oi}",
975 &(reqoid[0]), &units, &(reqoid[1]), &size,
976 &(reqoid[2]), &used, &varbind) == -1) {
977 break;
978 }
979 varbind = varbind->be_next->be_next->be_next;
980
981 unitsoid.bo_id[unitsoid.bo_n++] = df[i].index;
982 if (ober_oid_cmp(&unitsoid, &(reqoid[0])) != 0) {
983 warnx("df: received invalid object");
984 break;
985 }
986 unitsoid.bo_n--;
987 sizeoid.bo_id[sizeoid.bo_n++] = df[i].index;
988 if (ober_oid_cmp(&sizeoid, &(reqoid[1])) != 0) {
989 warnx("df: received invalid object");
990 break;
991 }
992 sizeoid.bo_n--;
993 usedoid.bo_id[usedoid.bo_n++] = df[i].index;
994 if (ober_oid_cmp(&usedoid, &(reqoid[2])) != 0) {
995 warnx("df: received invalid object");
996 break;
997 }
998 usedoid.bo_n--;
999 if (print_human)
1000 fmtret = fmt_scaled((units * size), df[i].size);
1001 if (!print_human || fmtret == -1)
1002 snprintf(df[i].size, sizeof(df[i].size), "%lld",
1003 (units * size) / 1024);
1004 len = (int) strlen(df[i].size);
1005 if (len > sizelen)
1006 sizelen = len;
1007 if (print_human)
1008 fmtret = fmt_scaled(units * used, df[i].used);
1009 if (!print_human || fmtret == -1)
1010 snprintf(df[i].used, sizeof(df[i].used), "%lld",
1011 (units * used) / 1024);
1012 len = (int) strlen(df[i].used);
1013 if (len > usedlen)
1014 usedlen = len;
1015 if (print_human)
1016 fmtret = fmt_scaled(units * (size - used),
1017 df[i].avail);
1018 if (!print_human || fmtret == -1)
1019 snprintf(df[i].avail, sizeof(df[i].avail),
1020 "%lld", (units * (size - used)) / 1024);
1021 len = (int) strlen(df[i].avail);
1022 if (len > availlen)
1023 availlen = len;
1024 if (size == 0)
1025 strlcpy(df[i].proc, "0%", sizeof(df[i].proc));
1026 else {
1027 snprintf(df[i].proc, sizeof(df[i].proc),
1028 "%lld%%", (used * 100) / size);
1029 }
1030 len = (int) strlen(df[i].proc);
1031 if (len > proclen)
1032 proclen = len;
1033 j++;
1034 }
1035 if (j == 0) {
1036 warnx("Failed to retrieve information for %s",
1037 df[i].descr);
1038 memmove(df + i, df + i + 1,
1039 (rows - i - 1) * sizeof(*df));
1040 rows--;
1041 i--;
1042 }
1043 }
1044
1045 printf("%-*s%*s%*s%*s%*s\n",
1046 descrlen, "Description",
1047 NEXTTAB(descrlen)(8 - (descrlen & 7)) + sizelen, "Size",
1048 NEXTTAB(sizelen)(8 - (sizelen & 7)) + usedlen, "Used",
1049 NEXTTAB(usedlen)(8 - (usedlen & 7)) + availlen, "Available",
1050 NEXTTAB(availlen)(8 - (availlen & 7)) + proclen, "Used%");
1051 for (i = 0; i < rows; i++) {
1052 printf("%s%*s%*s%*s%*s%*s\n",
1053 df[i].descr, descrlen - df[i].descrwidth, "",
1054 NEXTTAB(descrlen)(8 - (descrlen & 7)) + sizelen, df[i].size,
1055 NEXTTAB(sizelen)(8 - (sizelen & 7)) + usedlen, df[i].used,
1056 NEXTTAB(usedlen)(8 - (usedlen & 7)) + availlen, df[i].avail,
1057 NEXTTAB(availlen)(8 - (availlen & 7)) + proclen, df[i].proc);
1058 }
1059
1060 return 0;
1061}
1062
1063int
1064snmpc_mibtree(int argc, char *argv[])
1065{
1066 struct oid *oid;
1067 struct ber_oid soid;
1068 char buf[BUFSIZ1024];
1069 int i;
1070
1071 if (argc == 0) {
1072 for (oid = NULL((void *)0); (oid = smi_foreach(oid)) != NULL((void *)0);) {
1073 smi_oid2string(&oid->o_id, buf, sizeof(buf),
1074 oid_lookup);
1075 printf("%s\n", buf);
1076 }
1077 } else {
1078 for (i = 0; i < argc; i++) {
1079 if (smi_string2oid(argv[i], &soid) == -1) {
1080 warnx("%s: Unknown object identifier", argv[i]);
1081 continue;
1082 }
1083 smi_oid2string(&soid, buf, sizeof(buf), oid_lookup);
1084 printf("%s\n", buf);
1085 }
1086 }
1087 return 0;
1088}
1089
1090struct snmp_agent *
1091snmpc_connect(char *host, char *port)
1092{
1093 switch (version) {
1094 case SNMP_V1:
1095 case SNMP_V2C:
1096 return snmp_connect_v12(snmpc_parseagent(host, port), version,
1097 community);
1098 case SNMP_V3:
1099 return snmp_connect_v3(snmpc_parseagent(host, port), v3);
1100 }
1101 return NULL((void *)0);
1102}
1103
1104int
1105snmpc_print(struct ber_element *elm)
1106{
1107 struct ber_oid oid;
1108 char oids[SNMP_MAX_OID_STRLEN128];
1109 char *value;
1110
1111 elm = elm->be_subbe_union.bv_sub;
1112 if (ober_get_oid(elm, &oid) != 0) {
1113 errno(*__errno()) = EINVAL22;
1114 return 0;
1115 }
1116
1117 elm = elm->be_next;
1118 value = smi_print_element(&oid, elm, smi_print_hint, output_string,
1119 oid_lookup, utf8);
1120 if (value == NULL((void *)0))
1121 return 0;
1122
1123 if (print_varbind_only)
1124 printf("%s\n", value);
1125 else if (print_equals) {
1126 smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1127 printf("%s = %s\n", oids, value);
1128 } else {
1129 smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1130 printf("%s %s\n", oids, value);
1131 }
1132 free(value);
1133
1134 return 1;
1135}
1136
1137__dead__attribute__((__noreturn__)) void
1138snmpc_printerror(enum snmp_error error, struct ber_element *varbind,
1139 int index, const char *hint)
1140{
1141 struct ber_oid hoid, vboid;
1142 char oids[SNMP_MAX_OID_STRLEN128];
1143 const char *oid = NULL((void *)0);
1144 int i;
1145
1146 if (index >= 1) {
1147 /* Only print if the index is in the reply */
1148 for (i = 1; varbind != NULL((void *)0) && i < index;
1149 varbind = varbind->be_next)
1150 i++;
1151 if (varbind != NULL((void *)0) &&
1152 ober_get_oid(varbind->be_subbe_union.bv_sub, &vboid) == 0) {
1153 /* If user and reply conform print user input */
1154 if (hint != NULL((void *)0) &&
1155 smi_string2oid(hint, &hoid) == 0 &&
1156 ober_oid_cmp(&hoid, &vboid) == 0)
1157 oid = hint;
1158 else
1159 oid = smi_oid2string(&vboid, oids,
1160 sizeof(oids), oid_lookup);
1161 }
1162 }
1163 if (oid == NULL((void *)0))
1164 oid = "?";
1165
1166 switch (error) {
1167 case SNMP_ERROR_NONE:
1168 errx(1, "No error, how did I get here?");
1169 case SNMP_ERROR_TOOBIG:
1170 errx(1, "Can't parse oid %s: Response too big", oid);
1171 case SNMP_ERROR_NOSUCHNAME:
1172 errx(1, "Can't parse oid %s: No such object", oid);
1173 case SNMP_ERROR_BADVALUE:
1174 errx(1, "Can't parse oid %s: Bad value", oid);
1175 case SNMP_ERROR_READONLY:
1176 errx(1, "Can't parse oid %s: Read only", oid);
1177 case SNMP_ERROR_GENERR:
1178 errx(1, "Can't parse oid %s: Generic error", oid);
1179 case SNMP_ERROR_NOACCESS:
1180 errx(1, "Can't parse oid %s: Access denied", oid);
1181 case SNMP_ERROR_WRONGTYPE:
1182 errx(1, "Can't parse oid %s: Wrong type", oid);
1183 case SNMP_ERROR_WRONGLENGTH:
1184 errx(1, "Can't parse oid %s: Wrong length", oid);
1185 case SNMP_ERROR_WRONGENC:
1186 errx(1, "Can't parse oid %s: Wrong encoding", oid);
1187 case SNMP_ERROR_WRONGVALUE:
1188 errx(1, "Can't parse oid %s: Wrong value", oid);
1189 case SNMP_ERROR_NOCREATION:
1190 errx(1, "Can't parse oid %s: Can't be created", oid);
1191 case SNMP_ERROR_INCONVALUE:
1192 errx(1, "Can't parse oid %s: Inconsistent value", oid);
1193 case SNMP_ERROR_RESUNAVAIL:
1194 errx(1, "Can't parse oid %s: Resource unavailable", oid);
1195 case SNMP_ERROR_COMMITFAILED:
1196 errx(1, "Can't parse oid %s: Commit failed", oid);
1197 case SNMP_ERROR_UNDOFAILED:
1198 errx(1, "Can't parse oid %s: Undo faild", oid);
1199 case SNMP_ERROR_AUTHERROR:
1200 errx(1, "Can't parse oid %s: Authorization error", oid);
1201 case SNMP_ERROR_NOTWRITABLE:
1202 errx(1, "Can't parse oid %s: Not writable", oid);
1203 case SNMP_ERROR_INCONNAME:
1204 errx(1, "Can't parse oid %s: Inconsistent name", oid);
1205 }
1206 errx(1, "Can't parse oid %s: Unknown error (%d)", oid, error);
1207}
1208
1209int
1210snmpc_parseagent(char *agent, char *defaultport)
1211{
1212 struct addrinfo hints, *ai, *ai0 = NULL((void *)0);
1213 struct sockaddr_un saddr;
1214 char *agentdup, *specifier, *hostname, *port = NULL((void *)0);
1215 int error;
1216 int s;
1217
1218 if ((agentdup = specifier = strdup(agent)) == NULL((void *)0))
1219 err(1, NULL((void *)0));
1220
1221 bzero(&hints, sizeof(hints));
1222 if ((hostname = strchr(specifier, ':')) != NULL((void *)0)) {
1223 *hostname++ = '\0';
1224 if (strcasecmp(specifier, "udp") == 0) {
1225 hints.ai_family = AF_INET2;
1226 hints.ai_socktype = SOCK_DGRAM2;
1227 } else if (strcasecmp(specifier, "tcp") == 0) {
1228 hints.ai_family = AF_INET2;
1229 hints.ai_socktype = SOCK_STREAM1;
1230 } else if (strcasecmp(specifier, "udp6") == 0 ||
1231 strcasecmp(specifier, "udpv6") == 0 ||
1232 strcasecmp(specifier, "udpipv6") == 0) {
1233 hints.ai_family = AF_INET624;
1234 hints.ai_socktype = SOCK_DGRAM2;
1235 } else if (strcasecmp(specifier, "tcp6") == 0 ||
1236 strcasecmp(specifier, "tcpv6") == 0 ||
1237 strcasecmp(specifier, "tcpipv6") == 0) {
1238 hints.ai_family = AF_INET624;
1239 hints.ai_socktype = SOCK_STREAM1;
1240 } else if (strcasecmp(specifier, "unix") == 0) {
1241 hints.ai_family = AF_UNIX1;
1242 hints.ai_addr = (struct sockaddr *)&saddr;
1243 hints.ai_addrlen = sizeof(saddr);
1244 saddr.sun_len = sizeof(saddr);
1245 saddr.sun_family = AF_UNIX1;
1246 if (strlcpy(saddr.sun_path, hostname,
1247 sizeof(saddr.sun_path)) > sizeof(saddr.sun_path))
1248 errx(1, "Hostname path too long");
1249 ai = &hints;
1250 } else {
1251 *--hostname = ':';
1252 hostname = specifier;
1253 }
1254 } else {
1255 hostname = specifier;
1256 }
1257
1258 if (hints.ai_family == AF_INET2) {
1259 if ((port = strchr(hostname, ':')) != NULL((void *)0))
1260 *port++ = '\0';
1261 } else if (hints.ai_family == AF_INET624 || hints.ai_family == 0) {
1262 if (hostname[0] == '[') {
1263 hints.ai_family = AF_INET624;
1264 hostname++;
1265 if ((port = strchr(hostname, ']')) == NULL((void *)0))
1266 errx(1, "invalid agent");
1267 *port++ = '\0';
1268 if (port[0] == ':')
1269 *port++ = '\0';
1270 else if (port[0] == '\0')
1271 port = NULL((void *)0);
1272 else
1273 errx(1, "invalid agent");
1274 } else {
1275 if ((port = strrchr(hostname, ':')) != NULL((void *)0))
1276 *port++ = '\0';
1277 }
1278 }
1279
1280 if (hints.ai_family != AF_UNIX1) {
1281 if (hints.ai_socktype == 0)
1282 hints.ai_socktype = SOCK_DGRAM2;
1283 if (port == NULL((void *)0))
1284 port = defaultport;
1285 error = getaddrinfo(hostname, port, &hints, &ai0);
1286 if (error) {
1287 if (error != EAI_NODATA-5 || port == defaultport)
1288 errx(1, "%s", gai_strerror(error));
1289 *--port = ':';
1290 error = getaddrinfo(hostname, defaultport, &hints,
1291 &ai0);
1292 if (error)
1293 errx(1, "%s", gai_strerror(error));
1294 }
1295 s = -1;
1296 for (ai = ai0; ai != NULL((void *)0); ai = ai->ai_next) {
1297 if ((s = socket(ai->ai_family, ai->ai_socktype,
1298 ai->ai_protocol)) != -1 &&
1299 connect(s, (struct sockaddr *)ai->ai_addr,
1300 ai->ai_addrlen) != -1)
1301 break;
1302 close(s);
1303 s = -1;
1304 }
1305 } else {
1306 s = socket(AF_UNIX1, SOCK_STREAM1, 0);
1307 if (connect(s, (struct sockaddr *)ai->ai_addr,
1308 ai->ai_addrlen) == -1)
1309 err(1, "Can't connect to %s", agent);
1310 }
1311 if (s == -1)
1312 err(1, "Can't connect to agent %s", agent);
1313
1314
1315 if (ai0 != NULL((void *)0))
1316 freeaddrinfo(ai0);
1317 free(agentdup);
1318 return s;
1319}
1320
1321char *
1322snmpc_hex2bin(char *hexstr, size_t *binlen)
1323{
1324 char *decstr;
1325
1326 if (hexstr[0] == '0' && hexstr[1] == 'x')
21
Assuming the condition is false
1327 hexstr += 2;
1328 while (hexstr[0] == ' ' || hexstr[0] == '\t')
22
Assuming the condition is false
23
Assuming the condition is false
24
Loop condition is false. Execution continues on line 1331
1329 hexstr++;
1330
1331 if ((decstr = malloc((strlen(hexstr) / 2) + 1)) == NULL((void *)0))
25
Memory is allocated
26
Assuming the condition is false
27
Taking false branch
1332 return NULL((void *)0);
1333
1334 for (*binlen = 0; hexstr[0] != '\0'; (*binlen)++) {
28
Assuming the condition is false
29
Loop condition is false. Execution continues on line 1355
1335 hexstr[0] = toupper(hexstr[0]);
1336 hexstr[1] = toupper(hexstr[1]);
1337 if (hexstr[0] >= '0' && hexstr[0] <= '9')
1338 decstr[*binlen] = (hexstr[0] - '0') << 4;
1339 else if (hexstr[0] >= 'A' && hexstr[0] <= 'F')
1340 decstr[*binlen] = ((hexstr[0] - 'A') + 10) << 4;
1341 else
1342 goto fail;
1343 if (hexstr[1] >= '0' && hexstr[1] <= '9')
1344 decstr[*binlen] |= (hexstr[1] - '0');
1345 else if (hexstr[1] >= 'A' && hexstr[1] <= 'F')
1346 decstr[*binlen] |= (hexstr[1] - 'A') + 10;
1347 else
1348 goto fail;
1349
1350 hexstr += 2;
1351 while (hexstr[0] == ' ' || hexstr[0] == '\t')
1352 hexstr++;
1353 }
1354
1355 return decstr;
1356fail:
1357 errno(*__errno()) = EINVAL22;
1358 free(decstr);
1359 return NULL((void *)0);
1360}
1361
1362ssize_t
1363snmpc_mbswidth(char *str)
1364{
1365 wchar_t wc;
1366 size_t width = 0;
1367 size_t i;
1368 int len;
1369
1370 for (i = 0; (len = mbtowc(&wc, &(str[i]), MB_CUR_MAX__mb_cur_max())) != 0; i += len) {
1371 if (len == -1) {
1372 mbtowc(NULL((void *)0), NULL((void *)0), MB_CUR_MAX__mb_cur_max());
1373 return -1;
1374 }
1375 width += wcwidth(wc);
1376 }
1377 return width;
1378}
1379
1380struct ber_element *
1381snmpc_varbindparse(int argc, char *argv[])
1382{
1383 struct ber_oid oid, oidval;
1384 struct in_addr addr4;
1385 char *addr = (char *)&addr4;
1386 char *str = NULL((void *)0), *tmpstr, *endstr;
1387 const char *errstr = NULL((void *)0);
1388 struct ber_element *varbind = NULL((void *)0), *vblist = NULL((void *)0);
1389 int i, ret;
1390 size_t strl, byte;
1391 long long lval;
1392
1393 if (argc % 3 != 0)
1394 usage();
1395 for (i = 0; i < argc; i += 3) {
1396 if (smi_string2oid(argv[i], &oid) == -1)
1397 errx(1, "Invalid oid: %s\n", argv[i]);
1398 switch (argv[i + 1][0]) {
1399 case 'a':
1400 ret = inet_pton(AF_INET2, argv[i + 2], &addr4);
1401 if (ret == -1)
1402 err(1, "inet_pton");
1403 if (ret == 0)
1404 errx(1, "%s: Bad value notation (%s)", argv[i],
1405 argv[i + 2]);
1406 if ((varbind = ober_printf_elements(varbind, "{Oxt}",
1407 &oid, addr, sizeof(addr4), BER_CLASS_APPLICATION0x1,
1408 SNMP_T_IPADDR)) == NULL((void *)0))
1409 err(1, "ober_printf_elements");
1410 break;
1411 case 'b':
1412 tmpstr = argv[i + 2];
1413 strl = 0;
1414 do {
1415 lval = strtoll(tmpstr, &endstr, 10);
1416 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1417 endstr[0] != ',' && endstr[0] != '\0')
1418 errx(1, "%s: Bad value notation (%s)",
1419 argv[i], argv[i + 2]);
1420 if (tmpstr == endstr) {
1421 tmpstr++;
1422 continue;
1423 }
1424 if (lval < 0)
1425 errx(1, "%s: Bad value notation (%s)",
1426 argv[i], argv[i + 2]);
1427 byte = lval / 8;
1428 if (byte >= strl) {
1429 if ((str = recallocarray(str, strl,
1430 byte + 1, 1)) == NULL((void *)0))
1431 err(1, "malloc");
1432 strl = byte + 1;
1433 }
1434 str[byte] |= 0x80 >> (lval % 8);
1435 tmpstr = endstr + 1;
1436 } while (endstr[0] != '\0');
1437 /*
1438 * RFC3416 Section 2.5
1439 * A BITS value is encoded as an OCTET STRING
1440 */
1441 goto pastestring;
1442 case 'c':
1443 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1444 &errstr);
1445 if (errstr != NULL((void *)0))
1446 errx(1, "%s: Bad value notation (%s)", argv[i],
1447 argv[i + 2]);
1448 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1449 &oid, lval, BER_CLASS_APPLICATION0x1,
1450 SNMP_T_COUNTER32)) == NULL((void *)0))
1451 err(1, "ober_printf_elements");
1452 break;
1453 case 'd':
1454 /* String always shrinks */
1455 if ((str = malloc(strlen(argv[i + 2]))) == NULL((void *)0))
1456 err(1, "malloc");
1457 tmpstr = argv[i + 2];
1458 strl = 0;
1459 do {
1460 lval = strtoll(tmpstr, &endstr, 10);
1461 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1462 endstr[0] != '\0')
1463 errx(1, "%s: Bad value notation (%s)",
1464 argv[i], argv[i + 2]);
1465 if (tmpstr == endstr) {
1466 tmpstr++;
1467 continue;
1468 }
1469 if (lval < 0 || lval > 0xff)
1470 errx(1, "%s: Bad value notation (%s)",
1471 argv[i], argv[i + 2]);
1472 str[strl++] = (unsigned char) lval;
1473 tmpstr = endstr + 1;
1474 } while (endstr[0] != '\0');
1475 goto pastestring;
1476 case 'i':
1477 lval = strtonum(argv[i + 2], INT32_MIN(-0x7fffffff - 1), INT32_MAX0x7fffffff,
1478 &errstr);
1479 if (errstr != NULL((void *)0))
1480 errx(1, "%s: Bad value notation (%s)", argv[i],
1481 argv[i + 2]);
1482 if ((varbind = ober_printf_elements(varbind, "{Oi}",
1483 &oid, lval)) == NULL((void *)0))
1484 err(1, "ober_printf_elements");
1485 break;
1486 case 'n':
1487 if ((varbind = ober_printf_elements(varbind, "{O0}",
1488 &oid)) == NULL((void *)0))
1489 err(1, "ober_printf_elements");
1490 break;
1491 case 'o':
1492 if (smi_string2oid(argv[i + 2], &oidval) == -1)
1493 errx(1, "%s: Unknown Object Identifier (Sub-id "
1494 "not found: (top) -> %s)", argv[i],
1495 argv[i + 2]);
1496 if ((varbind = ober_printf_elements(varbind, "{OO}",
1497 &oid, &oidval)) == NULL((void *)0))
1498 err(1, "ober_printf_elements");
1499 break;
1500 case 's':
1501 if ((str = strdup(argv[i + 2])) == NULL((void *)0))
1502 err(1, NULL((void *)0));
1503 strl = strlen(argv[i + 2]);
1504pastestring:
1505 if ((varbind = ober_printf_elements(varbind, "{Ox}",
1506 &oid, str, strl)) == NULL((void *)0))
1507 err(1, "ober_printf_elements");
1508 free(str);
1509 break;
1510 case 't':
1511 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1512 &errstr);
1513 if (errstr != NULL((void *)0))
1514 errx(1, "%s: Bad value notation (%s)", argv[i],
1515 argv[i + 2]);
1516 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1517 &oid, lval, BER_CLASS_APPLICATION0x1,
1518 SNMP_T_TIMETICKS)) == NULL((void *)0))
1519 err(1, "ober_printf_elements");
1520 break;
1521 case 'u':
1522 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1523 &errstr);
1524 if (errstr != NULL((void *)0))
1525 errx(1, "%s: Bad value notation (%s)", argv[i],
1526 argv[i + 2]);
1527 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1528 &oid, lval, BER_CLASS_APPLICATION0x1,
1529 SNMP_T_GAUGE32)) == NULL((void *)0))
1530 err(1, "ober_printf_elements");
1531 break;
1532 case 'x':
1533 /* String always shrinks */
1534 if ((str = malloc(strlen(argv[i + 2]))) == NULL((void *)0))
1535 err(1, "malloc");
1536 tmpstr = argv[i + 2];
1537 strl = 0;
1538 do {
1539 lval = strtoll(tmpstr, &endstr, 16);
1540 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1541 endstr[0] != '\0')
1542 errx(1, "%s: Bad value notation (%s)",
1543 argv[i], argv[i + 2]);
1544 if (tmpstr == endstr) {
1545 tmpstr++;
1546 continue;
1547 }
1548 if (lval < 0 || lval > 0xff)
1549 errx(1, "%s: Bad value notation (%s)",
1550 argv[i], argv[i + 2]);
1551 str[strl++] = (unsigned char) lval;
1552 tmpstr = endstr + 1;
1553 } while (endstr[0] != '\0');
1554 goto pastestring;
1555 default:
1556 usage();
1557 }
1558 if (vblist == NULL((void *)0))
1559 vblist = varbind;
1560 }
1561
1562 return vblist;
1563}
1564
1565__dead__attribute__((__noreturn__)) void
1566usage(void)
1567{
1568 size_t i;
1569
1570 if (snmp_app != NULL((void *)0)) {
1571 fprintf(stderr(&__sF[2]), "usage: snmp %s%s%s\n",
1572 snmp_app->name,
1573 snmp_app->usecommonopt ?
1574 " [-A authpass] [-a digest] [-c community] [-e secengineid]\n"
1575 " [-E ctxengineid] [-K localpriv] [-k localauth] [-l seclevel]\n"
1576 " [-n ctxname] [-O afnqvxSQ] [-r retries] [-t timeout] [-u user]\n"
1577 " [-v version] [-X privpass] [-x cipher] [-Z boots,time]\n"
1578 " " : "",
1579 snmp_app->usage == NULL((void *)0) ? " " : snmp_app->usage);
1580 exit(1);
1581 }
1582 for (i = 0; i < (sizeof(snmp_apps)/sizeof(*snmp_apps)); i++) {
1583 if (i == 0)
1584 fprintf(stderr(&__sF[2]), "usage: ");
1585 else
1586 fprintf(stderr(&__sF[2]), " ");
1587 fprintf(stderr(&__sF[2]), "snmp %s%s %s\n",
1588 snmp_apps[i].name,
1589 snmp_apps[i].usecommonopt ?
1590 " [options]" : "",
1591 snmp_apps[i].usage ? snmp_apps[i].usage : "");
1592 }
1593 exit(1);
1594}