Commit | Line | Data |
---|---|---|
b62cce74 C |
1 | /* snmpi.c - really minimal SNMP initiator */ |
2 | ||
3 | #ifndef lint | |
4 | static char *rcsid = "$Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $"; | |
5 | #endif | |
6 | ||
7 | /* | |
8 | * $Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $ | |
9 | * | |
10 | * Contributed by NYSERNet Inc. This work was partially supported by the | |
11 | * U.S. Defense Advanced Research Projects Agency and the Rome Air Development | |
12 | * Center of the U.S. Air Force Systems Command under contract number | |
13 | * F30602-88-C-0016. | |
14 | * | |
15 | * | |
16 | * $Log: snmpi.c,v $ | |
17 | * Revision 7.28 91/03/09 11:57:50 mrose | |
18 | * update | |
19 | * | |
20 | * Revision 7.27 91/02/22 09:44:34 mrose | |
21 | * Interim 6.8 | |
22 | * | |
23 | * Revision 7.26 91/01/11 15:35:28 mrose | |
24 | * sets | |
25 | * | |
26 | * Revision 7.25 91/01/07 12:41:08 mrose | |
27 | * update | |
28 | * | |
29 | * Revision 7.24 90/10/23 20:37:09 mrose | |
30 | * update | |
31 | * | |
32 | * Revision 7.23 90/09/26 19:23:02 mrose | |
33 | * new-mibs | |
34 | * | |
35 | * Revision 7.22 90/09/26 18:47:18 mrose | |
36 | * more-compile | |
37 | * | |
38 | * Revision 7.21 90/09/26 14:57:48 mrose | |
39 | * compile -f | |
40 | * | |
41 | * Revision 7.20 90/09/07 11:11:39 mrose | |
42 | * update | |
43 | * | |
44 | * Revision 7.19 90/09/03 12:58:04 mrose | |
45 | * update | |
46 | * | |
47 | * Revision 7.18 90/08/30 15:11:11 mrose | |
48 | * ho-hum | |
49 | * | |
50 | * Revision 7.17 90/08/30 01:32:05 mrose | |
51 | * update | |
52 | * | |
53 | * Revision 7.16 90/08/20 21:25:52 mrose | |
54 | * touch-up | |
55 | * | |
56 | * Revision 7.15 90/08/16 17:01:13 mrose | |
57 | * touch-up | |
58 | * | |
59 | * Revision 7.14 90/08/08 14:01:31 mrose | |
60 | * stuff | |
61 | * | |
62 | * Revision 7.13 90/07/09 14:49:34 mrose | |
63 | * sync | |
64 | * | |
65 | * Revision 7.12 90/06/23 18:25:14 mrose | |
66 | * now | |
67 | * | |
68 | * Revision 7.11 90/06/23 17:01:55 mrose | |
69 | * update | |
70 | * | |
71 | * Revision 7.10 90/05/12 17:02:09 mrose | |
72 | * sync | |
73 | * | |
74 | * Revision 7.9 90/02/23 17:47:59 mrose | |
75 | * update | |
76 | * | |
77 | * Revision 7.8 90/02/19 19:17:05 mrose | |
78 | * again | |
79 | * | |
80 | * Revision 7.7 90/01/27 08:22:04 mrose | |
81 | * touch-up | |
82 | * | |
83 | * Revision 7.6 90/01/11 18:34:43 mrose | |
84 | * real-sync | |
85 | * | |
86 | * Revision 7.5 89/12/19 17:57:56 mrose | |
87 | * touch-up | |
88 | * | |
89 | * Revision 7.4 89/12/19 16:18:26 mrose | |
90 | * dgram | |
91 | * | |
92 | * Revision 7.3 89/12/12 16:13:47 mrose | |
93 | * touch-up | |
94 | * | |
95 | * Revision 7.2 89/12/11 16:22:33 mrose | |
96 | * more clts | |
97 | * | |
98 | * Revision 7.1 89/12/01 10:42:18 mrose | |
99 | * clts | |
100 | * | |
101 | * Revision 7.0 89/11/23 22:23:30 mrose | |
102 | * Release 6.0 | |
103 | * | |
104 | */ | |
105 | ||
106 | /* | |
107 | * NOTICE | |
108 | * | |
109 | * Acquisition, use, and distribution of this module and related | |
110 | * materials are subject to the restrictions of a license agreement. | |
111 | * Consult the Preface in the User's Manual for the full terms of | |
112 | * this agreement. | |
113 | * | |
114 | */ | |
115 | ||
116 | ||
117 | #include <setjmp.h> | |
118 | #include <signal.h> | |
119 | #include <stdio.h> | |
120 | #include <varargs.h> | |
121 | #include "SNMP-types.h" | |
122 | #include "objects.h" | |
123 | #include <sys/ioctl.h> | |
124 | #include "tailor.h" | |
125 | ||
126 | #include "dgram.h" | |
127 | #include "tsap.h" | |
128 | #ifdef TCP | |
129 | #include "internet.h" | |
130 | #endif | |
131 | #ifdef X25 | |
132 | #include "x25.h" | |
133 | #define COTS | |
134 | #endif | |
135 | #ifdef TP4 | |
136 | #include "tp4.h" | |
137 | #if !defined(CLTS) && !defined(COTS) | |
138 | #define COTS | |
139 | #endif | |
140 | #endif | |
141 | ||
142 | /* \f DATA */ | |
143 | ||
144 | int debug = 0; | |
145 | static int verbose = 0; | |
146 | int watch = 0; | |
147 | ||
148 | static char *myname = "snmp"; | |
149 | ||
150 | static char **op = NULLVP; | |
151 | ||
152 | static int ontty; | |
153 | static int armed; | |
154 | static jmp_buf intrenv; | |
155 | static int interrupted; | |
156 | ||
157 | static SFP istat; | |
158 | ||
159 | SFD intrser (); | |
160 | ||
161 | ||
162 | static char *defs = NULLCP; | |
163 | ||
164 | static PS ps; | |
165 | static char *community = "public"; | |
166 | ||
167 | static int sd; | |
168 | static struct TSAPaddr snmp_ta; | |
169 | ||
170 | char *snmp_error (); | |
171 | struct type_SNMP_Message *new_message (); | |
172 | ||
173 | ||
174 | void adios (), advise (); | |
175 | ||
176 | /* \f */ | |
177 | ||
178 | struct dispatch { | |
179 | char *ds_name; /* command name */ | |
180 | IFP ds_fnx; /* dispatch */ | |
181 | ||
182 | char *ds_help; /* help string */ | |
183 | }; | |
184 | struct dispatch *getds (); | |
185 | ||
186 | ||
187 | int f_audit (); | |
188 | #ifdef BSD42 | |
189 | int f_bulk (); | |
190 | #endif | |
191 | int f_compile (), f_dump (); | |
192 | int f_get (), f_get_next (), f_set (); | |
193 | int f_help (), f_quit (), f_status (); | |
194 | ||
195 | static struct dispatch dispatches[] = { | |
196 | "audit", f_audit, "audit traps", | |
197 | ||
198 | #ifdef BSD42 | |
199 | "bulk", f_bulk, "bulk retrieve colums from a table", | |
200 | #endif | |
201 | ||
202 | "compile", f_compile, "write compiled objects file", | |
203 | ||
204 | "dump", f_dump, "dump a portion of the MIB", | |
205 | ||
206 | "get", f_get, "perform get operation", | |
207 | ||
208 | "help", f_help, "print help information", | |
209 | ||
210 | "next", f_get_next, "perform powerful get-next operation", | |
211 | ||
212 | "quit", f_quit, "terminate program", | |
213 | ||
214 | "set", f_set, "perform set operation", | |
215 | ||
216 | "status", f_status, "report status", | |
217 | ||
218 | NULL | |
219 | }; | |
220 | ||
221 | ||
222 | static int helpwidth; | |
223 | ||
224 | ||
225 | #ifndef SYS5 | |
226 | long random (); | |
227 | #endif | |
228 | long time (); | |
229 | ||
230 | /* \f MAIN */ | |
231 | ||
232 | /* ARGSUSED */ | |
233 | ||
234 | main (argc, argv, envp) | |
235 | int argc; | |
236 | char **argv, | |
237 | **envp; | |
238 | { | |
239 | int eof, | |
240 | status, | |
241 | vecp; | |
242 | char buffer[BUFSIZ], | |
243 | *vec[NVEC + 1]; | |
244 | ||
245 | arginit (argv); | |
246 | ||
247 | status = 0; | |
248 | if (op) { | |
249 | vecp = 0; | |
250 | while (*op) | |
251 | vec[vecp++] = *op++; | |
252 | vec[vecp] = NULL; | |
253 | ||
254 | if (snmploop (vec, NOTOK) == NOTOK) | |
255 | status = 1; | |
256 | ||
257 | goto were_out_of_here; | |
258 | } | |
259 | ||
260 | istat = signal (SIGINT, intrser); | |
261 | ||
262 | eof = 0; | |
263 | for (interrupted = 0;; interrupted = 0) { | |
264 | if (getline ("%s> ", buffer) == NOTOK) { | |
265 | if (eof) | |
266 | break; | |
267 | ||
268 | eof = 1; | |
269 | continue; | |
270 | } | |
271 | eof = 0; | |
272 | ||
273 | bzero ((char *) vec, sizeof vec); | |
274 | if ((vecp = str2vec (buffer, vec)) < 1) | |
275 | continue; | |
276 | ||
277 | switch (snmploop (vec, OK)) { | |
278 | case NOTOK: | |
279 | status = 1; | |
280 | break; | |
281 | ||
282 | case OK: | |
283 | default: | |
284 | continue; | |
285 | ||
286 | case DONE: | |
287 | status = 0; | |
288 | break; | |
289 | } | |
290 | break; | |
291 | } | |
292 | ||
293 | (void) signal (SIGINT, istat); | |
294 | ||
295 | were_out_of_here: ; | |
296 | #ifdef COTS | |
297 | if (snmp_ta.ta_addrs -> na_stack != NA_TCP) { | |
298 | struct TSAPdisconnect tds; | |
299 | ||
300 | #ifdef CLTS | |
301 | if (snmp_ta.ta_addrs -> na_stack != NA_NSAP) | |
302 | #endif | |
303 | (void) TDiscRequest (sd, NULLCP, 0, &tds); | |
304 | } | |
305 | #endif | |
306 | ||
307 | exit (status); /* NOTREACHED */ | |
308 | } | |
309 | ||
310 | /* \f */ | |
311 | ||
312 | static int snmploop (vec, error) | |
313 | char **vec; | |
314 | int error; | |
315 | { | |
316 | register struct dispatch *ds; | |
317 | ||
318 | if ((ds = getds (strcmp (*vec, "?") ? *vec : "help")) == NULL) | |
319 | return error; | |
320 | switch ((*ds -> ds_fnx) (vec)) { | |
321 | case NOTOK: | |
322 | return error; | |
323 | ||
324 | case OK: | |
325 | default: | |
326 | return OK; | |
327 | ||
328 | case DONE: | |
329 | return DONE; | |
330 | } | |
331 | } | |
332 | ||
333 | /* \f */ | |
334 | ||
335 | static struct dispatch *getds (name) | |
336 | char *name; | |
337 | { | |
338 | register int longest, | |
339 | nmatches; | |
340 | register char *p, | |
341 | *q; | |
342 | char buffer[BUFSIZ]; | |
343 | register struct dispatch *ds, | |
344 | *fs; | |
345 | ||
346 | longest = nmatches = 0; | |
347 | for (ds = dispatches; p = ds -> ds_name; ds++) { | |
348 | for (q = name; *q == *p++; q++) | |
349 | if (*q == NULL) | |
350 | return ds; | |
351 | ||
352 | if (*q == NULL) | |
353 | if (q - name > longest) { | |
354 | longest = q - name; | |
355 | nmatches = 1; | |
356 | fs = ds; | |
357 | } | |
358 | else | |
359 | if (q - name == longest) | |
360 | nmatches++; | |
361 | } | |
362 | ||
363 | switch (nmatches) { | |
364 | case 0: | |
365 | advise (NULLCP, "unknown operation \"%s\"", name); | |
366 | return NULL; | |
367 | ||
368 | case 1: | |
369 | return fs; | |
370 | ||
371 | default: | |
372 | for (ds = dispatches, p = buffer; q = ds -> ds_name; ds++) | |
373 | if (strncmp (q, name, longest) == 0) { | |
374 | (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q); | |
375 | p += strlen (p); | |
376 | } | |
377 | advise (NULLCP, "ambiguous operation, it could be one of:%s", | |
378 | buffer); | |
379 | return NULL; | |
380 | } | |
381 | } | |
382 | ||
383 | /* \f OPERATIONS */ | |
384 | ||
385 | static int f_audit (vec) | |
386 | char **vec; | |
387 | { | |
388 | int follow, | |
389 | forever, | |
390 | i; | |
391 | long longtimeago, | |
392 | now; | |
393 | char *cp, | |
394 | *file; | |
395 | PE pe, | |
396 | p; | |
397 | PS ps2; | |
398 | struct type_SNMP_Audit *au; | |
399 | FILE *fp; | |
400 | ||
401 | file = "snmp.traps"; | |
402 | if (*++vec != NULL && strcmp (*vec, "-help") == 0) { | |
403 | printf ("audit [-f | -N | +N] [file]\n"); | |
404 | printf (" audit trap sink\n"); | |
405 | printf (" -f: endless loop\n"); | |
406 | printf (" -N: last N traps\n"); | |
407 | printf (" +N: first N traps\n"); | |
408 | printf (" file: trap file (default %s)\n", file); | |
409 | ||
410 | return OK; | |
411 | } | |
412 | ||
413 | follow = forever = 0; | |
414 | for (; cp = *vec; vec++) | |
415 | switch (*cp) { | |
416 | case '-': | |
417 | if (strcmp (cp, "-f") == 0) | |
418 | forever++, follow = 0; | |
419 | else | |
420 | follow = -atoi (++cp), forever = 0; | |
421 | break; | |
422 | ||
423 | case '+': | |
424 | follow = atoi (++cp), forever = 0; | |
425 | break; | |
426 | ||
427 | default: | |
428 | file = cp; | |
429 | break; | |
430 | } | |
431 | ||
432 | file = _isodefile (isodelogpath, file); | |
433 | if ((fp = fopen (file, "r")) == NULL) { | |
434 | advise (file, "unable to read"); | |
435 | return OK; | |
436 | } | |
437 | ||
438 | pe = p = NULLPE, au = NULL; | |
439 | if ((ps2 = ps_alloc (std_open)) == NULLPS) { | |
440 | advise (NULLCP, "ps_alloc(std_open): you lose"); | |
441 | goto out; | |
442 | } | |
443 | if (std_setup (ps2, fp) == NOTOK) { | |
444 | advise (NULLCP, "std_setup: %s", ps_error (ps2 -> ps_errno)); | |
445 | goto out; | |
446 | } | |
447 | ||
448 | (void) time (&now); | |
449 | longtimeago = now - 6L * 30L * 24L * 60L * 60L; | |
450 | ||
451 | if (follow < 0) { | |
452 | register long offset, | |
453 | *lp, | |
454 | *ep; | |
455 | long *opp; | |
456 | ||
457 | follow = -follow; | |
458 | if ((opp = (long *) calloc ((unsigned) follow, sizeof *opp)) == NULL) | |
459 | adios (NULLCP, "out of memory"); | |
460 | offset = ftell (fp); | |
461 | for (ep = (lp = opp) + follow; lp < ep; lp++) | |
462 | *lp = offset; | |
463 | lp = opp; | |
464 | ||
465 | for (;;) { | |
466 | if ((pe = ps2pe (ps2)) == NULLPE) | |
467 | break; | |
468 | if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK) | |
469 | goto bad_audit; | |
470 | ||
471 | fseek (fp, (long) au -> sizeOfEncodingWhichFollows, 1); | |
472 | ||
473 | free_SNMP_Audit (au); | |
474 | ||
475 | *lp++ = offset; | |
476 | if (lp >= ep) | |
477 | lp = opp; | |
478 | offset = ftell (fp); | |
479 | } | |
480 | ||
481 | fseek (fp, *lp, 0); | |
482 | free ((char *) opp); | |
483 | follow = 0; | |
484 | } | |
485 | ||
486 | for (i = 1;; i++) { | |
487 | long mtime; | |
488 | UTC ut; | |
489 | ||
490 | if (follow > 0 && i > follow) | |
491 | break; | |
492 | ||
493 | if ((pe = ps2pe (ps2)) == NULLPE) { | |
494 | if (ps2 -> ps_errno) | |
495 | advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno)); | |
496 | else | |
497 | if (forever) { | |
498 | clearerr (fp); | |
499 | ps2 -> ps_errno = PS_ERR_NONE; | |
500 | sleep (1); | |
501 | continue; | |
502 | } | |
503 | break; | |
504 | } | |
505 | if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK) { | |
506 | bad_audit: ; | |
507 | advise (NULLCP, "decode_SNMP_Audit: %s", PY_pepy); | |
508 | break; | |
509 | } | |
510 | ||
511 | if ((cp = qb2str (au -> dateAndTime)) == NULL) { | |
512 | no_mem: ; | |
513 | advise (NULLCP, "qb2str: out of memory"); | |
514 | break; | |
515 | } | |
516 | ut = str2gent (cp, strlen (cp)); | |
517 | free (cp); | |
518 | if (ut == NULL) { | |
519 | advise (NULLCP, "str2gent: you lose"); | |
520 | break; | |
521 | } | |
522 | mtime = gtime (ut2tm (ut)); | |
523 | cp = ctime (&mtime); | |
524 | if (forever) | |
525 | (void) time (&now); | |
526 | if (mtime < longtimeago || mtime > now) | |
527 | printf ("%-7.7s %-4.4s ", cp + 4, cp + 20); | |
528 | else | |
529 | printf ("%-12.12s ", cp + 4); | |
530 | ||
531 | if ((cp = qb2str (au -> source)) == NULL) | |
532 | goto no_mem; | |
533 | printf ("%s\n", cp); | |
534 | free (cp); | |
535 | ||
536 | if ((p = ps2pe (ps2)) == NULLPE) { | |
537 | if (ps2 -> ps_errno) | |
538 | advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno)); | |
539 | break; | |
540 | } | |
541 | if (print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP) == NOTOK) | |
542 | printf ("\n"); | |
543 | ||
544 | free_SNMP_Audit (au), au = NULL; | |
545 | } | |
546 | ||
547 | out: ; | |
548 | (void) fclose (fp); | |
549 | if (ps2) | |
550 | ps_free (ps2); | |
551 | if (pe) | |
552 | pe_free (pe); | |
553 | if (p) | |
554 | pe_free (p); | |
555 | if (au) | |
556 | free_SNMP_Audit (au); | |
557 | ||
558 | return OK; | |
559 | } | |
560 | ||
561 | /* \f */ | |
562 | ||
563 | #ifdef BSD42 | |
564 | int bulk1 (), bulk2 (); | |
565 | ||
566 | static int f_bulk (vec) | |
567 | char **vec; | |
568 | { | |
569 | int result; | |
570 | IFP fnx = bulk1; | |
571 | register struct type_SNMP_VarBindList **vp; | |
572 | struct type_SNMP_VarBindList *vb; | |
573 | OT et = NULL; | |
574 | ||
575 | if (*++vec != NULL && strcmp (*vec, "-help") == 0) { | |
576 | printf ("bulk [-alg1 | -alg2] columns...\n"); | |
577 | printf (" with arguments, bulk retrieves columns from a table\n"); | |
578 | ||
579 | return OK; | |
580 | } | |
581 | while (*vec) { | |
582 | if (strcmp (*vec, "-alg1") == 0) { | |
583 | fnx = bulk1; | |
584 | vec++; | |
585 | continue; | |
586 | } | |
587 | if (strcmp (*vec, "-alg2") == 0) { | |
588 | fnx = bulk2; | |
589 | vec++; | |
590 | continue; | |
591 | } | |
592 | break; | |
593 | } | |
594 | if (*vec == NULL) | |
595 | return OK; | |
596 | ||
597 | #ifdef COTS | |
598 | if (snmp_ta.ta_addrs -> na_stack != NA_TCP) { | |
599 | #ifdef CLTS | |
600 | if (snmp_ta.ta_addrs -> na_stack != NA_NSAP) { | |
601 | #endif | |
602 | advise (NULLCP, "bulk requires CL-mode transport!"); | |
603 | return NOTOK; | |
604 | #ifdef CLTS | |
605 | } | |
606 | #endif | |
607 | } | |
608 | #endif | |
609 | ||
610 | vp = &vb, vb = NULL; | |
611 | for (result = NOTOK; *vec; vec++) { | |
612 | register struct type_SNMP_VarBindList *bind; | |
613 | register struct type_SNMP_VarBind *v; | |
614 | OT ot; | |
615 | ||
616 | if ((ot = text2obj (*vec)) == NULL) { | |
617 | advise (NULLCP, "unknown object \"%s\"", *vec); | |
618 | goto out; | |
619 | } | |
620 | ||
621 | if (et) { | |
622 | register OID eid = et -> ot_name, | |
623 | oid = ot -> ot_name; | |
624 | ||
625 | if (eid -> oid_nelem != oid -> oid_nelem - 1 | |
626 | || bcmp ((char *) eid -> oid_elements, | |
627 | (char *) oid -> oid_elements, | |
628 | eid -> oid_nelem | |
629 | * sizeof (eid -> oid_elements[0])) != 0) { | |
630 | advise (NULLCP, "%s not in same table as previous arguments", | |
631 | ot -> ot_text); | |
632 | goto out; | |
633 | } | |
634 | } | |
635 | else { | |
636 | /* int i; */ | |
637 | ||
638 | ot -> ot_name -> oid_nelem--; | |
639 | et = name2obj (ot -> ot_name); | |
640 | ot -> ot_name -> oid_nelem++; | |
641 | ||
642 | if (et == NULL) { | |
643 | advise (NULLCP, "unable to find row object for %s", | |
644 | ot -> ot_text); | |
645 | goto out; | |
646 | } | |
647 | if (et -> ot_syntax | |
648 | /* || (i = strlen (et -> ot_text)) <= 5 | |
649 | || strcmp (et -> ot_text + i - 5, "Entry")*/) { | |
650 | advise (NULLCP, "%s is not a column object", ot -> ot_text); | |
651 | goto out; | |
652 | } | |
653 | } | |
654 | ||
655 | if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind)) | |
656 | == NULL) | |
657 | adios (NULLCP, "out of memory"); | |
658 | *vp = bind, vp = &bind -> next; | |
659 | ||
660 | if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL) | |
661 | adios (NULLCP, "out of memory"); | |
662 | bind -> VarBind = v; | |
663 | ||
664 | if ((v -> name = oid_cpy (ot -> ot_name)) == NULLOID | |
665 | || (v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, | |
666 | PE_PRIM_NULL)) == NULLPE) | |
667 | adios (NULLCP, "out of memory"); | |
668 | } | |
669 | ||
670 | (*fnx) (ps, sd, vb, community); | |
671 | result = OK; | |
672 | ||
673 | out: ; | |
674 | free_SNMP_VarBindList (vb); | |
675 | return result; | |
676 | } | |
677 | #endif | |
678 | ||
679 | /* \f */ | |
680 | ||
681 | static char *access_t[] = { "not-accessible", | |
682 | "read-only", | |
683 | "write-only", | |
684 | "read-write"}; | |
685 | ||
686 | static char *status_t[] = { "obsolete", | |
687 | "mandatory", | |
688 | "optional", | |
689 | "deprecated" }; | |
690 | ||
691 | ||
692 | static int f_compile (vec) | |
693 | char **vec; | |
694 | { | |
695 | register int i; | |
696 | int fast; | |
697 | char *cp, | |
698 | *file; | |
699 | register OS os; | |
700 | register OT ot; | |
701 | FILE *fp; | |
702 | ||
703 | fast = 0; | |
704 | file = defs ? defs : "./objects.defs"; | |
705 | if (*++vec != NULL && strcmp (*vec, "-help") == 0) { | |
706 | printf ("compile [-f] [file]\n"); | |
707 | printf (" -f: brief output (default to stdout)\n"); | |
708 | printf (" file: output file (default %s)\n", file); | |
709 | ||
710 | return OK; | |
711 | } | |
712 | while (cp = *vec++) { | |
713 | if (strcmp (cp, "-f") == 0) { | |
714 | fast = 1, file = NULLCP; | |
715 | continue; | |
716 | } | |
717 | ||
718 | file = cp; | |
719 | } | |
720 | ||
721 | if (file) { | |
722 | if ((fp = fopen (file, "w")) == NULL) { | |
723 | advise (file, "unable to write"); | |
724 | return OK; | |
725 | } | |
726 | if (!fast) { | |
727 | register int j, | |
728 | k; | |
729 | ||
730 | i = j = k = 0; | |
731 | for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) { | |
732 | i++; | |
733 | j += strlen (ot -> ot_text) | |
734 | + strlen (sprintoid (ot -> ot_name)); | |
735 | k += ot -> ot_name -> oid_nelem; | |
736 | } | |
737 | j += i << 1, k += i; | |
738 | fprintf (fp, "--* compiled %d %d %d\n", i, j, k); | |
739 | } | |
740 | } | |
741 | else | |
742 | fp = stdout; | |
743 | ||
744 | for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) { | |
745 | if (fast) { | |
746 | fprintf (fp, "%s=%s\n", ot -> ot_text, sprintoid (ot -> ot_name)); | |
747 | continue; | |
748 | } | |
749 | ||
750 | fprintf (fp, "%-20s %-20s", ot -> ot_text, sprintoid (ot -> ot_name)); | |
751 | if ((os = ot -> ot_syntax) || ot -> ot_status) | |
752 | fprintf (fp, " %-15s %-15s %s", | |
753 | os ? os -> os_name : "Aggregate", | |
754 | access_t[ot -> ot_access & OT_RDWRITE], | |
755 | status_t[ot -> ot_status & OT_DEPRECATED]); | |
756 | fprintf (fp, "\n"); | |
757 | } | |
758 | ||
759 | if (file) | |
760 | (void) fclose (fp); | |
761 | ||
762 | if (!fast) | |
763 | advise (NULLCP, "%d objects written to %s", i, file); | |
764 | ||
765 | return OK; | |
766 | } | |
767 | ||
768 | /* \f */ | |
769 | ||
770 | static int f_dump (vec) | |
771 | char **vec; | |
772 | { | |
773 | int request_id, | |
774 | rows, | |
775 | timing = 0; | |
776 | char *nvec[3]; | |
777 | OID oid; | |
778 | PE pe; | |
779 | struct type_SNMP_Message *msg; | |
780 | register struct type_SNMP_PDU *parm; | |
781 | register struct type_SNMP_VarBindList *vp; | |
782 | struct timeval tvs, | |
783 | now; | |
784 | ||
785 | if (*++vec != NULL && strcmp (*vec, "-help") == 0) { | |
786 | printf ("dump [object]\n"); | |
787 | printf (" with no arguments, dump entire MIB\n"); | |
788 | printf (" with an argument, dump a portion of the MIB\n"); | |
789 | ||
790 | return OK; | |
791 | } | |
792 | if (*vec && strcmp (*vec, "-time") == 0) { | |
793 | timing++; | |
794 | (void) gettimeofday (&tvs, (struct timezone *) 0); | |
795 | vec++; | |
796 | } | |
797 | ||
798 | nvec[0] = "dump"; | |
799 | nvec[1] = *vec ? *vec : "0.0"; | |
800 | nvec[2] = NULL; | |
801 | ||
802 | if ((msg = new_message (type_SNMP_PDUs_get__next__request, nvec)) == NULL) | |
803 | return OK; | |
804 | ||
805 | request_id = msg -> data -> un.get__response -> request__id = 0; | |
806 | ||
807 | if (*vec) { | |
808 | if ((oid = oid_cpy (msg -> data -> un.get__next__request -> | |
809 | variable__bindings -> VarBind -> name)) == NULLOID) | |
810 | adios (NULLCP, "out of memory"); | |
811 | } | |
812 | else | |
813 | oid = NULLOID; | |
814 | rows = 0; | |
815 | ||
816 | again: ; | |
817 | pe = NULLPE; | |
818 | ||
819 | if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) { | |
820 | if (watch) | |
821 | (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); | |
822 | ||
823 | if (pe2ps (ps, pe) == NOTOK) { | |
824 | advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno)); | |
825 | goto out; | |
826 | } | |
827 | } | |
828 | else | |
829 | advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy); | |
830 | ||
831 | try_again: ; | |
832 | if (pe) | |
833 | pe_free (pe); | |
834 | pe = NULLPE; | |
835 | ||
836 | free_SNMP_Message (msg); | |
837 | msg = NULL; | |
838 | ||
839 | if ((pe = ps2pe (ps)) == NULLPE) { | |
840 | advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno)); | |
841 | goto out; | |
842 | } | |
843 | ||
844 | if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) { | |
845 | advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy); | |
846 | goto out; | |
847 | } | |
848 | ||
849 | if (watch) | |
850 | (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); | |
851 | ||
852 | if (msg -> data -> offset != type_SNMP_PDUs_get__response) { | |
853 | advise (NULLCP, "unexpected message type %d", | |
854 | msg -> data -> offset); | |
855 | goto out; | |
856 | } | |
857 | ||
858 | if ((parm = msg -> data -> un.get__response) -> request__id | |
859 | != request_id) { | |
860 | fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n", | |
861 | parm -> request__id, request_id); | |
862 | goto try_again; | |
863 | } | |
864 | ||
865 | if (parm -> error__status != int_SNMP_error__status_noError) { | |
866 | if (parm -> error__status != int_SNMP_error__status_noSuchName) | |
867 | fprintf (stderr, "%s at position %d\n", | |
868 | snmp_error (parm -> error__status), parm -> error__index); | |
869 | goto out; | |
870 | } | |
871 | ||
872 | for (vp = parm -> variable__bindings; vp; vp = vp -> next) { | |
873 | caddr_t value; | |
874 | register OI oi; | |
875 | register OS os; | |
876 | register struct type_SNMP_VarBind *v = vp -> VarBind; | |
877 | ||
878 | if (oid | |
879 | && (oid -> oid_nelem > v -> name -> oid_nelem | |
880 | || bcmp ((char *) oid -> oid_elements, | |
881 | (char *) v -> name -> oid_elements, | |
882 | oid -> oid_nelem | |
883 | * sizeof oid -> oid_elements[0]))) | |
884 | goto out; | |
885 | ||
886 | if (timing) | |
887 | continue; | |
888 | ||
889 | printf ("%s=", oid2ode (vp -> VarBind -> name)); | |
890 | if ((oi = name2inst (v -> name)) == NULL | |
891 | || (os = oi -> oi_type -> ot_syntax) == NULL | |
892 | || (*os -> os_decode) (&value, v -> value) == NOTOK) | |
893 | vunknown (v -> value); | |
894 | else { | |
895 | (*os -> os_print) (value, os); | |
896 | printf ("\n"); | |
897 | ||
898 | (*os -> os_free) (value); | |
899 | } | |
900 | } | |
901 | rows++; | |
902 | ||
903 | if (pe) | |
904 | pe_free (pe); | |
905 | msg -> data -> offset = type_SNMP_PDUs_get__next__request; | |
906 | request_id = ++parm -> request__id; | |
907 | goto again; | |
908 | ||
909 | out: ; | |
910 | if (oid) | |
911 | oid_free (oid); | |
912 | if (pe) | |
913 | pe_free (pe); | |
914 | if (msg) | |
915 | free_SNMP_Message (msg); | |
916 | ||
917 | if (timing) { | |
918 | (void) gettimeofday (&now, (struct timezone *) 0); | |
919 | now.tv_sec -= tvs.tv_sec; | |
920 | if ((now.tv_usec -= tvs.tv_usec) < 0) | |
921 | now.tv_sec--, now.tv_usec += 1000000; | |
922 | advise (NULLCP, | |
923 | "%d entr%s retrieved in %d.%06d seconds", | |
924 | rows, rows != 1 ? "ies" : "y", now.tv_sec, now.tv_usec); | |
925 | } | |
926 | ||
927 | return OK; | |
928 | } | |
929 | ||
930 | /* \f */ | |
931 | ||
932 | static int f_get (vec) | |
933 | char **vec; | |
934 | { | |
935 | (void) process (new_message (type_SNMP_PDUs_get__request, vec)); | |
936 | } | |
937 | ||
938 | /* \f */ | |
939 | ||
940 | static int f_get_next (vec) | |
941 | char **vec; | |
942 | { | |
943 | (void) process (new_message (type_SNMP_PDUs_get__next__request, vec)); | |
944 | } | |
945 | ||
946 | /* \f */ | |
947 | ||
948 | static int f_set (vec) | |
949 | char **vec; | |
950 | { | |
951 | (void) process (new_message (type_SNMP_PDUs_set__request, vec)); | |
952 | } | |
953 | ||
954 | /* \f */ | |
955 | ||
956 | static char *errors[] = { | |
957 | "noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr" | |
958 | }; | |
959 | ||
960 | ||
961 | char *snmp_error (i) | |
962 | integer i; | |
963 | { | |
964 | static char buffer[BUFSIZ]; | |
965 | ||
966 | if (0 < i && i < sizeof errors / sizeof errors[0]) | |
967 | return errors[i]; | |
968 | (void) sprintf (buffer, "error %d", i); | |
969 | ||
970 | return buffer; | |
971 | } | |
972 | ||
973 | /* \f */ | |
974 | ||
975 | static struct type_SNMP_Message *new_message (offset, vec) | |
976 | int offset; | |
977 | char **vec; | |
978 | { | |
979 | register struct type_SNMP_Message *msg; | |
980 | register struct type_SNMP_PDUs *pdu; | |
981 | register struct type_SNMP_PDU *parm; | |
982 | register struct type_SNMP_VarBindList **vp; | |
983 | ||
984 | if ((msg = (struct type_SNMP_Message *) calloc (1, sizeof *msg)) == NULL) | |
985 | adios (NULLCP, "out of memory"); | |
986 | ||
987 | msg -> version = int_SNMP_version_version__1; | |
988 | ||
989 | if ((msg -> community = str2qb (community, strlen (community), 1)) == NULL) | |
990 | adios (NULLCP, "out of memory"); | |
991 | ||
992 | if ((pdu = (struct type_SNMP_PDUs *) calloc (1, sizeof *pdu)) == NULL) | |
993 | adios (NULLCP, "out of memory"); | |
994 | msg -> data = pdu; | |
995 | ||
996 | pdu -> offset = offset; | |
997 | ||
998 | /* for now, always a PDU... */ | |
999 | ||
1000 | if ((parm = (struct type_SNMP_PDU *) calloc (1, sizeof *parm)) == NULL) | |
1001 | adios (NULLCP, "out of memory"); | |
1002 | pdu -> un.get__request = parm; | |
1003 | ||
1004 | #ifndef SYS5 | |
1005 | parm -> request__id = ((int) random ()) & 0x7fffffff; | |
1006 | #else | |
1007 | parm -> request__id = ((int) rand ()) & 0x7fffffff; | |
1008 | #endif | |
1009 | ||
1010 | vp = &parm -> variable__bindings; | |
1011 | for (vec++; *vec; vec++) { | |
1012 | register struct type_SNMP_VarBindList *bind; | |
1013 | register struct type_SNMP_VarBind *v; | |
1014 | ||
1015 | if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind)) | |
1016 | == NULL) | |
1017 | adios (NULLCP, "out of memory"); | |
1018 | *vp = bind, vp = &bind -> next; | |
1019 | ||
1020 | if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL) | |
1021 | adios (NULLCP, "out of memory"); | |
1022 | bind -> VarBind = v; | |
1023 | ||
1024 | if (get_ava (v, *vec, offset) == NOTOK) { | |
1025 | free_SNMP_Message (msg); | |
1026 | return NULL; | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | return msg; | |
1031 | } | |
1032 | ||
1033 | /* \f */ | |
1034 | ||
1035 | static int get_ava (v, ava, offset) | |
1036 | register struct type_SNMP_VarBind *v; | |
1037 | char *ava; | |
1038 | int offset; | |
1039 | { | |
1040 | int result; | |
1041 | caddr_t value; | |
1042 | register char *cp; | |
1043 | register OI oi; | |
1044 | register OT ot; | |
1045 | register OS os; | |
1046 | OID oid; | |
1047 | ||
1048 | if (cp = index (ava, '=')) { | |
1049 | if (offset != type_SNMP_PDUs_set__request) | |
1050 | advise (NULLCP, "value unnecessary for get operation"); | |
1051 | *cp++ = NULL; | |
1052 | } | |
1053 | else | |
1054 | if (offset == type_SNMP_PDUs_set__request) { | |
1055 | advise (NULLCP, "need variable=value for set operation"); | |
1056 | return NOTOK; | |
1057 | } | |
1058 | ||
1059 | if ((oi = text2inst (ava)) == NULL) { | |
1060 | if (cp || (oid = text2oid (ava)) == NULL) { | |
1061 | advise (NULLCP, "unknown variable \"%s\"", ava); | |
1062 | return NOTOK; | |
1063 | } | |
1064 | ||
1065 | ot = NULLOT; | |
1066 | } | |
1067 | else | |
1068 | ot = oi -> oi_type; | |
1069 | ||
1070 | if ((v -> name = oid_cpy (oi ? oi -> oi_name : oid)) == NULLOID) | |
1071 | adios (NULLCP, "out of memory"); | |
1072 | ||
1073 | if (cp == NULL) { | |
1074 | if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL)) | |
1075 | == NULLPE) | |
1076 | adios (NULLCP, "out of memory"); | |
1077 | } | |
1078 | else { | |
1079 | if ((os = ot -> ot_syntax) == NULL) { | |
1080 | advise (NULLCP, "no syntax defined for object \"%s\"", ava); | |
1081 | return NOTOK; | |
1082 | } | |
1083 | ||
1084 | if ((*os -> os_parse) (&value, cp) == NOTOK) { | |
1085 | advise (NULLCP, "invalid value for variable \"%s\": \"%s\"", | |
1086 | ava, cp); | |
1087 | return NOTOK; | |
1088 | } | |
1089 | result = (*os -> os_encode) (value, &v -> value); | |
1090 | (*os -> os_free) (value); | |
1091 | ||
1092 | if (result == NOTOK) { | |
1093 | advise (NULLCP, "encoding error for variable \"%s\"", ava); | |
1094 | return NOTOK; | |
1095 | } | |
1096 | } | |
1097 | ||
1098 | if (oi == NULL) | |
1099 | oid_free (oid); | |
1100 | ||
1101 | return OK; | |
1102 | } | |
1103 | ||
1104 | /* \f */ | |
1105 | ||
1106 | static int process (msg) | |
1107 | struct type_SNMP_Message *msg; | |
1108 | { | |
1109 | int request_id; | |
1110 | PE pe; | |
1111 | register struct type_SNMP_PDU *parm; | |
1112 | register struct type_SNMP_VarBindList *vp; | |
1113 | ||
1114 | if (msg == NULL) | |
1115 | return OK; | |
1116 | ||
1117 | request_id = msg -> data -> un.get__request -> request__id; | |
1118 | if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) { | |
1119 | if (watch) | |
1120 | (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); | |
1121 | ||
1122 | if (pe2ps (ps, pe) == NOTOK) { | |
1123 | advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno)); | |
1124 | goto out; | |
1125 | } | |
1126 | } | |
1127 | else | |
1128 | advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy); | |
1129 | ||
1130 | try_again: ; | |
1131 | if (pe) | |
1132 | pe_free (pe); | |
1133 | pe = NULLPE; | |
1134 | ||
1135 | free_SNMP_Message (msg); | |
1136 | msg = NULL; | |
1137 | ||
1138 | if ((pe = ps2pe (ps)) == NULLPE) { | |
1139 | advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno)); | |
1140 | goto out; | |
1141 | } | |
1142 | ||
1143 | if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) { | |
1144 | advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy); | |
1145 | goto out; | |
1146 | } | |
1147 | ||
1148 | if (watch) | |
1149 | (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP); | |
1150 | ||
1151 | if (msg -> data -> offset != type_SNMP_PDUs_get__response) { | |
1152 | advise (NULLCP, "unexpected message type %d", | |
1153 | msg -> data -> offset); | |
1154 | goto out; | |
1155 | } | |
1156 | ||
1157 | if ((parm = msg -> data -> un.get__response) -> request__id | |
1158 | != request_id) { | |
1159 | fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n", | |
1160 | parm -> request__id, request_id); | |
1161 | goto try_again; | |
1162 | } | |
1163 | ||
1164 | if (parm -> error__status != int_SNMP_error__status_noError) { | |
1165 | fprintf (stderr, "%s at position %d\n", | |
1166 | snmp_error (parm -> error__status), parm -> error__index); | |
1167 | goto out; | |
1168 | } | |
1169 | ||
1170 | for (vp = parm -> variable__bindings; vp; vp = vp -> next) { | |
1171 | caddr_t value; | |
1172 | register OI oi; | |
1173 | register OS os; | |
1174 | register struct type_SNMP_VarBind *v = vp -> VarBind; | |
1175 | ||
1176 | if ((oi = name2inst (v -> name)) == NULL) { | |
1177 | advise (NULLCP, "unknown variable \"%s\"", oid2ode (v -> name)); | |
1178 | no_dice: ; | |
1179 | printf ("%s=", oid2ode (v -> name)); | |
1180 | vunknown (v -> value); | |
1181 | continue; | |
1182 | } | |
1183 | if ((os = oi -> oi_type -> ot_syntax) == NULL) { | |
1184 | advise (NULLCP, "unknown syntax for object \"%s\"", | |
1185 | oi -> oi_type -> ot_text); | |
1186 | goto no_dice; | |
1187 | } | |
1188 | if ((*os -> os_decode) (&value, v -> value) == NOTOK) { | |
1189 | advise (NULLCP, "decode error for variable \"%s\"", | |
1190 | oid2ode (v -> name)); | |
1191 | goto no_dice; | |
1192 | } | |
1193 | ||
1194 | printf ("%s=", oid2ode (v -> name)); | |
1195 | (*os -> os_print) (value, os); | |
1196 | printf ("\n"); | |
1197 | ||
1198 | (*os -> os_free) (value); | |
1199 | } | |
1200 | ||
1201 | out: ; | |
1202 | if (pe) | |
1203 | pe_free (pe); | |
1204 | if (msg) | |
1205 | free_SNMP_Message (msg); | |
1206 | ||
1207 | return OK; | |
1208 | } | |
1209 | ||
1210 | /* \f */ | |
1211 | ||
1212 | static int f_help (vec) | |
1213 | char **vec; | |
1214 | { | |
1215 | register int i, | |
1216 | j, | |
1217 | w; | |
1218 | int columns, | |
1219 | width, | |
1220 | lines; | |
1221 | register struct dispatch *ds, | |
1222 | *es; | |
1223 | ||
1224 | for (es = dispatches; es -> ds_name; es++) | |
1225 | continue; | |
1226 | width = helpwidth; | |
1227 | ||
1228 | if (*++vec == NULL) { | |
1229 | if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0) | |
1230 | columns = 1; | |
1231 | lines = ((es - dispatches) + columns - 1) / columns; | |
1232 | ||
1233 | printf ("Operations:\n"); | |
1234 | for (i = 0; i < lines; i++) | |
1235 | for (j = 0; j < columns; j++) { | |
1236 | ds = dispatches + j * lines + i; | |
1237 | printf ("%s", ds -> ds_name); | |
1238 | if (ds + lines >= es) { | |
1239 | printf ("\n"); | |
1240 | break; | |
1241 | } | |
1242 | for (w = strlen (ds -> ds_name); w < width; w = (w + 8) & ~7) | |
1243 | (void) putchar ('\t'); | |
1244 | } | |
1245 | printf ("\n"); | |
1246 | ||
1247 | return OK; | |
1248 | } | |
1249 | ||
1250 | if (strcmp (*vec, "-help") == 0) { | |
1251 | printf ("help [commands ...]\n"); | |
1252 | printf (" with no arguments, lists operations which may be invoked\n"); | |
1253 | printf (" otherwise prints help for each operation given\n"); | |
1254 | ||
1255 | return OK; | |
1256 | } | |
1257 | ||
1258 | for (; *vec; vec++) | |
1259 | if (strcmp (*vec, "?") == 0) { | |
1260 | for (ds = dispatches; ds -> ds_name; ds++) | |
1261 | printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help); | |
1262 | ||
1263 | break; | |
1264 | } | |
1265 | else | |
1266 | if (ds = getds (*vec)) | |
1267 | printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help); | |
1268 | ||
1269 | return OK; | |
1270 | } | |
1271 | ||
1272 | /* \f */ | |
1273 | ||
1274 | static int f_quit (vec) | |
1275 | char **vec; | |
1276 | { | |
1277 | if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) { | |
1278 | printf ("quit\n"); | |
1279 | printf (" terminate fred\n"); | |
1280 | ||
1281 | return OK; | |
1282 | } | |
1283 | ||
1284 | return DONE; | |
1285 | } | |
1286 | ||
1287 | /* \f */ | |
1288 | ||
1289 | static int f_status (vec) | |
1290 | char **vec; | |
1291 | { | |
1292 | if (*++vec != NULL && strcmp (*vec, "-help") == 0) { | |
1293 | printf ("status\n"); | |
1294 | printf (" report status\n"); | |
1295 | ||
1296 | return OK; | |
1297 | } | |
1298 | ||
1299 | printf ("Connected to %s using community \"%s\"\n", | |
1300 | taddr2str (&snmp_ta), community); | |
1301 | ||
1302 | return OK; | |
1303 | } | |
1304 | ||
1305 | /* \f SYNTAX */ | |
1306 | ||
1307 | static char *ifType[] = { | |
1308 | "other", "regular1822", "hdh1822", "ddn-x25", "rfc877-x25", | |
1309 | "ethernet-csmacd", "iso88023-csmacd", "iso88024-tokenBus", | |
1310 | "iso88025-tokenRing", "iso88026-man", "starLan", "proteon-10Mbit", | |
1311 | "proteon-80Mbit", "hyperchannel", "fddi", "lapb", "sdlc", "t1-carrier", | |
1312 | "cept", "basicISDN", "primaryISDN", "propPointToPointSerial", | |
1313 | "ppp", "softwareLoopback", "eon", "ethernet-3Mbit", | |
1314 | "nsip", "slip" | |
1315 | }; | |
1316 | ||
1317 | static char *ifStatus[] = { | |
1318 | "up", "down", "testing" | |
1319 | }; | |
1320 | ||
1321 | static char *ipForwarding[] = { | |
1322 | "gateway", "host" | |
1323 | }; | |
1324 | ||
1325 | static char *routeType[] = { | |
1326 | "other", "invalid", "direct", "remote" | |
1327 | }; | |
1328 | ||
1329 | static char *ipRouteProto[] = { | |
1330 | "other", "local", "netmgmt", "icmp", "egp", "ggp", "hello", "rip", "is-is", | |
1331 | "es-is", "ciscoIgrp", "bbnSpfIgp", "ospf", "bgp" | |
1332 | }; | |
1333 | ||
1334 | static char *netToMediaType[] = { | |
1335 | "other", "invalid", "dynamic", "static" | |
1336 | }; | |
1337 | ||
1338 | static char *tcpRtoAlgorithm[] = { | |
1339 | "other", "constant", "rsre", "vanj" | |
1340 | }; | |
1341 | ||
1342 | static char *tcpConnState[] = { | |
1343 | "closed", "listen", "synSent", "synReceived", "established", "finWait1", | |
1344 | "finWait2", "closeWait", "lastAck", "closing", "timewait" | |
1345 | }; | |
1346 | ||
1347 | static char *egpNeighState[] = { | |
1348 | "idle", "acquisition", "down", "up", "cease" | |
1349 | }; | |
1350 | ||
1351 | static char *egpNeighMode[] = { | |
1352 | "active", "passive" | |
1353 | }; | |
1354 | ||
1355 | static char *egpNeighEventTrigger[] = { | |
1356 | "start", "stop" | |
1357 | }; | |
1358 | ||
1359 | static char *enabled[] = { | |
1360 | "enabled", "disabled" | |
1361 | }; | |
1362 | ||
1363 | ||
1364 | static char *status[] = { | |
1365 | "valid", "invalid" | |
1366 | }; | |
1367 | ||
1368 | static char *smuxPstatus[] = { | |
1369 | "valid", "invalid", "connecting" | |
1370 | }; | |
1371 | ||
1372 | ||
1373 | static struct ivar { | |
1374 | char *iv_object; | |
1375 | ||
1376 | char **iv_values; | |
1377 | int iv_nvalue; | |
1378 | } ivars[] = { | |
1379 | "ifType", ifType, | |
1380 | sizeof ifType / sizeof ifType[0], | |
1381 | ||
1382 | "ifAdminStatus", ifStatus, | |
1383 | sizeof ifStatus / sizeof ifStatus[0], | |
1384 | ||
1385 | "ifOperStatus", ifStatus, | |
1386 | sizeof ifStatus / sizeof ifStatus[0], | |
1387 | ||
1388 | "ipForwarding", ipForwarding, | |
1389 | sizeof ipForwarding / sizeof ipForwarding[0], | |
1390 | ||
1391 | "ipRouteType", routeType, | |
1392 | sizeof routeType / sizeof routeType[0], | |
1393 | ||
1394 | "ipRouteProto", ipRouteProto, | |
1395 | sizeof ipRouteProto / sizeof ipRouteProto[0], | |
1396 | ||
1397 | "ipNetToMediaType", netToMediaType, | |
1398 | sizeof netToMediaType / sizeof netToMediaType[0], | |
1399 | ||
1400 | "tcpRtoAlgorithm", tcpRtoAlgorithm, | |
1401 | sizeof tcpRtoAlgorithm / sizeof tcpRtoAlgorithm[0], | |
1402 | ||
1403 | "tcpConnState", tcpConnState, | |
1404 | sizeof tcpConnState / sizeof tcpConnState[0], | |
1405 | ||
1406 | "egpNeighState", egpNeighState, | |
1407 | sizeof egpNeighState / sizeof egpNeighState[0], | |
1408 | ||
1409 | "egpNeighMode", egpNeighMode, | |
1410 | sizeof egpNeighMode / sizeof egpNeighMode[0], | |
1411 | ||
1412 | "egpNeighEventTrigger", egpNeighEventTrigger, | |
1413 | sizeof egpNeighEventTrigger / sizeof egpNeighEventTrigger[0], | |
1414 | ||
1415 | "snmpEnableAuthenTraps", enabled, | |
1416 | sizeof enabled / sizeof enabled[0], | |
1417 | ||
1418 | "smuxPstatus", smuxPstatus, | |
1419 | sizeof smuxPstatus / sizeof smuxPstatus[0], | |
1420 | ||
1421 | "smuxTstatus", status, | |
1422 | sizeof status / sizeof status[0], | |
1423 | ||
1424 | "unixNetstat", enabled, | |
1425 | sizeof enabled / sizeof enabled[0], | |
1426 | ||
1427 | NULL | |
1428 | }; | |
1429 | ||
1430 | /* \f */ | |
1431 | ||
1432 | static int enum_print (x, os) | |
1433 | integer *x; | |
1434 | OS os; | |
1435 | { | |
1436 | int i = *x; | |
1437 | ||
1438 | if (i <= 0 || i > os -> os_data2) | |
1439 | printf ("unknown(%d)", i); | |
1440 | else | |
1441 | printf ("%s(%d)", os -> os_data1[i - 1], i); | |
1442 | } | |
1443 | ||
1444 | ||
1445 | static moresyntax () { | |
1446 | register struct ivar *iv; | |
1447 | register OT ot; | |
1448 | register OS os; | |
1449 | ||
1450 | for (iv = ivars; iv -> iv_object; iv++) | |
1451 | if (ot = text2obj (iv -> iv_object)) { | |
1452 | char *name; | |
1453 | ||
1454 | if ((os = ot -> ot_syntax) == NULL) { | |
1455 | advise (NULLCP, "no syntax defined for object \"%s\"", | |
1456 | iv -> iv_object); | |
1457 | continue; | |
1458 | } | |
1459 | name = os -> os_name; | |
1460 | ||
1461 | (void) add_syntax (iv -> iv_object, os -> os_encode, | |
1462 | os -> os_decode, os -> os_free, os -> os_parse, | |
1463 | enum_print); | |
1464 | if ((os = text2syn (iv -> iv_object)) == NULL) | |
1465 | adios (NULLCP, "lost syntax for object \"%s\"", | |
1466 | iv -> iv_object); | |
1467 | ot -> ot_syntax = os; | |
1468 | os -> os_name = name; | |
1469 | os -> os_data1 = iv -> iv_values; | |
1470 | os -> os_data2 = iv -> iv_nvalue; | |
1471 | } | |
1472 | else | |
1473 | advise (NULLCP, "no \"%s\" object", iv -> iv_object); | |
1474 | } | |
1475 | ||
1476 | /* \f MISCELLANY */ | |
1477 | ||
1478 | static arginit (vec) | |
1479 | char **vec; | |
1480 | { | |
1481 | int w; | |
1482 | register char *ap, | |
1483 | *pp; | |
1484 | register struct dispatch *ds; | |
1485 | #ifdef TCP | |
1486 | int port; | |
1487 | struct sockaddr_in in_socket; | |
1488 | register struct sockaddr_in *isock = &in_socket; | |
1489 | register struct hostent *hp; | |
1490 | register struct servent *sp; | |
1491 | #endif | |
1492 | register struct TSAPaddr *ta = &snmp_ta, | |
1493 | *tz; | |
1494 | register struct NSAPaddr *na = ta -> ta_addrs; | |
1495 | ||
1496 | if (myname = rindex (*vec, '/')) | |
1497 | myname++; | |
1498 | if (myname == NULL || *myname == NULL) | |
1499 | myname = *vec; | |
1500 | ||
1501 | isodetailor (myname, 1); | |
1502 | ||
1503 | if (ontty = isatty (fileno (stdin))) | |
1504 | verbose++; | |
1505 | ||
1506 | if ((sp = getservbyname ("snmp", "udp")) == NULL) | |
1507 | advise (NULLCP, "udp/snmp: unknown service"); | |
1508 | ||
1509 | bzero ((char *) ta, sizeof *ta); | |
1510 | #ifdef TCP | |
1511 | na -> na_stack = NA_TCP; | |
1512 | na -> na_community = ts_comm_tcp_default; | |
1513 | (void) strncpy (na -> na_domain, getlocalhost (), | |
1514 | sizeof na -> na_domain - 1); | |
1515 | na -> na_port = sp ? sp -> s_port : htons ((u_short) 161); | |
1516 | na -> na_tset = NA_TSET_UDP; | |
1517 | ta -> ta_naddr = 1; | |
1518 | #endif | |
1519 | ||
1520 | for (vec++; ap = *vec; vec++) { | |
1521 | if (*ap == '-') { | |
1522 | while (*++ap) | |
1523 | switch (*ap) { | |
1524 | case 'a': /* e.g., NS+0504030201 */ | |
1525 | if ((pp = *++vec) == NULL || *pp == '-') | |
1526 | adios (NULLCP, "usage: %s -a agent", myname); | |
1527 | #ifdef TCP | |
1528 | if (hp = gethostbystring (pp)) { | |
1529 | if (na -> na_stack != NA_TCP) | |
1530 | adios (NULLCP, "use -a at most once..."); | |
1531 | inaddr_copy (hp, isock); | |
1532 | (void) strncpy (na -> na_domain, | |
1533 | inet_ntoa (isock -> sin_addr), | |
1534 | sizeof na -> na_domain - 1); | |
1535 | } | |
1536 | else | |
1537 | #endif | |
1538 | if ((tz = str2taddr (pp)) && tz -> ta_naddr > 0) { | |
1539 | *ta = *tz; /* struct copy */ | |
1540 | if (na -> na_stack == NA_TCP) { | |
1541 | if (na -> na_port == 0) | |
1542 | na -> na_port = sp ? sp -> s_port | |
1543 | : htons ((u_short) 161); | |
1544 | na -> na_tset = NA_TSET_UDP; | |
1545 | } | |
1546 | } | |
1547 | else | |
1548 | adios (NULLCP, "%s: unknown host", pp); | |
1549 | break; | |
1550 | ||
1551 | #ifdef TCP | |
1552 | case 'p': | |
1553 | if ((pp = *++vec) == NULL | |
1554 | || *pp == '-' | |
1555 | || (port = atoi (pp)) <= 0) | |
1556 | adios (NULLCP, "usage: %s -p portno", myname); | |
1557 | if (na -> na_stack != NA_TCP) | |
1558 | adios (NULLCP, "-p not allowed with %s", | |
1559 | taddr2str (ta)); | |
1560 | na -> na_port = htons ((u_short) port); | |
1561 | break; | |
1562 | #endif | |
1563 | ||
1564 | case 'c': | |
1565 | if ((pp = *++vec) == NULL || *pp == '-') | |
1566 | adios (NULLCP, "usage: %s -c community", myname); | |
1567 | community = pp; | |
1568 | break; | |
1569 | ||
1570 | case 'd': | |
1571 | debug++; | |
1572 | break; | |
1573 | ||
1574 | case 'v': | |
1575 | verbose++; | |
1576 | break; | |
1577 | ||
1578 | case 'w': | |
1579 | watch++; | |
1580 | break; | |
1581 | ||
1582 | case 'f': | |
1583 | if ((pp = *++vec) == NULL || *pp == '-') | |
1584 | adios (NULLCP, "usage: %s -f file", myname); | |
1585 | defs = pp; | |
1586 | break; | |
1587 | ||
1588 | default: | |
1589 | adios (NULLCP, "unknown switch -%c", *ap); | |
1590 | } | |
1591 | continue; | |
1592 | } | |
1593 | if (op == NULL) { | |
1594 | op = vec; | |
1595 | break; | |
1596 | } | |
1597 | } | |
1598 | ||
1599 | helpwidth = 0; | |
1600 | for (ds = dispatches; ds -> ds_name; ds++) | |
1601 | if ((w = strlen (ds -> ds_name)) > helpwidth) | |
1602 | helpwidth = w; | |
1603 | ||
1604 | if (ta -> ta_naddr == 0) | |
1605 | adios (NULLCP, "usage: %s -a string", myname); | |
1606 | switch (na -> na_stack) { | |
1607 | case NA_TCP: | |
1608 | #ifdef TCP | |
1609 | { | |
1610 | struct sockaddr_in lo_socket; | |
1611 | register struct sockaddr_in *lsock = &lo_socket; | |
1612 | ||
1613 | bzero ((char *) lsock, sizeof *lsock); | |
1614 | if ((hp = gethostbystring (pp = getlocalhost ())) == NULL) | |
1615 | adios (NULLCP, "%s: unknown host", pp); | |
1616 | lsock -> sin_family = hp -> h_addrtype; | |
1617 | inaddr_copy (hp, lsock); | |
1618 | /* If the request is being sent out on the loopback interface, | |
1619 | make sure it appears to have originated from the loopback | |
1620 | interface, rather than the interface used as the default | |
1621 | hostname. If the interface used as the default hostname | |
1622 | is a serial link, responses to requests with this origin | |
1623 | may be undeliverable. (EJP) */ | |
1624 | #define LOOPBACK ((127 << 24) + 1) | |
1625 | if (isock -> sin_addr.s_addr == LOOPBACK) | |
1626 | lsock -> sin_addr.s_addr = LOOPBACK; | |
1627 | #undef LOOPBACK | |
1628 | if ((sd = start_udp_client (lsock, 0, 0, 0)) == NOTOK) | |
1629 | adios ("failed", "start_udp_client"); | |
1630 | ||
1631 | bzero ((char *) isock, sizeof *isock); | |
1632 | if ((hp = gethostbystring (na -> na_domain)) == NULL) | |
1633 | adios (NULLCP, "%s: unknown host", na -> na_domain); | |
1634 | isock -> sin_family = hp -> h_addrtype; | |
1635 | isock -> sin_port = na -> na_port; | |
1636 | inaddr_copy (hp, isock); | |
1637 | ||
1638 | if (join_udp_server (sd, isock) == NOTOK) | |
1639 | adios ("failed", "join_udp_server"); | |
1640 | ||
1641 | if ((ps = ps_alloc (dg_open)) == NULLPS | |
1642 | || dg_setup (ps, sd, MAXDGRAM, read_udp_socket, | |
1643 | write_udp_socket, check_udp_socket) | |
1644 | == NOTOK) { | |
1645 | if (ps == NULLPS) | |
1646 | adios (NULLCP, "ps_alloc: out of memory"); | |
1647 | else | |
1648 | adios (NULLCP, "dg_setup: %s", | |
1649 | ps_error (ps -> ps_errno)); | |
1650 | } | |
1651 | } | |
1652 | break; | |
1653 | #else | |
1654 | adios (NULLCP, "UDP support not configured"); | |
1655 | #endif | |
1656 | ||
1657 | case NA_X25: | |
1658 | #ifdef X25 | |
1659 | goto cots; | |
1660 | #else | |
1661 | adios (NULLCP, "X.25 support not configured"); | |
1662 | #endif | |
1663 | ||
1664 | case NA_NSAP: | |
1665 | #ifdef CLTS | |
1666 | { | |
1667 | union sockaddr_osi lo_socket; | |
1668 | register union sockaddr_osi *lsock = &lo_socket; | |
1669 | ||
1670 | bzero ((char *) lsock, sizeof *lsock); | |
1671 | if ((sd = start_clts_client (lsock, 0, 0, 0)) == NOTOK) | |
1672 | adios ("failed", "start_clts_client"); | |
1673 | ||
1674 | (void) gen2tp4 (ta, lsock); | |
1675 | if (join_clts_server (sd, lsock) == NOTOK) | |
1676 | adios ("failed", "join_udp_server"); | |
1677 | ||
1678 | if ((ps = ps_alloc (dg_open)) == NULLPS | |
1679 | || dg_setup (ps, sd, MAXDGRAM, read_clts_socket, | |
1680 | write_clts_socket, check_clts_socket) | |
1681 | == NOTOK) { | |
1682 | if (ps == NULLPS) | |
1683 | adios (NULLCP, "ps_alloc: out of memory"); | |
1684 | else | |
1685 | adios (NULLCP, "dg_setup: %s", | |
1686 | ps_error (ps -> ps_errno)); | |
1687 | } | |
1688 | } | |
1689 | break; | |
1690 | #else | |
1691 | #ifdef TP4 | |
1692 | goto cots; | |
1693 | #else | |
1694 | adios (NULLCP, "TP4 support not configured"); | |
1695 | #endif | |
1696 | #endif | |
1697 | ||
1698 | default: | |
1699 | adios (NULLCP, "unknown network type 0x%x", na -> na_stack); | |
1700 | /* NOT REACHED */ | |
1701 | ||
1702 | #ifdef COTS | |
1703 | cots: ; | |
1704 | { | |
1705 | struct TSAPconnect tcs; | |
1706 | register struct TSAPconnect *tc = &tcs; | |
1707 | struct TSAPdisconnect tds; | |
1708 | register struct TSAPdisconnect *td = &tds; | |
1709 | ||
1710 | if (verbose) { | |
1711 | fprintf (stderr, "%s... ", taddr2str (ta)); | |
1712 | (void) fflush (stderr); | |
1713 | } | |
1714 | if (TConnRequest (NULLTA, ta, 0, NULLCP, 0, NULLQOS, tc, td) | |
1715 | == NOTOK) { | |
1716 | if (verbose) | |
1717 | fprintf (stderr," failed\n"); | |
1718 | adios (NULLCP, td -> td_cc > 0 | |
1719 | ? "T-CONNECT.REQUEST: [%s] %*.*s" | |
1720 | : "T-CONNECT.REQUEST: [%s]", | |
1721 | TErrString (td -> td_reason), | |
1722 | td -> td_cc, td -> td_cc, td -> td_data); | |
1723 | } | |
1724 | fprintf (stderr, "connected\n"); | |
1725 | ||
1726 | if ((ps = ps_alloc (dg_open)) == NULLPS | |
1727 | || dg_setup (ps, sd = tc -> tc_sd, MAXDGRAM, ts_read, | |
1728 | ts_write, NULLIFP) == NOTOK) { | |
1729 | if (ps == NULLPS) | |
1730 | adios (NULLCP, "ps_alloc: out of memory"); | |
1731 | else | |
1732 | adios (NULLCP, "dg_setup: %s", | |
1733 | ps_error (ps -> ps_errno)); | |
1734 | } | |
1735 | } | |
1736 | break; | |
1737 | #endif | |
1738 | } | |
1739 | ||
1740 | #ifdef SYS5 | |
1741 | (void) srand ((unsigned int) time ((long *) 0)); | |
1742 | #else | |
1743 | (void) srandom ((int) time ((long *) 0)); | |
1744 | #endif | |
1745 | ||
1746 | ps_len_strategy = PS_LEN_LONG; | |
1747 | ||
1748 | if (readobjects (defs) == NOTOK) | |
1749 | adios (NULLCP, "readobjects: %s", PY_pepy); | |
1750 | moresyntax (); | |
1751 | } | |
1752 | ||
1753 | /* \f INTERACTIVE */ | |
1754 | ||
1755 | static int getline (prompt, buffer) | |
1756 | char *prompt, | |
1757 | *buffer; | |
1758 | { | |
1759 | register int i; | |
1760 | register char *cp, | |
1761 | *ep; | |
1762 | static int sticky = 0; | |
1763 | ||
1764 | if (interrupted) { | |
1765 | interrupted = 0; | |
1766 | return NOTOK; | |
1767 | } | |
1768 | ||
1769 | if (sticky) { | |
1770 | sticky = 0; | |
1771 | return NOTOK; | |
1772 | } | |
1773 | ||
1774 | switch (setjmp (intrenv)) { | |
1775 | case OK: | |
1776 | armed++; | |
1777 | break; | |
1778 | ||
1779 | case NOTOK: | |
1780 | if (ontty) | |
1781 | printf ("\n"); /* and fall */ | |
1782 | default: | |
1783 | armed = 0; | |
1784 | return NOTOK; | |
1785 | } | |
1786 | ||
1787 | if (ontty) { | |
1788 | printf (prompt, myname); | |
1789 | (void) fflush (stdout); | |
1790 | } | |
1791 | ||
1792 | for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) { | |
1793 | if (i == EOF) { | |
1794 | if (ontty) | |
1795 | printf ("\n"); | |
1796 | clearerr (stdin); | |
1797 | if (cp == buffer) | |
1798 | longjmp (intrenv, DONE); | |
1799 | ||
1800 | sticky++; | |
1801 | break; | |
1802 | } | |
1803 | ||
1804 | if (cp < ep) | |
1805 | *cp++ = i; | |
1806 | } | |
1807 | *cp = NULL; | |
1808 | ||
1809 | armed = 0; | |
1810 | ||
1811 | return OK; | |
1812 | } | |
1813 | ||
1814 | /* \f */ | |
1815 | ||
1816 | /* ARGSUSED */ | |
1817 | ||
1818 | static SFD intrser (sig) | |
1819 | int sig; | |
1820 | { | |
1821 | #ifndef BSDSIGS | |
1822 | (void) signal (SIGINT, intrser); | |
1823 | #endif | |
1824 | ||
1825 | if (armed) | |
1826 | longjmp (intrenv, NOTOK); | |
1827 | ||
1828 | interrupted++; | |
1829 | } | |
1830 | ||
1831 | /* \f */ | |
1832 | ||
1833 | #ifndef TIOCGWINSZ | |
1834 | /* ARGSUSED */ | |
1835 | #endif | |
1836 | ||
1837 | static int ncols (fp) | |
1838 | FILE *fp; | |
1839 | { | |
1840 | #ifdef TIOCGWINSZ | |
1841 | int i; | |
1842 | struct winsize ws; | |
1843 | ||
1844 | if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK | |
1845 | && (i = ws.ws_col) > 0) | |
1846 | return i; | |
1847 | #endif | |
1848 | ||
1849 | return 80; | |
1850 | } | |
1851 | ||
1852 | /* \f ERRORS */ | |
1853 | ||
1854 | #ifndef lint | |
1855 | void _advise (); | |
1856 | ||
1857 | ||
1858 | void adios (va_alist) | |
1859 | va_dcl | |
1860 | { | |
1861 | va_list ap; | |
1862 | ||
1863 | va_start (ap); | |
1864 | ||
1865 | _advise (ap); | |
1866 | ||
1867 | va_end (ap); | |
1868 | ||
1869 | _exit (1); | |
1870 | } | |
1871 | #else | |
1872 | /* VARARGS */ | |
1873 | ||
1874 | void adios (what, fmt) | |
1875 | char *what, | |
1876 | *fmt; | |
1877 | { | |
1878 | adios (what, fmt); | |
1879 | } | |
1880 | #endif | |
1881 | ||
1882 | ||
1883 | #ifndef lint | |
1884 | void advise (va_alist) | |
1885 | va_dcl | |
1886 | { | |
1887 | va_list ap; | |
1888 | ||
1889 | va_start (ap); | |
1890 | ||
1891 | _advise (ap); | |
1892 | ||
1893 | va_end (ap); | |
1894 | } | |
1895 | ||
1896 | ||
1897 | static void _advise (ap) | |
1898 | va_list ap; | |
1899 | { | |
1900 | char buffer[BUFSIZ]; | |
1901 | ||
1902 | asprintf (buffer, ap); | |
1903 | ||
1904 | (void) fflush (stdout); | |
1905 | ||
1906 | fprintf (stderr, "%s: ", myname); | |
1907 | (void) fputs (buffer, stderr); | |
1908 | (void) fputc ('\n', stderr); | |
1909 | ||
1910 | (void) fflush (stderr); | |
1911 | } | |
1912 | #else | |
1913 | /* VARARGS */ | |
1914 | ||
1915 | void advise (what, fmt) | |
1916 | char *what, | |
1917 | *fmt; | |
1918 | { | |
1919 | advise (what, fmt); | |
1920 | } | |
1921 | #endif |