xref: /freebsd/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmpimport.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1a7398723SShteryana Shopova /*-
2a7398723SShteryana Shopova  * Copyright (c) 2006 The FreeBSD Project
3a7398723SShteryana Shopova  * All rights reserved.
4a7398723SShteryana Shopova  *
5a7398723SShteryana Shopova  * Author: Shteryana Shopova <syrinx@FreeBSD.org>
6a7398723SShteryana Shopova  *
7a7398723SShteryana Shopova  * Redistribution of this software and documentation and use in source and
8a7398723SShteryana Shopova  * binary forms, with or without modification, are permitted provided that
9a7398723SShteryana Shopova  * the following conditions are met:
10a7398723SShteryana Shopova  *
11a7398723SShteryana Shopova  * 1. Redistributions of source code or documentation must retain the above
12a7398723SShteryana Shopova  *    copyright notice, this list of conditions and the following disclaimer.
13a7398723SShteryana Shopova  * 2. Redistributions in binary form must reproduce the above copyright
14a7398723SShteryana Shopova  *    notice, this list of conditions and the following disclaimer in the
15a7398723SShteryana Shopova  *    documentation and/or other materials provided with the distribution.
16a7398723SShteryana Shopova  *
17a7398723SShteryana Shopova  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18a7398723SShteryana Shopova  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19a7398723SShteryana Shopova  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20a7398723SShteryana Shopova  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21a7398723SShteryana Shopova  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22a7398723SShteryana Shopova  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23a7398723SShteryana Shopova  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a7398723SShteryana Shopova  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25a7398723SShteryana Shopova  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26a7398723SShteryana Shopova  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27a7398723SShteryana Shopova  * SUCH DAMAGE.
28a7398723SShteryana Shopova  */
29a7398723SShteryana Shopova 
30a7398723SShteryana Shopova /*
31a7398723SShteryana Shopova  * Read file containing table description - reuse magic from gensnmptree.c.
32a7398723SShteryana Shopova  * Hopefully one day most of the code here will be part of libbsnmp and
33a7398723SShteryana Shopova  * this duplication won't be necessary.
34a7398723SShteryana Shopova  *
35a7398723SShteryana Shopova  * Syntax is:
36a7398723SShteryana Shopova  * ---------
37a7398723SShteryana Shopova  * file := top | top file
38a7398723SShteryana Shopova  *
39a7398723SShteryana Shopova  * top := tree | typedef | include
40a7398723SShteryana Shopova  *
41a7398723SShteryana Shopova  * tree := head elements ')'
42a7398723SShteryana Shopova  *
43a7398723SShteryana Shopova  * entry := head ':' index STRING elements ')'
44a7398723SShteryana Shopova  *
45a7398723SShteryana Shopova  * leaf := head type STRING ACCESS ')'
46a7398723SShteryana Shopova  *
47a7398723SShteryana Shopova  * column := head type ACCESS ')'
48a7398723SShteryana Shopova  *
49a7398723SShteryana Shopova  * type := BASETYPE | BASETYPE '|' subtype | enum | bits
50a7398723SShteryana Shopova  *
51a7398723SShteryana Shopova  * subtype := STRING
52a7398723SShteryana Shopova  *
53a7398723SShteryana Shopova  * enum := ENUM '(' value ')'
54a7398723SShteryana Shopova  *
55a7398723SShteryana Shopova  * bits := BITS '(' value ')'
56a7398723SShteryana Shopova  *
57a7398723SShteryana Shopova  * value := INT STRING | INT STRING value
58a7398723SShteryana Shopova  *
59a7398723SShteryana Shopova  * head := '(' INT STRING
60a7398723SShteryana Shopova  *
61a7398723SShteryana Shopova  * elements := EMPTY | elements element
62a7398723SShteryana Shopova  *
63a7398723SShteryana Shopova  * element := tree | leaf | column
64a7398723SShteryana Shopova  *
65a7398723SShteryana Shopova  * index := type | index type
66a7398723SShteryana Shopova  *
67a7398723SShteryana Shopova  * typedef := 'typedef' STRING type
68a7398723SShteryana Shopova  *
69a7398723SShteryana Shopova  * include := 'include' filespec
70a7398723SShteryana Shopova  *
71a7398723SShteryana Shopova  * filespec := '"' STRING '"' | '<' STRING '>'
72a7398723SShteryana Shopova  */
73a7398723SShteryana Shopova 
74a7398723SShteryana Shopova #include <sys/param.h>
75a7398723SShteryana Shopova #include <sys/queue.h>
76a7398723SShteryana Shopova #include <sys/uio.h>
77a7398723SShteryana Shopova 
78a7398723SShteryana Shopova #include <ctype.h>
79a7398723SShteryana Shopova #include <err.h>
80a7398723SShteryana Shopova #include <errno.h>
81a7398723SShteryana Shopova #include <fcntl.h>
82*1f474190SStefan Eßer #include <paths.h>
83a7398723SShteryana Shopova #include <stdio.h>
84a7398723SShteryana Shopova #include <stdlib.h>
85a7398723SShteryana Shopova #include <string.h>
86a7398723SShteryana Shopova #include <syslog.h>
87a7398723SShteryana Shopova #include <unistd.h>
88a7398723SShteryana Shopova 
89a7398723SShteryana Shopova #include <bsnmp/asn1.h>
90a7398723SShteryana Shopova #include <bsnmp/snmp.h>
91a7398723SShteryana Shopova #include <bsnmp/snmpagent.h>	/* SNMP_INDEXES_MAX */
92a7398723SShteryana Shopova #include "bsnmptc.h"
93a7398723SShteryana Shopova #include "bsnmptools.h"
94a7398723SShteryana Shopova 
95a7398723SShteryana Shopova enum snmp_tbl_entry {
96a7398723SShteryana Shopova 	ENTRY_NONE = 0,
97a7398723SShteryana Shopova 	ENTRY_INDEX,
98a7398723SShteryana Shopova 	ENTRY_DATA
99a7398723SShteryana Shopova };
100a7398723SShteryana Shopova 
101a7398723SShteryana Shopova enum {
102a7398723SShteryana Shopova 	FL_GET	= 0x01,
103a7398723SShteryana Shopova 	FL_SET	= 0x02,
104a7398723SShteryana Shopova };
105a7398723SShteryana Shopova 
106a7398723SShteryana Shopova /************************************************************
107a7398723SShteryana Shopova  *
108a7398723SShteryana Shopova  * Allocate memory and panic just in the case...
109a7398723SShteryana Shopova  */
110a7398723SShteryana Shopova static void *
xalloc(size_t size)111a7398723SShteryana Shopova xalloc(size_t size)
112a7398723SShteryana Shopova {
113a7398723SShteryana Shopova 	void *ptr;
114a7398723SShteryana Shopova 
115a7398723SShteryana Shopova 	if ((ptr = malloc(size)) == NULL)
116a7398723SShteryana Shopova 		err(1, "allocing %zu bytes", size);
117a7398723SShteryana Shopova 
118a7398723SShteryana Shopova 	return (ptr);
119a7398723SShteryana Shopova }
120a7398723SShteryana Shopova 
121a7398723SShteryana Shopova static char *
savestr(const char * s)122a7398723SShteryana Shopova savestr(const char *s)
123a7398723SShteryana Shopova {
124a7398723SShteryana Shopova 	if (s == NULL)
125a7398723SShteryana Shopova 		return (NULL);
126a7398723SShteryana Shopova 
127a7398723SShteryana Shopova 	return (strcpy(xalloc(strlen(s) + 1), s));
128a7398723SShteryana Shopova }
129a7398723SShteryana Shopova 
130a7398723SShteryana Shopova /************************************************************
131a7398723SShteryana Shopova  *
132a7398723SShteryana Shopova  * Input stack
133a7398723SShteryana Shopova  */
134a7398723SShteryana Shopova struct input {
135a7398723SShteryana Shopova 	FILE		*fp;
136a7398723SShteryana Shopova 	uint32_t	lno;
137a7398723SShteryana Shopova 	char		*fname;
138a7398723SShteryana Shopova 	char		*path;
139a7398723SShteryana Shopova 	LIST_ENTRY(input) link;
140a7398723SShteryana Shopova };
141a7398723SShteryana Shopova 
14229517fcaSEnji Cooper static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs);
14329517fcaSEnji Cooper static struct input *input = NULL;
14429517fcaSEnji Cooper static int32_t pbchar = -1;
145a7398723SShteryana Shopova 
146a7398723SShteryana Shopova #define	MAX_PATHS	100
147a7398723SShteryana Shopova 
148a7398723SShteryana Shopova static const char *paths[MAX_PATHS + 1] = {
149a7398723SShteryana Shopova 	"/usr/share/snmp/defs",
150*1f474190SStefan Eßer 	_PATH_LOCALBASE "/share/snmp/defs",
151a7398723SShteryana Shopova 	NULL
152a7398723SShteryana Shopova };
153a7398723SShteryana Shopova 
154a7398723SShteryana Shopova static void
input_new(FILE * fp,const char * path,const char * fname)155a7398723SShteryana Shopova input_new(FILE *fp, const char *path, const char *fname)
156a7398723SShteryana Shopova {
157a7398723SShteryana Shopova 	struct input *ip;
158a7398723SShteryana Shopova 
159a7398723SShteryana Shopova 	ip = xalloc(sizeof(*ip));
160a7398723SShteryana Shopova 	ip->fp = fp;
161a7398723SShteryana Shopova 	ip->lno = 1;
162a7398723SShteryana Shopova 	ip->fname = savestr(fname);
163a7398723SShteryana Shopova 	ip->path = savestr(path);
164a7398723SShteryana Shopova 	LIST_INSERT_HEAD(&inputs, ip, link);
165a7398723SShteryana Shopova 
166a7398723SShteryana Shopova 	input = ip;
167a7398723SShteryana Shopova }
168a7398723SShteryana Shopova 
169a7398723SShteryana Shopova static void
input_close(void)170a7398723SShteryana Shopova input_close(void)
171a7398723SShteryana Shopova {
172a7398723SShteryana Shopova 	if (input == NULL)
173a7398723SShteryana Shopova 		return;
174a7398723SShteryana Shopova 
175a7398723SShteryana Shopova 	fclose(input->fp);
176a7398723SShteryana Shopova 	free(input->fname);
177a7398723SShteryana Shopova 	free(input->path);
178a7398723SShteryana Shopova 	LIST_REMOVE(input, link);
179a7398723SShteryana Shopova 	free(input);
180a7398723SShteryana Shopova 
181a7398723SShteryana Shopova 	input = LIST_FIRST(&inputs);
182a7398723SShteryana Shopova }
183a7398723SShteryana Shopova 
184a7398723SShteryana Shopova static FILE *
tryopen(const char * path,const char * fname)185a7398723SShteryana Shopova tryopen(const char *path, const char *fname)
186a7398723SShteryana Shopova {
187a7398723SShteryana Shopova 	char *fn;
188a7398723SShteryana Shopova 	FILE *fp;
189a7398723SShteryana Shopova 
190a7398723SShteryana Shopova 	if (path == NULL)
191a7398723SShteryana Shopova 		fn = savestr(fname);
192a7398723SShteryana Shopova 	else {
193a7398723SShteryana Shopova 		fn = xalloc(strlen(path) + strlen(fname) + 2);
194a7398723SShteryana Shopova 		sprintf(fn, "%s/%s", path, fname);
195a7398723SShteryana Shopova 	}
196a7398723SShteryana Shopova 	fp = fopen(fn, "r");
197a7398723SShteryana Shopova 	free(fn);
198a7398723SShteryana Shopova 	return (fp);
199a7398723SShteryana Shopova }
200a7398723SShteryana Shopova 
201a7398723SShteryana Shopova static int32_t
input_fopen(const char * fname)202a7398723SShteryana Shopova input_fopen(const char *fname)
203a7398723SShteryana Shopova {
204a7398723SShteryana Shopova 	FILE *fp;
205a7398723SShteryana Shopova 	u_int p;
206a7398723SShteryana Shopova 
207a7398723SShteryana Shopova 	if (fname[0] == '/' || fname[0] == '.' || fname[0] == '~') {
208a7398723SShteryana Shopova 		if ((fp = tryopen(NULL, fname)) != NULL) {
209a7398723SShteryana Shopova 			input_new(fp, NULL, fname);
210a7398723SShteryana Shopova 			return (0);
211a7398723SShteryana Shopova 		}
212a7398723SShteryana Shopova 
213a7398723SShteryana Shopova 	} else {
214a7398723SShteryana Shopova 
215a7398723SShteryana Shopova 		for (p = 0; paths[p] != NULL; p++)
216a7398723SShteryana Shopova 			if ((fp = tryopen(paths[p], fname)) != NULL) {
217a7398723SShteryana Shopova 				input_new(fp, paths[p], fname);
218a7398723SShteryana Shopova 				return (0);
219a7398723SShteryana Shopova 			}
220a7398723SShteryana Shopova 	}
221a7398723SShteryana Shopova 
222a7398723SShteryana Shopova 	warnx("cannot open '%s'", fname);
223a7398723SShteryana Shopova 	return (-1);
224a7398723SShteryana Shopova }
225a7398723SShteryana Shopova 
226a7398723SShteryana Shopova static int32_t
tgetc(void)227a7398723SShteryana Shopova tgetc(void)
228a7398723SShteryana Shopova {
229a7398723SShteryana Shopova 	int c;
230a7398723SShteryana Shopova 
231a7398723SShteryana Shopova 	if (pbchar != -1) {
232a7398723SShteryana Shopova 		c = pbchar;
233a7398723SShteryana Shopova 		pbchar = -1;
234a7398723SShteryana Shopova 		return (c);
235a7398723SShteryana Shopova 	}
236a7398723SShteryana Shopova 
237a7398723SShteryana Shopova 	for (;;) {
238a7398723SShteryana Shopova 		if (input == NULL)
239a7398723SShteryana Shopova 			return (EOF);
240a7398723SShteryana Shopova 
241a7398723SShteryana Shopova 		if ((c = getc(input->fp)) != EOF)
242a7398723SShteryana Shopova 			return (c);
243a7398723SShteryana Shopova 
244a7398723SShteryana Shopova 		input_close();
245a7398723SShteryana Shopova 	}
246a7398723SShteryana Shopova }
247a7398723SShteryana Shopova 
248a7398723SShteryana Shopova static int32_t
tungetc(int c)249a7398723SShteryana Shopova tungetc(int c)
250a7398723SShteryana Shopova {
251a7398723SShteryana Shopova 
252a7398723SShteryana Shopova 	if (pbchar != -1)
253a7398723SShteryana Shopova 		return (-1);
254a7398723SShteryana Shopova 
255a7398723SShteryana Shopova 	pbchar = c;
256a7398723SShteryana Shopova 	return (1);
257a7398723SShteryana Shopova }
258a7398723SShteryana Shopova 
259a7398723SShteryana Shopova /************************************************************
260a7398723SShteryana Shopova  *
261a7398723SShteryana Shopova  * Parsing input
262a7398723SShteryana Shopova  */
263a7398723SShteryana Shopova enum tok {
264a7398723SShteryana Shopova 	TOK_EOF = 0200,	/* end-of-file seen */
265a7398723SShteryana Shopova 	TOK_NUM,	/* number */
266a7398723SShteryana Shopova 	TOK_STR,	/* string */
267a7398723SShteryana Shopova 	TOK_ACCESS,	/* access operator */
268a7398723SShteryana Shopova 	TOK_TYPE,	/* type operator */
269a7398723SShteryana Shopova 	TOK_ENUM,	/* enum token (kind of a type) */
270a7398723SShteryana Shopova 	TOK_TYPEDEF,	/* typedef directive */
271a7398723SShteryana Shopova 	TOK_DEFTYPE,	/* defined type */
272a7398723SShteryana Shopova 	TOK_INCLUDE,	/* include directive */
273a7398723SShteryana Shopova 	TOK_FILENAME,	/* filename ("foo.bar" or <foo.bar>) */
274a7398723SShteryana Shopova 	TOK_BITS,	/* bits token (kind of a type) */
275a7398723SShteryana Shopova 	TOK_ERR		/* unexpected char - exit */
276a7398723SShteryana Shopova };
277a7398723SShteryana Shopova 
278a7398723SShteryana Shopova static const struct {
279a7398723SShteryana Shopova 	const char	*str;
280a7398723SShteryana Shopova 	enum tok	tok;
281a7398723SShteryana Shopova 	uint32_t	val;
282a7398723SShteryana Shopova } keywords[] = {
283a7398723SShteryana Shopova 	{ "GET", TOK_ACCESS, FL_GET },
284a7398723SShteryana Shopova 	{ "SET", TOK_ACCESS, FL_SET },
285a7398723SShteryana Shopova 	{ "NULL", TOK_TYPE, SNMP_SYNTAX_NULL },
286a7398723SShteryana Shopova 	{ "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER },
287a7398723SShteryana Shopova 	{ "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER },
288a7398723SShteryana Shopova 	{ "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE },
289a7398723SShteryana Shopova 	{ "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING },
290a7398723SShteryana Shopova 	{ "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS },
291a7398723SShteryana Shopova 	{ "OID", TOK_TYPE, SNMP_SYNTAX_OID },
292a7398723SShteryana Shopova 	{ "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS },
293a7398723SShteryana Shopova 	{ "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER },
294a7398723SShteryana Shopova 	{ "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE },
295a7398723SShteryana Shopova 	{ "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 },
296a7398723SShteryana Shopova 	{ "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER },
297a7398723SShteryana Shopova 	{ "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING },
298a7398723SShteryana Shopova 	{ "typedef", TOK_TYPEDEF, 0 },
299a7398723SShteryana Shopova 	{ "include", TOK_INCLUDE, 0 },
300a7398723SShteryana Shopova 	{ NULL, 0, 0 }
301a7398723SShteryana Shopova };
302a7398723SShteryana Shopova 
30329517fcaSEnji Cooper static struct {
304a7398723SShteryana Shopova 	/* Current OID type, regarding table membership. */
305a7398723SShteryana Shopova 	enum snmp_tbl_entry	tbl_type;
306a7398723SShteryana Shopova 	/* A pointer to a structure in table list to add to its members. */
307a7398723SShteryana Shopova 	struct snmp_index_entry	*table_idx;
308a7398723SShteryana Shopova } table_data;
309a7398723SShteryana Shopova 
31029517fcaSEnji Cooper static struct asn_oid current_oid;
31129517fcaSEnji Cooper static char nexttok[MAXSTR];
31229517fcaSEnji Cooper static u_long val;		/* integer values */
31329517fcaSEnji Cooper static int32_t	all_cond;	/* all conditions are true */
31429517fcaSEnji Cooper static int32_t saved_token = -1;
315a7398723SShteryana Shopova 
316a7398723SShteryana Shopova /* Prepare the global data before parsing a new file. */
317a7398723SShteryana Shopova static void
snmp_import_init(struct asn_oid * append)318a7398723SShteryana Shopova snmp_import_init(struct asn_oid *append)
319a7398723SShteryana Shopova {
320a7398723SShteryana Shopova 	memset(&table_data, 0, sizeof(table_data));
321a7398723SShteryana Shopova 	memset(&current_oid, 0, sizeof(struct asn_oid));
322a7398723SShteryana Shopova 	memset(nexttok, 0, MAXSTR);
323a7398723SShteryana Shopova 
324a7398723SShteryana Shopova 	if (append != NULL)
325a7398723SShteryana Shopova 		asn_append_oid(&current_oid, append);
326a7398723SShteryana Shopova 
327a7398723SShteryana Shopova 	all_cond = 0;
328a7398723SShteryana Shopova 	val = 0;
329a7398723SShteryana Shopova 	saved_token = -1;
330a7398723SShteryana Shopova }
331a7398723SShteryana Shopova 
332a7398723SShteryana Shopova static int32_t
gettoken(struct snmp_toolinfo * snmptoolctx)333a7398723SShteryana Shopova gettoken(struct snmp_toolinfo *snmptoolctx)
334a7398723SShteryana Shopova {
335a7398723SShteryana Shopova 	int c;
336a7398723SShteryana Shopova 	struct enum_type *t;
337a7398723SShteryana Shopova 
338a7398723SShteryana Shopova 	if (saved_token != -1) {
339a7398723SShteryana Shopova 		c = saved_token;
340a7398723SShteryana Shopova 		saved_token = -1;
341a7398723SShteryana Shopova 		return (c);
342a7398723SShteryana Shopova 	}
343a7398723SShteryana Shopova 
344a7398723SShteryana Shopova   again:
345a7398723SShteryana Shopova 	/*
346a7398723SShteryana Shopova 	 * Skip any whitespace before the next token.
347a7398723SShteryana Shopova 	 */
348a7398723SShteryana Shopova 	while ((c = tgetc()) != EOF) {
349a7398723SShteryana Shopova 		if (c == '\n')
350a7398723SShteryana Shopova 			input->lno++;
351a7398723SShteryana Shopova 		if (!isspace(c))
352a7398723SShteryana Shopova 			break;
353a7398723SShteryana Shopova 	}
354a7398723SShteryana Shopova 	if (c == EOF)
355a7398723SShteryana Shopova 		return (TOK_EOF);
356a7398723SShteryana Shopova 
357a7398723SShteryana Shopova 	if (!isascii(c)) {
358a7398723SShteryana Shopova 		warnx("unexpected character %#2x", (u_int) c);
359a7398723SShteryana Shopova 		return (TOK_ERR);
360a7398723SShteryana Shopova 	}
361a7398723SShteryana Shopova 
362a7398723SShteryana Shopova 	/*
363a7398723SShteryana Shopova 	 * Skip comments.
364a7398723SShteryana Shopova 	 */
365a7398723SShteryana Shopova 	if (c == '#') {
366a7398723SShteryana Shopova 		while ((c = tgetc()) != EOF) {
367a7398723SShteryana Shopova 			if (c == '\n') {
368a7398723SShteryana Shopova 				input->lno++;
369a7398723SShteryana Shopova 				goto again;
370a7398723SShteryana Shopova 			}
371a7398723SShteryana Shopova 		}
372a7398723SShteryana Shopova 		warnx("unexpected EOF in comment");
373a7398723SShteryana Shopova 		return (TOK_ERR);
374a7398723SShteryana Shopova 	}
375a7398723SShteryana Shopova 
376a7398723SShteryana Shopova 	/*
377a7398723SShteryana Shopova 	 * Single character tokens.
378a7398723SShteryana Shopova 	 */
379a7398723SShteryana Shopova 	if (strchr("():|", c) != NULL)
380a7398723SShteryana Shopova 		return (c);
381a7398723SShteryana Shopova 
382a7398723SShteryana Shopova 	if (c == '"' || c == '<') {
383a7398723SShteryana Shopova 		int32_t end = c;
384a7398723SShteryana Shopova 		size_t n = 0;
385a7398723SShteryana Shopova 
386a7398723SShteryana Shopova 		val = 1;
387a7398723SShteryana Shopova 		if (c == '<') {
388a7398723SShteryana Shopova 			val = 0;
389a7398723SShteryana Shopova 			end = '>';
390a7398723SShteryana Shopova 		}
391a7398723SShteryana Shopova 
392a7398723SShteryana Shopova 		while ((c = tgetc()) != EOF) {
393a7398723SShteryana Shopova 			if (c == end)
394a7398723SShteryana Shopova 				break;
395a7398723SShteryana Shopova 			if (n == sizeof(nexttok) - 1) {
396a7398723SShteryana Shopova 				nexttok[n++] = '\0';
397a7398723SShteryana Shopova 				warnx("filename too long '%s...'", nexttok);
398a7398723SShteryana Shopova 				return (TOK_ERR);
399a7398723SShteryana Shopova 			}
400a7398723SShteryana Shopova 			nexttok[n++] = c;
401a7398723SShteryana Shopova 		}
402a7398723SShteryana Shopova 		nexttok[n++] = '\0';
403a7398723SShteryana Shopova 		return (TOK_FILENAME);
404a7398723SShteryana Shopova 	}
405a7398723SShteryana Shopova 
406a7398723SShteryana Shopova 	/*
407a7398723SShteryana Shopova 	 * Sort out numbers.
408a7398723SShteryana Shopova 	 */
409a7398723SShteryana Shopova 	if (isdigit(c)) {
410a7398723SShteryana Shopova 		size_t n = 0;
411a7398723SShteryana Shopova 		nexttok[n++] = c;
412a7398723SShteryana Shopova 		while ((c = tgetc()) != EOF) {
413a7398723SShteryana Shopova 			if (!isdigit(c)) {
414a7398723SShteryana Shopova 				if (tungetc(c) < 0)
415a7398723SShteryana Shopova 					return (TOK_ERR);
416a7398723SShteryana Shopova 				break;
417a7398723SShteryana Shopova 			}
418a7398723SShteryana Shopova 			if (n == sizeof(nexttok) - 1) {
419a7398723SShteryana Shopova 				nexttok[n++] = '\0';
420a7398723SShteryana Shopova 				warnx("number too long '%s...'", nexttok);
421a7398723SShteryana Shopova 				return (TOK_ERR);
422a7398723SShteryana Shopova 			}
423a7398723SShteryana Shopova 			nexttok[n++] = c;
424a7398723SShteryana Shopova 		}
425a7398723SShteryana Shopova 		nexttok[n++] = '\0';
426a7398723SShteryana Shopova 		sscanf(nexttok, "%lu", &val);
427a7398723SShteryana Shopova 		return (TOK_NUM);
428a7398723SShteryana Shopova 	}
429a7398723SShteryana Shopova 
430a7398723SShteryana Shopova 	/*
431a7398723SShteryana Shopova 	 * So that has to be a string.
432a7398723SShteryana Shopova 	 */
433a7398723SShteryana Shopova 	if (isalpha(c) || c == '_' || c == '-') {
434a7398723SShteryana Shopova 		size_t n = 0;
435a7398723SShteryana Shopova 		nexttok[n++] = c;
436a7398723SShteryana Shopova 		while ((c = tgetc()) != EOF) {
437a7398723SShteryana Shopova 			if (!isalnum(c) && c != '_' && c != '-') {
438a7398723SShteryana Shopova 				if (tungetc (c) < 0)
439a7398723SShteryana Shopova 					return (TOK_ERR);
440a7398723SShteryana Shopova 				break;
441a7398723SShteryana Shopova 			}
442a7398723SShteryana Shopova 			if (n == sizeof(nexttok) - 1) {
443a7398723SShteryana Shopova 				nexttok[n++] = '\0';
444a7398723SShteryana Shopova 				warnx("string too long '%s...'", nexttok);
445a7398723SShteryana Shopova 				return (TOK_ERR);
446a7398723SShteryana Shopova 			}
447a7398723SShteryana Shopova 			nexttok[n++] = c;
448a7398723SShteryana Shopova 		}
449a7398723SShteryana Shopova 		nexttok[n++] = '\0';
450a7398723SShteryana Shopova 
451a7398723SShteryana Shopova 		/*
452a7398723SShteryana Shopova 		 * Keywords.
453a7398723SShteryana Shopova 		 */
454a7398723SShteryana Shopova 		for (c = 0; keywords[c].str != NULL; c++)
455a7398723SShteryana Shopova 			if (strcmp(keywords[c].str, nexttok) == 0) {
456a7398723SShteryana Shopova 				val = keywords[c].val;
457a7398723SShteryana Shopova 				return (keywords[c].tok);
458a7398723SShteryana Shopova 			}
459a7398723SShteryana Shopova 
460a7398723SShteryana Shopova 		if ((t = snmp_enumtc_lookup(snmptoolctx, nexttok)) != NULL) {
461a7398723SShteryana Shopova 			val = t->syntax;
462a7398723SShteryana Shopova 			return (TOK_DEFTYPE);
463a7398723SShteryana Shopova 		}
464a7398723SShteryana Shopova 
465a7398723SShteryana Shopova 		return (TOK_STR);
466a7398723SShteryana Shopova 	}
467a7398723SShteryana Shopova 
468a7398723SShteryana Shopova 	if (isprint(c))
469a7398723SShteryana Shopova 		warnx("%u: unexpected character '%c'", input->lno, c);
470a7398723SShteryana Shopova 	else
471a7398723SShteryana Shopova 		warnx("%u: unexpected character 0x%02x", input->lno, (u_int) c);
472a7398723SShteryana Shopova 
473a7398723SShteryana Shopova 	return (TOK_ERR);
474a7398723SShteryana Shopova }
475a7398723SShteryana Shopova 
476a7398723SShteryana Shopova /*
477a7398723SShteryana Shopova  * Update table information.
478a7398723SShteryana Shopova  */
479a7398723SShteryana Shopova static struct snmp_index_entry *
snmp_import_update_table(enum snmp_tbl_entry te,struct snmp_index_entry * tbl)480a7398723SShteryana Shopova snmp_import_update_table(enum snmp_tbl_entry te, struct snmp_index_entry *tbl)
481a7398723SShteryana Shopova {
482a7398723SShteryana Shopova 	switch (te) {
483a7398723SShteryana Shopova 		case ENTRY_NONE:
484a7398723SShteryana Shopova 			if (table_data.tbl_type == ENTRY_NONE)
485a7398723SShteryana Shopova 				return (NULL);
486a7398723SShteryana Shopova 			if (table_data.tbl_type == ENTRY_INDEX)
487a7398723SShteryana Shopova 				table_data.table_idx = NULL;
488a7398723SShteryana Shopova 			table_data.tbl_type--;
489a7398723SShteryana Shopova 			return (NULL);
490a7398723SShteryana Shopova 
491a7398723SShteryana Shopova 		case ENTRY_INDEX:
492a7398723SShteryana Shopova 			if (tbl == NULL)
493a7398723SShteryana Shopova 				warnx("No table_index to add!!!");
494a7398723SShteryana Shopova 			table_data.table_idx = tbl;
495a7398723SShteryana Shopova 			table_data.tbl_type = ENTRY_INDEX;
496a7398723SShteryana Shopova 			return (tbl);
497a7398723SShteryana Shopova 
498a7398723SShteryana Shopova 		case ENTRY_DATA:
499a7398723SShteryana Shopova 			if (table_data.tbl_type == ENTRY_INDEX) {
500a7398723SShteryana Shopova 				table_data.tbl_type = ENTRY_DATA;
501a7398723SShteryana Shopova 				return (table_data.table_idx);
502a7398723SShteryana Shopova 			}
503a7398723SShteryana Shopova 			return (NULL);
504a7398723SShteryana Shopova 
505a7398723SShteryana Shopova 		default:
506a7398723SShteryana Shopova 			/* NOTREACHED */
507a7398723SShteryana Shopova 			warnx("Unknown table entry type!!!");
508a7398723SShteryana Shopova 			break;
509a7398723SShteryana Shopova 	}
510a7398723SShteryana Shopova 
511a7398723SShteryana Shopova 	return (NULL);
512a7398723SShteryana Shopova }
513a7398723SShteryana Shopova 
514a7398723SShteryana Shopova static int32_t
parse_enum(struct snmp_toolinfo * snmptoolctx,int32_t * tok,struct enum_pairs * enums)5154a2b63d5SEnji Cooper parse_enum(struct snmp_toolinfo *snmptoolctx, int32_t *tok,
516a7398723SShteryana Shopova     struct enum_pairs *enums)
517a7398723SShteryana Shopova {
518a7398723SShteryana Shopova 	while ((*tok = gettoken(snmptoolctx)) == TOK_STR) {
519a7398723SShteryana Shopova 		if (enum_pair_insert(enums, val, nexttok) < 0)
520a7398723SShteryana Shopova 			return (-1);
521a7398723SShteryana Shopova 		if ((*tok = gettoken(snmptoolctx)) != TOK_NUM)
522a7398723SShteryana Shopova 			break;
523a7398723SShteryana Shopova 	}
524a7398723SShteryana Shopova 
525a7398723SShteryana Shopova 	if (*tok != ')') {
526a7398723SShteryana Shopova 		warnx("')' at end of enums");
527a7398723SShteryana Shopova 		return (-1);
528a7398723SShteryana Shopova 	}
529a7398723SShteryana Shopova 
530a7398723SShteryana Shopova 	return (1);
531a7398723SShteryana Shopova }
532a7398723SShteryana Shopova 
533a7398723SShteryana Shopova static int32_t
parse_subtype(struct snmp_toolinfo * snmptoolctx,int32_t * tok,enum snmp_tc * tc)5344a2b63d5SEnji Cooper parse_subtype(struct snmp_toolinfo *snmptoolctx, int32_t *tok,
535a7398723SShteryana Shopova     enum snmp_tc *tc)
536a7398723SShteryana Shopova {
537a7398723SShteryana Shopova 	if ((*tok = gettoken(snmptoolctx)) != TOK_STR) {
538a7398723SShteryana Shopova 		warnx("subtype expected after '|'");
539a7398723SShteryana Shopova 		return (-1);
540a7398723SShteryana Shopova 	}
541a7398723SShteryana Shopova 
542a7398723SShteryana Shopova 	*tc = snmp_get_tc(nexttok);
543a7398723SShteryana Shopova 	*tok = gettoken(snmptoolctx);
544a7398723SShteryana Shopova 
545a7398723SShteryana Shopova 	return (1);
546a7398723SShteryana Shopova }
547a7398723SShteryana Shopova 
548a7398723SShteryana Shopova static int32_t
parse_type(struct snmp_toolinfo * snmptoolctx,int32_t * tok,enum snmp_tc * tc,struct enum_pairs ** snmp_enum)5494a2b63d5SEnji Cooper parse_type(struct snmp_toolinfo *snmptoolctx, int32_t *tok,
550a7398723SShteryana Shopova     enum snmp_tc *tc, struct enum_pairs **snmp_enum)
551a7398723SShteryana Shopova {
552a7398723SShteryana Shopova 	int32_t syntax, mem;
553a7398723SShteryana Shopova 
554a7398723SShteryana Shopova 	syntax = val;
555a7398723SShteryana Shopova 	*tc = 0;
556a7398723SShteryana Shopova 
557a7398723SShteryana Shopova 	if (*tok == TOK_ENUM || *tok == TOK_BITS) {
558a7398723SShteryana Shopova 		if (*snmp_enum == NULL) {
559a7398723SShteryana Shopova 			if ((*snmp_enum = enum_pairs_init()) == NULL)
560a7398723SShteryana Shopova 				return (-1);
561a7398723SShteryana Shopova 			mem = 1;
562a7398723SShteryana Shopova 			*tc = SNMP_TC_OWN;
563a7398723SShteryana Shopova 		} else
564a7398723SShteryana Shopova 			mem = 0;
565a7398723SShteryana Shopova 
566a7398723SShteryana Shopova 		if (gettoken(snmptoolctx) != '(') {
567a7398723SShteryana Shopova 			warnx("'(' expected after ENUM/BITS");
568a7398723SShteryana Shopova 			return (-1);
569a7398723SShteryana Shopova 		}
570a7398723SShteryana Shopova 
571a7398723SShteryana Shopova 		if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) {
572a7398723SShteryana Shopova 			warnx("need value for ENUM//BITS");
573a7398723SShteryana Shopova 			if (mem == 1) {
574a7398723SShteryana Shopova 				free(*snmp_enum);
575a7398723SShteryana Shopova 				*snmp_enum = NULL;
576a7398723SShteryana Shopova 			}
577a7398723SShteryana Shopova 			return (-1);
578a7398723SShteryana Shopova 		}
579a7398723SShteryana Shopova 
580a7398723SShteryana Shopova 		if (parse_enum(snmptoolctx, tok, *snmp_enum) < 0) {
581a7398723SShteryana Shopova 			enum_pairs_free(*snmp_enum);
582a7398723SShteryana Shopova 			*snmp_enum = NULL;
583a7398723SShteryana Shopova 			return (-1);
584a7398723SShteryana Shopova 		}
585a7398723SShteryana Shopova 
586a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
587a7398723SShteryana Shopova 
588a7398723SShteryana Shopova 	} else if (*tok == TOK_DEFTYPE) {
589a7398723SShteryana Shopova 		struct enum_type *t;
590a7398723SShteryana Shopova 
591a7398723SShteryana Shopova 		*tc = 0;
592a7398723SShteryana Shopova 		t = snmp_enumtc_lookup(snmptoolctx, nexttok);
593a7398723SShteryana Shopova 		if (t != NULL)
594a7398723SShteryana Shopova 			*snmp_enum = t->snmp_enum;
595a7398723SShteryana Shopova 
596a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
597a7398723SShteryana Shopova 
598a7398723SShteryana Shopova 	} else {
599a7398723SShteryana Shopova 		if ((*tok = gettoken(snmptoolctx)) == '|') {
600a7398723SShteryana Shopova 			if (parse_subtype(snmptoolctx, tok, tc) < 0)
601a7398723SShteryana Shopova 				return (-1);
602a7398723SShteryana Shopova 		}
603a7398723SShteryana Shopova 	}
604a7398723SShteryana Shopova 
605a7398723SShteryana Shopova 	return (syntax);
606a7398723SShteryana Shopova }
607a7398723SShteryana Shopova 
608a7398723SShteryana Shopova static int32_t
snmp_import_head(struct snmp_toolinfo * snmptoolctx)609a7398723SShteryana Shopova snmp_import_head(struct snmp_toolinfo *snmptoolctx)
610a7398723SShteryana Shopova {
611a7398723SShteryana Shopova 	enum tok tok;
612a7398723SShteryana Shopova 
613a7398723SShteryana Shopova 	if ((tok = gettoken(snmptoolctx)) == '(')
614a7398723SShteryana Shopova 		tok = gettoken(snmptoolctx);
615a7398723SShteryana Shopova 
616a7398723SShteryana Shopova 	if (tok != TOK_NUM  || val > ASN_MAXID ) {
617a7398723SShteryana Shopova 		warnx("Suboid expected - line %d", input->lno);
618a7398723SShteryana Shopova 		return (-1);
619a7398723SShteryana Shopova 	}
620a7398723SShteryana Shopova 
621a7398723SShteryana Shopova 	if (gettoken(snmptoolctx) != TOK_STR) {
622a7398723SShteryana Shopova 		warnx("Node name expected at line %d", input->lno);
623a7398723SShteryana Shopova 		return (-1);
624a7398723SShteryana Shopova 	}
625a7398723SShteryana Shopova 
626a7398723SShteryana Shopova 	return (1);
627a7398723SShteryana Shopova }
628a7398723SShteryana Shopova 
629a7398723SShteryana Shopova static int32_t
snmp_import_table(struct snmp_toolinfo * snmptoolctx,struct snmp_oid2str * obj)630a7398723SShteryana Shopova snmp_import_table(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *obj)
631a7398723SShteryana Shopova {
6324a2b63d5SEnji Cooper 	int32_t i, tok;
633a7398723SShteryana Shopova 	enum snmp_tc tc;
634a7398723SShteryana Shopova 	struct snmp_index_entry *entry;
635a7398723SShteryana Shopova 
63666987347SEnji Cooper 	if ((entry = calloc(1, sizeof(struct snmp_index_entry))) == NULL) {
637a7398723SShteryana Shopova 		syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));
638a7398723SShteryana Shopova 		return (-1);
639a7398723SShteryana Shopova 	}
640a7398723SShteryana Shopova 
641a7398723SShteryana Shopova 	STAILQ_INIT(&(entry->index_list));
642a7398723SShteryana Shopova 
643a7398723SShteryana Shopova 	for (i = 0, tok = gettoken(snmptoolctx); i < SNMP_INDEXES_MAX; i++) {
644a7398723SShteryana Shopova 		int32_t syntax;
645a7398723SShteryana Shopova 		struct enum_pairs *enums = NULL;
646a7398723SShteryana Shopova 
647a7398723SShteryana Shopova 		if (tok != TOK_TYPE && tok != TOK_DEFTYPE && tok != TOK_ENUM &&
648a7398723SShteryana Shopova 		    tok != TOK_BITS)
649a7398723SShteryana Shopova 			break;
650a7398723SShteryana Shopova 
651a7398723SShteryana Shopova 		if ((syntax = parse_type(snmptoolctx, &tok, &tc, &enums)) < 0) {
652a7398723SShteryana Shopova 			enum_pairs_free(enums);
653a7398723SShteryana Shopova 			snmp_index_listfree(&(entry->index_list));
654a7398723SShteryana Shopova 			free(entry);
655a7398723SShteryana Shopova 			return (-1);
656a7398723SShteryana Shopova 		}
657a7398723SShteryana Shopova 
658a7398723SShteryana Shopova 		if (snmp_syntax_insert(&(entry->index_list), enums, syntax,
659a7398723SShteryana Shopova 		    tc) < 0) {
660a7398723SShteryana Shopova 			snmp_index_listfree(&(entry->index_list));
661a7398723SShteryana Shopova 			enum_pairs_free(enums);
662a7398723SShteryana Shopova 			free(entry);
663a7398723SShteryana Shopova 			return (-1);
664a7398723SShteryana Shopova 		}
665a7398723SShteryana Shopova 	}
666a7398723SShteryana Shopova 
667a7398723SShteryana Shopova 	if (i == 0 || i > SNMP_INDEXES_MAX) {
668a7398723SShteryana Shopova 		warnx("Bad number of indexes at line %d", input->lno);
669a7398723SShteryana Shopova 		snmp_index_listfree(&(entry->index_list));
670a7398723SShteryana Shopova 		free(entry);
671a7398723SShteryana Shopova 		return (-1);
672a7398723SShteryana Shopova 	}
673a7398723SShteryana Shopova 
674a7398723SShteryana Shopova 	if (tok != TOK_STR) {
675a7398723SShteryana Shopova 		warnx("String expected after indexes at line %d", input->lno);
676a7398723SShteryana Shopova 		snmp_index_listfree(&(entry->index_list));
677a7398723SShteryana Shopova 		free(entry);
678a7398723SShteryana Shopova 		return (-1);
679a7398723SShteryana Shopova 	}
680a7398723SShteryana Shopova 
681a7398723SShteryana Shopova 	entry->string = obj->string;
682a7398723SShteryana Shopova 	entry->strlen = obj->strlen;
683a7398723SShteryana Shopova 	asn_append_oid(&(entry->var), &(obj->var));
684a7398723SShteryana Shopova 
685a7398723SShteryana Shopova 	if ((i = snmp_table_insert(snmptoolctx, entry)) < 0) {
686a7398723SShteryana Shopova 		snmp_index_listfree(&(entry->index_list));
687a7398723SShteryana Shopova 		free(entry);
688a7398723SShteryana Shopova 		return (-1);
689a7398723SShteryana Shopova 	} else if (i == 0) {
690a7398723SShteryana Shopova 		/* Same entry already present in lists. */
691a7398723SShteryana Shopova 		free(entry->string);
692a7398723SShteryana Shopova 		free(entry);
69381b38680SEnji Cooper 		return (0);
694a7398723SShteryana Shopova 	}
695a7398723SShteryana Shopova 
696a7398723SShteryana Shopova 	(void) snmp_import_update_table(ENTRY_INDEX, entry);
697a7398723SShteryana Shopova 
698a7398723SShteryana Shopova 	return (1);
699a7398723SShteryana Shopova }
700a7398723SShteryana Shopova 
701a7398723SShteryana Shopova /*
702a7398723SShteryana Shopova  * Read everything after the syntax type that is certainly a leaf OID info.
703a7398723SShteryana Shopova  */
704a7398723SShteryana Shopova static int32_t
snmp_import_leaf(struct snmp_toolinfo * snmptoolctx,int32_t * tok,struct snmp_oid2str * oid2str)7054a2b63d5SEnji Cooper snmp_import_leaf(struct snmp_toolinfo *snmptoolctx, int32_t *tok,
706a7398723SShteryana Shopova     struct snmp_oid2str *oid2str)
707a7398723SShteryana Shopova {
708a7398723SShteryana Shopova 	int32_t i, syntax;
709a7398723SShteryana Shopova 
710a7398723SShteryana Shopova 	if ((syntax = parse_type(snmptoolctx, tok, &(oid2str->tc), &(oid2str->snmp_enum)))
711a7398723SShteryana Shopova 	    < 0)
712a7398723SShteryana Shopova 		return(-1);
713a7398723SShteryana Shopova 
714a7398723SShteryana Shopova 	oid2str->syntax = syntax;
715a7398723SShteryana Shopova 	/*
716a7398723SShteryana Shopova 	 * That is the name of the function, corresponding to the entry.
717a7398723SShteryana Shopova 	 * It is used by bsnmpd, but is not interesting for us.
718a7398723SShteryana Shopova 	 */
719a7398723SShteryana Shopova 	if (*tok == TOK_STR)
720a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
721a7398723SShteryana Shopova 
722a7398723SShteryana Shopova 	for (i = 0; i < SNMP_ACCESS_GETSET && *tok == TOK_ACCESS; i++) {
723a7398723SShteryana Shopova 		oid2str->access |=  (uint32_t) val;
724a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
725a7398723SShteryana Shopova 	}
726a7398723SShteryana Shopova 
727a7398723SShteryana Shopova 	if (*tok != ')') {
728a7398723SShteryana Shopova 		warnx("')' expected at end of line %d", input->lno);
729a7398723SShteryana Shopova 		return (-1);
730a7398723SShteryana Shopova 	}
731a7398723SShteryana Shopova 
732a7398723SShteryana Shopova 	oid2str->table_idx = snmp_import_update_table(ENTRY_DATA,  NULL);
733a7398723SShteryana Shopova 
734a7398723SShteryana Shopova 	if ((i = snmp_leaf_insert(snmptoolctx, oid2str)) < 0) {
735a7398723SShteryana Shopova 		warnx("Error adding leaf %s to list", oid2str->string);
736a7398723SShteryana Shopova 		return (-1);
737a7398723SShteryana Shopova 	}
738a7398723SShteryana Shopova 
739a7398723SShteryana Shopova 	/*
740a7398723SShteryana Shopova 	 * Same entry is already present in the mapping lists and
741a7398723SShteryana Shopova 	 * the new one was not inserted.
742a7398723SShteryana Shopova 	 */
743a7398723SShteryana Shopova 	if (i == 0)  {
744a7398723SShteryana Shopova 		free(oid2str->string);
745a7398723SShteryana Shopova 		free(oid2str);
746a7398723SShteryana Shopova 	}
747a7398723SShteryana Shopova 
748a7398723SShteryana Shopova 	(void) snmp_import_update_table(ENTRY_NONE, NULL);
749a7398723SShteryana Shopova 
750a7398723SShteryana Shopova 	return (1);
751a7398723SShteryana Shopova }
752a7398723SShteryana Shopova 
753a7398723SShteryana Shopova static int32_t
snmp_import_object(struct snmp_toolinfo * snmptoolctx)754a7398723SShteryana Shopova snmp_import_object(struct snmp_toolinfo *snmptoolctx)
755a7398723SShteryana Shopova {
756a7398723SShteryana Shopova 	char *string;
757a7398723SShteryana Shopova 	int i;
7584a2b63d5SEnji Cooper 	int32_t tok;
759a7398723SShteryana Shopova 	struct snmp_oid2str *oid2str;
760a7398723SShteryana Shopova 
761a7398723SShteryana Shopova 	if (snmp_import_head(snmptoolctx) < 0)
762a7398723SShteryana Shopova 		return (-1);
763a7398723SShteryana Shopova 
76466987347SEnji Cooper 	if ((oid2str = calloc(1, sizeof(struct snmp_oid2str))) == NULL) {
76527c7c238SEnji Cooper 		syslog(LOG_ERR, "calloc() failed: %s", strerror(errno));
766a7398723SShteryana Shopova 		return (-1);
767a7398723SShteryana Shopova 	}
768a7398723SShteryana Shopova 
76927c7c238SEnji Cooper 	if ((string = strdup(nexttok)) == NULL) {
77027c7c238SEnji Cooper 		syslog(LOG_ERR, "strdup() failed: %s", strerror(errno));
771a7398723SShteryana Shopova 		free(oid2str);
772a7398723SShteryana Shopova 		return (-1);
773a7398723SShteryana Shopova 	}
774a7398723SShteryana Shopova 
775a7398723SShteryana Shopova 	oid2str->string = string;
776a7398723SShteryana Shopova 	oid2str->strlen = strlen(nexttok);
777a7398723SShteryana Shopova 
778a7398723SShteryana Shopova 	asn_append_oid(&(oid2str->var), &(current_oid));
779a7398723SShteryana Shopova 	if (snmp_suboid_append(&(oid2str->var), (asn_subid_t) val) < 0)
780a7398723SShteryana Shopova 		goto error;
781a7398723SShteryana Shopova 
782a7398723SShteryana Shopova 	/*
783a7398723SShteryana Shopova 	 * Prepared the entry - now figure out where to insert it.
784a7398723SShteryana Shopova 	 * After the object we have following options:
785a7398723SShteryana Shopova 	 * 1) new line, blank, ) - then it is an enum oid -> snmp_enumlist;
786a7398723SShteryana Shopova 	 * 2) new line , ( - nonleaf oid -> snmp_nodelist;
787a7398723SShteryana Shopova 	 * 2) ':' - table entry - a variable length SYNTAX_TYPE (one or more)
788a7398723SShteryana Shopova 	 *     may follow and second string must end line -> snmp_tablelist;
789a7398723SShteryana Shopova 	 * 3) OID , string  ) - this is a trap entry or a leaf -> snmp_oidlist;
790a7398723SShteryana Shopova 	 * 4) SYNTAX_TYPE, string (not always), get/set modifier - always last
791a7398723SShteryana Shopova 	 *     and )- this is definitely a leaf.
792a7398723SShteryana Shopova 	 */
793a7398723SShteryana Shopova 
794a7398723SShteryana Shopova 	switch (tok = gettoken(snmptoolctx)) {
795a7398723SShteryana Shopova 	    case  ')':
796a7398723SShteryana Shopova 		if ((i = snmp_enum_insert(snmptoolctx, oid2str)) < 0)
797a7398723SShteryana Shopova 			goto error;
798a7398723SShteryana Shopova 		if (i == 0) {
799a7398723SShteryana Shopova 			free(oid2str->string);
800a7398723SShteryana Shopova 			free(oid2str);
801a7398723SShteryana Shopova 		}
802a7398723SShteryana Shopova 		return (1);
803a7398723SShteryana Shopova 
804a7398723SShteryana Shopova 	    case '(':
805a7398723SShteryana Shopova 		if (snmp_suboid_append(&current_oid, (asn_subid_t) val) < 0)
806a7398723SShteryana Shopova 			goto error;
807a7398723SShteryana Shopova 
808a7398723SShteryana Shopova 		/*
809a7398723SShteryana Shopova 		 * Ignore the error for nodes since the .def files currently
810a7398723SShteryana Shopova 		 * contain different strings for 1.3.6.1.2.1 - mibII. Only make
811a7398723SShteryana Shopova 		 * sure the memory is freed and don't complain.
812a7398723SShteryana Shopova 		 */
813a7398723SShteryana Shopova 		if ((i = snmp_node_insert(snmptoolctx, oid2str)) <= 0) {
814a7398723SShteryana Shopova 			free(string);
815a7398723SShteryana Shopova 			free(oid2str);
816a7398723SShteryana Shopova 		}
817a7398723SShteryana Shopova 		return (snmp_import_object(snmptoolctx));
818a7398723SShteryana Shopova 
819a7398723SShteryana Shopova 	    case ':':
820a7398723SShteryana Shopova 		if (snmp_suboid_append(&current_oid, (asn_subid_t) val) < 0)
821a7398723SShteryana Shopova 			goto error;
822a7398723SShteryana Shopova 		if (snmp_import_table(snmptoolctx, oid2str) < 0)
823a7398723SShteryana Shopova 			goto error;
824a7398723SShteryana Shopova 		/*
825a7398723SShteryana Shopova 		 * A different table entry type was malloced and the data is
826a7398723SShteryana Shopova 		 * contained there.
827a7398723SShteryana Shopova 		 */
828a7398723SShteryana Shopova 		free(oid2str);
829a7398723SShteryana Shopova 		return (1);
830a7398723SShteryana Shopova 
831a7398723SShteryana Shopova 	    case TOK_TYPE:
832a7398723SShteryana Shopova 		/* FALLTHROUGH */
833a7398723SShteryana Shopova 	    case TOK_DEFTYPE:
834a7398723SShteryana Shopova 		/* FALLTHROUGH */
835a7398723SShteryana Shopova 	    case TOK_ENUM:
836a7398723SShteryana Shopova 	    	/* FALLTHROUGH */
837a7398723SShteryana Shopova 	    case TOK_BITS:
838a7398723SShteryana Shopova 		if (snmp_import_leaf(snmptoolctx, &tok, oid2str) < 0)
839a7398723SShteryana Shopova 				goto error;
840a7398723SShteryana Shopova 		return (1);
841a7398723SShteryana Shopova 
842a7398723SShteryana Shopova 	    default:
843a7398723SShteryana Shopova 		warnx("Unexpected token at line %d - %s", input->lno,
844a7398723SShteryana Shopova 		    input->fname);
845a7398723SShteryana Shopova 		break;
846a7398723SShteryana Shopova 	}
847a7398723SShteryana Shopova 
848a7398723SShteryana Shopova error:
849a7398723SShteryana Shopova 	snmp_mapping_entryfree(oid2str);
850a7398723SShteryana Shopova 
851a7398723SShteryana Shopova 	return (-1);
852a7398723SShteryana Shopova }
853a7398723SShteryana Shopova 
854a7398723SShteryana Shopova static int32_t
snmp_import_tree(struct snmp_toolinfo * snmptoolctx,int32_t * tok)8554a2b63d5SEnji Cooper snmp_import_tree(struct snmp_toolinfo *snmptoolctx, int32_t *tok)
856a7398723SShteryana Shopova {
857a7398723SShteryana Shopova 	while (*tok != TOK_EOF) {
858a7398723SShteryana Shopova 		switch (*tok) {
859a7398723SShteryana Shopova 		    case TOK_ERR:
860a7398723SShteryana Shopova 			return (-1);
861a7398723SShteryana Shopova 		    case '(':
862a7398723SShteryana Shopova 			if (snmp_import_object(snmptoolctx) < 0)
863a7398723SShteryana Shopova 			    return (-1);
864a7398723SShteryana Shopova 			break;
865a7398723SShteryana Shopova 		    case ')':
866a7398723SShteryana Shopova 			if (snmp_suboid_pop(&current_oid) < 0)
867a7398723SShteryana Shopova 			    return (-1);
868a7398723SShteryana Shopova 			(void) snmp_import_update_table(ENTRY_NONE, NULL);
869a7398723SShteryana Shopova 			break;
870a7398723SShteryana Shopova 		    default:
871a7398723SShteryana Shopova 			/* Anything else here would be illegal. */
872a7398723SShteryana Shopova 			return (-1);
873a7398723SShteryana Shopova 		}
874a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
875a7398723SShteryana Shopova 	}
876a7398723SShteryana Shopova 
877a7398723SShteryana Shopova 	return (0);
878a7398723SShteryana Shopova }
879a7398723SShteryana Shopova 
880a7398723SShteryana Shopova static int32_t
snmp_import_top(struct snmp_toolinfo * snmptoolctx,int32_t * tok)8814a2b63d5SEnji Cooper snmp_import_top(struct snmp_toolinfo *snmptoolctx, int32_t *tok)
882a7398723SShteryana Shopova {
883a7398723SShteryana Shopova 	enum snmp_tc tc;
884a7398723SShteryana Shopova 	struct enum_type *t;
885a7398723SShteryana Shopova 
886a7398723SShteryana Shopova 	if (*tok == '(')
887a7398723SShteryana Shopova 		return (snmp_import_tree(snmptoolctx, tok));
888a7398723SShteryana Shopova 
889a7398723SShteryana Shopova 	if (*tok == TOK_TYPEDEF) {
890a7398723SShteryana Shopova 		if ((*tok = gettoken(snmptoolctx)) != TOK_STR) {
891a7398723SShteryana Shopova 			warnx("type name expected after typedef - %s",
892a7398723SShteryana Shopova 			    input->fname);
893a7398723SShteryana Shopova 			return (-1);
894a7398723SShteryana Shopova 		}
895a7398723SShteryana Shopova 
896a7398723SShteryana Shopova 		t = snmp_enumtc_init(nexttok);
897a7398723SShteryana Shopova 
898a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
899a7398723SShteryana Shopova 		t->is_enum = (*tok == TOK_ENUM);
900a7398723SShteryana Shopova 		t->is_bits = (*tok == TOK_BITS);
901a7398723SShteryana Shopova 		t->syntax = parse_type(snmptoolctx, tok, &tc, &(t->snmp_enum));
902a7398723SShteryana Shopova 		snmp_enumtc_insert(snmptoolctx, t);
903a7398723SShteryana Shopova 
904a7398723SShteryana Shopova 		return (1);
905a7398723SShteryana Shopova 	}
906a7398723SShteryana Shopova 
907a7398723SShteryana Shopova 	if (*tok == TOK_INCLUDE) {
908a7398723SShteryana Shopova 		int i;
909a7398723SShteryana Shopova 
910a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
911a7398723SShteryana Shopova 		if (*tok != TOK_FILENAME) {
912a7398723SShteryana Shopova 			warnx("filename expected in include directive - %s",
913a7398723SShteryana Shopova 			    nexttok);
914a7398723SShteryana Shopova 			return (-1);
915a7398723SShteryana Shopova 		}
916a7398723SShteryana Shopova 
917a7398723SShteryana Shopova 		if (( i = add_filename(snmptoolctx, nexttok, NULL, 1)) == 0) {
918a7398723SShteryana Shopova 			*tok = gettoken(snmptoolctx);
919a7398723SShteryana Shopova 			return (1);
920a7398723SShteryana Shopova 		}
921a7398723SShteryana Shopova 
922a7398723SShteryana Shopova 		if (i == -1)
923a7398723SShteryana Shopova 			return (-1);
924a7398723SShteryana Shopova 
925a7398723SShteryana Shopova 		input_fopen(nexttok);
926a7398723SShteryana Shopova 		*tok = gettoken(snmptoolctx);
927a7398723SShteryana Shopova 		return (1);
928a7398723SShteryana Shopova 	}
929a7398723SShteryana Shopova 
930a7398723SShteryana Shopova 	warnx("'(' or 'typedef' expected - %s", nexttok);
931a7398723SShteryana Shopova 	return (-1);
932a7398723SShteryana Shopova }
933a7398723SShteryana Shopova 
934a7398723SShteryana Shopova static int32_t
snmp_import(struct snmp_toolinfo * snmptoolctx)935a7398723SShteryana Shopova snmp_import(struct snmp_toolinfo *snmptoolctx)
936a7398723SShteryana Shopova {
937a7398723SShteryana Shopova 	int i;
9384a2b63d5SEnji Cooper 	int32_t tok;
939a7398723SShteryana Shopova 
940a7398723SShteryana Shopova 	tok = gettoken(snmptoolctx);
941a7398723SShteryana Shopova 
942a7398723SShteryana Shopova 	do
943a7398723SShteryana Shopova 		i = snmp_import_top(snmptoolctx, &tok);
944a7398723SShteryana Shopova 	while (i > 0);
945a7398723SShteryana Shopova 
946a7398723SShteryana Shopova 	return (i);
947a7398723SShteryana Shopova }
948a7398723SShteryana Shopova 
949a7398723SShteryana Shopova /*
950a7398723SShteryana Shopova  * Read a .def file and import oid<->string mapping.
951a7398723SShteryana Shopova  * Mappings are inserted into a global structure containing list for each OID
952a7398723SShteryana Shopova  * syntax type.
953a7398723SShteryana Shopova  */
954a7398723SShteryana Shopova int32_t
snmp_import_file(struct snmp_toolinfo * snmptoolctx,struct fname * file)955a7398723SShteryana Shopova snmp_import_file(struct snmp_toolinfo *snmptoolctx, struct fname *file)
956a7398723SShteryana Shopova {
957a7398723SShteryana Shopova 	int idx;
958a7398723SShteryana Shopova 
959a7398723SShteryana Shopova 	snmp_import_init(&(file->cut));
960a7398723SShteryana Shopova 	input_fopen(file->name);
961a7398723SShteryana Shopova 	if ((idx = snmp_import(snmptoolctx)) < 0)
962a7398723SShteryana Shopova 		warnx("Failed to read mappings from file %s", file->name);
963a7398723SShteryana Shopova 
964a7398723SShteryana Shopova 	input_close();
965a7398723SShteryana Shopova 
966a7398723SShteryana Shopova 	return (idx);
967a7398723SShteryana Shopova }
968