diff options
author | Sergey Poznyakoff <gray@nxc.no> | 2018-02-02 14:50:53 +0100 |
---|---|---|
committer | Sergey Poznyakoff <gray@nxc.no> | 2018-02-02 14:50:53 +0100 |
commit | 8a2e9da972cee4714c02f3dd23a3b7fcab9a0476 (patch) | |
tree | ee00ab302734161ec756313e8bbede8a82fb86eb /src | |
parent | 83919b99e222077a1bb61757403779cc4f456edc (diff) | |
download | varnish-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/VARNISH-MIB.txt | 16 | ||||
-rw-r--r-- | src/backend.h | 2 | ||||
-rw-r--r-- | src/ban.c | 45 | ||||
-rw-r--r-- | src/betab.c | 20 | ||||
-rw-r--r-- | src/modconf.c | 123 | ||||
-rw-r--r-- | src/modconf.h | 9 | ||||
-rw-r--r-- | src/statdict.c | 4 | ||||
-rw-r--r-- | src/varnish_mib.mib2c | 88 | ||||
-rw-r--r-- | src/vcli.c | 228 | ||||
-rw-r--r-- | src/vclient.h | 21 |
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 @@ -14,30 +14,33 @@ # You should have received a copy of the GNU General Public License # along with varnish-mib. If not, see <http://www.gnu.org/licenses/>. dlmoddir=@DLMODDIR@ 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 .mib2c.c: MIBDIRS=${top_srcdir}/src:${NET_SNMP_MIBDIRS} MIBS="VARNISH-MIB:${NET_SNMP_MIBS}" \ mib2c -c $< -f $@ varnish #NET_SNMP_INCLUDES = `$(NET_SNMP_CONFIG) --cflags` 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 @@ -11,32 +11,32 @@ VARNISH-MIB DEFINITIONS ::= BEGIN IMPORTS MODULE-IDENTITY, OBJECT-TYPE, enterprises, Counter64, TimeTicks, Counter32, Integer32 FROM SNMPv2-SMI TEXTUAL-CONVENTION, DateAndTime FROM SNMPv2-TC 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 } backend OBJECT IDENTIFIER ::= { varnish 2 } total OBJECT IDENTIFIER ::= { varnish 3 } master OBJECT IDENTIFIER ::= { varnish 4 } session OBJECT IDENTIFIER ::= { varnish 5 } threads OBJECT IDENTIFIER ::= { varnish 6 } bans OBJECT IDENTIFIER ::= { varnish 7 } @@ -103,33 +103,35 @@ clientRequests400 OBJECT-TYPE SYNTAX Counter64 MAX-ACCESS read-only STATUS current DESCRIPTION "Client requests received, subject to 400 errors." ::= { client 7 } 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 DESCRIPTION "Client requests received, subject to 417 errors." ::= { client 10 } connections OBJECT IDENTIFIER ::= { backend 1 } @@ -177,25 +179,26 @@ backendConnRecycled OBJECT-TYPE SYNTAX Counter64 MAX-ACCESS read-only STATUS current DESCRIPTION "Backend connections recycles." ::= { connections 6 } 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 DESCRIPTION "Backend connections retried." ::= { connections 8 } backendRequests OBJECT-TYPE SYNTAX Counter64 @@ -903,25 +906,26 @@ vclDiscard OBJECT-TYPE SYNTAX Counter64 MAX-ACCESS read-only STATUS current DESCRIPTION "Number of discarded VCLs." ::= { vcl 3 } 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 } varnishGroups OBJECT IDENTIFIER ::= { varnishConfs 1 } varnishCompl OBJECT IDENTIFIER ::= { varnishConfs 2 } -- -- Groups -- diff --git a/src/backend.h b/src/backend.h index 0c15e60..d60f613 100644 --- a/src/backend.h +++ b/src/backend.h @@ -2,15 +2,15 @@ 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); +int backend_collect_addr(struct vsm *vsm); void backend_parser(const char *str, size_t len, regfun_t regfun, void *d); @@ -42,71 +42,34 @@ varnish_ban(netsnmp_agent_request_info *reqinfo, { int rc; struct vcli_conn conn; size_t len = requests->requestvb->val_len; char *expr = malloc(len + 1); 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) { struct banTable_entry *entry; netsnmp_tdata_row *row; entry = SNMP_MALLOC_TYPEDEF(struct banTable_entry); if (!entry) return NULL; @@ -147,25 +110,25 @@ int banTable_load(netsnmp_cache *cache, void *vmagic) { netsnmp_tdata *table = (netsnmp_tdata *) vmagic; long idx = 0; int rc; struct vcli_conn conn; 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)) return SNMP_ERR_GENERR; if (vcli_read_response(&conn)) return SNMP_ERR_GENERR; if (conn.resp != CLIS_OK) { @@ -257,31 +220,31 @@ banTable_load(netsnmp_cache *cache, void *vmagic) free(e.banTime); snmp_log(LOG_ERR, "out of memory\n"); return SNMP_ERR_GENERR; } memcpy(e.banExpression, q, e.banExpression_len); 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 @@ -127,25 +127,25 @@ backend_register(char const *name, size_t len, char const *param, dfn->vpt[i] = vpt; break; } } } 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; 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; @@ -173,40 +173,32 @@ backendTable_load(netsnmp_cache *cache, void *vmagic) 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; - 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; 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] == '.' @@ -325,37 +317,33 @@ backend_name_add(struct backend_name_list *namelist, 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); } 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 */ 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) 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 @@ -104,27 +104,24 @@ lookup(const char *name, int install) 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++) @@ -159,14 +156,13 @@ load_cb(void *priv, const struct VSC_point *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 6915689..404f511 100644 --- a/src/varnish_mib.mib2c +++ b/src/varnish_mib.mib2c @@ -26,36 +26,36 @@ @startperl@ $vars{'varnish_translate_table'} = { 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 => [ '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' ], 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' ], @@ -152,104 +152,106 @@ $vars{'modulename'} =~ s#.*/##; $vars{'modulename'} =~ s/\.c$//; #print "$vars{'modulename'}\n"; 0; @endperl@ @open ${modulename}.h@ /* 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. */ #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. An instance handler only hands us one request at a time, unwrapping any eventual GETNEXT requests. */ @foreach $i scalar@ @@ -579,52 +581,42 @@ initialize_table_$i(void) /* netsnmp_inject_handler_before(reg, netsnmp_cache_handler_get(cache), TABLE_TDATA_NAME); */ } @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 const oid ${i}_oid[] = { $i.commaoid }; $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'@ $varnish_if netsnmp_register_scalar( netsnmp_create_handler_registration("$i", handle_$i, ${i}_oid, OID_LENGTH(${i}_oid), @if !$i.settable@ HANDLER_CAN_RONLY @@ -16,32 +16,85 @@ */ #include "varnish_mib.h" #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #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) { char *p; if (size < conn->bufmax) return 0; p = realloc(conn->base, size); @@ -137,25 +190,25 @@ vcli_read(struct vcli_conn *conn, size_t size) snmp_log(LOG_ERR, "read: %s\n", strerror(errno)); ret = -1; break; } } } 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 vcli_getline(struct vcli_conn *conn) { fd_set rd; time_t start; struct timeval tv; long ttl; @@ -220,25 +273,25 @@ vcli_getline(struct vcli_conn *conn) } conn->base[conn->bufsize] = 0; } return ret; } 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)); return -1; } size += n; } return 0; } @@ -307,68 +360,78 @@ vcli_vasprintf(struct vcli_conn *conn, const char *fmt, va_list ap) int vcli_asprintf(struct vcli_conn *conn, const char *fmt, ...) { int rc; va_list ap; 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; gettimeofday(&now, NULL); timersub(&now, &start, &tv); if (timercmp(&tv, &connect_tv, < )) { FD_ZERO(&rset); FD_SET(fd, &rset); FD_ZERO(&wset); 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; } |