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
50extern int _bsnmptools_debug;
51#define	DEBUG	if (_bsnmptools_debug) fprintf
52
53/* Allocate memory and initialize list. */
54struct snmp_mappings *
55snmp_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
81void
82enum_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
100void
101snmp_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
112static void
113snmp_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
131void
132snmp_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
146static void
147snmp_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
162static void
163snmp_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
177int
178snmp_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
200static void
201snmp_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
216void
217snmp_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
232static void
233snmp_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. */
249struct enum_pairs *
250enum_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 */
267int32_t
268enum_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 */
298static int
299snmp_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
352int32_t
353snmp_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
361static int32_t
362snmp_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
370static int32_t
371snmp_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
379static int32_t
380snmp_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
388static int32_t
389snmp_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
397static int32_t
398snmp_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
406static int32_t
407snmp_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
415static int32_t
416snmp_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
424static int32_t
425snmp_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
433int32_t
434snmp_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
442int32_t
443snmp_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
469static int32_t
470snmp_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
479int32_t
480snmp_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
504int32_t
505snmp_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
556struct enum_type *
557snmp_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
577void
578snmp_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
587void
588snmp_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
596struct enum_type *
597snmp_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
611static void
612snmp_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
630static void
631snmp_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
648void
649snmp_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
698char *
699enum_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
714int32_t
715enum_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
729static int32_t
730snmp_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 */
748static int32_t
749snmp_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
767int32_t
768snmp_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
807int32_t
808snmp_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
816int32_t
817snmp_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
825int32_t
826snmp_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
834int32_t
835snmp_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
864int32_t
865snmp_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
879static int32_t
880snmp_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
903static int32_t
904snmp_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
935int32_t
936snmp_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
967int32_t
968snmp_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
977int32_t
978snmp_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