Bug Summary

File:src/usr.bin/snmp/snmpc.c
Warning:line 725, column 23
Assigned value is garbage or undefined

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;
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))
146 errx(1, "setlocale(LC_CTYPE, \"en_US.UTF-8\") failed");
147
148 if (pledge("stdio inet dns unix", NULL((void *)0)) == -1)
149 err(1, "pledge");
150
151 if (argc <= 1)
152 usage();
153
154 optstr[0] = '\0';
155 for (i = 0; i < sizeof(snmp_apps)/sizeof(*snmp_apps); i++) {
156 if (strcmp(snmp_apps[i].name, argv[1]) == 0) {
157 snmp_app = &snmp_apps[i];
158 if (snmp_app->optstring != NULL((void *)0)) {
159 if (strlcpy(optstr, snmp_app->optstring,
160 sizeof(optstr)) > sizeof(optstr))
161 errx(1, "strlcat");
162 }
163 break;
164 }
165 }
166 if (snmp_app == NULL((void *)0))
167 usage();
168
169 if (snmp_app->usecommonopt) {
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) {
181 switch (ch) {
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,
209 &ctxengineidlen);
210 if (ctxengineid == NULL((void *)0)) {
211 if (errno(*__errno()) == EINVAL22)
212 errx(1, "Bad engine ID value "
213 "after -3E flag.");
214 err(1, "-3E");
215 }
216 break;
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) {
472 if (community == NULL((void *)0) || community[0] == '\0')
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)
1
Assuming the condition is false
604 errx(1, "Cannot send V2 PDU on V1 session");
605 if (argc < 1 || argc > 2)
2
Assuming 'argc' is >= 1
3
Assuming 'argc' is <= 2
4
Taking false branch
606 usage();
607 oids = argc == 1 ? mib : argv[1];
5
Assuming 'argc' is not equal to 1
6
'?' condition is false
608
609 if ((agent = snmpc_connect(argv[0], "161"))== NULL((void *)0))
7
Assuming the condition is false
8
Taking false branch
610 err(1, "%s", snmp_app->name);
611 agent->timeout = timeout;
612 agent->retries = retries;
613 if (pledge("stdio", NULL((void *)0)) == -1)
9
Assuming the condition is false
10
Taking false branch
614 err(1, "pledge");
615
616 if (smi_string2oid(oids, &oid) == -1)
11
Assuming the condition is false
12
Taking false branch
617 errx(1, "%s: Unknown object identifier", oids);
618 bcopy(&oid, &noid, sizeof(noid));
619 if (print_time)
13
Assuming 'print_time' is 0
14
Taking false branch
620 clock_gettime(CLOCK_MONOTONIC3, &start);
621
622 if (walk_include_oid) {
15
Assuming 'walk_include_oid' is 0
16
Taking false branch
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) {
17
Loop condition is true. Entering loop body
642 for (i = 0; i < walk_skip_len; i++) {
18
Assuming 'i' is >= 'walk_skip_len'
19
Loop condition is false. Execution continues on line 650
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) {
20
Assuming the condition is false
21
Taking false branch
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))
22
Assuming the condition is false
23
Taking false branch
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) {
24
Assuming 'errorstatus' is equal to 0
25
Taking false branch
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)
26
Assuming 'class' is not equal to BER_CLASS_CONTEXT
668 printf("Received report:\n");
669 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
27
Assuming 'varbind' is not equal to NULL
28
Loop condition is true. Entering loop body
670 (void) ober_scanf_elements(varbind, "{oe}", &noid,
671 &value);
672 if (value->be_class == BER_CLASS_CONTEXT0x2 &&
29
Assuming field 'be_class' is equal to BER_CLASS_CONTEXT
31
Taking true branch
673 value->be_type == BER_TYPE_EOC0)
30
Assuming field 'be_type' is equal to BER_TYPE_EOC
674 break;
32
Execution continues on line 695
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
32.1
'class' is not equal to BER_CLASS_CONTEXT
== BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
697 return 1;
698 if (varbind
32.2
'varbind' is not equal to NULL
!= NULL((void *)0))
33
Taking true branch
699 break;
34
Execution continues on line 701
700 }
701 if (walk_fallback_oid && n == 0) {
35
Assuming 'walk_fallback_oid' is 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)
36
Assuming 'print_time' is not equal to 0
37
Taking true branch
721 clock_gettime(CLOCK_MONOTONIC3, &finish);
722 if (print_summary)
38
Assuming 'print_summary' is 0
39
Taking false branch
723 printf("Variables found: %d\n", n);
724 if (print_time
39.1
'print_time' is not equal to 0
) {
40
Taking true branch
725 if ((finish.tv_nsec -= start.tv_nsec) < 0) {
41
Assigned value is garbage or undefined
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')
1327 hexstr += 2;
1328 while (hexstr[0] == ' ' || hexstr[0] == '\t')
1329 hexstr++;
1330
1331 if ((decstr = malloc((strlen(hexstr) / 2) + 1)) == NULL((void *)0))
1332 return NULL((void *)0);
1333
1334 for (*binlen = 0; hexstr[0] != '\0'; (*binlen)++) {
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}