aboutsummaryrefslogtreecommitdiff
path: root/src/vcli.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcli.c')
-rw-r--r--src/vcli.c228
1 files changed, 141 insertions, 87 deletions
diff --git a/src/vcli.c b/src/vcli.c
index 499c365..2683c9d 100644
--- a/src/vcli.c
+++ b/src/vcli.c
@@ -25,14 +25,67 @@
#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
@@ -146,7 +199,7 @@ vcli_read(struct vcli_conn *conn, size_t size)
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;
@@ -229,7 +282,7 @@ 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);
@@ -316,14 +369,14 @@ vcli_asprintf(struct vcli_conn *conn, const char *fmt, ...)
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;
@@ -334,7 +387,7 @@ open_socket(struct sockaddr_in *sa, const char *connstr)
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) {
@@ -354,12 +407,22 @@ open_socket(struct sockaddr_in *sa, const char *connstr)
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;
@@ -423,82 +486,73 @@ vcli_handshake(struct vcli_conn *conn)
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;
}

Return to:

Send suggestions and report system problems to the System administrator.