Path: blob/main/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmpimport.c
106929 views
/*-1* Copyright (c) 2006 The FreeBSD Project2* All rights reserved.3*4* Author: Shteryana Shopova <[email protected]>5*6* Redistribution of this software and documentation and use in source and7* binary forms, with or without modification, are permitted provided that8* the following conditions are met:9*10* 1. Redistributions of source code or documentation must retain the above11* copyright notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* Read file containing table description - reuse magic from gensnmptree.c.31* Hopefully one day most of the code here will be part of libbsnmp and32* this duplication won't be necessary.33*34* Syntax is:35* ---------36* file := top | top file37*38* top := tree | typedef | include39*40* tree := head elements ')'41*42* entry := head ':' index STRING elements ')'43*44* leaf := head type STRING ACCESS ')'45*46* column := head type ACCESS ')'47*48* type := BASETYPE | BASETYPE '|' subtype | enum | bits49*50* subtype := STRING51*52* enum := ENUM '(' value ')'53*54* bits := BITS '(' value ')'55*56* value := INT STRING | INT STRING value57*58* head := '(' INT STRING59*60* elements := EMPTY | elements element61*62* element := tree | leaf | column63*64* index := type | index type65*66* typedef := 'typedef' STRING type67*68* include := 'include' filespec69*70* filespec := '"' STRING '"' | '<' STRING '>'71*/7273#include <sys/param.h>74#include <sys/queue.h>75#include <sys/uio.h>7677#include <ctype.h>78#include <err.h>79#include <errno.h>80#include <fcntl.h>81#include <paths.h>82#include <stdio.h>83#include <stdlib.h>84#include <string.h>85#include <syslog.h>86#include <unistd.h>8788#include <bsnmp/asn1.h>89#include <bsnmp/snmp.h>90#include <bsnmp/snmpagent.h> /* SNMP_INDEXES_MAX */91#include "bsnmptc.h"92#include "bsnmptools.h"9394enum snmp_tbl_entry {95ENTRY_NONE = 0,96ENTRY_INDEX,97ENTRY_DATA98};99100enum {101FL_GET = 0x01,102FL_SET = 0x02,103};104105/************************************************************106*107* Allocate memory and panic just in the case...108*/109static void *110xalloc(size_t size)111{112void *ptr;113114if ((ptr = malloc(size)) == NULL)115err(1, "allocing %zu bytes", size);116117return (ptr);118}119120static char *121savestr(const char *s)122{123if (s == NULL)124return (NULL);125126return (strcpy(xalloc(strlen(s) + 1), s));127}128129/************************************************************130*131* Input stack132*/133struct input {134FILE *fp;135uint32_t lno;136char *fname;137char *path;138LIST_ENTRY(input) link;139};140141static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs);142static struct input *input = NULL;143static int32_t pbchar = -1;144145#define MAX_PATHS 100146147static const char *paths[MAX_PATHS + 1] = {148"/usr/share/snmp/defs",149_PATH_LOCALBASE "/share/snmp/defs",150NULL151};152153static void154input_new(FILE *fp, const char *path, const char *fname)155{156struct input *ip;157158ip = xalloc(sizeof(*ip));159ip->fp = fp;160ip->lno = 1;161ip->fname = savestr(fname);162ip->path = savestr(path);163LIST_INSERT_HEAD(&inputs, ip, link);164165input = ip;166}167168static void169input_close(void)170{171if (input == NULL)172return;173174fclose(input->fp);175free(input->fname);176free(input->path);177LIST_REMOVE(input, link);178free(input);179180input = LIST_FIRST(&inputs);181}182183static FILE *184tryopen(const char *path, const char *fname)185{186char *fn;187FILE *fp;188189if (path == NULL)190fn = savestr(fname);191else {192fn = xalloc(strlen(path) + strlen(fname) + 2);193sprintf(fn, "%s/%s", path, fname);194}195fp = fopen(fn, "r");196free(fn);197return (fp);198}199200static int32_t201input_fopen(const char *fname)202{203FILE *fp;204u_int p;205206if (fname[0] == '/' || fname[0] == '.' || fname[0] == '~') {207if ((fp = tryopen(NULL, fname)) != NULL) {208input_new(fp, NULL, fname);209return (0);210}211212} else {213214for (p = 0; paths[p] != NULL; p++)215if ((fp = tryopen(paths[p], fname)) != NULL) {216input_new(fp, paths[p], fname);217return (0);218}219}220221warnx("cannot open '%s'", fname);222return (-1);223}224225static int32_t226tgetc(void)227{228int c;229230if (pbchar != -1) {231c = pbchar;232pbchar = -1;233return (c);234}235236for (;;) {237if (input == NULL)238return (EOF);239240if ((c = getc(input->fp)) != EOF)241return (c);242243input_close();244}245}246247static int32_t248tungetc(int c)249{250251if (pbchar != -1)252return (-1);253254pbchar = c;255return (1);256}257258/************************************************************259*260* Parsing input261*/262enum tok {263TOK_EOF = 0200, /* end-of-file seen */264TOK_NUM, /* number */265TOK_STR, /* string */266TOK_ACCESS, /* access operator */267TOK_TYPE, /* type operator */268TOK_ENUM, /* enum token (kind of a type) */269TOK_TYPEDEF, /* typedef directive */270TOK_DEFTYPE, /* defined type */271TOK_INCLUDE, /* include directive */272TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */273TOK_BITS, /* bits token (kind of a type) */274TOK_ERR /* unexpected char - exit */275};276277static const struct {278const char *str;279enum tok tok;280uint32_t val;281} keywords[] = {282{ "GET", TOK_ACCESS, FL_GET },283{ "SET", TOK_ACCESS, FL_SET },284{ "NULL", TOK_TYPE, SNMP_SYNTAX_NULL },285{ "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER },286{ "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER },287{ "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE },288{ "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING },289{ "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS },290{ "OID", TOK_TYPE, SNMP_SYNTAX_OID },291{ "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS },292{ "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER },293{ "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE },294{ "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 },295{ "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER },296{ "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING },297{ "typedef", TOK_TYPEDEF, 0 },298{ "include", TOK_INCLUDE, 0 },299{ NULL, 0, 0 }300};301302static struct {303/* Current OID type, regarding table membership. */304enum snmp_tbl_entry tbl_type;305/* A pointer to a structure in table list to add to its members. */306struct snmp_index_entry *table_idx;307} table_data;308309static struct asn_oid current_oid;310static char nexttok[MAXSTR];311static u_long val; /* integer values */312static int32_t all_cond; /* all conditions are true */313static int32_t saved_token = -1;314315/* Prepare the global data before parsing a new file. */316static void317snmp_import_init(struct asn_oid *append)318{319memset(&table_data, 0, sizeof(table_data));320memset(¤t_oid, 0, sizeof(struct asn_oid));321memset(nexttok, 0, MAXSTR);322323if (append != NULL)324asn_append_oid(¤t_oid, append);325326all_cond = 0;327val = 0;328saved_token = -1;329}330331static int32_t332gettoken(struct snmp_toolinfo *snmptoolctx)333{334int c;335struct enum_type *t;336337if (saved_token != -1) {338c = saved_token;339saved_token = -1;340return (c);341}342343again:344/*345* Skip any whitespace before the next token.346*/347while ((c = tgetc()) != EOF) {348if (c == '\n')349input->lno++;350if (!isspace(c))351break;352}353if (c == EOF)354return (TOK_EOF);355356if (!isascii(c)) {357warnx("unexpected character %#2x", (u_int) c);358return (TOK_ERR);359}360361/*362* Skip comments.363*/364if (c == '#') {365while ((c = tgetc()) != EOF) {366if (c == '\n') {367input->lno++;368goto again;369}370}371warnx("unexpected EOF in comment");372return (TOK_ERR);373}374375/*376* Single character tokens.377*/378if (strchr("():|", c) != NULL)379return (c);380381if (c == '"' || c == '<') {382int32_t end = c;383size_t n = 0;384385val = 1;386if (c == '<') {387val = 0;388end = '>';389}390391while ((c = tgetc()) != EOF) {392if (c == end)393break;394if (n == sizeof(nexttok) - 1) {395nexttok[n++] = '\0';396warnx("filename too long '%s...'", nexttok);397return (TOK_ERR);398}399nexttok[n++] = c;400}401nexttok[n++] = '\0';402return (TOK_FILENAME);403}404405/*406* Sort out numbers.407*/408if (isdigit(c)) {409size_t n = 0;410nexttok[n++] = c;411while ((c = tgetc()) != EOF) {412if (!isdigit(c)) {413if (tungetc(c) < 0)414return (TOK_ERR);415break;416}417if (n == sizeof(nexttok) - 1) {418nexttok[n++] = '\0';419warnx("number too long '%s...'", nexttok);420return (TOK_ERR);421}422nexttok[n++] = c;423}424nexttok[n++] = '\0';425sscanf(nexttok, "%lu", &val);426return (TOK_NUM);427}428429/*430* So that has to be a string.431*/432if (isalpha(c) || c == '_' || c == '-') {433size_t n = 0;434nexttok[n++] = c;435while ((c = tgetc()) != EOF) {436if (!isalnum(c) && c != '_' && c != '-') {437if (tungetc (c) < 0)438return (TOK_ERR);439break;440}441if (n == sizeof(nexttok) - 1) {442nexttok[n++] = '\0';443warnx("string too long '%s...'", nexttok);444return (TOK_ERR);445}446nexttok[n++] = c;447}448nexttok[n++] = '\0';449450/*451* Keywords.452*/453for (c = 0; keywords[c].str != NULL; c++)454if (strcmp(keywords[c].str, nexttok) == 0) {455val = keywords[c].val;456return (keywords[c].tok);457}458459if ((t = snmp_enumtc_lookup(snmptoolctx, nexttok)) != NULL) {460val = t->syntax;461return (TOK_DEFTYPE);462}463464return (TOK_STR);465}466467if (isprint(c))468warnx("%u: unexpected character '%c'", input->lno, c);469else470warnx("%u: unexpected character 0x%02x", input->lno, (u_int) c);471472return (TOK_ERR);473}474475/*476* Update table information.477*/478static struct snmp_index_entry *479snmp_import_update_table(enum snmp_tbl_entry te, struct snmp_index_entry *tbl)480{481switch (te) {482case ENTRY_NONE:483if (table_data.tbl_type == ENTRY_NONE)484return (NULL);485if (table_data.tbl_type == ENTRY_INDEX)486table_data.table_idx = NULL;487table_data.tbl_type--;488return (NULL);489490case ENTRY_INDEX:491if (tbl == NULL)492warnx("No table_index to add!!!");493table_data.table_idx = tbl;494table_data.tbl_type = ENTRY_INDEX;495return (tbl);496497case ENTRY_DATA:498if (table_data.tbl_type == ENTRY_INDEX) {499table_data.tbl_type = ENTRY_DATA;500return (table_data.table_idx);501}502return (NULL);503504default:505/* NOTREACHED */506warnx("Unknown table entry type!!!");507break;508}509510return (NULL);511}512513static int32_t514parse_enum(struct snmp_toolinfo *snmptoolctx, int32_t *tok,515struct enum_pairs *enums)516{517while ((*tok = gettoken(snmptoolctx)) == TOK_STR) {518if (enum_pair_insert(enums, val, nexttok) < 0)519return (-1);520if ((*tok = gettoken(snmptoolctx)) != TOK_NUM)521break;522}523524if (*tok != ')') {525warnx("')' at end of enums");526return (-1);527}528529return (1);530}531532static int32_t533parse_subtype(struct snmp_toolinfo *snmptoolctx, int32_t *tok,534enum snmp_tc *tc)535{536if ((*tok = gettoken(snmptoolctx)) != TOK_STR) {537warnx("subtype expected after '|'");538return (-1);539}540541*tc = snmp_get_tc(nexttok);542*tok = gettoken(snmptoolctx);543544return (1);545}546547static int32_t548parse_type(struct snmp_toolinfo *snmptoolctx, int32_t *tok,549enum snmp_tc *tc, struct enum_pairs **snmp_enum)550{551int32_t syntax, mem;552553syntax = val;554*tc = 0;555556if (*tok == TOK_ENUM || *tok == TOK_BITS) {557if (*snmp_enum == NULL) {558if ((*snmp_enum = enum_pairs_init()) == NULL)559return (-1);560mem = 1;561*tc = SNMP_TC_OWN;562} else563mem = 0;564565if (gettoken(snmptoolctx) != '(') {566warnx("'(' expected after ENUM/BITS");567return (-1);568}569570if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) {571warnx("need value for ENUM//BITS");572if (mem == 1) {573free(*snmp_enum);574*snmp_enum = NULL;575}576return (-1);577}578579if (parse_enum(snmptoolctx, tok, *snmp_enum) < 0) {580enum_pairs_free(*snmp_enum);581*snmp_enum = NULL;582return (-1);583}584585*tok = gettoken(snmptoolctx);586587} else if (*tok == TOK_DEFTYPE) {588struct enum_type *t;589590*tc = 0;591t = snmp_enumtc_lookup(snmptoolctx, nexttok);592if (t != NULL)593*snmp_enum = t->snmp_enum;594595*tok = gettoken(snmptoolctx);596597} else {598if ((*tok = gettoken(snmptoolctx)) == '|') {599if (parse_subtype(snmptoolctx, tok, tc) < 0)600return (-1);601}602}603604return (syntax);605}606607static int32_t608snmp_import_head(struct snmp_toolinfo *snmptoolctx)609{610enum tok tok;611612if ((tok = gettoken(snmptoolctx)) == '(')613tok = gettoken(snmptoolctx);614615if (tok != TOK_NUM || val > ASN_MAXID ) {616warnx("Suboid expected - line %d", input->lno);617return (-1);618}619620if (gettoken(snmptoolctx) != TOK_STR) {621warnx("Node name expected at line %d", input->lno);622return (-1);623}624625return (1);626}627628static int32_t629snmp_import_table(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *obj)630{631int32_t i, tok;632enum snmp_tc tc;633struct snmp_index_entry *entry;634635if ((entry = calloc(1, sizeof(struct snmp_index_entry))) == NULL) {636syslog(LOG_ERR, "malloc() failed: %s", strerror(errno));637return (-1);638}639640STAILQ_INIT(&(entry->index_list));641642for (i = 0, tok = gettoken(snmptoolctx); i < SNMP_INDEXES_MAX; i++) {643int32_t syntax;644struct enum_pairs *enums = NULL;645646if (tok != TOK_TYPE && tok != TOK_DEFTYPE && tok != TOK_ENUM &&647tok != TOK_BITS)648break;649650if ((syntax = parse_type(snmptoolctx, &tok, &tc, &enums)) < 0) {651enum_pairs_free(enums);652snmp_index_listfree(&(entry->index_list));653free(entry);654return (-1);655}656657if (snmp_syntax_insert(&(entry->index_list), enums, syntax,658tc) < 0) {659snmp_index_listfree(&(entry->index_list));660enum_pairs_free(enums);661free(entry);662return (-1);663}664}665666if (i == 0 || i > SNMP_INDEXES_MAX) {667warnx("Bad number of indexes at line %d", input->lno);668snmp_index_listfree(&(entry->index_list));669free(entry);670return (-1);671}672673if (tok != TOK_STR) {674warnx("String expected after indexes at line %d", input->lno);675snmp_index_listfree(&(entry->index_list));676free(entry);677return (-1);678}679680entry->string = obj->string;681entry->strlen = obj->strlen;682asn_append_oid(&(entry->var), &(obj->var));683684if ((i = snmp_table_insert(snmptoolctx, entry)) < 0) {685snmp_index_listfree(&(entry->index_list));686free(entry);687return (-1);688} else if (i == 0) {689/* Same entry already present in lists. */690free(entry->string);691free(entry);692return (0);693}694695(void) snmp_import_update_table(ENTRY_INDEX, entry);696697return (1);698}699700/*701* Read everything after the syntax type that is certainly a leaf OID info.702*/703static int32_t704snmp_import_leaf(struct snmp_toolinfo *snmptoolctx, int32_t *tok,705struct snmp_oid2str *oid2str)706{707int32_t i, syntax;708709if ((syntax = parse_type(snmptoolctx, tok, &(oid2str->tc), &(oid2str->snmp_enum)))710< 0)711return(-1);712713oid2str->syntax = syntax;714/*715* That is the name of the function, corresponding to the entry.716* It is used by bsnmpd, but is not interesting for us.717*/718if (*tok == TOK_STR)719*tok = gettoken(snmptoolctx);720721for (i = 0; i < SNMP_ACCESS_GETSET && *tok == TOK_ACCESS; i++) {722oid2str->access |= (uint32_t) val;723*tok = gettoken(snmptoolctx);724}725726if (*tok != ')') {727warnx("')' expected at end of line %d", input->lno);728return (-1);729}730731oid2str->table_idx = snmp_import_update_table(ENTRY_DATA, NULL);732733if ((i = snmp_leaf_insert(snmptoolctx, oid2str)) < 0) {734warnx("Error adding leaf %s to list", oid2str->string);735return (-1);736}737738/*739* Same entry is already present in the mapping lists and740* the new one was not inserted.741*/742if (i == 0) {743free(oid2str->string);744free(oid2str);745}746747(void) snmp_import_update_table(ENTRY_NONE, NULL);748749return (1);750}751752static int32_t753snmp_import_object(struct snmp_toolinfo *snmptoolctx)754{755char *string;756int i;757int32_t tok;758struct snmp_oid2str *oid2str;759760if (snmp_import_head(snmptoolctx) < 0)761return (-1);762763if ((oid2str = calloc(1, sizeof(struct snmp_oid2str))) == NULL) {764syslog(LOG_ERR, "calloc() failed: %s", strerror(errno));765return (-1);766}767768if ((string = strdup(nexttok)) == NULL) {769syslog(LOG_ERR, "strdup() failed: %s", strerror(errno));770free(oid2str);771return (-1);772}773774oid2str->string = string;775oid2str->strlen = strlen(nexttok);776777asn_append_oid(&(oid2str->var), &(current_oid));778if (snmp_suboid_append(&(oid2str->var), (asn_subid_t) val) < 0)779goto error;780781/*782* Prepared the entry - now figure out where to insert it.783* After the object we have following options:784* 1) new line, blank, ) - then it is an enum oid -> snmp_enumlist;785* 2) new line , ( - nonleaf oid -> snmp_nodelist;786* 2) ':' - table entry - a variable length SYNTAX_TYPE (one or more)787* may follow and second string must end line -> snmp_tablelist;788* 3) OID , string ) - this is a trap entry or a leaf -> snmp_oidlist;789* 4) SYNTAX_TYPE, string (not always), get/set modifier - always last790* and )- this is definitely a leaf.791*/792793switch (tok = gettoken(snmptoolctx)) {794case ')':795if ((i = snmp_enum_insert(snmptoolctx, oid2str)) < 0)796goto error;797if (i == 0) {798free(oid2str->string);799free(oid2str);800}801return (1);802803case '(':804if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0)805goto error;806807/*808* Ignore the error for nodes since the .def files currently809* contain different strings for 1.3.6.1.2.1 - mibII. Only make810* sure the memory is freed and don't complain.811*/812if ((i = snmp_node_insert(snmptoolctx, oid2str)) <= 0) {813free(string);814free(oid2str);815}816return (snmp_import_object(snmptoolctx));817818case ':':819if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0)820goto error;821if (snmp_import_table(snmptoolctx, oid2str) < 0)822goto error;823/*824* A different table entry type was malloced and the data is825* contained there.826*/827free(oid2str);828return (1);829830case TOK_TYPE:831/* FALLTHROUGH */832case TOK_DEFTYPE:833/* FALLTHROUGH */834case TOK_ENUM:835/* FALLTHROUGH */836case TOK_BITS:837if (snmp_import_leaf(snmptoolctx, &tok, oid2str) < 0)838goto error;839return (1);840841default:842warnx("Unexpected token at line %d - %s", input->lno,843input->fname);844break;845}846847error:848snmp_mapping_entryfree(oid2str);849850return (-1);851}852853static int32_t854snmp_import_tree(struct snmp_toolinfo *snmptoolctx, int32_t *tok)855{856while (*tok != TOK_EOF) {857switch (*tok) {858case TOK_ERR:859return (-1);860case '(':861if (snmp_import_object(snmptoolctx) < 0)862return (-1);863break;864case ')':865if (snmp_suboid_pop(¤t_oid) < 0)866return (-1);867(void) snmp_import_update_table(ENTRY_NONE, NULL);868break;869default:870/* Anything else here would be illegal. */871return (-1);872}873*tok = gettoken(snmptoolctx);874}875876return (0);877}878879static int32_t880snmp_import_top(struct snmp_toolinfo *snmptoolctx, int32_t *tok)881{882enum snmp_tc tc;883struct enum_type *t;884885if (*tok == '(')886return (snmp_import_tree(snmptoolctx, tok));887888if (*tok == TOK_TYPEDEF) {889if ((*tok = gettoken(snmptoolctx)) != TOK_STR) {890warnx("type name expected after typedef - %s",891input->fname);892return (-1);893}894895t = snmp_enumtc_init(nexttok);896897*tok = gettoken(snmptoolctx);898t->is_enum = (*tok == TOK_ENUM);899t->is_bits = (*tok == TOK_BITS);900t->syntax = parse_type(snmptoolctx, tok, &tc, &(t->snmp_enum));901snmp_enumtc_insert(snmptoolctx, t);902903return (1);904}905906if (*tok == TOK_INCLUDE) {907int i;908909*tok = gettoken(snmptoolctx);910if (*tok != TOK_FILENAME) {911warnx("filename expected in include directive - %s",912nexttok);913return (-1);914}915916if (( i = add_filename(snmptoolctx, nexttok, NULL, 1)) == 0) {917*tok = gettoken(snmptoolctx);918return (1);919}920921if (i == -1)922return (-1);923924input_fopen(nexttok);925*tok = gettoken(snmptoolctx);926return (1);927}928929warnx("'(' or 'typedef' expected - %s", nexttok);930return (-1);931}932933static int32_t934snmp_import(struct snmp_toolinfo *snmptoolctx)935{936int i;937int32_t tok;938939tok = gettoken(snmptoolctx);940941do942i = snmp_import_top(snmptoolctx, &tok);943while (i > 0);944945return (i);946}947948/*949* Read a .def file and import oid<->string mapping.950* Mappings are inserted into a global structure containing list for each OID951* syntax type.952*/953int32_t954snmp_import_file(struct snmp_toolinfo *snmptoolctx, struct fname *file)955{956int idx;957958snmp_import_init(&(file->cut));959input_fopen(file->name);960if ((idx = snmp_import(snmptoolctx)) < 0)961warnx("Failed to read mappings from file %s", file->name);962963input_close();964965return (idx);966}967968969