Add IPv6 transport for bsnmp.
This patch adds a new table begemotSnmpdTransInetTable that uses the InetAddressType textual convention and can be used to create listening ports for IPv4, IPv6, zoned IPv6 and based on DNS names. It also supports future extension beyond UDP by adding a protocol identifier to the table index. In order to support this gensnmptree had to be modified. Submitted by: harti MFC after: 1 month Relnotes: yes Differential Revision: https://reviews.freebsd.org/D16654
This commit is contained in:
parent
a8cb655d2e
commit
04d1781439
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" $Begemot: gensnmptree.1 383 2006-05-30 07:40:49Z brandt_h $
|
||||
.\"
|
||||
.Dd June 29, 2018
|
||||
.Dd April 2, 2019
|
||||
.Dt GENSNMPTREE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -100,25 +100,11 @@ is the length of the OID.
|
||||
is the last component of the OID.
|
||||
.El
|
||||
.It Fl F
|
||||
Together with
|
||||
.Fl E
|
||||
causes
|
||||
.Nm
|
||||
instead of the generation of enum definitions the generation of
|
||||
functions for checking a value to be one of the enumeration variants and
|
||||
for conversion between strings and the enum. The file is sent to standard
|
||||
output and is meant to be included into a C-file for compilation.
|
||||
emit definitions for C-functions includeable in a C-file that do some basic
|
||||
stuff on enums like value checking and conversion between value and strings.
|
||||
.It Fl f
|
||||
This flag can be used together with
|
||||
.Fl E
|
||||
or when generating the tree files. It causes
|
||||
.Nm
|
||||
to emit static inline functions for checking a value to be one of the
|
||||
enumeration values and for conversion between strings and the enum.
|
||||
If used when generating the tree files, the preprocessor symbol
|
||||
.Ar SNMPTREE_TYPES
|
||||
must be defined when including the tree header file for these definitions
|
||||
to become visible.
|
||||
emit definitions for inline C-functions that do some basic
|
||||
stuff on enums like value checking and conversion between value and strings.
|
||||
.It Fl h
|
||||
Print a short help page.
|
||||
.It Fl I Ar directory
|
||||
@ -136,36 +122,6 @@ Instead of normal output print the resulting tree.
|
||||
Prefix the file names and the table name with
|
||||
.Ar prefix .
|
||||
.El
|
||||
.Pp
|
||||
The following functions are generated by
|
||||
.Fl f
|
||||
or
|
||||
.Fl F :
|
||||
.Pp
|
||||
.Ft static inline int
|
||||
.Fn isok_EnumName "enum EnumName" ;
|
||||
.Pp
|
||||
.Ft static inline const char *
|
||||
.Fn tostr_EnumName "enum EnumName" ;
|
||||
.Pp
|
||||
.Ft static inline int
|
||||
.Fn fromstr_EnumName "const char *" "enum EnumName *" ;
|
||||
.Pp
|
||||
The
|
||||
.Fa EnumName
|
||||
is replaced with the enumeration name.
|
||||
.Fn isok_EnumName
|
||||
returns 1 if the argument is one of the valid enum values and 0 otherwise.
|
||||
.Fn tostr_EnumName
|
||||
returns a string representation of the enumeration value.
|
||||
If the values is not one of the legal values
|
||||
.Ar EnumName???
|
||||
is returned.
|
||||
.Fn fromstr_EnumName
|
||||
returns 1 if the string represents one of the legal enumeration values and
|
||||
0 otherwise.
|
||||
If 1 is return the variable pointed to by the second argument is set to
|
||||
the enumeration value.
|
||||
.Sh MIBS
|
||||
The syntax of the MIB description file can formally be specified as follows:
|
||||
.Bd -unfilled -offset indent
|
||||
|
@ -110,7 +110,6 @@ static int debug;
|
||||
|
||||
static const char usgtxt[] = "\
|
||||
Generate SNMP tables.\n\
|
||||
$Id$\n\
|
||||
usage: gensnmptree [-dEeFfhlt] [-I directory] [-i infile] [-p prefix]\n\
|
||||
[name]...\n\
|
||||
options:\n\
|
||||
@ -127,6 +126,37 @@ options:\n\
|
||||
-t generate a .def file\n\
|
||||
";
|
||||
|
||||
/**
|
||||
* Program operation.
|
||||
*/
|
||||
enum op {
|
||||
/** generate the tree */
|
||||
OP_GEN,
|
||||
|
||||
/** extract OIDs */
|
||||
OP_EXTRACT,
|
||||
|
||||
/** print the parsed tree */
|
||||
OP_TREE,
|
||||
|
||||
/** extract enums */
|
||||
OP_ENUMS,
|
||||
};
|
||||
|
||||
/**
|
||||
* Which functions to create.
|
||||
*/
|
||||
enum gen_funcs {
|
||||
/** none */
|
||||
GEN_FUNCS_NONE,
|
||||
|
||||
/** functions for header files */
|
||||
GEN_FUNCS_H,
|
||||
|
||||
/** functions for C files */
|
||||
GEN_FUNCS_C,
|
||||
};
|
||||
|
||||
/*
|
||||
* A node in the OID tree
|
||||
*/
|
||||
@ -162,15 +192,18 @@ struct node {
|
||||
uint32_t index; /* index for table entry */
|
||||
char *func; /* function for tables */
|
||||
struct node_list subs;
|
||||
char *subtypes[SNMP_INDEXES_MAX];
|
||||
} entry;
|
||||
|
||||
struct leaf {
|
||||
enum snmp_syntax syntax; /* syntax for this leaf */
|
||||
char *func; /* function name */
|
||||
char *subtype; /* subtype */
|
||||
} leaf;
|
||||
|
||||
struct column {
|
||||
enum snmp_syntax syntax; /* syntax for this column */
|
||||
char *subtype; /* subtype */
|
||||
} column;
|
||||
} u;
|
||||
};
|
||||
@ -214,7 +247,7 @@ xalloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if ((ptr = malloc(size)) == NULL)
|
||||
if ((ptr = calloc(1, size)) == NULL)
|
||||
err(1, "allocing %zu bytes", size);
|
||||
|
||||
return (ptr);
|
||||
@ -710,12 +743,14 @@ make_type(const char *s)
|
||||
* token.
|
||||
*/
|
||||
static u_int
|
||||
parse_type(enum tok *tok, struct type *t, const char *vname)
|
||||
parse_type(enum tok *tok, struct type *t, const char *vname, char **subtype)
|
||||
{
|
||||
u_int syntax;
|
||||
struct enums *e;
|
||||
|
||||
syntax = val;
|
||||
if (subtype != NULL)
|
||||
*subtype = NULL;
|
||||
|
||||
if (*tok == TOK_ENUM || *tok == TOK_BITS) {
|
||||
if (t == NULL && vname != NULL) {
|
||||
@ -759,6 +794,8 @@ parse_type(enum tok *tok, struct type *t, const char *vname)
|
||||
if ((*tok = gettoken()) == '|') {
|
||||
if (gettoken() != TOK_STR)
|
||||
report("subtype expected after '|'");
|
||||
if (subtype != NULL)
|
||||
*subtype = savetok();
|
||||
*tok = gettoken();
|
||||
}
|
||||
}
|
||||
@ -794,18 +831,21 @@ parse(enum tok tok)
|
||||
if ((tok = gettoken()) == TOK_TYPE || tok == TOK_DEFTYPE ||
|
||||
tok == TOK_ENUM || tok == TOK_BITS) {
|
||||
/* LEAF or COLUM */
|
||||
u_int syntax = parse_type(&tok, NULL, node->name);
|
||||
char *subtype;
|
||||
u_int syntax = parse_type(&tok, NULL, node->name, &subtype);
|
||||
|
||||
if (tok == TOK_STR) {
|
||||
/* LEAF */
|
||||
node->type = NODE_LEAF;
|
||||
node->u.leaf.func = savetok();
|
||||
node->u.leaf.syntax = syntax;
|
||||
node->u.leaf.subtype = subtype;
|
||||
tok = gettoken();
|
||||
} else {
|
||||
/* COLUMN */
|
||||
node->type = NODE_COLUMN;
|
||||
node->u.column.syntax = syntax;
|
||||
node->u.column.subtype = subtype;
|
||||
}
|
||||
|
||||
while (tok != ')') {
|
||||
@ -825,9 +865,12 @@ parse(enum tok tok)
|
||||
tok = gettoken();
|
||||
while (tok == TOK_TYPE || tok == TOK_DEFTYPE ||
|
||||
tok == TOK_ENUM || tok == TOK_BITS) {
|
||||
u_int syntax = parse_type(&tok, NULL, node->name);
|
||||
if (index_count++ == SNMP_INDEXES_MAX)
|
||||
char *subtype;
|
||||
u_int syntax = parse_type(&tok, NULL, node->name,
|
||||
&subtype);
|
||||
if (index_count == SNMP_INDEXES_MAX)
|
||||
report("too many table indexes");
|
||||
node->u.entry.subtypes[index_count++] = subtype;
|
||||
node->u.entry.index |=
|
||||
syntax << (SNMP_INDEX_SHIFT * index_count);
|
||||
}
|
||||
@ -882,7 +925,8 @@ parse_top(enum tok tok)
|
||||
tok = gettoken();
|
||||
t->is_enum = (tok == TOK_ENUM);
|
||||
t->is_bits = (tok == TOK_BITS);
|
||||
t->syntax = parse_type(&tok, t, NULL);
|
||||
|
||||
t->syntax = parse_type(&tok, t, NULL, NULL);
|
||||
pushback(tok);
|
||||
|
||||
return (NULL);
|
||||
@ -903,7 +947,7 @@ parse_top(enum tok tok)
|
||||
* Generate the C-code table part for one node.
|
||||
*/
|
||||
static void
|
||||
gen_node(FILE *fp, struct node *np, struct asn_oid *oid, u_int idx,
|
||||
gen_node(FILE *fp, const struct node *np, struct asn_oid *oid, u_int idx,
|
||||
const char *func)
|
||||
{
|
||||
u_int n;
|
||||
@ -1008,7 +1052,7 @@ gen_node(FILE *fp, struct node *np, struct asn_oid *oid, u_int idx,
|
||||
* Generate the header file with the function declarations.
|
||||
*/
|
||||
static void
|
||||
gen_header(FILE *fp, struct node *np, u_int oidlen, const char *func)
|
||||
gen_header(FILE *fp, const struct node *np, u_int oidlen, const char *func)
|
||||
{
|
||||
char f[MAXSTR + 4];
|
||||
struct node *sub;
|
||||
@ -1058,7 +1102,7 @@ gen_header(FILE *fp, struct node *np, u_int oidlen, const char *func)
|
||||
* Generate the OID table.
|
||||
*/
|
||||
static void
|
||||
gen_table(FILE *fp, struct node *node)
|
||||
gen_table(FILE *fp, const struct node *node)
|
||||
{
|
||||
struct asn_oid oid;
|
||||
|
||||
@ -1067,7 +1111,6 @@ gen_table(FILE *fp, struct node *node)
|
||||
#ifdef HAVE_STDINT_H
|
||||
fprintf(fp, "#include <stdint.h>\n");
|
||||
#endif
|
||||
fprintf(fp, "#include <string.h>\n");
|
||||
if (localincs) {
|
||||
fprintf(fp, "#include \"asn1.h\"\n");
|
||||
fprintf(fp, "#include \"snmp.h\"\n");
|
||||
@ -1118,6 +1161,8 @@ gen_tree(const struct node *np, int level)
|
||||
|
||||
case NODE_LEAF:
|
||||
print_syntax(np->u.leaf.syntax);
|
||||
if (np->u.leaf.subtype != NULL)
|
||||
printf(" | %s", np->u.leaf.subtype);
|
||||
printf(" %s%s%s)\n", np->u.leaf.func,
|
||||
(np->flags & FL_GET) ? " GET" : "",
|
||||
(np->flags & FL_SET) ? " SET" : "");
|
||||
@ -1137,8 +1182,11 @@ gen_tree(const struct node *np, int level)
|
||||
case NODE_ENTRY:
|
||||
printf(" :");
|
||||
|
||||
for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++)
|
||||
for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++) {
|
||||
print_syntax(SNMP_INDEX(np->u.entry.index, i));
|
||||
if (np->u.entry.subtypes[i] != NULL)
|
||||
printf(" | %s", np->u.entry.subtypes[i]);
|
||||
}
|
||||
printf(" %s\n", np->u.entry.func);
|
||||
TAILQ_FOREACH(sp, &np->u.entry.subs, link)
|
||||
gen_tree(sp, level + 1);
|
||||
@ -1147,6 +1195,8 @@ gen_tree(const struct node *np, int level)
|
||||
|
||||
case NODE_COLUMN:
|
||||
print_syntax(np->u.column.syntax);
|
||||
if (np->u.column.subtype != NULL)
|
||||
printf(" | %s", np->u.column.subtype);
|
||||
printf("%s%s)\n", (np->flags & FL_GET) ? " GET" : "",
|
||||
(np->flags & FL_SET) ? " SET" : "");
|
||||
break;
|
||||
@ -1194,15 +1244,6 @@ extract(FILE *fp, const struct node *np, struct asn_oid *oid, const char *obj,
|
||||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the named OID.
|
||||
*
|
||||
* \param fp file to extract to
|
||||
* \param root root of the tree
|
||||
* \param object name of the object to extract
|
||||
*
|
||||
* \return 0 on success, -1 if the object was not found
|
||||
*/
|
||||
static int
|
||||
gen_extract(FILE *fp, const struct node *root, char *object)
|
||||
{
|
||||
@ -1390,45 +1431,6 @@ unminus(FILE *fp, const char *s)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a definition for the enum packed into a guard against multiple
|
||||
* definitions.
|
||||
*
|
||||
* \param fp file to write definition to
|
||||
* \param t type
|
||||
*/
|
||||
static void
|
||||
gen_enum(FILE *fp, const struct type *t)
|
||||
{
|
||||
const struct enums *e;
|
||||
long min = LONG_MAX;
|
||||
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "#ifndef %s_defined__\n", t->name);
|
||||
fprintf(fp, "#define %s_defined__\n", t->name);
|
||||
fprintf(fp, "/*\n");
|
||||
fprintf(fp, " * From %s:%u\n", t->from_fname, t->from_lno);
|
||||
fprintf(fp, " */\n");
|
||||
fprintf(fp, "enum %s {\n", t->name);
|
||||
TAILQ_FOREACH(e, &t->enums, link) {
|
||||
fprintf(fp, "\t%s_", t->name);
|
||||
unminus(fp, e->name);
|
||||
fprintf(fp, " = %ld,\n", e->value);
|
||||
if (e->value < min)
|
||||
min = e->value;
|
||||
}
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#define STROFF_%s %ld\n", t->name, min);
|
||||
fprintf(fp, "#define STRING_%s \\\n", t->name);
|
||||
TAILQ_FOREACH(e, &t->enums, link) {
|
||||
fprintf(fp, "\t[%ld] = \"%s_", e->value - min, t->name);
|
||||
unminus(fp, e->name);
|
||||
fprintf(fp, "\",\\\n");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "#endif /* %s_defined__ */\n", t->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate helper functions for an enum.
|
||||
*
|
||||
@ -1493,6 +1495,54 @@ gen_enum_funcs(FILE *fp, const struct type *t, int ccode)
|
||||
fprintf(fp, "}\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a definition for the enum packed into a guard against multiple
|
||||
* definitions.
|
||||
*
|
||||
* \param fp file to write definition to
|
||||
* \param t type
|
||||
* \param dof generate functions too
|
||||
*/
|
||||
static void
|
||||
gen_enum(FILE *fp, const struct type *t, int dof)
|
||||
{
|
||||
const struct enums *e;
|
||||
long min = LONG_MAX;
|
||||
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "#ifndef %s_defined__\n", t->name);
|
||||
fprintf(fp, "#define %s_defined__\n", t->name);
|
||||
fprintf(fp, "/*\n");
|
||||
fprintf(fp, " * From %s:%u\n", t->from_fname, t->from_lno);
|
||||
fprintf(fp, " */\n");
|
||||
fprintf(fp, "enum %s {\n", t->name);
|
||||
TAILQ_FOREACH(e, &t->enums, link) {
|
||||
fprintf(fp, "\t%s_", t->name);
|
||||
unminus(fp, e->name);
|
||||
fprintf(fp, " = %ld,\n", e->value);
|
||||
if (e->value < min)
|
||||
min = e->value;
|
||||
}
|
||||
fprintf(fp, "};\n");
|
||||
fprintf(fp, "#define STROFF_%s %ld\n", t->name, min);
|
||||
fprintf(fp, "#define STRING_%s \\\n", t->name);
|
||||
TAILQ_FOREACH(e, &t->enums, link) {
|
||||
fprintf(fp, "\t[%ld] = \"%s_", e->value - min, t->name);
|
||||
unminus(fp, e->name);
|
||||
fprintf(fp, "\",\\\n");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
if (dof) {
|
||||
fprintf(fp, "#ifdef SNMPENUM_FUNCS\n");
|
||||
fprintf(fp, "\n");
|
||||
gen_enum_funcs(fp, t, 0);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "#endif\n");
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fprintf(fp, "#endif /* %s_defined__ */\n", t->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate helper functions for an enum. This generates code for a c file.
|
||||
*
|
||||
@ -1529,6 +1579,16 @@ gen_all_enum_funcs(FILE *fp, int ccode)
|
||||
gen_enum_funcs(fp, t, ccode);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_enums(FILE *fp, int dof)
|
||||
{
|
||||
const struct type *t;
|
||||
|
||||
LIST_FOREACH(t, &types, link)
|
||||
if (t->is_enum || t->is_bits)
|
||||
gen_enum(fp, t, dof);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a given enum to the specified file and optionally generate static
|
||||
* inline helper functions for them.
|
||||
@ -1546,9 +1606,7 @@ extract_enum(FILE *fp, const char *name, int gen_funcs)
|
||||
|
||||
LIST_FOREACH(t, &types, link)
|
||||
if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) {
|
||||
gen_enum(fp, t);
|
||||
if (gen_funcs)
|
||||
gen_enum_funcs(fp, t, 0);
|
||||
gen_enum(fp, t, gen_funcs);
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
@ -1567,11 +1625,8 @@ extract_all_enums(FILE *fp, int gen_funcs)
|
||||
const struct type *t;
|
||||
|
||||
LIST_FOREACH(t, &types, link)
|
||||
if (t->is_enum || t->is_bits) {
|
||||
gen_enum(fp, t);
|
||||
if (gen_funcs)
|
||||
gen_enum_funcs(fp, t, 0);
|
||||
}
|
||||
if (t->is_enum || t->is_bits)
|
||||
gen_enum(fp, t, gen_funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1579,13 +1634,12 @@ extract_all_enums(FILE *fp, int gen_funcs)
|
||||
*
|
||||
* \param argc number of arguments
|
||||
* \param argv arguments (enum names)
|
||||
* \param gen_funcs_h generate functions into the header file
|
||||
* \param gen_funcs_c generate a .c file with functions
|
||||
* \param gen_funcs which functions to generate
|
||||
*/
|
||||
static void
|
||||
make_enums(int argc, char *argv[], int gen_funcs_h, int gen_funcs_c)
|
||||
make_enums(int argc, char *argv[], enum gen_funcs gen_funcs)
|
||||
{
|
||||
if (gen_funcs_c) {
|
||||
if (gen_funcs == GEN_FUNCS_C) {
|
||||
if (argc == 0)
|
||||
gen_all_enum_funcs(stdout, 1);
|
||||
else {
|
||||
@ -1595,30 +1649,58 @@ make_enums(int argc, char *argv[], int gen_funcs_h, int gen_funcs_c)
|
||||
}
|
||||
} else {
|
||||
if (argc == 0)
|
||||
extract_all_enums(stdout, gen_funcs_h);
|
||||
extract_all_enums(stdout, gen_funcs == GEN_FUNCS_H);
|
||||
else {
|
||||
for (int i = 0; i < argc; i++)
|
||||
if (extract_enum(stdout, argv[i], gen_funcs_h))
|
||||
if (extract_enum(stdout, argv[i],
|
||||
gen_funcs == GEN_FUNCS_H))
|
||||
errx(1, "enum not found: %s", argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the operation tables for the daemon or a module.
|
||||
*
|
||||
* \param root tree root
|
||||
* \param gen_funcs generate enum funcs
|
||||
*/
|
||||
static void
|
||||
make_table(const struct node *root, int gen_funcs)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
char fname[MAXPATHLEN + 1];
|
||||
sprintf(fname, "%stree.h", file_prefix);
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
err(1, "%s: ", fname);
|
||||
gen_header(fp, root, PREFIX_LEN, NULL);
|
||||
|
||||
fprintf(fp, "\n#ifdef SNMPTREE_TYPES\n");
|
||||
gen_enums(fp, gen_funcs);
|
||||
fprintf(fp, "\n#endif /* SNMPTREE_TYPES */\n\n");
|
||||
|
||||
fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size);
|
||||
fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
sprintf(fname, "%stree.c", file_prefix);
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
err(1, "%s: ", fname);
|
||||
gen_table(fp, root);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int do_extract = 0;
|
||||
int do_tree = 0;
|
||||
int do_enums = 0;
|
||||
int gen_funcs_h = 0;
|
||||
int gen_funcs_c = 0;
|
||||
int opt;
|
||||
struct node *root;
|
||||
char fname[MAXPATHLEN + 1];
|
||||
int tok;
|
||||
FILE *fp;
|
||||
enum op op = OP_GEN;
|
||||
enum gen_funcs gen_funcs = GEN_FUNCS_NONE;
|
||||
|
||||
char *infile = NULL;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "dEeFfhI:i:lp:t")) != EOF)
|
||||
switch (opt) {
|
||||
|
||||
@ -1627,19 +1709,29 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
do_enums = 1;
|
||||
if (op != OP_GEN && op != OP_ENUMS)
|
||||
errx(1, "-E conflicts with earlier options");
|
||||
op = OP_ENUMS;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
do_extract = 1;
|
||||
if (op != OP_GEN && op != OP_EXTRACT)
|
||||
errx(1, "-e conflicts with earlier options");
|
||||
op = OP_EXTRACT;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
gen_funcs_c = 1;
|
||||
if (gen_funcs != GEN_FUNCS_NONE &&
|
||||
gen_funcs != GEN_FUNCS_C)
|
||||
errx(1, "-F conflicts with -f");
|
||||
gen_funcs = GEN_FUNCS_C;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
gen_funcs_h = 1;
|
||||
if (gen_funcs != GEN_FUNCS_NONE &&
|
||||
gen_funcs != GEN_FUNCS_H)
|
||||
errx(1, "-f conflicts with -F");
|
||||
gen_funcs = GEN_FUNCS_H;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@ -1666,75 +1758,61 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 't':
|
||||
do_tree = 1;
|
||||
if (op != OP_GEN && op != OP_TREE)
|
||||
errx(1, "-t conflicts with earlier options");
|
||||
op = OP_TREE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_extract + do_tree + do_enums > 1)
|
||||
errx(1, "conflicting options -e/-t/-E");
|
||||
if (!do_extract && !do_enums && argc != optind)
|
||||
errx(1, "no arguments allowed");
|
||||
if (do_extract && argc == optind)
|
||||
errx(1, "no objects specified");
|
||||
|
||||
if ((gen_funcs_h || gen_funcs_c) && (do_extract || do_tree))
|
||||
errx(1, "-f and -F not allowed with -e or -t");
|
||||
if (gen_funcs_c && !do_enums)
|
||||
errx(1, "-F requires -E");
|
||||
if (gen_funcs_h && gen_funcs_c)
|
||||
errx(1, "-f and -F are mutually exclusive");
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* open input */
|
||||
if (infile == NULL) {
|
||||
input_new(stdin, NULL, "<stdin>");
|
||||
} else {
|
||||
FILE *fp;
|
||||
if ((fp = fopen(infile, "r")) == NULL)
|
||||
err(1, "%s", infile);
|
||||
input_new(fp, NULL, infile);
|
||||
}
|
||||
|
||||
root = parse_top(gettoken());
|
||||
/* parse and check input */
|
||||
struct node *root = parse_top(gettoken());
|
||||
|
||||
int tok;
|
||||
while ((tok = gettoken()) != TOK_EOF)
|
||||
merge(&root, parse_top(tok));
|
||||
|
||||
if (root)
|
||||
check_tree(root);
|
||||
|
||||
if (do_extract) {
|
||||
while (optind < argc) {
|
||||
if (gen_extract(stdout, root, argv[optind]))
|
||||
errx(1, "object not found: %s", argv[optind]);
|
||||
optind++;
|
||||
}
|
||||
/* do what the user has requested */
|
||||
switch (op) {
|
||||
|
||||
case OP_EXTRACT:
|
||||
if (argc == 0)
|
||||
errx(1, "-e requires arguments");
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
if (gen_extract(stdout, root, argv[i]))
|
||||
errx(1, "object not found: %s", argv[i]);
|
||||
return (0);
|
||||
}
|
||||
if (do_enums) {
|
||||
make_enums(argc - optind, argv + optind,
|
||||
gen_funcs_h, gen_funcs_c);
|
||||
|
||||
case OP_ENUMS:
|
||||
make_enums(argc, argv, gen_funcs);
|
||||
return (0);
|
||||
}
|
||||
if (do_tree) {
|
||||
|
||||
case OP_TREE:
|
||||
if (argc != 0)
|
||||
errx(1, "-t allows no arguments");
|
||||
gen_tree(root, 0);
|
||||
return (0);
|
||||
|
||||
case OP_GEN:
|
||||
if (argc != 0)
|
||||
errx(1, "tree generation allows no arguments");
|
||||
make_table(root, gen_funcs == GEN_FUNCS_H);
|
||||
return (0);
|
||||
}
|
||||
sprintf(fname, "%stree.h", file_prefix);
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
err(1, "%s: ", fname);
|
||||
gen_header(fp, root, PREFIX_LEN, NULL);
|
||||
|
||||
fprintf(fp, "\n#ifdef SNMPTREE_TYPES\n");
|
||||
extract_all_enums(fp, gen_funcs_h);
|
||||
fprintf(fp, "\n#endif /* SNMPTREE_TYPES */\n\n");
|
||||
|
||||
fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size);
|
||||
fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
sprintf(fname, "%stree.c", file_prefix);
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
err(1, "%s: ", fname);
|
||||
gen_table(fp, root);
|
||||
fclose(fp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005
|
||||
* Copyright (c) 2004-2005,2018
|
||||
* Hartmut Brandt.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2001-2003
|
||||
@ -34,11 +34,13 @@
|
||||
*
|
||||
* Support functions for SNMP clients.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <net/if.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
@ -58,12 +60,16 @@
|
||||
#include <err.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "support.h"
|
||||
#include "asn1.h"
|
||||
#include "snmp.h"
|
||||
#include "snmpclient.h"
|
||||
#include "snmppriv.h"
|
||||
|
||||
#define DEBUG_PARSE 0
|
||||
|
||||
/* global context */
|
||||
struct snmp_client snmp_client;
|
||||
|
||||
@ -924,7 +930,8 @@ open_client_udp(const char *host, const char *port)
|
||||
/* open connection */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = snmp_client.trans == SNMP_TRANS_UDP ? AF_INET:
|
||||
AF_INET6;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = 0;
|
||||
error = getaddrinfo(snmp_client.chost, snmp_client.cport, &hints, &res0);
|
||||
@ -1068,6 +1075,7 @@ snmp_open(const char *host, const char *port, const char *readcomm,
|
||||
switch (snmp_client.trans) {
|
||||
|
||||
case SNMP_TRANS_UDP:
|
||||
case SNMP_TRANS_UDP6:
|
||||
if (open_client_udp(host, port) != 0)
|
||||
return (-1);
|
||||
break;
|
||||
@ -1866,99 +1874,410 @@ snmp_client_set_port(struct snmp_client *cl, const char *p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a server specification
|
||||
/**
|
||||
* Try to get a transport identifier which is a leading alphanumeric string
|
||||
* (starting with '_' or a letter and including also '_') terminated by
|
||||
* a double colon. The string may not be empty. The transport identifier
|
||||
* is optional.
|
||||
*
|
||||
* [trans::][community@][server][:port]
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of transport; updated to point to
|
||||
* the next character to parse
|
||||
*
|
||||
* \return end of transport; equals *strp if there is none; NULL if there
|
||||
* was an error
|
||||
*/
|
||||
static inline const char *
|
||||
get_transp(struct snmp_client *sc, const char **strp)
|
||||
{
|
||||
const char *p = *strp;
|
||||
|
||||
if (isascii(*p) && (isalpha(*p) || *p == '_')) {
|
||||
p++;
|
||||
while (isascii(*p) && (isalnum(*p) || *p == '_'))
|
||||
p++;
|
||||
if (p[0] == ':' && p[1] == ':') {
|
||||
*strp = p + 2;
|
||||
return (p);
|
||||
}
|
||||
}
|
||||
if (p[0] == ':' && p[1] == ':') {
|
||||
seterr(sc, "empty transport specifier");
|
||||
return (NULL);
|
||||
}
|
||||
return (*strp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get community string. Eat everything up to the last @ (if there is
|
||||
* any) but only if it is not longer than SNMP_COMMUNITY_MAXLEN. Empty
|
||||
* community strings are legal.
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of community; updated to the point to
|
||||
* the next character to parse
|
||||
*
|
||||
* \return end of community; equals *strp if there is none; NULL if there
|
||||
* was an error
|
||||
*/
|
||||
static inline const char *
|
||||
get_comm(struct snmp_client *sc, const char **strp)
|
||||
{
|
||||
const char *p = strrchr(*strp, '@');
|
||||
|
||||
if (p == NULL)
|
||||
/* no community string */
|
||||
return (*strp);
|
||||
|
||||
if (p - *strp > SNMP_COMMUNITY_MAXLEN) {
|
||||
seterr(sc, "community string too long '%.*s'",
|
||||
p - *strp, *strp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
*strp = p + 1;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get an IPv6 address. This starts with an [ and should end with an ]
|
||||
* and everything between should be not longer than INET6_ADDRSTRLEN and
|
||||
* parseable by inet_pton().
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of IPv6 address (the '['); updated to point to
|
||||
* the next character to parse (the one after the closing ']')
|
||||
*
|
||||
* \return end of address (equals *strp + 1 if there is none) or NULL
|
||||
* on errors
|
||||
*/
|
||||
static inline const char *
|
||||
get_ipv6(struct snmp_client *sc, const char **strp)
|
||||
{
|
||||
char str[INET6_ADDRSTRLEN + IF_NAMESIZE];
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
|
||||
if (**strp != '[')
|
||||
return (*strp + 1);
|
||||
|
||||
const char *p = *strp + 1;
|
||||
while (*p != ']' ) {
|
||||
if (*p == '\0') {
|
||||
seterr(sc, "unterminated IPv6 address '%.*s'",
|
||||
p - *strp, *strp);
|
||||
return (NULL);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p - *strp > INET6_ADDRSTRLEN + IF_NAMESIZE) {
|
||||
seterr(sc, "IPv6 address too long '%.*s'", p - *strp, *strp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
strncpy(str, *strp + 1, p - (*strp + 1));
|
||||
str[p - (*strp + 1)] = '\0';
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST;
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
error = getaddrinfo(str, NULL, &hints, &res);
|
||||
if (error != 0) {
|
||||
seterr(sc, "%s: %s", str, gai_strerror(error));
|
||||
return (NULL);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
*strp = p + 1;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get an IPv4 address. This starts with a digit and consists of digits
|
||||
* and dots, is not longer INET_ADDRSTRLEN and must be parseable by
|
||||
* inet_aton().
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of IPv4 address; updated to point to the
|
||||
* next character to parse
|
||||
*
|
||||
* \return end of address (equals *strp if there is none) or NULL
|
||||
* on errors
|
||||
*/
|
||||
static inline const char *
|
||||
get_ipv4(struct snmp_client *sc, const char **strp)
|
||||
{
|
||||
const char *p = *strp;
|
||||
|
||||
while (isascii(*p) && (isdigit(*p) || *p == '.'))
|
||||
p++;
|
||||
|
||||
if (p - *strp > INET_ADDRSTRLEN) {
|
||||
seterr(sc, "IPv4 address too long '%.*s'", p - *strp, *strp);
|
||||
return (NULL);
|
||||
}
|
||||
if (*strp == p)
|
||||
return *strp;
|
||||
|
||||
char str[INET_ADDRSTRLEN + 1];
|
||||
strncpy(str, *strp, p - *strp);
|
||||
str[p - *strp] = '\0';
|
||||
|
||||
struct in_addr addr;
|
||||
if (inet_aton(str, &addr) != 1) {
|
||||
seterr(sc, "illegal IPv4 address '%s'", str);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
*strp = p;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get a hostname. This includes everything up to but not including
|
||||
* the last colon (if any). There is no length restriction.
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of hostname; updated to point to the next
|
||||
* character to parse (the trailing NUL character or the last
|
||||
* colon)
|
||||
*
|
||||
* \return end of address (equals *strp if there is none)
|
||||
*/
|
||||
static inline const char *
|
||||
get_host(struct snmp_client *sc __unused, const char **strp)
|
||||
{
|
||||
const char *p = strrchr(*strp, ':');
|
||||
|
||||
if (p == NULL) {
|
||||
*strp += strlen(*strp);
|
||||
return (*strp);
|
||||
}
|
||||
|
||||
*strp = p;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get a port number. This start with a colon and extends to the end
|
||||
* of string. The port number must not be empty.
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param strp possible start of port specification; if this points to a
|
||||
* colon there is a port specification
|
||||
*
|
||||
* \return end of port number (equals *strp if there is none); NULL
|
||||
* if there is no port number
|
||||
*/
|
||||
static inline const char *
|
||||
get_port(struct snmp_client *sc, const char **strp)
|
||||
{
|
||||
if (**strp != ':')
|
||||
return (*strp + 1);
|
||||
|
||||
if ((*strp)[1] == '\0') {
|
||||
seterr(sc, "empty port name");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
*strp += strlen(*strp);
|
||||
return (*strp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the string in the range given by two pointers.
|
||||
*
|
||||
* \param sc client struct to set errors
|
||||
* \param s begin and end pointers
|
||||
*
|
||||
* \return freshly allocated copy of the string between s[0] and s[1]
|
||||
*/
|
||||
static inline char *
|
||||
save_str(struct snmp_client *sc, const char *const s[2])
|
||||
{
|
||||
char *m;
|
||||
|
||||
if ((m = malloc(s[1] - s[0] + 1)) == NULL) {
|
||||
seterr(sc, "%s: %s", __func__, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
strncpy(m, s[0], s[1] - s[0]);
|
||||
m[s[1] - s[0]] = '\0';
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a server specification. All parts are optional:
|
||||
*
|
||||
* [<trans>::][<comm>@][<host-or-ip>][:<port>]
|
||||
*
|
||||
* The transport string consists of letters, digits or '_' and starts with
|
||||
* a letter or digit. It is terminated by two colons and may not be empty.
|
||||
*
|
||||
* The community string is terminated by the last '@' and does not exceed
|
||||
* SNMP_COMMUNITY_MAXLEN. It may be empty.
|
||||
*
|
||||
* The host or ip is either an IPv4 address (as parsed by inet_pton()), an
|
||||
* IPv6 address in '[' and ']' and parseable by inet_aton() or a hostname
|
||||
* terminated by the last colon or by the NUL character.
|
||||
*
|
||||
* The port number may be specified numerically or symbolically and starts
|
||||
* with the last colon.
|
||||
*
|
||||
* The functions sets the chost, cport, trans, read_community and
|
||||
* write_community fields on success and the error field on errors.
|
||||
* The chost and cport fields are allocated by malloc(3), their previous
|
||||
* content is deallocated by free(3).
|
||||
*
|
||||
* The function explicitly allows mismatches between the transport and
|
||||
* the address type in order to support IPv4 in IPv6 addresses.
|
||||
*
|
||||
* \param sc client struct to fill
|
||||
* \param str string to parse
|
||||
*
|
||||
* \return 0 on success and -1 on errors
|
||||
*/
|
||||
int
|
||||
snmp_parse_server(struct snmp_client *sc, const char *str)
|
||||
{
|
||||
const char *p, *s = str;
|
||||
#if DEBUG_PARSE
|
||||
const char *const orig = str;
|
||||
#endif
|
||||
|
||||
/* look for a double colon */
|
||||
for (p = s; *p != '\0'; p++) {
|
||||
if (*p == '\\' && p[1] != '\0') {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
if (*p == ':' && p[1] == ':')
|
||||
break;
|
||||
}
|
||||
if (*p != '\0') {
|
||||
if (p > s) {
|
||||
if (p - s == 3 && strncmp(s, "udp", 3) == 0)
|
||||
sc->trans = SNMP_TRANS_UDP;
|
||||
else if (p - s == 6 && strncmp(s, "stream", 6) == 0)
|
||||
sc->trans = SNMP_TRANS_LOC_STREAM;
|
||||
else if (p - s == 5 && strncmp(s, "dgram", 5) == 0)
|
||||
sc->trans = SNMP_TRANS_LOC_DGRAM;
|
||||
else {
|
||||
seterr(sc, "unknown SNMP transport '%.*s'",
|
||||
(int)(p - s), s);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
s = p + 2;
|
||||
const char *const trans_list[] = {
|
||||
[SNMP_TRANS_UDP] = "udp",
|
||||
[SNMP_TRANS_LOC_DGRAM] = "dgram",
|
||||
[SNMP_TRANS_LOC_STREAM] = "stream",
|
||||
[SNMP_TRANS_UDP6] = "udp6",
|
||||
};
|
||||
|
||||
/* parse input */
|
||||
const char *const transp[2] = {
|
||||
str,
|
||||
get_transp(sc, &str),
|
||||
};
|
||||
if (transp[1] == NULL)
|
||||
return (-1);
|
||||
|
||||
const char *const comm[2] = {
|
||||
str,
|
||||
get_comm(sc, &str),
|
||||
};
|
||||
if (comm[1] == NULL)
|
||||
return (-1);
|
||||
|
||||
const char *const ipv6[2] = {
|
||||
str + 1,
|
||||
get_ipv6(sc, &str),
|
||||
};
|
||||
if (ipv6[1] == NULL)
|
||||
return (-1);
|
||||
|
||||
const char *ipv4[2] = {
|
||||
str,
|
||||
str,
|
||||
};
|
||||
|
||||
const char *host[2] = {
|
||||
str,
|
||||
str,
|
||||
};
|
||||
|
||||
if (ipv6[0] == ipv6[1]) {
|
||||
ipv4[1] = get_ipv4(sc, &str);
|
||||
|
||||
if (ipv4[0] == ipv4[1])
|
||||
host[1] = get_host(sc, &str);
|
||||
}
|
||||
|
||||
/* look for a @ */
|
||||
for (p = s; *p != '\0'; p++) {
|
||||
if (*p == '\\' && p[1] != '\0') {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
if (*p == '@')
|
||||
break;
|
||||
const char *port[2] = {
|
||||
str + 1,
|
||||
get_port(sc, &str),
|
||||
};
|
||||
if (port[1] == NULL)
|
||||
return (-1);
|
||||
|
||||
if (*str != '\0') {
|
||||
seterr(sc, "junk at end of server specification '%s'", str);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (*p != '\0') {
|
||||
if (p - s > SNMP_COMMUNITY_MAXLEN) {
|
||||
seterr(sc, "community string too long");
|
||||
return (-1);
|
||||
}
|
||||
strncpy(sc->read_community, s, p - s);
|
||||
sc->read_community[p - s] = '\0';
|
||||
strncpy(sc->write_community, s, p - s);
|
||||
sc->write_community[p - s] = '\0';
|
||||
s = p + 1;
|
||||
}
|
||||
#if DEBUG_PARSE
|
||||
printf("transp: %zu %zu\n", transp[0] - orig, transp[1] - orig);
|
||||
printf("comm: %zu %zu\n", comm[0] - orig, comm[1] - orig);
|
||||
printf("ipv6: %zu %zu\n", ipv6[0] - orig, ipv6[1] - orig);
|
||||
printf("ipv4: %zu %zu\n", ipv4[0] - orig, ipv4[1] - orig);
|
||||
printf("host: %zu %zu\n", host[0] - orig, host[1] - orig);
|
||||
printf("port: %zu %zu\n", port[0] - orig, port[1] - orig);
|
||||
#endif
|
||||
|
||||
/* look for a colon */
|
||||
for (p = s; *p != '\0'; p++) {
|
||||
if (*p == '\\' && p[1] != '\0') {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
if (*p == ':')
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == ':') {
|
||||
if (p > s) {
|
||||
/* host:port */
|
||||
free(sc->chost);
|
||||
if ((sc->chost = malloc(p - s + 1)) == NULL) {
|
||||
seterr(sc, "%s", strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
strncpy(sc->chost, s, p - s);
|
||||
sc->chost[p - s] = '\0';
|
||||
}
|
||||
/* port */
|
||||
free(sc->cport);
|
||||
if ((sc->cport = strdup(p + 1)) == NULL) {
|
||||
seterr(sc, "%s", strerror(errno));
|
||||
return (-1);
|
||||
/* analyse and allocate */
|
||||
int i = -1;
|
||||
if (transp[0] != transp[1]) {
|
||||
for (i = 0; i < (int)nitems(trans_list); i++) {
|
||||
if (trans_list[i] != NULL &&
|
||||
strlen(trans_list[i]) == (size_t)(transp[1] -
|
||||
transp[0]) && !strncmp(trans_list[i], transp[0],
|
||||
transp[1] - transp[0]))
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (p > s) {
|
||||
/* host */
|
||||
free(sc->chost);
|
||||
if ((sc->chost = strdup(s)) == NULL) {
|
||||
seterr(sc, "%s", strerror(errno));
|
||||
if (i == (int)nitems(trans_list)) {
|
||||
seterr(sc, "unknown transport specifier '%.*s'",
|
||||
transp[1] - transp[0], transp[0]);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
char *chost;
|
||||
|
||||
if (ipv6[0] != ipv6[1]) {
|
||||
if ((chost = save_str(sc, ipv6)) == NULL)
|
||||
return (-1);
|
||||
if (i == -1)
|
||||
i = SNMP_TRANS_UDP6;
|
||||
} else if (ipv4[0] != ipv4[1]) {
|
||||
if ((chost = save_str(sc, ipv4)) == NULL)
|
||||
return (-1);
|
||||
if (i == -1)
|
||||
i = SNMP_TRANS_UDP;
|
||||
} else {
|
||||
if ((chost = save_str(sc, host)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (i == -1) {
|
||||
/* Default transport is UDP unless the host contains
|
||||
* a slash in which case we default to DGRAM. */
|
||||
i = SNMP_TRANS_UDP;
|
||||
for (const char *p = host[0]; p < host[1]; p++)
|
||||
if (*p == '/') {
|
||||
i = SNMP_TRANS_LOC_DGRAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *cport = save_str(sc, port);
|
||||
if (cport == NULL) {
|
||||
free(chost);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* commit */
|
||||
sc->trans = i;
|
||||
|
||||
strncpy(sc->read_community, comm[0], comm[1] - comm[0]);
|
||||
sc->read_community[comm[1] - comm[0]] = '\0';
|
||||
strncpy(sc->write_community, comm[0], comm[1] - comm[0]);
|
||||
sc->write_community[comm[1] - comm[0]] = '\0';
|
||||
|
||||
free(sc->chost);
|
||||
sc->chost = chost;
|
||||
free(sc->cport);
|
||||
sc->cport = cport;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
#define SNMP_TRANS_UDP 0
|
||||
#define SNMP_TRANS_LOC_DGRAM 1
|
||||
#define SNMP_TRANS_LOC_STREAM 2
|
||||
#define SNMP_TRANS_UDP6 3
|
||||
|
||||
/* type of callback function for responses
|
||||
* this callback function is responsible for free() any memory associated with
|
||||
|
@ -46,3 +46,11 @@ typedef StorageType ENUM (
|
||||
5 readOnly
|
||||
)
|
||||
|
||||
typedef InetAddressType ENUM (
|
||||
0 unknown
|
||||
1 ipv4
|
||||
2 ipv6
|
||||
3 ipv4z
|
||||
4 ipv6z
|
||||
16 dns
|
||||
)
|
||||
|
@ -3,6 +3,10 @@
|
||||
-- Fraunhofer Institute for Open Communication Systems (FhG Fokus).
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Copyright (c) 2018
|
||||
-- Hartmut Brandt.
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- Author: Harti Brandt <harti@freebsd.org>
|
||||
--
|
||||
-- Redistribution and use in source and binary forms, with or without
|
||||
@ -34,17 +38,17 @@ BEGEMOT-SNMPD-MIB DEFINITIONS ::= BEGIN
|
||||
|
||||
IMPORTS
|
||||
MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY, Counter32,
|
||||
Unsigned32, IpAddress
|
||||
Integer32, Unsigned32, IpAddress
|
||||
FROM SNMPv2-SMI
|
||||
TEXTUAL-CONVENTION, TruthValue, RowStatus
|
||||
FROM SNMPv2-TC
|
||||
MODULE-COMPLIANCE, OBJECT-GROUP
|
||||
FROM SNMPv2-CONF
|
||||
InetAddressType, InetAddress, InetPortNumber
|
||||
FROM INET-ADDRESS-MIB
|
||||
begemot
|
||||
FROM BEGEMOT-MIB;
|
||||
|
||||
begemotSnmpd MODULE-IDENTITY
|
||||
LAST-UPDATED "201801190000Z"
|
||||
LAST-UPDATED "201808080000Z"
|
||||
ORGANIZATION "Fraunhofer FOKUS, CATS"
|
||||
CONTACT-INFO
|
||||
" Hartmut Brandt
|
||||
@ -59,6 +63,9 @@ begemotSnmpd MODULE-IDENTITY
|
||||
E-mail: harti@freebsd.org"
|
||||
DESCRIPTION
|
||||
"The MIB module for the Begemot SNMP daemon."
|
||||
REVISION "201808080000Z"
|
||||
DESCRIPTION
|
||||
"Add the begemotSnmpdTransInetTable."
|
||||
::= { begemot 1 }
|
||||
|
||||
begemotSnmpdObjects OBJECT IDENTIFIER ::= { begemotSnmpd 1 }
|
||||
@ -93,7 +100,7 @@ begemotSnmpdAgentFreeBSD OBJECT-IDENTITY
|
||||
begemotSnmpdConfig OBJECT IDENTIFIER ::= { begemotSnmpdObjects 1 }
|
||||
|
||||
begemotSnmpdTransmitBuffer OBJECT-TYPE
|
||||
SYNTAX INTEGER (484..65535)
|
||||
SYNTAX Integer32 (484..65535)
|
||||
MAX-ACCESS read-write
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
@ -103,7 +110,7 @@ begemotSnmpdTransmitBuffer OBJECT-TYPE
|
||||
::= { begemotSnmpdConfig 1 }
|
||||
|
||||
begemotSnmpdReceiveBuffer OBJECT-TYPE
|
||||
SYNTAX INTEGER (484..65535)
|
||||
SYNTAX Integer32 (484..65535)
|
||||
MAX-ACCESS read-write
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
@ -181,7 +188,7 @@ begemotTrapSinkAddr OBJECT-TYPE
|
||||
::= { begemotTrapSinkEntry 1 }
|
||||
|
||||
begemotTrapSinkPort OBJECT-TYPE
|
||||
SYNTAX INTEGER (1..65535)
|
||||
SYNTAX Integer32 (1..65535)
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
@ -203,7 +210,7 @@ begemotTrapSinkStatus OBJECT-TYPE
|
||||
begemotSnmpdPortTable OBJECT-TYPE
|
||||
SYNTAX SEQUENCE OF BegemotSnmpdPortEntry
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
STATUS deprecated
|
||||
DESCRIPTION
|
||||
"A table with descriptions of UDP ports to listen on
|
||||
for SNMP messages."
|
||||
@ -212,7 +219,7 @@ begemotSnmpdPortTable OBJECT-TYPE
|
||||
begemotSnmpdPortEntry OBJECT-TYPE
|
||||
SYNTAX BegemotSnmpdPortEntry
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
STATUS deprecated
|
||||
DESCRIPTION
|
||||
"An entry in the table with descriptions of UDP ports to
|
||||
listen on for SNMP messages."
|
||||
@ -228,15 +235,15 @@ BegemotSnmpdPortEntry ::= SEQUENCE {
|
||||
begemotSnmpdPortAddress OBJECT-TYPE
|
||||
SYNTAX IpAddress
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
STATUS deprecated
|
||||
DESCRIPTION
|
||||
"The IP address to bind to."
|
||||
::= { begemotSnmpdPortEntry 1 }
|
||||
|
||||
begemotSnmpdPortPort OBJECT-TYPE
|
||||
SYNTAX INTEGER (1..65535)
|
||||
SYNTAX Integer32 (1..65535)
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
STATUS deprecated
|
||||
DESCRIPTION
|
||||
"The UDP port to listen on for SNMP messages."
|
||||
::= { begemotSnmpdPortEntry 2 }
|
||||
@ -244,7 +251,7 @@ begemotSnmpdPortPort OBJECT-TYPE
|
||||
begemotSnmpdPortStatus OBJECT-TYPE
|
||||
SYNTAX INTEGER { valid(1), invalid(2) }
|
||||
MAX-ACCESS read-create
|
||||
STATUS current
|
||||
STATUS deprecated
|
||||
DESCRIPTION
|
||||
"Set status to 1 to create entry, set it to 2 to delete it."
|
||||
::= { begemotSnmpdPortEntry 3 }
|
||||
@ -275,7 +282,7 @@ BegemotSnmpdCommunityEntry ::= SEQUENCE {
|
||||
begemotSnmpdCommunityIndex Unsigned32,
|
||||
begemotSnmpdCommunityString OCTET STRING,
|
||||
begemotSnmpdCommunityDescr OCTET STRING,
|
||||
begemotSnmpdCommunityPermission INTEGER
|
||||
begemotSnmpdCommunityPermission Unsigned32
|
||||
}
|
||||
|
||||
begemotSnmpdCommunityModule OBJECT-TYPE
|
||||
@ -312,7 +319,7 @@ begemotSnmpdCommunityDescr OBJECT-TYPE
|
||||
::= { begemotSnmpdCommunityEntry 4 }
|
||||
|
||||
begemotSnmpdCommunityPermission OBJECT-TYPE
|
||||
SYNTAX INTEGER (1..4294967295)
|
||||
SYNTAX Unsigned32 (1..4294967295)
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
@ -449,7 +456,7 @@ begemotSnmpdDebugSnmpTrace OBJECT-TYPE
|
||||
::= { begemotSnmpdDebug 2 }
|
||||
|
||||
begemotSnmpdDebugSyslogPri OBJECT-TYPE
|
||||
SYNTAX INTEGER (0..8)
|
||||
SYNTAX Integer32 (0..8)
|
||||
MAX-ACCESS read-write
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
@ -570,10 +577,115 @@ begemotSnmpdTransportOid OBJECT-TYPE
|
||||
"A pointer to the group with the transport-dependend stuff."
|
||||
::= { begemotSnmpdTransportEntry 3 }
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
--
|
||||
-- Internet port table.
|
||||
--
|
||||
BegemotSnmpdTransportProto ::= TEXTUAL-CONVENTION
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"A value that represents the type of protocol to be used for
|
||||
listening on a socket. The following protocols are currently
|
||||
used:
|
||||
|
||||
udp(1) Use UDP for IPv4 and IPv6 sockets."
|
||||
SYNTAX INTEGER {
|
||||
udp(1)
|
||||
}
|
||||
|
||||
begemotSnmpdTransInetTable OBJECT-TYPE
|
||||
SYNTAX SEQUENCE OF BegemotSnmpdTransInetEntry
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"This table contains all the ports the daemon should listen on.
|
||||
Entries can be created at initialization time via the config
|
||||
file or at run time via a SET. One row can map to several open
|
||||
sockets in the case of InetAddressType::dns rows. These rows
|
||||
open one socket for each address returned by getaddrinfo(3).
|
||||
for SNMP messages."
|
||||
::= { begemotSnmpdObjects 11 }
|
||||
|
||||
begemotSnmpdTransInetEntry OBJECT-TYPE
|
||||
SYNTAX BegemotSnmpdTransInetEntry
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"A row of the internet port table. Each row may map to one or
|
||||
more listening sockets."
|
||||
INDEX {
|
||||
begemotSnmpdTransInetAddressType,
|
||||
begemotSnmpdTransInetAddress,
|
||||
begemotSnmpdTransInetPort,
|
||||
begemotSnmpdTransInetProto
|
||||
}
|
||||
::= { begemotSnmpdTransInetTable 1 }
|
||||
|
||||
BegemotSnmpdTransInetEntry ::= SEQUENCE {
|
||||
begemotSnmpdTransInetAddressType InetAddressType,
|
||||
begemotSnmpdTransInetAddress InetAddress,
|
||||
begemotSnmpdTransInetPort InetPortNumber,
|
||||
begemotSnmpdTransInetProto BegemotSnmpdTransportProto,
|
||||
begemotSnmpdTransInetStatus RowStatus
|
||||
}
|
||||
|
||||
begemotSnmpdTransInetAddressType OBJECT-TYPE
|
||||
SYNTAX InetAddressType
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"The type of the address. Only ipv4, ipv6, ipv6z and dns are
|
||||
supported."
|
||||
::= { begemotSnmpdTransInetEntry 1 }
|
||||
|
||||
begemotSnmpdTransInetAddress OBJECT-TYPE
|
||||
SYNTAX InetAddress (SIZE (0..64))
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"The address. For ipv4 addresses the length must be 4, ipv6
|
||||
addresses have a length of 16 and ipv6z addresses a length of
|
||||
20 where the last four bytes are the interface index in big
|
||||
endian format. dns addresses may be of zero-length in which case
|
||||
getaddrinfo() generates INADDR_ANY and its IPv6 equivalent. dns
|
||||
addresses will open a socket for all addresses returned by
|
||||
getaddrinfo()."
|
||||
::= { begemotSnmpdTransInetEntry 2 }
|
||||
|
||||
begemotSnmpdTransInetPort OBJECT-TYPE
|
||||
SYNTAX InetPortNumber (1..65535)
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"The port to listen on for SNMP messages."
|
||||
::= { begemotSnmpdTransInetEntry 3 }
|
||||
|
||||
begemotSnmpdTransInetProto OBJECT-TYPE
|
||||
SYNTAX BegemotSnmpdTransportProto
|
||||
MAX-ACCESS not-accessible
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"The protocol to use. Currently only the value udp(1) is supported."
|
||||
::= { begemotSnmpdTransInetEntry 4 }
|
||||
|
||||
begemotSnmpdTransInetStatus OBJECT-TYPE
|
||||
SYNTAX RowStatus
|
||||
MAX-ACCESS read-create
|
||||
STATUS current
|
||||
DESCRIPTION
|
||||
"The status of the conceptual row. A row may be created using
|
||||
createAndGo(4) or createAndWait(5). An inactive row can be
|
||||
activated writing active(1) and an active row can be inactivated
|
||||
by writing notInService(2). Finally active or inactive rows can be
|
||||
deleted by writing the value destroy(6). The value of this field
|
||||
will never read as notReady(3)."
|
||||
::= { begemotSnmpdTransInetEntry 5 }
|
||||
|
||||
--
|
||||
-- XXX These should go into their own MIB
|
||||
--
|
||||
begemotSnmpdTransUdp OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 2 }
|
||||
begemotSnmpdTransLsock OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 3 }
|
||||
begemotSnmpdTransInet OBJECT IDENTIFIER ::= { begemotSnmpdTransportMappings 4 }
|
||||
|
||||
END
|
||||
|
@ -65,6 +65,8 @@
|
||||
#include "tree.h"
|
||||
#include "oid.h"
|
||||
|
||||
#include "trans_inet.h"
|
||||
|
||||
#define PATH_PID "/var/run/%s.pid"
|
||||
#define PATH_CONFIG "/etc/%s.config"
|
||||
#define PATH_ENGINE "/var/%s.engine"
|
||||
@ -1038,7 +1040,7 @@ snmpd_input(struct port_input *pi, struct tport *tport)
|
||||
ssize_t ret, slen;
|
||||
int32_t vi;
|
||||
#ifdef USE_TCPWRAPPERS
|
||||
char client[16];
|
||||
char client[INET6_ADDRSTRLEN];
|
||||
#endif
|
||||
|
||||
ret = tport->transport->vtab->recv(tport, pi);
|
||||
@ -1184,8 +1186,12 @@ snmpd_input(struct port_input *pi, struct tport *tport)
|
||||
sndbuf, &sndlen, "SNMP", ierr, vi, NULL);
|
||||
|
||||
if (ferr == SNMPD_INPUT_OK) {
|
||||
slen = tport->transport->vtab->send(tport, sndbuf, sndlen,
|
||||
pi->peer, pi->peerlen);
|
||||
if (tport->transport->vtab->send != NULL)
|
||||
slen = tport->transport->vtab->send(tport, sndbuf,
|
||||
sndlen, pi->peer, pi->peerlen);
|
||||
else
|
||||
slen = tport->transport->vtab->send2(tport, sndbuf,
|
||||
sndlen, pi);
|
||||
if (slen == -1)
|
||||
syslog(LOG_ERR, "send*: %m");
|
||||
else if ((size_t)slen != sndlen)
|
||||
@ -1201,7 +1207,8 @@ snmpd_input(struct port_input *pi, struct tport *tport)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a PDU to a given port
|
||||
* Send a PDU to a given port. If this is a multi-socket port, use the
|
||||
* first socket.
|
||||
*/
|
||||
void
|
||||
snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu,
|
||||
@ -1224,7 +1231,10 @@ snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu,
|
||||
|
||||
snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY");
|
||||
|
||||
len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen);
|
||||
if (trans->vtab->send != NULL)
|
||||
len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen);
|
||||
else
|
||||
len = trans->vtab->send2(tp, sndbuf, sndlen, NULL);
|
||||
|
||||
if (len == -1)
|
||||
syslog(LOG_ERR, "sendto: %m");
|
||||
@ -1238,16 +1248,37 @@ snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu,
|
||||
|
||||
/*
|
||||
* Close an input source
|
||||
*
|
||||
* \param pi input instance
|
||||
*/
|
||||
void
|
||||
snmpd_input_close(struct port_input *pi)
|
||||
{
|
||||
if (pi->id != NULL)
|
||||
if (pi->id != NULL) {
|
||||
fd_deselect(pi->id);
|
||||
if (pi->fd >= 0)
|
||||
pi->id = NULL;
|
||||
}
|
||||
if (pi->fd >= 0) {
|
||||
(void)close(pi->fd);
|
||||
if (pi->buf != NULL)
|
||||
pi->fd = -1;
|
||||
}
|
||||
if (pi->buf != NULL) {
|
||||
free(pi->buf);
|
||||
pi->buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an input source.
|
||||
*
|
||||
* \param pi input instance
|
||||
*/
|
||||
void
|
||||
snmpd_input_init(struct port_input *pi)
|
||||
{
|
||||
pi->id = NULL;
|
||||
pi->fd = -1;
|
||||
pi->buf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1633,6 +1664,8 @@ main(int argc, char *argv[])
|
||||
syslog(LOG_WARNING, "cannot start UDP transport");
|
||||
if (lsock_trans.start() != SNMP_ERR_NOERROR)
|
||||
syslog(LOG_WARNING, "cannot start LSOCK transport");
|
||||
if (inet_trans.start() != SNMP_ERR_NOERROR)
|
||||
syslog(LOG_WARNING, "cannot start INET transport");
|
||||
|
||||
#ifdef USE_LIBBEGEMOT
|
||||
if (debug.evdebug > 0)
|
||||
|
@ -72,8 +72,18 @@ begemotSnmpdCommunityString.0.1 = $(read)
|
||||
begemotSnmpdCommunityDisable = 1
|
||||
|
||||
# open standard SNMP ports
|
||||
begemotSnmpdPortStatus.[$(host)].161 = 1
|
||||
begemotSnmpdPortStatus.127.0.0.1.161 = 1
|
||||
# begemotSnmpdPortStatus.[$(host)].161 = 1
|
||||
# begemotSnmpdPortStatus.127.0.0.1.161 = 1
|
||||
|
||||
# UDP over IPv4: 127.0.0.1:161
|
||||
begemotSnmpdTransInetStatus.1.4.127.0.0.1.161.1 = 4
|
||||
|
||||
# UDP over IPv6: ::1:161
|
||||
begemotSnmpdTransInetStatus.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.161.1 = 4
|
||||
|
||||
# Use domain name and IPv6 link-local address with scope zone id as address
|
||||
# begemotSnmpdTransInetStatus.16."localhost".161.1 = 4
|
||||
# begemotSnmpdTransInetStatus.16."fe80::1%em0".161.1 = 4
|
||||
|
||||
# open a unix domain socket
|
||||
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
|
||||
|
@ -174,7 +174,7 @@ TAILQ_HEAD(tport_list, tport);
|
||||
|
||||
int snmpd_input(struct port_input *, struct tport *);
|
||||
void snmpd_input_close(struct port_input *);
|
||||
|
||||
void snmpd_input_init(struct port_input *);
|
||||
|
||||
/*
|
||||
* Transport domain
|
||||
@ -194,6 +194,10 @@ struct transport_def {
|
||||
ssize_t (*send)(struct tport *, const u_char *, size_t,
|
||||
const struct sockaddr *, size_t);
|
||||
ssize_t (*recv)(struct tport *, struct port_input *);
|
||||
|
||||
/** send via a multi-socket port */
|
||||
ssize_t (*send2)(struct tport *, const u_char *, size_t,
|
||||
struct port_input *);
|
||||
};
|
||||
struct transport {
|
||||
struct asn_oid index; /* transport table index */
|
||||
|
@ -56,6 +56,48 @@
|
||||
* ordering can be done either on an integer/unsigned field, an asn_oid
|
||||
* or an ordering function.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First set of macros is used when the link is embedded into sub-struct
|
||||
* and links these sub-structs. The sub-struct must be the first field.
|
||||
*
|
||||
* The list is a list of the subfield types.
|
||||
*/
|
||||
#define INSERT_OBJECT_OID_LINK_INDEX_TYPE(PTR, LIST, LINK, INDEX, SUBF) do {\
|
||||
typedef __typeof ((PTR)->SUBF) _subf_type; \
|
||||
_subf_type *_lelem; \
|
||||
\
|
||||
TAILQ_FOREACH(_lelem, (LIST), LINK) \
|
||||
if (asn_compare_oid(&_lelem->INDEX, &(PTR)->SUBF.INDEX) > 0)\
|
||||
break; \
|
||||
if (_lelem == NULL) \
|
||||
TAILQ_INSERT_TAIL((LIST), &(PTR)->SUBF, LINK); \
|
||||
else \
|
||||
TAILQ_INSERT_BEFORE(_lelem, &(PTR)->SUBF, LINK); \
|
||||
} while (0)
|
||||
|
||||
#define NEXT_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\
|
||||
__typeof (TAILQ_FIRST((LIST))) _lelem; \
|
||||
\
|
||||
TAILQ_FOREACH(_lelem, (LIST), LINK) \
|
||||
if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \
|
||||
break; \
|
||||
(TYPE *)(_lelem); \
|
||||
})
|
||||
|
||||
#define FIND_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\
|
||||
__typeof (TAILQ_FIRST((LIST))) _lelem; \
|
||||
\
|
||||
TAILQ_FOREACH(_lelem, (LIST), LINK) \
|
||||
if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \
|
||||
break; \
|
||||
(TYPE *)(_lelem); \
|
||||
})
|
||||
|
||||
/*
|
||||
* This set of macros allows specification of the link and index name.
|
||||
* The index is an OID.
|
||||
*/
|
||||
#define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \
|
||||
__typeof (PTR) _lelem; \
|
||||
\
|
||||
|
1342
contrib/bsnmp/snmpd/trans_inet.c
Normal file
1342
contrib/bsnmp/snmpd/trans_inet.c
Normal file
File diff suppressed because it is too large
Load Diff
38
contrib/bsnmp/snmpd/trans_inet.h
Normal file
38
contrib/bsnmp/snmpd/trans_inet.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018
|
||||
* Hartmut Brandt.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Harti Brandt <harti@freebsd.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef trans_inet_h_1530971397
|
||||
#define trans_inet_h_1530971397
|
||||
|
||||
/* transport declaration */
|
||||
extern const struct transport_def inet_trans;
|
||||
|
||||
#endif
|
@ -70,7 +70,8 @@ const struct transport_def lsock_trans = {
|
||||
lsock_close_port,
|
||||
lsock_init_port,
|
||||
lsock_send,
|
||||
lsock_recv
|
||||
lsock_recv,
|
||||
NULL
|
||||
};
|
||||
static struct transport *my_trans;
|
||||
|
||||
|
@ -67,7 +67,8 @@ const struct transport_def udp_trans = {
|
||||
udp_close_port,
|
||||
udp_init_port,
|
||||
udp_send,
|
||||
udp_recv
|
||||
udp_recv,
|
||||
NULL
|
||||
};
|
||||
static struct transport *my_trans;
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Copyright (c) 2018
|
||||
# Hartmut Brandt.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Author: Harti Brandt <harti@freebsd.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@ -33,6 +37,10 @@
|
||||
|
||||
include "tc.def"
|
||||
|
||||
typedef BegemotSnmpdTransportProto ENUM (
|
||||
1 udp
|
||||
)
|
||||
|
||||
(1 internet
|
||||
(2 mgmt
|
||||
(1 mibII
|
||||
@ -172,13 +180,24 @@ include "tc.def"
|
||||
))
|
||||
(2 begemotSnmpdTransUdp OID op_transport_dummy)
|
||||
(3 begemotSnmpdTransLsock OID op_transport_dummy)
|
||||
(4 begemotSnmpdTransInet OID op_transport_dummy)
|
||||
)
|
||||
(11 begemotSnmpdTransInetTable
|
||||
(1 begemotSnmpdTransInetEntry : INTEGER OCTETSTRING INTEGER INTEGER op_snmp_trans_inet
|
||||
(1 begemotSnmpdTransInetAddressType InetAddressType)
|
||||
(2 begemotSnmpdTransInetAddress OCTETSTRING)
|
||||
(3 begemotSnmpdTransInetPort INTEGER)
|
||||
(4 begemotSnmpdTransInetProto BegemotSnmpdTransportProto)
|
||||
(5 begemotSnmpdTransInetStatus RowStatus GET SET)
|
||||
|
||||
))
|
||||
)
|
||||
(2 begemotSnmpdDefs
|
||||
(1 begemotSnmpdAgent
|
||||
(1 begemotSnmpdAgentFreeBSD OID op_dummy)
|
||||
)
|
||||
)
|
||||
(3 begemotSnmpdCompliance)
|
||||
)
|
||||
))
|
||||
)
|
||||
|
@ -129,4 +129,8 @@ MLINKS+= bsnmplib.3 snmp_value_copy.3
|
||||
MLINKS+= bsnmplib.3 snmp_value_free.3
|
||||
MLINKS+= bsnmplib.3 snmp_value_parse.3
|
||||
|
||||
FILESGROUPS+= DEFS
|
||||
DEFS= tc.def
|
||||
DEFSDIR?= ${SHAREDIR}/snmp/defs
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
@ -11,11 +11,11 @@ CONFS= snmpd.config
|
||||
CONFSMODE= 600
|
||||
PROG= bsnmpd
|
||||
SRCS= main.c action.c config.c export.c trap.c trans_udp.c trans_lsock.c
|
||||
SRCS+= oid.h tree.c tree.h
|
||||
SRCS+= trans_inet.c oid.h tree.c tree.h
|
||||
XSYM= snmpMIB begemotSnmpdModuleTable begemotSnmpd begemotTrapSinkTable \
|
||||
sysUpTime snmpTrapOID coldStart authenticationFailure \
|
||||
begemotSnmpdTransUdp begemotSnmpdTransLsock begemotSnmpdLocalPortTable \
|
||||
freeBSD freeBSDVersion
|
||||
freeBSD freeBSDVersion begemotSnmpdTransInet
|
||||
CLEANFILES= oid.h tree.c tree.h
|
||||
|
||||
MAN= bsnmpd.1 snmpmod.3
|
||||
|
@ -92,10 +92,22 @@ begemotSnmpdDebugSyslogPri = 7
|
||||
#
|
||||
begemotSnmpdCommunityString.0.1 = $(read)
|
||||
# begemotSnmpdCommunityString.0.2 = $(write)
|
||||
# begemotSnmpdCommunityString.0.3 = "otherPublic"
|
||||
begemotSnmpdCommunityDisable = 1
|
||||
|
||||
# open standard SNMP ports
|
||||
begemotSnmpdPortStatus.0.0.0.0.161 = 1
|
||||
begemotSnmpdTransInetStatus.1.4.0.0.0.0.161.1 = 4
|
||||
begemotSnmpdTransInetStatus.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.161.1 = 4
|
||||
|
||||
# UDP over IPv4: 127.0.0.1:161
|
||||
# begemotSnmpdTransInetStatus.1.4.127.0.0.1.161.1 = 4
|
||||
|
||||
# UDP over IPv6: ::1:161
|
||||
# begemotSnmpdTransInetStatus.2.16.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.161.1 = 4
|
||||
|
||||
# Use domain name and IPv6 link-local address with scope zone id as address
|
||||
# begemotSnmpdTransInetStatus.16."localhost".161.1 = 4
|
||||
# begemotSnmpdTransInetStatus.16."fe80::1%em0".161.1 = 4
|
||||
|
||||
# open a unix domain socket
|
||||
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
|
||||
|
Loading…
Reference in New Issue
Block a user