aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@nxc.no>2018-02-02 14:50:53 +0100
committerSergey Poznyakoff <gray@nxc.no>2018-02-02 14:50:53 +0100
commit8a2e9da972cee4714c02f3dd23a3b7fcab9a0476 (patch)
treeee00ab302734161ec756313e8bbede8a82fb86eb
parent83919b99e222077a1bb61757403779cc4f456edc (diff)
downloadvarnish-mib-8a2e9da972cee4714c02f3dd23a3b7fcab9a0476.tar.gz
varnish-mib-8a2e9da972cee4714c02f3dd23a3b7fcab9a0476.tar.bz2
Bugfixes
Use consistend debug token names. Make sure configuration settings are honored by opening VSM and doing initial loading after the configuration has been read and processed. Avoid inifinite recursion in dict_load. * src/modconf.c: New file. * src/modconf.h: New file. * src/vclient.h: New file. * src/Makefile.am: Add new files. * src/VARNISH-MIB.txt: Minor changes in descriptions. * src/backend.h (backend_collect_addr): Change prototype. * src/ban.c: Remove configuration management functions. * src/betab.c: Likewise. * src/statdict.c (dict_lookup): Remove debugging kludge. (dict_load): Don't call backend_collect_addr. It is responsibility of the caller. * src/varnish_mib.mib2c: Rearrange includes. Open VSM after parsing configuration. (init_$modulename): Allow loading of one instance only. * src/vcli.c: Rewrite socket support.
-rw-r--r--src/Makefile.am5
-rw-r--r--src/VARNISH-MIB.txt16
-rw-r--r--src/backend.h2
-rw-r--r--src/ban.c45
-rw-r--r--src/betab.c20
-rw-r--r--src/modconf.c123
-rw-r--r--src/modconf.h9
-rw-r--r--src/statdict.c4
-rw-r--r--src/varnish_mib.mib2c88
-rw-r--r--src/vcli.c228
-rw-r--r--src/vclient.h21
11 files changed, 357 insertions, 204 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3b5547b..3ef9fa5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,18 +20,21 @@ dlmod_LTLIBRARIES = varnish-mib.la
varnish_mib_la_SOURCES = \
auth.c\
ban.c\
backend.h\
belex.l\
betab.c\
+ modconf.h\
+ modconf.c\
sha256.c\
sha256.h\
statdict.c\
varnish_mib.c\
varnish_mib.h\
- vcli.c
+ vcli.c\
+ vclient.h
BUILT_SOURCES = \
varnish_mib.c\
varnish_mib.h
varnish_mib.c varnish_mib.h: varnish_mib.mib2c VARNISH-MIB.txt
diff --git a/src/VARNISH-MIB.txt b/src/VARNISH-MIB.txt
index 8d60477..6b03f21 100644
--- a/src/VARNISH-MIB.txt
+++ b/src/VARNISH-MIB.txt
@@ -17,20 +17,20 @@ IMPORTS
InetAddressIPv4, InetAddressIPv6, InetPortNumber
FROM INET-ADDRESS-MIB
OBJECT-GROUP, MODULE-COMPLIANCE
FROM SNMPv2-CONF;
varnishMIB MODULE-IDENTITY
- LAST-UPDATED "201802012132Z"
+ LAST-UPDATED "201802020845Z"
ORGANIZATION "Shared Autonomous sYstems"
CONTACT-INFO "Morten Hermanrud <mhe@say.no>
Sergey Poznyakoff <gray@gnu.org>
"
DESCRIPTION
"This MIB module defines objects for Varnish reverse web proxy."
- REVISION "201802012132Z"
+ REVISION "201802020845Z"
DESCRIPTION
"Second revision."
::= { varnish 0 }
varnish OBJECT IDENTIFIER ::= { enterprises 33043 6 1 }
client OBJECT IDENTIFIER ::= { varnish 1 }
@@ -109,21 +109,23 @@ clientRequests400 OBJECT-TYPE
clientRequests411 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
- "Client requests received, subject to 411 errors."
+ "Client requests received, subject to 411 errors.
+ This OID is not available in Varnish version 5 and above."
::= { client 8 }
clientRequests413 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
- "Client requests received, subject to 413 errors."
+ "Client requests received, subject to 413 errors.
+ This OID is not available in Varnish version 5 and above."
::= { client 9 }
clientRequests417 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
@@ -183,13 +185,14 @@ backendConnRecycled OBJECT-TYPE
backendConnUnused OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
- "Backend connections unused."
+ "Backend connections unused.
+ This OID is not available in Varnish version 5 and above."
::= { connections 7 }
backendConnRetry OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
@@ -909,13 +912,14 @@ vclDiscard OBJECT-TYPE
vclFail OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
- "Number of VCL failures"
+ "Number of VCL failures.
+ This OID is not available in Varnish 4 and below."
::= { vcl 4 }
--
-- Groups and Compliance
--
varnishConfs OBJECT IDENTIFIER ::= { varnish 100 }
diff --git a/src/backend.h b/src/backend.h
index 0c15e60..d60f613 100644
--- a/src/backend.h
+++ b/src/backend.h
@@ -8,9 +8,9 @@ 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);
+int backend_collect_addr(struct vsm *vsm);
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 0c354e9..1f4583b 100644
--- a/src/ban.c
+++ b/src/ban.c
@@ -48,59 +48,22 @@ varnish_ban(netsnmp_agent_request_info *reqinfo,
if (!expr) {
snmp_log(LOG_ERR, "out of memory\n");
return SNMP_ERR_GENERR;
}
memcpy(expr, requests->requestvb->val.string, len);
expr[len] = 0;
- DEBUGMSGTL(("varnish_ban", "setting ban %s\n", expr));
+ DEBUGMSGTL(("varnish_mib:ban", "setting ban %s\n", expr));
rc = vcli_connect(vsm, &conn);
if (rc == SNMP_ERR_NOERROR) {
rc = send_ban_cmd(&conn, expr);
vcli_disconnect(&conn);
}
free(expr);
return rc ? SNMP_ERR_GENERR : SNMP_ERR_NOERROR;
}
-unsigned banTable_timeout = 60;
-
-int
-varnish_mib_timeout_parser(const char *token, char *line, unsigned *retval)
-{
- char *p;
- unsigned long n = strtoul(line, &p, 10);
-
- if (*p) {
- if (isspace(*p)) {
- while (*p && isspace(*p))
- ++p;
- if (*p) {
- config_perror("too many arguments");
- return 1;
- }
- } else {
- config_perror("invalid timeout value");
- return 1;
- }
- }
-
- if (n > UINT_MAX) {
- config_perror("timeout value out of allowed range");
- return 1;
- }
-
- *retval = n;
- return 0;
-}
-
-void
-varnish_ban_table_timeout_parser(const char *token, char *line)
-{
- varnish_mib_timeout_parser(token, line, &banTable_timeout);
-}
-
/*
* create a new row in the table
*/
static struct banTable_entry *
create_entry(netsnmp_tdata *table_data, long idx, struct banTable_entry *ent)
{
@@ -153,13 +116,13 @@ banTable_load(netsnmp_cache *cache, void *vmagic)
char *p;
struct vsm *vsm = varnish_get_vsm_data();
if (!vsm)
return SNMP_ERR_GENERR;
- DEBUGMSGTL(("varnish_ban", "reloading ban table\n"));
+ DEBUGMSGTL(("varnish_mib:ban", "reloading ban table\n"));
rc = vcli_connect(vsm, &conn);
if (rc != SNMP_ERR_NOERROR)
return rc;
if (vcli_asprintf(&conn, "ban.list\n") || vcli_write(&conn))
@@ -263,23 +226,23 @@ banTable_load(netsnmp_cache *cache, void *vmagic)
create_entry(table, idx, &e);
++idx;
q += e.banExpression_len;
p = q;
}
vcli_disconnect(&conn);
- DEBUGMSGTL(("varnish_ban", "loaded %ld ban entries\n", idx));
+ DEBUGMSGTL(("varnish_mib:ban", "loaded %ld ban entries\n", idx));
return 0;
}
void
banTable_free(netsnmp_cache *cache, void *vmagic)
{
netsnmp_tdata *table = (netsnmp_tdata *) vmagic;
netsnmp_tdata_row *row;
- DEBUGMSGTL(("varnish_ban", "freeing ban table\n"));
+ DEBUGMSGTL(("varnish_mib:ban", "freeing ban table\n"));
while ((row = netsnmp_tdata_row_first(table))) {
struct banTable_entry *entry = row->data;
free(entry->banExpression);
free(entry->banTime);
SNMP_FREE(entry);
netsnmp_tdata_remove_and_delete_row(table, row);
diff --git a/src/betab.c b/src/betab.c
index 388083b..afec48a 100644
--- a/src/betab.c
+++ b/src/betab.c
@@ -133,13 +133,13 @@ backend_register(char const *name, size_t len, char const *param,
int
backendTable_load(netsnmp_cache *cache, void *vmagic)
{
netsnmp_tdata *table_data = (netsnmp_tdata *) vmagic;
struct backend_dfn *dfn;
- DEBUGMSGTL(("varnish_backend", "loading backend table\n"));
+ DEBUGMSGTL(("varnish_mib:backend", "loading backend table\n"));
VTAILQ_FOREACH(dfn, &backends, list) {
int i;
netsnmp_tdata_row *row;
struct backendTable_entry *ent;
@@ -179,28 +179,20 @@ backendTable_load(netsnmp_cache *cache, void *vmagic)
void
backendTable_free(netsnmp_cache *cache, void *vmagic)
{
netsnmp_tdata *table = (netsnmp_tdata *) vmagic;
netsnmp_tdata_row *row;
- DEBUGMSGTL(("varnish_backend", "freeing backend table\n"));
+ DEBUGMSGTL(("varnish_mib: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;
@@ -331,25 +323,21 @@ backend_name_add(struct backend_name_list *namelist,
name->str.start = str;
name->str.len = len;
VTAILQ_INSERT_TAIL(namelist, name, list);
}
int
-backend_collect_addr(void)
+backend_collect_addr(struct vsm *vsm)
{
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"));
+ DEBUGMSGTL(("varnish_mib:backend", "getting backend info\n"));
rc = vcli_connect(vsm, &conn);
if (rc != SNMP_ERR_NOERROR)
return rc;
/* Select backend names */
diff --git a/src/modconf.c b/src/modconf.c
new file mode 100644
index 0000000..85b2582
--- /dev/null
+++ b/src/modconf.c
@@ -0,0 +1,123 @@
+#include "varnish_mib.h"
+#include <ctype.h>
+
+static int
+timeout_parser(const char *token, char *line, unsigned *retval)
+{
+ char *p;
+ unsigned long n = strtoul(line, &p, 10);
+
+ if (*p) {
+ if (isspace(*p)) {
+ while (*p && isspace(*p))
+ ++p;
+ if (*p) {
+ config_perror("too many arguments");
+ return 1;
+ }
+ } else {
+ config_perror("invalid timeout value");
+ return 1;
+ }
+ }
+
+ if (n > UINT_MAX) {
+ config_perror("timeout value out of allowed range");
+ return 1;
+ }
+
+ *retval = n;
+ return 0;
+}
+
+unsigned banTable_timeout = 60;
+unsigned vcli_timeout = 5;
+unsigned backendTable_timeout = 5;
+vcli_sockaddr_t vcli_sockaddr;
+char *vcli_secret;
+
+static void
+ban_table_timeout_parser(const char *token, char *line)
+{
+ timeout_parser(token, line, &banTable_timeout);
+}
+
+static void
+backend_table_timeout_parser(const char *token, char *line)
+{
+ timeout_parser(token, line, &backendTable_timeout);
+}
+
+static void
+vcli_timeout_parser(const char *token, char *line)
+{
+ timeout_parser(token, line, &vcli_timeout);
+}
+
+static void
+vcli_address_parser(const char *token, char *line)
+{
+ vcli_sockaddr = vcli_parse_sockaddr(line);
+}
+
+static void
+vcli_address_releaser(void)
+{
+ free(vcli_sockaddr);
+}
+
+static void
+vcli_secret_parser(const char *token, char *line)
+{
+ vcli_secret = strdup(line);
+}
+
+static void
+vcli_secret_releaser(void)
+{
+ free(vcli_secret);
+}
+
+struct varnish_mib_config
+{
+ char *token;
+ char *help;
+ void (*parser)(const char *token, char *line);
+ void (*releaser) (void);
+};
+
+static struct varnish_mib_config config[] = {
+ { "varnishBanTableTimeout",
+ "varnishBanTableTimeout SECONDS",
+ ban_table_timeout_parser },
+ { "varnishBackendTableTimeout",
+ "varnishBackendTableTimeout SECONDS",
+ backend_table_timeout_parser },
+ { "varnishCLIPortTimeout",
+ "varnishCLIPortTimeout SECONDS",
+ vcli_timeout_parser },
+ { "varnishCLISocket",
+ "varnishCLISocket ADDRESS[:PORT]",
+ vcli_address_parser,
+ vcli_address_releaser },
+ { "varnishCLISecretFile",
+ "varnishCLISecretFile FILE",
+ vcli_secret_parser,
+ vcli_secret_releaser },
+ { NULL }
+};
+
+void
+varnish_mib_config_init(void)
+{
+ struct varnish_mib_config *cp;
+ for (cp = config; cp->token; cp++) {
+ if (!register_config_handler("snmpd",
+ cp->token,
+ cp->parser,
+ cp->releaser,
+ cp->help))
+ snmp_log(LOG_ERR,"can't register %s config handler\n",
+ cp->token);
+ }
+}
diff --git a/src/modconf.h b/src/modconf.h
new file mode 100644
index 0000000..0a7d8fc
--- /dev/null
+++ b/src/modconf.h
@@ -0,0 +1,9 @@
+extern unsigned banTable_timeout;
+extern unsigned vcli_timeout;
+extern unsigned backendTable_timeout;
+extern vcli_sockaddr_t vcli_sockaddr;
+extern char *vcli_secret;
+
+void varnish_mib_config_init(void);
+
+
diff --git a/src/statdict.c b/src/statdict.c
index e87123b..69b442f 100644
--- a/src/statdict.c
+++ b/src/statdict.c
@@ -110,15 +110,12 @@ lookup(const char *name, int 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;
}
@@ -165,8 +162,7 @@ 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 6915689..404f511 100644
--- a/src/varnish_mib.mib2c
+++ b/src/varnish_mib.mib2c
@@ -32,24 +32,24 @@ $vars{'varnish_translate_table'} = {
clientCacheMisses => [ 'DICT', 'MAIN.cache_miss' ],
clientBan => [ 'STRING', '',
{ varnish_set_action => 'varnish_ban' } ],
clientRequestsReceived => [ 'DICT', 'MAIN.client_req' ],
clientRequests400 => [ 'DICT', 'MAIN.client_req_400' ],
- clientRequests411 => [ 'NULL', 'MAIN.client_req_411' ],
- clientRequests413 => [ 'NULL', 'MAIN.client_req_413' ],
+ clientRequests411 => [ 'NULL' ],
+ clientRequests413 => [ 'NULL' ],
clientRequests417 => [ 'DICT', 'MAIN.client_req_417' ],
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' ],
+ backendConnUnused => [ 'NULL' ],
backendConnRetry => [ 'DICT', 'MAIN.backend_retry' ],
backendRequests => [ 'DICT', 'MAIN.backend_req' ],
totalSessions => [ 'DICT', 'MAIN.s_sess' ],
totalRequests => [ 'DICT', 'MAIN.client_req' ],
totalPipe => [ 'DICT', 'MAIN.s_pipe' ],
@@ -158,52 +158,35 @@ $vars{'modulename'} =~ s/\.c$//;
/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
+#include <errno.h>
#include <vapi/vsc.h>
#include <vapi/vsm.h>
#include <vcli.h>
+#include <vas.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
-typedef struct vcli_conn {
- int fd;
- char *secret;
- int resp;
- char *base;
- size_t bufmax;
- size_t bufsize;
-} vcli_conn_t;
-
-int vcli_write(vcli_conn_t *conn);
-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 *vsm, vcli_conn_t *conn);
+#include "vclient.h"
+#include "modconf.h"
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 *vsm);
-int varnish_mib_timeout_parser(const char *token, char *line,
- unsigned *retval);
-
-void varnish_ban_table_timeout_parser(const char *token, char *line);
-void varnish_vcli_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. */
@@ -211,39 +194,58 @@ void dict_load(struct vsc *vsc);
#include "varnish_mib.h"
#include "backend.h"
static struct vsm *vd;
static struct vsc *vsc;
-void
-varnish_snmp_init(void)
+int
+post_config(int majorID, int minorID, void *serverarg, void *clientarg)
{
vd = VSM_New();
- if (vd) {
- vsc = VSC_New(vd);
- if (vsc) {
- if (VSM_Attach(vd, 2))
- fprintf(stderr, "%s\n", VSM_Error(vd));
- }
+ if (!vd) {
+ snmp_log(LOG_ERR, "VSM_New: %s\n", strerror(errno));
+ return 1;
+ }
+
+ vsc = VSC_New(vd);
+ if (!vsc) {
+ snmp_log(LOG_ERR, "VSC_New: %s\n", strerror(errno));
+ return 1;
}
+
+ if (VSM_Attach(vd, 2))
+ snmp_log(LOG_ERR, "%s\n", VSM_Error(vd));
+
dict_load(vsc);
+ backend_collect_addr(vd);
+ return 0;
+}
+
+void
+varnish_snmp_init(void)
+{
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_POST_READ_CONFIG,
+ post_config,
+ NULL);
}
void
varnish_snmp_deinit(void)
{
/* FIXME? */
}
struct vsm *
-varnish_get_vsm_data()
+varnish_get_vsm_data(void)
{
if (vd) {
if (VSM_Status(vd) & (VSM_MGT_CHANGED|VSM_WRK_CHANGED)) {
DEBUGMSGTL(("$modulename", "reopening vd\n"));
dict_load(vsc);
+ backend_collect_addr(vd);
}
}
return vd;
}
/* Variable handlers.
@@ -585,12 +587,16 @@ initialize_table_$i(void)
@end@
/** Initializes the $name module */
void
init_$modulename(void)
{
+ if (vd) {
+ snmp_log(LOG_ERR, "%s: can't be loaded twice\n", "$modulename");
+ abort();
+ }
@foreach $i scalar@
@startperl@
&{$vars{'varnish_translate'}}($vars{'i'});
@endperl@
@if $varnish_type ne 'NULL'@
$varnish_if
@@ -598,27 +604,13 @@ $varnish_if
$varnish_endif
@end@
@end@
DEBUGMSGTL(("$modulename", "Initializing\n"));
- if (!register_config_handler("snmpd", "varnishBanTableTimeout",
- varnish_ban_table_timeout_parser,
- 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,
- "varnishCLIPortTimeout SECONDS"))
- snmp_log(LOG_ERR,"can't register config handler\n");
+ varnish_mib_config_init();
@foreach $i scalar@
@startperl@
&{$vars{'varnish_translate'}}($vars{'i'});
@endperl@
@if $varnish_type ne 'NULL'@
diff --git a/src/vcli.c b/src/vcli.c
index 499c365..2683c9d 100644
--- a/src/vcli.c
+++ b/src/vcli.c
@@ -22,20 +22,73 @@
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
+struct vcli_sockaddr {
+ socklen_t len;
+ struct sockaddr addr[1];
+};
+
#define ISSPACE(c) ((c)==' '||(c)=='\t'||(c)=='\n')
-static unsigned vcli_timeout = 5;
+vcli_sockaddr_t
+vcli_parse_sockaddr(char const *arg)
+{
+ char *node;
+ size_t n;
+ int rc;
+ struct addrinfo *res;
+ char const *p;
+ vcli_sockaddr_t sa;
+
+ n = strcspn(arg, ": \t");
+ node = malloc(n + 1);
+ if (!node) {
+ snmp_log(LOG_ERR, "out of memory\n");
+ return NULL;
+ }
-void
-varnish_vcli_timeout_parser(const char *token, char *line)
+ memcpy(node, arg, n);
+ node[n] = 0;
+ p = arg + n;
+ if (*p == ':')
+ p++;
+ else
+ while (*p && ISSPACE(*p))
+ p++;
+
+ if (!p)
+ p = "6082";
+
+ rc = getaddrinfo(node, p, NULL, &res);
+ free(node);
+ if (rc) {
+ snmp_log(LOG_ERR, "can't resolve %s\n", arg);
+ return NULL;
+ }
+
+ sa = malloc(sizeof(*sa) - sizeof(sa->addr) + res->ai_addrlen);
+ if (!sa) {
+ snmp_log(LOG_ERR, "out of memory\n");
+ return NULL;
+ }
+ sa->len = res->ai_addrlen;
+ memcpy(sa->addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ return sa;
+}
+
+vcli_sockaddr_t
+vcli_sockaddr_dup(vcli_sockaddr_t src)
{
- varnish_mib_timeout_parser(token, line, &vcli_timeout);
+ vcli_sockaddr_t dst;
+ dst = malloc(sizeof(*dst) - sizeof(dst->addr) + src->len);
+ memcpy(dst, src, src->len);
+ return dst;
}
#define VCLI_INIT_ALLOC 16
static int
vcli_alloc(struct vcli_conn *conn, size_t size)
@@ -143,13 +196,13 @@ vcli_read(struct vcli_conn *conn, size_t size)
}
if (ret == 0) {
if (conn->bufsize == 0)
ret = -1;
conn->base[conn->bufsize] = 0;
- DEBUGMSGTL(("varnish_mib:vcli", "<<varnish: %s\n", conn->base));
+ DEBUGMSGTL(("transcript:varnish_mib", "<<varnish: %s\n", conn->base));
}
return ret;
}
static int
@@ -226,13 +279,13 @@ vcli_getline(struct vcli_conn *conn)
int
vcli_write(struct vcli_conn *conn)
{
size_t size;
- DEBUGMSGTL(("varnish_mib:vcli", ">>varnish: %s\n", conn->base));
+ DEBUGMSGTL(("transcript:varnish_mib", ">>varnish: %s\n", conn->base));
for (size = 0; size < conn->bufsize; ) {
int n = write(conn->fd, conn->base + size,
conn->bufsize - size);
if (n < 0) {
snmp_log(LOG_ERR, "write error: %s\n",
strerror(errno));
@@ -313,31 +366,31 @@ vcli_asprintf(struct vcli_conn *conn, const char *fmt, ...)
va_start(ap, fmt);
rc = vcli_vasprintf(conn, fmt, ap);
va_end(ap);
return rc;
}
-
-
+
static int
-open_socket(struct sockaddr_in *sa, const char *connstr)
+open_socket(vcli_sockaddr_t sa)
{
- int fd = socket(sa->sin_family, SOCK_STREAM, 0);
+ int fd;
struct timeval start, connect_tv;
-
+
+ fd = socket(sa->addr->sa_family, SOCK_STREAM, 0);
if (fd == -1) {
snmp_log(LOG_ERR, "socket: %s\n", strerror(errno));
return -1;
}
connect_tv.tv_sec = vcli_timeout;
connect_tv.tv_usec = 0;
gettimeofday(&start, NULL);
for (;;) {
- int rc = connect(fd, sa, sizeof(*sa));
+ int rc = connect(fd, sa->addr, sa->len);
if (rc == 0)
break;
else if (errno == ECONNREFUSED) {
struct timeval tv, now;
fd_set rset, wset, xset;
@@ -351,18 +404,28 @@ open_socket(struct sockaddr_in *sa, const char *connstr)
FD_SET(fd, &wset);
FD_ZERO(&xset);
FD_SET(fd, &xset);
select(fd + 1, &rset, &wset, &xset, &tv);
continue;
}
+ } else {
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+ int ec = errno;
+ if (getnameinfo(sa->addr, sa->len,
+ hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV) == 0)
+ snmp_log(LOG_ERR,
+ "cannot connect to %s:%s: %s\n",
+ hbuf, sbuf, strerror(ec));
+ else
+ snmp_log(LOG_ERR,
+ "cannot connect to varnish: %s\n",
+ strerror(ec));
+ close(fd);
+ return -1;
}
-
- snmp_log(LOG_ERR, "cannot connect to %s: %s\n",
- connstr, strerror(errno));
- close(fd);
- return -1;
}
return fd;
}
void
@@ -420,85 +483,76 @@ vcli_handshake(struct vcli_conn *conn)
return 1;
}
return 0;
}
-int
-vcli_connect(struct vsm *vsm, struct vcli_conn *conn)
+static int
+parse_connection(struct vsm *vsm, vcli_sockaddr_t *addr, char **secret)
{
- struct sockaddr_in vcli_sa;
- char *portstr, *p;
- unsigned long n;
- short pn;
- struct hostent *hp;
- char *T_arg = NULL, *S_arg = NULL;
- memset(conn, 0, sizeof(*conn));
-
- 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;
- }
- 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;
- }
-
- 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", T_arg);
- free(T_arg);
- free(S_arg);
- return SNMP_ERR_GENERR;
- }
- for (*portstr++ = 0; ISSPACE(*portstr); portstr++)
- ;
-
- n = pn = strtoul(portstr, &p, 0);
- if (n != pn || (*p && !ISSPACE(*p))) {
- snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", T_arg);
+ if (vcli_sockaddr) {
+ DEBUGMSGTL(("varnish_mib:vcli",
+ "using configured sockaddr\n"));
+ *addr = vcli_sockaddr_dup(vcli_sockaddr);
+ } else {
+ char *T_arg, *p;
+ 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;
+ }
+ p = T_arg + strlen(T_arg) - 1;
+ if (*p == '\n')
+ *p = 0;
+ DEBUGMSGTL(("varnish_mib:vcli", "-T '%s'\n", T_arg));
+ *addr = vcli_parse_sockaddr(T_arg);
free(T_arg);
- free(S_arg);
- return SNMP_ERR_GENERR;
}
-
- hp = gethostbyname(T_arg);
- if (!hp) {
- snmp_log(LOG_ERR, "unknown host name %s\n", T_arg);
- free(T_arg);
- free(S_arg);
+ if (!*addr)
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", 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);
+ if (vcli_secret) {
+ DEBUGMSGTL(("varnish_mib:vcli",
+ "using configured secret\n"));
+ *secret = strdup(vcli_secret);
+ if (!*secret) {
+ snmp_log(LOG_ERR, "out of memory");
+ return SNMP_ERR_GENERR;
+ }
+ } else {
+ char *S_arg = VSM_Dup(vsm, "Arg", "-S");
+ if (!S_arg) {
+ snmp_log(LOG_ERR, "no -S arg in shared memory\n");
+ return SNMP_ERR_GENERR;
+ }
+ DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", S_arg));
+ *secret = S_arg;
+ }
+ return 0;
+}
- conn->fd = open_socket(&vcli_sa, T_arg);
- free(T_arg);
- if (conn->fd == -1) {
- free(S_arg);
- return SNMP_ERR_GENERR;
- }
+int
+vcli_connect(struct vsm *vsm, struct vcli_conn *conn)
+{
+ vcli_sockaddr_t addr = NULL;
+ char *secret = NULL;
+ int rc;
- DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", S_arg));
- conn->secret = S_arg;
-
- if (vcli_handshake(conn)) {
- vcli_disconnect(conn);
- return SNMP_ERR_GENERR;
+ rc = parse_connection(vsm, &addr, &secret);
+ if (rc == 0) {
+ memset(conn, 0, sizeof(*conn));
+ conn->fd = open_socket(addr);
+ if (conn->fd == -1)
+ rc = SNMP_ERR_GENERR;
+ else {
+ conn->secret = secret;
+ secret = NULL;
+ if (vcli_handshake(conn)) {
+ vcli_disconnect(conn);
+ rc = SNMP_ERR_GENERR;
+ }
+ }
}
- return SNMP_ERR_NOERROR;
+ free(addr);
+ free(secret);
+ return rc;
}
diff --git a/src/vclient.h b/src/vclient.h
new file mode 100644
index 0000000..8bb3cdf
--- /dev/null
+++ b/src/vclient.h
@@ -0,0 +1,21 @@
+struct vcli_sockaddr;
+typedef struct vcli_sockaddr *vcli_sockaddr_t;
+
+vcli_sockaddr_t vcli_parse_sockaddr(char const *arg);
+
+typedef struct vcli_conn {
+ int fd;
+ char *secret;
+ int resp;
+ char *base;
+ size_t bufmax;
+ size_t bufsize;
+} vcli_conn_t;
+
+int vcli_write(vcli_conn_t *conn);
+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 *vsm, vcli_conn_t *conn);
+

Return to:

Send suggestions and report system problems to the System administrator.