|
|
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.