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. */
51 struct snmp_mappings *
snmp_mapping_init(void)52 snmp_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 
77 void
enum_pairs_free(struct enum_pairs * headp)78 enum_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 
96 void
snmp_mapping_entryfree(struct snmp_oid2str * entry)97 snmp_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 
108 static void
snmp_mapping_listfree(struct snmp_mapping * headp)109 snmp_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 
127 void
snmp_index_listfree(struct snmp_idxlist * headp)128 snmp_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 
142 static void
snmp_mapping_table_listfree(struct snmp_table_index * headp)143 snmp_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 
158 static void
snmp_enumtc_listfree(struct snmp_enum_tc * headp)159 snmp_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 
173 int
snmp_mapping_free(struct snmp_toolinfo * snmptoolctx)174 snmp_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 
196 static void
snmp_dump_enumpairs(struct enum_pairs * headp)197 snmp_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 
212 void
snmp_dump_oid2str(struct snmp_oid2str * entry)213 snmp_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 
228 static void
snmp_dump_indexlist(struct snmp_idxlist * headp)229 snmp_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. */
245 struct enum_pairs *
enum_pairs_init(void)246 enum_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  */
263 int32_t
enum_pair_insert(struct enum_pairs * headp,int32_t enum_val,char * enum_str)264 enum_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  */
291 static int
snmp_mapping_insert(struct snmp_mapping * headp,struct snmp_oid2str * entry)292 snmp_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 
345 int32_t
snmp_node_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)346 snmp_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 
354 static int32_t
snmp_int_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)355 snmp_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 
363 static int32_t
snmp_oct_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)364 snmp_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 
372 static int32_t
snmp_oid_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)373 snmp_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 
381 static int32_t
snmp_ip_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)382 snmp_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 
390 static int32_t
snmp_tick_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)391 snmp_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 
399 static int32_t
snmp_cnt_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)400 snmp_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 
408 static int32_t
snmp_gauge_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)409 snmp_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 
417 static int32_t
snmp_cnt64_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)418 snmp_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 
426 int32_t
snmp_enum_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)427 snmp_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 
435 int32_t
snmp_leaf_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * entry)436 snmp_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 
462 static int32_t
snmp_index_insert(struct snmp_idxlist * headp,struct index * idx)463 snmp_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 
472 int32_t
snmp_syntax_insert(struct snmp_idxlist * headp,struct enum_pairs * enums,enum snmp_syntax syntax,enum snmp_tc tc)473 snmp_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 
495 int32_t
snmp_table_insert(struct snmp_toolinfo * snmptoolctx,struct snmp_index_entry * entry)496 snmp_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 
547 struct enum_type *
snmp_enumtc_init(char * name)548 snmp_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 
566 void
snmp_enumtc_free(struct enum_type * tc)567 snmp_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 
576 void
snmp_enumtc_insert(struct snmp_toolinfo * snmptoolctx,struct enum_type * entry)577 snmp_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 
585 struct enum_type *
snmp_enumtc_lookup(struct snmp_toolinfo * snmptoolctx,char * name)586 snmp_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 
600 static void
snmp_mapping_dumplist(struct snmp_mapping * headp)601 snmp_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 
619 static void
snmp_mapping_dumptable(struct snmp_table_index * headp)620 snmp_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 
637 void
snmp_mapping_dump(struct snmp_toolinfo * snmptoolctx)638 snmp_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 
687 char *
enum_string_lookup(struct enum_pairs * headp,int32_t enum_val)688 enum_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 
703 int32_t
enum_number_lookup(struct enum_pairs * headp,char * e_str)704 enum_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 
718 static int32_t
snmp_lookuplist_string(struct snmp_mapping * headp,struct snmp_object * s)719 snmp_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 */
737 static int32_t
snmp_lookup_leaf(struct snmp_mapping * headp,struct snmp_object * s)738 snmp_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 
756 int32_t
snmp_lookup_leafstring(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)757 snmp_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 
796 int32_t
snmp_lookup_enumstring(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)797 snmp_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 
805 int32_t
snmp_lookup_oidstring(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)806 snmp_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 
814 int32_t
snmp_lookup_nodestring(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)815 snmp_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 
823 int32_t
snmp_lookup_allstring(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)824 snmp_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 
853 int32_t
snmp_lookup_nonleaf_string(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s)854 snmp_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 
868 static int32_t
snmp_lookup_oidlist(struct snmp_mapping * hp,struct snmp_object * s,char * oid)869 snmp_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 
892 static int32_t
snmp_lookup_tablelist(struct snmp_toolinfo * snmptoolctx,struct snmp_table_index * headp,struct snmp_object * s,char * oid)893 snmp_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 
924 int32_t
snmp_lookup_oidall(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s,char * oid)925 snmp_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 
956 int32_t
snmp_lookup_enumoid(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s,char * oid)957 snmp_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 
966 int32_t
snmp_lookup_oid(struct snmp_toolinfo * snmptoolctx,struct snmp_object * s,char * oid)967 snmp_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