[PATCH 0/1] reg-tests fix.

2019-04-19 Thread flecaille
From: Frédéric Lécaille 

Hi ML,
Here is a little patch to fix the reg tests with missing REQUIRE_VERSION 
declarations.

Fred.

Frédéric Lécaille (1):
  REGTEST: Missing REQUIRE_VERSION declarations.

 reg-tests/checks/s1.vtc  | 1 +
 reg-tests/peers/s_basic_sync.vtc | 2 ++
 reg-tests/peers/s_tls_basic_sync.vtc | 1 +
 3 files changed, 4 insertions(+)

-- 
2.11.0



[PATCH 1/1] REGTEST: Missing REQUIRE_VERSION declarations.

2019-04-19 Thread flecaille
From: Frédéric Lécaille 

checks/s1.vtc needs support for "srvrecord" which came with 1.8 version.
peers/s_basic_sync.vtc and s_tls_basic_sync.vtc need support for "server"
keyword usage in "peers" section which came with 2.0 version.
---
 reg-tests/checks/s1.vtc  | 1 +
 reg-tests/peers/s_basic_sync.vtc | 2 ++
 reg-tests/peers/s_tls_basic_sync.vtc | 1 +
 3 files changed, 4 insertions(+)

diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc
index abb0f2fc1..2e38867c8 100644
--- a/reg-tests/checks/s1.vtc
+++ b/reg-tests/checks/s1.vtc
@@ -6,6 +6,7 @@ feature ignore_unknown_macro
 # The first health-checks passed tests are checked for all these servers
 # thanks to syslog messages.
 
+#REQUIRE_VERSION=1.8
 #EXCLUDE_TARGETS=freebsd
 
 # Note that the first syslog message received is: "Proxy  started."
diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc
index 4e35054b3..ecf8fd059 100644
--- a/reg-tests/peers/s_basic_sync.vtc
+++ b/reg-tests/peers/s_basic_sync.vtc
@@ -1,6 +1,8 @@
 vtest "Basic test for peers protocol"
 feature ignore_unknown_macro
 
+#REQUIRE_VERSION=2.0
+
 haproxy h1 -arg "-L A" -conf {
 defaults
 timeout client  1s
diff --git a/reg-tests/peers/s_tls_basic_sync.vtc 
b/reg-tests/peers/s_tls_basic_sync.vtc
index 6710d3196..41e874b4d 100644
--- a/reg-tests/peers/s_tls_basic_sync.vtc
+++ b/reg-tests/peers/s_tls_basic_sync.vtc
@@ -1,5 +1,6 @@
 vtest "Basic test for peers protocol over SSL/TLS"
 #REQUIRE_OPTIONS=OPENSSL
+#REQUIRE_VERSION=2.0
 feature ignore_unknown_macro
 
 haproxy h1 -arg "-L A" -conf {
-- 
2.11.0



[PATCH 1/1] REGTEST: Peers reg tests.

2019-01-18 Thread flecaille
This is a better patch to update only reg-tests/peers/s_tls_basic_sync.vtc:

We add a 4th haproxy process seen as peer D, without any encryption enabled for
all the four peers A,B,C and D.
On the three first haproxy instances side A,B, C, we declare D with ssl/tls
activated. Consequently D cannot be synched with A or B or C. This is what is
checked with D CLI: no stick-table entry may have been synchronized with A, B
and C.

Fred.



[PATCH] REGTEST: Peers reg tests.

2019-01-18 Thread flecaille
From: Frédéric Lécaille 

---
 reg-tests/peers/common.pem   |   1 +
 reg-tests/peers/s_basic_sync.vtc | 115 +++
 reg-tests/peers/s_tls_basic_sync.vtc | 150 +++
 3 files changed, 266 insertions(+)
 create mode 12 reg-tests/peers/common.pem
 create mode 100644 reg-tests/peers/s_basic_sync.vtc
 create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc

diff --git a/reg-tests/peers/common.pem b/reg-tests/peers/common.pem
new file mode 12
index ..a4433d56
--- /dev/null
+++ b/reg-tests/peers/common.pem
@@ -0,0 +1 @@
+../ssl/common.pem
\ No newline at end of file
diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc
new file mode 100644
index ..4e35054b
--- /dev/null
+++ b/reg-tests/peers/s_basic_sync.vtc
@@ -0,0 +1,115 @@
+vtest "Basic test for peers protocol"
+feature ignore_unknown_macro
+
+haproxy h1 -arg "-L A" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${A}"
+server A
+server B ${h2_B_addr}:${h2_B_port}
+server C ${h3_C_addr}:${h3_C_port}
+
+frontend fe
+bind "fd@${fe}"
+tcp-request content track-sc0 url table stkt
+tcp-request content sc-inc-gpc0(0)
+}
+
+haproxy h2 -arg "-L B" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${B}"
+server A ${h1_A_addr}:${h1_A_port}
+server B
+server C ${h3_C_addr}:${h3_C_port}
+
+frontend fe
+bind "fd@${fe}"
+http-request track-sc0 url table stkt
+http-request sc-inc-gpc0(0)
+}
+
+haproxy h3 -arg "-L C" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${C}"
+server A ${h1_A_addr}:${h1_A_port}
+server B ${h2_B_addr}:${h2_B_port}
+server C
+
+frontend fe
+bind "fd@${fe}"
+http-request track-sc0 url table stkt
+http-request sc-inc-gpc0(0)
+}
+
+client c1 -connect ${h1_fe_sock} {
+txreq -url "c1_client"
+expect_close
+} -start
+
+client c2 -connect ${h1_fe_sock} {
+txreq -url "c2_client"
+expect_close
+} -start
+
+client c3 -connect ${h1_fe_sock} {
+txreq -url "c3_client"
+expect_close
+} -start
+
+client c4 -connect ${h1_fe_sock} {
+txreq -url "c4_client"
+expect_close
+} -start
+
+haproxy h1 -start
+delay 0.2
+haproxy h2 -start
+delay 0.2
+haproxy h3 -start
+delay 0.2
+
+client c1 -wait
+client c2 -wait
+client c3 -wait
+client c4 -wait
+
+delay 2
+
+haproxy h1 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
+haproxy h2 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
+haproxy h3 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
diff --git a/reg-tests/peers/s_tls_basic_sync.vtc 
b/reg-tests/peers/s_tls_basic_sync.vtc
new file mode 100644
index ..81ab7ba1
--- /dev/null
+++ b/reg-tests/peers/s_tls_basic_sync.vtc
@@ -0,0 +1,150 @@
+vtest "Basic test for peers protocol over SSL/TLS"
+feature ignore_unknown_macro
+
+haproxy h1 -arg "-L A" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+default-server ssl crt ${testdir}/common.pem verify none
+bind "fd@${A}" ssl crt ${testdir}/common.pem
+server A
+server B ${h2_B_addr}:${h2_B_port}
+server C ${h3_C_addr}:${h3_C_port}
+server D ${h4_D_addr}:${h4_D_port}
+
+frontend fe
+bind "fd@${fe}"
+tcp-request content track-sc0 url table stkt
+tcp-request content sc-inc-gpc0(0)
+}
+
+haproxy h2 -arg "-L B" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+ 

[PATCH 0/1] Peers reg tests.

2019-01-17 Thread flecaille
From: Frédéric Lécaille 

Hi ML,

Here are new reg tests for peers.
They are supposed to test the SSL/TLS support for haproxy peer protocol.
(see https://www.mail-archive.com/haproxy@formilux.org/msg32438.html).

Furthermore, vtest fixes are required:
https://github.com/vtest/VTest/pull/9
Let's wait for PHK validation.

Fred.

Frédéric Lécaille (1):
  REGTEST: Peers reg tests.

 reg-tests/peers/common.pem   |   1 +
 reg-tests/peers/s_basic_sync.vtc | 115 ++
 reg-tests/peers/s_tls_basic_sync.vtc | 118 +++
 3 files changed, 234 insertions(+)
 create mode 12 reg-tests/peers/common.pem
 create mode 100644 reg-tests/peers/s_basic_sync.vtc
 create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc

-- 
2.11.0



[PATCH 1/1] REGTEST: Peers reg tests.

2019-01-17 Thread flecaille
From: Frédéric Lécaille 

---
 reg-tests/peers/common.pem   |   1 +
 reg-tests/peers/s_basic_sync.vtc | 115 ++
 reg-tests/peers/s_tls_basic_sync.vtc | 118 +++
 3 files changed, 234 insertions(+)
 create mode 12 reg-tests/peers/common.pem
 create mode 100644 reg-tests/peers/s_basic_sync.vtc
 create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc

diff --git a/reg-tests/peers/common.pem b/reg-tests/peers/common.pem
new file mode 12
index ..a4433d56
--- /dev/null
+++ b/reg-tests/peers/common.pem
@@ -0,0 +1 @@
+../ssl/common.pem
\ No newline at end of file
diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc
new file mode 100644
index ..4e35054b
--- /dev/null
+++ b/reg-tests/peers/s_basic_sync.vtc
@@ -0,0 +1,115 @@
+vtest "Basic test for peers protocol"
+feature ignore_unknown_macro
+
+haproxy h1 -arg "-L A" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${A}"
+server A
+server B ${h2_B_addr}:${h2_B_port}
+server C ${h3_C_addr}:${h3_C_port}
+
+frontend fe
+bind "fd@${fe}"
+tcp-request content track-sc0 url table stkt
+tcp-request content sc-inc-gpc0(0)
+}
+
+haproxy h2 -arg "-L B" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${B}"
+server A ${h1_A_addr}:${h1_A_port}
+server B
+server C ${h3_C_addr}:${h3_C_port}
+
+frontend fe
+bind "fd@${fe}"
+http-request track-sc0 url table stkt
+http-request sc-inc-gpc0(0)
+}
+
+haproxy h3 -arg "-L C" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+bind "fd@${C}"
+server A ${h1_A_addr}:${h1_A_port}
+server B ${h2_B_addr}:${h2_B_port}
+server C
+
+frontend fe
+bind "fd@${fe}"
+http-request track-sc0 url table stkt
+http-request sc-inc-gpc0(0)
+}
+
+client c1 -connect ${h1_fe_sock} {
+txreq -url "c1_client"
+expect_close
+} -start
+
+client c2 -connect ${h1_fe_sock} {
+txreq -url "c2_client"
+expect_close
+} -start
+
+client c3 -connect ${h1_fe_sock} {
+txreq -url "c3_client"
+expect_close
+} -start
+
+client c4 -connect ${h1_fe_sock} {
+txreq -url "c4_client"
+expect_close
+} -start
+
+haproxy h1 -start
+delay 0.2
+haproxy h2 -start
+delay 0.2
+haproxy h3 -start
+delay 0.2
+
+client c1 -wait
+client c2 -wait
+client c3 -wait
+client c4 -wait
+
+delay 2
+
+haproxy h1 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
+haproxy h2 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
+haproxy h3 -cli {
+send "show table stkt"
+expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, 
used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 
conn_rate\\(5\\)=1 conn_cur=0){4}"
+}
+
diff --git a/reg-tests/peers/s_tls_basic_sync.vtc 
b/reg-tests/peers/s_tls_basic_sync.vtc
new file mode 100644
index ..3c1428e3
--- /dev/null
+++ b/reg-tests/peers/s_tls_basic_sync.vtc
@@ -0,0 +1,118 @@
+vtest "Basic test for peers protocol over SSL/TLS"
+feature ignore_unknown_macro
+
+haproxy h1 -arg "-L A" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+default-server ssl crt ${testdir}/common.pem verify none
+bind "fd@${A}" ssl crt ${testdir}/common.pem
+server A
+server B ${h2_B_addr}:${h2_B_port}
+server C ${h3_C_addr}:${h3_C_port}
+
+frontend fe
+bind "fd@${fe}"
+tcp-request content track-sc0 url table stkt
+tcp-request content sc-inc-gpc0(0)
+}
+
+haproxy h2 -arg "-L B" -conf {
+defaults
+timeout client  1s
+timeout connect 1s
+timeout server  1s
+
+backend stkt
+stick-table type string size 10m store 
server_id,gpc0,conn_cur,conn_rate(5) peers peers
+
+peers peers
+default-serve

[PATCH 08/12] MINOR: peers: Make outgoing connection to SSL/TLS peers work.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

This patch adds pointer to a struct server to peer structure which
is initialized after having parsed a remote "peer" line.

After having parsed all peers section we run ->prepare_srv to initialize
all SSL/TLS stuff of remote perr (or server).

Remaining thing to do to completely support peer protocol over SSL/TLS:
make "bind" keyword be supported in "peers" sections to make SSL/TLS
incoming connections to local peers work.

May be backported to 1.5 and newer.
---
 include/proto/peers.h | 26 ++
 include/types/peers.h |  1 +
 src/cfgparse.c| 13 +++--
 src/peers.c   |  5 +++--
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/proto/peers.h b/include/proto/peers.h
index 9d4aaff2..ce4feaa4 100644
--- a/include/proto/peers.h
+++ b/include/proto/peers.h
@@ -25,9 +25,35 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#if defined(USE_OPENSSL)
+static inline enum obj_type *peer_session_target(struct peer *p, struct stream 
*s)
+{
+   if (p->srv->use_ssl)
+   return &p->srv->obj_type;
+   else
+   return &s->be->obj_type;
+}
+
+static inline struct xprt_ops *peer_xprt(struct peer *p)
+{
+   return p->srv->use_ssl ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW);
+}
+#else
+static inline enum obj_type *peer_session_target(struct peer *p, struct stream 
*s)
+{
+   return &s->be->obj_type;
+}
+
+static inline struct xprt_ops *peer_xprt(struct peer *p)
+{
+   return xprt_get(XPRT_RAW);
+}
+#endif
+
 int peers_init_sync(struct peers *peers);
 void peers_register_table(struct peers *, struct stktable *table);
 void peers_setup_frontend(struct proxy *fe);
