summaryrefslogtreecommitdiff
path: root/other/b-scan/tmp/modules/mod_snmp.c
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/b-scan/tmp/modules/mod_snmp.c
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/b-scan/tmp/modules/mod_snmp.c')
-rw-r--r--other/b-scan/tmp/modules/mod_snmp.c899
1 files changed, 899 insertions, 0 deletions
diff --git a/other/b-scan/tmp/modules/mod_snmp.c b/other/b-scan/tmp/modules/mod_snmp.c
new file mode 100644
index 0000000..db56455
--- /dev/null
+++ b/other/b-scan/tmp/modules/mod_snmp.c
@@ -0,0 +1,899 @@
1/*
2 * SimpleNetworkManagementProtocol module for bscan.
3 * RFC 1157
4 * <buggy/lame implementation>
5 *
6 * ###fixme todo: port to sparc
7 */
8
9#include <bscan/bscan.h>
10#include <bscan/module.h>
11#include <bscan/system.h>
12#include <stdio.h>
13
14
15#ifndef MOD_NAME
16#define MOD_NAME "mod_snmp"
17#endif
18
19#define SNMP_DFLT_REQOBJ "1.3.6.1.2.1.1"
20
21#define MAX_VALSTRLEN 512
22
23#define MOPT_NOOBJ 0x01
24#define MOPT_STRIP 0x02
25
26#define SNMP_GET 0xa0
27#define SNMP_GET_NEXT 0xa1
28#define SNMP_SET 0xa3
29#define ASN_SUBCAT 0x30 /* BER encoding, sub-categorie */
30
31#ifndef ASN_INTEGER
32#define ASN_INTEGER ((u_char)0x02)
33#endif
34#define ASN_INTEGERSTR "INTEGER"
35#ifndef ASN_BIT_STR
36#define ASN_BIT_STR ((u_char)0x03)
37#endif
38#define ASN_BIT_STRSTR "BITSTRING"
39#ifndef ASN_OCTET_STR
40#define ASN_OCTET_STR ((u_char)0x04)
41#endif
42#define ASN_OCTET_STRSTR "STRING"
43#ifndef ASN_NULL
44#define ASN_NULL ((u_char)0x05)
45#endif
46#define ASN_NULLSTR "NULL"
47#ifndef ASN_OBJECT_ID
48#define ASN_OBJECT_ID ((u_char)0x06)
49#endif
50#define ASN_OBJECT_IDSTR "OBJ"
51#ifndef ASN_APPLICATION
52#define ASN_APPLICATION ((u_char)0x40)
53#endif
54#ifndef ASN_LONG_LEN
55#define ASN_LONG_LEN ((u_char)0x80)
56#endif
57#define ASN_APPLICATIONSTR "APPLICATION"
58#ifndef ASN_IPADDRESS
59#define ASN_IPADDRESS (ASN_APPLICATION | 0)
60#endif
61#define ASN_IPADDRESSSTR "IPADDR"
62#ifndef ASN_UNSIGNED
63#define ASN_UNSIGNED (ASN_APPLICATION | 2)
64#endif
65#define ASN_UNSIGNEDSTR ASN_INTEGERSTR
66#ifndef ASN_TIMETICKS
67#define ASN_TIMETICKS (ASN_APPLICATION | 3)
68#endif
69#define ASN_TIMETICKSSTR "TIMETICKS"
70#ifndef ASN_COUNTER
71#define ASN_COUNTER (ASN_APPLICATION | 1)
72#endif
73#define ASN_COUNTERSTR "COUNTER"
74
75#define SNMP_ERR_WRONGTYPE (7)
76#define SNMP_ERR_WRONGLENGTH (8)
77#define SNMP_ERR_WRONGENCODING (9)
78#define SNMP_ERR_WRONGVALUE (10)
79#define SNMP_ERR_NOCREATION (11)
80#define SNMP_ERR_INCONSISTENTVALUE (12)
81#define SNMP_ERR_RESOURCEUNAVAILABLE (13)
82#define SNMP_ERR_COMMITFAILED (14)
83#define SNMP_ERR_UNDOFAILED (15)
84#define SNMP_ERR_AUTHORIZATIONERROR (16)
85#define SNMP_ERR_NOTWRITABLE (17)
86
87char *snmp_error[] = {
88 "NO ERROR",
89 "TOO BIG",
90 "NO SUCH NAME",
91 "BAD VALUE",
92 "READONLY",
93 "GENERELL ERROR",
94 "NO ACCESS",
95 "WRONG TYPE",
96 "WRONG LENGTH",
97 "WRONG ENCODING",
98 "WRONG VALUE",
99 "NO CREATION",
100 "INCONSISTENT VALUE",
101 "RESOURCE UNAVAILABLE",
102 "COMMIT FAILED",
103 "UNDO FAILED",
104 "AUTORISATION ERROR",
105 "NOT WRITEABLE",
106 "INCONSISTENT NAME" };
107
108#define MAX_SNMP_ERR 18
109
110
111
112#define ADD_DATA(ptr, in, len, totlen) memcpy(ptr, in, len);\
113 *totlen = *totlen + len;
114
115#define min(a,b) ((a)<(b)?(a):(b))
116
117
118static int isinit=0;
119/*
120 * some variables from the binary-process
121 */
122extern int dlt_len;
123extern u_char *align_buf;
124extern unsigned short ip_options;
125extern struct ip *ip;
126extern struct Ether_header *eth;
127extern u_int plen, pcaplen;
128extern struct timeval *pts;
129
130struct _pdu
131{
132 u_char *varbuf;
133 int varlen;
134};
135
136struct _mopt
137{
138 char *community;
139 u_char flags;
140 u_char snmptor; /* type of request */
141 struct _pdu pdu;
142} static mopt;
143
144struct _pdunfo
145{
146 u_char *community;
147 u_char *pdu_type;
148 u_char *error_status;
149 u_char *error_idx;
150} static pdunfo;
151
152
153/*
154 * static functions prototypes
155 */
156static int mdo_opt(int, char **, struct _opt *);
157static void init_vars(struct _opt *);
158static int process_rcv(struct _opt *);
159static int add_snmp (u_char *, int *);
160static int add_snmpreq (u_char *, int *, u_char, u_char *, struct _pdu *);
161static int add_snmp_var(struct _pdu *, u_char *);
162static int build_snmp_objreq(u_char *, u_char *,u_char *, u_char, u_char *);
163static int str2asnv(u_char *, u_char, u_char *, u_char *);
164static int str2objid(u_char *, u_char *, u_char *);
165
166
167/*
168 * print out usage informations
169 */
170void
171musage()
172{
173 printf ("\n"MOD_NAME"\n");
174 printf ("snmp module\n");
175 printf (" -p <port>, destination port, default 161\n");
176 printf (" -o <port>, source port, default 53\n");
177 printf (" -r <request[:type[:value]]>, default '1.3.6.1.2.1.1 (system)'\n");
178 printf (" -c <community name>, default 'public'\n");
179 printf (" -g <requesttype>, (get|getnext|set), default 'getnext'\n");
180 printf (" -s strip unprintable characters from STRING types, and output as text\n");
181 printf (" -q dont print out OBJ-types\n");
182 printf ("\n");
183 printf ("type: i: INTEGER, s: STRING, n: NULLOBJ, o: OBJID\n");
184 printf (" t: TIMETICKS, a: IPADDRESS, b: BITSTRING, c: COUNTER\n");
185 printf ("\n");
186 printf ("you can request multiple objects with one request:\n");
187 printf ("-g get -r 1.3.6.1.2.1.1.1.0 -r 1.3.6.1.2.1.1.4.0 -r 1.3.6.1.2.1.1.5.0\n");
188}
189
190
191/*
192 * return 0 on success, != 0 on failure
193 */
194int
195init(char **modname, int argc, char *argv[], struct _opt *opt)
196{
197#ifdef DEBUG
198 printf("MODULE INIT\n");
199#endif
200 if (isinit)
201 return(-1);
202
203 *modname = MOD_NAME;
204 isinit = 1;
205 init_vars(opt);
206
207 if (mdo_opt(argc, argv, opt) != 0)
208 return(-1);
209
210 return(0);
211}
212
213/*
214 * fini-routine. called on cleanup
215 */
216int
217fini()
218{
219#ifdef DEBUG
220 printf("MODULE FINI\n");
221#endif
222 return(0);
223}
224
225
226/*
227 * Module entry point [entry]
228 * RMOD_OK: everything allright. send the packet out [if first]
229 * or do nothing [MOD_RCV].
230 * RMOD_SKIP: proceed with next IP without sending out the packet.
231 * RMOD_ERROR: failed to create packet.
232 * RMOD_ABRT: critical failure, abort!
233 */
234int
235callmdl(int entry, struct _opt *opt)
236{
237#ifdef DEBUG
238 printf("MODULE CALLMDL\n");
239#endif
240 if (entry == MOD_FIRSTPKG)
241 {
242 add_snmp(opt->packet+ ETH_SIZE + IP_SIZE + UDP_SIZE, &opt->pkg_len);
243 add_udphdr (opt->packet+ ETH_SIZE+ IP_SIZE, &opt->nt, opt->pkg_len);
244 add_iphdr (opt->packet + ETH_SIZE, IPPROTO_UDP, &opt->nt, opt->pkg_len + UDP_SIZE);
245 opt->pkg_len += UDP_SIZE + IP_SIZE;
246
247 return(RMOD_OK);
248 }
249
250 if (entry == MOD_RCV)
251 process_rcv(opt);
252
253 return(RMOD_OK);
254}
255
256
257/*
258 ***********************************************************
259 * Our OWN/static functions for THIS module *
260 ***********************************************************
261 */
262
263/*
264 * initialize all local variables.
265 * We use some 'unused' variables of the masterprogramm
266 */
267static void
268init_vars(struct _opt *opt)
269{
270 opt->nt.sport = htons(32770);
271 opt->nt.dport = htons(161);
272 mopt.flags = 0;
273 mopt.community = "public";
274 mopt.snmptor = SNMP_GET_NEXT;
275}
276
277
278/*
279 * LOCAL/STATIC function, only available in the module
280 * return 0 on success, != 0 on failure
281 */
282static int
283mdo_opt(int argc, char *argv[], struct _opt *opt)
284{
285 extern char *optarg;
286 /*extern int optind, opterr, optopt;*/
287 int c;
288
289 while ((c = getopt (argc, argv, "qsg:c:r:p:o:")) != -1)
290 {
291 switch (c)
292 {
293 case 'q':
294 mopt.flags |= MOPT_NOOBJ;
295 break;
296 case 's':
297 mopt.flags |= MOPT_STRIP;
298 break;
299 case 'p':
300 opt->nt.dport = htons(atoi(optarg));
301 break;
302 case 'o':
303 opt->nt.sport = htons(atoi(optarg));
304 break;
305 case 'r':
306 add_snmp_var(&mopt.pdu, optarg);
307 break;
308 case 'c':
309 mopt.community = optarg;
310 break;
311 case 'g':
312 if (strcasecmp (optarg, "get") == 0)
313 mopt.snmptor = SNMP_GET;
314 else if (strcasecmp (optarg, "getnext") == 0)
315 mopt.snmptor = SNMP_GET_NEXT;
316 else if (strcasecmp (optarg, "set") == 0)
317 mopt.snmptor = SNMP_SET;
318 else
319 return (-1);
320 break;
321 case ':':
322 fprintf(stderr, "missing parameter\n");
323 return(-1);
324 default:
325 return(-1);
326 }
327 }
328
329 if (mopt.pdu.varbuf == NULL)
330 add_snmp_var(&mopt.pdu, SNMP_DFLT_REQOBJ);
331
332 return(0);
333}
334
335
336static u_char
337strtoasn_vtype(int src)
338{
339
340 src = tolower(src);
341
342 switch (src)
343 {
344 case 'i':
345 return(ASN_INTEGER);
346 case 's':
347 return(ASN_OCTET_STR);
348 case 'n':
349 return(ASN_NULL);
350 case 'o':
351 return(ASN_OBJECT_ID);
352 case 't':
353 return(ASN_TIMETICKS);
354 case 'b':
355 return(ASN_BIT_STR);
356 case 'a':
357 return(ASN_IPADDRESS);
358 case 'u':
359 return(ASN_UNSIGNED);
360 case 'c':
361 return(ASN_COUNTER);
362 default:
363 fprintf(stderr, "WARNING: unsupported value-type.\n");
364 return(src);
365 }
366
367 return(ASN_NULL);
368}
369
370/*
371 * add variable to our variable-queue
372 * input: <objid-dodded notation>:<value type>:<value>-format
373 * return 0 on success, !=0 on parse error etc
374 */
375static int
376add_snmp_var(struct _pdu *pdu, u_char *src)
377{
378 u_char *request;
379 u_char vtype = 5;
380 u_char *value = NULL;
381 u_char *ptr = NULL;
382 u_char reqlen=0;
383
384 if (pdu->varbuf == NULL)
385 {
386 pdu->varbuf = calloc(1, 1024);
387 pdu->varlen = 0;
388 }
389
390 request = src;
391
392 if ( (ptr = strchr(src, ':')) != NULL)
393 *ptr++ = '\0';
394
395 src = ptr;
396 if (ptr != NULL)
397 {
398 if ( (ptr = strchr(src, ':')) != NULL)
399 {
400 *ptr++ = '\0';
401 if (strlen(ptr) > 0)
402 value = ptr;
403 }
404 vtype = strtoasn_vtype(*src);
405 }
406
407 if (build_snmp_objreq(pdu->varbuf + pdu->varlen, &reqlen, request, vtype, value) != 0)
408 {
409 fprintf(stderr, "WARNING: error while parsing reqOBJ\n");
410 return(-1);
411 }
412
413 pdu->varlen += reqlen;
414
415 return(0);
416}
417
418/*
419 * convert OBJ-ID and build the snmp-request packet
420 * save the work and reuse [better performance, the snmp
421 * packet is always the same].
422 * return 0 on success
423 */
424static int
425add_snmp(u_char *ptr, int *lenptr)
426{
427 static u_char *buf = NULL;
428 static int buflen;
429
430 if (buf != NULL) /* fastmode, use old copy of previous build snmppkg */
431 {
432 *lenptr = buflen;
433 memcpy(ptr, buf, buflen);
434 return(0);
435 }
436
437 if (buf == NULL)
438 buf = malloc(1024);
439
440 add_snmpreq (ptr, lenptr, mopt.snmptor, mopt.community, &mopt.pdu);
441
442 memcpy(buf, ptr, *lenptr); /* for later reuse */
443 buflen = *lenptr;
444
445 return(0);
446}
447
448/*
449 * convert snmp obj in dotted-notation, 0-terminated string to obj-id in asn.1
450 */
451static int
452str2objid(u_char *dst, u_char *retlen, u_char *src)
453{
454 u_char *dotptr;
455 u_char len;
456
457 if (strncmp(src, "1.3.6.1.", 8) != 0)
458 return(-1); /* snmp only , iso.org.dot.internet.* */
459
460 src += 8; /* we know the first 8 bytes. */
461
462 memcpy(dst, "\x2b\x06\x01", 3); /* yepp, we know this. "1.3.6.1" */
463 dst += 3;
464 dotptr = src;
465 len = 3; /* 2b-06-01 */
466 while ( (dotptr = strchr (src, '.')) != NULL)
467 {
468 *dotptr = '\0';
469 *dst++ = (u_char)atoi(src);
470 src = ++dotptr;
471 len++;
472 }
473 if (strlen(src) > 0)
474 {
475 *dst++ = (u_char)atoi(src);
476 len++;
477 }
478
479 *retlen = len;
480 return(0);
481}
482
483
484/*
485 * convert input to ASN.1 BER encodet <obj-id><value>
486 * dst: guess what.
487 * ptr: snmp obj in dotted-notation (1.3.6.1.2.1.1....), 0-terminated string
488 * tov: type of value, ASN.1 encodet (int, 8octet string, ...)
489 * value: the value (string, 0-terminated)
490 * return: 0 on success
491 */
492static int
493build_snmp_objreq(u_char *dst, u_char *retlen, u_char *src, u_char tov,
494 u_char *value)
495{
496 u_char *srcw;
497 u_char vlen = 0;
498 u_char *sublen;
499 u_char *subsublen;
500 u_char *subvlen;
501 u_char len;
502
503 srcw = alloca(strlen(src)+1);
504 memcpy(srcw, src, strlen(src)+1);
505 if (strlen(srcw) <= 4)
506 return(-1);
507
508 *dst++ = ASN_SUBCAT;
509 sublen = dst++; /* we set the length later coz we dont know it yet */
510
511 *dst++ = 0x06; /* OBJ-ID */
512 subsublen = dst++; /* and this also not */
513
514 if (str2objid(dst, &len, srcw) != 0)
515 return(-1);
516
517 *subsublen = len; /* length of obj */
518 dst += len;
519
520 *dst++ = tov; /* type of value */
521 subvlen = dst++; /* we set this later..we dont know the length yet */
522 str2asnv(value, tov, dst, &vlen);
523
524 *subvlen = vlen; /* length of value */
525
526 *sublen = len + vlen + 4; /* length of <obj-id><tov:value> */
527
528 *retlen = len + vlen + 6;
529 return(0);
530}
531
532
533/*
534 * convert 0-terminated string value to asn encodet value
535 * return 0 on success
536 * on return the length of rvalue < value.
537 * input: value [0 terminated string]
538 * tov [asn]-type of value
539 * output: rvalue [non 0-terminated string with asn-value]
540 * vlen [length of rvalue]
541 * return 0 on success
542 * attention: we use full integers (length=4, not reduced in length
543 * to the minimum size). the snmp-lib reduces the length of an
544 * integer to the minimum size...but this is not a must
545 */
546static int
547str2asnv(u_char *value, u_char tov, u_char *rvalue, u_char *vlen)
548{
549 unsigned long int ltmp;
550
551 if (rvalue == NULL)
552 return(0); /* yes, NULL is allowed */
553 if ((rvalue != NULL) && (vlen == NULL))
554 return(-1);
555
556 switch(tov)
557 {
558 case ASN_INTEGER:
559 ltmp = htonl(strtol(value, NULL, 10));
560 memcpy(rvalue, &ltmp, sizeof(ltmp));
561 *vlen = sizeof(ltmp);
562 break;
563 case ASN_UNSIGNED:
564 case ASN_COUNTER:
565 case ASN_TIMETICKS:
566 ltmp = htonl(strtoul(value, NULL, 10));
567 memcpy(rvalue, &ltmp, sizeof(ltmp));
568 *vlen = (sizeof(ltmp));
569 break;
570 case ASN_IPADDRESS:
571 ltmp = inet_addr(value);
572 memcpy(rvalue, &ltmp, sizeof(ltmp));
573 *vlen = sizeof(ltmp);
574 break;
575 case ASN_OBJECT_ID:
576 str2objid(rvalue, vlen, value);
577 break;
578 case ASN_OCTET_STR:
579 memcpy(rvalue, value, strlen(value));
580 *vlen = strlen(value);
581 break;
582 case ASN_NULL:
583 *vlen = 0;
584 break;
585 default:
586 *vlen = 0;
587 fprintf(stderr, "WARNING, unsupported value type !\n");
588 }
589
590 return(0);
591}
592
593/*
594 * add snmp request
595 * build the entire SNMP packet [version, community, pdu, id, error, idx, ..]
596 * req: objs + values [BER encodet, already with header and \x30 sub start]
597 * reqlen: len of entire req [objs + values]
598 * tor: type of request [get, getnext, set]
599 */
600static int
601add_snmpreq (u_char *pkt, int *len, u_char tor, u_char *community, struct _pdu *pdu)
602{
603 int le = 0;
604
605 *(pkt + le++) = ASN_SUBCAT;
606 *(pkt + le++) = (u_char)(pdu->varlen + strlen(community) + 18);
607 ADD_DATA(pkt + le, "\x02\x01\x00\x04" , 4, &le); /* SNMPv1 + STRINGOBJ*/
608 *(pkt + le++) = (u_char)strlen(community);
609 ADD_DATA(pkt + le, community, strlen(community), &le);
610 *(pkt + le++) = tor; /* PDU GET-NEXTrequest */
611 /* lenof(<req-id> + <err-state> + <err-idx> + <SUB> <obj+values>) */
612 *(pkt + le++) = (u_char)(pdu->varlen + 11);
613 /* <req-id> + <err-state> + <err-idx> <SUB-OBJ> */
614 ADD_DATA(pkt + le, "\x02\x01\x01\x02\x01\00\x02\x01\x00\x30", 10, &le);
615 *(pkt + le++) = (u_char)(pdu->varlen);
616 ADD_DATA(pkt + le, pdu->varbuf, pdu->varlen, &le);
617
618 *len = le;
619 return(0);
620}
621
622
623/*
624 * convert asn encoded obj to string
625 * input: string of <type of value><length of value><value>
626 * datalen: max len i'm allowed to read from "ptr --> ..."
627 * return:
628 * prefix is the string representation of the value-type e.g. "OCTET-STRING"..
629 * and '<trunc>' if value got truncated.
630 * is < 64 chars...
631 * val: the value (0-terminated string)
632 * return 0 on success
633 * 1 if truncated (value-length > size of snmp or val to small)
634 * -1 on error
635 */
636static int
637asn2str(u_char *ptr, u_char *prefix, u_char *val, unsigned int datalen)
638{
639 unsigned long int len, day, hour, min, sec, msec;
640 u_char *ptr2;
641 u_char vlen = *(ptr+1); /* saved value length */
642 u_char tov = *ptr;
643 unsigned long int ltmp;
644 int i, slen = 0;
645 u_char buf[128];
646
647 if (vlen > datalen-2)
648 len = datalen-2;
649 else
650 len = vlen;
651
652 *val = '\0';
653 *prefix = '\0';
654
655 switch(tov)
656 {
657 case ASN_IPADDRESS:
658 if (len > sizeof(ltmp))
659 len = sizeof(ltmp);
660
661 ptr2 = (u_char *)&ltmp;
662 memcpy(ptr2 + sizeof(ltmp) - len, ptr+2, len);
663 sprintf(val, "%s", int_ntoa(ltmp));
664 strcpy(prefix, ASN_IPADDRESSSTR);
665 break;
666 case ASN_NULL:
667 strcpy(prefix, ASN_NULLSTR);
668 break;
669 case ASN_TIMETICKS:
670 if (len > sizeof(ltmp))
671 len = sizeof(ltmp);
672
673 ltmp = 0;
674 ptr2 = (u_char *)&ltmp;
675 memcpy(ptr2 + sizeof(ltmp) - len, ptr+2, len);
676 ltmp = ntohl(ltmp);
677 day = ltmp / 8640000;
678 hour = (ltmp % 8640000) / 360000;
679 min = (ltmp % 360000) / 6000;
680 sec = (ltmp % 6000) / 100;
681 msec = (ltmp % 100);
682 sprintf(val, "(%lu) %d days, %2.2d:%2.2d:%2.2d.%d", ltmp,
683 (int)day, (int)hour, (int)min, (int)sec, (int)msec);
684 if (tov == ASN_TIMETICKS)
685 strcpy(prefix, ASN_TIMETICKSSTR);
686 break;
687 case ASN_INTEGER:
688 case ASN_UNSIGNED:
689 case ASN_COUNTER:
690 ltmp = 0;
691 if (len > sizeof(ltmp))
692 len = sizeof(ltmp);
693
694 ptr2 = (u_char *)&ltmp;
695 memcpy(ptr2 + sizeof(ltmp) - len, ptr+2, len);
696
697 if (tov == ASN_INTEGER)
698 sprintf(val, "%lu", (unsigned long int)ntohl(ltmp));
699 else
700 sprintf(val, "%ld", (long int)ntohl(ltmp));
701
702 if (tov == ASN_INTEGER)
703 strcpy(prefix, ASN_INTEGERSTR);
704 if (tov == ASN_UNSIGNED)
705 strcpy(prefix, ASN_UNSIGNEDSTR);
706 if (tov == ASN_COUNTER)
707 strcpy(prefix, ASN_COUNTERSTR);
708 break;
709 case ASN_OCTET_STR:
710 if (isprintdata(ptr+2, len))
711 {
712 if (len > MAX_VALSTRLEN-1)
713 len = MAX_VALSTRLEN-1;
714 memcpy(val, ptr+2, len);
715 val[len] = '\0';
716 } else if ((mopt.flags & MOPT_STRIP) == MOPT_STRIP) {
717 dat2strip(val, MAX_VALSTRLEN, ptr+2, len);
718 } else {
719 dat2hexstr(val, MAX_VALSTRLEN, ptr+2, len);
720 }
721
722 strcpy(prefix, ASN_OCTET_STRSTR);
723 break;
724 case ASN_OBJECT_ID:
725 i = 0;
726 slen = 0;
727 while(i < len)
728 {
729 if (*(ptr+2+i) == 0x2b)
730 strcpy(buf, "1.3."); /* substituate shorts */
731 else
732 snprintf(buf, sizeof(buf), "%d.", *(ptr+2+i));
733
734 buf[sizeof(buf)-1] = '\0';
735 slen = strlen(val) + strlen(buf);
736
737 if (slen < MAX_VALSTRLEN -1)
738 strcat(val, buf);
739 else
740 break;
741
742 i++;
743 }
744 val[slen-1] = '\0'; /* remove last '.' */
745 strcpy(prefix, ASN_OBJECT_IDSTR);
746 break;
747 default:
748 dat2hexstr(val, MAX_VALSTRLEN, ptr+2, len);
749 break;
750 }
751
752 if (*prefix == '\0')
753 strcpy(prefix, "UNKNOWN");
754
755 if (vlen > len)
756 {
757 strcat(prefix, "<trunc>");
758 return(1);
759 }
760
761 return(0);
762}
763
764/*
765 * return TypeOfValue and let next point to the next asn encodet obj
766 * ptr: pointer to asn.1 encodet obj
767 * len: returns the length of the OLD value + suffix [length we skipped]
768 * next: returns a pointer to the next obj.
769 */
770static u_char
771asn_getnext(u_char *ptr, u_char *len, u_char **next)
772{
773 u_char vlen = *(ptr+1);
774
775 if (*ptr == ASN_SUBCAT)
776 {
777 if (vlen & ASN_LONG_LEN)
778 vlen = vlen & ~ASN_LONG_LEN;
779 else
780 vlen = 0;
781 }
782
783 *next = ptr + vlen + 2;
784
785 *len = vlen + 2;
786 return(**next);
787}
788
789#define RETURN_ILLLEN(x,y,r) if (x >= y) return(r);
790
791/*
792 * handle incoming snmp answers, answer with 'next' if not last record
793 */
794static int
795process_rcv(struct _opt *opt)
796{
797 struct udphdr *udp;
798 u_char *ptr;
799 int len;
800 int snmplen;
801 uint iphdr_len = 0;
802 u_char objlen;
803 u_char buf[MAX_VALSTRLEN];
804 u_char prefix[32];
805 u_char buf2[MAX_VALSTRLEN + 32];
806 u_char asnprefix[128];
807 u_char c;
808
809 if (ip->ip_p != IPPROTO_UDP)
810 return(0);
811
812 iphdr_len = IP_SIZE + ip_options;
813 if (plen < dlt_len + iphdr_len + sizeof(*udp))
814 return(-1); /* invalid size */
815
816 udp = (struct udphdr *) (align_buf + iphdr_len);
817 ptr = (u_char *) (align_buf + iphdr_len + sizeof(*udp));
818 snmplen = plen - dlt_len - iphdr_len - sizeof(*udp);
819 len = 0;
820
821 /*
822 * we dont check the value of the ASN_SUBCAT-length coz many buggy
823 * hosts out there return a wrong length [0xff, 0x80, ...]
824 */
825
826 ptr += 2; len += 3; /* pointing on the 3rd element */
827 RETURN_ILLLEN(len, snmplen, 0);
828
829 asn_getnext(ptr, &objlen, &ptr); /* skip version, get community */
830 len += objlen;
831 RETURN_ILLLEN(len, snmplen, 0);
832 pdunfo.community = ptr;
833
834 asn_getnext(ptr, &objlen, &ptr); /* skip community, get pdu */
835 len += objlen;
836 RETURN_ILLLEN(len, snmplen, 0);
837 pdunfo.pdu_type = ptr;
838 ptr += 2;
839 len += 2; /* skip pdu, get reqid */
840 RETURN_ILLLEN(len, snmplen, 0);
841
842 asn_getnext(ptr, &objlen, &ptr); /* skip reqid, get errorstatus */
843 len += objlen;
844 RETURN_ILLLEN(len, snmplen, 0);
845 pdunfo.error_status = ptr;
846
847 asn_getnext(ptr, &objlen, &ptr); /* skip errorstatus, get erroridx */
848 len += objlen;
849 RETURN_ILLLEN(len, snmplen, 0);
850 pdunfo.error_idx = ptr;
851
852 asn_getnext(ptr, &objlen, &ptr); /* skip erroridx, get */
853 len += objlen;
854 RETURN_ILLLEN(len, snmplen, 0);
855
856 asn_getnext(ptr, &objlen, &ptr); /* we reached the SUB section */
857 len += objlen;
858 RETURN_ILLLEN(len, snmplen, 0);
859
860 snprintf(prefix, sizeof(prefix) - 1, "%s:%d ", int_ntoa(ip->ip_src),
861 ntohs(udp->uh_sport));
862
863 c = *(pdunfo.error_status+2);
864 if (c != 0)
865 {
866 if (c < MAX_SNMP_ERR)
867 {
868 printf("%s%s (%d)\n", prefix, snmp_error[c],
869 *(pdunfo.error_idx+2));
870 } else {
871 printf("%s UNKNOWN ERROR\n", prefix);
872 }
873 }
874
875 while (1)
876 {
877 asn_getnext(ptr, &objlen, &ptr);
878 if (objlen == 0)
879 return(0);
880
881 len += objlen;
882 RETURN_ILLLEN(len, snmplen, 0);
883 if (*ptr == ASN_SUBCAT)
884 continue;
885
886 if ((mopt.flags & MOPT_NOOBJ) && (*ptr == ASN_OBJECT_ID))
887 continue;
888
889 asn2str(ptr, asnprefix, buf, snmplen - len + 1);
890 snprintf(buf2, sizeof(buf2)-1, "%s %s", asnprefix, buf);
891 buf2[sizeof(buf2)-1] = '\0';
892 save_write(stdout, prefix, buf2, strlen(buf2));
893 }
894
895 return(0);
896
897}
898
899