Bug Summary

File:src/usr.bin/snmp/snmpc.c
Warning:line 520, column 9
Potential leak of memory pointed to by 'secengineid'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name snmpc.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -I /usr/src/usr.bin/snmp -internal-isystem /usr/local/llvm16/lib/clang/16/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 -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/snmp/snmpc.c
1/* $OpenBSD: snmpc.c,v 1.40 2022/12/26 19:16:03 jmc 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;
164 }
165 }
166 if (snmp_app
13.1
'snmp_app' is not equal to NULL
== NULL((void *)0))
13
Execution continues on line 166
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
32
Execution continues on line 180
33
Assuming the condition is false
34
Loop condition is false. Execution continues on line 468
181 switch (ch) {
19
Control jumps to 'case 101:' at line 217
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,
20
Calling 'snmpc_hex2bin'
30
Returned allocated memory
219 &secengineidlen);
220 if (secengineid
30.1
'secengineid' is not equal to NULL
== NULL((void *)0)) {
31
Taking false branch
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 (!snmp_app->usecommonopt) {
35
Assuming field 'usecommonopt' is 0
36
Taking true branch
472 /* No SNMP protocol settings */
473 } else if (version == SNMP_V1 || version == SNMP_V2C) {
474 if (community == NULL((void *)0) || community[0] == '\0')
475 errx(1, "No community name specified.");
476 } else if (version == SNMP_V3) {
477 /* Setup USM */
478 if (user == NULL((void *)0) || user[0] == '\0')
479 errx(1, "No securityName specified");
480 if ((sec = usm_init(user, strlen(user))) == NULL((void *)0))
481 err(1, "usm_init");
482 if (seclevel & SNMP_MSGFLAG_AUTH0x01) {
483 if (md == NULL((void *)0))
484 md = EVP_sha1();
485 if (authkey == NULL((void *)0))
486 errx(1, "No authKey or authPassword specified");
487 if (usm_setauth(sec, md, authkey, authkeylen,
488 authkeylevel) == -1)
489 err(1, "Can't set authkey");
490 }
491 if (seclevel & SNMP_MSGFLAG_PRIV0x02) {
492 if (cipher == NULL((void *)0))
493 cipher = EVP_aes_128_cfb128();
494 if (privkey == NULL((void *)0))
495 errx(1, "No privKey or privPassword specified");
496 if (usm_setpriv(sec, cipher, privkey, privkeylen,
497 privkeylevel) == -1)
498 err(1, "Can't set authkey");
499 }
500 if (secengineid != NULL((void *)0)) {
501 if (usm_setengineid(sec, secengineid,
502 secengineidlen) == -1)
503 err(1, "Can't set secengineid");
504 }
505 if (zflag)
506 if (usm_setbootstime(sec, boots, time) == -1)
507 err(1, "Can't set boots/time");
508 v3 = snmp_v3_init(seclevel, ctxname, ctxname == NULL((void *)0) ? 0 :
509 strlen(ctxname), sec);
510 if (v3 == NULL((void *)0))
511 err(1, "snmp_v3_init");
512 if (ctxengineid != NULL((void *)0)) {
513 if (snmp_v3_setengineid(v3, ctxengineid,
514 ctxengineidlen) == -1)
515 err(1, "Can't set ctxengineid");
516 }
517 }
518
519
520 return snmp_app->exec(argc, argv);
37
Potential leak of memory pointed to by 'secengineid'
521}
522
523int
524snmpc_get(int argc, char *argv[])
525{
526 struct ber_oid *oid;
527 struct ber_element *pdu, *varbind;
528 struct snmp_agent *agent;
529 int errorstatus, errorindex;
530 int i;
531 int class;
532 unsigned type;
533 char *hint = NULL((void *)0);
534
535 if (argc < 2)
536 usage();
537
538 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
539 err(1, "%s", snmp_app->name);
540 agent->timeout = timeout;
541 agent->retries = retries;
542
543 if (pledge("stdio", NULL((void *)0)) == -1)
544 err(1, "pledge");
545 argc--;
546 argv++;
547
548 oid = reallocarray(NULL((void *)0), argc, sizeof(*oid));
549 if (oid == NULL((void *)0))
550 err(1, "malloc");
551 for (i = 0; i < argc; i++) {
552 if (smi_string2oid(argv[i], &oid[i]) == -1)
553 errx(1, "%s: Unknown object identifier", argv[i]);
554 }
555 if (strcmp(snmp_app->name, "getnext") == 0) {
556 if ((pdu = snmp_getnext(agent, oid, argc)) == NULL((void *)0))
557 err(1, "getnext");
558 } else if (strcmp(snmp_app->name, "bulkget") == 0) {
559 if (version < SNMP_V2C)
560 errx(1, "Cannot send V2 PDU on V1 session");
561 if (non_repeaters > argc)
562 errx(1, "need more objects than -Cn<num>");
563 if ((pdu = snmp_getbulk(agent, oid, argc, non_repeaters,
564 max_repetitions)) == NULL((void *)0))
565 err(1, "bulkget");
566 } else {
567 if ((pdu = snmp_get(agent, oid, argc)) == NULL((void *)0))
568 err(1, "get");
569 }
570
571 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
572 &errorindex, &varbind);
573 if (errorstatus != 0) {
574 if (errorindex >= 1 && errorindex <= argc)
575 hint = argv[errorindex - 1];
576 snmpc_printerror((enum snmp_error) errorstatus, varbind,
577 errorindex, hint);
578 }
579
580 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
581 printf("Received report:\n");
582 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
583 if (!snmpc_print(varbind))
584 err(1, "Can't print response");
585 }
586 ober_free_elements(pdu);
587 snmp_free_agent(agent);
588 return 0;
589}
590
591int
592snmpc_walk(int argc, char *argv[])
593{
594 struct ber_oid oid, loid, noid;
595 struct ber_element *pdu, *varbind, *value;
596 struct timespec start, finish;
597 struct snmp_agent *agent;
598 const char *oids;
599 int n = 0, prev_cmp, skip_cmp;
600 int errorstatus, errorindex;
601 int class;
602 size_t i;
603 unsigned type;
604
605 if (strcmp(snmp_app->name, "bulkwalk") == 0 && version < SNMP_V2C)
606 errx(1, "Cannot send V2 PDU on V1 session");
607 if (argc < 1 || argc > 2)
608 usage();
609 oids = argc == 1 ? mib : argv[1];
610
611 if ((agent = snmpc_connect(argv[0], "161"))== NULL((void *)0))
612 err(1, "%s", snmp_app->name);
613 agent->timeout = timeout;
614 agent->retries = retries;
615 if (pledge("stdio", NULL((void *)0)) == -1)
616 err(1, "pledge");
617
618 if (smi_string2oid(oids, &oid) == -1)
619 errx(1, "%s: Unknown object identifier", oids);
620 bcopy(&oid, &noid, sizeof(noid));
621 if (print_time)
622 clock_gettime(CLOCK_MONOTONIC3, &start);
623
624 if (walk_include_oid) {
625 if ((pdu = snmp_get(agent, &oid, 1)) == NULL((void *)0))
626 err(1, "%s", snmp_app->name);
627
628 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
629 &errorstatus, &errorindex, &varbind);
630 if (errorstatus != 0)
631 snmpc_printerror((enum snmp_error) errorstatus, varbind,
632 errorindex, oids);
633
634 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
635 printf("Received report:\n");
636 if (!snmpc_print(varbind))
637 err(1, "Can't print response");
638 ober_free_element(pdu);
639 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
640 return 1;
641 n++;
642 }
643 while (1) {
644 for (i = 0; i < walk_skip_len; i++) {
645 skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
646 if (skip_cmp == 0 || skip_cmp == 2) {
647 bcopy(&(walk_skip[i]), &noid, sizeof(noid));
648 noid.bo_id[noid.bo_n -1]++;
649 break;
650 }
651 }
652 bcopy(&noid, &loid, sizeof(loid));
653 if (strcmp(snmp_app->name, "bulkwalk") == 0) {
654 if ((pdu = snmp_getbulk(agent, &noid, 1,
655 non_repeaters, max_repetitions)) == NULL((void *)0))
656 err(1, "bulkwalk");
657 } else {
658 if ((pdu = snmp_getnext(agent, &noid, 1)) == NULL((void *)0))
659 err(1, "walk");
660 }
661
662 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
663 &errorstatus, &errorindex, &varbind);
664 if (errorstatus != 0) {
665 snmpc_printerror((enum snmp_error) errorstatus, varbind,
666 errorindex, NULL((void *)0));
667 }
668
669 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
670 printf("Received report:\n");
671 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
672 (void) ober_scanf_elements(varbind, "{oe}", &noid,
673 &value);
674 if (value->be_class == BER_CLASS_CONTEXT0x2 &&
675 value->be_type == BER_TYPE_EOC0)
676 break;
677 for (i = 0; i < walk_skip_len; i++) {
678 skip_cmp = ober_oid_cmp(&noid, &(walk_skip[i]));
679 if (skip_cmp == 0 || skip_cmp == 2)
680 break;
681 }
682 if (i < walk_skip_len)
683 continue;
684 prev_cmp = ober_oid_cmp(&noid, &loid);
685 if (walk_check_increase && prev_cmp == -1)
686 errx(1, "OID not increasing");
687 if (prev_cmp == 0 || ober_oid_cmp(&noid, &oid) != 2)
688 break;
689 if (walk_end.bo_n != 0 &&
690 ober_oid_cmp(&noid, &walk_end) != -1)
691 break;
692
693 if (!snmpc_print(varbind))
694 err(1, "Can't print response");
695 n++;
696 }
697 ober_free_elements(pdu);
698 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
699 return 1;
700 if (varbind != NULL((void *)0))
701 break;
702 }
703 if (walk_fallback_oid && n == 0) {
704 if ((pdu = snmp_get(agent, &oid, 1)) == NULL((void *)0))
705 err(1, "%s", snmp_app->name);
706
707 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
708 &errorstatus, &errorindex, &varbind);
709 if (errorstatus != 0)
710 snmpc_printerror((enum snmp_error) errorstatus, varbind,
711 errorindex, oids);
712
713 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
714 printf("Received report:\n");
715 if (!snmpc_print(varbind))
716 err(1, "Can't print response");
717 ober_free_element(pdu);
718 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
719 return 1;
720 n++;
721 }
722 if (print_time)
723 clock_gettime(CLOCK_MONOTONIC3, &finish);
724 if (print_summary)
725 printf("Variables found: %d\n", n);
726 if (print_time) {
727 if ((finish.tv_nsec -= start.tv_nsec) < 0) {
728 finish.tv_sec -= 1;
729 finish.tv_nsec += 1000000000;
730 }
731 finish.tv_sec -= start.tv_sec;
732 fprintf(stderr(&__sF[2]), "Total traversal time: %lld.%09ld seconds\n",
733 finish.tv_sec, finish.tv_nsec);
734 }
735 snmp_free_agent(agent);
736 return 0;
737}
738
739int
740snmpc_set(int argc, char *argv[])
741{
742 struct snmp_agent *agent;
743 struct ber_element *pdu, *varbind;
744 int errorstatus, errorindex;
745 int class;
746 unsigned type;
747 char *hint = NULL((void *)0);
748
749 if (argc < 4)
750 usage();
751 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
752 err(1, "%s", snmp_app->name);
753 argc--;
754 argv++;
755
756 if (pledge("stdio", NULL((void *)0)) == -1)
757 err(1, "pledge");
758
759 if ((pdu = snmp_set(agent, snmpc_varbindparse(argc, argv))) == NULL((void *)0))
760 err(1, "set");
761
762 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus,
763 &errorindex, &varbind);
764 if (errorstatus != 0) {
765 if (errorindex >= 1 && errorindex <= argc / 3)
766 hint = argv[(errorindex - 1) * 3];
767 snmpc_printerror((enum snmp_error) errorstatus, varbind,
768 errorindex, hint);
769 }
770
771 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT)
772 printf("Received report:\n");
773 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
774 if (!snmpc_print(varbind))
775 err(1, "Can't print response");
776 }
777 ober_free_elements(pdu);
778 snmp_free_agent(agent);
779 return 0;
780}
781
782int
783snmpc_trap(int argc, char *argv[])
784{
785 struct snmp_agent *agent;
786 struct timespec ts;
787 struct ber_oid trapoid;
788 const char *errstr = NULL((void *)0);
789 long long lval;
790
791 if (version == SNMP_V1)
792 errx(1, "trap is not supported for snmp v1");
793
794 if (argc < 3)
795 usage();
796
797 if ((agent = snmpc_connect(argv[0], "162")) == NULL((void *)0))
798 err(1, "%s", snmp_app->name);
799
800 if (pledge("stdio", NULL((void *)0)) == -1)
801 err(1, "pledge");
802
803 if (argv[1][0] == '\0') {
804 if (clock_gettime(CLOCK_UPTIME5, &ts) == -1)
805 err(1, "clock_gettime");
806 } else {
807 lval = strtonum(argv[1], 0, UINT32_MAX0xffffffffU, &errstr);
808 if (errstr != NULL((void *)0))
809 errx(1, "Bad value notation (%s)", argv[1]);
810 ts.tv_sec = lval / 100;
811 ts.tv_nsec = (lval % 100) * 10000000;
812 }
813 if (smi_string2oid(argv[2], &trapoid) == -1)
814 errx(1, "Invalid oid: %s\n", argv[2]);
815
816 argc -= 3;
817 argv += 3;
818
819 snmp_trap(agent, &ts, &trapoid, snmpc_varbindparse(argc, argv));
820
821 return 0;
822}
823
824#define INCR_NEXTTAB(x)((x + 8) & ~7) ((x + 8) & ~7)
825#define NEXTTAB(x)(8 - (x & 7)) (8 - (x & 7))
826int
827snmpc_df(int argc, char *argv[])
828{
829 struct snmpc_df {
830 uint32_t index;
831 char *descr;
832 int descrwidth;
833 /* Theoretical maximum for 2 32 bit values multiplied */
834 char size[21];
835 char used[21];
836 char avail[21];
837 char proc[5];
838 } *df = NULL((void *)0);
839 struct ber_oid descroid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 3 }, 11};
840 struct ber_oid unitsoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 4 }, 11};
841 struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11};
842 struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11};
843 struct ber_oid oid, *reqoid;
844 char oids[SNMP_MAX_OID_STRLEN128];
845 struct ber_element *pdu, *varbind, *elm;
846 struct snmp_agent *agent;
847 int errorstatus, errorindex;
848 int class;
849 size_t i, j, rows = 0;
850 unsigned type;
851 char *string;
852 int descrlen = 0, sizelen = 0, usedlen = 0, availlen = 0, proclen = 0;
853 int len;
854 long long units, size, used;
855 int fmtret;
856
857 if (argc != 1)
858 usage();
859
860 if ((agent = snmpc_connect(argv[0], "161")) == NULL((void *)0))
861 err(1, "%s", snmp_app->name);
862 agent->timeout = timeout;
863 agent->retries = retries;
864
865 if (pledge("stdio", NULL((void *)0)) == -1)
866 err(1, "pledge");
867
868 descrlen = sizeof("Description") - 1;
869 sizelen = sizeof("Size") - 1;
870 usedlen = sizeof("Used") - 1;
871 availlen = sizeof("Available") - 1;
872 proclen = sizeof("Used%") - 1;
873
874 bcopy(&descroid, &oid, sizeof(descroid));
875
876 i = 0;
877 while(1) {
878 if (version < SNMP_V2C) {
879 if ((pdu = snmp_getnext(agent, &oid, 1)) == NULL((void *)0))
880 err(1, "df");
881 } else {
882 if ((pdu = snmp_getbulk(agent, &oid, 1, 0,
883 max_repetitions)) == NULL((void *)0))
884 err(1, "df");
885 }
886
887 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
888 &errorstatus, &errorindex, &varbind);
889 if (errorstatus != 0)
890 snmpc_printerror((enum snmp_error) errorstatus, varbind,
891 errorindex, NULL((void *)0));
892
893 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT) {
894 printf("Received report:\n");
895 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
896 if (!snmpc_print(varbind))
897 err(1, "Can't print response");
898 }
899 return 1;
900 }
901 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
902 if (ober_scanf_elements(varbind, "{os", &oid,
903 &string) == -1 ||
904 ober_oid_cmp(&oid, &descroid) != 2)
905 break;
906 rows++;
907 }
908 if ((df = reallocarray(df, rows, sizeof(*df))) == NULL((void *)0))
909 err(1, "malloc");
910 (void) ober_scanf_elements(pdu, "{SSS{e", &varbind);
911 for (; i < rows; varbind = varbind->be_next, i++) {
912 if (ober_scanf_elements(varbind, "{oe", &oid,
913 &elm) == -1) {
914 i--;
915 rows--;
916 continue;
917 }
918 if (ober_oid_cmp(&oid, &descroid) != 2)
919 break;
920 df[i].index = oid.bo_id[oid.bo_n - 1];
921 if ((df[i].descr = smi_print_element(&oid, elm, 0,
922 smi_os_ascii, 0, utf8)) == NULL((void *)0)) {
923 smi_oid2string(&oid, oids, sizeof(oids),
924 oid_lookup);
925 warn("df: can't print oid %s", oids);
926 i--;
927 rows--;
928 continue;
929 }
930 if ((df[i].descrwidth =
931 (int) snmpc_mbswidth(df[i].descr)) == -1)
932 err(1, "df: invalid hrStorageDescr");
933 if (df[i].descrwidth > descrlen)
934 descrlen = df[i].descrwidth;
935 }
936 ober_free_elements(pdu);
937 if (varbind != NULL((void *)0))
938 break;
939 }
940
941 if (max_repetitions < 3)
942 max_repetitions = 3;
943 if ((reqoid = reallocarray(NULL((void *)0), max_repetitions, sizeof(*reqoid))) == NULL((void *)0))
944 err(1, "malloc");
945 for (i = 0; i < rows;) {
946 for (j = 0; i + j < rows && j < (size_t)max_repetitions / 3;
947 j++) {
948 bcopy(&unitsoid, &(reqoid[(j * 3) + 0]),
949 sizeof(unitsoid));
950 reqoid[(j * 3) + 0].bo_id[
951 reqoid[(j * 3) + 0].bo_n++] = df[i + j].index;
952 bcopy(&sizeoid, &(reqoid[(j * 3) + 1]),
953 sizeof(sizeoid));
954 reqoid[(j * 3) + 1].bo_id[
955 reqoid[(j * 3) + 1].bo_n++] = df[i + j].index;
956 bcopy(&usedoid, &(reqoid[(j * 3) + 2]),
957 sizeof(usedoid));
958 reqoid[(j * 3) + 2].bo_id[
959 reqoid[(j * 3) + 2].bo_n++] = df[i + j].index;
960 }
961 if ((pdu = snmp_get(agent, reqoid, j * 3)) == NULL((void *)0))
962 err(1, "df");
963 (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
964 &errorstatus, &errorindex, &varbind);
965 if (errorstatus != 0)
966 snmpc_printerror((enum snmp_error) errorstatus, varbind,
967 errorindex, NULL((void *)0));
968 if (class == BER_CLASS_CONTEXT0x2 && type == SNMP_C_REPORT) {
969 printf("Received report:\n");
970 for (; varbind != NULL((void *)0); varbind = varbind->be_next) {
971 if (!snmpc_print(varbind))
972 err(1, "Can't print response");
973 }
974 }
975 for (j = 0; varbind != NULL((void *)0); i++) {
976 if (ober_scanf_elements(varbind, "{oi}{oi}{oi}",
977 &(reqoid[0]), &units, &(reqoid[1]), &size,
978 &(reqoid[2]), &used, &varbind) == -1) {
979 break;
980 }
981 varbind = varbind->be_next->be_next->be_next;
982
983 unitsoid.bo_id[unitsoid.bo_n++] = df[i].index;
984 if (ober_oid_cmp(&unitsoid, &(reqoid[0])) != 0) {
985 warnx("df: received invalid object");
986 break;
987 }
988 unitsoid.bo_n--;
989 sizeoid.bo_id[sizeoid.bo_n++] = df[i].index;
990 if (ober_oid_cmp(&sizeoid, &(reqoid[1])) != 0) {
991 warnx("df: received invalid object");
992 break;
993 }
994 sizeoid.bo_n--;
995 usedoid.bo_id[usedoid.bo_n++] = df[i].index;
996 if (ober_oid_cmp(&usedoid, &(reqoid[2])) != 0) {
997 warnx("df: received invalid object");
998 break;
999 }
1000 usedoid.bo_n--;
1001 if (print_human)
1002 fmtret = fmt_scaled((units * size), df[i].size);
1003 if (!print_human || fmtret == -1)
1004 snprintf(df[i].size, sizeof(df[i].size), "%lld",
1005 (units * size) / 1024);
1006 len = (int) strlen(df[i].size);
1007 if (len > sizelen)
1008 sizelen = len;
1009 if (print_human)
1010 fmtret = fmt_scaled(units * used, df[i].used);
1011 if (!print_human || fmtret == -1)
1012 snprintf(df[i].used, sizeof(df[i].used), "%lld",
1013 (units * used) / 1024);
1014 len = (int) strlen(df[i].used);
1015 if (len > usedlen)
1016 usedlen = len;
1017 if (print_human)
1018 fmtret = fmt_scaled(units * (size - used),
1019 df[i].avail);
1020 if (!print_human || fmtret == -1)
1021 snprintf(df[i].avail, sizeof(df[i].avail),
1022 "%lld", (units * (size - used)) / 1024);
1023 len = (int) strlen(df[i].avail);
1024 if (len > availlen)
1025 availlen = len;
1026 if (size == 0)
1027 strlcpy(df[i].proc, "0%", sizeof(df[i].proc));
1028 else {
1029 snprintf(df[i].proc, sizeof(df[i].proc),
1030 "%lld%%", (used * 100) / size);
1031 }
1032 len = (int) strlen(df[i].proc);
1033 if (len > proclen)
1034 proclen = len;
1035 j++;
1036 }
1037 if (j == 0) {
1038 warnx("Failed to retrieve information for %s",
1039 df[i].descr);
1040 memmove(df + i, df + i + 1,
1041 (rows - i - 1) * sizeof(*df));
1042 rows--;
1043 i--;
1044 }
1045 }
1046
1047 printf("%-*s%*s%*s%*s%*s\n",
1048 descrlen, "Description",
1049 NEXTTAB(descrlen)(8 - (descrlen & 7)) + sizelen, "Size",
1050 NEXTTAB(sizelen)(8 - (sizelen & 7)) + usedlen, "Used",
1051 NEXTTAB(usedlen)(8 - (usedlen & 7)) + availlen, "Available",
1052 NEXTTAB(availlen)(8 - (availlen & 7)) + proclen, "Used%");
1053 for (i = 0; i < rows; i++) {
1054 printf("%s%*s%*s%*s%*s%*s\n",
1055 df[i].descr, descrlen - df[i].descrwidth, "",
1056 NEXTTAB(descrlen)(8 - (descrlen & 7)) + sizelen, df[i].size,
1057 NEXTTAB(sizelen)(8 - (sizelen & 7)) + usedlen, df[i].used,
1058 NEXTTAB(usedlen)(8 - (usedlen & 7)) + availlen, df[i].avail,
1059 NEXTTAB(availlen)(8 - (availlen & 7)) + proclen, df[i].proc);
1060 }
1061
1062 return 0;
1063}
1064
1065int
1066snmpc_mibtree(int argc, char *argv[])
1067{
1068 struct oid *oid;
1069 struct ber_oid soid;
1070 char buf[BUFSIZ1024];
1071 int i;
1072
1073 if (argc == 0) {
1074 for (oid = NULL((void *)0); (oid = smi_foreach(oid)) != NULL((void *)0);) {
1075 smi_oid2string(&oid->o_id, buf, sizeof(buf),
1076 oid_lookup);
1077 printf("%s\n", buf);
1078 }
1079 } else {
1080 for (i = 0; i < argc; i++) {
1081 if (smi_string2oid(argv[i], &soid) == -1) {
1082 warnx("%s: Unknown object identifier", argv[i]);
1083 continue;
1084 }
1085 smi_oid2string(&soid, buf, sizeof(buf), oid_lookup);
1086 printf("%s\n", buf);
1087 }
1088 }
1089 return 0;
1090}
1091
1092struct snmp_agent *
1093snmpc_connect(char *host, char *port)
1094{
1095 switch (version) {
1096 case SNMP_V1:
1097 case SNMP_V2C:
1098 return snmp_connect_v12(snmpc_parseagent(host, port), version,
1099 community);
1100 case SNMP_V3:
1101 return snmp_connect_v3(snmpc_parseagent(host, port), v3);
1102 }
1103 return NULL((void *)0);
1104}
1105
1106int
1107snmpc_print(struct ber_element *elm)
1108{
1109 struct ber_oid oid;
1110 char oids[SNMP_MAX_OID_STRLEN128];
1111 char *value;
1112
1113 elm = elm->be_subbe_union.bv_sub;
1114 if (ober_get_oid(elm, &oid) != 0) {
1115 errno(*__errno()) = EINVAL22;
1116 return 0;
1117 }
1118
1119 elm = elm->be_next;
1120 value = smi_print_element(&oid, elm, smi_print_hint, output_string,
1121 oid_lookup, utf8);
1122 if (value == NULL((void *)0))
1123 return 0;
1124
1125 if (print_varbind_only)
1126 printf("%s\n", value);
1127 else if (print_equals) {
1128 smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1129 printf("%s = %s\n", oids, value);
1130 } else {
1131 smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
1132 printf("%s %s\n", oids, value);
1133 }
1134 free(value);
1135
1136 return 1;
1137}
1138
1139__dead__attribute__((__noreturn__)) void
1140snmpc_printerror(enum snmp_error error, struct ber_element *varbind,
1141 int index, const char *hint)
1142{
1143 struct ber_oid hoid, vboid;
1144 char oids[SNMP_MAX_OID_STRLEN128];
1145 const char *oid = NULL((void *)0);
1146 int i;
1147
1148 if (index >= 1) {
1149 /* Only print if the index is in the reply */
1150 for (i = 1; varbind != NULL((void *)0) && i < index;
1151 varbind = varbind->be_next)
1152 i++;
1153 if (varbind != NULL((void *)0) &&
1154 ober_get_oid(varbind->be_subbe_union.bv_sub, &vboid) == 0) {
1155 /* If user and reply conform print user input */
1156 if (hint != NULL((void *)0) &&
1157 smi_string2oid(hint, &hoid) == 0 &&
1158 ober_oid_cmp(&hoid, &vboid) == 0)
1159 oid = hint;
1160 else
1161 oid = smi_oid2string(&vboid, oids,
1162 sizeof(oids), oid_lookup);
1163 }
1164 }
1165 if (oid == NULL((void *)0))
1166 oid = "?";
1167
1168 switch (error) {
1169 case SNMP_ERROR_NONE:
1170 errx(1, "No error, how did I get here?");
1171 case SNMP_ERROR_TOOBIG:
1172 errx(1, "Can't parse oid %s: Response too big", oid);
1173 case SNMP_ERROR_NOSUCHNAME:
1174 errx(1, "Can't parse oid %s: No such object", oid);
1175 case SNMP_ERROR_BADVALUE:
1176 errx(1, "Can't parse oid %s: Bad value", oid);
1177 case SNMP_ERROR_READONLY:
1178 errx(1, "Can't parse oid %s: Read only", oid);
1179 case SNMP_ERROR_GENERR:
1180 errx(1, "Can't parse oid %s: Generic error", oid);
1181 case SNMP_ERROR_NOACCESS:
1182 errx(1, "Can't parse oid %s: Access denied", oid);
1183 case SNMP_ERROR_WRONGTYPE:
1184 errx(1, "Can't parse oid %s: Wrong type", oid);
1185 case SNMP_ERROR_WRONGLENGTH:
1186 errx(1, "Can't parse oid %s: Wrong length", oid);
1187 case SNMP_ERROR_WRONGENC:
1188 errx(1, "Can't parse oid %s: Wrong encoding", oid);
1189 case SNMP_ERROR_WRONGVALUE:
1190 errx(1, "Can't parse oid %s: Wrong value", oid);
1191 case SNMP_ERROR_NOCREATION:
1192 errx(1, "Can't parse oid %s: Can't be created", oid);
1193 case SNMP_ERROR_INCONVALUE:
1194 errx(1, "Can't parse oid %s: Inconsistent value", oid);
1195 case SNMP_ERROR_RESUNAVAIL:
1196 errx(1, "Can't parse oid %s: Resource unavailable", oid);
1197 case SNMP_ERROR_COMMITFAILED:
1198 errx(1, "Can't parse oid %s: Commit failed", oid);
1199 case SNMP_ERROR_UNDOFAILED:
1200 errx(1, "Can't parse oid %s: Undo failed", oid);
1201 case SNMP_ERROR_AUTHERROR:
1202 errx(1, "Can't parse oid %s: Authorization error", oid);
1203 case SNMP_ERROR_NOTWRITABLE:
1204 errx(1, "Can't parse oid %s: Not writable", oid);
1205 case SNMP_ERROR_INCONNAME:
1206 errx(1, "Can't parse oid %s: Inconsistent name", oid);
1207 }
1208 errx(1, "Can't parse oid %s: Unknown error (%d)", oid, error);
1209}
1210
1211int
1212snmpc_parseagent(char *agent, char *defaultport)
1213{
1214 struct addrinfo hints, *ai, *ai0 = NULL((void *)0);
1215 struct sockaddr_un saddr;
1216 char *agentdup, *specifier, *hostname, *port = NULL((void *)0);
1217 int error;
1218 int s;
1219
1220 if ((agentdup = specifier = strdup(agent)) == NULL((void *)0))
1221 err(1, NULL((void *)0));
1222
1223 bzero(&hints, sizeof(hints));
1224 if ((hostname = strchr(specifier, ':')) != NULL((void *)0)) {
1225 *hostname++ = '\0';
1226 if (strcasecmp(specifier, "udp") == 0) {
1227 hints.ai_family = AF_INET2;
1228 hints.ai_socktype = SOCK_DGRAM2;
1229 } else if (strcasecmp(specifier, "tcp") == 0) {
1230 hints.ai_family = AF_INET2;
1231 hints.ai_socktype = SOCK_STREAM1;
1232 } else if (strcasecmp(specifier, "udp6") == 0 ||
1233 strcasecmp(specifier, "udpv6") == 0 ||
1234 strcasecmp(specifier, "udpipv6") == 0) {
1235 hints.ai_family = AF_INET624;
1236 hints.ai_socktype = SOCK_DGRAM2;
1237 } else if (strcasecmp(specifier, "tcp6") == 0 ||
1238 strcasecmp(specifier, "tcpv6") == 0 ||
1239 strcasecmp(specifier, "tcpipv6") == 0) {
1240 hints.ai_family = AF_INET624;
1241 hints.ai_socktype = SOCK_STREAM1;
1242 } else if (strcasecmp(specifier, "unix") == 0) {
1243 hints.ai_family = AF_UNIX1;
1244 hints.ai_addr = (struct sockaddr *)&saddr;
1245 hints.ai_addrlen = sizeof(saddr);
1246 saddr.sun_len = sizeof(saddr);
1247 saddr.sun_family = AF_UNIX1;
1248 if (strlcpy(saddr.sun_path, hostname,
1249 sizeof(saddr.sun_path)) > sizeof(saddr.sun_path))
1250 errx(1, "Hostname path too long");
1251 ai = &hints;
1252 } else {
1253 *--hostname = ':';
1254 hostname = specifier;
1255 }
1256 } else {
1257 hostname = specifier;
1258 }
1259
1260 if (hints.ai_family == AF_INET2) {
1261 if ((port = strchr(hostname, ':')) != NULL((void *)0))
1262 *port++ = '\0';
1263 } else if (hints.ai_family == AF_INET624 || hints.ai_family == 0) {
1264 if (hostname[0] == '[') {
1265 hints.ai_family = AF_INET624;
1266 hostname++;
1267 if ((port = strchr(hostname, ']')) == NULL((void *)0))
1268 errx(1, "invalid agent");
1269 *port++ = '\0';
1270 if (port[0] == ':')
1271 *port++ = '\0';
1272 else if (port[0] == '\0')
1273 port = NULL((void *)0);
1274 else
1275 errx(1, "invalid agent");
1276 } else {
1277 if ((port = strrchr(hostname, ':')) != NULL((void *)0))
1278 *port++ = '\0';
1279 }
1280 }
1281
1282 if (hints.ai_family != AF_UNIX1) {
1283 if (hints.ai_socktype == 0)
1284 hints.ai_socktype = SOCK_DGRAM2;
1285 if (port == NULL((void *)0))
1286 port = defaultport;
1287 error = getaddrinfo(hostname, port, &hints, &ai0);
1288 if (error) {
1289 if (error != EAI_NODATA-5 || port == defaultport)
1290 errx(1, "%s", gai_strerror(error));
1291 *--port = ':';
1292 error = getaddrinfo(hostname, defaultport, &hints,
1293 &ai0);
1294 if (error)
1295 errx(1, "%s", gai_strerror(error));
1296 }
1297 s = -1;
1298 for (ai = ai0; ai != NULL((void *)0); ai = ai->ai_next) {
1299 if ((s = socket(ai->ai_family, ai->ai_socktype,
1300 ai->ai_protocol)) != -1 &&
1301 connect(s, (struct sockaddr *)ai->ai_addr,
1302 ai->ai_addrlen) != -1)
1303 break;
1304 close(s);
1305 s = -1;
1306 }
1307 } else {
1308 s = socket(AF_UNIX1, SOCK_STREAM1, 0);
1309 if (connect(s, (struct sockaddr *)ai->ai_addr,
1310 ai->ai_addrlen) == -1)
1311 err(1, "Can't connect to %s", agent);
1312 }
1313 if (s == -1)
1314 err(1, "Can't connect to agent %s", agent);
1315
1316
1317 if (ai0 != NULL((void *)0))
1318 freeaddrinfo(ai0);
1319 free(agentdup);
1320 return s;
1321}
1322
1323char *
1324snmpc_hex2bin(char *hexstr, size_t *binlen)
1325{
1326 char *decstr;
1327
1328 if (hexstr[0] == '0' && hexstr[1] == 'x')
21
Assuming the condition is false
1329 hexstr += 2;
1330 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 1333
1331 hexstr++;
1332
1333 if ((decstr = malloc((strlen(hexstr) / 2) + 1)) == NULL((void *)0))
25
Memory is allocated
26
Assuming the condition is false
27
Taking false branch
1334 return NULL((void *)0);
1335
1336 for (*binlen = 0; hexstr[0] != '\0'; (*binlen)++) {
28
Assuming the condition is false
29
Loop condition is false. Execution continues on line 1357
1337 hexstr[0] = toupper(hexstr[0]);
1338 hexstr[1] = toupper(hexstr[1]);
1339 if (hexstr[0] >= '0' && hexstr[0] <= '9')
1340 decstr[*binlen] = (hexstr[0] - '0') << 4;
1341 else if (hexstr[0] >= 'A' && hexstr[0] <= 'F')
1342 decstr[*binlen] = ((hexstr[0] - 'A') + 10) << 4;
1343 else
1344 goto fail;
1345 if (hexstr[1] >= '0' && hexstr[1] <= '9')
1346 decstr[*binlen] |= (hexstr[1] - '0');
1347 else if (hexstr[1] >= 'A' && hexstr[1] <= 'F')
1348 decstr[*binlen] |= (hexstr[1] - 'A') + 10;
1349 else
1350 goto fail;
1351
1352 hexstr += 2;
1353 while (hexstr[0] == ' ' || hexstr[0] == '\t')
1354 hexstr++;
1355 }
1356
1357 return decstr;
1358fail:
1359 errno(*__errno()) = EINVAL22;
1360 free(decstr);
1361 return NULL((void *)0);
1362}
1363
1364ssize_t
1365snmpc_mbswidth(char *str)
1366{
1367 wchar_t wc;
1368 size_t width = 0;
1369 size_t i;
1370 int len;
1371
1372 for (i = 0; (len = mbtowc(&wc, &(str[i]), MB_CUR_MAX__mb_cur_max())) != 0; i += len) {
1373 if (len == -1) {
1374 mbtowc(NULL((void *)0), NULL((void *)0), MB_CUR_MAX__mb_cur_max());
1375 return -1;
1376 }
1377 width += wcwidth(wc);
1378 }
1379 return width;
1380}
1381
1382struct ber_element *
1383snmpc_varbindparse(int argc, char *argv[])
1384{
1385 struct ber_oid oid, oidval;
1386 struct in_addr addr4;
1387 char *addr = (char *)&addr4;
1388 char *str = NULL((void *)0), *tmpstr, *endstr;
1389 const char *errstr = NULL((void *)0);
1390 struct ber_element *varbind = NULL((void *)0), *vblist = NULL((void *)0);
1391 int i, ret;
1392 size_t strl, byte;
1393 long long lval;
1394
1395 if (argc % 3 != 0)
1396 usage();
1397 for (i = 0; i < argc; i += 3) {
1398 if (smi_string2oid(argv[i], &oid) == -1)
1399 errx(1, "Invalid oid: %s\n", argv[i]);
1400 switch (argv[i + 1][0]) {
1401 case 'a':
1402 ret = inet_pton(AF_INET2, argv[i + 2], &addr4);
1403 if (ret == -1)
1404 err(1, "inet_pton");
1405 if (ret == 0)
1406 errx(1, "%s: Bad value notation (%s)", argv[i],
1407 argv[i + 2]);
1408 if ((varbind = ober_printf_elements(varbind, "{Oxt}",
1409 &oid, addr, sizeof(addr4), BER_CLASS_APPLICATION0x1,
1410 SNMP_T_IPADDR)) == NULL((void *)0))
1411 err(1, "ober_printf_elements");
1412 break;
1413 case 'b':
1414 tmpstr = argv[i + 2];
1415 strl = 0;
1416 do {
1417 lval = strtoll(tmpstr, &endstr, 10);
1418 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1419 endstr[0] != ',' && endstr[0] != '\0')
1420 errx(1, "%s: Bad value notation (%s)",
1421 argv[i], argv[i + 2]);
1422 if (tmpstr == endstr) {
1423 tmpstr++;
1424 continue;
1425 }
1426 if (lval < 0)
1427 errx(1, "%s: Bad value notation (%s)",
1428 argv[i], argv[i + 2]);
1429 byte = lval / 8;
1430 if (byte >= strl) {
1431 if ((str = recallocarray(str, strl,
1432 byte + 1, 1)) == NULL((void *)0))
1433 err(1, "malloc");
1434 strl = byte + 1;
1435 }
1436 str[byte] |= 0x80 >> (lval % 8);
1437 tmpstr = endstr + 1;
1438 } while (endstr[0] != '\0');
1439 /*
1440 * RFC3416 Section 2.5
1441 * A BITS value is encoded as an OCTET STRING
1442 */
1443 goto pastestring;
1444 case 'c':
1445 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1446 &errstr);
1447 if (errstr != NULL((void *)0))
1448 errx(1, "%s: Bad value notation (%s)", argv[i],
1449 argv[i + 2]);
1450 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1451 &oid, lval, BER_CLASS_APPLICATION0x1,
1452 SNMP_T_COUNTER32)) == NULL((void *)0))
1453 err(1, "ober_printf_elements");
1454 break;
1455 case 'd':
1456 /* String always shrinks */
1457 if ((str = malloc(strlen(argv[i + 2]))) == NULL((void *)0))
1458 err(1, "malloc");
1459 tmpstr = argv[i + 2];
1460 strl = 0;
1461 do {
1462 lval = strtoll(tmpstr, &endstr, 10);
1463 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1464 endstr[0] != '\0')
1465 errx(1, "%s: Bad value notation (%s)",
1466 argv[i], argv[i + 2]);
1467 if (tmpstr == endstr) {
1468 tmpstr++;
1469 continue;
1470 }
1471 if (lval < 0 || lval > 0xff)
1472 errx(1, "%s: Bad value notation (%s)",
1473 argv[i], argv[i + 2]);
1474 str[strl++] = (unsigned char) lval;
1475 tmpstr = endstr + 1;
1476 } while (endstr[0] != '\0');
1477 goto pastestring;
1478 case 'i':
1479 lval = strtonum(argv[i + 2], INT32_MIN(-0x7fffffff - 1), INT32_MAX0x7fffffff,
1480 &errstr);
1481 if (errstr != NULL((void *)0))
1482 errx(1, "%s: Bad value notation (%s)", argv[i],
1483 argv[i + 2]);
1484 if ((varbind = ober_printf_elements(varbind, "{Oi}",
1485 &oid, lval)) == NULL((void *)0))
1486 err(1, "ober_printf_elements");
1487 break;
1488 case 'n':
1489 if ((varbind = ober_printf_elements(varbind, "{O0}",
1490 &oid)) == NULL((void *)0))
1491 err(1, "ober_printf_elements");
1492 break;
1493 case 'o':
1494 if (smi_string2oid(argv[i + 2], &oidval) == -1)
1495 errx(1, "%s: Unknown Object Identifier (Sub-id "
1496 "not found: (top) -> %s)", argv[i],
1497 argv[i + 2]);
1498 if ((varbind = ober_printf_elements(varbind, "{OO}",
1499 &oid, &oidval)) == NULL((void *)0))
1500 err(1, "ober_printf_elements");
1501 break;
1502 case 's':
1503 if ((str = strdup(argv[i + 2])) == NULL((void *)0))
1504 err(1, NULL((void *)0));
1505 strl = strlen(argv[i + 2]);
1506pastestring:
1507 if ((varbind = ober_printf_elements(varbind, "{Ox}",
1508 &oid, str, strl)) == NULL((void *)0))
1509 err(1, "ober_printf_elements");
1510 free(str);
1511 break;
1512 case 't':
1513 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1514 &errstr);
1515 if (errstr != NULL((void *)0))
1516 errx(1, "%s: Bad value notation (%s)", argv[i],
1517 argv[i + 2]);
1518 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1519 &oid, lval, BER_CLASS_APPLICATION0x1,
1520 SNMP_T_TIMETICKS)) == NULL((void *)0))
1521 err(1, "ober_printf_elements");
1522 break;
1523 case 'u':
1524 lval = strtonum(argv[i + 2], 0, UINT32_MAX0xffffffffU,
1525 &errstr);
1526 if (errstr != NULL((void *)0))
1527 errx(1, "%s: Bad value notation (%s)", argv[i],
1528 argv[i + 2]);
1529 if ((varbind = ober_printf_elements(varbind, "{Oit}",
1530 &oid, lval, BER_CLASS_APPLICATION0x1,
1531 SNMP_T_GAUGE32)) == NULL((void *)0))
1532 err(1, "ober_printf_elements");
1533 break;
1534 case 'x':
1535 /* String always shrinks */
1536 if ((str = malloc(strlen(argv[i + 2]))) == NULL((void *)0))
1537 err(1, "malloc");
1538 tmpstr = argv[i + 2];
1539 strl = 0;
1540 do {
1541 lval = strtoll(tmpstr, &endstr, 16);
1542 if (endstr[0] != ' ' && endstr[0] != '\t' &&
1543 endstr[0] != '\0')
1544 errx(1, "%s: Bad value notation (%s)",
1545 argv[i], argv[i + 2]);
1546 if (tmpstr == endstr) {
1547 tmpstr++;
1548 continue;
1549 }
1550 if (lval < 0 || lval > 0xff)
1551 errx(1, "%s: Bad value notation (%s)",
1552 argv[i], argv[i + 2]);
1553 str[strl++] = (unsigned char) lval;
1554 tmpstr = endstr + 1;
1555 } while (endstr[0] != '\0');
1556 goto pastestring;
1557 default:
1558 usage();
1559 }
1560 if (vblist == NULL((void *)0))
1561 vblist = varbind;
1562 }
1563
1564 return vblist;
1565}
1566
1567__dead__attribute__((__noreturn__)) void
1568usage(void)
1569{
1570 size_t i;
1571
1572 if (snmp_app != NULL((void *)0)) {
1573 fprintf(stderr(&__sF[2]), "usage: snmp %s%s%s\n",
1574 snmp_app->name,
1575 snmp_app->usecommonopt ?
1576 " [-A authpass] [-a digest] [-c community] [-e secengineid]\n"
1577 " [-E ctxengineid] [-K localpriv] [-k localauth] [-l seclevel]\n"
1578 " [-n ctxname] [-O afnqvxSQ] [-r retries] [-t timeout] [-u user]\n"
1579 " [-v version] [-X privpass] [-x cipher] [-Z boots,time]\n"
1580 " " : "",
1581 snmp_app->usage == NULL((void *)0) ? " " : snmp_app->usage);
1582 exit(1);
1583 }
1584 for (i = 0; i < (sizeof(snmp_apps)/sizeof(*snmp_apps)); i++) {
1585 if (i == 0)
1586 fprintf(stderr(&__sF[2]), "usage: ");
1587 else
1588 fprintf(stderr(&__sF[2]), " ");
1589 fprintf(stderr(&__sF[2]), "snmp %s%s %s\n",
1590 snmp_apps[i].name,
1591 snmp_apps[i].usecommonopt ?
1592 " [options]" : "",
1593 snmp_apps[i].usage ? snmp_apps[i].usage : "");
1594 }
1595 exit(1);
1596}