Annotation of src/usr.bin/snmp/snmpc.c, Revision 1.1
1.1 ! martijn 1: /* $OpenBSD$ */
! 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:
! 27: #include <ber.h>
! 28: #include <err.h>
! 29: #include <errno.h>
! 30: #include <netdb.h>
! 31: #include <poll.h>
! 32: #include <stdio.h>
! 33: #include <stdlib.h>
! 34: #include <stdint.h>
! 35: #include <string.h>
! 36: #include <time.h>
! 37: #include <unistd.h>
! 38:
! 39: #include "smi.h"
! 40: #include "snmp.h"
! 41:
! 42: #define GETOPT_COMMON "c:r:t:v:O:"
! 43:
! 44: int snmpc_get(int, char *[]);
! 45: int snmpc_walk(int, char *[]);
! 46: int snmpc_trap(int, char *[]);
! 47: int snmpc_mibtree(int, char *[]);
! 48: int snmpc_parseagent(char *, char *);
! 49: int snmpc_print(struct ber_element *);
! 50: __dead void snmpc_printerror(enum snmp_error, char *);
! 51: void usage(void);
! 52:
! 53: struct snmp_app {
! 54: const char *name;
! 55: const int usecommonopt;
! 56: const char *optstring;
! 57: const char *usage;
! 58: int (*exec)(int, char *[]);
! 59: };
! 60:
! 61: struct snmp_app snmp_apps[] = {
! 62: {"get", 1, NULL, "agent oid ...", snmpc_get},
! 63: {"getnext", 1, NULL, "agent oid ...", snmpc_get},
! 64: {"walk", 1, "C:", "[-C cIipt] [-C E OID] agent [oid]", snmpc_walk},
! 65: {"bulkget", 1, "C:", "[-C n<nonrep>r<maxrep>] agent oid ...", snmpc_get},
! 66: {"bulkwalk", 1, "C:", "[-C cipn<nonrep>r<maxrep>] agent [oid]", snmpc_walk},
! 67: { "trap", 1, NULL, "agent uptime oid [oid type value] ...", snmpc_trap},
! 68: {"mibtree", 0, "O:", "[-O fnS]", snmpc_mibtree}
! 69: };
! 70: struct snmp_app *snmp_app = NULL;
! 71:
! 72: char *community = "public";
! 73: char *mib = "mib_2";
! 74: int retries = 5;
! 75: int timeout = 1;
! 76: int version = SNMP_V2C;
! 77: int print_equals = 1;
! 78: int print_varbind_only = 0;
! 79: int print_summary = 0;
! 80: int print_time = 0;
! 81: int walk_check_increase = 1;
! 82: int walk_fallback_oid = 1;
! 83: int walk_include_oid = 0;
! 84: int smi_print_hint = 1;
! 85: int non_repeaters = 0;
! 86: int max_repetitions = 10;
! 87: struct ber_oid walk_end = {{0}, 0};
! 88: enum smi_oid_lookup oid_lookup = smi_oidl_short;
! 89: enum smi_output_string output_string = smi_os_default;
! 90:
! 91: int
! 92: main(int argc, char *argv[])
! 93: {
! 94: char optstr[BUFSIZ];
! 95: const char *errstr;
! 96: char *strtolp;
! 97: int ch;
! 98: size_t i;
! 99:
! 100: if (pledge("stdio inet dns", NULL) == -1)
! 101: err(1, "pledge");
! 102:
! 103: if (argc <= 1)
! 104: usage();
! 105:
! 106: for (i = 0; i < sizeof(snmp_apps)/sizeof(*snmp_apps); i++) {
! 107: if (strcmp(snmp_apps[i].name, argv[1]) == 0) {
! 108: snmp_app = &snmp_apps[i];
! 109: if (snmp_app->optstring != NULL) {
! 110: if (strlcpy(optstr, snmp_app->optstring,
! 111: sizeof(optstr)) > sizeof(optstr))
! 112: errx(1, "strlcat");
! 113: }
! 114: break;
! 115: }
! 116: }
! 117: if (snmp_app == NULL)
! 118: usage();
! 119:
! 120: if (snmp_app->usecommonopt) {
! 121: if (strlcat(optstr, GETOPT_COMMON, sizeof(optstr)) >
! 122: sizeof(optstr))
! 123: errx(1, "strlcpy");
! 124: }
! 125:
! 126: argc--;
! 127: argv++;
! 128:
! 129: smi_init();
! 130:
! 131: while ((ch = getopt(argc, argv, optstr)) != -1) {
! 132: switch (ch) {
! 133: case 'c':
! 134: community = optarg;
! 135: break;
! 136: case 'r':
! 137: if ((retries = strtonum(optarg, 0, INT_MAX,
! 138: &errstr)) == 0) {
! 139: if (errstr != NULL)
! 140: errx(1, "-r: %s argument", errstr);
! 141: }
! 142: break;
! 143: case 't':
! 144: if ((timeout = strtonum(optarg, 1, INT_MAX,
! 145: &errstr)) == 0) {
! 146: if (errstr != NULL)
! 147: errx(1, "-t: %s argument", errstr);
! 148: }
! 149: break;
! 150: case 'v':
! 151: if (strcmp(optarg, "1") == 0)
! 152: version = SNMP_V1;
! 153: else if (strcmp(optarg, "2c") == 0)
! 154: version = SNMP_V2C;
! 155: else
! 156: errc(1, EINVAL, "-v");
! 157: break;
! 158: case 'C':
! 159: for (i = 0; i < strlen(optarg); i++) {
! 160: switch (optarg[i]) {
! 161: case 'c':
! 162: if (strcmp(snmp_app->name, "walk") &&
! 163: strcmp(snmp_app->name, "bulkwalk"))
! 164: usage();
! 165: walk_check_increase = 0;
! 166: break;
! 167: case 'i':
! 168: if (strcmp(snmp_app->name, "walk") &&
! 169: strcmp(snmp_app->name, "bulkwalk"))
! 170: usage();
! 171: walk_include_oid = 1;
! 172: break;
! 173: case 'n':
! 174: if (strcmp(snmp_app->name, "bulkget") &&
! 175: strcmp(snmp_app->name, "bulkwalk"))
! 176: usage();
! 177: errno = 0;
! 178: non_repeaters = strtol(&optarg[i + 1],
! 179: &strtolp, 10);
! 180: if (non_repeaters < 0 ||
! 181: errno == ERANGE) {
! 182: if (non_repeaters < 0)
! 183: errx(1, "%s%s",
! 184: "-Cn: too small ",
! 185: "argument");
! 186: else
! 187: errx(1, "%s%s",
! 188: "-Cn: too large",
! 189: "argument");
! 190: } else if (&optarg[i + 1] == strtolp)
! 191: errx(1, "-Cn invalid argument");
! 192: i = strtolp - optarg - 1;
! 193: break;
! 194: case 'p':
! 195: if (strcmp(snmp_app->name, "walk") &&
! 196: strcmp(snmp_app->name, "bulkwalk"))
! 197: usage();
! 198: print_summary = 1;
! 199: break;
! 200: case 'r':
! 201: if (strcmp(snmp_app->name, "bulkget") &&
! 202: strcmp(snmp_app->name, "bulkwalk"))
! 203: usage();
! 204: errno = 0;
! 205: max_repetitions = strtol(&optarg[i + 1],
! 206: &strtolp, 10);
! 207: if (max_repetitions < 0 ||
! 208: errno == ERANGE) {
! 209: if (max_repetitions < 0)
! 210: errx(1, "%s%s",
! 211: "-Cr: too small ",
! 212: "argument");
! 213: else
! 214: errx(1, "%s%s",
! 215: "-Cr: too large",
! 216: "argument");
! 217: } else if (&optarg[i + 1] == strtolp)
! 218: errx(1, "-Cr invalid argument");
! 219: i = strtolp - optarg - 1;
! 220: break;
! 221: case 't':
! 222: if (strcmp(snmp_app->name, "walk"))
! 223: usage();
! 224: print_time = 1;
! 225: break;
! 226: case 'E':
! 227: if (strcmp(snmp_app->name, "walk"))
! 228: usage();
! 229: if (smi_string2oid(argv[optind],
! 230: &walk_end) != 0)
! 231: errx(1, "%s: %s",
! 232: "Unknown Object Identifier",
! 233: argv[optind]);
! 234: optind++;
! 235: continue;
! 236: case 'I':
! 237: if (strcmp(snmp_app->name, "walk"))
! 238: usage();
! 239: walk_fallback_oid = 0;
! 240: break;
! 241: default:
! 242: usage();
! 243: }
! 244: if (optarg[i] == 'E')
! 245: break;
! 246: }
! 247: break;
! 248: case 'O':
! 249: for (i = 0; i < strlen(optarg); i++) {
! 250: if (strcmp(snmp_app->name, "mibtree") == 0 &&
! 251: optarg[i] != 'f' && optarg[i] != 'n' &&
! 252: optarg[i] != 'S')
! 253: usage();
! 254: switch (optarg[i]) {
! 255: case 'a':
! 256: output_string = smi_os_ascii;
! 257: break;
! 258: case 'f':
! 259: oid_lookup = smi_oidl_full;
! 260: break;
! 261: case 'n':
! 262: oid_lookup = smi_oidl_numeric;
! 263: break;
! 264: case 'q':
! 265: print_equals = 0;
! 266: smi_print_hint = 0;
! 267: break;
! 268: case 'v':
! 269: print_varbind_only = 1;
! 270: break;
! 271: case 'x':
! 272: output_string = smi_os_hex;
! 273: break;
! 274: case 'S':
! 275: oid_lookup = smi_oidl_short;
! 276: break;
! 277: case 'Q':
! 278: smi_print_hint = 0;
! 279: break;
! 280: default:
! 281: usage();
! 282: }
! 283: }
! 284: break;
! 285: default:
! 286: usage();
! 287: }
! 288: }
! 289: argc -= optind;
! 290: argv += optind;
! 291:
! 292: return snmp_app->exec(argc, argv);
! 293: }
! 294:
! 295: int
! 296: snmpc_get(int argc, char *argv[])
! 297: {
! 298: struct ber_oid *oid;
! 299: struct ber_element *pdu, *varbind;
! 300: struct snmp_agent *agent;
! 301: int errorstatus, errorindex;
! 302: int i;
! 303:
! 304: if (argc < 2)
! 305: usage();
! 306:
! 307: agent = snmp_connect_v12(snmpc_parseagent(argv[0], "161"), version,
! 308: community);
! 309: if (agent == NULL)
! 310: err(1, "%s", snmp_app->name);
! 311: agent->timeout = timeout;
! 312: agent->retries = retries;
! 313:
! 314: if (pledge("stdio", NULL) == -1)
! 315: err(1, "pledge");
! 316: argc--;
! 317: argv++;
! 318:
! 319: oid = reallocarray(NULL, argc, sizeof(*oid));
! 320: for (i = 0; i < argc; i++) {
! 321: if (smi_string2oid(argv[i], &oid[i]) == -1)
! 322: errx(1, "%s: Unknown object identifier", argv[0]);
! 323: }
! 324: if (strcmp(snmp_app->name, "getnext") == 0) {
! 325: if ((pdu = snmp_getnext(agent, oid, argc)) == NULL)
! 326: err(1, "getnext");
! 327: } else if (strcmp(snmp_app->name, "bulkget") == 0) {
! 328: if (version < SNMP_V2C)
! 329: errx(1, "Cannot send V2 PDU on V1 session");
! 330: if (non_repeaters > argc)
! 331: errx(1, "need more objects than -Cn<num>");
! 332: if ((pdu = snmp_getbulk(agent, oid, argc, non_repeaters,
! 333: max_repetitions)) == NULL)
! 334: err(1, "bulkget");
! 335: } else {
! 336: if ((pdu = snmp_get(agent, oid, argc)) == NULL)
! 337: err(1, "get");
! 338: }
! 339:
! 340: (void) ber_scanf_elements(pdu, "{Sdd{e", &errorstatus, &errorindex,
! 341: &varbind);
! 342: if (errorstatus != 0)
! 343: snmpc_printerror((enum snmp_error) errorstatus,
! 344: argv[errorindex]);
! 345:
! 346: for (; varbind != NULL; varbind = varbind->be_next) {
! 347: if (!snmpc_print(varbind))
! 348: err(1, "Can't print response");
! 349: }
! 350: ber_free_elements(pdu);
! 351: snmp_free_agent(agent);
! 352: return 0;
! 353: }
! 354:
! 355: int
! 356: snmpc_walk(int argc, char *argv[])
! 357: {
! 358: struct ber_oid oid, loid, noid;
! 359: struct ber_element *pdu, *varbind, *value;
! 360: struct timespec start, finish;
! 361: struct snmp_agent *agent;
! 362: const char *oids;
! 363: char oidstr[SNMP_MAX_OID_STRLEN];
! 364: int n = 0, prev_cmp;
! 365: int errorstatus, errorindex;
! 366:
! 367: if (strcmp(snmp_app->name, "bulkwalk") == 0 && version < SNMP_V2C)
! 368: errx(1, "Cannot send V2 PDU on V1 session");
! 369: if (argc < 1 || argc > 2)
! 370: usage();
! 371: oids = argc == 1 ? mib : argv[1];
! 372:
! 373: agent = snmp_connect_v12(snmpc_parseagent(argv[0], "161"), version, community);
! 374: if (agent == NULL)
! 375: err(1, "%s", snmp_app->name);
! 376: agent->timeout = timeout;
! 377: agent->retries = retries;
! 378: if (pledge("stdio", NULL) == -1)
! 379: err(1, "pledge");
! 380:
! 381: if (smi_string2oid(oids, &oid) == -1)
! 382: errx(1, "%s: Unknown object identifier", oids);
! 383: bcopy(&oid, &noid, sizeof(noid));
! 384: if (print_time)
! 385: clock_gettime(CLOCK_MONOTONIC, &start);
! 386:
! 387: if (walk_include_oid) {
! 388: if ((pdu = snmp_get(agent, &oid, 1)) == NULL)
! 389: err(1, "%s", snmp_app->name);
! 390:
! 391: (void) ber_scanf_elements(pdu, "{Sdd{e", &errorstatus,
! 392: &errorindex, &varbind);
! 393: if (errorstatus != 0)
! 394: snmpc_printerror((enum snmp_error) errorstatus,
! 395: argv[errorindex]);
! 396:
! 397: if (!snmpc_print(varbind))
! 398: err(1, "Can't print response");
! 399: ber_free_element(pdu);
! 400: n++;
! 401: }
! 402: while (1) {
! 403: bcopy(&noid, &loid, sizeof(loid));
! 404: if (strcmp(snmp_app->name, "bulkwalk") == 0) {
! 405: if ((pdu = snmp_getbulk(agent, &noid, 1,
! 406: non_repeaters, max_repetitions)) == NULL)
! 407: err(1, "bulkwalk");
! 408: } else {
! 409: if ((pdu = snmp_getnext(agent, &noid, 1)) == NULL)
! 410: err(1, "walk");
! 411: }
! 412:
! 413: (void) ber_scanf_elements(pdu, "{Sdd{e", &errorstatus,
! 414: &errorindex, &varbind);
! 415: if (errorstatus != 0) {
! 416: smi_oid2string(&noid, oidstr, sizeof(oidstr),
! 417: oid_lookup);
! 418: snmpc_printerror((enum snmp_error) errorstatus, oidstr);
! 419: }
! 420:
! 421: for (;varbind != NULL; varbind = varbind->be_next) {
! 422: (void) ber_scanf_elements(varbind, "{oe}", &noid,
! 423: &value);
! 424: if (value->be_class == BER_CLASS_CONTEXT &&
! 425: value->be_type == BER_TYPE_EOC)
! 426: break;
! 427: prev_cmp = ber_oid_cmp(&loid, &noid);
! 428: if (walk_check_increase && prev_cmp == -1)
! 429: errx(1, "OID not increasing");
! 430: if (prev_cmp == 0 || ber_oid_cmp(&oid, &noid) != 2)
! 431: break;
! 432: if (walk_end.bo_n != 0 &&
! 433: ber_oid_cmp(&walk_end, &noid) != -1)
! 434: break;
! 435:
! 436: if (!snmpc_print(varbind))
! 437: err(1, "Can't print response");
! 438: n++;
! 439: }
! 440: ber_free_elements(pdu);
! 441: if (varbind != NULL)
! 442: break;
! 443: }
! 444: if (walk_fallback_oid && n == 0) {
! 445: if ((pdu = snmp_get(agent, &oid, 1)) == NULL)
! 446: err(1, "%s", snmp_app->name);
! 447:
! 448: (void) ber_scanf_elements(pdu, "{Sdd{e", &errorstatus,
! 449: &errorindex, &varbind);
! 450: if (errorstatus != 0)
! 451: snmpc_printerror((enum snmp_error) errorstatus,
! 452: argv[errorindex]);
! 453:
! 454: if (!snmpc_print(varbind))
! 455: err(1, "Can't print response");
! 456: ber_free_element(pdu);
! 457: n++;
! 458: }
! 459: if (print_time)
! 460: clock_gettime(CLOCK_MONOTONIC, &finish);
! 461: if (print_summary)
! 462: printf("Variables found: %d\n", n);
! 463: if (print_time) {
! 464: if ((finish.tv_nsec -= start.tv_nsec) < 0) {
! 465: finish.tv_sec -= 1;
! 466: finish.tv_nsec += 1000000000;
! 467: }
! 468: finish.tv_sec -= start.tv_sec;
! 469: fprintf(stderr, "Total traversal time: %lld.%09ld seconds\n",
! 470: finish.tv_sec, finish.tv_nsec);
! 471: }
! 472: snmp_free_agent(agent);
! 473: return 0;
! 474: }
! 475:
! 476: int
! 477: snmpc_trap(int argc, char *argv[])
! 478: {
! 479: struct snmp_agent *agent;
! 480: struct timespec ts;
! 481: struct ber_oid trapoid, oid, oidval;
! 482: struct in_addr addr4;
! 483: char *addr = (char *)&addr4;
! 484: char *str = NULL, *tmpstr, *endstr;
! 485: const char *errstr = NULL;
! 486: struct ber_element *varbind = NULL, *pdu = NULL;
! 487: long long lval;
! 488: int i, ret;
! 489: size_t strl, byte;
! 490:
! 491: if (argc < 3 || argc % 3 != 0)
! 492: usage();
! 493: if (version == SNMP_V1)
! 494: errx(1, "trap is not supported for snmp v1");
! 495:
! 496: agent = snmp_connect_v12(snmpc_parseagent(argv[0], "162"),
! 497: version, community);
! 498: if (agent == NULL)
! 499: err(1, "%s", snmp_app->name);
! 500:
! 501: if (pledge("stdio", NULL) == -1)
! 502: err(1, "pledge");
! 503:
! 504: if (argv[1][0] == '\0') {
! 505: if (clock_gettime(CLOCK_UPTIME, &ts) == -1)
! 506: err(1, "clock_gettime");
! 507: } else {
! 508: lval = strtonum(argv[1], 0, LLONG_MAX, &errstr);
! 509: if (errstr != NULL)
! 510: errx(1, "Bad value notation (%s)", argv[1]);
! 511: ts.tv_sec = lval / 100;
! 512: ts.tv_nsec = (lval % 100) * 10000000;
! 513: }
! 514: if (smi_string2oid(argv[2], &trapoid) == -1)
! 515: errx(1, "Invalid oid: %s\n", argv[2]);
! 516:
! 517: argc -= 3;
! 518: argv += 3;
! 519: for (i = 0; i < argc; i += 3) {
! 520: if (smi_string2oid(argv[i], &oid) == -1)
! 521: errx(1, "Invalid oid: %s\n", argv[i]);
! 522: switch (argv[i + 1][0]) {
! 523: case 'a':
! 524: ret = inet_pton(AF_INET, argv[i + 2], &addr4);
! 525: if (ret == -1)
! 526: err(1, "inet_pton");
! 527: if (ret == 0)
! 528: errx(1, "%s: Bad value notation (%s)", argv[i],
! 529: argv[i + 2]);
! 530: if ((varbind = ber_printf_elements(varbind, "{Oxt}",
! 531: &oid, addr, sizeof(addr4), BER_CLASS_APPLICATION,
! 532: SNMP_T_IPADDR)) == NULL)
! 533: err(1, "ber_printf_elements");
! 534: break;
! 535: case 'b':
! 536: tmpstr = argv[i + 2];
! 537: strl = 0;
! 538: do {
! 539: lval = strtoll(tmpstr, &endstr, 10);
! 540: if (endstr[0] != ' ' && endstr[0] != '\t' &&
! 541: endstr[0] != ',' && endstr[0] != '\0')
! 542: errx(1, "%s: Bad value notation (%s)",
! 543: argv[i], argv[i + 2]);
! 544: if (tmpstr == endstr) {
! 545: tmpstr++;
! 546: continue;
! 547: }
! 548: if (lval < 0)
! 549: errx(1, "%s: Bad value notation (%s)",
! 550: argv[i], argv[i + 2]);
! 551: byte = lval / 8;
! 552: if (byte >= strl) {
! 553: if ((str = recallocarray(str, strl,
! 554: byte + 1, 1)) == NULL)
! 555: err(1, NULL);
! 556: strl = byte + 1;
! 557: }
! 558: str[byte] |= 0x80 >> (lval % 8);
! 559: tmpstr = endstr + 1;
! 560: } while (endstr[0] != '\0');
! 561: /*
! 562: * RFC3416 Section 2.5
! 563: * A BITS value is encoded as an OCTET STRING
! 564: */
! 565: goto pastestring;
! 566: case 'c':
! 567: lval = strtonum(argv[i + 2], INT32_MIN, INT32_MAX,
! 568: &errstr);
! 569: if (errstr != NULL)
! 570: errx(1, "%s: Bad value notation (%s)", argv[i],
! 571: argv[i + 2]);
! 572: if ((varbind = ber_printf_elements(varbind, "{Oit}",
! 573: &oid, lval, BER_CLASS_APPLICATION,
! 574: SNMP_T_COUNTER32)) == NULL)
! 575: err(1, "ber_printf_elements");
! 576: break;
! 577: case 'd':
! 578: /* String always shrinks */
! 579: if ((str = malloc(strlen(argv[i + 2]))) == NULL)
! 580: err(1, NULL);
! 581: tmpstr = argv[i + 2];
! 582: strl = 0;
! 583: do {
! 584: lval = strtoll(tmpstr, &endstr, 10);
! 585: if (endstr[0] != ' ' && endstr[0] != '\t' &&
! 586: endstr[0] != '\0')
! 587: errx(1, "%s: Bad value notation (%s)",
! 588: argv[i], argv[i + 2]);
! 589: if (tmpstr == endstr) {
! 590: tmpstr++;
! 591: continue;
! 592: }
! 593: if (lval < 0 || lval > 0xff)
! 594: errx(1, "%s: Bad value notation (%s)",
! 595: argv[i], argv[i + 2]);
! 596: str[strl++] = (unsigned char) lval;
! 597: tmpstr = endstr + 1;
! 598: } while (endstr[0] != '\0');
! 599: goto pastestring;
! 600: case 'u':
! 601: case 'i':
! 602: lval = strtonum(argv[i + 2], LLONG_MIN, LLONG_MAX,
! 603: &errstr);
! 604: if (errstr != NULL)
! 605: errx(1, "%s: Bad value notation (%s)", argv[i],
! 606: argv[i + 2]);
! 607: if ((varbind = ber_printf_elements(varbind, "{Oi}",
! 608: &oid, lval)) == NULL)
! 609: err(1, "ber_printf_elements");
! 610: break;
! 611: case 'n':
! 612: if ((varbind = ber_printf_elements(varbind, "{O0}",
! 613: &oid)) == NULL)
! 614: err(1, "ber_printf_elements");
! 615: break;
! 616: case 'o':
! 617: if (smi_string2oid(argv[i + 2], &oidval) == -1)
! 618: errx(1, "%s: Unknown Object Identifier (Sub-id "
! 619: "not found: (top) -> %s)", argv[i],
! 620: argv[i + 2]);
! 621: if ((varbind = ber_printf_elements(varbind, "{OO}",
! 622: &oid, &oidval)) == NULL)
! 623: err(1, "ber_printf_elements");
! 624: break;
! 625: case 's':
! 626: if ((str = strdup(argv[i + 2])) == NULL)
! 627: err(1, NULL);
! 628: strl = strlen(argv[i + 2]);
! 629: pastestring:
! 630: if ((varbind = ber_printf_elements(varbind, "{Ox}",
! 631: &oid, str, strl)) == NULL)
! 632: err(1, "ber_printf_elements");
! 633: free(str);
! 634: break;
! 635: case 't':
! 636: lval = strtonum(argv[i + 2], LLONG_MIN, LLONG_MAX,
! 637: &errstr);
! 638: if (errstr != NULL)
! 639: errx(1, "%s: Bad value notation (%s)", argv[i],
! 640: argv[i + 2]);
! 641: if ((varbind = ber_printf_elements(varbind, "{Oit}",
! 642: &oid, lval, BER_CLASS_APPLICATION,
! 643: SNMP_T_TIMETICKS)) == NULL)
! 644: err(1, "ber_printf_elements");
! 645: break;
! 646: case 'x':
! 647: /* String always shrinks */
! 648: if ((str = malloc(strlen(argv[i + 2]))) == NULL)
! 649: err(1, NULL);
! 650: tmpstr = argv[i + 2];
! 651: strl = 0;
! 652: do {
! 653: lval = strtoll(tmpstr, &endstr, 16);
! 654: if (endstr[0] != ' ' && endstr[0] != '\t' &&
! 655: endstr[0] != '\0')
! 656: errx(1, "%s: Bad value notation (%s)",
! 657: argv[i], argv[i + 2]);
! 658: if (tmpstr == endstr) {
! 659: tmpstr++;
! 660: continue;
! 661: }
! 662: if (lval < 0 || lval > 0xff)
! 663: errx(1, "%s: Bad value notation (%s)",
! 664: argv[i], argv[i + 2]);
! 665: str[strl++] = (unsigned char) lval;
! 666: tmpstr = endstr + 1;
! 667: } while (endstr[0] != '\0');
! 668: goto pastestring;
! 669: default:
! 670: usage();
! 671: }
! 672: if (pdu == NULL)
! 673: pdu = varbind;
! 674: }
! 675:
! 676: snmp_trap(agent, &ts, &trapoid, pdu);
! 677:
! 678: return 0;
! 679: }
! 680:
! 681: int
! 682: snmpc_mibtree(int argc, char *argv[])
! 683: {
! 684: struct oid *oid;
! 685: char buf[BUFSIZ];
! 686:
! 687: for (oid = NULL; (oid = smi_foreach(oid, 0)) != NULL;) {
! 688: smi_oid2string(&oid->o_id, buf, sizeof(buf), oid_lookup);
! 689: printf("%s\n", buf);
! 690: }
! 691: return 0;
! 692: }
! 693:
! 694: int
! 695: snmpc_print(struct ber_element *elm)
! 696: {
! 697: struct ber_oid oid;
! 698: char oids[SNMP_MAX_OID_STRLEN];
! 699: char *value;
! 700:
! 701: elm = elm->be_sub;
! 702: if (ber_get_oid(elm, &oid) != 0) {
! 703: errno = EINVAL;
! 704: return 0;
! 705: }
! 706:
! 707: elm = elm->be_next;
! 708: value = smi_print_element(elm, smi_print_hint, output_string, oid_lookup);
! 709: if (value == NULL)
! 710: return 0;
! 711:
! 712: if (print_varbind_only)
! 713: printf("%s\n", value);
! 714: else if (print_equals) {
! 715: smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
! 716: printf("%s = %s\n", oids, value);
! 717: } else {
! 718: smi_oid2string(&oid, oids, sizeof(oids), oid_lookup);
! 719: printf("%s %s\n", oids, value);
! 720: }
! 721: free(value);
! 722:
! 723: return 1;
! 724: }
! 725:
! 726: __dead void
! 727: snmpc_printerror(enum snmp_error error, char *oid)
! 728: {
! 729: switch (error)
! 730: {
! 731: case SNMP_ERROR_NONE:
! 732: errx(1, "No error, how did I get here?");
! 733: case SNMP_ERROR_TOOBIG:
! 734: errx(1, "Can't parse oid %s: Response too big", oid);
! 735: case SNMP_ERROR_NOSUCHNAME:
! 736: errx(1, "Can't parse oid %s: No such object", oid);
! 737: case SNMP_ERROR_BADVALUE:
! 738: errx(1, "Can't parse oid %s: Bad value", oid);
! 739: case SNMP_ERROR_READONLY:
! 740: errx(1, "Can't parse oid %s: Read only", oid);
! 741: case SNMP_ERROR_GENERR:
! 742: errx(1, "Can't parse oid %s: Generic error", oid);
! 743: case SNMP_ERROR_NOACCESS:
! 744: errx(1, "Can't parse oid %s: Access denied", oid);
! 745: case SNMP_ERROR_WRONGTYPE:
! 746: errx(1, "Can't parse oid %s: Wrong type", oid);
! 747: case SNMP_ERROR_WRONGLENGTH:
! 748: errx(1, "Can't parse oid %s: Wrong length", oid);
! 749: case SNMP_ERROR_WRONGENC:
! 750: errx(1, "Can't parse oid %s: Wrong encoding", oid);
! 751: case SNMP_ERROR_WRONGVALUE:
! 752: errx(1, "Can't parse oid %s: Wrong value", oid);
! 753: case SNMP_ERROR_NOCREATION:
! 754: errx(1, "Can't parse oid %s: Can't be created", oid);
! 755: case SNMP_ERROR_INCONVALUE:
! 756: errx(1, "Can't parse oid %s: Inconsistent value", oid);
! 757: case SNMP_ERROR_RESUNAVAIL:
! 758: errx(1, "Can't parse oid %s: Resource unavailable", oid);
! 759: case SNMP_ERROR_COMMITFAILED:
! 760: errx(1, "Can't parse oid %s: Commit failed", oid);
! 761: case SNMP_ERROR_UNDOFAILED:
! 762: errx(1, "Can't parse oid %s: Undo faild", oid);
! 763: case SNMP_ERROR_AUTHERROR:
! 764: errx(1, "Can't parse oid %s: Authorization error", oid);
! 765: case SNMP_ERROR_NOTWRITABLE:
! 766: errx(1, "Can't parse oid %s: Not writable", oid);
! 767: case SNMP_ERROR_INCONNAME:
! 768: errx(1, "Can't parse oid %s: Inconsistent name", oid);
! 769: }
! 770: errx(1, "Can't parse oid %s: Unknown error (%d)", oid, error);
! 771: }
! 772:
! 773: int
! 774: snmpc_parseagent(char *agent, char *defaultport)
! 775: {
! 776: struct addrinfo hints, *ai, *ai0 = NULL;
! 777: struct sockaddr_un saddr;
! 778: char *agentdup, *specifier, *hostname, *port = NULL;
! 779: int error;
! 780: int s;
! 781:
! 782: if ((agentdup = specifier = strdup(agent)) == NULL)
! 783: err(1, NULL);
! 784:
! 785: bzero(&hints, sizeof(hints));
! 786: if ((hostname = strchr(specifier, ':')) != NULL) {
! 787: *hostname++ = '\0';
! 788: if (strcasecmp(specifier, "udp") == 0) {
! 789: hints.ai_family = AF_INET;
! 790: hints.ai_socktype = SOCK_DGRAM;
! 791: } else if (strcasecmp(specifier, "tcp") == 0) {
! 792: hints.ai_family = AF_INET;
! 793: hints.ai_socktype = SOCK_STREAM;
! 794: } else if (strcasecmp(specifier, "udp6") == 0 ||
! 795: strcasecmp(specifier, "udpv6") == 0 ||
! 796: strcasecmp(specifier, "udpipv6") == 0) {
! 797: hints.ai_family = AF_INET6;
! 798: hints.ai_socktype = SOCK_DGRAM;
! 799: } else if (strcasecmp(specifier, "tcp6") == 0 ||
! 800: strcasecmp(specifier, "tcpv6") == 0 ||
! 801: strcasecmp(specifier, "tcpipv6") == 0) {
! 802: hints.ai_family = AF_INET6;
! 803: hints.ai_socktype = SOCK_STREAM;
! 804: } else if (strcasecmp(specifier, "unix") == 0) {
! 805: hints.ai_family = AF_UNIX;
! 806: hints.ai_socktype = SOCK_STREAM;
! 807: hints.ai_addr = (struct sockaddr *)&saddr;
! 808: hints.ai_addrlen = sizeof(saddr);
! 809: saddr.sun_len = sizeof(saddr);
! 810: saddr.sun_family = AF_UNIX;
! 811: if (strlcpy(saddr.sun_path, hostname,
! 812: sizeof(saddr.sun_path)) > sizeof(saddr.sun_path))
! 813: errx(1, "Hostname path too long");
! 814: ai = &hints;
! 815: } else {
! 816: port = hostname;
! 817: hostname = specifier;
! 818: specifier = NULL;
! 819: hints.ai_family = AF_INET;
! 820: hints.ai_socktype = SOCK_DGRAM;
! 821: }
! 822: if (port == NULL) {
! 823: if (hints.ai_family == AF_INET) {
! 824: if ((port = strchr(hostname, ':')) != NULL)
! 825: *port++ = '\0';
! 826: } else if (hints.ai_family == AF_INET6) {
! 827: if (hostname[0] == '[') {
! 828: hostname++;
! 829: if ((port = strchr(hostname, ']')) == NULL)
! 830: errx(1, "invalid agent");
! 831: *port++ = '\0';
! 832: if (port[0] == ':')
! 833: *port++ = '\0';
! 834: else
! 835: port = NULL;
! 836: } else {
! 837: if ((port = strrchr(hostname, ':')) == NULL)
! 838: errx(1, "invalid agent");
! 839: *port++ = '\0';
! 840: }
! 841: }
! 842: }
! 843: } else {
! 844: hostname = specifier;
! 845: hints.ai_family = AF_INET;
! 846: hints.ai_socktype = SOCK_DGRAM;
! 847: }
! 848:
! 849: if (hints.ai_family != AF_UNIX) {
! 850: if (port == NULL)
! 851: port = defaultport;
! 852: error = getaddrinfo(hostname, port, &hints, &ai0);
! 853: if (error)
! 854: errx(1, "%s", gai_strerror(error));
! 855: s = -1;
! 856: for (ai = ai0; ai != NULL; ai = ai->ai_next) {
! 857: if ((s = socket(ai->ai_family, ai->ai_socktype,
! 858: ai->ai_protocol)) == -1)
! 859: continue;
! 860: break;
! 861: }
! 862: } else
! 863: s = socket(hints.ai_family, hints.ai_socktype,
! 864: hints.ai_protocol);
! 865: if (s == -1)
! 866: err(1, "socket");
! 867:
! 868: if (connect(s, (struct sockaddr *)ai->ai_addr, ai->ai_addrlen) == -1)
! 869: err(1, "Can't connect to %s", agent);
! 870:
! 871: if (ai0 != NULL)
! 872: freeaddrinfo(ai0);
! 873: free(agentdup);
! 874: return s;
! 875: }
! 876:
! 877: __dead void
! 878: usage(void)
! 879: {
! 880: size_t i;
! 881:
! 882: extern char *__progname;
! 883:
! 884: if (snmp_app != NULL) {
! 885: fprintf(stderr, "usage: %s %s%s%s%s\n",
! 886: __progname, snmp_app->name,
! 887: snmp_app->usecommonopt ?
! 888: " [-c community] [-r retries] [-t timeout] "
! 889: "[-v protocol version] [-O afnqvxSQ]" : "",
! 890: snmp_app->usage == NULL ? "" : " ",
! 891: snmp_app->usage == NULL ? "" : snmp_app->usage);
! 892: exit(1);
! 893: }
! 894: fprintf(stderr, "usage: \n");
! 895: for (i = 0; i < (sizeof(snmp_apps)/sizeof(*snmp_apps)); i++) {
! 896: fprintf(stderr, "%*s %s%s%s%s\n",
! 897: (int) (sizeof("usage:") + strlen(__progname)),
! 898: __progname, snmp_apps[i].name,
! 899: snmp_apps[i].usecommonopt ?
! 900: " [-c community] [-r retries] [-t timeout] "
! 901: "[-v protocol version] [-O afnqvxSQ]" : "",
! 902: snmp_apps[i].usage == NULL ? "" : " ",
! 903: snmp_apps[i].usage == NULL ? "" : snmp_apps[i].usage);
! 904: }
! 905: exit(1);
! 906: }