summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@nxc.no>2018-02-01 14:16:07 (GMT)
committer Sergey Poznyakoff <gray@nxc.no>2018-02-01 16:10:10 (GMT)
commit85f908426e444a596b979a9569bf83fadfa5ace1 (patch) (side-by-side diff)
tree7513334ef43be06b45f39f13ef9b6a3bf37931d8
parent94973146c58df26b20e17e2e5b1274216ca88969 (diff)
downloadvarnish-mib-85f908426e444a596b979a9569bf83fadfa5ace1.tar.gz
varnish-mib-85f908426e444a596b979a9569bf83fadfa5ace1.tar.bz2
Rewrite for Varnish 5.x
* configure.ac (AC_CHECK_VSC_C_MAIN_MEMBERS): Remove. * src/.gitignore: Update. * src/Makefile.am (varnish_mib_la_SOURCES): Add new sources. * src/backend.h: New file. * src/belex.l: New file. * src/statdict.c: New file. * src/ban.c: Rewrite. * src/betab.c: Rewrite. * src/varnish_mib.mib2c: Rewrite. * src/vcli.c: Rewrite.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac5
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/backend.h16
-rw-r--r--src/ban.c15
-rw-r--r--src/belex.l178
-rw-r--r--src/betab.c482
-rw-r--r--src/statdict.c172
-rw-r--r--src/varnish_mib.mib2c227
-rw-r--r--src/vcli.c69
10 files changed, 830 insertions, 338 deletions
diff --git a/configure.ac b/configure.ac
index cf0bf05..c334724 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# This file is part of Varnish-mib -*- autoconf -*-
-# Copyright (C) 2014-2016 Sergey Poznyakoff
+# Copyright (C) 2014-2018 Sergey Poznyakoff
#
# Varnish-mib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@ if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([could not find a C99 compatible compiler])
fi
AC_PROG_CPP
+AM_PROG_LEX
AC_PROG_INSTALL
AC_PROG_LIBTOOL
@@ -57,8 +58,6 @@ if test -n "$v"; then
IFS=$save_IFS
fi
-AC_CHECK_VSC_C_MAIN_MEMBERS
-
# Check for Net-SNMP
AC_PATH_PROG([NET_SNMP_CONFIG], net-snmp-config, none, $PATH)
if test "$NET_SNMP_CONFIG" = "none"; then
diff --git a/src/.gitignore b/src/.gitignore
index 61958b7..f40282a 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,2 +1,3 @@
varnish_mib.c
varnish_mib.h
+belex.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 48c786b..3a7f12a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,9 +20,12 @@ dlmod_LTLIBRARIES = varnish-mib.la
varnish_mib_la_SOURCES = \
auth.c\
ban.c\
+ backend.h\
+ belex.l\
betab.c\
sha256.c\
sha256.h\
+ statdict.c\
varnish_mib.c\
varnish_mib.h\
vcli.c
diff --git a/src/backend.h b/src/backend.h
new file mode 100644
index 0000000..0c15e60
--- a/dev/null
+++ b/src/backend.h
@@ -0,0 +1,16 @@
+typedef struct be_string {
+ char const *start;
+ size_t len;
+} be_string_t;
+
+typedef void (*regfun_t)(be_string_t *, be_string_t *, be_string_t *, void *);
+
+void read_defs(const char *str, size_t len, regfun_t regfun, void *d);
+void varnish_backend_table_timeout_parser(const char *token, char *line);
+struct VSC_point;
+void backend_register(char const *name, size_t len, char const *param,
+ const struct VSC_point *vpt);
+void backend_clear(void);
+int backend_collect_addr(void);
+void backend_parser(const char *str, size_t len, regfun_t regfun, void *d);
+
diff --git a/src/ban.c b/src/ban.c
index 26dc5f4..0c354e9 100644
--- a/src/ban.c
+++ b/src/ban.c
@@ -38,7 +38,7 @@ send_ban_cmd(vcli_conn_t *conn, const char *expr)
int
varnish_ban(netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests,
- struct VSM_data *vd)
+ struct vsm *vsm)
{
int rc;
struct vcli_conn conn;
@@ -52,7 +52,7 @@ varnish_ban(netsnmp_agent_request_info *reqinfo,
memcpy(expr, requests->requestvb->val.string, len);
expr[len] = 0;
DEBUGMSGTL(("varnish_ban", "setting ban %s\n", expr));
- rc = vcli_connect(vd, &conn);
+ rc = vcli_connect(vsm, &conn);
if (rc == SNMP_ERR_NOERROR) {
rc = send_ban_cmd(&conn, expr);
vcli_disconnect(&conn);
@@ -151,13 +151,14 @@ banTable_load(netsnmp_cache *cache, void *vmagic)
int rc;
struct vcli_conn conn;
char *p;
- struct VSM_data *vd;
+
+ struct vsm *vsm = varnish_get_vsm_data();
+ if (!vsm)
+ return SNMP_ERR_GENERR;
DEBUGMSGTL(("varnish_ban", "reloading ban table\n"));
- vd = varnish_get_vsm_data();
- if (!vd)
- return SNMP_ERR_NOSUCHNAME;
- rc = vcli_connect(vd, &conn);
+ rc = vcli_connect(vsm, &conn);
+
if (rc != SNMP_ERR_NOERROR)
return rc;
diff --git a/src/belex.l b/src/belex.l
new file mode 100644
index 0000000..f35f114
--- a/dev/null
+++ b/src/belex.l
@@ -0,0 +1,178 @@
+%option nounput
+%option noinput
+
+%{
+#include "backend.h"
+
+enum {
+ T_BOGUS = 256,
+ T_IDENT,
+ T_NUMBER,
+ T_STRING,
+ T_BACKEND,
+ T_HOST,
+ T_PORT
+};
+
+static char const *input_string;
+static size_t input_len;
+static size_t input_pos;
+static char const *string_start;
+static size_t current_pos;
+
+#define YY_INPUT(buf,result,max_size) \
+ do { \
+ size_t n = input_len - input_pos; \
+ if (n > max_size) \
+ n = max_size; \
+ memcpy(buf, input_string, n); \
+ input_pos += n; \
+ result = n; \
+ } while (0)
+
+#define YY_USER_ACTION \
+ current_pos += yyleng;
+
+#define YY_DECL static int yylex(void)
+static int yywrap(void);
+
+static char const *
+input_point(void)
+{
+ return input_string + current_pos;
+}
+
+#define YYSTYPE be_string_t
+#define YYSTYPE_INITIALIZER { NULL, 0 }
+
+static YYSTYPE yylval;
+%}
+
+%x COMMENT STR
+
+%%
+ /* C-style comments */
+"/*" BEGIN(COMMENT);
+<COMMENT>[^*]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/]* /* eat up '*'s not followed by '/'s */
+<COMMENT>"*"+"/" BEGIN(INITIAL);
+
+ /* Single-line comments */
+"//".*\n ;
+#.*\n ;
+
+ /* Multi-line strings */
+"{\"" { BEGIN(STR); string_start = input_point(); }
+<STR>[^\"]* /* eat anything that's not a '"' */
+<STR>"\""+[^"}]* /* eat up '"'s not followed by '}'s */
+<STR>"\""+"}" { BEGIN(INITIAL);
+ yylval.start = string_start;
+ yylval.len = input_point() - yylval.start - 2;
+ return T_STRING;
+ }
+ /* Single-line strings */
+\".*\" {
+ yylval.start = input_point() - yyleng + 1;
+ yylval.len = yyleng - 2;
+ return T_STRING;
+ }
+backend return T_BACKEND;
+".host" return T_HOST;
+".port" return T_PORT;
+"{"|"}"|"="|";" return yytext[0];
+
+[a-zA-Z_][a-zA-Z0-9_.]+ {
+ yylval.start = input_point() - yyleng;
+ yylval.len = yyleng;
+ return T_IDENT;
+ }
+[0-9]+ return T_NUMBER;
+
+[ \t\n]+ ;
+
+. return T_BOGUS;
+
+%%
+int
+yywrap(void)
+{
+ return 1;
+}
+
+static void
+set_input(char const *str, size_t len)
+{
+ input_string = str;
+ input_len = len;
+ input_pos = 0;
+ current_pos = 0;
+}
+
+static int brace_nesting;
+
+static void
+read_backend(regfun_t regfun, void *d)
+{
+ int c;
+ int in_statement;
+ YYSTYPE label, host = YYSTYPE_INITIALIZER, port = YYSTYPE_INITIALIZER;
+
+ if ((c = yylex()) != T_IDENT && c != T_STRING)
+ return;
+ label = yylval;
+ if ((c = yylex()) != '{')
+ return;
+ brace_nesting++;
+ in_statement = 0;
+ while (brace_nesting == 1) {
+ c = yylex();
+ if (c == 0)
+ break;
+ else if (c == '{')
+ brace_nesting++;
+ else if (c == '}')
+ brace_nesting++;
+ else if (in_statement) {
+ if (c == ';')
+ in_statement = 0;
+ } else {
+ in_statement = 1;
+ if (c == T_HOST || c == T_PORT) {
+ YYSTYPE *stk = c == T_HOST ? &host : &port;
+ in_statement = 1;
+ if ((c = yylex()) == '=') {
+ c = yylex();
+ if (c == T_STRING || c == T_IDENT) {
+ *stk = yylval;
+ }
+ }
+ }
+ }
+ }
+ regfun(&label, &host, &port, d);
+}
+
+void
+backend_parser(const char *str, size_t len, regfun_t regfun, void *d)
+{
+ int c;
+
+ set_input(str, len);
+
+ brace_nesting = 0;
+ while ((c = yylex())) {
+ if (brace_nesting == 0) {
+ if (c == T_BACKEND) {
+ read_backend(regfun, d);
+ }
+ }
+ switch (c) {
+ case '{':
+ brace_nesting++;
+ break;
+ case '}':
+ brace_nesting--;
+ break;
+ }
+ }
+}
diff --git a/src/betab.c b/src/betab.c
index 49e02f7..388083b 100644
--- a/src/betab.c
+++ b/src/betab.c
@@ -1,5 +1,5 @@
/* This file is part of varnish-mib
- Copyright (C) 2014 Sergey Poznyakoff
+ Copyright (C) 2014, 2018 Sergey Poznyakoff
Varnish-mib is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,73 +15,39 @@
along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
*/
#include "varnish_mib.h"
+#include <varnish/vas.h>
+#include <varnish/vqueue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
#include <arpa/inet.h>
+#include <netinet/in.h>
-unsigned backendTable_timeout = 5;
-
-void
-varnish_backend_table_timeout_parser(const char *token, char *line)
-{
- varnish_mib_timeout_parser(token, line, &backendTable_timeout);
-}
-
-/*
- * create a new row in the table
- */
-static struct backendTable_entry *
-create_entry(netsnmp_tdata *table_data, long idx,
- struct backendTable_entry *ent)
-{
- struct backendTable_entry *entry;
- netsnmp_tdata_row *row;
-
- entry = SNMP_MALLOC_TYPEDEF(struct backendTable_entry);
- if (!entry)
- return NULL;
-
- row = netsnmp_tdata_create_row();
- if (!row) {
- SNMP_FREE(entry);
- return NULL;
- }
- row->data = entry;
- *entry = *ent;
-
- entry->vbeIndex = idx;
- netsnmp_tdata_row_add_index(row, ASN_INTEGER,
- &entry->vbeIndex,
- sizeof(entry->vbeIndex));
- if (table_data)
- netsnmp_tdata_add_row(table_data, row);
- return entry;
-}
+#include "backend.h"
-#define VSC_POINT_TYPE(p) ((p)->section->fantom->type)
-#define VSC_POINT_IDENT(p) ((p)->section->fantom->ident)
-#define VSC_POINT_NAME(p) ((p)->desc->name)
-#if VARNISHAPI_MINOR == 0
-# define VSC_POINT_FMT(p) ((p)->desc->fmt)
-#elif VARNISHAPI_MINOR == 1
-# define VSC_POINT_FMT(p) ((p)->desc->ctype)
-#else
-# error "unsupported Varnish API minor number"
-#endif
-
-struct betab_priv {
- int err;
- long idx;
- struct backendTable_entry ent;
- netsnmp_tdata *table;
+enum {
+ vbeHappyProbes,
+ vbeRequestHeaderBytes,
+ vbeRequestBodyBytes,
+ vbeResponseHeaderBytes,
+ vbeResponseBodyBytes,
+ vbePipeHeaderBytes,
+ vbePipeIn,
+ vbePipeOut,
+ VBE_MAX
};
struct betab_trans {
- const char *name;
+ char const *param;
size_t off;
};
-static struct betab_trans betab_trans[] = {
+/*
{ "vcls",
offsetof(struct backendTable_entry, vbeVcls) },
+*/
+
+static struct betab_trans betab_trans[] = {
{ "happy",
offsetof(struct backendTable_entry, vbeHappyProbes) },
{ "bereq_hdrbytes",
@@ -101,168 +67,308 @@ static struct betab_trans betab_trans[] = {
{ NULL }
};
-static int
-identcmp(struct betab_priv *bp, const char *ident)
-{
- size_t len;
- size_t i;
+struct backend_dfn {
+ long vbeIndex;
+
+ char *vbeIdent;
+ size_t vbeIdent_len;
+
+ char vbeIPv4[4];
+ size_t vbeIPv4_len;
+ char vbeIPv6[16];
+ size_t vbeIPv6_len;
+ u_long vbePort;
- if (bp->idx == -1)
- return 1;
- for (i = 0; i < bp->ent.vbeIdent_len; i++, ident++)
- if (bp->ent.vbeIdent[i] != *ident)
- return 1;
- if (*ident == '(' || *ident == 0)
- return 0;
- return 1;
-}
+ const struct VSC_point *vpt[VBE_MAX];
+
+ VTAILQ_ENTRY(backend_dfn) list;
+};
-static void
-uint32_to_bytes (unsigned char *bytes, uint32_t u)
-{
- int i;
+static VTAILQ_HEAD(, backend_dfn) backends
+ = VTAILQ_HEAD_INITIALIZER(backends);
- for (i = 0; i < 4; i++)
- {
- bytes[i] = u & 0xff;
- u >>= 8;
- }
+void
+backend_clear(void)
+{
+ while (!VTAILQ_EMPTY(&backends)) {
+ struct backend_dfn *dfn = VTAILQ_FIRST(&backends);
+ VTAILQ_REMOVE(&backends, dfn, list);
+ free(dfn->vbeIdent);
+ SNMP_FREE(dfn);
+ }
}
-static void
-scanbuf(const char *s, struct backendTable_entry *ent)
+void
+backend_register(char const *name, size_t len, char const *param,
+ const struct VSC_point *vpt)
{
- char ipv4buf[16];
- char ipv6buf[81];
- unsigned long port;
- char *p;
- union {
- struct in_addr in;
- struct in6_addr in6;
- } v;
+ int i = 0;
+ struct backend_dfn *dfn;
- if (*s != '(')
- return;
- ++s;
- p = ipv4buf;
- while (p < ipv4buf + sizeof(ipv4buf) && *s && *s != ',')
- *p++ = *s++;
- if (*s != ',')
- return;
- *p = 0;
+ VTAILQ_FOREACH(dfn, &backends, list) {
+ if (dfn->vbeIdent_len == len
+ && memcmp(dfn->vbeIdent, name, len) == 0)
+ break;
+ i++;
+ }
+ if (!dfn) {
+ dfn = SNMP_MALLOC_TYPEDEF(struct backend_dfn);
+ AN(dfn);
+ dfn->vbeIndex = i;
+ dfn->vbeIdent = malloc(len + 1);
+ AN(dfn->vbeIdent);
+ memcpy(dfn->vbeIdent, name, len);
+ dfn->vbeIdent[len] = 0;
+ dfn->vbeIdent_len = len;
+ VTAILQ_INSERT_TAIL(&backends, dfn, list);
+ }
+ for (i = 0; betab_trans[i].param; i++) {
+ if (strcmp(betab_trans[i].param, param) == 0) {
+ dfn->vpt[i] = vpt;
+ break;
+ }
+ }
+}
- ++s;
- p = ipv6buf;
- while (p < ipv6buf + sizeof(ipv6buf) && *s && *s != ',')
- *p++ = *s++;
- *p = 0;
+int
+backendTable_load(netsnmp_cache *cache, void *vmagic)
+{
+ netsnmp_tdata *table_data = (netsnmp_tdata *) vmagic;
+ struct backend_dfn *dfn;
- ++s;
- port = strtoul(s, &p, 10);
- if (*p != ')' || port > USHRT_MAX)
- return;
+ DEBUGMSGTL(("varnish_backend", "loading backend table\n"));
+
+ VTAILQ_FOREACH(dfn, &backends, list) {
+ int i;
+
+ netsnmp_tdata_row *row;
+ struct backendTable_entry *ent;
+
+ ent = SNMP_MALLOC_TYPEDEF(struct backendTable_entry);
+ ent->vbeIndex = dfn->vbeIndex;
+ ent->vbeIdent = malloc(dfn->vbeIdent_len);
+ memcpy(ent->vbeIdent, dfn->vbeIdent, dfn->vbeIdent_len);
+ ent->vbeIdent_len = dfn->vbeIdent_len;
+ memset(ent->vbeIPv4, 0, sizeof ent->vbeIPv4);
+
+ memcpy(ent->vbeIPv4, dfn->vbeIPv4, dfn->vbeIPv4_len);
+ ent->vbeIPv4_len = dfn->vbeIPv4_len;
+ memcpy(ent->vbeIPv6, dfn->vbeIPv6, ent->vbeIPv6_len);
+ ent->vbeIPv6_len = dfn->vbeIPv6_len;
+ ent->vbePort = dfn->vbePort;
+
+ for (i = 0; i < VBE_MAX; i++) {
+ U64 *u = (U64*)((char*)ent + betab_trans[i].off);
+ uint64_t n = *(const volatile uint64_t*)dfn->vpt[i]->ptr;
+ u->high = n >> 32;
+ u->low = n & 0xffffffff;
+ }
+
+ row = netsnmp_tdata_create_row();
+ if (!row)
+ break;
+ row->data = ent;
+ netsnmp_tdata_row_add_index(row, ASN_INTEGER,
+ &ent->vbeIndex,
+ sizeof(ent->vbeIndex));
+ netsnmp_tdata_add_row(table_data, row);
+ }
+ return 0;
+}
+
+void
+backendTable_free(netsnmp_cache *cache, void *vmagic)
+{
+ netsnmp_tdata *table = (netsnmp_tdata *) vmagic;
+ netsnmp_tdata_row *row;
- if (ipv4buf[0] && inet_pton(AF_INET, ipv4buf, &v)) {
- ent->vbeIPv4_len = 4;
- uint32_to_bytes(ent->vbeIPv4, v.in.s_addr);
+ DEBUGMSGTL(("varnish_backend", "freeing backend table\n"));
+ while ((row = netsnmp_tdata_row_first(table))) {
+ struct backendTable_entry *entry = row->data;
+ free(entry->vbeIdent);
+ SNMP_FREE(entry);
+ netsnmp_tdata_remove_and_delete_row(table, row);
}
+}
+
+unsigned backendTable_timeout = 5;
+
+void
+varnish_backend_table_timeout_parser(const char *token, char *line)
+{
+ varnish_mib_timeout_parser(token, line, &backendTable_timeout);
+}
+
+static struct backend_dfn *
+dfn_lookup(be_string_t *vclname, be_string_t *label)
+{
+ size_t namelen;
+ struct backend_dfn *dfn;
- if (ipv6buf[0] && inet_pton(AF_INET6, ipv6buf, &v)) {
- ent->vbeIPv6_len = 16;
- memcpy(ent->vbeIPv6, &v, ent->vbeIPv6_len);
+ namelen = vclname->len + label->len + 1;
+ VTAILQ_FOREACH(dfn, &backends, list) {
+ if (dfn->vbeIdent_len == namelen
+ && memcmp(dfn->vbeIdent, vclname->start, vclname->len) == 0
+ && dfn->vbeIdent[vclname->len] == '.'
+ && memcmp(dfn->vbeIdent + vclname->len + 1,
+ label->start, label->len) == 0)
+ return dfn;
}
- ent->vbePort = port;
-}
-
-/* Process a single statistics point. See comment below. */
-static int
-create_entry_cb(void *priv, const struct VSC_point *const pt)
+ return NULL;
+}
+
+static u_long
+to_port(be_string_t *str)
{
- struct betab_priv *bp = priv;
- struct betab_trans *tp;
-
- if (bp->err || !pt || strcmp(VSC_POINT_TYPE(pt), "VBE") ||
- strcmp(VSC_POINT_FMT(pt), "uint64_t"))
- return 0;
- if (identcmp(bp, VSC_POINT_IDENT(pt))) {
- const char *full_id;
-
- if (bp->idx != -1
- && !create_entry(bp->table, bp->idx, &bp->ent)) {
- snmp_log(LOG_ERR, "out of memory\n");
- bp->err = SNMP_ERR_GENERR;
+ int i;
+ u_long v = 0;
+ for (i = 0; i < str->len; i++) {
+ static char dig[] = "0123456789";
+ char *p = strchr(dig, str->start[i]);
+ if (!p)
return 0;
- }
+ v = v * 10 + p - dig;
+ }
+ return v;
+}
- memset(&bp->ent, 0, sizeof(bp->ent));
- bp->ent.vbeIndex = ++bp->idx;
+static void
+uint32_to_bytes (unsigned char *bytes, uint32_t u)
+{
+ int i;
- full_id = VSC_POINT_IDENT(pt);
- bp->ent.vbeIdent_len = strcspn(full_id, "(");
- bp->ent.vbeIdent = malloc(bp->ent.vbeIdent_len);
- if (!bp->ent.vbeIdent) {
- snmp_log(LOG_ERR, "out of memory\n");
- bp->err = SNMP_ERR_GENERR;
- return 0;
- }
- memcpy(bp->ent.vbeIdent, full_id, bp->ent.vbeIdent_len);
- full_id += bp->ent.vbeIdent_len;
- scanbuf(full_id, &bp->ent);
+ for (i = 0; i < 4; i++) {
+ bytes[i] = u & 0xff;
+ u >>= 8;
}
+}
- for (tp = betab_trans; tp->name; tp++) {
- if (strcmp(VSC_POINT_NAME(pt), tp->name) == 0) {
- U64 *u = (U64*)((char*)&bp->ent + tp->off);
- uint64_t n = *(const volatile uint64_t*)pt->ptr;
- u->high = n >> 32;
- u->low = n & 0xffffffff;
- break;
+static void
+update_dfn(be_string_t *label, be_string_t *host, be_string_t *port,
+ void *data)
+{
+ struct backend_dfn *dfn;
+
+ dfn = dfn_lookup(data, label);
+ if (!dfn)
+ return;
+ dfn->vbePort = to_port(port);
+ if (host->len) {
+ struct addrinfo *res, *ap;
+ int rc;
+ char *node;
+
+ node = malloc(host->len+1);
+ AN(node);
+ memcpy(node, host->start, host->len);
+ node[host->len] = 0;
+ rc = getaddrinfo(node, NULL, NULL, &res);
+ free(node);
+ if (rc)
+ return;
+ for (ap = res; ap; ap = ap->ai_next) {
+ if (ap->ai_addr->sa_family == AF_INET) {
+ if (dfn->vbeIPv4_len == 0) {
+ struct sockaddr_in *s =
+ (struct sockaddr_in *)ap->ai_addr;
+ uint32_to_bytes((unsigned char*)dfn->vbeIPv4,
+ s->sin_addr.s_addr);
+ dfn->vbeIPv4_len = 4;
+ }
+ } else if (ap->ai_addr->sa_family == AF_INET6) {
+ if (dfn->vbeIPv4_len == 0) {
+ struct sockaddr_in6 *s =
+ (struct sockaddr_in6 *)ap->ai_addr;
+ dfn->vbeIPv6_len = 16;
+ memcpy(dfn->vbeIPv6, &s->sin6_addr,
+ dfn->vbeIPv6_len);
+ }
+ }
}
+ freeaddrinfo(res);
}
- return 0;
}
-/* Varnish API does not provide access to struct VSC_C_vbe, so the only
- way to backend statistics is to iterate over all statistics data, selecting
- the entries marked as VBE. That's what this function does.
- */
-int
-backendTable_load(netsnmp_cache *cache, void *vmagic)
+static int
+backend_parse(struct vcli_conn *conn, be_string_t *name)
{
- struct betab_priv bp;
- struct VSM_data *vd = varnish_get_vsm_data();
+ if (vcli_asprintf(conn, "vcl.show %*.*s\n",
+ (int)name->len, (int)name->len,
+ name->start)
+ || vcli_write(conn))
+ return SNMP_ERR_GENERR;
- if (!vd)
- return SNMP_ERR_NOSUCHNAME;
+ if (vcli_read_response(conn))
+ return SNMP_ERR_GENERR;
- bp.idx = -1;
- bp.err = 0;
- bp.table = (netsnmp_tdata *) vmagic;
- memset(&bp.ent, 0, sizeof(bp.ent));
-
- DEBUGMSGTL(("varnish_ban", "loading backend table\n"));
- VSC_Iter(vd, NULL, create_entry_cb, &bp);
- /* FIXME: perhaps handle bp.err separately */
- if (bp.idx != -1) {
- DEBUGMSGTL(("varnish_ban", "loaded %lu backend entries\n",
- bp.idx + 1));
- if (!create_entry(bp.table, bp.idx, &bp.ent))
- snmp_log(LOG_ERR, "out of memory\n");
+ if (conn->resp != CLIS_OK) {
+ snmp_log(LOG_ERR, "vcl.show command rejected: %u %s\n",
+ conn->resp, conn->base);
+ return SNMP_ERR_GENERR;
}
+ backend_parser(conn->base, conn->bufsize, update_dfn, name);
return 0;
}
+
+struct backend_name {
+ be_string_t str;
+ VTAILQ_ENTRY(backend_name) list;
+};
+VTAILQ_HEAD(backend_name_list, backend_name);
-void
-backendTable_free(netsnmp_cache *cache, void *vmagic)
+static void
+backend_name_add(struct backend_name_list *namelist,
+ char const *str, size_t len)
{
- netsnmp_tdata *table = (netsnmp_tdata *) vmagic;
- netsnmp_tdata_row *row;
+ struct backend_name *name;
+ VTAILQ_FOREACH(name, namelist, list) {
+ if (name->str.len == len
+ && memcmp(name->str.start, str, len) == 0)
+ return;
+ }
+ name = SNMP_MALLOC_TYPEDEF(struct backend_name);
+ AN(name);
+ name->str.start = str;
+ name->str.len = len;
+ VTAILQ_INSERT_TAIL(namelist, name, list);
+}
- DEBUGMSGTL(("varnish_ban", "freeing backend table\n"));
- while ((row = netsnmp_tdata_row_first(table))) {
- struct backendTable_entry *entry = row->data;
- free(entry->vbeIdent);
- SNMP_FREE(entry);
- netsnmp_tdata_remove_and_delete_row(table, row);
+int
+backend_collect_addr(void)
+{
+ struct backend_dfn *dfn;
+ struct vcli_conn conn;
+ struct vsm *vsm;
+ int rc;
+ struct backend_name_list namelist
+ = VTAILQ_HEAD_INITIALIZER(namelist);
+
+ vsm = varnish_get_vsm_data();
+ if (!vsm)
+ return SNMP_ERR_GENERR;
+ DEBUGMSGTL(("varnish_backend", "getting backend info\n"));
+
+ rc = vcli_connect(vsm, &conn);
+ if (rc != SNMP_ERR_NOERROR)
+ return rc;
+
+ /* Select backend names */
+ VTAILQ_FOREACH(dfn, &backends, list) {
+ int i;
+ for (i = 0; i < dfn->vbeIdent_len; i++)
+ if (dfn->vbeIdent[i] == '.')
+ break;
+ if (i == dfn->vbeIdent_len)
+ continue;
+ backend_name_add(&namelist, dfn->vbeIdent, i);
}
+
+ while (!VTAILQ_EMPTY(&namelist)) {
+ struct backend_name *name = VTAILQ_FIRST(&namelist);
+ VTAILQ_REMOVE(&namelist, name, list);
+ backend_parse(&conn, &name->str);
+ }
+
+ vcli_disconnect(&conn);
+ return 0;
}
diff --git a/src/statdict.c b/src/statdict.c
new file mode 100644
index 0000000..e87123b
--- a/dev/null
+++ b/src/statdict.c
@@ -0,0 +1,172 @@
+/* This file is part of varnish-mib
+ Copyright (C) 2018 Sergey Poznyakoff
+
+ Varnish-mib is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Varnish-mib is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <vapi/vsc.h>
+#include <vapi/vsm.h>
+#include <vas.h>
+#include <vcli.h>
+#include "backend.h"
+
+static size_t hash_size[] = {
+ 7, 17, 37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411
+};
+static size_t hash_num = 0;
+static struct VSC_point **dict;
+
+#define SIZE_T_MAX ((size_t)-1)
+
+static inline size_t
+rotl(size_t x, int n)
+{
+ return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_T_MAX;
+}
+
+static size_t
+hash(const char *str)
+{
+ size_t value = 0;
+ unsigned char ch;
+
+ while ((ch = *str++))
+ value = ch + rotl(value, 7);
+ return value % hash_size[hash_num];
+}
+
+struct VSC_point **lookup(const char *name, int install);
+
+static void
+rehash(void)
+{
+ struct VSC_point **old_dict = dict;
+ size_t old_size = hash_size[hash_num];
+ size_t i;
+
+ ++hash_num;
+ AN(hash_num < sizeof(hash_size) / sizeof(hash_size[0]));
+ dict = calloc(hash_size[hash_num], sizeof(dict[0]));
+ AN(dict);
+
+ for (i = 0; i < old_size; i++) {
+ if (old_dict[i])
+ *lookup(old_dict[i]->name, 1) = old_dict[i];
+ }
+ free(old_dict);
+}
+
+struct VSC_point **
+lookup(const char *name, int install)
+{
+ size_t i, pos;
+
+ if (!dict) {
+ if (install) {
+ dict = calloc(hash_size[hash_num], sizeof(dict[0]));
+ AN(dict);
+ } else
+ return NULL;
+ }
+
+ pos = hash(name);
+
+ for (i = pos; dict[i];) {
+ if (strcmp(dict[i]->name, name) == 0) {
+ return &dict[i];
+ }
+
+ if (++i >= hash_size[hash_num])
+ i = 0;
+ if (i == pos)
+ break;
+ }
+
+ if (!install)
+ return NULL;
+
+ if (!dict[i])
+ return &dict[i];
+
+ rehash();
+ return lookup(name, install);
+}
+
+int
+dict_lookup(char const *key, uint64_t *val)
+{
+ struct VSC_point **ent;
+
+ ent = lookup(key, 0);
+ if (!ent) {
+ fprintf(stderr, "%s NOT FOUND\n", key);
+ }
+ if (!ent)
+ return -1;
+ *val = *(uint64_t*)(*ent)->ptr;
+ return 0;
+}
+
+void
+dict_clear(void)
+{
+ if (dict) {
+ size_t i;
+ for (i = 0; i < hash_size[hash_num]; i++)
+ if (dict[i])
+ VSC_Destroy_Point(&dict[i]);
+ }
+}
+
+struct VSC_point const *
+dict_install(struct VSC_point const *pt)
+{
+ struct VSC_point **ent;
+
+ ent = lookup(pt->name, 1);
+ AN(ent);
+ if (*ent)
+ VSC_Destroy_Point(ent);
+ *ent = VSC_Clone_Point(pt);
+ return *ent;
+}
+
+static int
+load_cb(void *priv, const struct VSC_point *vpt)
+{
+ AZ(strcmp(vpt->ctype, "uint64_t"));
+ vpt = dict_install(vpt);
+ if (strncmp(vpt->name, "VBE.", 4) == 0) {
+ char const *name = vpt->name + 4;
+ char *p = strrchr(name, '.');
+ if (p) {
+ backend_register(name, p - name, p + 1, vpt);
+ }
+ }
+ return 0;
+}
+
+void
+dict_load(struct vsc *vsc)
+{
+ struct vsm_fantom fantom = VSM_FANTOM_NULL;
+ dict_clear();
+ backend_clear();
+ VSC_Iter(vsc, &fantom, load_cb, NULL);
+ backend_collect_addr();
+}
diff --git a/src/varnish_mib.mib2c b/src/varnish_mib.mib2c
index 9d49ce9..a458723 100644
--- a/src/varnish_mib.mib2c
+++ b/src/varnish_mib.mib2c
@@ -1,5 +1,5 @@
# This file is part of varnish-mib -*- c -*-
-# Copyright (C) 2014-2016 Sergey Poznyakoff
+# Copyright (C) 2014-2018 Sergey Poznyakoff
#
# Varnish-mib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,80 +25,79 @@
@enddefine@
@startperl@
$vars{'varnish_translate_table'} = {
- uptime => [ 'MAIN', 'uptime' ],
- clientAcceptedConnections => [ 'MAIN', 'sess_conn' ],
- clientRequestsReceived => [ 'MAIN', 'client_req' ],
- clientCacheHits => [ 'MAIN', 'cache_hit' ],
- clientCacheHitsPass => [ 'MAIN', 'cache_hitpass' ],
- clientCacheMisses => [ 'MAIN', 'cache_miss' ],
+ uptime => [ 'DICT', 'MAIN.uptime' ],
+ clientAcceptedConnections => [ 'DICT', 'MAIN.sess_conn' ],
+ clientCacheHits => [ 'DICT', 'MAIN.cache_hit' ],
+ clientCacheHitsPass => [ 'DICT', 'MAIN.cache_hitpass' ],
+ clientCacheMisses => [ 'DICT', 'MAIN.cache_miss' ],
clientBan => [ 'STRING', '',
{ varnish_set_action => 'varnish_ban' } ],
- clientRequestsReceived => [ 'MAIN', 'client_req' ],
- clientRequests400 => [ 'MAIN', 'client_req_400' ],
- clientRequests411 => [ 'MAIN', 'client_req_411' ],
- clientRequests413 => [ 'MAIN', 'client_req_413' ],
- clientRequests417 => [ 'MAIN', 'client_req_417' ],
+ clientRequestsReceived => [ 'DICT', 'MAIN.client_req' ],
+ clientRequests400 => [ 'DICT', 'MAIN.client_req_400' ],
+ clientRequests411 => [ 'NULL', 'MAIN.client_req_411' ],
+ clientRequests413 => [ 'NULL', 'MAIN.client_req_413' ],
+ clientRequests417 => [ 'DICT', 'MAIN.client_req_417' ],
- backendConnSuccess => [ 'MAIN', 'backend_conn' ],
- backendConnNotAttempted => [ 'MAIN', 'backend_unhealthy' ],
- backendConnToMany => [ 'MAIN', 'backend_busy' ],
- backendConnFailures => [ 'MAIN', 'backend_fail' ],
- backendConnReuses => [ 'MAIN', 'backend_reuse' ],
- backendConnRecycled => [ 'MAIN', 'backend_recycle' ],
- backendConnUnused => [ 'MAIN', 'backend_toolate' ],
- backendConnRetry => [ 'MAIN', 'backend_retry' ],
- backendRequests => [ 'MAIN', 'backend_req' ],
+ backendConnSuccess => [ 'DICT', 'MAIN.backend_conn' ],
+ backendConnNotAttempted => [ 'DICT', 'MAIN.backend_unhealthy' ],
+ backendConnToMany => [ 'DICT', 'MAIN.backend_busy' ],
+ backendConnFailures => [ 'DICT', 'MAIN.backend_fail' ],
+ backendConnReuses => [ 'DICT', 'MAIN.backend_reuse' ],
+ backendConnRecycled => [ 'DICT', 'MAIN.backend_recycle' ],
+ backendConnUnused => [ 'NULL', 'MAIN.backend_toolate' ],
+ backendConnRetry => [ 'DICT', 'MAIN.backend_retry' ],
+ backendRequests => [ 'DICT', 'MAIN.backend_req' ],
- totalSessions => [ 'MAIN', 's_sess' ],
- totalRequests => [ 'MAIN', 's_req' ],
- totalPipe => [ 'MAIN', 's_pipe' ],
- totalPass => [ 'MAIN', 's_pass' ],
- totalFetch => [ 'MAIN', 's_fetch' ],
- totalRequestHeaderBytes => [ 'MAIN', 's_req_hdrbytes' ],
- totalRequestBodyBytes => [ 'MAIN', 's_req_bodybytes' ],
- totalResponseHeaderBytes => [ 'MAIN', 's_resp_hdrbytes' ],
- totalResponseBodyBytes => [ 'MAIN', 's_resp_bodybytes' ],
- totalPipeHeaderBytes => [ 'MAIN', 's_pipe_hdrbytes' ],
- totalPipeIn => [ 'MAIN', 's_pipe_in' ],
- totalPipeOut => [ 'MAIN', 's_pipe_out' ],
+ totalSessions => [ 'DICT', 'MAIN.s_sess' ],
+ totalRequests => [ 'DICT', 'MAIN.client_req' ],
+ totalPipe => [ 'DICT', 'MAIN.s_pipe' ],
+ totalPass => [ 'DICT', 'MAIN.s_pass' ],
+ totalFetch => [ 'DICT', 'MAIN.s_fetch' ],
+ totalRequestHeaderBytes => [ 'DICT', 'MAIN.s_req_hdrbytes' ],
+ totalRequestBodyBytes => [ 'DICT', 'MAIN.s_req_bodybytes' ],
+ totalResponseHeaderBytes => [ 'DICT', 'MAIN.s_resp_hdrbytes' ],
+ totalResponseBodyBytes => [ 'DICT', 'MAIN.s_resp_bodybytes' ],
+ totalPipeHeaderBytes => [ 'DICT', 'MAIN.s_pipe_hdrbytes' ],
+ totalPipeIn => [ 'DICT', 'MAIN.s_pipe_in' ],
+ totalPipeOut => [ 'DICT', 'MAIN.s_pipe_out' ],
- sessAccepted => [ 'MAIN', 'sess_conn'],
- sessQueued => [ 'MAIN', 'sess_queued'],
- sessDropped => [ 'MAIN', 'sess_dropped'],
- sessClosed => [ 'MAIN', 'sess_closed'],
- sessPipeline => [ 'MAIN', 'sess_pipeline'],
- sessReadAhead => [ 'MAIN', 'sess_readahead'],
- sessHerd => [ 'MAIN', 'sess_herd'],
- sessDrop => [ 'MAIN', 'sess_drop'],
- sessFail => [ 'MAIN', 'sess_fail'],
- sessPipeOverflow => [ 'MAIN', 'sess_pipe_overflow'],
-
- threadsPools => [ 'MAIN', 'pools'],
- threadsTotal => [ 'MAIN', 'threads'],
- threadsLimitHits => [ 'MAIN', 'threads_limited'],
- threadsCreated => [ 'MAIN', 'threads_created'],
- threadsDestroyed => [ 'MAIN', 'threads_destroyed'],
- threadsFailed => [ 'MAIN', 'threads_failed'],
- threadsQueueLength => [ 'MAIN', 'thread_queue_len'],
-
- bansTotal => [ 'MAIN', 'bans' ],
- bansCompleted => [ 'MAIN', 'bans_completed' ],
- bansObj => [ 'MAIN', 'bans_obj' ],
- bansReq => [ 'MAIN', 'bans_req' ],
- bansAdded => [ 'MAIN', 'bans_added' ],
- bansDeleted => [ 'MAIN', 'bans_deleted' ],
- bansTested => [ 'MAIN', 'bans_tested' ],
- bansObjectsKilled => [ 'MAIN', 'bans_obj_killed' ],
- bansLurkerTested => [ 'MAIN', 'bans_lurker_tested' ],
- bansTestTested => [ 'MAIN', 'bans_tests_tested' ],
- bansLurkerTestTested => [ 'MAIN', 'bans_lurker_tests_tested' ],
- bansLurkerObjKilled => [ 'MAIN', 'bans_lurker_obj_killed' ],
- bansDups => [ 'MAIN', 'bans_dups' ],
- bansLurkerContention => [ 'MAIN', 'bans_lurker_contention' ],
- bansPersistedBytes => [ 'MAIN', 'bans_persisted_bytes' ],
- bansPersistedFragmentation => [ 'MAIN', 'bans_persisted_fragmentation' ],
+ sessAccepted => [ 'DICT', 'MAIN.sess_conn'],
+ sessQueued => [ 'DICT', 'MAIN.sess_queued'],
+ sessDropped => [ 'DICT', 'MAIN.sess_dropped'],
+ sessClosed => [ 'DICT', 'MAIN.sess_closed'],
+ sessPipeline => [ 'DICT', 'MAIN.s_pipe'],
+ sessReadAhead => [ 'DICT', 'MAIN.sess_readahead'],
+ sessHerd => [ 'DICT', 'MAIN.sess_herd'],
+ sessDrop => [ 'DICT', 'MAIN.sess_drop'],
+ sessFail => [ 'DICT', 'MAIN.sess_fail'],
+ sessPipeOverflow => [ 'DICT', 'MAIN.sc_pipe_overflow'],
+
+ threadsPools => [ 'DICT', 'MAIN.pools'],
+ threadsTotal => [ 'DICT', 'MAIN.threads'],
+ threadsLimitHits => [ 'DICT', 'MAIN.threads_limited'],
+ threadsCreated => [ 'DICT', 'MAIN.threads_created'],
+ threadsDestroyed => [ 'DICT', 'MAIN.threads_destroyed'],
+ threadsFailed => [ 'DICT', 'MAIN.threads_failed'],
+ threadsQueueLength => [ 'DICT', 'MAIN.thread_queue_len'],
+
+ bansTotal => [ 'DICT', 'MAIN.bans' ],
+ bansCompleted => [ 'DICT', 'MAIN.bans_completed' ],
+ bansObj => [ 'DICT', 'MAIN.bans_obj' ],
+ bansReq => [ 'DICT', 'MAIN.bans_req' ],
+ bansAdded => [ 'DICT', 'MAIN.bans_added' ],
+ bansDeleted => [ 'DICT', 'MAIN.bans_deleted' ],
+ bansTested => [ 'DICT', 'MAIN.bans_tested' ],
+ bansObjectsKilled => [ 'DICT', 'MAIN.bans_obj_killed' ],
+ bansLurkerTested => [ 'DICT', 'MAIN.bans_lurker_tested' ],
+ bansTestTested => [ 'DICT', 'MAIN.bans_tests_tested' ],
+ bansLurkerTestTested => [ 'DICT', 'MAIN.bans_lurker_tests_tested' ],
+ bansLurkerObjKilled => [ 'DICT', 'MAIN.bans_lurker_obj_killed' ],
+ bansDups => [ 'DICT', 'MAIN.bans_dups' ],
+ bansLurkerContention => [ 'DICT', 'MAIN.bans_lurker_contention' ],
+ bansPersistedBytes => [ 'DICT', 'MAIN.bans_persisted_bytes' ],
+ bansPersistedFragmentation => [ 'DICT', 'MAIN.bans_persisted_fragmentation' ],
};
@@ -118,13 +117,6 @@ $vars{'varnish_translate'} = sub {
} else {
delete $vars{$setkw};
}
- if ($vars{'varnish_type'} eq 'MAIN') {
- $vars{'varnish_if'} = "#if HAVE_STRUCT_VSC_C_MAIN_" . uc($vars{'varnish_member'});
- $vars{'varnish_endif'} = '#endif';
- } else {
- delete $vars{'varnish_if'};
- delete $vars{'varnish_endif'}
- }
return 0;
};
@@ -176,16 +168,16 @@ int vcli_read_response(vcli_conn_t *conn);
int vcli_vasprintf(vcli_conn_t *conn, const char *fmt, va_list ap);
int vcli_asprintf(vcli_conn_t *conn, const char *fmt, ...);
void vcli_disconnect(vcli_conn_t *conn);
-int vcli_connect(struct VSM_data *vd, vcli_conn_t *conn);
+int vcli_connect(struct vsm *vsm, vcli_conn_t *conn);
-struct VSM_data *varnish_get_vsm_data(void);
+struct vsm *varnish_get_vsm_data(void);
int varnish_auth_response(const char *file, const char *challenge,
char response[CLI_AUTH_RESPONSE_LEN + 1]);
int varnish_ban(netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests,
- struct VSM_data *vd);
+ struct vsm *vsm);
int varnish_mib_timeout_parser(const char *token, char *line,
unsigned *retval);
@@ -193,36 +185,49 @@ int varnish_mib_timeout_parser(const char *token, char *line,
void varnish_ban_table_timeout_parser(const char *token, char *line);
void varnish_vcli_timeout_parser(const char *token, char *line);
-void varnish_backend_table_timeout_parser(const char *token, char *line);
+int dict_lookup(char const *key, uint64_t *val);
+void dict_install(struct VSC_point const *pt);
+void dict_load(struct vsc *vsc);
@open ${name}@
/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */
#include "varnish_mib.h"
+#include "backend.h"
-static struct VSM_data *vd;
+static struct vsm *vd;
+static struct vsc *vsc;
void
varnish_snmp_init(void)
{
- vd = VSM_New();
+ vd = VSM_New();
+ if (vd) {
+ vsc = VSC_New(vd);
+ if (vsc) {
+ if (VSM_Attach(vd, 2))
+ fprintf(stderr, "%s\n", VSM_Error(vd));
+ }
+ }
+ dict_load(vsc);
}
void
varnish_snmp_deinit(void)
{
- VSM_Close(vd);
+ /* FIXME? */
}
-struct VSM_data *
+struct vsm *
varnish_get_vsm_data()
{
- if (VSM_Abandoned(vd)) {
- DEBUGMSGTL(("$modulename", "reopening vd\n"));
- VSM_Close(vd);
- VSM_Open(vd);
- }
- return vd;
+ if (vd) {
+ if (VSM_Status(vd) & (VSM_MGT_CHANGED|VSM_WRK_CHANGED)) {
+ DEBUGMSGTL(("$modulename", "reopening vd\n"));
+ dict_load(vsc);
+ }
+ }
+ return vd;
}
/* Variable handlers.
@@ -251,24 +256,24 @@ handle_$i(netsnmp_mib_handler *handler,
switch(reqinfo->mode) {
case MODE_GET:
- @if $varnish_type eq 'MAIN'@
- {
- struct VSC_C_main const *st = VSC_Main(vd, NULL);
+ @if $varnish_type eq 'DICT'@
+ {
+ uint64_t val;
+ if (dict_lookup("$varnish_member", &val))
+ return SNMP_ERR_NOSUCHNAME;
@if $i.type eq 'ASN_COUNTER64'@
+ {
struct counter64 ctr;
- if (!st)
- return SNMP_ERR_NOSUCHNAME;
- ctr.high = st->$varnish_member >> 32;
- ctr.low = st->$varnish_member & 0xffffffff;
+ ctr.high = val >> 32;
+ ctr.low = val & 0xffffffff;
snmp_set_var_typed_value(requests->requestvb, $i.type,
&ctr,
sizeof(ctr));
+ }
@else@
- if (!st)
- return SNMP_ERR_NOSUCHNAME;
snmp_set_var_typed_value(requests->requestvb, $i.type,
- &st->$varnish_member,
- sizeof(st->$varnish_member));
+ &val,
+ sizeof(val));
@end@
}
@elsif $varnish_type eq 'STRING'@
@@ -297,6 +302,20 @@ handle_$i(netsnmp_mib_handler *handler,
snmp_set_var_typed_value(requests->requestvb, $i.type,
&$varnish_member, sizeof($varnish_member));
@end@
+ @elsif $varnish_type eq 'NULL'@
+ {
+ @if $i.type eq 'ASN_COUNTER64'@
+ struct counter64 ctr = { 0, 0};
+ snmp_set_var_typed_value(requests->requestvb, $i.type,
+ &ctr,
+ sizeof(ctr));
+ @else@
+ uint64_t val;
+ snmp_set_var_typed_value(requests->requestvb, $i.type,
+ &val,
+ sizeof(val));
+ @end@
+ }
@else@
@printf "unrecognized type %s for %s" $varnish_type $i@
@end@
@@ -415,11 +434,11 @@ struct ${i}_entry {
@startperl@
&{$vars{'set_field_dim'}}($vars{'c'});
@endperl@
- @if $field_dim > 0@
+ @if $field_dim > 0@
$c.decl ${c}[$field_dim];
- @else@
+ @else@
$c.decl *$c;
- @end@
+ @end@
size_t ${c}_len;
@else@
$c.decl $c;
@@ -567,13 +586,11 @@ $varnish_endif
NULL,
"varnishBanTableTimeout SECONDS"))
snmp_log(LOG_ERR,"can't register config handler\n");
-
if (!register_config_handler("snmpd", "varnishBackendTableTimeout",
varnish_backend_table_timeout_parser,
NULL,
"varnishBackendTableTimeout SECONDS"))
snmp_log(LOG_ERR,"can't register config handler\n");
-
if (!register_config_handler("snmpd", "varnishCLIPortTimeout",
varnish_vcli_timeout_parser,
NULL,
diff --git a/src/vcli.c b/src/vcli.c
index c204cf3..499c365 100644
--- a/src/vcli.c
+++ b/src/vcli.c
@@ -424,33 +424,36 @@ vcli_handshake(struct vcli_conn *conn)
}
int
-vcli_connect(struct VSM_data *vd, struct vcli_conn *conn)
+vcli_connect(struct vsm *vsm, struct vcli_conn *conn)
{
- struct VSM_fantom vt;
struct sockaddr_in vcli_sa;
- char *s, *portstr, *p;
+ char *portstr, *p;
unsigned long n;
short pn;
struct hostent *hp;
-
+ char *T_arg = NULL, *S_arg = NULL;
memset(conn, 0, sizeof(*conn));
- if (!VSM_Get(vd, &vt, "Arg", "-T", "")) {
+ T_arg = VSM_Dup(vsm, "Arg", "-T");
+ if (!T_arg) {
snmp_log(LOG_ERR, "no -T arg in shared memory\n");
return SNMP_ERR_GENERR;
}
- DEBUGMSGTL(("varnish_mib:vcli", "-T '%s'\n", (char*) vt.b));
+ S_arg = VSM_Dup(vsm, "Arg", "-S");
+ if (!S_arg) {
+ free(T_arg);
+ snmp_log(LOG_ERR, "no -S arg in shared memory\n");
+ return SNMP_ERR_GENERR;
+ }
- s = strdup(vt.b);
- if (!s) {
- snmp_log(LOG_ERR, "out of memory\n");
- return SNMP_ERR_GENERR;
- }
- for (portstr = s; !ISSPACE(*portstr); portstr++)
+ DEBUGMSGTL(("varnish_mib:vcli", "-T '%s'\n", (char*) T_arg));
+
+ for (portstr = T_arg; !ISSPACE(*portstr); portstr++)
;
if (!*portstr) {
- snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", s);
- free(s);
+ snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", T_arg);
+ free(T_arg);
+ free(S_arg);
return SNMP_ERR_GENERR;
}
for (*portstr++ = 0; ISSPACE(*portstr); portstr++)
@@ -458,44 +461,40 @@ vcli_connect(struct VSM_data *vd, struct vcli_conn *conn)
n = pn = strtoul(portstr, &p, 0);
if (n != pn || (*p && !ISSPACE(*p))) {
- snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", s);
- free(s);
+ snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", T_arg);
+ free(T_arg);
+ free(S_arg);
return SNMP_ERR_GENERR;
}
- hp = gethostbyname(s);
+ hp = gethostbyname(T_arg);
if (!hp) {
- snmp_log(LOG_ERR, "unknown host name %s\n", s);
- free(s);
+ snmp_log(LOG_ERR, "unknown host name %s\n", T_arg);
+ free(T_arg);
+ free(S_arg);
return SNMP_ERR_GENERR;
}
vcli_sa.sin_family = hp->h_addrtype;
if (vcli_sa.sin_family != AF_INET) {
- snmp_log(LOG_ERR, "unknown host name %s\n", s);
- free(s);
+ snmp_log(LOG_ERR, "unknown host name %s\n", T_arg);
+ free(T_arg);
+ free(S_arg);
return SNMP_ERR_GENERR;
}
memmove(&vcli_sa.sin_addr, hp->h_addr, 4);
vcli_sa.sin_port = htons(pn);
- conn->fd = open_socket(&vcli_sa, s);
- free(s);
- if (conn->fd == -1)
- return SNMP_ERR_GENERR;
-
- if (!VSM_Get(vd, &vt, "Arg", "-S", "")) {
- snmp_log(LOG_ERR, "no -S arg in shared memory\n");
- return SNMP_ERR_GENERR;
- }
- DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", (char*) vt.b));
- s = strdup(vt.b);
- if (!s) {
- snmp_log(LOG_ERR, "out of memory\n");
+ conn->fd = open_socket(&vcli_sa, T_arg);
+ free(T_arg);
+ if (conn->fd == -1) {
+ free(S_arg);
return SNMP_ERR_GENERR;
}
- conn->secret = s;
+
+ DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", S_arg));
+ conn->secret = S_arg;
if (vcli_handshake(conn)) {
vcli_disconnect(conn);

Return to:

Send suggestions and report system problems to the System administrator.