diff --git a/include/types/peers.h b/include/types/peers.h
index 58c8c4ee..5200d56b 100644
--- a/include/types/peers.h
+++ b/include/types/peers.h
@@ -67,6 +67,7 @@ struct peer {
struct shared_table *remote_table;
struct shared_table *last_local_table;
struct shared_table *tables;
+   struct server *srv;
__decl_hathreads(HA_SPINLOCK_T lock); /* lock used to handle this peer 
section */
struct peer *next;/* next peer in the list */
 };
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6d199c97..f6f25143 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -514,6 +514,7 @@ static int init_peers_frontend(const char *file, int 
linenum,
  out:
if (id && !p->id)
p->id = strdup(id);
+   free(p->conf.file);
p->conf.args.file = p->conf.file = strdup(file);
p->conf.args.line = p->conf.line = linenum;
 
@@ -624,9 +625,10 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->sock_init_arg = NULL;
HA_SPIN_INIT(&newpeer->lock);
 
-   if (strcmp(newpeer->id, localpeer) != 0)
-   /* We are done. */
+   if (strcmp(newpeer->id, localpeer) != 0) {
+   newpeer->srv = curpeers->peers_fe->srv;
goto out;
+   }
 
if (cfg_peers->local) {
ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
@@ -3634,6 +3636,13 @@ out_uri_auth_compat:
curpeers->peers_fe = NULL;
}
else {
+   p = curpeers->remote;
+   while (p) {
+   if (p->srv && p->srv->use_ssl &&
+   xprt_get(XPRT_SSL) && 
xprt_get(XPRT_SSL)->prepare_srv)
+   cfgerr += 
xprt_get(XPRT_SSL)->prepare_srv(p->srv);
+   p = p->next;
+   }
if (!peers_init_sync(curpeers)) {
ha_alert("Peers section '%s': out of 
memory, giving up on peers.\n",
 curpeers->id);
diff --git a/src/peers.c b/src/peers.c
index e580f2ca..d4d3859e 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1996,10 +1997,10 @@ static struct appctx *peer_session_create(struct peers 
*peers, struct peer *peer
if (unlikely((cs = cs_new(conn)) == NULL))
goto out_free_conn;
 
-   conn->target = s->target = &s->be->obj_type;
+   conn->target = s->target = peer_session_target(peer, s);
memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to));
 
-   conn_prepare(conn, peer->proto, peer->xprt);
+   conn_prepare(conn, peer->proto, peer_xprt(peer));
conn_install_mux(conn, &mux_pt_ops, cs, s->be, NULL);
si_attach_cs(&s->si[1], cs);
 
-- 
2.11.0



[PATCH 11/12] MINOR: peers: Less confusing peer binding parsing.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

With this patch the "server" lines do not parse anymore the bind address
for local peers.
We do not use anymore list_for_each_entry() to set the "peers" section
listeners parameter because there is only one listener by "peers" section.
---
 include/proto/server.h |  2 +-
 src/cfgparse-listen.c  |  2 +-
 src/cfgparse.c | 58 --
 src/server.c   | 10 ++---
 4 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/include/proto/server.h b/include/proto/server.h
index b3a9b877..436ffb5d 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -39,7 +39,7 @@
 int srv_downtime(const struct server *s);
 int srv_lastsession(const struct server *s);
 int srv_getinter(const struct check *check);
-int parse_server(const char *file, int linenum, char **args, struct proxy 
*curproxy, struct proxy *defproxy);
+int parse_server(const char *file, int linenum, char **args, struct proxy 
*curproxy, struct proxy *defproxy, int parse_addr);
 int update_server_addr(struct server *s, void *ip, int ip_sin_family, const 
char *updater);
 const char *update_server_addr_port(struct server *s, const char *addr, const 
char *port, char *updater);
 struct server *server_find_by_id(struct proxy *bk, int id);
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index aa2d8608..fdbdfd34 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -677,7 +677,7 @@ int cfg_parse_listen(const char *file, int linenum, char 
**args, int kwm)
if (!strcmp(args[0], "server") ||
!strcmp(args[0], "default-server") ||
!strcmp(args[0], "server-template")) {
-   err_code |= parse_server(file, linenum, args, curproxy, 
&defproxy);
+   err_code |= parse_server(file, linenum, args, curproxy, 
&defproxy, 1);
if (err_code & ERR_FATAL)
goto out;
}
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 2a6a4839..4d0a9ade 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -623,8 +623,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum,
 NULL, xprt_get(XPRT_RAW));
if (*args[0] == 'b') {
-   struct sockaddr_storage *sk;
-   int port, port1, port2;
+   struct listener *l;
 
if (peer_line) {
ha_alert("parsing [%s:%d] : mixing \"peer\" and 
\"bind\" line is forbidden\n", file, linenum);
@@ -632,13 +631,26 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
goto out;
}
 
-   sk = str2sa_range(args[1], &port, &port1, &port2, 
&errmsg, NULL, NULL, 0);
-   if (!sk) {
-   ha_alert("parsing [%s:%d]: '%s %s': %s\n",
-file, linenum, args[0], 
args[1], errmsg);
-   err_code |= ERR_ALERT | ERR_FATAL;
+   if (!str2listener(args[1], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing +[%s:%d] : '%s %s' : 
%s\n", file, linenum, args[0], args[1], errmsg);
+   }
+   else
+   ha_alert("parsing [%s:%d] : '%s %s' : 
error encountered while parsing listening address %s.\n",
+file, linenum, 
args[0], args[1], args[2]);
+   err_code |= ERR_FATAL;
goto out;
}
+   l = LIST_ELEM(bind_conf->listeners.n, typeof(l), 
by_bind);
+   l->maxaccept = 1;
+   l->maxconn = curpeers->peers_fe->maxconn;
+   l->backlog = curpeers->peers_fe->backlog;
+   l->accept = session_accept_fd;
+   l->analysers |=  curpeers->peers_fe->fe_req_ana;
+   l->default_target = curpeers->peers_fe->default_target;
+   l->options |= LI_O_UNLIMITED; /* don't make the peers 
subject to global limits */
+   global.maxsock += l->maxconn;
 
bind_line = 1;
if (cfg_peers->local) {
@@ -655,7 +667,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
goto out;
}
}
-   newpeer->addr = *sk;
+

[PATCH 01/12] MINOR: cfgparse: Extract some code to be re-used.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Create init_peers_frontend() function to allocate and initialize
the frontend of "peers" sections (->peers_fe) so that to reuse it later.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 34 ++
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 7c316df0..6fde7c9f 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -483,6 +483,31 @@ void init_default_instance()
defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
 }
 
+/* Allocate and initialize the frontend of a "peers" section found in
+ * file  at line  with  as ID.
+ * Return 0 if succeeded, -1 if not.
+ */
+static int init_peers_frontend(const char *file, int linenum,
+   const char *id, struct peers *peers)
+{
+   struct proxy *p;
+
+   p = calloc(1, sizeof *p);
+   if (!p) {
+   ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
+   return -1;
+   }
+
+   init_new_proxy(p);
+   p->parent = peers;
+   p->id = strdup(id);
+   p->conf.args.file = p->conf.file = strdup(file);
+   p->conf.args.line = p->conf.line = linenum;
+   peers_setup_frontend(p);
+   peers->peers_fe = p;
+
+   return 0;
+}
 
 /*
  * Parse a line in a ,  or  section.
@@ -625,19 +650,12 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
cfg_peers->local = newpeer;
 
if (!curpeers->peers_fe) {
-   if ((curpeers->peers_fe  = calloc(1, 
sizeof(struct proxy))) == NULL) {
+   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
ha_alert("parsing [%s:%d] : out of 
memory.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
}
 
-   init_new_proxy(curpeers->peers_fe);
-   curpeers->peers_fe->parent = curpeers;
-   curpeers->peers_fe->id = strdup(args[1]);
-   curpeers->peers_fe->conf.args.file = 
curpeers->peers_fe->conf.file = strdup(file);
-   curpeers->peers_fe->conf.args.line = 
curpeers->peers_fe->conf.line = linenum;
-   peers_setup_frontend(curpeers->peers_fe);
-
bind_conf = bind_conf_alloc(curpeers->peers_fe, 
file, linenum, args[2], xprt_get(XPRT_RAW));
 
if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-- 
2.11.0



[PATCH 07/12] MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

With this patch "default-server" lines are supported in "peers" sections
to setup the default settings of peers which are from now setup
when parsing both "peer" and "server" lines.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 88 +++---
 src/peers.c|  2 +-
 src/server.c   |  3 +-
 3 files changed, 32 insertions(+), 61 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 715faaef..6d199c97 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -486,15 +486,18 @@ void init_default_instance()
 /* Allocate and initialize the frontend of a "peers" section found in
  * file  at line  with  as ID.
  * Return 0 if succeeded, -1 if not.
+ * Note that this function may be called from "default-server"
+ * or "peer" lines.
  */
 static int init_peers_frontend(const char *file, int linenum,
const char *id, struct peers *peers)
 {
struct proxy *p;
 
-   if (peers->peers_fe)
-   /* Nothing to do */
-   return 0;
+   if (peers->peers_fe) {
+   p = peers->peers_fe;
+   goto out;
+   }
 
p = calloc(1, sizeof *p);
if (!p) {
@@ -503,12 +506,16 @@ static int init_peers_frontend(const char *file, int 
linenum,
}
 
init_new_proxy(p);
+   peers_setup_frontend(p);
p->parent = peers;
-   p->id = strdup(id);
+   /* Finally store this frontend. */
+   peers->peers_fe = p;
+
+ out:
+   if (id && !p->id)
+   p->id = strdup(id);
p->conf.args.file = p->conf.file = strdup(file);
p->conf.args.line = p->conf.line = linenum;
-   peers_setup_frontend(p);
-   peers->peers_fe = p;
 
return 0;
 }
@@ -533,7 +540,14 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
int err_code = 0;
char *errmsg = NULL;
 
-   if (strcmp(args[0], "peers") == 0) { /* new peers section */
+   if (strcmp(args[0], "default-server") == 0) {
+   if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
+   err_code |= parse_server(file, linenum, args, 
curpeers->peers_fe, NULL);
+   }
+   else if (strcmp(args[0], "peers") == 0) { /* new peers section */
if (!*args[1]) {
ha_alert("parsing [%s:%d] : missing name for peers 
section.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
@@ -577,26 +591,8 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
curpeers->id = strdup(args[1]);
curpeers->state = PR_STNEW;
}
-   else if (strcmp(args[0], "peer") == 0) { /* peer definition */
-   struct sockaddr_storage *sk;
-   int port1, port2;
-   struct protocol *proto;
-
-   if (!*args[2]) {
-   ha_alert("parsing [%s:%d] : '%s' expects  and 
[:] as arguments.\n",
-file, linenum, args[0]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   err = invalid_char(args[1]);
-   if (err) {
-   ha_alert("parsing [%s:%d] : character '%c' is not 
permitted in server name '%s'.\n",
-file, linenum, *err, args[1]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
+   else if (strcmp(args[0], "peer") == 0 ||
+strcmp(args[0], "server") == 0) { /* peer or server definition 
*/
if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, 
linenum);
err_code |= ERR_ALERT | ERR_ABORT;
@@ -613,37 +609,17 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->last_change = now.tv_sec;
newpeer->id = strdup(args[1]);
 
-   sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, 
NULL, 1);
-   if (!sk) {
-   ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, 
linenum, args[0], args[1], errmsg);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   proto = protocol_by_family(sk->ss_family);
-   if (!proto || !proto->connect) {
-   ha_alert("parsing [%s:%d] : '%s %s' : connect() not 
supported for this address family.\n",
-file, linenum, args[0], args[1]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   if (port1 != port

[PATCH 09/12] MINOR: cfgparse: SSL/TLS binding in "peers" sections.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

This patch makes "bind" work in "peers" sections. All "bind" settings
are supported, excepted ip:port parameters which are provided on
"peer" (or server) line matching the local peer.
After having parsed the configuration files ->prepare_bind_conf is run
to initialize all SSL/TLS stuff for the local peer.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 95 ++
 1 file changed, 90 insertions(+), 5 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index f6f25143..ef69b37d 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -521,6 +521,31 @@ static int init_peers_frontend(const char *file, int 
linenum,
return 0;
 }
 
+/* Only change ->file, ->line and ->arg struct bind_conf member values
+ * if already present.
+ */
+static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p,
+  const char *file, int line,
+  const char *arg, struct xprt_ops 
*xprt)
+{
+   struct bind_conf *bind_conf;
+
+   if (!LIST_ISEMPTY(&p->conf.bind)) {
+   bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), 
by_fe);
+   free(bind_conf->file);
+   bind_conf->file = strdup(file);
+   bind_conf->line = line;
+   if (arg) {
+   free(bind_conf->arg);
+   bind_conf->arg = strdup(arg);
+   }
+   }
+   else {
+   bind_conf = bind_conf_alloc(p, file, line, arg, xprt);
+   }
+
+   return bind_conf;
+}
 /*
  * Parse a line in a ,  or  section.
  * Returns the error code, 0 if OK, or any combination of :
@@ -541,7 +566,56 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
int err_code = 0;
char *errmsg = NULL;
 
-   if (strcmp(args[0], "default-server") == 0) {
+   if (strcmp(args[0], "bind") == 0) {
+   int cur_arg;
+   static int kws_dumped;
+   struct bind_conf *bind_conf;
+   struct bind_kw *kw;
+   char *kws;
+
+   cur_arg = 1;
+
+   if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
+
+   bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum,
+NULL, xprt_get(XPRT_RAW));
+   while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) {
+   int ret;
+
+   ret = kw->parse(args, cur_arg, curpeers->peers_fe, 
bind_conf, &errmsg);
+   err_code |= ret;
+   if (ret) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : %s\n", 
file, linenum, errmsg);
+   }
+   else
+   ha_alert("parsing [%s:%d]: error 
encountered while processing '%s'\n",
+file, linenum, args[cur_arg]);
+   if (ret & ERR_FATAL)
+   goto out;
+   }
+   cur_arg += 1 + kw->skip;
+   }
+   kws = NULL;
+   if (!kws_dumped) {
+   kws_dumped = 1;
+   bind_dump_kws(&kws);
+   indent_msg(&kws, 4);
+   }
+   if (*args[cur_arg] != 0) {
+   ha_alert("parsing [%s:%d] : unknown keyword '%s' in 
'%s' section.%s%s\n",
+file, linenum, args[cur_arg], cursection,
+kws ? " Registered keywords :" : "", kws ? 
kws: "");
+   free(kws);
+   err_code |= ERR_ALERT | ERR_FATAL;
+   goto out;
+   }
+   }
+   else if (strcmp(args[0], "default-server") == 0) {
if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
@@ -641,7 +715,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, 
args[2], xprt_get(XPRT_RAW));
+   bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
 
if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, 
linenum, &errmsg)) {
if (errmsg && *errmsg) {

[PATCH 05/12] MINOR: cfgparse: Rework peers frontend init.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Even if not already the case, we suppose that the frontend "peers" section
may have been already initialized outside of "peer" line, we seperate
their initializations from their binding initializations.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 50 --
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index e3e96b51..22a3da72 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -659,39 +659,37 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   if (!curpeers->peers_fe) {
-   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
+   if (!curpeers->peers_fe &&
+   init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
-   }
-
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
+   }
 
-   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-   if (errmsg && *errmsg) {
-   indent_msg(&errmsg, 2);
-   ha_alert("parsing [%s:%d] : '%s %s' : 
%s\n", file, linenum, args[0], args[1], errmsg);
-   }
-   else
-   ha_alert("parsing [%s:%d] : '%s %s' : 
error encountered while parsing listening address %s.\n",
-file, linenum, args[0], 
args[1], args[2]);
-   err_code |= ERR_FATAL;
-   goto out;
-   }
+   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, 
args[2], xprt_get(XPRT_RAW));
 
-   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
-   l->maxaccept = 1;
-   l->maxconn = curpeers->peers_fe->maxconn;
-   l->backlog = curpeers->peers_fe->backlog;
-   l->accept = session_accept_fd;
-   l->analysers |=  curpeers->peers_fe->fe_req_ana;
-   l->default_target = 
curpeers->peers_fe->default_target;
-   l->options |= LI_O_UNLIMITED; /* don't make the 
peers subject to global limits */
-   global.maxsock += l->maxconn;
+   if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, 
linenum, &errmsg)) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : '%s %s' : %s\n", 
file, linenum, args[0], args[1], errmsg);
}
-   cfg_peers->local = newpeer;
+   else
+   ha_alert("parsing [%s:%d] : '%s %s' : error 
encountered while parsing listening address %s.\n",
+file, linenum, args[0], args[1], 
args[2]);
+   err_code |= ERR_FATAL;
+   goto out;
}
+   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+   l->maxaccept = 1;
+   l->maxconn = curpeers->peers_fe->maxconn;
+   l->backlog = curpeers->peers_fe->backlog;
+   l->accept = session_accept_fd;
+   l->analysers |=  curpeers->peers_fe->fe_req_ana;
+   l->default_target = curpeers->peers_fe->default_target;
+   l->options |= LI_O_UNLIMITED; /* don't make the peers 
subject to global limits */
+   global.maxsock += l->maxconn;
+   }
+   cfg_peers->local = newpeer;
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
curpeers->state = PR_STSTOPPED;
-- 
2.11.0



[PATCH 12/12] DOC: peers: SSL/TLS documentation for "peers"

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

---
 doc/configuration.txt | 40 +++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 888515fb..960f1948 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1928,15 +1928,34 @@ peers 
   Creates a new peer list with name . It is an independent section,
   which is referenced by one or more stick-tables.
 
+bind []: [, ...] [param*]
+  Defines the binding parameters of the local peer of this "peers" section.
+  Such lines are not supported with "peer" line in the same "peers" section.
+
 disabled
   Disables a peers section. It disables both listening and any synchronization
   related to this section. This is provided to disable synchronization of stick
   tables without having to comment out all "peers" references.
 
+default-bind [param*]
+  Defines the binding parameters for the local peer, excepted its address.
+
+default-server [param*]
+  Change default options for a server in a "peers" section.
+
+  Arguments:
+  is a list of parameters for this server. The "default-server"
+  keyword accepts an important number of options and has a complete
+  section dedicated to it. Please refer to section 5 for more
+  details.
+
+
+  See also: "server" and section 5 about server options
+
 enable
   This re-enables a disabled peers section which was previously disabled.
 
-peer  :
+peer  : [param*]
   Defines a peer inside a peers section.
   If  is set to the local peer name (by default hostname, or forced
   using "-L" command line option), haproxy will listen for incoming remote peer
@@ -1955,7 +1974,20 @@ peer  :
   You may want to reference some environment variables in the address
   parameter, see section 2.3 about environment variables.
 
+  Note: "peer" keyword may transparently be replaced by "server" keyword (see
+  "server" keyword explanation below).
+
+server  [:] [param*]
+  As previously mentionned, "peer" keyword may be replaced by "server" keyword
+  with a support for all "server" parameters found in 5.2 paragraph.
+  If the underlying peer is local, : parameters must not be present.
+  These parameters must  be provided on a "bind" line (see "bind" keyword
+  of this "peers" section).
+  Some of these parameters are irrelevant for "peers" sections.
+
+
   Example:
+# The old way.
 peers mypeers
 peer haproxy1 192.168.0.1:1024
 peer haproxy2 192.168.0.2:1024
@@ -1970,6 +2002,12 @@ peer  :
 server srv1 192.168.0.30:80
 server srv2 192.168.0.31:80
 
+   Example:
+ peers mypeers
+ bind 127.0.0.11:10001 ssl crt mycerts/pem
+ default-server ssl verify none
+ server hostA  127.0.0.10:1
+ server hostB  #local peer
 
 3.6. Mailers
 
-- 
2.11.0



[PATCH 03/12] CLEANUP: cfgparse: Code reindentation.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

May help the series of patches to be reviewed.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 72 +-
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6670a861..04e36e8c 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -648,49 +648,49 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* We are done. */
goto out;
 
-   /* Current is local peer, it define a frontend */
-   newpeer->local = 1;
-   cfg_peers->local = newpeer;
-
-   if (!curpeers->peers_fe) {
-   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
-   ha_alert("parsing [%s:%d] : out of 
memory.\n", file, linenum);
-   err_code |= ERR_ALERT | ERR_ABORT;
-   goto out;
-   }
+   /* Current is local peer, it define a frontend */
+   newpeer->local = 1;
+   cfg_peers->local = newpeer;
 
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, 
file, linenum, args[2], xprt_get(XPRT_RAW));
+   if (!curpeers->peers_fe) {
+   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
+   ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
 
-   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-   if (errmsg && *errmsg) {
-   indent_msg(&errmsg, 2);
-   ha_alert("parsing [%s:%d] : '%s 
%s' : %s\n", file, linenum, args[0], args[1], errmsg);
-   }
-   else
-   ha_alert("parsing [%s:%d] : '%s 
%s' : error encountered while parsing listening address %s.\n",
-file, linenum, 
args[0], args[1], args[2]);
-   err_code |= ERR_FATAL;
-   goto out;
-   }
+   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
 
-   list_for_each_entry(l, &bind_conf->listeners, 
by_bind) {
-   l->maxaccept = 1;
-   l->maxconn = 
curpeers->peers_fe->maxconn;
-   l->backlog = 
curpeers->peers_fe->backlog;
-   l->accept = session_accept_fd;
-   l->analysers |=  
curpeers->peers_fe->fe_req_ana;
-   l->default_target = 
curpeers->peers_fe->default_target;
-   l->options |= LI_O_UNLIMITED; /* don't 
make the peers subject to global limits */
-   global.maxsock += l->maxconn;
+   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : '%s %s' : 
%s\n", file, linenum, args[0], args[1], errmsg);
}
-   }
-   else {
-   ha_alert("parsing [%s:%d] : '%s %s' : local 
peer name already referenced at %s:%d.\n",
-file, linenum, args[0], args[1],
-curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
+   else
+   ha_alert("parsing [%s:%d] : '%s %s' : 
error encountered while parsing listening address %s.\n",
+file, linenum, args[0], 
args[1], args[2]);
err_code |= ERR_FATAL;
goto out;
}
+
+   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+   l->maxaccept = 1;
+   l->maxconn = curpeers->peers_fe->maxconn;
+   l->backlog = curpeers->peers_fe->backlog;
+   l->accept = session_accep

[PATCH 06/12] MINOR: cfgparse: Simplication.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Make init_peers_frontend() be callable without having to check if
there is something to do or not.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 22a3da72..715faaef 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -492,6 +492,10 @@ static int init_peers_frontend(const char *file, int 
linenum,
 {
struct proxy *p;
 
+   if (peers->peers_fe)
+   /* Nothing to do */
+   return 0;
+
p = calloc(1, sizeof *p);
if (!p) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
@@ -659,8 +663,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   if (!curpeers->peers_fe &&
-   init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
+   if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
-- 
2.11.0



[PATCH 04/12] MINOR: cfgparse: Useless frontend initialization in "peers" sections.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Use ->local "peers" struct member to flag a "peers" section frontend
has being initialized. This is to be able to initialize the frontend
of "peers" sections on lines different from "peer" lines.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 04e36e8c..e3e96b51 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -648,9 +648,16 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* We are done. */
goto out;
 
+   if (cfg_peers->local) {
+   ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
+file, linenum, args[0], args[1],
+curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
+   err_code |= ERR_FATAL;
+   goto out;
+   }
+
/* Current is local peer, it define a frontend */
newpeer->local = 1;
-   cfg_peers->local = newpeer;
 
if (!curpeers->peers_fe) {
if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
@@ -683,13 +690,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
l->options |= LI_O_UNLIMITED; /* don't make the 
peers subject to global limits */
global.maxsock += l->maxconn;
}
-   }
-   else {
-   ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
-file, linenum, args[0], args[1],
-curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
-   err_code |= ERR_FATAL;
-   goto out;
+   cfg_peers->local = newpeer;
}
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
-- 
2.11.0



[PATCH 02/12] CLEANUP: cfgparse: Return asap from cfg_parse_peers().

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Avoid useless code indentation.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6fde7c9f..6670a861 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -644,7 +644,10 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->sock_init_arg = NULL;
HA_SPIN_INIT(&newpeer->lock);
 
-   if (strcmp(newpeer->id, localpeer) == 0) {
+   if (strcmp(newpeer->id, localpeer) != 0)
+   /* We are done. */
+   goto out;
+
/* Current is local peer, it define a frontend */
newpeer->local = 1;
cfg_peers->local = newpeer;
@@ -688,7 +691,6 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
err_code |= ERR_FATAL;
goto out;
}
-   }
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
curpeers->state = PR_STSTOPPED;
-- 
2.11.0



[PATCH 10/12] MINOR: cfgparse: peers: Be less confusing.

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Make "bind" line also parse the local peer bind address.
Add "default-bind" option to parse the binding options excepted the bind 
address.
Prevent "bind" lines to be mixed with "peer" line to help in handling the 
migration.
---
 src/cfgparse.c | 153 +
 1 file changed, 122 insertions(+), 31 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index ef69b37d..2a6a4839 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -516,7 +516,8 @@ static int init_peers_frontend(const char *file, int 
linenum,
p->id = strdup(id);
free(p->conf.file);
p->conf.args.file = p->conf.file = strdup(file);
-   p->conf.args.line = p->conf.line = linenum;
+   if (linenum != -1)
+   p->conf.args.line = p->conf.line = linenum;
 
return 0;
 }
@@ -546,6 +547,44 @@ static struct bind_conf *bind_conf_uniq_alloc(struct proxy 
*p,
 
return bind_conf;
 }
+
+/*
+ * Allocate a new struct peer parsed at line  in file 
+ * to be added to .
+ * Returns the new allocated structure if succeeded, NULL if not.
+ */
+static struct peer *cfg_peers_add_peer(struct peers *peers,
+   const char *file, int linenum,
+   const char *id, int local)
+{
+   struct peer *p;
+
+   p = calloc(1, sizeof *p);
+   if (!p) {
+   ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
+   return NULL;
+   }
+
+   /* the peers are linked backwards first */
+   peers->count++;
+   p->next = peers->remote;
+   peers->remote = p;
+   p->conf.file = strdup(file);
+   p->conf.line = linenum;
+   p->last_change = now.tv_sec;
+   p->xprt  = xprt_get(XPRT_RAW);
+   p->sock_init_arg = NULL;
+   HA_SPIN_INIT(&p->lock);
+   if (id)
+   p->id = strdup(id);
+   if (local) {
+   p->local = 1;
+   peers->local = p;
+   }
+
+   return p;
+}
+
 /*
  * Parse a line in a ,  or  section.
  * Returns the error code, 0 if OK, or any combination of :
@@ -565,8 +604,9 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
struct listener *l;
int err_code = 0;
char *errmsg = NULL;
+   static int bind_line, peer_line;
 
-   if (strcmp(args[0], "bind") == 0) {
+   if (strcmp(args[0], "bind") == 0 || strcmp(args[0], "default-bind") == 
0) {
int cur_arg;
static int kws_dumped;
struct bind_conf *bind_conf;
@@ -582,6 +622,44 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
 
bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum,
 NULL, xprt_get(XPRT_RAW));
+   if (*args[0] == 'b') {
+   struct sockaddr_storage *sk;
+   int port, port1, port2;
+
+   if (peer_line) {
+   ha_alert("parsing [%s:%d] : mixing \"peer\" and 
\"bind\" line is forbidden\n", file, linenum);
+   err_code |= ERR_ALERT | ERR_FATAL;
+   goto out;
+   }
+
+   sk = str2sa_range(args[1], &port, &port1, &port2, 
&errmsg, NULL, NULL, 0);
+   if (!sk) {
+   ha_alert("parsing [%s:%d]: '%s %s': %s\n",
+file, linenum, args[0], 
args[1], errmsg);
+   err_code |= ERR_ALERT | ERR_FATAL;
+   goto out;
+   }
+
+   bind_line = 1;
+   if (cfg_peers->local) {
+   newpeer = cfg_peers->local;
+   }
+   else {
+   /* This peer is local.
+* Note that we do not set the peer ID. This 
latter is initialized
+* when parsing "peer" or "server" line.
+*/
+   newpeer = cfg_peers_add_peer(curpeers, file, 
linenum, NULL, 1);
+   if (!newpeer) {
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
+   }
+   newpeer->addr = *sk;
+   newpeer->proto = 
protocol_by_family(newpeer->addr.ss_family);
+   cur_arg++;
+   }
+
while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) {
int ret;
 
@@ -616,13 +694,15 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
}
}

[PATCH 00/12] Peers SSL/TSL support

2019-01-16 Thread flecaille
From: Frédéric Lécaille 

Hi ML, Willy,

Here is a new series of patches for this feature with Willy's remarks
taken into an account. Was easy to break something ;) but I think
this series does not break the current usage of "peers" section.

I prefered work from the previous series without rebasing anything
excepted for the doc patch.

So, the first nine patches #1 up to #9 included are the same as in the
first series. Then come the three last patches with the patch for the
doc as the last one.

I will check how to test all this asap. I think we have to modify
vtest/varnishtest to resolve macros created by different haproxy processes.
The expansion must be done at the very last time: when all the macros have
been created.

Fred.

Frédéric Lécaille (12):
  MINOR: cfgparse: Extract some code to be re-used.
  CLEANUP: cfgparse: Return asap from cfg_parse_peers().
  CLEANUP: cfgparse: Code reindentation.
  MINOR: cfgparse: Useless frontend initialization in "peers" sections.
  MINOR: cfgparse: Rework peers frontend init.
  MINOR: cfgparse: Simplication.
  MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.
  MINOR: peers: Make outgoing connection to SSL/TLS peers work.
  MINOR: cfgparse: SSL/TLS binding in "peers" sections.
  MINOR: cfgparse: peers: Be less confusing.
  MINOR: peers: Less confusing peer binding parsing.
  DOC: peers: SSL/TLS documentation for "peers"

 doc/configuration.txt  |  40 -
 include/proto/peers.h  |  26 
 include/proto/server.h |   2 +-
 include/types/peers.h  |   1 +
 src/cfgparse-listen.c  |   2 +-
 src/cfgparse.c | 405 -
 src/peers.c|   7 +-
 src/server.c   |  13 +-
 8 files changed, 380 insertions(+), 116 deletions(-)

-- 
2.11.0



[PATCH 01/10] MINOR: cfgparse: Extract some code to be re-used.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Create init_peers_frontend() function to allocate and initialize
the frontend of "peers" sections (->peers_fe) so that to reuse it later.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 34 ++
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 7c316df0..6fde7c9f 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -483,6 +483,31 @@ void init_default_instance()
defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
 }
 
