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