1 /*-
2  * Copyright (c) 2006 The FreeBSD Project
3  * All rights reserved.
4  *
5  * Author: Shteryana Shopova <syrinx@FreeBSD.org>
6  *
7  * Redistribution of this software and documentation and use in source and
8  * binary forms, with or without modification, are permitted provided that
9  * the following conditions are met:
10  *
11  * 1. Redistributions of source code or documentation must retain the above
12  *    copyright notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #include <sys/param.h>
33 #include <sys/queue.h>
34 #include <sys/uio.h>
35 
36 #include <ctype.h>
37 #include <err.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <unistd.h>
44 
45 #include <bsnmp/asn1.h>
46 #include <bsnmp/snmp.h>
47 #include "bsnmptc.h"
48 #include "bsnmptools.h"
49 
50 #define	DEBUG	if (_bsnmptools_debug) fprintf
51 
52 /* Allocate memory and initialize list. */
53 struct snmp_mappings *
54 snmp_mapping_init(void)
55 {
56 	struct snmp_mappings *m;
57 
58 	if ((m = malloc(sizeof(struct snmp_mappings))) == NULL) {
59 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
60 		return (NULL);
61 	}
62 
63 	memset(m, 0, sizeof(struct snmp_mappings));
64 	return (m);
65 }
66 
67 #define		snmp_nodelist	mappings->nodelist
68 #define		snmp_intlist	mappings->intlist
69 #define		snmp_octlist	mappings->octlist
70 #define		snmp_oidlist	mappings->oidlist
71 #define		snmp_iplist	mappings->iplist
72 #define		snmp_ticklist	mappings->ticklist
73 #define		snmp_cntlist	mappings->cntlist
74 #define		snmp_gaugelist	mappings->gaugelist
75 #define		snmp_cnt64list	mappings->cnt64list
76 #define		snmp_enumlist	mappings->enumlist
77 #define		snmp_tablelist	mappings->tablelist
78 #define		snmp_tclist	mappings->tclist
79 
80 void
81 enum_pairs_free(struct enum_pairs *headp)
82 {
83 	struct enum_pair *e;
84 
85 	if (headp == NULL)
86 		return;
87 
88 	while ((e = STAILQ_FIRST(headp)) != NULL) {
89 		STAILQ_REMOVE_HEAD(headp, link);
90 
91 		if (e->enum_str)
92 			free(e->enum_str);
93 		free(e);
94 	}
95 
96 	free(headp);
97 }
98 
99 void
100 snmp_mapping_entryfree(struct snmp_oid2str *entry)
101 {
102 	if (entry->string)
103 		free(entry->string);
104 
105 	if (entry->tc == SNMP_TC_OWN)
106 		enum_pairs_free(entry->snmp_enum);
107 
108 	free(entry);
109 }
110 
111 static void
112 snmp_mapping_listfree(struct snmp_mapping *headp)
113 {
114 	struct snmp_oid2str *p;
115 
116 	while ((p = SLIST_FIRST(headp)) != NULL) {
117 		SLIST_REMOVE_HEAD(headp, link);
118 
119 		if (p->string)
120 			free(p->string);
121 
122 		if (p->tc == SNMP_TC_OWN)
123 			enum_pairs_free(p->snmp_enum);
124 		free(p);
125 	}
126 
127 	SLIST_INIT(headp);
128 }
129 
130 void
131 snmp_index_listfree(struct snmp_idxlist *headp)
132 {
133 	struct index *i;
134 
135 	while ((i = STAILQ_FIRST(headp)) != NULL) {
136 		STAILQ_REMOVE_HEAD(headp, link);
137 		if (i->tc == SNMP_TC_OWN)
138 			enum_pairs_free(i->snmp_enum);
139 		free(i);
140 	}
141 
142 	STAILQ_INIT(headp);
143 }
144 
145 static void
146 snmp_mapping_table_listfree(struct snmp_table_index *headp)
147 {
148 	struct snmp_index_entry *t;
149 
150 	while ((t = SLIST_FIRST(headp)) != NULL) {
151 		SLIST_REMOVE_HEAD(headp, link);
152 
153 		if (t->string)
154 			free(t->string);
155 
156 		snmp_index_listfree(&(t->index_list));
157 		free(t);
158 	}
159 }
160 
161 static void
162 snmp_enumtc_listfree(struct snmp_enum_tc *headp)
163 {
164 	struct enum_type *t;
165 
166 	while ((t = SLIST_FIRST(headp)) != NULL) {
167 		SLIST_REMOVE_HEAD(headp, link);
168 
169 		if (t->name)
170 			free(t->name);
171 		enum_pairs_free(t->snmp_enum);
172 		free(t);
173 	}
174 }
175 
176 int
177 snmp_mapping_free(struct snmp_toolinfo *snmptoolctx)
178 {
179 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL)
180 		return (-1);
181 
182 	snmp_mapping_listfree(&snmptoolctx->snmp_nodelist);
183 	snmp_mapping_listfree(&snmptoolctx->snmp_intlist);
184 	snmp_mapping_listfree(&snmptoolctx->snmp_octlist);
185 	snmp_mapping_listfree(&snmptoolctx->snmp_oidlist);
186 	snmp_mapping_listfree(&snmptoolctx->snmp_iplist);
187 	snmp_mapping_listfree(&snmptoolctx->snmp_ticklist);
188 	snmp_mapping_listfree(&snmptoolctx->snmp_cntlist);
189 	snmp_mapping_listfree(&snmptoolctx->snmp_gaugelist);
190 	snmp_mapping_listfree(&snmptoolctx->snmp_cnt64list);
191 	snmp_mapping_listfree(&snmptoolctx->snmp_enumlist);
192 	snmp_mapping_table_listfree(&snmptoolctx->snmp_tablelist);
193 	snmp_enumtc_listfree(&snmptoolctx->snmp_tclist);
194 	free(snmptoolctx->mappings);
195 
196 	return (0);
197 }
198 
199 static void
200 snmp_dump_enumpairs(struct enum_pairs *headp)
201 {
202 	struct enum_pair *entry;
203 
204 	if (headp == NULL)
205 		return;
206 
207 	fprintf(stderr,"enums: ");
208 	STAILQ_FOREACH(entry, headp, link)
209 		fprintf(stderr,"%d - %s, ", entry->enum_val,
210 		    (entry->enum_str == NULL)?"NULL":entry->enum_str);
211 
212 	fprintf(stderr,"; ");
213 }
214 
215 void
216 snmp_dump_oid2str(struct snmp_oid2str *entry)
217 {
218 	char buf[ASN_OIDSTRLEN];
219 
220 	if (entry != NULL) {
221 		memset(buf, 0, sizeof(buf));
222 		asn_oid2str_r(&(entry->var), buf);
223 		DEBUG(stderr, "%s - %s - %d - %d - %d", buf, entry->string,
224 		    entry->syntax, entry->access, entry->strlen);
225 		snmp_dump_enumpairs(entry->snmp_enum);
226 		DEBUG(stderr,"%s \n", (entry->table_idx == NULL)?"No table":
227 		    entry->table_idx->string);
228 	}
229 }
230 
231 static void
232 snmp_dump_indexlist(struct snmp_idxlist *headp)
233 {
234 	struct index *entry;
235 
236 	if (headp == NULL)
237 		return;
238 
239 	STAILQ_FOREACH(entry, headp, link) {
240 		fprintf(stderr,"%d, ", entry->syntax);
241 		snmp_dump_enumpairs(entry->snmp_enum);
242 	}
243 
244 	fprintf(stderr,"\n");
245 }
246 
247 /* Initialize the enum pairs list of a oid2str entry. */
248 struct enum_pairs *
249 enum_pairs_init(void)
250 {
251 	struct enum_pairs *snmp_enum;
252 
253 	if ((snmp_enum = malloc(sizeof(struct enum_pairs))) == NULL) {
254 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
255 		return (NULL);
256 	}
257 
258 	STAILQ_INIT(snmp_enum);
259 	return (snmp_enum);
260 }
261 
262 /*
263  * Given a number and string, allocate memory for a (int, string) pair and add
264  * it to the given oid2str mapping entry's enum pairs list.
265  */
266 int32_t
267 enum_pair_insert(struct enum_pairs *headp, int32_t enum_val, char *enum_str)
268 {
269 	struct enum_pair *e_new;
270 
271 	if ((e_new = calloc(1, sizeof(struct enum_pair))) == NULL) {
272 		syslog(LOG_ERR, "calloc() failed: %s", strerror(errno));
273 		return (-1);
274 	}
275 
276 	if ((e_new->enum_str = strdup(enum_str)) == NULL) {
277 		syslog(LOG_ERR, "strdup() failed: %s", strerror(errno));
278 		free(e_new);
279 		return (-1);
280 	}
281 
282 	e_new->enum_val = enum_val;
283 	STAILQ_INSERT_TAIL(headp, e_new, link);
284 
285 	return (1);
286 
287 }
288 
289 /*
290  * Insert an entry in a list - entries are lexicographicaly order by asn_oid.
291  * Returns 1 on success, -1 if list is not initialized, 0 if a matching oid already
292  * exists. Error cheking is left to calling function.
293  */
294 static int
295 snmp_mapping_insert(struct snmp_mapping *headp, struct snmp_oid2str *entry)
296 {
297 	int32_t rc;
298 	struct snmp_oid2str *temp, *prev;
299 
300 	if (entry == NULL)
301 		return(-1);
302 
303 	if ((prev = SLIST_FIRST(headp)) == NULL ||
304 	    asn_compare_oid(&(entry->var), &(prev->var)) < 0) {
305 		SLIST_INSERT_HEAD(headp, entry, link);
306 		return (1);
307 	} else
308 		rc = -1;	/* Make the compiler happy. */
309 
310 	SLIST_FOREACH(temp, headp, link) {
311 		if ((rc = asn_compare_oid(&(entry->var), &(temp->var))) <= 0)
312 			break;
313 		prev = temp;
314 		rc = -1;
315 	}
316 
317 	switch (rc) {
318 	    case 0:
319 		/* Ops, matching OIDs - hope the rest info also matches. */
320 		if (strncmp(temp->string, entry->string, entry->strlen)) {
321 			syslog(LOG_INFO, "Matching OIDs with different string "
322 			    "mappings: old - %s, new - %s", temp->string,
323 			    entry->string);
324 			return (-1);
325 		}
326 		/*
327 		 * Ok, we have that already.
328 		 * As long as the strings match - don't complain.
329 		 */
330 		return (0);
331 
332 	    case 1:
333 		SLIST_INSERT_AFTER(temp, entry, link);
334 		break;
335 
336 	    case -1:
337 		SLIST_INSERT_AFTER(prev, entry, link);
338 		break;
339 
340 	    default:
341 		/* NOTREACHED */
342 		return (-1);
343 	}
344 
345 	return (1);
346 }
347 
348 int32_t
349 snmp_node_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
350 {
351 	if (snmptoolctx != NULL && snmptoolctx->mappings)
352 		return (snmp_mapping_insert(&snmptoolctx->snmp_nodelist,entry));
353 
354 	return (-1);
355 }
356 
357 static int32_t
358 snmp_int_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
359 {
360 	if (snmptoolctx != NULL && snmptoolctx->mappings)
361 		return (snmp_mapping_insert(&snmptoolctx->snmp_intlist,entry));
362 
363 	return (-1);
364 }
365 
366 static int32_t
367 snmp_oct_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
368 {
369 	if (snmptoolctx != NULL && snmptoolctx->mappings)
370 		return (snmp_mapping_insert(&snmptoolctx->snmp_octlist,entry));
371 
372 	return (-1);
373 }
374 
375 static int32_t
376 snmp_oid_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
377 {
378 	if (snmptoolctx != NULL && snmptoolctx->mappings)
379 		return (snmp_mapping_insert(&snmptoolctx->snmp_oidlist,entry));
380 
381 	return (-1);
382 }
383 
384 static int32_t
385 snmp_ip_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
386 {
387 	if (snmptoolctx != NULL && snmptoolctx->mappings)
388 		return (snmp_mapping_insert(&snmptoolctx->snmp_iplist,entry));
389 
390 	return (-1);
391 }
392 
393 static int32_t
394 snmp_tick_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
395 {
396 	if (snmptoolctx != NULL && snmptoolctx->mappings)
397 		return (snmp_mapping_insert(&snmptoolctx->snmp_ticklist,entry));
398 
399 	return (-1);
400 }
401 
402 static int32_t
403 snmp_cnt_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
404 {
405 	if (snmptoolctx != NULL && snmptoolctx->mappings)
406 		return (snmp_mapping_insert(&snmptoolctx->snmp_cntlist,entry));
407 
408 	return (-1);
409 }
410 
411 static int32_t
412 snmp_gauge_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
413 {
414 	if (snmptoolctx != NULL && snmptoolctx->mappings)
415 		return (snmp_mapping_insert(&snmptoolctx->snmp_gaugelist,entry));
416 
417 	return (-1);
418 }
419 
420 static int32_t
421 snmp_cnt64_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
422 {
423 	if (snmptoolctx != NULL && snmptoolctx->mappings)
424 		return (snmp_mapping_insert(&snmptoolctx->snmp_cnt64list,entry));
425 
426 	return (-1);
427 }
428 
429 int32_t
430 snmp_enum_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
431 {
432 	if (snmptoolctx != NULL && snmptoolctx->mappings)
433 		return (snmp_mapping_insert(&snmptoolctx->snmp_enumlist,entry));
434 
435 	return (-1);
436 }
437 
438 int32_t
439 snmp_leaf_insert(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *entry)
440 {
441 	switch (entry->syntax) {
442 		case SNMP_SYNTAX_INTEGER:
443 			return (snmp_int_insert(snmptoolctx, entry));
444 		case SNMP_SYNTAX_OCTETSTRING:
445 			return (snmp_oct_insert(snmptoolctx, entry));
446 		case SNMP_SYNTAX_OID:
447 			return (snmp_oid_insert(snmptoolctx, entry));
448 		case SNMP_SYNTAX_IPADDRESS:
449 			return (snmp_ip_insert(snmptoolctx, entry));
450 		case SNMP_SYNTAX_COUNTER:
451 			return (snmp_cnt_insert(snmptoolctx, entry));
452 		case SNMP_SYNTAX_GAUGE:
453 			return (snmp_gauge_insert(snmptoolctx, entry));
454 		case SNMP_SYNTAX_TIMETICKS:
455 			return (snmp_tick_insert(snmptoolctx, entry));
456 		case SNMP_SYNTAX_COUNTER64:
457 			return (snmp_cnt64_insert(snmptoolctx, entry));
458 		default:
459 			break;
460 	}
461 
462 	return (-1);
463 }
464 
465 static int32_t
466 snmp_index_insert(struct snmp_idxlist *headp, struct index *idx)
467 {
468 	if (headp == NULL || idx == NULL)
469 		return (-1);
470 
471 	STAILQ_INSERT_TAIL(headp, idx, link);
472 	return (1);
473 }
474 
475 int32_t
476 snmp_syntax_insert(struct snmp_idxlist *headp, struct enum_pairs *enums,
477     enum snmp_syntax syntax, enum snmp_tc tc)
478 {
479 	struct index *idx;
480 
481 	if ((idx = malloc(sizeof(struct index))) == NULL) {
482 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
483 		return (-1);
484 	}
485 
486 	memset(idx, 0, sizeof(struct index));
487 
488 	if (snmp_index_insert(headp, idx) < 0) {
489 		free(idx);
490 		return (-1);
491 	}
492 
493 	idx->syntax = syntax;
494 	idx->snmp_enum = enums;
495 	idx->tc = tc;
496 
497 	return (1);
498 }
499 
500 int32_t
501 snmp_table_insert(struct snmp_toolinfo *snmptoolctx,
502     struct snmp_index_entry *entry)
503 {
504 	int32_t rc;
505 	struct snmp_index_entry *temp, *prev;
506 
507 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL ||
508 	    entry == NULL)
509 		return(-1);
510 
511 	if ((prev = SLIST_FIRST(&snmptoolctx->snmp_tablelist)) == NULL ||
512 	    asn_compare_oid(&(entry->var), &(prev->var)) < 0) {
513 		SLIST_INSERT_HEAD(&snmptoolctx->snmp_tablelist, entry, link);
514 		return (1);
515 	} else
516 		rc = -1;	/* Make the compiler happy. */
517 
518 	SLIST_FOREACH(temp, &snmptoolctx->snmp_tablelist, link) {
519 		if ((rc = asn_compare_oid(&(entry->var), &(temp->var))) <= 0)
520 			break;
521 		prev = temp;
522 		rc = -1;
523 	}
524 
525 	switch (rc) {
526 	    case 0:
527 		/* Ops, matching OIDs - hope the rest info also matches. */
528 		if (strncmp(temp->string, entry->string, entry->strlen)) {
529 			syslog(LOG_INFO, "Matching OIDs with different string "
530 			    "mapping - old - %s, new - %s", temp->string,
531 			    entry->string);
532 			return (-1);
533 		}
534 		return(0);
535 
536 	    case 1:
537 		SLIST_INSERT_AFTER(temp, entry, link);
538 		break;
539 
540 	    case -1:
541 		SLIST_INSERT_AFTER(prev, entry, link);
542 		break;
543 
544 	    default:
545 		/* NOTREACHED */
546 		return (-1);
547 	}
548 
549 	return (1);
550 }
551 
552 struct enum_type *
553 snmp_enumtc_init(char *name)
554 {
555 	struct enum_type *enum_tc;
556 
557 	if ((enum_tc = calloc(1, sizeof(struct enum_type))) == NULL) {
558 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
559 		return (NULL);
560 	}
561 
562 	if ((enum_tc->name = strdup(name)) == NULL) {
563 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
564 		free(enum_tc);
565 		return (NULL);
566 	}
567 
568 	return (enum_tc);
569 }
570 
571 void
572 snmp_enumtc_free(struct enum_type *tc)
573 {
574 	if (tc->name)
575 		free(tc->name);
576 	if (tc->snmp_enum)
577 		enum_pairs_free(tc->snmp_enum);
578 	free(tc);
579 }
580 
581 void
582 snmp_enumtc_insert(struct snmp_toolinfo *snmptoolctx, struct enum_type *entry)
583 {
584 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL)
585 		return;	/* XXX no error handling? */
586 
587 	SLIST_INSERT_HEAD(&snmptoolctx->snmp_tclist, entry, link);
588 }
589 
590 struct enum_type *
591 snmp_enumtc_lookup(struct snmp_toolinfo *snmptoolctx, char *name)
592 {
593 	struct enum_type *temp;
594 
595 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL)
596 		return (NULL);
597 
598 	SLIST_FOREACH(temp, &snmptoolctx->snmp_tclist, link) {
599 		if (strcmp(temp->name, name) == 0)
600 			return (temp);
601 	}
602 	return (NULL);
603 }
604 
605 static void
606 snmp_mapping_dumplist(struct snmp_mapping *headp)
607 {
608 	char buf[ASN_OIDSTRLEN];
609 	struct snmp_oid2str *entry;
610 
611 	if (headp == NULL)
612 		return;
613 
614 	SLIST_FOREACH(entry,headp,link) {
615 		memset(buf, 0, sizeof(buf));
616 		asn_oid2str_r(&(entry->var), buf);
617 		fprintf(stderr, "%s - %s - %d - %d - %d", buf, entry->string,
618 		    entry->syntax, entry->access ,entry->strlen);
619 		fprintf(stderr," - %s \n", (entry->table_idx == NULL)?
620 		    "No table":entry->table_idx->string);
621 	}
622 }
623 
624 static void
625 snmp_mapping_dumptable(struct snmp_table_index *headp)
626 {
627 	char buf[ASN_OIDSTRLEN];
628 	struct snmp_index_entry *entry;
629 
630 	if (headp == NULL)
631 		return;
632 
633 	SLIST_FOREACH(entry, headp, link) {
634 		memset(buf, 0, sizeof(buf));
635 		asn_oid2str_r(&(entry->var), buf);
636 		fprintf(stderr,"%s - %s - %d - ", buf, entry->string,
637 		    entry->strlen);
638 		snmp_dump_indexlist(&(entry->index_list));
639 	}
640 }
641 
642 void
643 snmp_mapping_dump(struct snmp_toolinfo *snmptoolctx /* int bits */)
644 {
645 	if (!_bsnmptools_debug)
646 		return;
647 
648 	if (snmptoolctx == NULL) {
649 		fprintf(stderr,"No snmptool context!\n");
650 		return;
651 	}
652 
653 	if (snmptoolctx->mappings == NULL) {
654 		fprintf(stderr,"No mappings!\n");
655 		return;
656 	}
657 
658 	fprintf(stderr,"snmp_nodelist:\n");
659 	snmp_mapping_dumplist(&snmptoolctx->snmp_nodelist);
660 
661 	fprintf(stderr,"snmp_intlist:\n");
662 	snmp_mapping_dumplist(&snmptoolctx->snmp_intlist);
663 
664 	fprintf(stderr,"snmp_octlist:\n");
665 	snmp_mapping_dumplist(&snmptoolctx->snmp_octlist);
666 
667 	fprintf(stderr,"snmp_oidlist:\n");
668 	snmp_mapping_dumplist(&snmptoolctx->snmp_oidlist);
669 
670 	fprintf(stderr,"snmp_iplist:\n");
671 	snmp_mapping_dumplist(&snmptoolctx->snmp_iplist);
672 
673 	fprintf(stderr,"snmp_ticklist:\n");
674 	snmp_mapping_dumplist(&snmptoolctx->snmp_ticklist);
675 
676 	fprintf(stderr,"snmp_cntlist:\n");
677 	snmp_mapping_dumplist(&snmptoolctx->snmp_cntlist);
678 
679 	fprintf(stderr,"snmp_gaugelist:\n");
680 	snmp_mapping_dumplist(&snmptoolctx->snmp_gaugelist);
681 
682 	fprintf(stderr,"snmp_cnt64list:\n");
683 	snmp_mapping_dumplist(&snmptoolctx->snmp_cnt64list);
684 
685 	fprintf(stderr,"snmp_enumlist:\n");
686 	snmp_mapping_dumplist(&snmptoolctx->snmp_enumlist);
687 
688 	fprintf(stderr,"snmp_tablelist:\n");
689 	snmp_mapping_dumptable(&snmptoolctx->snmp_tablelist);
690 }
691 
692 char *
693 enum_string_lookup(struct enum_pairs *headp, int32_t enum_val)
694 {
695 	struct enum_pair *temp;
696 
697 	if (headp == NULL)
698 		return (NULL);
699 
700 	STAILQ_FOREACH(temp, headp, link) {
701 		if (temp->enum_val == enum_val)
702 			return (temp->enum_str);
703 	}
704 
705 	return (NULL);
706 }
707 
708 int32_t
709 enum_number_lookup(struct enum_pairs *headp, char *e_str)
710 {
711 	struct enum_pair *tmp;
712 
713 	if (headp == NULL)
714 		return (-1);
715 
716 	STAILQ_FOREACH(tmp, headp, link)
717 		if (strncmp(tmp->enum_str, e_str, strlen(tmp->enum_str)) == 0)
718 			return (tmp->enum_val);
719 
720 	return (-1);
721 }
722 
723 static int32_t
724 snmp_lookuplist_string(struct snmp_mapping *headp, struct snmp_object *s)
725 {
726 	struct snmp_oid2str *temp;
727 
728 	if (headp == NULL)
729 		return (-1);
730 
731 	SLIST_FOREACH(temp, headp, link)
732 		if (asn_compare_oid(&(temp->var), &(s->val.var)) == 0)
733 			break;
734 
735 	if ((s->info = temp) == NULL)
736 		return (-1);
737 
738 	return (1);
739 }
740 
741 /* provided an asn_oid find the corresponding string for it */
742 static int32_t
743 snmp_lookup_leaf(struct snmp_mapping *headp, struct snmp_object *s)
744 {
745 	struct snmp_oid2str *temp;
746 
747 	if (headp == NULL)
748 		return (-1);
749 
750 	SLIST_FOREACH(temp,headp,link) {
751 		if ((asn_compare_oid(&(temp->var), &(s->val.var)) == 0) ||
752 		    (asn_is_suboid(&(temp->var), &(s->val.var)))) {
753 			s->info = temp;
754 			return (1);
755 		}
756 	}
757 
758 	return (-1);
759 }
760 
761 int32_t
762 snmp_lookup_leafstring(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s)
763 {
764 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL || s == NULL)
765 		return (-1);
766 
767 	switch (s->val.syntax) {
768 		case SNMP_SYNTAX_INTEGER:
769 			return (snmp_lookup_leaf(&snmptoolctx->snmp_intlist, s));
770 		case SNMP_SYNTAX_OCTETSTRING:
771 			return (snmp_lookup_leaf(&snmptoolctx->snmp_octlist, s));
772 		case SNMP_SYNTAX_OID:
773 			return (snmp_lookup_leaf(&snmptoolctx->snmp_oidlist, s));
774 		case SNMP_SYNTAX_IPADDRESS:
775 			return (snmp_lookup_leaf(&snmptoolctx->snmp_iplist, s));
776 		case SNMP_SYNTAX_COUNTER:
777 			return (snmp_lookup_leaf(&snmptoolctx->snmp_cntlist, s));
778 		case SNMP_SYNTAX_GAUGE:
779 			return (snmp_lookup_leaf(
780 			    &snmptoolctx->snmp_gaugelist, s));
781 		case SNMP_SYNTAX_TIMETICKS:
782 			return (snmp_lookup_leaf(
783 			    &snmptoolctx->snmp_ticklist, s));
784 		case SNMP_SYNTAX_COUNTER64:
785 			return (snmp_lookup_leaf(
786 			    &snmptoolctx->snmp_cnt64list, s));
787 		case SNMP_SYNTAX_NOSUCHOBJECT:
788 			/* FALLTHROUGH */
789 		case SNMP_SYNTAX_NOSUCHINSTANCE:
790 			/* FALLTHROUGH */
791 		case SNMP_SYNTAX_ENDOFMIBVIEW:
792 			return (snmp_lookup_allstring(snmptoolctx, s));
793 		default:
794 			warnx("Unknown syntax - %d", s->val.syntax);
795 			break;
796 	}
797 
798 	return (-1);
799 }
800 
801 int32_t
802 snmp_lookup_enumstring(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s)
803 {
804 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL || s == NULL)
805 		return (-1);
806 
807 	return (snmp_lookuplist_string(&snmptoolctx->snmp_enumlist, s));
808 }
809 
810 int32_t
811 snmp_lookup_oidstring(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s)
812 {
813 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL || s == NULL)
814 		return (-1);
815 
816 	return (snmp_lookuplist_string(&snmptoolctx->snmp_oidlist, s));
817 }
818 
819 int32_t
820 snmp_lookup_nodestring(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s)
821 {
822 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL || s == NULL)
823 		return (-1);
824 
825 	return (snmp_lookuplist_string(&snmptoolctx->snmp_nodelist, s));
826 }
827 
828 int32_t
829 snmp_lookup_allstring(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s)
830 {
831 	if (snmptoolctx == NULL || snmptoolctx->mappings == NULL)
832 		return (-1);
833 
834 	if (snmp_lookup_leaf(&snmptoolctx->snmp_intlist, s) > 0)
835 		return (1);
836 	if (snmp_lookup_leaf(&snmptoolctx->snmp_octlist, s) > 0)
837 		return (1);
838 	if (snmp_lookup_leaf(&snmptoolctx->snmp_oidlist, s) > 0)
839 		return (1);
840 	if (snmp_lookup_leaf(&snmptoolctx->snmp_iplist, s) > 0)
841 		return (1);
842 	if (snmp_lookup_leaf(&snmptoolctx->snmp_cntlist, s) > 0)
843 		return (1);
844 	if (snmp_lookup_leaf(&snmptoolctx->snmp_gaugelist, s) > 0)
845 		return (1);
846 	if (snmp_lookup_leaf(&snmptoolctx->snmp_ticklist, s) > 0)
847 		return (1);
848 	if (snmp_lookup_leaf(&snmptoolctx->snmp_cnt64list, s) > 0)
849 		return (1);
850 	if (snmp_lookuplist_string(&snmptoolctx->snmp_enumlist, s) > 0)
851 		return (1);
852 	if (snmp_lookuplist_string(&snmptoolctx->snmp_nodelist, s) > 0)
853 		return (1);
854 
855 	return (-1);
856 }
857 
858 int32_t
859 snmp_lookup_nonleaf_string(struct snmp_toolinfo *snmptoolctx,
860     struct snmp_object *s)
861 {
862 	if (snmptoolctx == NULL)
863 		return (-1);
864 
865 	if (snmp_lookuplist_string(&snmptoolctx->snmp_nodelist, s) > 0)
866 		return (1);
867 	if (snmp_lookuplist_string(&snmptoolctx->snmp_enumlist, s) > 0)
868 		return (1);
869 
870 	return (-1);
871 }
872 
873 static int32_t
874 snmp_lookup_oidlist(struct snmp_mapping *hp, struct snmp_object *s, char *oid)
875 {
876 	struct snmp_oid2str *temp;
877 
878 	if (hp == NULL)
879 		return (-1);
880 
881 	SLIST_FOREACH(temp, hp, link) {
882 		if (temp->strlen != strlen(oid))
883 			continue;
884 
885 		if (strncmp(temp->string, oid, temp->strlen))
886 			continue;
887 
888 		s->val.syntax = temp->syntax;
889 		s->info = temp;
890 		asn_append_oid(&(s->val.var), &(temp->var));
891 		return (1);
892 	}
893 
894 	return (-1);
895 }
896 
897 static int32_t
898 snmp_lookup_tablelist(struct snmp_toolinfo *snmptoolctx,
899     struct snmp_table_index *headp, struct snmp_object *s, char *oid)
900 {
901 	struct snmp_index_entry *temp;
902 
903 	if (snmptoolctx == NULL || headp == NULL)
904 		return (-1);
905 
906 	SLIST_FOREACH(temp, headp, link) {
907 		if (temp->strlen != strlen(oid))
908 			continue;
909 
910 		if (strncmp(temp->string, oid, temp->strlen))
911 			continue;
912 
913 		/*
914 		 * Another hack here - if we were given a table name
915 		 * return the corresponding pointer to it's entry.
916 		 * That should not change the reponce we'll get.
917 		 */
918 		s->val.syntax = SNMP_SYNTAX_NULL;
919 		asn_append_oid(&(s->val.var), &(temp->var));
920 		if (snmp_lookup_leaf(&snmptoolctx->snmp_nodelist, s) > 0)
921 			return (1);
922 		else
923 			return (-1);
924 	}
925 
926 	return (-1);
927 }
928 
929 int32_t
930 snmp_lookup_oidall(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s,
931     char *oid)
932 {
933 	if (snmptoolctx == NULL || s == NULL || oid == NULL)
934 		return (-1);
935 
936 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_intlist, s, oid) > 0)
937 		return (1);
938 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_octlist, s, oid) > 0)
939 		return (1);
940 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_oidlist, s, oid) > 0)
941 		return (1);
942 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_iplist, s, oid) > 0)
943 		return (1);
944 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_ticklist, s, oid) > 0)
945 		return (1);
946 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_cntlist, s, oid) > 0)
947 		return (1);
948 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_gaugelist, s, oid) > 0)
949 		return (1);
950 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_cnt64list, s, oid) > 0)
951 		return (1);
952 	if (snmp_lookup_oidlist(&snmptoolctx->snmp_nodelist, s, oid) > 0)
953 		return (1);
954 	if (snmp_lookup_tablelist(snmptoolctx, &snmptoolctx->snmp_tablelist,
955 	    s, oid) > 0)
956 		return (1);
957 
958 	return (-1);
959 }
960 
961 int32_t
962 snmp_lookup_enumoid(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s,
963     char *oid)
964 {
965 	if (snmptoolctx == NULL || s == NULL)
966 		return (-1);
967 
968 	return (snmp_lookup_oidlist(&snmptoolctx->snmp_enumlist, s, oid));
969 }
970 
971 int32_t
972 snmp_lookup_oid(struct snmp_toolinfo *snmptoolctx, struct snmp_object *s,
973     char *oid)
974 {
975 	if (snmptoolctx == NULL || s == NULL)
976 		return (-1);
977 
978 	switch (s->val.syntax) {
979 		case SNMP_SYNTAX_INTEGER:
980 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_intlist,
981 			    s, oid));
982 		case SNMP_SYNTAX_OCTETSTRING:
983 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_octlist,
984 			    s, oid));
985 		case SNMP_SYNTAX_OID:
986 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_oidlist,
987 			    s, oid));
988 		case SNMP_SYNTAX_IPADDRESS:
989 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_iplist,
990 			    s, oid));
991 		case SNMP_SYNTAX_COUNTER:
992 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_cntlist,
993 			    s, oid));
994 		case SNMP_SYNTAX_GAUGE:
995 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_gaugelist,
996 			    s, oid));
997 		case SNMP_SYNTAX_TIMETICKS:
998 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_ticklist,
999 			    s, oid));
1000 		case SNMP_SYNTAX_COUNTER64:
1001 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_cnt64list,
1002 			    s, oid));
1003 		case SNMP_SYNTAX_NULL:
1004 			return (snmp_lookup_oidlist(&snmptoolctx->snmp_nodelist,
1005 			    s, oid));
1006 		default:
1007 			warnx("Unknown syntax - %d", s->val.syntax);
1008 			break;
1009 	}
1010 
1011 	return (-1);
1012 }
1013