+/* Allocate and initialize the frontend of a "peers" section found in
+ * file  at line  with  as ID.
+ * Return 0 if succeeded, -1 if not.
+ */
+static int init_peers_frontend(const char *file, int linenum,
+   const char *id, struct peers *peers)
+{
+   struct proxy *p;
+
+   p = calloc(1, sizeof *p);
+   if (!p) {
+   ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
+   return -1;
+   }
+
+   init_new_proxy(p);
+   p->parent = peers;
+   p->id = strdup(id);
+   p->conf.args.file = p->conf.file = strdup(file);
+   p->conf.args.line = p->conf.line = linenum;
+   peers_setup_frontend(p);
+   peers->peers_fe = p;
+
+   return 0;
+}
 
 /*
  * Parse a line in a ,  or  section.
@@ -625,19 +650,12 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
cfg_peers->local = newpeer;
 
if (!curpeers->peers_fe) {
-   if ((curpeers->peers_fe  = calloc(1, 
sizeof(struct proxy))) == NULL) {
+   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
ha_alert("parsing [%s:%d] : out of 
memory.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
}
 
-   init_new_proxy(curpeers->peers_fe);
-   curpeers->peers_fe->parent = curpeers;
-   curpeers->peers_fe->id = strdup(args[1]);
-   curpeers->peers_fe->conf.args.file = 
curpeers->peers_fe->conf.file = strdup(file);
-   curpeers->peers_fe->conf.args.line = 
curpeers->peers_fe->conf.line = linenum;
-   peers_setup_frontend(curpeers->peers_fe);
-
bind_conf = bind_conf_alloc(curpeers->peers_fe, 
file, linenum, args[2], xprt_get(XPRT_RAW));
 
if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-- 
2.11.0



[PATCH 06/10] MINOR: cfgparse: Simplication.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Make init_peers_frontend() be callable without having to check if
there is something to do or not.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 22a3da72..715faaef 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -492,6 +492,10 @@ static int init_peers_frontend(const char *file, int 
linenum,
 {
struct proxy *p;
 
+   if (peers->peers_fe)
+   /* Nothing to do */
+   return 0;
+
p = calloc(1, sizeof *p);
if (!p) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
@@ -659,8 +663,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   if (!curpeers->peers_fe &&
-   init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
+   if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
-- 
2.11.0



[PATCH 05/10] MINOR: cfgparse: Rework peers frontend init.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Even if not already the case, we suppose that the frontend "peers" section
may have been already initialized outside of "peer" line, we seperate
their initializations from their binding initializations.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 50 --
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index e3e96b51..22a3da72 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -659,39 +659,37 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   if (!curpeers->peers_fe) {
-   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
+   if (!curpeers->peers_fe &&
+   init_peers_frontend(file, linenum, args[1], curpeers) != 0) 
{
ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
-   }
-
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
+   }
 
-   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-   if (errmsg && *errmsg) {
-   indent_msg(&errmsg, 2);
-   ha_alert("parsing [%s:%d] : '%s %s' : 
%s\n", file, linenum, args[0], args[1], errmsg);
-   }
-   else
-   ha_alert("parsing [%s:%d] : '%s %s' : 
error encountered while parsing listening address %s.\n",
-file, linenum, args[0], 
args[1], args[2]);
-   err_code |= ERR_FATAL;
-   goto out;
-   }
+   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, 
args[2], xprt_get(XPRT_RAW));
 
