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