|
|
1.1 ! root 1: /* snmp.c - SNMP changes for gawk */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/snmp/gawk-2.11/RCS/snmp.c,v 7.2 90/06/06 22:59:38 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/snmp/gawk-2.11/RCS/snmp.c,v 7.2 90/06/06 22:59:38 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: snmp.c,v $ ! 12: * Revision 7.2 90/06/06 22:59:38 mrose ! 13: * update ! 14: * ! 15: * Revision 7.1 90/03/22 16:44:22 mrose ! 16: * touch-up ! 17: * ! 18: * Revision 7.0 90/03/05 10:33:19 mrose ! 19: * *** empty log message *** ! 20: * ! 21: */ ! 22: ! 23: /* ! 24: * NOTICE ! 25: * ! 26: * Acquisition, use, and distribution of this module and related ! 27: * materials are subject to the restrictions of a license agreement. ! 28: * Consult the Preface in the User's Manual for the full terms of ! 29: * this agreement. ! 30: * ! 31: */ ! 32: ! 33: ! 34: #ifdef SNMP ! 35: #include "awk.h" ! 36: #ifdef HUGE ! 37: #undef HUGE ! 38: #endif ! 39: #include <isode/snmp/objects.h> ! 40: #include <isode/pepy/SNMP-types.h> ! 41: #include <isode/dgram.h> ! 42: #include <isode/internet.h> ! 43: #include <isode/tailor.h> ! 44: ! 45: /* DATA */ ! 46: ! 47: int debug = 0; ! 48: ! 49: int snmp_enabled = 1; ! 50: int snmp_scalars_as_arrays = 1; ! 51: char *snmp_file = NULLCP; ! 52: ! 53: static int snmp_id = 0; ! 54: static int snmp_retries = 3; ! 55: static int snmp_timeout = 10; ! 56: ! 57: static char *snmp_agent = NULL; ! 58: static char *snmp_community = NULL; ! 59: ! 60: NODE *AGENT_node, ! 61: *COMMUNITY_node, ! 62: *DIAGNOSTIC_node, ! 63: *ERROR_node, ! 64: *RETRIES_node, ! 65: *TIMEOUT_node; ! 66: NODE *Ndot_string; ! 67: ! 68: static int snmp_fd = NOTOK; ! 69: static struct sockaddr_in in_socket; ! 70: static PS ps = NULLPS; ! 71: ! 72: static struct type_SNMP_Message msgs; ! 73: static struct type_SNMP_PDUs pdus; ! 74: static struct type_SNMP_PDU parms; ! 75: static struct type_SNMP_VarBindList vps; ! 76: static struct type_SNMP_VarBind vs; ! 77: ! 78: ! 79: struct snmp_search { ! 80: struct search s_search; /* must be first entry */ ! 81: ! 82: OT s_parent; ! 83: ! 84: PE s_pe; ! 85: struct type_SNMP_VarBindList *s_bindings; ! 86: ! 87: struct snmp_search *s_prev; ! 88: struct snmp_search *s_next; ! 89: }; ! 90: ! 91: static struct snmp_search *head = NULL; ! 92: static struct snmp_search *tail = NULL; ! 93: ! 94: ! 95: char *snmp_error (), *snmp_variable (); ! 96: ! 97: ! 98: #ifndef SYS5 ! 99: long random (); ! 100: #endif ! 101: ! 102: /* INIT */ ! 103: ! 104: int check_snmp (r, name) ! 105: NODE *r; ! 106: char *name; ! 107: { ! 108: char c; ! 109: register char *cp; ! 110: OT ot; ! 111: static int inited = 0; ! 112: ! 113: if (inited == 0) { ! 114: inited = 1; ! 115: ! 116: snmp_onceonly (); ! 117: } ! 118: ! 119: for (cp = name; is_identchar (*cp); cp++) ! 120: continue; ! 121: if (c = *cp) ! 122: *cp = NULL; ! 123: if ((ot = text2obj (name)) && ot -> ot_syntax) { ! 124: r -> magic = (caddr_t) ot; ! 125: if (ot -> ot_getfnx || snmp_scalars_as_arrays) ! 126: r -> type = Node_var_array; ! 127: } ! 128: *cp = c; ! 129: } ! 130: ! 131: /* */ ! 132: ! 133: int f_integer (), f_octets (), f_display (), f_objectID (), f_null (), ! 134: f_ipaddr (), f_clnpaddr (); ! 135: ! 136: ! 137: static struct pair { ! 138: char *pp_name; ! 139: IFP pp_value; ! 140: } pairs[] = { ! 141: "INTEGER", f_integer, ! 142: "Services", f_integer, ! 143: "OctetString", f_octets, ! 144: "DisplayString", f_display, ! 145: "ObjectID", f_objectID, ! 146: "NULL", f_null, ! 147: "IpAddress", f_ipaddr, ! 148: "NetworkAddress", f_ipaddr, ! 149: "Counter", f_integer, ! 150: "Gauge", f_integer, ! 151: "TimeTicks", f_integer, ! 152: "ClnpAddress", f_clnpaddr, ! 153: ! 154: NULL ! 155: }; ! 156: ! 157: ! 158: static snmp_onceonly () { ! 159: int i; ! 160: register struct pair *pp; ! 161: register struct type_SNMP_Message *msg = &msgs; ! 162: register struct type_SNMP_PDUs *pdu = &pdus; ! 163: register struct type_SNMP_PDU *parm = &parms; ! 164: register struct type_SNMP_VarBindList *vp = &vps; ! 165: register struct type_SNMP_VarBind *v = &vs; ! 166: OS os; ! 167: register OT ot, ! 168: ot2; ! 169: ! 170: Ndot_string = make_string (".", 1); ! 171: Ndot_string -> flags |= PERM; ! 172: ! 173: if (readobjects (snmp_file) == NOTOK) ! 174: fatal ("readobjects: %s", PY_pepy); ! 175: ! 176: /* mark entries that are actually arrays! */ ! 177: for (ot = text2obj ("iso"); ot; ot = ot -> ot_next) { ! 178: if (ot -> ot_syntax ! 179: || (i = strlen (ot -> ot_text)) <= 5 ! 180: || strcmp (ot -> ot_text + i - 5, "Entry")) ! 181: continue; ! 182: for (ot2 = ot -> ot_children; ot2; ot2 = ot2 -> ot_sibling) ! 183: if (ot2 -> ot_children || !ot2 -> ot_syntax) ! 184: break; ! 185: if (ot2) ! 186: continue; ! 187: for (ot2 = ot -> ot_children; ot2; ot2 = ot2 -> ot_sibling) ! 188: ot2 -> ot_getfnx = (IFP) 1; ! 189: } ! 190: ! 191: for (pp = pairs; pp -> pp_name; pp++) ! 192: if ((os = text2syn (pp -> pp_name)) == NULL) ! 193: fatal ("lost syntax for \"%s\"", pp -> pp_name); ! 194: else ! 195: os -> os_decode = pp -> pp_value; ! 196: ! 197: bzero ((char *) msg, sizeof *msg); ! 198: msg -> version = int_SNMP_version_version__1; ! 199: msg -> data = pdu; ! 200: ! 201: bzero ((char *) pdu, sizeof *pdu); ! 202: pdu -> offset = type_SNMP_PDUs_get__request; ! 203: pdu -> un.get__request = parm; ! 204: ! 205: bzero ((char *) parm, sizeof *parm); ! 206: parm -> variable__bindings = vp; ! 207: ! 208: bzero ((char *) vp, sizeof *vp); ! 209: vp -> VarBind = v; ! 210: ! 211: bzero ((char *) v, sizeof *v); ! 212: if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL)) ! 213: == NULLPE) ! 214: fatal ("pe_alloc: out of memory"); ! 215: ! 216: ps_len_strategy = PS_LEN_LONG; ! 217: ! 218: #ifndef SYS5 ! 219: srandom (getpid ()); ! 220: #else ! 221: srand (getpid ()); ! 222: #endif ! 223: } ! 224: ! 225: /* GET */ ! 226: ! 227: int snmp_get (ptr, instname) ! 228: NODE *ptr; ! 229: char *instname; ! 230: { ! 231: int gotone, ! 232: retries, ! 233: status = -1; ! 234: struct type_SNMP_Message *msg = &msgs; ! 235: register struct type_SNMP_PDU *parm = msg -> data -> un.get__request; ! 236: register struct type_SNMP_VarBind *v = ! 237: parm -> variable__bindings -> VarBind; ! 238: PE pe = NULLPE, ! 239: p = NULLPE; ! 240: OID oid; ! 241: OT ot = (OT) ptr -> magic; ! 242: NODE *value = NULL; ! 243: ! 244: if (snmp_ready () == NOTOK) ! 245: goto out; ! 246: ! 247: parm -> request__id = snmp_id; ! 248: if (v -> name) ! 249: free_SNMP_ObjectName (v -> name), v -> name = NULL; ! 250: ! 251: if (instname == NULL) { ! 252: if (ot -> ot_getfnx || snmp_scalars_as_arrays) { ! 253: register struct snmp_search *s; ! 254: ! 255: for (s = tail; s; s = s -> s_prev) { ! 256: register struct type_SNMP_VarBindList *vp; ! 257: ! 258: if (ot -> ot_name -> oid_nelem ! 259: != (oid = s -> s_parent -> ot_name) -> oid_nelem + 1 ! 260: || bcmp ((char *) ot -> ot_name -> oid_elements, ! 261: (char *) oid -> oid_elements, ! 262: oid -> oid_nelem ! 263: * sizeof ot -> ot_name -> oid_elements[0])) ! 264: continue; ! 265: for (vp = s -> s_bindings; vp; vp = vp -> next) { ! 266: v = vp -> VarBind; ! 267: ! 268: if (ot -> ot_name -> oid_nelem >= v -> name -> oid_nelem) ! 269: fatal ("snmp_get: internal error"); ! 270: if (bcmp ((char *) v -> name -> oid_elements, ! 271: (char *) ot -> ot_name -> oid_elements, ! 272: ot -> ot_name -> oid_nelem ! 273: * sizeof ot -> ot_name -> oid_elements[0])) ! 274: continue; ! 275: ! 276: goto get_value; ! 277: } ! 278: status = int_SNMP_error__status_noSuchName; ! 279: goto out; ! 280: } ! 281: if (ot -> ot_getfnx) { ! 282: snmp_diag (NULLCP, ! 283: "can't use SNMP array variable as scalar unless within for-in construct"); ! 284: goto out; ! 285: } ! 286: } ! 287: ! 288: if ((oid = v -> name = oid_extend (ot -> ot_name, 1)) == NULL) { ! 289: no_mem_for_inst: ; ! 290: snmp_diag (NULLCP, "oid_extend: out of memory"); ! 291: goto out; ! 292: } ! 293: v -> name -> oid_elements[v -> name -> oid_nelem - 1] = 0; ! 294: } ! 295: else { ! 296: register int i; ! 297: register unsigned int *ip, ! 298: *jp; ! 299: OID inst = str2oid (instname); ! 300: ! 301: if (inst == NULL) { ! 302: snmp_diag (NULLCP, "str2oid: bad instance identifier \"%s\"", ! 303: instname); ! 304: goto out; ! 305: } ! 306: if ((oid = v -> name = oid_extend (ot -> ot_name, inst -> oid_nelem)) ! 307: == NULL) ! 308: goto no_mem_for_inst; ! 309: ip = oid -> oid_elements + oid -> oid_nelem - inst -> oid_nelem; ! 310: jp = inst -> oid_elements; ! 311: for (i = inst -> oid_nelem; i > 0; i--) ! 312: *ip++ = *jp++; ! 313: } ! 314: ! 315: if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) == NOTOK) { ! 316: snmp_diag (NULLCP, "encode_SNMP_Message: %s", PY_pepy); ! 317: goto out; ! 318: } ! 319: ! 320: msg = NULL, gotone = 0; ! 321: for (retries = snmp_retries; retries > 0; ) { ! 322: int len; ! 323: fd_set rfds; ! 324: ! 325: if (debug > 1) ! 326: print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); ! 327: len = ps -> ps_byteno; ! 328: if (pe2ps (ps, pe) == NOTOK) { ! 329: snmp_diag (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno)); ! 330: goto error_x; ! 331: } ! 332: if (debug > 0 && (len = ps -> ps_byteno - len) > 484) ! 333: fprintf (stderr, "sent message of %d octets\n", len); ! 334: ! 335: FD_ZERO (&rfds); ! 336: FD_SET (snmp_fd, &rfds); ! 337: ! 338: switch (xselect (snmp_fd + 1, &rfds, NULLFD, NULLFD, snmp_timeout)) { ! 339: case NOTOK: ! 340: snmp_diag ("failed", "xselect"); ! 341: goto error_x; ! 342: ! 343: default: ! 344: if (FD_ISSET (snmp_fd, &rfds)) ! 345: break; ! 346: /* else fall... */ ! 347: case OK: ! 348: if (debug > 0) ! 349: fprintf (stderr, "timeout...\n"); ! 350: retries--; ! 351: continue; ! 352: } ! 353: ! 354: if ((p = ps2pe (ps)) == NULLPE) { ! 355: snmp_diag (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno)); ! 356: goto error_x; ! 357: } ! 358: if (decode_SNMP_Message (p, 1, NULLIP, NULLVP, &msg) == NOTOK) { ! 359: snmp_diag (NULLCP, "decode_SNMP_Message: %s", PY_pepy); ! 360: goto out; ! 361: } ! 362: if (debug > 1) ! 363: print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP); ! 364: ! 365: if (msg -> data -> offset != type_SNMP_PDUs_get__response) { ! 366: snmp_diag (NULLCP, "unexpected message type %d", ! 367: msg -> data -> offset); ! 368: goto out; ! 369: } ! 370: ! 371: if ((parm = msg -> data -> un.get__response) -> request__id == snmp_id) ! 372: break; ! 373: ! 374: if (debug > 0) ! 375: fprintf (stderr, "bad ID (got %d, wanted %d)\n", ! 376: parm -> request__id, snmp_id); ! 377: ! 378: if (msg) ! 379: free_SNMP_Message (msg), msg = NULL; ! 380: if (p) ! 381: pe_free (p), p = NULLPE; ! 382: ! 383: gotone++; ! 384: } ! 385: if (retries <= 0) { ! 386: snmp_diag (NULLCP, ! 387: "no %sresponse within %d retries of %s%d second%s each", ! 388: gotone ? "acceptable " : "", snmp_retries + gotone, ! 389: gotone ? "upto " : "", ! 390: snmp_timeout, snmp_timeout != 1 ? "s" : ""); ! 391: goto out; ! 392: } ! 393: ! 394: if ((status = parm -> error__status) != int_SNMP_error__status_noError) { ! 395: char *cp = snmp_variable (parm, parm -> error__index); ! 396: ! 397: snmp_diag (NULLCP, cp ? "%s at position %d (%s)" : "%s at position %d", ! 398: snmp_error (status), parm -> error__index, cp); ! 399: goto out; ! 400: } ! 401: ! 402: if (parm -> variable__bindings == NULL ! 403: || (v = parm -> variable__bindings -> VarBind) == NULL) { ! 404: snmp_diag (NULLCP, "missing variable in response"); ! 405: goto out; ! 406: } ! 407: if (debug > 0 && parm -> variable__bindings -> next) ! 408: fprintf (stderr, "too many responses: %s\n", ! 409: oid2ode (parm -> variable__bindings -> next -> VarBind -> name)); ! 410: ! 411: if (oid_cmp (oid, v -> name)) { ! 412: char buffer[BUFSIZ]; ! 413: ! 414: (void) strcpy (buffer, oid2ode (v -> name)); ! 415: snmp_diag (NULLCP, "wrong variable returned (got %s, wanted %s)", ! 416: buffer, oid2ode (oid)); ! 417: goto out; ! 418: } ! 419: ! 420: get_value: ; ! 421: if ((*ot -> ot_syntax -> os_decode) (&value, v -> value) == NOTOK) { ! 422: snmp_diag (NULLCP, "decode error for variable \"%s\": %s", ! 423: oid2ode (v -> name), PY_pepy); ! 424: goto out; ! 425: } ! 426: ! 427: goto out; ! 428: ! 429: error_x: ; ! 430: if (ps) ! 431: ps_free (ps), ps = NULLPS; ! 432: if (snmp_fd != NOTOK) ! 433: (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK; ! 434: ! 435: out: ; ! 436: if (msg && msg != &msgs) ! 437: free_SNMP_Message (msg); ! 438: if (p) ! 439: pe_free (p); ! 440: if (pe) ! 441: pe_free (pe); ! 442: ! 443: deref = ptr -> var_value; ! 444: do_deref (); ! 445: ! 446: ptr -> var_value = value ? value : Nnull_string; ! 447: ! 448: assign_number (&ERROR_node -> var_value, (AWKNUM) status); ! 449: } ! 450: ! 451: /* */ ! 452: ! 453: static snmp_ready () { ! 454: int changed = 0; ! 455: char *pp; ! 456: struct sockaddr_in lo_socket; ! 457: register struct sockaddr_in *lsock = &lo_socket; ! 458: register struct sockaddr_in *isock = &in_socket; ! 459: register struct hostent *hp; ! 460: register struct servent *sp; ! 461: register NODE *tmp; ! 462: ! 463: deref = DIAGNOSTIC_node -> var_value; ! 464: do_deref (); ! 465: ! 466: DIAGNOSTIC_node -> var_value = Nnull_string; ! 467: ! 468: if ((snmp_retries = (int) RETRIES_node -> var_value -> numbr) <= 0) ! 469: snmp_retries = 1; ! 470: if ((snmp_timeout = (int) TIMEOUT_node -> var_value -> numbr) <= 0) ! 471: snmp_timeout = 1; ! 472: ! 473: if (snmp_id >= 0x7fffffff) ! 474: snmp_id = 0; ! 475: snmp_id++; ! 476: ! 477: if (snmp_fd == NOTOK || ps == NULLPS) ! 478: changed++; ! 479: ! 480: tmp = force_string (AGENT_node -> var_value); ! 481: if (snmp_agent == NULL || strcmp (snmp_agent, tmp -> stptr)) { ! 482: if (snmp_agent) ! 483: free (snmp_agent), snmp_agent = NULL; ! 484: ! 485: emalloc (snmp_agent, char *, strlen (tmp -> stptr) + 1, "snmp_init1"); ! 486: (void) strcpy (snmp_agent, tmp -> stptr); ! 487: ! 488: changed++; ! 489: } ! 490: ! 491: tmp = force_string (COMMUNITY_node -> var_value); ! 492: if (snmp_community == NULL || strcmp (snmp_community, tmp -> stptr)) { ! 493: register struct type_SNMP_Message *msg = &msgs; ! 494: ! 495: if (snmp_community) ! 496: free (snmp_community), snmp_community = NULL; ! 497: ! 498: emalloc (snmp_community, char *, strlen (tmp -> stptr) + 1, ! 499: "snmp_init2"); ! 500: (void) strcpy (snmp_community, tmp -> stptr); ! 501: ! 502: if ((msg -> community = str2qb (snmp_community, ! 503: strlen (snmp_community), 1)) == NULL) { ! 504: snmp_diag (NULLCP, "str2qb: out of memory"); ! 505: free (snmp_community), snmp_community = NULL; ! 506: return NOTOK; ! 507: } ! 508: } ! 509: ! 510: if (changed) { ! 511: if (ps) ! 512: ps_free (ps), ps = NULLPS; ! 513: if (snmp_fd != NOTOK) ! 514: (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK; ! 515: } ! 516: else ! 517: return OK; ! 518: ! 519: bzero ((char *) lsock, sizeof *lsock); ! 520: if ((hp = gethostbystring (pp = strcmp (snmp_agent, "localhost") ! 521: ? getlocalhost () : "localhost")) ! 522: == NULL) { ! 523: snmp_diag (NULLCP, "%s: unknown host", pp); ! 524: return NOTOK; ! 525: } ! 526: lsock -> sin_family = hp -> h_addrtype; ! 527: inaddr_copy (hp, lsock); ! 528: if ((snmp_fd = start_udp_client (lsock, 0, 0, 0)) == NOTOK) { ! 529: snmp_diag ("failed", "start_udp_server"); ! 530: return NOTOK; ! 531: } ! 532: ! 533: bzero ((char *) isock, sizeof *isock); ! 534: if ((hp = gethostbystring (snmp_agent)) == NULL) { ! 535: snmp_diag (NULLCP, "%s: unknown host", snmp_agent); ! 536: return NOTOK; ! 537: } ! 538: isock -> sin_family = hp -> h_addrtype; ! 539: isock -> sin_port = (sp = getservbyname ("snmp", "udp")) ! 540: ? sp -> s_port ! 541: : htons ((u_short) 161); ! 542: inaddr_copy (hp, isock); ! 543: ! 544: if (join_udp_server (snmp_fd, isock) == NOTOK) { ! 545: snmp_diag ("failed", "join_udp_server"); ! 546: return NOTOK; ! 547: } ! 548: ! 549: if ((ps = ps_alloc (dg_open)) == NULLPS ! 550: || dg_setup (ps, snmp_fd, MAXDGRAM, read_udp_socket, ! 551: write_udp_socket) == NOTOK) { ! 552: if (ps == NULLPS) ! 553: snmp_diag (NULLCP, "ps_alloc: out of memory"); ! 554: else ! 555: snmp_diag (NULLCP, "dg_setup: %s", ps_error (ps -> ps_errno)); ! 556: ! 557: return NOTOK; ! 558: } ! 559: ! 560: #ifndef SYS5 ! 561: snmp_id = ((int) random ()) & 0x7fffffff; ! 562: #else ! 563: snmp_id = ((int) rand ()) & 0x7fffffff; ! 564: #endif ! 565: ! 566: return OK; ! 567: } ! 568: ! 569: /* */ ! 570: ! 571: #ifndef lint ! 572: static snmp_diag (va_alist) ! 573: va_dcl ! 574: { ! 575: char *what, ! 576: buffer[BUFSIZ]; ! 577: va_list ap; ! 578: ! 579: va_start (ap); ! 580: ! 581: what = va_arg (ap, char *); ! 582: ! 583: _asprintf (buffer, what, ap); ! 584: ! 585: va_end (ap); ! 586: ! 587: if (debug > 0) ! 588: fprintf (stderr, "%s\n", buffer); ! 589: ! 590: deref = DIAGNOSTIC_node -> var_value; ! 591: do_deref (); ! 592: ! 593: DIAGNOSTIC_node -> var_value = make_string (buffer, strlen (buffer)); ! 594: } ! 595: #else ! 596: /* VARARGS */ ! 597: ! 598: static snmp_diag (what, fmt) ! 599: char *what, ! 600: *fmt; ! 601: { ! 602: snmp_diag (what, fmt); ! 603: } ! 604: #endif ! 605: ! 606: /* SCAN */ ! 607: ! 608: struct search *snmp_assoc_scan (symbol) ! 609: NODE *symbol; ! 610: { ! 611: register struct snmp_search *s; ! 612: register OT ot = (OT) symbol -> magic; ! 613: register struct type_SNMP_VarBindList **vp; ! 614: ! 615: if (!ot -> ot_getfnx && !snmp_scalars_as_arrays) ! 616: fatal ("can't use SNMP scalar variable as control for for-in"); ! 617: ! 618: emalloc (s, struct snmp_search *, sizeof *s, "snmp_assoc_scan1"); ! 619: bzero ((char *) s, sizeof *s); ! 620: ! 621: ot -> ot_name -> oid_nelem--; ! 622: s -> s_parent = name2obj (ot -> ot_name); ! 623: ot -> ot_name -> oid_nelem++; ! 624: ! 625: if ((ot = s -> s_parent) == NULL) ! 626: fatal ("unable to find parent for \"%s\"", snmp_name (symbol)); ! 627: ! 628: vp = &s -> s_bindings; ! 629: for (ot = ot -> ot_children; ot; ot = ot -> ot_sibling) { ! 630: register struct type_SNMP_VarBindList *bind; ! 631: register struct type_SNMP_VarBind *v; ! 632: ! 633: if (!ot -> ot_syntax) ! 634: continue; ! 635: emalloc (bind, struct type_SNMP_VarBindList *, sizeof *bind, ! 636: "snmp_assoc_scan2"); ! 637: *vp = bind, vp = &bind -> next; ! 638: bind -> next = NULL; ! 639: ! 640: emalloc (v, struct type_SNMP_VarBind *, sizeof *v, "snmp_assoc_scan3"); ! 641: bind -> VarBind = v; ! 642: if ((v -> name = oid_cpy (ot -> ot_name)) == NULL) ! 643: fatal ("oid_cpy: out of memory"); ! 644: if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL)) ! 645: == NULLPE) ! 646: fatal ("pe_alloc: out of memory"); ! 647: } ! 648: ! 649: if (head == NULL) ! 650: head = tail = s; ! 651: else { ! 652: tail -> s_next = s; ! 653: s -> s_prev = tail; ! 654: tail = s; ! 655: } ! 656: ! 657: return snmp_assoc_next (&s -> s_search, 0); ! 658: } ! 659: ! 660: /* */ ! 661: ! 662: struct search *snmp_assoc_next (lookat, done) ! 663: struct search *lookat; ! 664: int done; ! 665: { ! 666: int i; ! 667: char *cp; ! 668: register struct snmp_search *s = (struct snmp_search *) lookat; ! 669: register struct search *l = &s -> s_search; ! 670: struct OIDentifier oids; ! 671: OID oid; ! 672: OT ot = s -> s_parent; ! 673: register struct type_SNMP_VarBind *v; ! 674: ! 675: deref = l -> retval, l -> retval = NULL; ! 676: do_deref (); ! 677: ! 678: if (done || snmp_get_next (s) == NOTOK || s -> s_bindings == NULL) { ! 679: if (s -> s_bindings) ! 680: free_SNMP_VarBind (s -> s_bindings); ! 681: if (s -> s_pe) ! 682: pe_free (s -> s_pe); ! 683: if (tail != s) ! 684: fatal ("snmp_assoc_next: internal error1"); ! 685: if (tail = s -> s_prev) ! 686: tail -> s_next = NULL; ! 687: else ! 688: head = NULL; ! 689: ! 690: free ((char *) s); ! 691: return NULL; ! 692: } ! 693: ! 694: if ((v = s -> s_bindings -> VarBind) == NULL || (oid = v -> name) == NULL) ! 695: fatal ("snmp_assoc_next: internal error2"); ! 696: if (ot -> ot_name -> oid_nelem >= oid -> oid_nelem ! 697: || bcmp ((char *) ot -> ot_name -> oid_elements, ! 698: (char *) oid -> oid_elements, ! 699: ot -> ot_name -> oid_nelem ! 700: * sizeof oid -> oid_elements[0])) ! 701: fatal ("snmp_assoc_next: internal error3"); ! 702: ! 703: oids.oid_nelem = oid -> oid_nelem - (i = ot -> ot_name -> oid_nelem + 1); ! 704: oids.oid_elements = oid -> oid_elements + i; ! 705: ! 706: cp = sprintoid (&oids); ! 707: ! 708: l -> retval = make_string (cp, strlen (cp)); ! 709: ! 710: return l; ! 711: } ! 712: ! 713: /* */ ! 714: ! 715: static int snmp_get_next (s) ! 716: register struct snmp_search *s; ! 717: { ! 718: int gotone, ! 719: result = NOTOK, ! 720: retries, ! 721: status = -1; ! 722: struct type_SNMP_Message *msg = &msgs; ! 723: register struct type_SNMP_PDU *parm = msg -> data -> un.get__request; ! 724: register struct type_SNMP_VarBindList *vp = parm -> variable__bindings, ! 725: *vp2, ! 726: **vpp; ! 727: PE pe = NULLPE, ! 728: p = NULLPE; ! 729: ! 730: if (snmp_ready () == NOTOK) ! 731: goto out; ! 732: ! 733: msg -> data -> offset = type_SNMP_PDUs_get__next__request; ! 734: parm -> request__id = snmp_id; ! 735: parm -> variable__bindings = s -> s_bindings; ! 736: ! 737: result = encode_SNMP_Message (&pe, 1, 0, NULLCP, msg); ! 738: ! 739: parm -> variable__bindings = vp; ! 740: msg -> data -> offset = type_SNMP_PDUs_get__request; ! 741: ! 742: if (result == NOTOK) { ! 743: snmp_diag (NULLCP, "encode_SNMP_Message: %s", PY_pepy); ! 744: goto out; ! 745: } ! 746: result = NOTOK; ! 747: ! 748: msg = NULL, gotone = 0; ! 749: for (retries = snmp_retries; retries > 0; ) { ! 750: int len; ! 751: fd_set rfds; ! 752: ! 753: if (debug > 1) ! 754: print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); ! 755: len = ps -> ps_byteno; ! 756: if (pe2ps (ps, pe) == NOTOK) { ! 757: snmp_diag (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno)); ! 758: goto error_x; ! 759: } ! 760: if (debug > 0 && (len = ps -> ps_byteno - len) > 484) ! 761: fprintf (stderr, "sent message of %d octets\n", len); ! 762: ! 763: FD_ZERO (&rfds); ! 764: FD_SET (snmp_fd, &rfds); ! 765: ! 766: switch (xselect (snmp_fd + 1, &rfds, NULLFD, NULLFD, snmp_timeout)) { ! 767: case NOTOK: ! 768: snmp_diag ("failed", "xselect"); ! 769: goto error_x; ! 770: ! 771: default: ! 772: if (FD_ISSET (snmp_fd, &rfds)) ! 773: break; ! 774: /* else fall... */ ! 775: case OK: ! 776: retries--; ! 777: continue; ! 778: } ! 779: ! 780: if ((p = ps2pe (ps)) == NULLPE) { ! 781: snmp_diag (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno)); ! 782: goto error_x; ! 783: } ! 784: if (decode_SNMP_Message (p, 1, NULLIP, NULLVP, &msg) == NOTOK) { ! 785: snmp_diag (NULLCP, "decode_SNMP_Message: %s", PY_pepy); ! 786: goto out; ! 787: } ! 788: if (debug > 1) ! 789: print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP); ! 790: ! 791: if (msg -> data -> offset != type_SNMP_PDUs_get__response) { ! 792: snmp_diag (NULLCP, "unexpected message type %d", ! 793: msg -> data -> offset); ! 794: goto out; ! 795: } ! 796: ! 797: if ((parm = msg -> data -> un.get__response) -> request__id == snmp_id) ! 798: break; ! 799: ! 800: if (msg) ! 801: free_SNMP_Message (msg), msg = NULL; ! 802: if (p) ! 803: pe_free (p), p = NULLPE; ! 804: ! 805: gotone++; ! 806: } ! 807: if (retries <= 0) { ! 808: snmp_diag (NULLCP, ! 809: "no %sresponse within %d retries of %s%d second%s each", ! 810: gotone ? "acceptable " : "", snmp_retries + gotone, ! 811: gotone ? "upto " : "", ! 812: snmp_timeout, snmp_timeout != 1 ? "s" : ""); ! 813: goto out; ! 814: } ! 815: ! 816: if ((status = parm -> error__status) != int_SNMP_error__status_noError) { ! 817: char *cp = snmp_variable (parm, parm -> error__index); ! 818: ! 819: snmp_diag (NULLCP, cp ? "%s at position %d (%s)" : "%s at position %d", ! 820: snmp_error (status), parm -> error__index, ! 821: cp); ! 822: goto out; ! 823: } ! 824: ! 825: for (vp = s -> s_bindings, vpp = &parm -> variable__bindings; ! 826: vp && (vp2 = *vpp); ! 827: vp = vp -> next) { ! 828: if (name2obj (vp -> VarBind -> name) ! 829: != name2obj (vp2 -> VarBind -> name)) { ! 830: *vpp = vp2 -> next; ! 831: vp2 -> next = NULL; ! 832: free_SNMP_VarBindList (vp2); ! 833: } ! 834: else ! 835: vpp = &vp2 -> next; ! 836: } ! 837: if (vp) { ! 838: snmp_diag (NULLCP, "missing variable in response"); ! 839: goto out; ! 840: } ! 841: else ! 842: if (vp2 = *vpp) { ! 843: if (debug > 0) ! 844: fprintf (stderr, "too many responses starting with: %s\n", ! 845: oid2ode (vp2 -> VarBind -> name)); ! 846: ! 847: *vpp = NULL; ! 848: free_SNMP_VarBindList (vp2); ! 849: } ! 850: ! 851: if (s -> s_bindings) ! 852: free_SNMP_VarBindList (s -> s_bindings); ! 853: if (s -> s_pe) ! 854: pe_free (s -> s_pe); ! 855: ! 856: s -> s_bindings = parm -> variable__bindings; ! 857: parm -> variable__bindings = NULL; ! 858: s -> s_pe = p; ! 859: p = NULLPE; ! 860: ! 861: result = OK; ! 862: goto out; ! 863: ! 864: error_x: ; ! 865: if (ps) ! 866: ps_free (ps), ps = NULLPS; ! 867: if (snmp_fd != NOTOK) ! 868: (void) close_udp_socket (snmp_fd), snmp_fd = NOTOK; ! 869: ! 870: out: ; ! 871: if (msg && msg != &msgs) ! 872: free_SNMP_Message (msg); ! 873: if (p) ! 874: pe_free (p); ! 875: if (pe) ! 876: pe_free (pe); ! 877: ! 878: assign_number (&ERROR_node -> var_value, (AWKNUM) status); ! 879: ! 880: return result; ! 881: } ! 882: ! 883: /* DECODE */ ! 884: ! 885: static NODE *make_octet_node (base, len) ! 886: char *base; ! 887: int len; ! 888: { ! 889: register char *bp, ! 890: *cp, ! 891: *ep; ! 892: char *s = ""; ! 893: register NODE *r; ! 894: ! 895: r = newnode (Node_val); ! 896: emalloc (r -> stptr, char *, len * 3 + 1, "make_octet_node"); ! 897: bp = r -> stptr; ! 898: for (ep = (cp = base) + len; cp < ep; cp++, s = ":") { ! 899: (void) sprintf (bp, "%s%02x", s, *cp & 0xff); ! 900: bp += strlen (bp); ! 901: } ! 902: *bp = NULL; /* in case len == 0 */ ! 903: r -> stlen = bp - r -> stptr; ! 904: r -> stref = 1; ! 905: r -> flags |= STR | MALLOC; ! 906: ! 907: return r; ! 908: } ! 909: ! 910: ! 911: static int f_integer (x, pe) ! 912: NODE **x; ! 913: PE pe; ! 914: { ! 915: integer i = prim2num (pe); ! 916: ! 917: if (i == NOTOK && pe -> pe_errno != PE_ERR_NONE) { ! 918: (void) strcpy (PY_pepy, pe_error (pe -> pe_errno)); ! 919: return NOTOK; ! 920: } ! 921: ! 922: *x = make_number ((AWKNUM) i); ! 923: ! 924: return OK; ! 925: } ! 926: ! 927: ! 928: static int f_octets (x, pe) ! 929: NODE **x; ! 930: PE pe; ! 931: { ! 932: struct qbuf *qb = prim2qb (pe); ! 933: ! 934: if (qb == NULL|| qb_pullup (qb) == NOTOK) { ! 935: (void) strcpy (PY_pepy, qb ? "qb_pullup: out of memory" ! 936: : pe_error (pe -> pe_errno)); ! 937: return NOTOK; ! 938: } ! 939: ! 940: *x = make_octet_node (qb -> qb_forw -> qb_data, qb -> qb_forw -> qb_len); ! 941: ! 942: qb_free (qb); ! 943: ! 944: return OK; ! 945: } ! 946: ! 947: ! 948: static int f_display (x, pe) ! 949: NODE **x; ! 950: PE pe; ! 951: { ! 952: struct qbuf *qb = prim2qb (pe); ! 953: ! 954: if (qb == NULL|| qb_pullup (qb) == NOTOK) { ! 955: (void) strcpy (PY_pepy, qb ? "qb_pullup: out of memory" ! 956: : pe_error (pe -> pe_errno)); ! 957: return NOTOK; ! 958: } ! 959: ! 960: *x = make_string (qb -> qb_forw -> qb_data, qb -> qb_forw -> qb_len); ! 961: ! 962: qb_free (qb); ! 963: ! 964: return OK; ! 965: } ! 966: ! 967: ! 968: static int f_objectID (x, pe) ! 969: NODE **x; ! 970: PE pe; ! 971: { ! 972: char *cp; ! 973: OID oid = prim2oid (pe); ! 974: ! 975: if (oid == NULLOID) { ! 976: (void) strcpy (PY_pepy, pe_error (pe -> pe_errno)); ! 977: return NOTOK; ! 978: } ! 979: cp = sprintoid (oid); ! 980: ! 981: *x = make_string (cp, strlen (cp)); ! 982: ! 983: return OK; ! 984: } ! 985: ! 986: ! 987: /* ARGSUSED */ ! 988: ! 989: static int f_null (x, pe) ! 990: NODE **x; ! 991: PE pe; ! 992: { ! 993: *x = make_str_node ("NULL", 4, 0); ! 994: ! 995: return OK; ! 996: } ! 997: ! 998: ! 999: static int f_ipaddr (x, pe) ! 1000: NODE **x; ! 1001: PE pe; ! 1002: { ! 1003: char ipaddr[16]; ! 1004: struct type_SNMP_IpAddress *ip; ! 1005: struct qbuf *qb; ! 1006: ! 1007: if (decode_SNMP_IpAddress (pe, 1, NULLIP, NULLVP, &ip) == NOTOK) ! 1008: return NOTOK; ! 1009: if (qb_pullup (ip) == NOTOK) { ! 1010: (void) strcpy (PY_pepy, "qb_pullup: out of memory"); ! 1011: free_SNMP_IpAddress (ip); ! 1012: return NOTOK; ! 1013: } ! 1014: if ((qb = ip -> qb_forw) -> qb_len != 4) { ! 1015: (void) sprintf (PY_pepy, ! 1016: "IpAddress is wrong length (got %d, wanted 4)", ! 1017: qb -> qb_len); ! 1018: free_SNMP_IpAddress (ip); ! 1019: return NOTOK; ! 1020: } ! 1021: (void) sprintf (ipaddr, "%d.%d.%d.%d", ! 1022: qb -> qb_data[0] & 0xff, qb -> qb_data[1] & 0xff, ! 1023: qb -> qb_data[2] & 0xff, qb -> qb_data[3] & 0xff); ! 1024: ! 1025: *x = make_str_node (ipaddr, strlen (ipaddr), 0); ! 1026: ! 1027: free_SNMP_IpAddress (ip); ! 1028: ! 1029: return OK; ! 1030: } ! 1031: ! 1032: ! 1033: static int f_clnpaddr (x, pe) ! 1034: NODE **x; ! 1035: PE pe; ! 1036: { ! 1037: int len; ! 1038: struct type_SNMP_ClnpAddress *clnp; ! 1039: struct qbuf *qb; ! 1040: ! 1041: if (decode_SNMP_ClnpAddress (pe, 1, NULLIP, NULLVP, &clnp) == NOTOK) ! 1042: return NOTOK; ! 1043: if (qb_pullup (clnp) == NOTOK) { ! 1044: (void) strcpy (PY_pepy, "qb_pullup: out of memory"); ! 1045: free_SNMP_ClnpAddress (clnp); ! 1046: return NOTOK; ! 1047: } ! 1048: qb = clnp -> qb_forw; ! 1049: if ((len = qb -> qb_data[0] & 0xff) >= qb -> qb_len) ! 1050: len = qb -> qb_len - 1; ! 1051: ! 1052: *x = make_octet_node (qb -> qb_data, len); ! 1053: ! 1054: free_SNMP_ClnpAddress (clnp); ! 1055: ! 1056: return OK; ! 1057: } ! 1058: ! 1059: /* MISC */ ! 1060: ! 1061: char *snmp_name (ptr) ! 1062: NODE *ptr; ! 1063: { ! 1064: return ((OT) (ptr -> magic)) -> ot_text; ! 1065: } ! 1066: ! 1067: /* */ ! 1068: ! 1069: static char *errors[] = { ! 1070: "noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr" ! 1071: }; ! 1072: ! 1073: ! 1074: static char *snmp_error (i) ! 1075: int i; ! 1076: { ! 1077: static char buffer[BUFSIZ]; ! 1078: ! 1079: if (0 < i && i < sizeof errors / sizeof errors[0]) ! 1080: return errors[i]; ! 1081: (void) sprintf (buffer, "error %d", i); ! 1082: ! 1083: return buffer; ! 1084: } ! 1085: ! 1086: ! 1087: static char *snmp_variable (parm, index) ! 1088: register struct type_SNMP_PDU *parm; ! 1089: int index; ! 1090: { ! 1091: register struct type_SNMP_VarBindList *vp; ! 1092: ! 1093: if (index <= 0 || (vp = parm -> variable__bindings) == NULL) ! 1094: return NULL; ! 1095: for (index--; index > 0; index--) ! 1096: if ((vp = vp -> next) == NULL) ! 1097: return NULL; ! 1098: ! 1099: return oid2ode (vp -> VarBind -> name); ! 1100: } ! 1101: #endif /* SNMP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.