-   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
-   l->maxaccept = 1;
-   l->maxconn = curpeers->peers_fe->maxconn;
-   l->backlog = curpeers->peers_fe->backlog;
-   l->accept = session_accept_fd;
-   l->analysers |=  curpeers->peers_fe->fe_req_ana;
-   l->default_target = 
curpeers->peers_fe->default_target;
-   l->options |= LI_O_UNLIMITED; /* don't make the 
peers subject to global limits */
-   global.maxsock += l->maxconn;
+   if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, 
linenum, &errmsg)) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : '%s %s' : %s\n", 
file, linenum, args[0], args[1], errmsg);
}
-   cfg_peers->local = newpeer;
+   else
+   ha_alert("parsing [%s:%d] : '%s %s' : error 
encountered while parsing listening address %s.\n",
+file, linenum, args[0], args[1], 
args[2]);
+   err_code |= ERR_FATAL;
+   goto out;
}
+   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+   l->maxaccept = 1;
+   l->maxconn = curpeers->peers_fe->maxconn;
+   l->backlog = curpeers->peers_fe->backlog;
+   l->accept = session_accept_fd;
+   l->analysers |=  curpeers->peers_fe->fe_req_ana;
+   l->default_target = curpeers->peers_fe->default_target;
+   l->options |= LI_O_UNLIMITED; /* don't make the peers 
subject to global limits */
+   global.maxsock += l->maxconn;
+   }
+   cfg_peers->local = newpeer;
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
curpeers->state = PR_STSTOPPED;
-- 
2.11.0



[PATCH 10/10] DOC: peers: SSL/TLS documentation for "peers"

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

---
 doc/configuration.txt | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 888515fb..d55e4bd3 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1928,6 +1928,12 @@ peers 
   Creates a new peer list with name . It is an independent section,
   which is referenced by one or more stick-tables.
 
+bind [param*]
+  Defines the binding parameters of the local peer of this "peers" section.
+  To avoid some redundancy, and as the  and  parameters
+  are already provided on "peer" (or "server") lines, they are not supported
+  by "bind" keyword in "peers" sections.
+
 disabled
   Disables a peers section. It disables both listening and any synchronization
   related to this section. This is provided to disable synchronization of stick
@@ -1936,7 +1942,7 @@ disabled
 enable
   This re-enables a disabled peers section which was previously disabled.
 
-peer  :
+peer  : [param*]
   Defines a peer inside a peers section.
   If  is set to the local peer name (by default hostname, or forced
   using "-L" command line option), haproxy will listen for incoming remote peer
@@ -1955,6 +1961,15 @@ peer  :
   You may want to reference some environment variables in the address
   parameter, see section 2.3 about environment variables.
 
+  Note: "peer" keyword may transparently be replaced by "server" keyword (see
+  "server" keyword explanation below).
+
+server  : [param*]
+  As previously mentionned, "peer" keyword may be replaced by "server" keyword
+  with a support for all "server" parameters found in 5.2 paragraph.
+  Some of these parameters are irrelevant for "peers" sections.
+
+
   Example:
 peers mypeers
 peer haproxy1 192.168.0.1:1024
@@ -1970,6 +1985,12 @@ peer  :
 server srv1 192.168.0.30:80
 server srv2 192.168.0.31:80
 
+   Example:
+ peers mypeers
+ bind ssl crt mycerts/pem
+ default-server ssl verify none
+ server hostA  127.0.0.10:1
+ server hostB  127.0.0.11:10001
 
 3.6. Mailers
 
-- 
2.11.0



[PATCH 04/10] MINOR: cfgparse: Useless frontend initialization in "peers" sections.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Use ->local "peers" struct member to flag a "peers" section frontend
has being initialized. This is to be able to initialize the frontend
of "peers" sections on lines different from "peer" lines.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 04e36e8c..e3e96b51 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -648,9 +648,16 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* We are done. */
goto out;
 
+   if (cfg_peers->local) {
+   ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
+file, linenum, args[0], args[1],
+curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
+   err_code |= ERR_FATAL;
+   goto out;
+   }
+
/* Current is local peer, it define a frontend */
newpeer->local = 1;
-   cfg_peers->local = newpeer;
 
if (!curpeers->peers_fe) {
if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
@@ -683,13 +690,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
l->options |= LI_O_UNLIMITED; /* don't make the 
peers subject to global limits */
global.maxsock += l->maxconn;
}
-   }
-   else {
-   ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
-file, linenum, args[0], args[1],
-curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
-   err_code |= ERR_FATAL;
-   goto out;
+   cfg_peers->local = newpeer;
}
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
-- 
2.11.0



[PATCH 07/10] MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

