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