summaryrefslogtreecommitdiffabout
path: root/src
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) (unidiff)
tree7513334ef43be06b45f39f13ef9b6a3bf37931d8 /src
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 (limited to 'src') (more/less context) (ignore whitespace changes)
-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
9 files changed, 828 insertions, 335 deletions
diff --git a/src/.gitignore b/src/.gitignore
index 61958b7..f40282a 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,2 +1,3 @@
1varnish_mib.c 1varnish_mib.c
2varnish_mib.h 2varnish_mib.h
3belex.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
20varnish_mib_la_SOURCES = \ 20varnish_mib_la_SOURCES = \
21 auth.c\ 21 auth.c\
22 ban.c\ 22 ban.c\
23 backend.h\
24 belex.l\
23 betab.c\ 25 betab.c\
24 sha256.c\ 26 sha256.c\
25 sha256.h\ 27 sha256.h\
28 statdict.c\
26 varnish_mib.c\ 29 varnish_mib.c\
27 varnish_mib.h\ 30 varnish_mib.h\
28 vcli.c 31 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 @@
1typedef struct be_string {
2 char const *start;
3 size_t len;
4} be_string_t;
5
6typedef void (*regfun_t)(be_string_t *, be_string_t *, be_string_t *, void *);
7
8void read_defs(const char *str, size_t len, regfun_t regfun, void *d);
9void varnish_backend_table_timeout_parser(const char *token, char *line);
10struct VSC_point;
11void backend_register(char const *name, size_t len, char const *param,
12 const struct VSC_point *vpt);
13void backend_clear(void);
14int backend_collect_addr(void);
15void backend_parser(const char *str, size_t len, regfun_t regfun, void *d);
16
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)
38int 38int
39varnish_ban(netsnmp_agent_request_info *reqinfo, 39varnish_ban(netsnmp_agent_request_info *reqinfo,
40 netsnmp_request_info *requests, 40 netsnmp_request_info *requests,
41 struct VSM_data *vd) 41 struct vsm *vsm)
42{ 42{
43 int rc; 43 int rc;
44 struct vcli_conn conn; 44 struct vcli_conn conn;
@@ -52,7 +52,7 @@ varnish_ban(netsnmp_agent_request_info *reqinfo,
52 memcpy(expr, requests->requestvb->val.string, len); 52 memcpy(expr, requests->requestvb->val.string, len);
53 expr[len] = 0; 53 expr[len] = 0;
54 DEBUGMSGTL(("varnish_ban", "setting ban %s\n", expr)); 54 DEBUGMSGTL(("varnish_ban", "setting ban %s\n", expr));
55 rc = vcli_connect(vd, &conn); 55 rc = vcli_connect(vsm, &conn);
56 if (rc == SNMP_ERR_NOERROR) { 56 if (rc == SNMP_ERR_NOERROR) {
57 rc = send_ban_cmd(&conn, expr); 57 rc = send_ban_cmd(&conn, expr);
58 vcli_disconnect(&conn); 58 vcli_disconnect(&conn);
@@ -151,13 +151,14 @@ banTable_load(netsnmp_cache *cache, void *vmagic)
151 int rc; 151 int rc;
152 struct vcli_conn conn; 152 struct vcli_conn conn;
153 char *p; 153 char *p;
154 struct VSM_data *vd; 154
155 struct vsm *vsm = varnish_get_vsm_data();
156 if (!vsm)
157 return SNMP_ERR_GENERR;
155 158
156 DEBUGMSGTL(("varnish_ban", "reloading ban table\n")); 159 DEBUGMSGTL(("varnish_ban", "reloading ban table\n"));
157 vd = varnish_get_vsm_data(); 160 rc = vcli_connect(vsm, &conn);
158 if (!vd) 161
159 return SNMP_ERR_NOSUCHNAME;
160 rc = vcli_connect(vd, &conn);
161 if (rc != SNMP_ERR_NOERROR) 162 if (rc != SNMP_ERR_NOERROR)
162 return rc; 163 return rc;
163 164
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 @@
1%option nounput
2%option noinput
3
4%{
5#include "backend.h"
6
7enum {
8 T_BOGUS = 256,
9 T_IDENT,
10 T_NUMBER,
11 T_STRING,
12 T_BACKEND,
13 T_HOST,
14 T_PORT
15};
16
17static char const *input_string;
18static size_t input_len;
19static size_t input_pos;
20static char const *string_start;
21static size_t current_pos;
22
23#define YY_INPUT(buf,result,max_size) \
24 do { \
25 size_t n = input_len - input_pos;\
26 if (n > max_size) \
27 n = max_size; \
28 memcpy(buf, input_string, n); \
29 input_pos += n; \
30 result = n; \
31 } while (0)
32
33 #define YY_USER_ACTION \
34 current_pos += yyleng;
35
36#define YY_DECL static int yylex(void)
37static int yywrap(void);
38
39static char const *
40input_point(void)
41{
42 return input_string + current_pos;
43}
44
45#define YYSTYPE be_string_t
46#define YYSTYPE_INITIALIZER { NULL, 0 }
47
48static YYSTYPE yylval;
49%}
50
51%x COMMENT STR
52
53%%
54 /* C-style comments */
55"/*" BEGIN(COMMENT);
56<COMMENT>[^*]* /* eat anything that's not a '*' */
57<COMMENT>"*"+[^*/]* /* eat up '*'s not followed by '/'s */
58<COMMENT>"*"+"/" BEGIN(INITIAL);
59
60 /* Single-line comments */
61"//".*\n ;
62#.*\n ;
63
64 /* Multi-line strings */
65"{\"" { BEGIN(STR); string_start = input_point(); }
66<STR>[^\"]* /* eat anything that's not a '"' */
67<STR>"\""+[^"}]* /* eat up '"'s not followed by '}'s */
68<STR>"\""+"}" { BEGIN(INITIAL);
69 yylval.start = string_start;
70 yylval.len = input_point() - yylval.start - 2;
71 return T_STRING;
72 }
73 /* Single-line strings */
74\".*\" {
75 yylval.start = input_point() - yyleng + 1;
76 yylval.len = yyleng - 2;
77 return T_STRING;
78 }
79backend return T_BACKEND;
80".host" return T_HOST;
81".port" return T_PORT;
82"{"|"}"|"="|";" return yytext[0];
83
84[a-zA-Z_][a-zA-Z0-9_.]+ {
85 yylval.start = input_point() - yyleng;
86 yylval.len = yyleng;
87 return T_IDENT;
88 }
89[0-9]+ return T_NUMBER;
90
91[ \t\n]+ ;
92
93. return T_BOGUS;
94
95%%
96int
97yywrap(void)
98{
99 return 1;
100}
101
102static void
103set_input(char const *str, size_t len)
104{
105 input_string = str;
106 input_len = len;
107 input_pos = 0;
108 current_pos = 0;
109}
110
111static int brace_nesting;
112
113static void
114read_backend(regfun_t regfun, void *d)
115{
116 int c;
117 int in_statement;
118 YYSTYPE label, host = YYSTYPE_INITIALIZER, port = YYSTYPE_INITIALIZER;
119
120 if ((c = yylex()) != T_IDENT && c != T_STRING)
121 return;
122 label = yylval;
123 if ((c = yylex()) != '{')
124 return;
125 brace_nesting++;
126 in_statement = 0;
127 while (brace_nesting == 1) {
128 c = yylex();
129 if (c == 0)
130 break;
131 else if (c == '{')
132 brace_nesting++;
133 else if (c == '}')
134 brace_nesting++;
135 else if (in_statement) {
136 if (c == ';')
137 in_statement = 0;
138 } else {
139 in_statement = 1;
140 if (c == T_HOST || c == T_PORT) {
141 YYSTYPE *stk = c == T_HOST ? &host : &port;
142 in_statement = 1;
143 if ((c = yylex()) == '=') {
144 c = yylex();
145 if (c == T_STRING || c == T_IDENT) {
146 *stk = yylval;
147 }
148 }
149 }
150 }
151 }
152 regfun(&label, &host, &port, d);
153}
154
155void
156backend_parser(const char *str, size_t len, regfun_t regfun, void *d)
157{
158 int c;
159
160 set_input(str, len);
161
162 brace_nesting = 0;
163 while ((c = yylex())) {
164 if (brace_nesting == 0) {
165 if (c == T_BACKEND) {
166 read_backend(regfun, d);
167 }
168 }
169 switch (c) {
170 case '{':
171 brace_nesting++;
172 break;
173 case '}':
174 brace_nesting--;
175 break;
176 }
177 }
178}
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 @@
1/* This file is part of varnish-mib 1/* This file is part of varnish-mib
2 Copyright (C) 2014 Sergey Poznyakoff 2 Copyright (C) 2014, 2018 Sergey Poznyakoff
3 3
4 Varnish-mib is free software; you can redistribute it and/or modify 4 Varnish-mib is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -15,73 +15,39 @@
15 along with varnish-mib. If not, see <http://www.gnu.org/licenses/>. 15 along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include "varnish_mib.h" 17#include "varnish_mib.h"
18#include <varnish/vas.h>
19#include <varnish/vqueue.h>
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <netdb.h>
18#include <arpa/inet.h> 23#include <arpa/inet.h>
24#include <netinet/in.h>
19 25
20unsigned backendTable_timeout = 5; 26#include "backend.h"
21
22void
23varnish_backend_table_timeout_parser(const char *token, char *line)
24{
25 varnish_mib_timeout_parser(token, line, &backendTable_timeout);
26}
27
28/*
29 * create a new row in the table
30 */
31static struct backendTable_entry *
32create_entry(netsnmp_tdata *table_data, long idx,
33 struct backendTable_entry *ent)
34{
35 struct backendTable_entry *entry;
36 netsnmp_tdata_row *row;
37
38 entry = SNMP_MALLOC_TYPEDEF(struct backendTable_entry);
39 if (!entry)
40 return NULL;
41
42 row = netsnmp_tdata_create_row();
43 if (!row) {
44 SNMP_FREE(entry);
45 return NULL;
46 }
47 row->data = entry;
48 *entry = *ent;
49
50 entry->vbeIndex = idx;
51 netsnmp_tdata_row_add_index(row, ASN_INTEGER,
52 &entry->vbeIndex,
53 sizeof(entry->vbeIndex));
54 if (table_data)
55 netsnmp_tdata_add_row(table_data, row);
56 return entry;
57}
58 27
59#define VSC_POINT_TYPE(p) ((p)->section->fantom->type) 28enum {
60#define VSC_POINT_IDENT(p) ((p)->section->fantom->ident) 29 vbeHappyProbes,
61#define VSC_POINT_NAME(p) ((p)->desc->name) 30 vbeRequestHeaderBytes,
62#if VARNISHAPI_MINOR == 0 31 vbeRequestBodyBytes,
63# define VSC_POINT_FMT(p) ((p)->desc->fmt) 32 vbeResponseHeaderBytes,
64#elif VARNISHAPI_MINOR == 1 33 vbeResponseBodyBytes,
65# define VSC_POINT_FMT(p) ((p)->desc->ctype) 34 vbePipeHeaderBytes,
66#else 35 vbePipeIn,
67# error "unsupported Varnish API minor number" 36 vbePipeOut,
68#endif 37 VBE_MAX
69
70struct betab_priv {
71 int err;
72 long idx;
73 struct backendTable_entry ent;
74 netsnmp_tdata *table;
75}; 38};
76 39
77struct betab_trans { 40struct betab_trans {
78 const char *name; 41 char const *param;
79 size_t off; 42 size_t off;
80}; 43};
81 44
82static struct betab_trans betab_trans[] = { 45/*
83 { "vcls", 46 { "vcls",
84 offsetof(struct backendTable_entry, vbeVcls) }, 47 offsetof(struct backendTable_entry, vbeVcls) },
48*/
49
50static struct betab_trans betab_trans[] = {
85 { "happy", 51 { "happy",
86 offsetof(struct backendTable_entry, vbeHappyProbes) }, 52 offsetof(struct backendTable_entry, vbeHappyProbes) },
87 { "bereq_hdrbytes", 53 { "bereq_hdrbytes",
@@ -101,168 +67,308 @@ static struct betab_trans betab_trans[] = {
101 { NULL } 67 { NULL }
102}; 68};
103 69
104static int 70struct backend_dfn {
105identcmp(struct betab_priv *bp, const char *ident) 71 long vbeIndex;
106{ 72
107 size_t len; 73 char *vbeIdent;
108 size_t i; 74 size_t vbeIdent_len;
75
76 char vbeIPv4[4];
77 size_t vbeIPv4_len;
78 char vbeIPv6[16];
79 size_t vbeIPv6_len;
80 u_long vbePort;
109 81
110 if (bp->idx == -1) 82 const struct VSC_point *vpt[VBE_MAX];
111 return 1; 83
112 for (i = 0; i < bp->ent.vbeIdent_len; i++, ident++) 84 VTAILQ_ENTRY(backend_dfn) list;
113 if (bp->ent.vbeIdent[i] != *ident) 85 };
114 return 1;
115 if (*ident == '(' || *ident == 0)
116 return 0;
117 return 1;
118}
119 86
120static void 87static VTAILQ_HEAD(, backend_dfn) backends
121uint32_to_bytes (unsigned char *bytes, uint32_t u) 88 = VTAILQ_HEAD_INITIALIZER(backends);
122{
123 int i;
124 89
125 for (i = 0; i < 4; i++) 90void
126 { 91backend_clear(void)
127 bytes[i] = u & 0xff; 92{
128 u >>= 8; 93 while (!VTAILQ_EMPTY(&backends)) {
129 } 94 struct backend_dfn *dfn = VTAILQ_FIRST(&backends);
95 VTAILQ_REMOVE(&backends, dfn, list);
96 free(dfn->vbeIdent);
97 SNMP_FREE(dfn);
98 }
130} 99}
131 100
132static void 101void
133scanbuf(const char *s, struct backendTable_entry *ent) 102backend_register(char const *name, size_t len, char const *param,
103 const struct VSC_point *vpt)
134{ 104{
135 char ipv4buf[16]; 105 int i = 0;
136 char ipv6buf[81]; 106 struct backend_dfn *dfn;
137 unsigned long port;
138 char *p;
139 union {
140 struct in_addr in;
141 struct in6_addr in6;
142 } v;
143 107
144 if (*s != '(') 108 VTAILQ_FOREACH(dfn, &backends, list) {
145 return; 109 if (dfn->vbeIdent_len == len
146 ++s; 110 && memcmp(dfn->vbeIdent, name, len) == 0)
147 p = ipv4buf; 111 break;
148 while (p < ipv4buf + sizeof(ipv4buf) && *s && *s != ',') 112 i++;
149 *p++ = *s++; 113 }
150 if (*s != ',') 114 if (!dfn) {
151 return; 115 dfn = SNMP_MALLOC_TYPEDEF(struct backend_dfn);
152 *p = 0; 116 AN(dfn);
117 dfn->vbeIndex = i;
118 dfn->vbeIdent = malloc(len + 1);
119 AN(dfn->vbeIdent);
120 memcpy(dfn->vbeIdent, name, len);
121 dfn->vbeIdent[len] = 0;
122 dfn->vbeIdent_len = len;
123 VTAILQ_INSERT_TAIL(&backends, dfn, list);
124 }
125 for (i = 0; betab_trans[i].param; i++) {
126 if (strcmp(betab_trans[i].param, param) == 0) {
127 dfn->vpt[i] = vpt;
128 break;
129 }
130 }
131}
153 132
154 ++s; 133int
155 p = ipv6buf; 134backendTable_load(netsnmp_cache *cache, void *vmagic)
156 while (p < ipv6buf + sizeof(ipv6buf) && *s && *s != ',') 135{
157 *p++ = *s++; 136 netsnmp_tdata *table_data = (netsnmp_tdata *) vmagic;
158 *p = 0; 137 struct backend_dfn *dfn;
159 138
160 ++s; 139 DEBUGMSGTL(("varnish_backend", "loading backend table\n"));
161 port = strtoul(s, &p, 10); 140
162 if (*p != ')' || port > USHRT_MAX) 141 VTAILQ_FOREACH(dfn, &backends, list) {
163 return; 142 int i;
143
144 netsnmp_tdata_row *row;
145 struct backendTable_entry *ent;
146
147 ent = SNMP_MALLOC_TYPEDEF(struct backendTable_entry);
148 ent->vbeIndex = dfn->vbeIndex;
149 ent->vbeIdent = malloc(dfn->vbeIdent_len);
150 memcpy(ent->vbeIdent, dfn->vbeIdent, dfn->vbeIdent_len);
151 ent->vbeIdent_len = dfn->vbeIdent_len;
152 memset(ent->vbeIPv4, 0, sizeof ent->vbeIPv4);
153
154 memcpy(ent->vbeIPv4, dfn->vbeIPv4, dfn->vbeIPv4_len);
155 ent->vbeIPv4_len = dfn->vbeIPv4_len;
156 memcpy(ent->vbeIPv6, dfn->vbeIPv6, ent->vbeIPv6_len);
157 ent->vbeIPv6_len = dfn->vbeIPv6_len;
158 ent->vbePort = dfn->vbePort;
159
160 for (i = 0; i < VBE_MAX; i++) {
161 U64 *u = (U64*)((char*)ent + betab_trans[i].off);
162 uint64_t n = *(const volatile uint64_t*)dfn->vpt[i]->ptr;
163 u->high = n >> 32;
164 u->low = n & 0xffffffff;
165 }
166
167 row = netsnmp_tdata_create_row();
168 if (!row)
169 break;
170 row->data = ent;
171 netsnmp_tdata_row_add_index(row, ASN_INTEGER,
172 &ent->vbeIndex,
173 sizeof(ent->vbeIndex));
174 netsnmp_tdata_add_row(table_data, row);
175 }
176 return 0;
177}
178
179void
180backendTable_free(netsnmp_cache *cache, void *vmagic)
181{
182 netsnmp_tdata *table = (netsnmp_tdata *) vmagic;
183 netsnmp_tdata_row *row;
164 184
165 if (ipv4buf[0] && inet_pton(AF_INET, ipv4buf, &v)) { 185 DEBUGMSGTL(("varnish_backend", "freeing backend table\n"));
166 ent->vbeIPv4_len = 4; 186 while ((row = netsnmp_tdata_row_first(table))) {
167 uint32_to_bytes(ent->vbeIPv4, v.in.s_addr); 187 struct backendTable_entry *entry = row->data;
188 free(entry->vbeIdent);
189 SNMP_FREE(entry);
190 netsnmp_tdata_remove_and_delete_row(table, row);
168 } 191 }
192}
193
194unsigned backendTable_timeout = 5;
195
196void
197varnish_backend_table_timeout_parser(const char *token, char *line)
198{
199 varnish_mib_timeout_parser(token, line, &backendTable_timeout);
200}
201
202static struct backend_dfn *
203dfn_lookup(be_string_t *vclname, be_string_t *label)
204{
205 size_t namelen;
206 struct backend_dfn *dfn;
169 207
170 if (ipv6buf[0] && inet_pton(AF_INET6, ipv6buf, &v)) { 208 namelen = vclname->len + label->len + 1;
171 ent->vbeIPv6_len = 16; 209 VTAILQ_FOREACH(dfn, &backends, list) {
172 memcpy(ent->vbeIPv6, &v, ent->vbeIPv6_len); 210 if (dfn->vbeIdent_len == namelen
211 && memcmp(dfn->vbeIdent, vclname->start, vclname->len) == 0
212 && dfn->vbeIdent[vclname->len] == '.'
213 && memcmp(dfn->vbeIdent + vclname->len + 1,
214 label->start, label->len) == 0)
215 return dfn;
173 } 216 }
174 ent->vbePort = port; 217 return NULL;
175 } 218}
176 219
177/* Process a single statistics point. See comment below. */ 220static u_long
178static int 221to_port(be_string_t *str)
179create_entry_cb(void *priv, const struct VSC_point *const pt)
180{ 222{
181 struct betab_priv *bp = priv; 223 int i;
182 struct betab_trans *tp; 224 u_long v = 0;
183 225 for (i = 0; i < str->len; i++) {
184 if (bp->err || !pt || strcmp(VSC_POINT_TYPE(pt), "VBE") || 226 static char dig[] = "0123456789";
185 strcmp(VSC_POINT_FMT(pt), "uint64_t")) 227 char *p = strchr(dig, str->start[i]);
186 return 0; 228 if (!p)
187 if (identcmp(bp, VSC_POINT_IDENT(pt))) {
188 const char *full_id;
189
190 if (bp->idx != -1
191 && !create_entry(bp->table, bp->idx, &bp->ent)) {
192 snmp_log(LOG_ERR, "out of memory\n");
193 bp->err = SNMP_ERR_GENERR;
194 return 0; 229 return 0;
195 } 230 v = v * 10 + p - dig;
231 }
232 return v;
233}
196 234
197 memset(&bp->ent, 0, sizeof(bp->ent)); 235static void
198 bp->ent.vbeIndex = ++bp->idx; 236uint32_to_bytes (unsigned char *bytes, uint32_t u)
237{
238 int i;
199 239
200 full_id = VSC_POINT_IDENT(pt); 240 for (i = 0; i < 4; i++){
201 bp->ent.vbeIdent_len = strcspn(full_id, "("); 241 bytes[i] = u & 0xff;
202 bp->ent.vbeIdent = malloc(bp->ent.vbeIdent_len); 242 u >>= 8;
203 if (!bp->ent.vbeIdent) {
204 snmp_log(LOG_ERR, "out of memory\n");
205 bp->err = SNMP_ERR_GENERR;
206 return 0;
207 }
208 memcpy(bp->ent.vbeIdent, full_id, bp->ent.vbeIdent_len);
209 full_id += bp->ent.vbeIdent_len;
210 scanbuf(full_id, &bp->ent);
211 } 243 }
244}
212 245
213 for (tp = betab_trans; tp->name; tp++) { 246static void
214 if (strcmp(VSC_POINT_NAME(pt), tp->name) == 0) { 247update_dfn(be_string_t *label, be_string_t *host, be_string_t *port,
215 U64 *u = (U64*)((char*)&bp->ent + tp->off); 248 void *data)
216 uint64_t n = *(const volatile uint64_t*)pt->ptr; 249{
217 u->high = n >> 32; 250 struct backend_dfn *dfn;
218 u->low = n & 0xffffffff; 251
219 break; 252 dfn = dfn_lookup(data, label);
253 if (!dfn)
254 return;
255 dfn->vbePort = to_port(port);
256 if (host->len) {
257 struct addrinfo *res, *ap;
258 int rc;
259 char *node;
260
261 node = malloc(host->len+1);
262 AN(node);
263 memcpy(node, host->start, host->len);
264 node[host->len] = 0;
265 rc = getaddrinfo(node, NULL, NULL, &res);
266 free(node);
267 if (rc)
268 return;
269 for (ap = res; ap; ap = ap->ai_next) {
270 if (ap->ai_addr->sa_family == AF_INET) {
271 if (dfn->vbeIPv4_len == 0) {
272 struct sockaddr_in *s =
273 (struct sockaddr_in *)ap->ai_addr;
274 uint32_to_bytes((unsigned char*)dfn->vbeIPv4,
275 s->sin_addr.s_addr);
276 dfn->vbeIPv4_len = 4;
277 }
278 } else if (ap->ai_addr->sa_family == AF_INET6) {
279 if (dfn->vbeIPv4_len == 0) {
280 struct sockaddr_in6 *s =
281 (struct sockaddr_in6 *)ap->ai_addr;
282 dfn->vbeIPv6_len = 16;
283 memcpy(dfn->vbeIPv6, &s->sin6_addr,
284 dfn->vbeIPv6_len);
285 }
286 }
220 } 287 }
288 freeaddrinfo(res);
221 } 289 }
222 return 0;
223} 290}
224 291
225/* Varnish API does not provide access to struct VSC_C_vbe, so the only 292static int
226 way to backend statistics is to iterate over all statistics data, selecting 293backend_parse(struct vcli_conn *conn, be_string_t *name)
227 the entries marked as VBE. That's what this function does.
228 */
229int
230backendTable_load(netsnmp_cache *cache, void *vmagic)
231{ 294{
232 struct betab_priv bp; 295 if (vcli_asprintf(conn, "vcl.show %*.*s\n",
233 struct VSM_data *vd = varnish_get_vsm_data(); 296 (int)name->len, (int)name->len,
297 name->start)
298 || vcli_write(conn))
299 return SNMP_ERR_GENERR;
234 300
235 if (!vd) 301 if (vcli_read_response(conn))
236 return SNMP_ERR_NOSUCHNAME; 302 return SNMP_ERR_GENERR;
237 303
238 bp.idx = -1; 304 if (conn->resp != CLIS_OK) {
239 bp.err = 0; 305 snmp_log(LOG_ERR, "vcl.show command rejected: %u %s\n",
240 bp.table = (netsnmp_tdata *) vmagic; 306 conn->resp, conn->base);
241 memset(&bp.ent, 0, sizeof(bp.ent)); 307 return SNMP_ERR_GENERR;
242
243 DEBUGMSGTL(("varnish_ban", "loading backend table\n"));
244 VSC_Iter(vd, NULL, create_entry_cb, &bp);
245 /* FIXME: perhaps handle bp.err separately */
246 if (bp.idx != -1) {
247 DEBUGMSGTL(("varnish_ban", "loaded %lu backend entries\n",
248 bp.idx + 1));
249 if (!create_entry(bp.table, bp.idx, &bp.ent))
250 snmp_log(LOG_ERR, "out of memory\n");
251 } 308 }
309 backend_parser(conn->base, conn->bufsize, update_dfn, name);
252 return 0; 310 return 0;
253} 311}
312
313struct backend_name {
314 be_string_t str;
315 VTAILQ_ENTRY(backend_name) list;
316};
317VTAILQ_HEAD(backend_name_list, backend_name);
254 318
255void 319static void
256backendTable_free(netsnmp_cache *cache, void *vmagic) 320backend_name_add(struct backend_name_list *namelist,
321 char const *str, size_t len)
257{ 322{
258 netsnmp_tdata *table = (netsnmp_tdata *) vmagic; 323 struct backend_name *name;
259 netsnmp_tdata_row *row; 324 VTAILQ_FOREACH(name, namelist, list) {
325 if (name->str.len == len
326 && memcmp(name->str.start, str, len) == 0)
327 return;
328 }
329 name = SNMP_MALLOC_TYPEDEF(struct backend_name);
330 AN(name);
331 name->str.start = str;
332 name->str.len = len;
333 VTAILQ_INSERT_TAIL(namelist, name, list);
334}
260 335
261 DEBUGMSGTL(("varnish_ban", "freeing backend table\n")); 336int
262 while ((row = netsnmp_tdata_row_first(table))) { 337backend_collect_addr(void)
263 struct backendTable_entry *entry = row->data; 338{
264 free(entry->vbeIdent); 339 struct backend_dfn *dfn;
265 SNMP_FREE(entry); 340 struct vcli_conn conn;
266 netsnmp_tdata_remove_and_delete_row(table, row); 341 struct vsm *vsm;
342 int rc;
343 struct backend_name_list namelist
344 = VTAILQ_HEAD_INITIALIZER(namelist);
345
346 vsm = varnish_get_vsm_data();
347 if (!vsm)
348 return SNMP_ERR_GENERR;
349 DEBUGMSGTL(("varnish_backend", "getting backend info\n"));
350
351 rc = vcli_connect(vsm, &conn);
352 if (rc != SNMP_ERR_NOERROR)
353 return rc;
354
355 /* Select backend names */
356 VTAILQ_FOREACH(dfn, &backends, list) {
357 int i;
358 for (i = 0; i < dfn->vbeIdent_len; i++)
359 if (dfn->vbeIdent[i] == '.')
360 break;
361 if (i == dfn->vbeIdent_len)
362 continue;
363 backend_name_add(&namelist, dfn->vbeIdent, i);
267 } 364 }
365
366 while (!VTAILQ_EMPTY(&namelist)) {
367 struct backend_name *name = VTAILQ_FIRST(&namelist);
368 VTAILQ_REMOVE(&namelist, name, list);
369 backend_parse(&conn, &name->str);
370 }
371
372 vcli_disconnect(&conn);
373 return 0;
268} 374}
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 @@
1/* This file is part of varnish-mib
2 Copyright (C) 2018 Sergey Poznyakoff
3
4 Varnish-mib is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Varnish-mib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with varnish-mib. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include <stdio.h>
18#include <stdlib.h>
19#include <limits.h>
20#include <inttypes.h>
21#include <string.h>
22#include <vapi/vsc.h>
23#include <vapi/vsm.h>
24#include <vas.h>
25#include <vcli.h>
26#include "backend.h"
27
28static size_t hash_size[] = {
29 7, 17, 37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411
30};
31static size_t hash_num = 0;
32static struct VSC_point **dict;
33
34#define SIZE_T_MAX ((size_t)-1)
35
36static inline size_t
37rotl(size_t x, int n)
38{
39 return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_T_MAX;
40}
41
42static size_t
43hash(const char *str)
44{
45 size_t value = 0;
46 unsigned char ch;
47
48 while ((ch = *str++))
49 value = ch + rotl(value, 7);
50 return value % hash_size[hash_num];
51}
52
53struct VSC_point **lookup(const char *name, int install);
54
55static void
56rehash(void)
57{
58 struct VSC_point **old_dict = dict;
59 size_t old_size = hash_size[hash_num];
60 size_t i;
61
62 ++hash_num;
63 AN(hash_num < sizeof(hash_size) / sizeof(hash_size[0]));
64 dict = calloc(hash_size[hash_num], sizeof(dict[0]));
65 AN(dict);
66
67 for (i = 0; i < old_size; i++) {
68 if (old_dict[i])
69 *lookup(old_dict[i]->name, 1) = old_dict[i];
70 }
71 free(old_dict);
72}
73
74struct VSC_point **
75lookup(const char *name, int install)
76{
77 size_t i, pos;
78
79 if (!dict) {
80 if (install) {
81 dict = calloc(hash_size[hash_num], sizeof(dict[0]));
82 AN(dict);
83 } else
84 return NULL;
85 }
86
87 pos = hash(name);
88
89 for (i = pos; dict[i];) {
90 if (strcmp(dict[i]->name, name) == 0) {
91 return &dict[i];
92 }
93
94 if (++i >= hash_size[hash_num])
95 i = 0;
96 if (i == pos)
97 break;
98 }
99
100 if (!install)
101 return NULL;
102
103 if (!dict[i])
104 return &dict[i];
105
106 rehash();
107 return lookup(name, install);
108}
109
110int
111dict_lookup(char const *key, uint64_t *val)
112{
113 struct VSC_point **ent;
114
115 ent = lookup(key, 0);
116 if (!ent) {
117 fprintf(stderr, "%s NOT FOUND\n", key);
118 }
119 if (!ent)
120 return -1;
121 *val = *(uint64_t*)(*ent)->ptr;
122 return 0;
123}
124
125void
126dict_clear(void)
127{
128 if (dict) {
129 size_t i;
130 for (i = 0; i < hash_size[hash_num]; i++)
131 if (dict[i])
132 VSC_Destroy_Point(&dict[i]);
133 }
134}
135
136struct VSC_point const *
137dict_install(struct VSC_point const *pt)
138{
139 struct VSC_point **ent;
140
141 ent = lookup(pt->name, 1);
142 AN(ent);
143 if (*ent)
144 VSC_Destroy_Point(ent);
145 *ent = VSC_Clone_Point(pt);
146 return *ent;
147}
148
149static int
150load_cb(void *priv, const struct VSC_point *vpt)
151{
152 AZ(strcmp(vpt->ctype, "uint64_t"));
153 vpt = dict_install(vpt);
154 if (strncmp(vpt->name, "VBE.", 4) == 0) {
155 char const *name = vpt->name + 4;
156 char *p = strrchr(name, '.');
157 if (p) {
158 backend_register(name, p - name, p + 1, vpt);
159 }
160 }
161 return 0;
162}
163
164void
165dict_load(struct vsc *vsc)
166{
167 struct vsm_fantom fantom = VSM_FANTOM_NULL;
168 dict_clear();
169 backend_clear();
170 VSC_Iter(vsc, &fantom, load_cb, NULL);
171 backend_collect_addr();
172}
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 @@
1# This file is part of varnish-mib -*- c -*- 1# This file is part of varnish-mib -*- c -*-
2# Copyright (C) 2014-2016 Sergey Poznyakoff 2# Copyright (C) 2014-2018 Sergey Poznyakoff
3# 3#
4# Varnish-mib is free software; you can redistribute it and/or modify 4# Varnish-mib is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by 5# it under the terms of the GNU General Public License as published by
@@ -25,80 +25,79 @@
25@enddefine@ 25@enddefine@
26@startperl@ 26@startperl@
27$vars{'varnish_translate_table'} = { 27$vars{'varnish_translate_table'} = {
28 uptime => [ 'MAIN', 'uptime' ], 28 uptime => [ 'DICT', 'MAIN.uptime' ],
29 clientAcceptedConnections => [ 'MAIN', 'sess_conn' ], 29 clientAcceptedConnections => [ 'DICT', 'MAIN.sess_conn' ],
30 clientRequestsReceived => [ 'MAIN', 'client_req' ], 30 clientCacheHits => [ 'DICT', 'MAIN.cache_hit' ],
31 clientCacheHits => [ 'MAIN', 'cache_hit' ], 31 clientCacheHitsPass => [ 'DICT', 'MAIN.cache_hitpass' ],
32 clientCacheHitsPass => [ 'MAIN', 'cache_hitpass' ], 32 clientCacheMisses => [ 'DICT', 'MAIN.cache_miss' ],
33 clientCacheMisses => [ 'MAIN', 'cache_miss' ],
34 clientBan => [ 'STRING', '', 33 clientBan => [ 'STRING', '',
35 { varnish_set_action => 'varnish_ban' } ], 34 { varnish_set_action => 'varnish_ban' } ],
36 35
37 clientRequestsReceived => [ 'MAIN', 'client_req' ], 36 clientRequestsReceived => [ 'DICT', 'MAIN.client_req' ],
38 clientRequests400 => [ 'MAIN', 'client_req_400' ], 37 clientRequests400 => [ 'DICT', 'MAIN.client_req_400' ],
39 clientRequests411 => [ 'MAIN', 'client_req_411' ], 38 clientRequests411 => [ 'NULL', 'MAIN.client_req_411' ],
40 clientRequests413 => [ 'MAIN', 'client_req_413' ], 39 clientRequests413 => [ 'NULL', 'MAIN.client_req_413' ],
41 clientRequests417 => [ 'MAIN', 'client_req_417' ], 40 clientRequests417 => [ 'DICT', 'MAIN.client_req_417' ],
42 41
43 42
44 backendConnSuccess => [ 'MAIN', 'backend_conn' ], 43 backendConnSuccess => [ 'DICT', 'MAIN.backend_conn' ],
45 backendConnNotAttempted => [ 'MAIN', 'backend_unhealthy' ], 44 backendConnNotAttempted => [ 'DICT', 'MAIN.backend_unhealthy' ],
46 backendConnToMany => [ 'MAIN', 'backend_busy' ], 45 backendConnToMany => [ 'DICT', 'MAIN.backend_busy' ],
47 backendConnFailures => [ 'MAIN', 'backend_fail' ], 46 backendConnFailures => [ 'DICT', 'MAIN.backend_fail' ],
48 backendConnReuses => [ 'MAIN', 'backend_reuse' ], 47 backendConnReuses => [ 'DICT', 'MAIN.backend_reuse' ],
49 backendConnRecycled => [ 'MAIN', 'backend_recycle' ], 48 backendConnRecycled => [ 'DICT', 'MAIN.backend_recycle' ],
50 backendConnUnused => [ 'MAIN', 'backend_toolate' ], 49 backendConnUnused => [ 'NULL', 'MAIN.backend_toolate' ],
51 backendConnRetry => [ 'MAIN', 'backend_retry' ], 50 backendConnRetry => [ 'DICT', 'MAIN.backend_retry' ],
52 backendRequests => [ 'MAIN', 'backend_req' ], 51 backendRequests => [ 'DICT', 'MAIN.backend_req' ],
53 52
54 totalSessions => [ 'MAIN', 's_sess' ], 53 totalSessions => [ 'DICT', 'MAIN.s_sess' ],
55 totalRequests => [ 'MAIN', 's_req' ], 54 totalRequests => [ 'DICT', 'MAIN.client_req' ],
56 totalPipe => [ 'MAIN', 's_pipe' ], 55 totalPipe => [ 'DICT', 'MAIN.s_pipe' ],
57 totalPass => [ 'MAIN', 's_pass' ], 56 totalPass => [ 'DICT', 'MAIN.s_pass' ],
58 totalFetch => [ 'MAIN', 's_fetch' ], 57 totalFetch => [ 'DICT', 'MAIN.s_fetch' ],
59 totalRequestHeaderBytes => [ 'MAIN', 's_req_hdrbytes' ], 58 totalRequestHeaderBytes => [ 'DICT', 'MAIN.s_req_hdrbytes' ],
60 totalRequestBodyBytes => [ 'MAIN', 's_req_bodybytes' ], 59 totalRequestBodyBytes => [ 'DICT', 'MAIN.s_req_bodybytes' ],
61 totalResponseHeaderBytes => [ 'MAIN', 's_resp_hdrbytes' ], 60 totalResponseHeaderBytes => [ 'DICT', 'MAIN.s_resp_hdrbytes' ],
62 totalResponseBodyBytes => [ 'MAIN', 's_resp_bodybytes' ], 61 totalResponseBodyBytes => [ 'DICT', 'MAIN.s_resp_bodybytes' ],
63 totalPipeHeaderBytes => [ 'MAIN', 's_pipe_hdrbytes' ], 62 totalPipeHeaderBytes => [ 'DICT', 'MAIN.s_pipe_hdrbytes' ],
64 totalPipeIn => [ 'MAIN', 's_pipe_in' ], 63 totalPipeIn => [ 'DICT', 'MAIN.s_pipe_in' ],
65 totalPipeOut => [ 'MAIN', 's_pipe_out' ], 64 totalPipeOut => [ 'DICT', 'MAIN.s_pipe_out' ],
66 65
67 sessAccepted => [ 'MAIN', 'sess_conn'], 66 sessAccepted => [ 'DICT', 'MAIN.sess_conn'],
68 sessQueued => [ 'MAIN', 'sess_queued'], 67 sessQueued => [ 'DICT', 'MAIN.sess_queued'],
69 sessDropped => [ 'MAIN', 'sess_dropped'], 68 sessDropped => [ 'DICT', 'MAIN.sess_dropped'],
70 sessClosed => [ 'MAIN', 'sess_closed'], 69 sessClosed => [ 'DICT', 'MAIN.sess_closed'],
71 sessPipeline => [ 'MAIN', 'sess_pipeline'], 70 sessPipeline => [ 'DICT', 'MAIN.s_pipe'],
72 sessReadAhead => [ 'MAIN', 'sess_readahead'], 71 sessReadAhead => [ 'DICT', 'MAIN.sess_readahead'],
73 sessHerd => [ 'MAIN', 'sess_herd'], 72 sessHerd => [ 'DICT', 'MAIN.sess_herd'],
74 sessDrop => [ 'MAIN', 'sess_drop'], 73 sessDrop => [ 'DICT', 'MAIN.sess_drop'],
75 sessFail => [ 'MAIN', 'sess_fail'], 74 sessFail => [ 'DICT', 'MAIN.sess_fail'],
76 sessPipeOverflow => [ 'MAIN', 'sess_pipe_overflow'], 75 sessPipeOverflow => [ 'DICT', 'MAIN.sc_pipe_overflow'],
77 76
78 threadsPools => [ 'MAIN', 'pools'], 77 threadsPools => [ 'DICT', 'MAIN.pools'],
79 threadsTotal => [ 'MAIN', 'threads'], 78 threadsTotal => [ 'DICT', 'MAIN.threads'],
80 threadsLimitHits => [ 'MAIN', 'threads_limited'], 79 threadsLimitHits => [ 'DICT', 'MAIN.threads_limited'],
81 threadsCreated => [ 'MAIN', 'threads_created'], 80 threadsCreated => [ 'DICT', 'MAIN.threads_created'],
82 threadsDestroyed => [ 'MAIN', 'threads_destroyed'], 81 threadsDestroyed => [ 'DICT', 'MAIN.threads_destroyed'],
83 threadsFailed => [ 'MAIN', 'threads_failed'], 82 threadsFailed => [ 'DICT', 'MAIN.threads_failed'],
84 threadsQueueLength => [ 'MAIN', 'thread_queue_len'], 83 threadsQueueLength => [ 'DICT', 'MAIN.thread_queue_len'],
85 84
86 bansTotal => [ 'MAIN', 'bans' ], 85 bansTotal => [ 'DICT', 'MAIN.bans' ],
87 bansCompleted => [ 'MAIN', 'bans_completed' ], 86 bansCompleted => [ 'DICT', 'MAIN.bans_completed' ],
88 bansObj => [ 'MAIN', 'bans_obj' ], 87 bansObj => [ 'DICT', 'MAIN.bans_obj' ],
89 bansReq => [ 'MAIN', 'bans_req' ], 88 bansReq => [ 'DICT', 'MAIN.bans_req' ],
90 bansAdded => [ 'MAIN', 'bans_added' ], 89 bansAdded => [ 'DICT', 'MAIN.bans_added' ],
91 bansDeleted => [ 'MAIN', 'bans_deleted' ], 90 bansDeleted => [ 'DICT', 'MAIN.bans_deleted' ],
92 bansTested => [ 'MAIN', 'bans_tested' ], 91 bansTested => [ 'DICT', 'MAIN.bans_tested' ],
93 bansObjectsKilled => [ 'MAIN', 'bans_obj_killed' ], 92 bansObjectsKilled => [ 'DICT', 'MAIN.bans_obj_killed' ],
94 bansLurkerTested => [ 'MAIN', 'bans_lurker_tested' ], 93 bansLurkerTested => [ 'DICT', 'MAIN.bans_lurker_tested' ],
95 bansTestTested => [ 'MAIN', 'bans_tests_tested' ], 94 bansTestTested => [ 'DICT', 'MAIN.bans_tests_tested' ],
96 bansLurkerTestTested => [ 'MAIN', 'bans_lurker_tests_tested' ], 95 bansLurkerTestTested => [ 'DICT', 'MAIN.bans_lurker_tests_tested' ],
97 bansLurkerObjKilled => [ 'MAIN', 'bans_lurker_obj_killed' ], 96 bansLurkerObjKilled => [ 'DICT', 'MAIN.bans_lurker_obj_killed' ],
98 bansDups => [ 'MAIN', 'bans_dups' ], 97 bansDups => [ 'DICT', 'MAIN.bans_dups' ],
99 bansLurkerContention => [ 'MAIN', 'bans_lurker_contention' ], 98 bansLurkerContention => [ 'DICT', 'MAIN.bans_lurker_contention' ],
100 bansPersistedBytes => [ 'MAIN', 'bans_persisted_bytes' ], 99 bansPersistedBytes => [ 'DICT', 'MAIN.bans_persisted_bytes' ],
101 bansPersistedFragmentation => [ 'MAIN', 'bans_persisted_fragmentation' ], 100 bansPersistedFragmentation => [ 'DICT', 'MAIN.bans_persisted_fragmentation' ],
102 101
103}; 102};
104 103
@@ -118,13 +117,6 @@ $vars{'varnish_translate'} = sub {
118 } else { 117 } else {
119 delete $vars{$setkw}; 118 delete $vars{$setkw};
120 } 119 }
121 if ($vars{'varnish_type'} eq 'MAIN') {
122 $vars{'varnish_if'} = "#if HAVE_STRUCT_VSC_C_MAIN_" . uc($vars{'varnish_member'});
123 $vars{'varnish_endif'} = '#endif';
124 } else {
125 delete $vars{'varnish_if'};
126 delete $vars{'varnish_endif'}
127 }
128 return 0; 120 return 0;
129}; 121};
130 122
@@ -176,16 +168,16 @@ int vcli_read_response(vcli_conn_t *conn);
176int vcli_vasprintf(vcli_conn_t *conn, const char *fmt, va_list ap); 168int vcli_vasprintf(vcli_conn_t *conn, const char *fmt, va_list ap);
177int vcli_asprintf(vcli_conn_t *conn, const char *fmt, ...); 169int vcli_asprintf(vcli_conn_t *conn, const char *fmt, ...);
178void vcli_disconnect(vcli_conn_t *conn); 170void vcli_disconnect(vcli_conn_t *conn);
179int vcli_connect(struct VSM_data *vd, vcli_conn_t *conn); 171int vcli_connect(struct vsm *vsm, vcli_conn_t *conn);
180 172
181struct VSM_data *varnish_get_vsm_data(void); 173struct vsm *varnish_get_vsm_data(void);
182 174
183int varnish_auth_response(const char *file, const char *challenge, 175int varnish_auth_response(const char *file, const char *challenge,
184 char response[CLI_AUTH_RESPONSE_LEN + 1]); 176 char response[CLI_AUTH_RESPONSE_LEN + 1]);
185 177
186int varnish_ban(netsnmp_agent_request_info *reqinfo, 178int varnish_ban(netsnmp_agent_request_info *reqinfo,
187 netsnmp_request_info *requests, 179 netsnmp_request_info *requests,
188 struct VSM_data *vd); 180 struct vsm *vsm);
189 181
190int varnish_mib_timeout_parser(const char *token, char *line, 182int varnish_mib_timeout_parser(const char *token, char *line,
191 unsigned *retval); 183 unsigned *retval);
@@ -193,36 +185,49 @@ int varnish_mib_timeout_parser(const char *token, char *line,
193void varnish_ban_table_timeout_parser(const char *token, char *line); 185void varnish_ban_table_timeout_parser(const char *token, char *line);
194void varnish_vcli_timeout_parser(const char *token, char *line); 186void varnish_vcli_timeout_parser(const char *token, char *line);
195 187
196void varnish_backend_table_timeout_parser(const char *token, char *line); 188int dict_lookup(char const *key, uint64_t *val);
189void dict_install(struct VSC_point const *pt);
190void dict_load(struct vsc *vsc);
197 191
198@open ${name}@ 192@open ${name}@
199/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */ 193/* THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT. */
200 194
201#include "varnish_mib.h" 195#include "varnish_mib.h"
196#include "backend.h"
202 197
203static struct VSM_data *vd; 198static struct vsm *vd;
199static struct vsc *vsc;
204 200
205void 201void
206varnish_snmp_init(void) 202varnish_snmp_init(void)
207{ 203{
208 vd = VSM_New(); 204 vd = VSM_New();
205 if (vd) {
206 vsc = VSC_New(vd);
207 if (vsc) {
208 if (VSM_Attach(vd, 2))
209 fprintf(stderr, "%s\n", VSM_Error(vd));
210 }
211 }
212 dict_load(vsc);
209} 213}
210 214
211void 215void
212varnish_snmp_deinit(void) 216varnish_snmp_deinit(void)
213{ 217{
214 VSM_Close(vd); 218 /* FIXME? */
215} 219}
216 220
217struct VSM_data * 221struct vsm *
218varnish_get_vsm_data() 222varnish_get_vsm_data()
219{ 223{
220 if (VSM_Abandoned(vd)) { 224 if (vd) {
221 DEBUGMSGTL(("$modulename", "reopening vd\n")); 225 if (VSM_Status(vd) & (VSM_MGT_CHANGED|VSM_WRK_CHANGED)) {
222 VSM_Close(vd); 226 DEBUGMSGTL(("$modulename", "reopening vd\n"));
223 VSM_Open(vd); 227 dict_load(vsc);
224 } 228 }
225 return vd; 229 }
230 return vd;
226} 231}
227 232
228/* Variable handlers. 233/* Variable handlers.
@@ -251,24 +256,24 @@ handle_$i(netsnmp_mib_handler *handler,
251 256
252 switch(reqinfo->mode) { 257 switch(reqinfo->mode) {
253 case MODE_GET: 258 case MODE_GET:
254 @if $varnish_type eq 'MAIN'@ 259 @if $varnish_type eq 'DICT'@
255 { 260 {
256 struct VSC_C_main const *st = VSC_Main(vd, NULL); 261 uint64_t val;
262 if (dict_lookup("$varnish_member", &val))
263 return SNMP_ERR_NOSUCHNAME;
257 @if $i.type eq 'ASN_COUNTER64'@ 264 @if $i.type eq 'ASN_COUNTER64'@
265 {
258 struct counter64 ctr; 266 struct counter64 ctr;
259 if (!st) 267 ctr.high = val >> 32;
260 return SNMP_ERR_NOSUCHNAME; 268 ctr.low = val & 0xffffffff;
261 ctr.high = st->$varnish_member >> 32;
262 ctr.low = st->$varnish_member & 0xffffffff;
263 snmp_set_var_typed_value(requests->requestvb, $i.type, 269 snmp_set_var_typed_value(requests->requestvb, $i.type,
264 &ctr, 270 &ctr,
265 sizeof(ctr)); 271 sizeof(ctr));
272 }
266 @else@ 273 @else@
267 if (!st)
268 return SNMP_ERR_NOSUCHNAME;
269 snmp_set_var_typed_value(requests->requestvb, $i.type, 274 snmp_set_var_typed_value(requests->requestvb, $i.type,
270 &st->$varnish_member, 275 &val,
271 sizeof(st->$varnish_member)); 276 sizeof(val));
272 @end@ 277 @end@
273 } 278 }
274 @elsif $varnish_type eq 'STRING'@ 279 @elsif $varnish_type eq 'STRING'@
@@ -297,6 +302,20 @@ handle_$i(netsnmp_mib_handler *handler,
297 snmp_set_var_typed_value(requests->requestvb, $i.type, 302 snmp_set_var_typed_value(requests->requestvb, $i.type,
298 &$varnish_member, sizeof($varnish_member)); 303 &$varnish_member, sizeof($varnish_member));
299 @end@ 304 @end@
305 @elsif $varnish_type eq 'NULL'@
306 {
307 @if $i.type eq 'ASN_COUNTER64'@
308 struct counter64 ctr = { 0, 0};
309 snmp_set_var_typed_value(requests->requestvb, $i.type,
310 &ctr,
311 sizeof(ctr));
312 @else@
313 uint64_t val;
314 snmp_set_var_typed_value(requests->requestvb, $i.type,
315 &val,
316 sizeof(val));
317 @end@
318 }
300 @else@ 319 @else@
301 @printf "unrecognized type %s for %s" $varnish_type $i@ 320 @printf "unrecognized type %s for %s" $varnish_type $i@
302 @end@ 321 @end@
@@ -415,11 +434,11 @@ struct ${i}_entry {
415 @startperl@ 434 @startperl@
416 &{$vars{'set_field_dim'}}($vars{'c'}); 435 &{$vars{'set_field_dim'}}($vars{'c'});
417 @endperl@ 436 @endperl@
418 @if $field_dim > 0@ 437 @if $field_dim > 0@
419 $c.decl ${c}[$field_dim]; 438 $c.decl ${c}[$field_dim];
420 @else@ 439 @else@
421 $c.decl *$c; 440 $c.decl *$c;
422 @end@ 441 @end@
423 size_t ${c}_len; 442 size_t ${c}_len;
424 @else@ 443 @else@
425 $c.decl $c; 444 $c.decl $c;
@@ -567,13 +586,11 @@ $varnish_endif
567 NULL, 586 NULL,
568 "varnishBanTableTimeout SECONDS")) 587 "varnishBanTableTimeout SECONDS"))
569 snmp_log(LOG_ERR,"can't register config handler\n"); 588 snmp_log(LOG_ERR,"can't register config handler\n");
570
571 if (!register_config_handler("snmpd", "varnishBackendTableTimeout", 589 if (!register_config_handler("snmpd", "varnishBackendTableTimeout",
572 varnish_backend_table_timeout_parser, 590 varnish_backend_table_timeout_parser,
573 NULL, 591 NULL,
574 "varnishBackendTableTimeout SECONDS")) 592 "varnishBackendTableTimeout SECONDS"))
575 snmp_log(LOG_ERR,"can't register config handler\n"); 593 snmp_log(LOG_ERR,"can't register config handler\n");
576
577 if (!register_config_handler("snmpd", "varnishCLIPortTimeout", 594 if (!register_config_handler("snmpd", "varnishCLIPortTimeout",
578 varnish_vcli_timeout_parser, 595 varnish_vcli_timeout_parser,
579 NULL, 596 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)
424} 424}
425 425
426int 426int
427vcli_connect(struct VSM_data *vd, struct vcli_conn *conn) 427vcli_connect(struct vsm *vsm, struct vcli_conn *conn)
428{ 428{
429 struct VSM_fantom vt;
430 struct sockaddr_in vcli_sa; 429 struct sockaddr_in vcli_sa;
431 char *s, *portstr, *p; 430 char *portstr, *p;
432 unsigned long n; 431 unsigned long n;
433 short pn; 432 short pn;
434 struct hostent *hp; 433 struct hostent *hp;
435 434 char *T_arg = NULL, *S_arg = NULL;
436 memset(conn, 0, sizeof(*conn)); 435 memset(conn, 0, sizeof(*conn));
437 436
438 if (!VSM_Get(vd, &vt, "Arg", "-T", "")) { 437 T_arg = VSM_Dup(vsm, "Arg", "-T");
438 if (!T_arg) {
439 snmp_log(LOG_ERR, "no -T arg in shared memory\n"); 439 snmp_log(LOG_ERR, "no -T arg in shared memory\n");
440 return SNMP_ERR_GENERR; 440 return SNMP_ERR_GENERR;
441 } 441 }
442 DEBUGMSGTL(("varnish_mib:vcli", "-T '%s'\n", (char*) vt.b)); 442 S_arg = VSM_Dup(vsm, "Arg", "-S");
443 if (!S_arg) {
444 free(T_arg);
445 snmp_log(LOG_ERR, "no -S arg in shared memory\n");
446 return SNMP_ERR_GENERR;
447 }
443 448
444 s = strdup(vt.b); 449 DEBUGMSGTL(("varnish_mib:vcli", "-T '%s'\n", (char*) T_arg));
445 if (!s) { 450
446 snmp_log(LOG_ERR, "out of memory\n"); 451 for (portstr = T_arg; !ISSPACE(*portstr); portstr++)
447 return SNMP_ERR_GENERR;
448 }
449 for (portstr = s; !ISSPACE(*portstr); portstr++)
450 ; 452 ;
451 if (!*portstr) { 453 if (!*portstr) {
452 snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", s); 454 snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", T_arg);
453 free(s); 455 free(T_arg);
456 free(S_arg);
454 return SNMP_ERR_GENERR; 457 return SNMP_ERR_GENERR;
455 } 458 }
456 for (*portstr++ = 0; ISSPACE(*portstr); portstr++) 459 for (*portstr++ = 0; ISSPACE(*portstr); portstr++)
@@ -458,44 +461,40 @@ vcli_connect(struct VSM_data *vd, struct vcli_conn *conn)
458 461
459 n = pn = strtoul(portstr, &p, 0); 462 n = pn = strtoul(portstr, &p, 0);
460 if (n != pn || (*p && !ISSPACE(*p))) { 463 if (n != pn || (*p && !ISSPACE(*p))) {
461 snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", s); 464 snmp_log(LOG_ERR, "unrecognized -T arg: %s\n", T_arg);
462 free(s); 465 free(T_arg);
466 free(S_arg);
463 return SNMP_ERR_GENERR; 467 return SNMP_ERR_GENERR;
464 } 468 }
465 469
466 hp = gethostbyname(s); 470 hp = gethostbyname(T_arg);
467 if (!hp) { 471 if (!hp) {
468 snmp_log(LOG_ERR, "unknown host name %s\n", s); 472 snmp_log(LOG_ERR, "unknown host name %s\n", T_arg);
469 free(s); 473 free(T_arg);
474 free(S_arg);
470 return SNMP_ERR_GENERR; 475 return SNMP_ERR_GENERR;
471 } 476 }
472 477
473 vcli_sa.sin_family = hp->h_addrtype; 478 vcli_sa.sin_family = hp->h_addrtype;
474 if (vcli_sa.sin_family != AF_INET) { 479 if (vcli_sa.sin_family != AF_INET) {
475 snmp_log(LOG_ERR, "unknown host name %s\n", s); 480 snmp_log(LOG_ERR, "unknown host name %s\n", T_arg);
476 free(s); 481 free(T_arg);
482 free(S_arg);
477 return SNMP_ERR_GENERR; 483 return SNMP_ERR_GENERR;
478 } 484 }
479 485
480 memmove(&vcli_sa.sin_addr, hp->h_addr, 4); 486 memmove(&vcli_sa.sin_addr, hp->h_addr, 4);
481 vcli_sa.sin_port = htons(pn); 487 vcli_sa.sin_port = htons(pn);
482 488
483 conn->fd = open_socket(&vcli_sa, s); 489 conn->fd = open_socket(&vcli_sa, T_arg);
484 free(s); 490 free(T_arg);
485 if (conn->fd == -1) 491 if (conn->fd == -1) {
486 return SNMP_ERR_GENERR; 492 free(S_arg);
487
488 if (!VSM_Get(vd, &vt, "Arg", "-S", "")) {
489 snmp_log(LOG_ERR, "no -S arg in shared memory\n");
490 return SNMP_ERR_GENERR;
491 }
492 DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", (char*) vt.b));
493 s = strdup(vt.b);
494 if (!s) {
495 snmp_log(LOG_ERR, "out of memory\n");
496 return SNMP_ERR_GENERR; 493 return SNMP_ERR_GENERR;
497 } 494 }
498 conn->secret = s; 495
496 DEBUGMSGTL(("varnish_mib:vcli", "-S '%s'\n", S_arg));
497 conn->secret = S_arg;
499 498
500 if (vcli_handshake(conn)) { 499 if (vcli_handshake(conn)) {
501 vcli_disconnect(conn); 500 vcli_disconnect(conn);

Return to:

Send suggestions and report system problems to the System administrator.