With this patch "default-server" lines are supported in "peers" sections
to setup the default settings of peers which are from now setup
when parsing both "peer" and "server" lines.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 88 +++---
 src/peers.c|  2 +-
 src/server.c   |  3 +-
 3 files changed, 32 insertions(+), 61 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 715faaef..6d199c97 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -486,15 +486,18 @@ void init_default_instance()
 /* Allocate and initialize the frontend of a "peers" section found in
  * file  at line  with  as ID.
  * Return 0 if succeeded, -1 if not.
+ * Note that this function may be called from "default-server"
+ * or "peer" lines.
  */
 static int init_peers_frontend(const char *file, int linenum,
const char *id, struct peers *peers)
 {
struct proxy *p;
 
-   if (peers->peers_fe)
-   /* Nothing to do */
-   return 0;
+   if (peers->peers_fe) {
+   p = peers->peers_fe;
+   goto out;
+   }
 
p = calloc(1, sizeof *p);
if (!p) {
@@ -503,12 +506,16 @@ static int init_peers_frontend(const char *file, int 
linenum,
}
 
init_new_proxy(p);
+   peers_setup_frontend(p);
p->parent = peers;
-   p->id = strdup(id);
+   /* Finally store this frontend. */
+   peers->peers_fe = p;
+
+ out:
+   if (id && !p->id)
+   p->id = strdup(id);
p->conf.args.file = p->conf.file = strdup(file);
p->conf.args.line = p->conf.line = linenum;
-   peers_setup_frontend(p);
-   peers->peers_fe = p;
 
return 0;
 }
@@ -533,7 +540,14 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
int err_code = 0;
char *errmsg = NULL;
 
-   if (strcmp(args[0], "peers") == 0) { /* new peers section */
+   if (strcmp(args[0], "default-server") == 0) {
+   if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
+   err_code |= parse_server(file, linenum, args, 
curpeers->peers_fe, NULL);
+   }
+   else if (strcmp(args[0], "peers") == 0) { /* new peers section */
if (!*args[1]) {
ha_alert("parsing [%s:%d] : missing name for peers 
section.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
@@ -577,26 +591,8 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
curpeers->id = strdup(args[1]);
curpeers->state = PR_STNEW;
}
-   else if (strcmp(args[0], "peer") == 0) { /* peer definition */
-   struct sockaddr_storage *sk;
-   int port1, port2;
-   struct protocol *proto;
-
-   if (!*args[2]) {
-   ha_alert("parsing [%s:%d] : '%s' expects  and 
[:] as arguments.\n",
-file, linenum, args[0]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   err = invalid_char(args[1]);
-   if (err) {
-   ha_alert("parsing [%s:%d] : character '%c' is not 
permitted in server name '%s'.\n",
-file, linenum, *err, args[1]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
+   else if (strcmp(args[0], "peer") == 0 ||
+strcmp(args[0], "server") == 0) { /* peer or server definition 
*/
if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, 
linenum);
err_code |= ERR_ALERT | ERR_ABORT;
@@ -613,37 +609,17 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->last_change = now.tv_sec;
newpeer->id = strdup(args[1]);
 
-   sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, 
NULL, 1);
-   if (!sk) {
-   ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, 
linenum, args[0], args[1], errmsg);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   proto = protocol_by_family(sk->ss_family);
-   if (!proto || !proto->connect) {
-   ha_alert("parsing [%s:%d] : '%s %s' : connect() not 
supported for this address family.\n",
-file, linenum, args[0], args[1]);
-   err_code |= ERR_ALERT | ERR_FATAL;
-   goto out;
-   }
-
-   if (port1 != port

[PATCH 03/10] CLEANUP: cfgparse: Code reindentation.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

May help the series of patches to be reviewed.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 72 +-
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6670a861..04e36e8c 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -648,49 +648,49 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* We are done. */
goto out;
 
-   /* Current is local peer, it define a frontend */
-   newpeer->local = 1;
-   cfg_peers->local = newpeer;
-
-   if (!curpeers->peers_fe) {
-   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
-   ha_alert("parsing [%s:%d] : out of 
memory.\n", file, linenum);
-   err_code |= ERR_ALERT | ERR_ABORT;
-   goto out;
-   }
+   /* Current is local peer, it define a frontend */
+   newpeer->local = 1;
+   cfg_peers->local = newpeer;
 
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, 
file, linenum, args[2], xprt_get(XPRT_RAW));
+   if (!curpeers->peers_fe) {
+   if (init_peers_frontend(file, linenum, args[1], 
curpeers) != 0) {
+   ha_alert("parsing [%s:%d] : out of memory.\n", 
file, linenum);
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
 
-   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
-   if (errmsg && *errmsg) {
-   indent_msg(&errmsg, 2);
-   ha_alert("parsing [%s:%d] : '%s 
%s' : %s\n", file, linenum, args[0], args[1], errmsg);
-   }
-   else
-   ha_alert("parsing [%s:%d] : '%s 
%s' : error encountered while parsing listening address %s.\n",
-file, linenum, 
args[0], args[1], args[2]);
-   err_code |= ERR_FATAL;
-   goto out;
-   }
+   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
 
-   list_for_each_entry(l, &bind_conf->listeners, 
by_bind) {
-   l->maxaccept = 1;
-   l->maxconn = 
curpeers->peers_fe->maxconn;
-   l->backlog = 
curpeers->peers_fe->backlog;
-   l->accept = session_accept_fd;
-   l->analysers |=  
curpeers->peers_fe->fe_req_ana;
-   l->default_target = 
curpeers->peers_fe->default_target;
-   l->options |= LI_O_UNLIMITED; /* don't 
make the peers subject to global limits */
-   global.maxsock += l->maxconn;
+   if (!str2listener(args[2], curpeers->peers_fe, 
bind_conf, file, linenum, &errmsg)) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : '%s %s' : 
%s\n", file, linenum, args[0], args[1], errmsg);
}
-   }
-   else {
-   ha_alert("parsing [%s:%d] : '%s %s' : local 
peer name already referenced at %s:%d.\n",
-file, linenum, args[0], args[1],
-curpeers->peers_fe->conf.file, 
curpeers->peers_fe->conf.line);
+   else
+   ha_alert("parsing [%s:%d] : '%s %s' : 
error encountered while parsing listening address %s.\n",
+file, linenum, args[0], 
args[1], args[2]);
err_code |= ERR_FATAL;
goto out;
}
+
+   list_for_each_entry(l, &bind_conf->listeners, by_bind) {
+   l->maxaccept = 1;
+   l->maxconn = curpeers->peers_fe->maxconn;
+   l->backlog = curpeers->peers_fe->backlog;
+   l->accept = session_accep

[PATCH 08/10] MINOR: peers: Make outgoing connection to SSL/TLS peers work.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

This patch adds pointer to a struct server to peer structure which
is initialized after having parsed a remote "peer" line.

After having parsed all peers section we run ->prepare_srv to initialize
all SSL/TLS stuff of remote perr (or server).

Remaining thing to do to completely support peer protocol over SSL/TLS:
make "bind" keyword be supported in "peers" sections to make SSL/TLS
incoming connections to local peers work.

May be backported to 1.5 and newer.
---
 include/proto/peers.h | 26 ++
 include/types/peers.h |  1 +
 src/cfgparse.c| 13 +++--
 src/peers.c   |  5 +++--
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/proto/peers.h b/include/proto/peers.h
index 9d4aaff2..ce4feaa4 100644
--- a/include/proto/peers.h
+++ b/include/proto/peers.h
@@ -25,9 +25,35 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#if defined(USE_OPENSSL)
+static inline enum obj_type *peer_session_target(struct peer *p, struct stream 
*s)
+{
+   if (p->srv->use_ssl)
+   return &p->srv->obj_type;
+   else
+   return &s->be->obj_type;
+}
+
+static inline struct xprt_ops *peer_xprt(struct peer *p)
+{
+   return p->srv->use_ssl ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW);
+}
+#else
+static inline enum obj_type *peer_session_target(struct peer *p, struct stream 
*s)
+{
+   return &s->be->obj_type;
+}
+
+static inline struct xprt_ops *peer_xprt(struct peer *p)
+{
+   return xprt_get(XPRT_RAW);
+}
+#endif
+
 int peers_init_sync(struct peers *peers);
 void peers_register_table(struct peers *, struct stktable *table);
 void peers_setup_frontend(struct proxy *fe);
diff --git a/include/types/peers.h b/include/types/peers.h
index 58c8c4ee..5200d56b 100644
--- a/include/types/peers.h
+++ b/include/types/peers.h
@@ -67,6 +67,7 @@ struct peer {
struct shared_table *remote_table;
struct shared_table *last_local_table;
struct shared_table *tables;
+   struct server *srv;
__decl_hathreads(HA_SPINLOCK_T lock); /* lock used to handle this peer 
section */
struct peer *next;/* next peer in the list */
 };
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6d199c97..f6f25143 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -514,6 +514,7 @@ static int init_peers_frontend(const char *file, int 
linenum,
  out:
if (id && !p->id)
p->id = strdup(id);
+   free(p->conf.file);
p->conf.args.file = p->conf.file = strdup(file);
p->conf.args.line = p->conf.line = linenum;
 
@@ -624,9 +625,10 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->sock_init_arg = NULL;
HA_SPIN_INIT(&newpeer->lock);
 
-   if (strcmp(newpeer->id, localpeer) != 0)
-   /* We are done. */
+   if (strcmp(newpeer->id, localpeer) != 0) {
+   newpeer->srv = curpeers->peers_fe->srv;
goto out;
+   }
 
if (cfg_peers->local) {
ha_alert("parsing [%s:%d] : '%s %s' : local peer name 
already referenced at %s:%d.\n",
@@ -3634,6 +3636,13 @@ out_uri_auth_compat:
curpeers->peers_fe = NULL;
}
else {
+   p = curpeers->remote;
+   while (p) {
+   if (p->srv && p->srv->use_ssl &&
+   xprt_get(XPRT_SSL) && 
xprt_get(XPRT_SSL)->prepare_srv)
+   cfgerr += 
xprt_get(XPRT_SSL)->prepare_srv(p->srv);
+   p = p->next;
+   }
if (!peers_init_sync(curpeers)) {
ha_alert("Peers section '%s': out of 
memory, giving up on peers.\n",
 curpeers->id);
diff --git a/src/peers.c b/src/peers.c
index e580f2ca..d4d3859e 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1996,10 +1997,10 @@ static struct appctx *peer_session_create(struct peers 
*peers, struct peer *peer
if (unlikely((cs = cs_new(conn)) == NULL))
goto out_free_conn;
 
-   conn->target = s->target = &s->be->obj_type;
+   conn->target = s->target = peer_session_target(peer, s);
memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to));
 
-   conn_prepare(conn, peer->proto, peer->xprt);
+   conn_prepare(conn, peer->proto, peer_xprt(peer));
conn_install_mux(conn, &mux_pt_ops, cs, s->be, NULL);
si_attach_cs(&s->si[1], cs);
 
-- 
2.11.0



[PATCH 02/10] CLEANUP: cfgparse: Return asap from cfg_parse_peers().

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Avoid useless code indentation.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6fde7c9f..6670a861 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -644,7 +644,10 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
newpeer->sock_init_arg = NULL;
HA_SPIN_INIT(&newpeer->lock);
 
-   if (strcmp(newpeer->id, localpeer) == 0) {
+   if (strcmp(newpeer->id, localpeer) != 0)
+   /* We are done. */
+   goto out;
+
/* Current is local peer, it define a frontend */
newpeer->local = 1;
cfg_peers->local = newpeer;
@@ -688,7 +691,6 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
err_code |= ERR_FATAL;
goto out;
}
-   }
} /* neither "peer" nor "peers" */
else if (!strcmp(args[0], "disabled")) {  /* disables this peers 
section */
curpeers->state = PR_STSTOPPED;
-- 
2.11.0



[PATCH 00/10] Peers SSL/TLS support

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Hi ML,

With this series of patches we add the SSL/TLS support to haproxy peers.

Regards,
Fred.

Frédéric Lécaille (10):
  MINOR: cfgparse: Extract some code to be re-used.
  CLEANUP: cfgparse: Return asap from cfg_parse_peers().
  CLEANUP: cfgparse: Code reindentation.
  MINOR: cfgparse: Useless frontend initialization in "peers" sections.
  MINOR: cfgparse: Rework peers frontend init.
  MINOR: cfgparse: Simplication.
  MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.
  MINOR: peers: Make outgoing connection to SSL/TLS peers work.
  MINOR: cfgparse: SSL/TLS binding in "peers" sections.
  DOC: peers: SSL/TLS documentation for "peers"

 doc/configuration.txt |  23 -
 include/proto/peers.h |  26 +
 include/types/peers.h |   1 +
 src/cfgparse.c| 272 +-
 src/peers.c   |   7 +-
 src/server.c  |   3 +-
 6 files changed, 234 insertions(+), 98 deletions(-)

-- 
2.11.0



[PATCH 09/10] MINOR: cfgparse: SSL/TLS binding in "peers" sections.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

This patch makes "bind" work in "peers" sections. All "bind" settings
are supported, excepted ip:port parameters which are provided on
"peer" (or server) line matching the local peer.
After having parsed the configuration files ->prepare_bind_conf is run
to initialize all SSL/TLS stuff for the local peer.

May be backported to 1.5 and newer.
---
 src/cfgparse.c | 95 ++
 1 file changed, 90 insertions(+), 5 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index f6f25143..ef69b37d 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -521,6 +521,31 @@ static int init_peers_frontend(const char *file, int 
linenum,
return 0;
 }
 
+/* Only change ->file, ->line and ->arg struct bind_conf member values
+ * if already present.
+ */
+static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p,
+  const char *file, int line,
+  const char *arg, struct xprt_ops 
*xprt)
+{
+   struct bind_conf *bind_conf;
+
+   if (!LIST_ISEMPTY(&p->conf.bind)) {
+   bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), 
by_fe);
+   free(bind_conf->file);
+   bind_conf->file = strdup(file);
+   bind_conf->line = line;
+   if (arg) {
+   free(bind_conf->arg);
+   bind_conf->arg = strdup(arg);
+   }
+   }
+   else {
+   bind_conf = bind_conf_alloc(p, file, line, arg, xprt);
+   }
+
+   return bind_conf;
+}
 /*
  * Parse a line in a ,  or  section.
  * Returns the error code, 0 if OK, or any combination of :
@@ -541,7 +566,56 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
int err_code = 0;
char *errmsg = NULL;
 
-   if (strcmp(args[0], "default-server") == 0) {
+   if (strcmp(args[0], "bind") == 0) {
+   int cur_arg;
+   static int kws_dumped;
+   struct bind_conf *bind_conf;
+   struct bind_kw *kw;
+   char *kws;
+
+   cur_arg = 1;
+
+   if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
+   err_code |= ERR_ALERT | ERR_ABORT;
+   goto out;
+   }
+
+   bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum,
+NULL, xprt_get(XPRT_RAW));
+   while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) {
+   int ret;
+
+   ret = kw->parse(args, cur_arg, curpeers->peers_fe, 
bind_conf, &errmsg);
+   err_code |= ret;
+   if (ret) {
+   if (errmsg && *errmsg) {
+   indent_msg(&errmsg, 2);
+   ha_alert("parsing [%s:%d] : %s\n", 
file, linenum, errmsg);
+   }
+   else
+   ha_alert("parsing [%s:%d]: error 
encountered while processing '%s'\n",
+file, linenum, args[cur_arg]);
+   if (ret & ERR_FATAL)
+   goto out;
+   }
+   cur_arg += 1 + kw->skip;
+   }
+   kws = NULL;
+   if (!kws_dumped) {
+   kws_dumped = 1;
+   bind_dump_kws(&kws);
+   indent_msg(&kws, 4);
+   }
+   if (*args[cur_arg] != 0) {
+   ha_alert("parsing [%s:%d] : unknown keyword '%s' in 
'%s' section.%s%s\n",
+file, linenum, args[cur_arg], cursection,
+kws ? " Registered keywords :" : "", kws ? 
kws: "");
+   free(kws);
+   err_code |= ERR_ALERT | ERR_FATAL;
+   goto out;
+   }
+   }
+   else if (strcmp(args[0], "default-server") == 0) {
if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) {
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
@@ -641,7 +715,7 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
/* Current is local peer, it define a frontend */
newpeer->local = 1;
 
-   bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, 
args[2], xprt_get(XPRT_RAW));
+   bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, 
linenum, args[2], xprt_get(XPRT_RAW));
 
if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, 
linenum, &errmsg)) {
if (errmsg && *errmsg) {

[PATCH 2/2] REGTEST: Adapt reg test doc files to vtest.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

This is a first patch to switch from varnishtest to new standalone
varnish cache reg testing program: vtest.

More information may be found here:

https://github.com/vtest/VTest
https://varnish-cache.org/docs/trunk/reference/varnishtest.html
https://varnish-cache.org/docs/trunk/reference/vtc.html
---
 doc/regression-testing.txt | 78 +-
 reg-tests/README   | 69 
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/doc/regression-testing.txt b/doc/regression-testing.txt
index 2a96b0cd..77ebaecb 100644
--- a/doc/regression-testing.txt
+++ b/doc/regression-testing.txt
@@ -1,74 +1,82 @@
-   +-+
-   | HAProxy regression testing with varnishtest |
-   +-+
+   +---+
+   | HAProxy regression testing with vtest |
+   +---+
 
 
 The information found in this file are a short starting guide to help you to
 write VTC (Varnish Test Case) scripts (or VTC files) for haproxy regression 
testing.
 Such VTC files are currently used to test Varnish cache application developed 
by
 Poul-Henning Kamp. A very big thanks you to him for having helped you to add
-our haproxy C modules to varnishtest tool.
+our haproxy C modules to vtest tool. Note that vtest was formally developed for
+varnish cache reg testing and was named varnishtest. vtest is an haproxy 
specific
+version of varnishtest program which reuses the non varnish cache specific 
code.
 
 A lot of general information about how to write VTC files may be found in 
'man/vtc.7'
-manual. It is *highly* recommended to read this manual before asking. This
-documentation only deals with the varnishtest support for haproxy.
+manual of varnish cache sources directory or directly on the web here:
 
+https://varnish-cache.org/docs/trunk/reference/vtc.html
 
-varnishtest installation
+It is *highly* recommended to read this manual before asking to haproxy ML. 
This
+documentation only deals with the vtest support for haproxy.
+
+
+vtest installation
 
 
-To use varnishtest you will have to download and compile the recent Varnish 
cache
-sources found at https://github.com/varnishcache/varnish-cache.
+To use vtest you will have to download and compile the recent vtest
+sources found at https://github.com/vtest/VTest.
 
-To compile Varnish cache :
+To compile vtest:
 
-$ ./autogen.sh
-$ ./configure
-$ make
+$ cd VTest
+$ make vtest
 
-The varnishtest sources may be found in 'bin/varnishtest' directory.
-'bin/varnishtest/tests' is plenty of VTC files for Varnish cache. After having
-compiled these sources, the varnishtest executable location is
-'bin/varnishtest/varnishtest'.
+Note that varnishtest may be also compiled but not without the varnish cache
+sources already compiled:
 
-varnishtest is able to search for the haproxy executable file it is supposed to
-launch in the PATH environment variable. To force the executable to be used by
-varnishtest, the HAPROXY_PROGRAM environment variable for varnishtest may be
-typically set as follows:
+$ VARNISH_SRC=<...> make varnishtest
 
- $ HAPROXY_PROGRAM=~/srcs/haproxy/haproxy varnishtest ...
+After having compiled these sources, the vtest executable location is at the
+root of the vtest sources directory.
 
 
-varnistest exectution
+vtest exectution
 -
 
-varnishtest program comes with interesting options. The most interesting are:
+vtest is able to search for the haproxy executable file it is supposed to
+launch thanks to the PATH environment variable. To force the executable to be 
used by
+vtest, the HAPROXY_PROGRAM environment variable for vtest may be
+typically set as follows:
+
+ $ HAPROXY_PROGRAM=~/srcs/haproxy/haproxy vtest ...
+
+vtest program comes with interesting options. The most interesting are:
 
 -t  Timeout in seconds to abort the test if some launched program
--v  By default, varnishtest does not dump the outputs of processus it 
launched
+-v  By default, vtest does not dump the outputs of processus it launched
 when the test passes. With this option the outputs are dumped even
 when the test passes.
 -L  to always keep the temporary VTC directories.
 -l  to keep the temporary VTC directories only when the test fails.
 
-About haproxy when launched by varnishtest, -d option is enabled by default.
+About haproxy, when launched by vtest, -d option is enabled by default.
 
 
 How to write VTC files
 --
 
-A VTC file must start with a "varnishtest" command line followed by a 
descriptive
-line enclosed by double quotes. This is not specific to the VTC files for 
haproxy.
+A VTC file must start with a "varnishtest" or "vtest" command 

[PATCH 0/2] Switch to vtest.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

Hi ML,

With these patches, haproxy switches to the new varnish cache reg testing tool
named vtest, formerly known as varnishtest.

From the user point of view, there is no very much differences compared to the
usage of varnishtest. Before we started the reg testing process as follows:

   $ VARNISTEST_PROGRAM=<...> make reg-tests

now we have to run:

   $ VTEST_PROGRAM=<...> make reg-tests

More information may be found here: https://github.com/vtest/VTest

Fred.


Frédéric Lécaille (2):
  REGTEST: Adapt reg test doc files to vtest.
  REGTEST: Switch to vtest.

 doc/regression-testing.txt | 78 +-
 reg-tests/README   | 67 ++-
 scripts/run-regtests.sh| 28 -
 3 files changed, 96 insertions(+), 77 deletions(-)

-- 
2.11.0



[PATCH 1/2] REGTEST: Switch to vtest.

2019-01-11 Thread flecaille
From: Frédéric Lécaille 

This patch replace the usage of the formerly varnish cache reg
testing program, name varnishtest by the new standalone one: vtest.
---
 Makefile| 10 +-
 scripts/run-regtests.sh | 28 ++--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/Makefile b/Makefile
index 6e77b073..10be7cc3 100644
--- a/Makefile
+++ b/Makefile
@@ -101,7 +101,7 @@
 #   SUBVERS: add a sub-version (eg: platform, model, ...).
 #   VERDATE: force haproxy's release date.
 #
-#   VARNISHTEST_PROGRAM : location of the varnishtest program to run reg-tests.
+#   VTEST_PROGRAM : location of the vtest program to run reg-tests.
 
 # verbosity: pass V=1 for verbose shell invocation
 V = 0
@@ -1113,10 +1113,10 @@ reg-tests:
 
 reg-tests-help:
@echo
-   @echo "To launch the reg tests for haproxy, first export to your 
environment VARNISHTEST_PROGRAM variable to point to your varnishtest program:"
-   @echo "$$ export VARNISHTEST_PROGRAM=/opt/local/bin/varnishtest"
+   @echo "To launch the reg tests for haproxy, first export to your 
environment VTEST_PROGRAM variable to point to your vtest program:"
+   @echo "$$ export VTEST_PROGRAM=/opt/local/bin/vtest"
@echo "or"
-   @echo "$$ setenv VARNISHTEST_PROGRAM /opt/local/bin/varnishtest"
+   @echo "$$ setenv VTEST_PROGRAM /opt/local/bin/vtest"
@echo
@echo "The same thing may be done to set your haproxy program with 
HAPROXY_PROGRAM but with ./haproxy as default value."
@echo
@@ -1124,7 +1124,7 @@ reg-tests-help:
@echo "$$ make reg-tests"
@echo
@echo "You can also set the programs to be used on the command line:"
-   @echo "$$ VARNISHTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make 
reg-tests"
+   @echo "$$ VTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make reg-tests"
@echo
@echo "To run tests with specific levels:"
@echo "$$ LEVEL=1,3,4   make reg-tests  #list of levels"
diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh
index e648fa0a..8469163b 100755
--- a/scripts/run-regtests.sh
+++ b/scripts/run-regtests.sh
@@ -13,11 +13,11 @@ _help()
 run-regtests.sh ./tests1 ./tests2
 
   Parameters:
---j , To run varnishtest with multiple jobs / threads for a faster 
overall result
+--j , To run vtest with multiple jobs / threads for a faster overall 
result
   run-regtests.sh ./fasttest --j 16
 
 --v, to run verbose
-  run-regtests.sh --v, disables the default varnishtest 'quiet' parameter
+  run-regtests.sh --v, disables the default vtest 'quiet' parameter
 
 --debug to show test logs on standard ouput (implies --v)
   run-regtests.sh --debug
@@ -25,8 +25,8 @@ _help()
 --keep-logs to keep all log directories (by default kept if test fails)
   run-regtests.sh --keep-logs
 
---varnishtestparams , passes custom ARGS to varnishtest
-  run-regtests.sh --varnishtestparams "-n 10"
+--vtestparams , passes custom ARGS to vtest
+  run-regtests.sh --vtestparams "-n 10"
 
 --clean to cleanup previous reg-tests log directories and exit
   run-regtests.sh --clean
@@ -54,12 +54,12 @@ _help()
 #REQUIRE_VERSION=0.0
 #REQUIRE_VERSION_BELOW=99.9
 
-  Configure environment variables to set the haproxy and varnishtest binaries 
to use
+  Configure environment variables to set the haproxy and vtest binaries to use
 setenv HAPROXY_PROGRAM /usr/local/sbin/haproxy
-setenv VARNISHTEST_PROGRAM /usr/local/bin/varnishtest
+setenv VTEST_PROGRAM /usr/local/bin/vtest
   or
 export HAPROXY_PROGRAM=/usr/local/sbin/haproxy
-export VARNISHTEST_PROGRAM=/usr/local/bin/varnishtest
+export VTEST_PROGRAM=/usr/local/bin/vtest
 EOF
   exit 0
 }
@@ -248,8 +248,8 @@ _process() {
   jobcount="$2"
   shift
   ;;
---varnishtestparams)
-  varnishtestparams="$2"
+--vtestparams)
+  vtestparams="$2"
   shift
   ;;
 --v)
@@ -294,7 +294,7 @@ _version() {
 
 
 HAPROXY_PROGRAM="${HAPROXY_PROGRAM:-${PWD}/haproxy}"
-VARNISHTEST_PROGRAM="${VARNISHTEST_PROGRAM:-varnishtest}"
+VTEST_PROGRAM="${VTEST_PROGRAM:-vtest}"
 TESTDIR="${TMPDIR:-/tmp}"
 REGTESTS=""
 
@@ -315,8 +315,8 @@ if ! [ -x "$(command -v $HAPROXY_PROGRAM)" ]; then
   echo "haproxy not found in path, please specify HAPROXY_PROGRAM environment 
variable"
   preparefailed=1
 fi
-if ! [ -x "$(command -v $VARNISHTEST_PROGRAM)" ]; then
-  echo "varnishtest not found in path, please specify VARNISHTEST_PROGRAM 
environment variable"
+if ! [ -x "$(command -v $VTEST_PROGRAM)" ]; then
+  echo "vtest not found in path, please specify VTEST_PROGRAM environment 
variable"
   preparefailed=1
 fi
 if [ $preparefailed ]; then
@@ -424,14 +424,14 @@ else
   done
 fi
 
-echo "## Starting varnishtest 
##"
+echo "## Starti

[PATCH 0/1] Be more verbous when reg tests fail.

2019-01-08 Thread flecaille
From: Frédéric Lécaille 

With this patch when the test fails it may be useful to collect additional 
information
coming from varnishtes especially when this latter aborts.

For instance without this patch reg-tests/mailers/k_healthcheckmail.vtc does not
produce relevant information.

$ VARNISHTEST_PROGRAM=<...> make reg-tests 
reg-tests/mailers/k_healthcheckmail.vtc

## test results in: ...
  

With this patch these following lines are added to the test results output:

*diag  0.0 Assert error in vtc_log_emit(), vtc_log.c line 157:
*diag  0.0   Condition(vtclog_left > l) not true. (errno=0 Success)


In this case varnishtest aborts because its logging buffer is full.
We can make it use a 32MB buffer as follows:

$ VARNISHTEST_PROGRAM=<...> make reg-tests 
reg-tests/mailers/k_healthcheckmail.vtc -- \
   --varnishtestparams "-b$((32<<20))"

with more relevant results:

## test results in: ...
 c27.1 EXPECT resp.http.mailsreceived (11858) == "16" failed

Frédéric Lécaille (1):
  REGTEST: Add some informatoin to test results.

 scripts/run-regtests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.11.0



[PATCH 1/1] REGTEST: Add some informatoin to test results.

2019-01-08 Thread flecaille
From: Frédéric Lécaille 

When the reg tests fail, it may be useful to display additional information
coming from varnishtest, especially when this latter aborts.
In such case, the test output may be made of lines prefixed by "* diag"
string.
---
 scripts/run-regtests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh
index 80353de9..e648fa0a 100755
--- a/scripts/run-regtests.sh
+++ b/scripts/run-regtests.sh
@@ -454,7 +454,7 @@ if [ -d "${TESTDIR}" ]; then
 cat <<- EOF | tee -a "$TESTDIR/failedtests.log"
 $(echo "## $(cat "$i/INFO") ##")
 $(echo "## test results in: \"$i\"")
-$(grep -- ^ "$i/LOG")
+$(grep -E -- "^(|\*diag)" "$i/LOG")
 EOF
   done' sh {} +
 fi
-- 
2.11.0



[PATCH 1/1] REGTEST: "capture (request|response)" regtest.

2019-01-08 Thread flecaille
From: Frédéric Lécaille 

---
 reg-tests/http-capture/h0.vtc | 92 +++
 1 file changed, 92 insertions(+)
 create mode 100644 reg-tests/http-capture/h0.vtc

diff --git a/reg-tests/http-capture/h0.vtc 
b/reg-tests/http-capture/h0.vtc
new file mode 100644
index ..9f6ec8c5
--- /dev/null
+++ b/reg-tests/http-capture/h0.vtc
@@ -0,0 +1,92 @@
+varnishtest "Tests for 'capture (request|response) header"
+feature ignore_unknown_macro
+
+# This script checks that the last occurrences of "fooresp" and "fooreq" header
+# are correctly captured and added to the logs.
+# Note that varnishtest does not support more than MAX_HDR header.
+
+syslog S -level info {
+recv
+expect ~ "[^:\\[ ]\\[${h_pid}\\]: .* .* fe be/srv .* 200 17641 - -  .* 
.* {HPhx8n59qjjNBLjP} {htb56qDdCcbRVTfS} \"GET / HTTP/1\\.1\""
+} -start
+
+server s {
+rxreq
+txresp -hdr "fooresp: HnFDGJ6KvhSG5QjX" -hdr "fooresp: 8dp7vBMQjTMkVwtG" \
+   -hdr "fooresp: NTpxWmvsNKGxvH6K" -hdr "fooresp: sPKNNJ5VRBDz9qXP" \
+   -hdr "fooresp: HnFDGJ6KvhSG5QjX" -hdr "fooresp: 8dp7vBMQjTMkVwtG" \
+   -hdr "fooresp: VSNnccbGkvfM9JK9" -hdr "fooresp: 9D5cjwtK3LCxmg4F" \
+   -hdr "fooresp: dsbxGqlBPRWGP3vX" -hdr "fooresp: xf6VK6GXlgdj5mwc" \
+   -hdr "fooresp: 8jzM3clRKtdL2WWb" -hdr "fooresp: v7ZHrTPjDR6lm6Bg" \
+   -hdr "fooresp: FQT6th9whMqQ7Z6C" -hdr "fooresp: KM22HH6lRBw6SHQT" \
+   -hdr "fooresp: PmRHphHXmTV9kZNS" -hdr "fooresp: CkGRbTJrD5nSVpFk" \
+   -hdr "fooresp: KQ9mzmMHpmmZ2SXP" -hdr "fooresp: W5FqfFDN6dqBxjK7" \
+   -hdr "fooresp: bvcxNPK4gpnTvn3z" -hdr "fooresp: BSXRLSWMsgQN54cC" \
+   -hdr "fooresp: ZX9ttTnlbXtJK55d" -hdr "fooresp: KH9StjMHF73NqzL8" \
+   -hdr "fooresp: W2q2m6MvMLcnXsX7" -hdr "fooresp: wtrjnJgFzHDvMg5r" \
+   -hdr "fooresp: Vpk2c2DsbWf2Gtwh" -hdr "fooresp: sCcW2qpRhFHHRDpH" \
+   -hdr "fooresp: P4mltXtvxLsnPcNS" -hdr "fooresp: TXgdSKNMmsJ8x9zq" \
+   -hdr "fooresp: n5t8pdZgnGFXZDd3" -hdr "fooresp: pD84GCtkWZqWbCM9" \
+   -hdr "fooresp: wx2FPxsGqSRjNVws" -hdr "fooresp: TXmtBCqPTVGFc3NK" \
+   -hdr "fooresp: 4DrFTLxpcPk2n3Zv" -hdr "fooresp: vrcFr9MWpqJWhK4h" \
+   -hdr "fooresp: HMsCHMZnHT3q8qD2" -hdr "fooresp: HsCXQGTxDpsMf4z6" \
+   -hdr "fooresp: 9rb2vjvvd2SzCQVT" -hdr "fooresp: qn5C2fZTWHVp7NkC" \
+   -hdr "fooresp: ZVd5ltcngZFHXfvr" -hdr "fooresp: j6BZVdV8fkz5tgjR" \
+   -hdr "fooresp: 6qfVwfHqdfntQjmP" -hdr "fooresp: RRr9nTnwjG6d2x7X" \
+   -hdr "fooresp: RJXtWtdJRTss6JgZ" -hdr "fooresp: zzHZWm6bqXDN9k47" \
+   -hdr "fooresp: htb56qDdCcbRVTfS" \
+   -bodylen 16384
+} -start
+
+haproxy h -conf {
+defaults
+mode http
+${no-htx} option http-use-htx
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+
+backend be
+server srv ${s_addr}:${s_port}
+
+frontend fe
+option httplog
+log ${S_addr}:${S_port} local0 debug err
+capture request header fooreq len 25
+capture response header fooresp len 25
+
+bind "fd@${fe}"
+use_backend be
+} -start
+
+client c1 -connect ${h_fe_sock} {
+ txreq -hdr "fooreq: c8Ck8sx8qfXk5pSS" -hdr "fooreq: TGNXbG2DF3TmLWK3" \
+   -hdr "fooreq: mBxq9Cgr8GN6hkt6" -hdr "fooreq: MHZ6VBCPgs564KfR" \
+   -hdr "fooreq: BCCwX2kL9BSMCqvt" -hdr "fooreq: 8rXw87xVTphpRQb7" \
+   -hdr "fooreq: gJ3Tp9kXQlqLC8Qp" -hdr "fooreq: dFnLs6wpMl2M5N7c" \
+   -hdr "fooreq: r3f9WgQ8Brqw37Kj" -hdr "fooreq: dbJzSSdCqV3ZVtXK" \
+   -hdr "fooreq: 5HxHd6g4n2Rj2CNG" -hdr "fooreq: HNqQSNfkt6q4zK26" \
+   -hdr "fooreq: rzqNcfskPR7vW4jG" -hdr "fooreq: 9c7txWhsdrwmkR6d" \
+   -hdr "fooreq: 3v8Nztg9l9vLSKJm" -hdr "fooreq: lh4WDxMX577h4z3l" \
+   -hdr "fooreq: mFtHj5SKDvfcGzfq" -hdr "fooreq: PZ5B5wRM9D7GLm7W" \
+   -hdr "fooreq: fFpN4zCkLTxzp5Dz" -hdr "fooreq: J5XMdfCCHmmwkr2f" \
+   -hdr "fooreq: KqssZ3SkZnZJF8mz" -hdr "fooreq: HrGgsnBnslKN7Msz" \
+   -hdr "fooreq: d8TQltZ39xFZBNx2" -hdr "fooreq: mwDt2k2tvqM8x5kQ" \
+   -hdr "fooreq: 7Qh6tM7s7z3P8XCl" -hdr "fooreq: S3mTVbbPhJbLR7n2" \
+   -hdr "fooreq: zr7hMDvrrwfvpmTT" -hdr "fooreq: lV9TnZX2CtSnr4k8" \
+   -hdr "fooreq: bMdJx8pVDG2nWFNg" -hdr "fooreq: FkGvB2cBwNrB3cm4" \
+   -hdr "fooreq: 5ckNn3m6m8r2CXLF" -hdr "fooreq: sk4pJGTSZ5HMPJP5" \
+   -hdr "fooreq: HgVgQ73zhLwX6Wzq" -hdr "fooreq: T5k2QbFKvCVJlz4c" \
+   -hdr "fooreq: SKcNPw8CXGKhtxNP" -hdr "fooreq: n9fFrcR2kRQJrCpZ" \
+   -hdr "fooreq: hrJ2MXCdcSCDhQ6n" -hdr "fooreq: 9xsWQ8srzLDvG9F4" \
+   -hdr "fooreq: GNcP9NBTFJkg4hbk" -hdr "fooreq: Vg8B8MNwz4T7q5Tj" \
+   -hdr "fooreq: XXns3qPCzZmt9j4G" -hdr "fooreq: hD7TnP43bcPHm5g2" \
+   -hdr "fooreq: wZbxVq7MwmfBSqb5" -hdr "fooreq: HPhx8n59qjjNBLjP" \
+   -bod

[PATCH 0/1] A basic reg test for HTTP header captures

2019-01-08 Thread flecaille
From: Frédéric Lécaille 

Hi ML,

Here is a basic test to check that this is the last occurence of 
request/response
headers which are sent to the logs.

Fred.

Frédéric Lécaille (1):
  REGTEST: "capture (request|response)" regtest.

 reg-tests/http-capture/h0.vtc | 92 +++
 1 file changed, 92 insertions(+)
 create mode 100644 reg-tests/http-capture/h0.vtc

-- 
2.11.0



[PATCH 1/1] REGTEST: A basic test for "http-buffer-request"

2018-12-21 Thread flecaille
From: Frédéric Lécaille 

---
 reg-tests/http-messaging/h3.vtc | 78 +
 1 file changed, 78 insertions(+)
 create mode 100644 reg-tests/http-messaging/h3.vtc

diff --git a/reg-tests/http-messaging/h3.vtc 
b/reg-tests/http-messaging/h3.vtc
new file mode 100644
index ..2ce21408
--- /dev/null
+++ b/reg-tests/http-messaging/h3.vtc
@@ -0,0 +1,78 @@
+varnishtest "A test for http-request-buffer option"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=1.6
+
+# This test checks HTTP request buffering feature.
+# We run one server s1 which can serve only one client (no -repeat argument 
here).
+# c1 client uses a malformed request which is not transferred to s1 server
+# thanks to "http-buffer-request". If this was the case, c2 client
+# could not connect to s1 server and this would lead to make this test fail.
+
+server s1 {
+   rxreq
+   expect req.bodylen == 257
+   txresp
+} -start
+
+syslog S -level info {
+   recv
+   expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 fe1/ .* 408 .* - - 
cD-- .* .* \"GET 
/this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url
 HTTP/1\\.1\""
+   recv
+   expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 be1/srv1 0/0/0/0/0 200 .* - 
-  .* .* \"GET / HTTP/1\\.1\""
+} -start
+
+haproxy h1 -conf {
+   defaults
+   mode http
+   ${no-htx} option http-use-htx
+   timeout client  100ms
+   timeout server  1s
+   timeout connect 1s
+
+   backend be1
+   server srv1 ${s1_addr}:${s1_port}
+
+   frontend fe1
+   option httplog
+   option http-buffer-request
+   log ${S_addr}:${S_port} local0 debug err
+   bind "fd@${fe1}"
+   use_backend be1
+} -start
+
+client c1 -connect ${h1_fe1_sock} {
+   send "GET"
+   send " "
+   send "/this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send "-this-is-a-long-url"
+   send " HTT"
+   send "P/1.1"
+   send "\r"
+   send "\n"
+   send "Content-Length: 209\r\n\r\n"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   send "abcdefghijklmnopqrstuvwxyz"
+   rxresp
+   expect resp.status == 408
+} -run
+
+client c2 -connect ${h1_fe1_sock} {
+   txreq -bodylen 257
+   rxresp
+   expect resp.status == 200
+} -run
+
+syslog S -wait
+
-- 
2.11.0



[PATCH 0/1] A reg test for "http-buffer-request" option

2018-12-21 Thread flecaille
From: Frédéric Lécaille 

Fred.

Frédéric Lécaille (1):
  REGTEST: A basic test for "http-buffer-request"

 reg-tests/http-messaging/h3.vtc | 78 +
 1 file changed, 78 insertions(+)
 create mode 100644 reg-tests/http-messaging/h3.vtc

-- 
2.11.0



[PATCH 2/4] REGTEST: Be less Linux specific with a syslog regex.

2018-12-20 Thread flecaille
From: Frédéric Lécaille 

This patch makes at least this test pass on FreeBSD systems.
The regex to be matched with syslog message was too much Linux specific.
---
 reg-tests/checks/s3.vtc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reg-tests/checks/s3.vtc b/reg-tests/checks/s3.vtc
index b57b965f..6ce10b0e 100644
--- a/reg-tests/checks/s3.vtc
+++ b/reg-tests/checks/s3.vtc
@@ -27,7 +27,7 @@ syslog S3 -level notice {
 recv
 expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started"
 recv
-expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 
failed, reason: Layer4 connection problem, info: \"General socket error 
\\(Network is unreachable\\)\", check duration: [[:digit:]]+ms, status: 0/1 
DOWN."
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 
failed, reason: Layer4 .* check duration: [[:digit:]]+ms, status: 0/1 DOWN."
 } -start
 
 syslog S4 -level notice {
-- 
2.11.0




[PATCH 4/4] REGTEST: Exclude freebsd target for some reg tests.

2018-12-20 Thread flecaille
From: Frédéric Lécaille 

This patch excludes freebsd target for health-checks reg tests
which rely on TCP_DEFER_ACCEPT usage. This is specific to Linux.
---
 reg-tests/checks/s0.vtc | 1 +
 reg-tests/checks/s1.vtc | 2 ++
 reg-tests/checks/s2.vtc | 1 +
 3 files changed, 4 insertions(+)

diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc
index 0aae83a5..93575d34 100644
--- a/reg-tests/checks/s0.vtc
+++ b/reg-tests/checks/s0.vtc
@@ -2,6 +2,7 @@ varnishtest "Health-check test"
 feature ignore_unknown_macro
 
 #REQUIRE_VERSION=1.8
+#EXCLUDE_TARGETS=freebsd
 
 # This script test health-checks for four backends with one server by backend.
 # A syslog server is attached to each backend to check the syslog messages
diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc
index ff972efd..abb0f2fc 100644
--- a/reg-tests/checks/s1.vtc
+++ b/reg-tests/checks/s1.vtc
@@ -6,6 +6,8 @@ feature ignore_unknown_macro
 # The first health-checks passed tests are checked for all these servers
 # thanks to syslog messages.
 
+#EXCLUDE_TARGETS=freebsd
+
 # Note that the first syslog message received is: "Proxy  started."
 syslog S -repeat 21 -level notice {
 recv
diff --git a/reg-tests/checks/s2.vtc b/reg-tests/checks/s2.vtc
index 7246..2449ba75 100644
--- a/reg-tests/checks/s2.vtc
+++ b/reg-tests/checks/s2.vtc
@@ -2,6 +2,7 @@ varnishtest "Health-checks"
 feature ignore_unknown_macro
 
 #REQUIRE_VERSION=1.8
+#EXCLUDE_TARGETS=freebsd
 
 # This script start 40 servers named s0 up to s39.
 # For 0 <= i <= 19:
-- 
2.11.0




[PATCH 3/4] REGTEST: Missing enclosing quotes for ${tmpdir} macro.

2018-12-20 Thread flecaille
From: Frédéric Lécaille 

---
 reg-tests/connection/b0.vtc  | 4 ++--
 reg-tests/seamless-reload/b0.vtc | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/reg-tests/connection/b0.vtc b/reg-tests/connection/b0.vtc
index 50bb7494..9b36c45a 100644
--- a/reg-tests/connection/b0.vtc
+++ b/reg-tests/connection/b0.vtc
@@ -36,14 +36,14 @@ haproxy h1 -conf {
 
 listen http
 bind-process 1
-bind unix@${tmpdir}/http.socket accept-proxy name ssl-offload-http
+bind unix@"${tmpdir}/http.socket" accept-proxy name ssl-offload-http
 option forwardfor
 
 listen ssl-offload-http
 option httplog
 bind-process 2-4
 bind "fd@${ssl}" ssl crt ${testdir}/common.pem ssl no-sslv3 alpn 
h2,http/1.1
-server http unix@${tmpdir}/http.socket send-proxy
+server http unix@"${tmpdir}/http.socket" send-proxy
 } -start
 
 
diff --git a/reg-tests/seamless-reload/b0.vtc 
b/reg-tests/seamless-reload/b0.vtc
index 8f7acf64..779b2774 100644
--- a/reg-tests/seamless-reload/b0.vtc
+++ b/reg-tests/seamless-reload/b0.vtc
@@ -18,7 +18,7 @@ feature ignore_unknown_macro
 
 haproxy h1 -W -conf {
   global
-stats socket ${tmpdir}/h1/stats level admin expose-fd listeners
+stats socket "${tmpdir}/h1/stats" level admin expose-fd listeners
 
   defaults
 mode http
@@ -38,7 +38,7 @@ haproxy h1 -W -conf {
 } -start
 
 shell {
-  kill -USR2 $(cat ${tmpdir}/h1/pid)
+  kill -USR2 $(cat "${tmpdir}/h1/pid")
 }
 
 client c1 -connect ${h1_testme_sock} {
-- 
2.11.0




[PATCH 0/4] A few fixes for reg tests.

2018-12-20 Thread flecaille
From: Frédéric Lécaille 

Hi ML,

Here is a series of patches to fix a few reg testing issues.

Fred.
Frédéric Lécaille (4):
  REGTEST: Fix a typo about barrier type.
  REGTEST: Be less Linux specific with a syslog regex.
  REGTEST: Missing enclosing quotes for ${tmpdir} macro.
  REGTEST: Exclude freebsd target for some reg tests.

 reg-tests/checks/s0.vtc  | 3 ++-
 reg-tests/checks/s1.vtc  | 2 ++
 reg-tests/checks/s2.vtc  | 1 +
 reg-tests/checks/s3.vtc  | 2 +-
 reg-tests/connection/b0.vtc  | 4 ++--
 reg-tests/seamless-reload/b0.vtc | 4 ++--
 6 files changed, 10 insertions(+), 6 deletions(-)

-- 
2.11.0




[PATCH 1/4] REGTEST: Fix a typo about barrier type.

2018-12-20 Thread flecaille
From: Frédéric Lécaille 

Fix a typo, furthermore there is no reason to use a barrier with "sock" as type
which are more varnish cache specific: used to synchronize the VCL.
---
 reg-tests/checks/s0.vtc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc
index 35d0a988..0aae83a5 100644
--- a/reg-tests/checks/s0.vtc
+++ b/reg-tests/checks/s0.vtc
@@ -18,7 +18,7 @@ feature ignore_unknown_macro
 # before enabling the servers.
 
 # Cyclic barrier to synchonize the CLI with the syslog servers
-barrier b1 sock 5 -cyclic
+barrier b1 cond 5 -cyclic
 
 # These servers are there only for the health-check test.
 server s1 {
-- 
2.11.0




[PATCH 1/1] REGTEST: Make reg-tests target support argument.

2018-12-19 Thread flecaille
From: Frédéric Lécaille 

With this patch we can provide a list of argument to reg-tests target.
Useful to run reg tests for a list of VTC files like that:

$ VARNISHTEST_PROGRAM=<...> make reg-tests reg-tests/checks/*.vtc
---
 Makefile | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 47258511..450622ed 100644
--- a/Makefile
+++ b/Makefile
@@ -1092,9 +1092,15 @@ opts:
@echo 'OPTIONS_OBJS="$(strip $(OPTIONS_OBJS))"'
@echo 'OBJS="$(strip $(OBJS))"'
 
+ifeq (reg-tests, $(firstword $(MAKECMDGOALS)))
+  REGTEST_ARGS := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
+  $(eval $(REGTEST_ARGS):;@true)
+endif
+
 # Target to run the regression testing script files.
 reg-tests:
-   ./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REG_TEST_FILES)
+   @./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REGTEST_ARGS) 
$(REG_TEST_FILES)
+.PHONY: $(REGTEST_ARGS)
 
 reg-tests-help:
@echo
-- 
2.11.0




[PATCH 0/1] REGTEST: Reg testing improvement.

2018-12-19 Thread flecaille
From: Frédéric Lécaille 

Here is a little patch to make reg-tests target able of taking
arguments. May be useful during debugging steps.

Thanks to 
https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run
for this recipe.
Frédéric Lécaille (1):
  REGTEST: Make reg-tests target support argument.

 Makefile | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

-- 
2.11.0




[PATCH 1/1] REGTEST: Add a reg test for health-checks over SSL/TLS.

2018-12-18 Thread flecaille
From: Frédéric Lécaille 

This script runs two tests. One with "httpchk" over SSL/TLS and another
one with "check-ssl" option. As varnishtest does not support SSL/TLS
we use two haproxy processes to run these tests. h2 haproxy process
be2 and be4 backends declare one server each wich are the frontend
of h1 haproxy process. We check the layer6/7 checks thanks to syslog
messages.

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/checks/common.pem |  1 +
 reg-tests/checks/s4.vtc | 99 +
 2 files changed, 100 insertions(+)
 create mode 12 reg-tests/checks/common.pem
 create mode 100644 reg-tests/checks/s4.vtc

diff --git a/reg-tests/checks/common.pem b/reg-tests/checks/common.pem
new file mode 12
index ..a4433d56
--- /dev/null
+++ b/reg-tests/checks/common.pem
@@ -0,0 +1 @@
+../ssl/common.pem
\ No newline at end of file
diff --git a/reg-tests/checks/s4.vtc b/reg-tests/checks/s4.vtc
new file mode 100644
index ..1caeea1b
--- /dev/null
+++ b/reg-tests/checks/s4.vtc
@@ -0,0 +1,99 @@
+varnishtest "Health-check test over TLS/SSL"
+feature ignore_unknown_macro
+
+
+# This script tests health-checks for a TLS/SSL backend with "option httpchk"
+# and "check-ssl" option enabled attached to h2 haproxy process. This haproxy
+# h2 process is chained to h1 other one.
+#
+server s1 {
+rxreq
+expect req.method == OPTIONS
+expect req.url == *
+expect req.proto == HTTP/1.1
+txresp
+} -start
+
+server s2 {
+} -start
+
+syslog S1 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy fe1 started."
+recv info
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1~ be1/srv1 .* 200 [[:digit:]]+ - 
-  .* \"OPTIONS \\* HTTP/1.1\""
+recv info
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1~ be1/srv1 .* 504 [[:digit:]]+ - 
- sH-- .* \"OPTIONS \\* HTTP/1.1\""
+} -start
+
+haproxy h1 -conf {
+global
+tune.ssl.default-dh-param 2048
+
+defaults
+mode http
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+
+backend be1
+server srv1 ${s1_addr}:${s1_port}
+
+backend be2
+server srv2 ${s2_addr}:${s2_port}
+
+frontend fe1
+option httplog
+log ${S1_addr}:${S1_port} len 2048 local0 debug err
+bind "fd@${fe1}" ssl crt ${testdir}/common.pem
+use_backend be1
+
+frontend fe2
+option tcplog
+bind "fd@${fe2}" ssl crt ${testdir}/common.pem
+use_backend be2
+} -start
+
+syslog S2 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Proxy be2 started."
+recv
+expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be2/srv1 
succeeded, reason: Layer7 check passed, code: 200, info: \"OK\", check 
duration: [[:digit:]]+ms, status: 1/1 UP."
+recv
+expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be2/srv1 
failed, reason: Layer7 wrong status, code: 504, info: \"Gateway Time-out\", 
check duration: [[:digit:]]+ms, status: 0/1 DOWN."
+} -start
+
+syslog S4 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Proxy be4 started."
+recv
+expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be4/srv2 
succeeded, reason: Layer6 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP."
+} -start
+
+haproxy h2 -conf {
+global
+tune.ssl.default-dh-param 2048
+
+defaults
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+default-server downinter 1s rise 1 fall 1
+
+backend be2
+option log-health-checks
+option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
+log ${S2_addr}:${S2_port} daemon
+server srv1 ${h1_fe1_addr}:${h1_fe1_port} ssl crt 
${testdir}/common.pem verify none check
+
+backend be4
+option log-health-checks
+log ${S4_addr}:${S4_port} daemon
+server srv2 ${h1_fe2_addr}:${h1_fe2_port} ssl crt 
${testdir}/common.pem verify none check-ssl check
+} -start
+
+syslog S1 -wait
+
+syslog S2 -wait
+syslog S4 -wait
+
-- 
2.11.0




[PATCH 1/1] REGTEST: Add a reg test for HTTP cookies.

2018-12-14 Thread flecaille
From: Frédéric Lécaille 

This script tests the "cookie  insert indirect" directive with
header checks on server and client side. syslog messages are also
checked, especially --II (invalid, insert) flags logging.

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/http-cookies/h0.vtc | 58 +++
 1 file changed, 58 insertions(+)
 create mode 100644 reg-tests/http-cookies/h0.vtc

diff --git a/reg-tests/http-cookies/h0.vtc 
b/reg-tests/http-cookies/h0.vtc
new file mode 100644
index ..3ea16acc
--- /dev/null
+++ b/reg-tests/http-cookies/h0.vtc
@@ -0,0 +1,58 @@
+varnishtest "HTTP cookie basic test"
+feature ignore_unknown_macro
+
+# This script tests "cookie  insert indirect" directive.
+# The client sends a wrong "SRVID=s2" cookie.
+# haproxy removes it.
+# The server replies with "SRVID=S1" after having checked that
+# no cookies were sent by haproxy.
+# haproxy replies "SRVID=server-one" to the client.
+# We log the HTTP request to a syslog server and check their "--II"
+# (invalid, insert) flags.
+
+syslog S1 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy (fe|be)1 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy (fe|be)1 started."
+recv info
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1 be1/srv1 .* --II .* \"GET / 
HTTP/1\\.1\""
+} -start
+
+server s1 {
+   rxreq
+   expect req.http.cookie == 
+txresp -hdr "Cookie: SRVID=S1"
+} -start
+
+haproxy h1 -conf {
+   global
+log ${S1_addr}:${S1_port} len 2048 local0 debug err
+
+defaults
+mode http
+   option httplog
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+log global
+
+backend be1
+cookie SRVID insert indirect
+server srv1 ${s1_addr}:${s1_port} cookie server-one
+
+frontend fe1
+   option httplog
+bind "fd@${fe1}"
+use_backend be1
+} -start
+
+client c1 -connect ${h1_fe1_sock} {
+txreq -hdr "Cookie: SRVID=s2"
+rxresp
+expect resp.http.Set-Cookie ~ "^SRVID=server-one;.*"
+} -start
+
+
+client c1 -wait
+syslog S1 -wait
-- 
2.11.0




[PATCH 2/5] REGTEST: Add a first test for health-checks.

2018-12-13 Thread flecaille
From: Frédéric Lécaille 

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/checks/s0.vtc | 207 
 1 file changed, 207 insertions(+)
 create mode 100644 reg-tests/checks/s0.vtc

diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc
new file mode 100644
index ..35d0a988
--- /dev/null
+++ b/reg-tests/checks/s0.vtc
@@ -0,0 +1,207 @@
+varnishtest "Health-check test"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=1.8
+
+# This script test health-checks for four backends with one server by backend.
+# A syslog server is attached to each backend to check the syslog messages
+# in the righ order.
+
+# First, we check a health-check has passed for all the servers thanks to the 
syslog
+# messages. Then each server is disabled. The health-check status are checked.
+# Then each server is re-enabled. Finally health-check status
+# verifications for each server terminate the execution of this script.
+
+# Note that the CLI is synchronized with the syslog servers so that
+# to be sure to receive the passed health-checks status messages before
+# disabling the servers. Same thing, when we check that the servers are down
+# before enabling the servers.
+
+# Cyclic barrier to synchonize the CLI with the syslog servers
+barrier b1 sock 5 -cyclic
+
+# These servers are there only for the health-check test.
+server s1 {
+} -start
+
+server s2 {
+} -start
+
+server s3 {
+} -start
+
+server s4 {
+} -start
+
+syslog S1 -level notice {
+recv
+expect ~ "Proxy be1 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+barrier b1 sync
+recv alert
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be1/srv1 is going DOWN for 
maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 
requeued, 0 remaining in queue."
+recv emerg
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be1 has no server available!"
+barrier b1 sync
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be1/srv1 is UP/READY \\(leaving 
forced maintenance\\).|Health check for server be1/srv1 succeeded, reason: 
Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)"
+barrier b1 sync
+} -start
+
+syslog S2 -level notice {
+recv
+expect ~ "Proxy be2 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+barrier b1 sync
+recv alert
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be2/srv2 is going DOWN for 
maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 
requeued, 0 remaining in queue."
+recv emerg
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be2 has no server available!"
+barrier b1 sync
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be2/srv2 is UP/READY \\(leaving 
forced maintenance\\).|Health check for server be2/srv2 succeeded, reason: 
Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)"
+barrier b1 sync
+} -start
+
+syslog S3 -level notice {
+recv
+expect ~ "Proxy be3 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+barrier b1 sync
+recv alert
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be3/srv3 is going DOWN for 
maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 
requeued, 0 remaining in queue."
+recv emerg
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be3 has no server available!"
+barrier b1 sync
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be3/srv3 is UP/READY \\(leaving 
forced maintenance\\).|Health check for server be3/srv3 succeeded, reason: 
Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)"
+barrier b1 sync
+} -start
+
+syslog S4 -level notice {
+recv
+expect ~ "Proxy be4 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv4 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+barrier b1 sync
+recv alert
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be4/srv4 is going DOWN for 
maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 
requeued, 0 remaining in queue."
+recv emerg
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be4 has no server available!"
+barrier b1 sync
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be4/srv4 is UP/READY \\(leaving 
forced maintenance\\).|Health check for server be4/srv4 succeeded, reason: 
Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)"
+barrier b1 sync
+} -start
+
+
+haproxy h1 -conf {
+defaults
+timeout client  1s
+timeout server  1s
+timeout connect

[PATCH 1/5] REGTEST: Reg testing improvements.

2018-12-13 Thread flecaille
From: Frédéric Lécaille 

Add a new target to the Makefile named "reg-tests-help" to have an idea
about how to run the reg tests from haproxy Makefile.
Handle list of levels and lists of level range passed to make with LEVEL 
variable.
New supported syntax:
LEVEL=1,4 make reg-tests
LEVEL=1-2,5-6 make reg-tests
Add two new levels 5 and 6. 5 is for broken script, 6 for experimental scripts.

Signed-off-by: Frédéric Lécaille 
---
 Makefile| 34 +++---
 scripts/run-regtests.sh | 91 +++--
 2 files changed, 110 insertions(+), 15 deletions(-)

diff --git a/Makefile b/Makefile
index 587bc048..ae2e75ea 100644
--- a/Makefile
+++ b/Makefile
@@ -1090,10 +1090,34 @@ opts:
@echo 'OBJS="$(strip $(OBJS))"'
 
 # Target to run the regression testing script files.
-# LEVEL 1 scripts are dedicated to pure haproxy compliance tests (prefixed 
with 'h' letter).
-# LEVEL 2 scripts are slow scripts (prefixed with 's' letter).
-# LEVEL 3 scripts are low interest scripts (prefixed with 'l' letter).
-# LEVEL 4 scripts are in relation with bugs they help to reproduce (prefixed 
with 'b' letter).
 reg-tests:
./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REG_TEST_FILES)
-.PHONY: reg-tests
+
+reg-tests-help:
+   @echo
+   @echo "To launch the reg tests for haproxy, first export to your 
environment VARNISHTEST_PROGRAM variable to point to your varnishtest program:"
+   @echo "$$ export VARNISHTEST_PROGRAM=/opt/local/bin/varnishtest"
+   @echo "or"
+   @echo "$$ setenv VARNISHTEST_PROGRAM /opt/local/bin/varnishtest"
+   @echo
+   @echo "The same thing may be done to set your haproxy program with 
HAPROXY_PROGRAM but with ./haproxy as default value."
+   @echo
+   @echo "To run all the tests:"
+   @echo "$$ make reg-tests"
+   @echo
+   @echo "You can also set the programs to be used on the command line:"
+   @echo "$$ VARNISHTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make 
reg-tests"
+   @echo
+   @echo "To run tests with specific levels:"
+   @echo "$$ LEVEL=1,3,4   make reg-tests  #list of levels"
+   @echo "$$ LEVEL=1-3,5-6 make reg-tests  #list of range of levels"
+   @echo
+   @echo "About the levels:"
+   @echo "LEVEL 1 scripts are dedicated to pure haproxy compliance 
tests (prefixed with 'h' letter)."
+   @echo "LEVEL 2 scripts are slow scripts (prefixed with 's' letter)."
+   @echo "LEVEL 3 scripts are low interest scripts (prefixed with 'l' 
letter)."
+   @echo "LEVEL 4 scripts are in relation with bugs they help to 
reproduce (prefixed with 'b' letter)."
+   @echo "LEVEL 5 scripts are broken scripts, typically used to fastly 
disable broken scripts (prefixed with 'k' letter)."
+   @echo "LEVEL 6 scripts are experimental, typically used to develop 
new scripts (prefixed with 'e' lettre)."
+
+.PHONY: reg-tests reg-tests-help
diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh
index 3034e363..3ed38062 100755
--- a/scripts/run-regtests.sh
+++ b/scripts/run-regtests.sh
@@ -40,10 +40,85 @@ if [ "$1" = "--help" ]; then
   Configure environment variables to set the haproxy and varnishtest binaries 
to use
 setenv HAPROXY_PROGRAM /usr/local/sbin/haproxy
 setenv VARNISHTEST_PROGRAM /usr/local/bin/varnishtest
+  or
+export HAPROXY_PROGRAM=/usr/local/sbin/haproxy
+export VARNISHTEST_PROGRAM=/usr/local/bin/varnishtest
 EOF
   return
 fi
 
+add_range_to_test_list()
+{
+level0="*.vtc"
+level1="h*.vtc"
+level2="s*.vtc"
+level3="l*.vtc"
+level4="b*.vtc"
+level5="k*.vtc"
+level6="e*.vtc"
+
+new_range=$(echo $1 | tr '-' ' ')
+non_digit=$(echo $new_range | grep '[^0-9 ]')
+if [ -n "$non_digit" ] ; then
+return
+fi
+if [ "$new_range" = "$1" ] ; then
+if [ $1 -gt 6 ] ; then
+return
+fi
+eval echo '$'level$1
+return
+fi
+if [ -z "$new_range" ] ; then
+return
+fi
+list=
+for l in $(seq $new_range) ; do
+if [ -n "l" ] ; then
+if [ -z "$list" ] ; then
+list="$(eval echo '$'level${l})"
+else
+list="$list $(eval echo '$'level${l})"
+fi
+fi
+done
+
+echo $list
+}
+
+
+build_test_list()
+{
+# Remove any spacing character
+LEVEL="$(echo $LEVEL | tr -d ' ')"
+# Replave any comma character by a space character
+LEVEL="$(echo $LEVEL | tr ',' ' ')"
+list=
+for range in $LEVEL ; do
+if [ -z "$list" ] ; then
+list=$(add_range_to_test_list $range)
+else
+list="$list $(add_range_to_test_list $range)"
+fi
+done
+
+echo $list
+}
+
+build_find_expr()
+{
+expr=
+for i in $@; do
+if [ -z "$expr" ] ; then
+expr="-name \"$i\""
+else
+expr="$expr -o -name \"$i\""
+ 

[PATCH 4/5] REGTEST: level 1 health-check test 2.

2018-12-13 Thread flecaille
From: Frédéric Lécaille 

With this test we check that the health-checks do not consume any connection on
the backend side.

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/checks/s2.vtc | 677 
 1 file changed, 677 insertions(+)
 create mode 100644 reg-tests/checks/s2.vtc

diff --git a/reg-tests/checks/s2.vtc b/reg-tests/checks/s2.vtc
new file mode 100644
index ..7246
--- /dev/null
+++ b/reg-tests/checks/s2.vtc
@@ -0,0 +1,677 @@
+varnishtest "Health-checks"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=1.8
+
+# This script start 40 servers named s0 up to s39.
+# For 0 <= i <= 19:
+#   - s(i) and s(i+1) belong to backend be(2*i+1),
+#   - fe(2*i+1) backend is configured to used be(2*i+1) backend.
+#   - only s(2*i+1) servers have health-checks enabled,
+#   - we start 20 clients named s(2*i+1) which connect to fe(2*i+1) frontend,
+#   - so that to ensure that health-checks do not consume any connection
+# (any varnishtest server without -repeat  with n > 1 accepts
+# only one connection).
+
+# Note that the first syslog message received is: "Proxy  started."
+syslog S1 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be1 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S3 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S5 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be5 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be5/srv5 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S7 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be7 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be7/srv7 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S9 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be9 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be9/srv9 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S11 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be11 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be11/srv11 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S13 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be13 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be13/srv13 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S15 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be15 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be15/srv15 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S17 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be17 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be17/srv17 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S19 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be19 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be19/srv19 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S21 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be21 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be21/srv21 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S23 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be23 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be23/srv23 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S25 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be25 started."
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be25/srv25 
succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 
1/1 UP"
+} -start
+
+syslog S27 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be27 started."
+recv
+expect ~ "[^:\\[ ]\\[${h

[PATCH 3/5] REGTEST: Reg test for "check" health-check option.

2018-12-13 Thread flecaille
From: Frédéric Lécaille 

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/checks/s1.vtc | 114 
 1 file changed, 114 insertions(+)
 create mode 100644 reg-tests/checks/s1.vtc

diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc
new file mode 100644
index ..ff972efd
--- /dev/null
+++ b/reg-tests/checks/s1.vtc
@@ -0,0 +1,114 @@
+varnishtest "Health-checks: only for servers with 'check' set"
+feature ignore_unknown_macro
+
+# This test start 40 servers in the same backend, named srv0 up to srv39.
+# Only the odd servers have health-checks enabled.
+# The first health-checks passed tests are checked for all these servers
+# thanks to syslog messages.
+
+# Note that the first syslog message received is: "Proxy  started."
+syslog S -repeat 21 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Health check for server 
be1/srv([13579]|[123][13579]) succeeded, reason: Layer4 check passed, check 
duration: [[:digit:]]+ms, status: 1/1 UP|Proxy be1 started.)"
+} -start
+
+server s0 {} -start
+server s1 {} -start
+server s2 {} -start
+server s3 {} -start
+server s4 {} -start
+server s5 {} -start
+server s6 {} -start
+server s7 {} -start
+server s8 {} -start
+server s9 {} -start
+server s10 {} -start
+server s11 {} -start
+server s12 {} -start
+server s13 {} -start
+server s14 {} -start
+server s15 {} -start
+server s16 {} -start
+server s17 {} -start
+server s18 {} -start
+server s19 {} -start
+server s20 {} -start
+server s21 {} -start
+server s22 {} -start
+server s23 {} -start
+server s24 {} -start
+server s25 {} -start
+server s26 {} -start
+server s27 {} -start
+server s28 {} -start
+server s29 {} -start
+server s30 {} -start
+server s31 {} -start
+server s32 {} -start
+server s33 {} -start
+server s34 {} -start
+server s35 {} -start
+server s36 {} -start
+server s37 {} -start
+server s38 {} -start
+server s39 {} -start
+
+haproxy h1 -conf {
+defaults
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+default-server no-check downinter 1s rise 1 fall 1
+
+backend be1
+option log-health-checks
+log ${S_addr}:${S_port} daemon
+server srv0 ${s0_addr}:${s0_port}
+server srv1 ${s1_addr}:${s1_port} check
+server srv2 ${s2_addr}:${s2_port}
+server srv3 ${s3_addr}:${s3_port} check
+server srv4 ${s4_addr}:${s4_port}
+server srv5 ${s5_addr}:${s5_port} check
+server srv6 ${s6_addr}:${s6_port}
+server srv7 ${s7_addr}:${s7_port} check
+server srv8 ${s8_addr}:${s8_port}
+server srv9 ${s9_addr}:${s9_port} check
+server srv10 ${s10_addr}:${s10_port}
+server srv11 ${s11_addr}:${s11_port} check
+server srv12 ${s12_addr}:${s12_port}
+server srv13 ${s13_addr}:${s13_port} check
+server srv14 ${s14_addr}:${s14_port}
+server srv15 ${s15_addr}:${s15_port} check
+server srv16 ${s16_addr}:${s16_port}
+server srv17 ${s17_addr}:${s17_port} check
+server srv18 ${s18_addr}:${s18_port}
+server srv19 ${s19_addr}:${s19_port} check
+server srv20 ${s20_addr}:${s20_port}
+server srv21 ${s21_addr}:${s21_port} check
+server srv22 ${s22_addr}:${s22_port}
+server srv23 ${s23_addr}:${s23_port} check
+server srv24 ${s24_addr}:${s24_port}
+server srv25 ${s25_addr}:${s25_port} check
+server srv26 ${s26_addr}:${s26_port}
+server srv27 ${s27_addr}:${s27_port} check
+server srv28 ${s28_addr}:${s28_port}
+server srv29 ${s29_addr}:${s29_port} check
+server srv30 ${s30_addr}:${s30_port}
+server srv31 ${s31_addr}:${s31_port} check
+server srv32 ${s32_addr}:${s32_port}
+server srv33 ${s33_addr}:${s33_port} check
+server srv34 ${s34_addr}:${s34_port}
+server srv35 ${s35_addr}:${s35_port} check
+server srv36 ${s36_addr}:${s36_port}
+server srv37 ${s37_addr}:${s37_port} check
+server srv38 ${s38_addr}:${s38_port}
+server srv39 ${s39_addr}:${s39_port} check
+} -start
+
+syslog S -wait
+
+haproxy h1 -cli {
+send "show servers state"
+expect ~ "# be_id be_name srv_id srv_name srv_addr srv_op_state 
srv_admin_state srv_uweight srv_iweight srv_time_since_last_change 
srv_check_status srv_check_result srv_check_health srv_check_state 
srv_agent_state bk_f_forced_id srv_f_forced_id srv_fqdn srv_port srvrecord\n2 
be1 1 srv0 ${s0_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - ${s0_port} -\n2 be1 
2 srv1 ${s1_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ ){3}0 0 0 - ${s1_port} 
-\n2 be1 3 srv2 ${s2_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - ${s2_port} -\n2 
be1 4 srv3 ${s3_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ ){3}0 0 0 - 
${s3_port} -\n2 be1 5 srv4 ${s4_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - 
${s4_port} -\n2 be1 6 srv5 ${s5_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ 
){3}0 0 0 - ${s5_port} -\n

[PATCH 5/5] REGTEST: Add miscellaneous reg tests for health-checks.

2018-12-13 Thread flecaille
From: Frédéric Lécaille 

Signed-off-by: Frédéric Lécaille 
---
 reg-tests/checks/s3.vtc | 95 +
 1 file changed, 95 insertions(+)
 create mode 100644 reg-tests/checks/s3.vtc

diff --git a/reg-tests/checks/s3.vtc b/reg-tests/checks/s3.vtc
new file mode 100644
index ..b57b965f
--- /dev/null
+++ b/reg-tests/checks/s3.vtc
@@ -0,0 +1,95 @@
+varnishtest "Check: smptchk option"
+feature ignore_unknown_macro
+
+barrier b cond 3
+
+syslog S1 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be1 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 
succeeded, reason: Layer7 check passed, code: 248, check duration: 
[[:digit:]]+ms, status: 1/1 UP."
+barrier b sync
+recv
+expect ~ "Health check for server be1/srv1 failed, reason: Layer7 timeout, 
check duration: [[:digit:]]+ms, status: 0/1 DOWN"
+} -start
+
+syslog S2 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be2 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 
succeeded, reason: Layer7 check passed, code: 200, info: \"OK\", check 
duration: [[:digit:]]+ms, status: 1/1 UP."
+barrier b sync
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 
failed, reason: Layer7 timeout, check duration: [[:digit:]]+ms, status: 0/1 
DOWN"
+} -start
+
+syslog S3 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 
failed, reason: Layer4 connection problem, info: \"General socket error 
\\(Network is unreachable\\)\", check duration: [[:digit:]]+ms, status: 0/1 
DOWN."
+} -start
+
+syslog S4 -level notice {
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be4 started"
+recv
+expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv4 
failed, reason: Layer4 connection problem, info: \"Connection refused\", check 
duration: [[:digit:]]+ms, status: 0/1 DOWN."
+} -start
+
+server s1 {
+recv 16
+send "2"
+send "4"
+send "8"
+send "\r\n\r\n"
+} -start
+
+server s2 {
+rxreq
+txresp
+} -start
+
+haproxy h1 -conf {
+defaults
+timeout client 1s
+timeout server 1s
+timeout connect 1s
+option log-health-checks
+default-server downinter 1s rise 1 fall 1
+
+backend be1
+option smtpchk
+log ${S1_addr}:${S1_port} daemon
+server srv1 ${s1_addr}:${s1_port} check
+
+backend be2
+mode tcp
+log ${S2_addr}:${S2_port} daemon
+option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
+server srv2  ${s2_addr}:${s2_port} check
+
+backend be3
+log ${S3_addr}:${S3_port} daemon
+server srv3 255.255.255.255:1 check
+
+backend be4
+log ${S4_addr}:${S4_port} daemon
+server srv4 localhost:1 check
+} -start
+
+haproxy h1 -cli {
+barrier b sync
+send "show servers state"
+expect ~ .*
+}
+
+server s1 -wait
+server s2 -wait
+
+syslog S1 -wait
+syslog S2 -wait
+syslog S3 -wait
+syslog S4 -wait
+
+
-- 
2.11.0