Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2019-09-25 01:50:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new.7948 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Wed Sep 25 01:50:23 2019 rev:74 rq:731949 version:2.0.6+git0.58706ab4 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2019-09-07 11:26:29.438486292 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new.7948/haproxy.changes 2019-09-25 01:50:25.085600808 +0200 @@ -1,0 +2,49 @@ +Tue Sep 17 15:41:39 UTC 2019 - [email protected] + +- Update to version 2.0.6+git0.58706ab4: + * [RELEASE] Released version 2.0.6 + * MINOR: sample: Add UUID-fetch + * BUG/MINOR: Missing stat_field_names (since f21d17bb) + * BUG/MINOR: backend: Fix a possible null pointer dereference + * BUG/MINOR: acl: Fix memory leaks when an ACL expression is parsed + * BUG/MINOR: filters: Properly set the HTTP status code on analysis error + * BUG/MEDIUM: http: also reject messages where "chunked" is missing from transfer-enoding + * BUG/MINOR: ssl: always check for ssl connection before getting its XPRT context + * BUG/MINOR: listener: Fix a possible null pointer dereference + * MINOR: stats: report the number of idle connections for each server + * BUG/MEDIUM: connection: don't keep more idle connections than ever needed + * BUG/MAJOR: ssl: ssl_sock was not fully initialized. + * BUG/MINOR: lb/leastconn: ignore the server weights for empty servers + * MINOR: contrib/prometheus-exporter: Report DRAIN/MAINT/NOLB status for servers + * BUG/MINOR: checks: do not uselessly poll for reads before the connection is up + * BUG/MINOR: checks: make __event_chk_srv_r() report success before closing + * BUG/MINOR: checks: start sending the request right after connect() + * BUG/MINOR: checks: stop polling for write when we have nothing left to send + * BUG/MEDIUM: cache: Don't cache objects if the size of headers is too big + * BUG/MEDIUM: cache: Properly copy headers splitted on several shctx blocks + * BUG/MINOR: mux-h1: Be sure to update the count before adding EOM after trailers + * BUG/MINOR: mux-h1: Don't stop anymore input processing when the max is reached + * BUG/MINOR: mux-h1: Fix size evaluation of HTX messages after headers parsing + * BUG/MINOR: h1: Properly reset h1m when parsing is restarted + * BUG/MINOR: http-ana: Reset response flags when 1xx messages are handled + * BUG/MEDIUM: peers: local peer socket not bound. + * BUG/MEDIUM: proto-http: Always start the parsing if there is no outgoing data + * BUG/MEDIUM: url32 does not take the path part into account in the returned hash. + * BUG/MEDIUM: listener/threads: fix an AB/BA locking issue in delete_listener() + * BUG/MINOR: mworker: disable SIGPROF on re-exec + * DOC: fixed typo in management.txt + * BUG/MEDIUM: mux-h1: do not report errors on transfers ending on buffer full + * BUG/MEDIUM: mux-h1: do not truncate trailing 0CRLF on buffer boundary + * MEDIUM: debug: make the thread dump code show Lua backtraces + * MINOR: lua: export applet and task handlers + * MINOR: tools: add append_prefixed_str() + * MINOR: debug: indicate the applet name when the task is task_run_applet() + +------------------------------------------------------------------- +Thu Aug 22 11:23:04 CEST 2019 - [email protected] + +- Use %license instead of %doc [bsc#1082318] +- Recommend apparmor, it's not required to work (make haproxy + useable in a container) + +------------------------------------------------------------------- Old: ---- haproxy-2.0.5+git0.d905f49a.tar.gz New: ---- haproxy-2.0.6+git0.58706ab4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.FBSw9i/_old 2019-09-25 01:50:25.969600795 +0200 +++ /var/tmp/diff_new_pack.FBSw9i/_new 2019-09-25 01:50:25.973600795 +0200 @@ -1,7 +1,7 @@ # # spec file for package haproxy # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -47,7 +47,7 @@ %endif Name: haproxy -Version: 2.0.5+git0.d905f49a +Version: 2.0.6+git0.58706ab4 Release: 0 # # @@ -55,10 +55,10 @@ %if %{with apparmor} %if 0%{?suse_version} <= 1315 BuildRequires: apparmor-profiles -Requires: apparmor-profiles +Recommends: apparmor-profiles %else BuildRequires: apparmor-abstractions -Requires: apparmor-abstractions +Recommends: apparmor-abstractions %endif %if %{with apparmor_reload} BuildRequires: apparmor-rpm-macros @@ -230,7 +230,8 @@ %files %defattr(-,root,root,-) -%doc CHANGELOG README LICENSE +%license LICENSE +%doc CHANGELOG README %doc ROADMAP doc/* examples/ %doc contrib/netsnmp-perl/ contrib/selinux/ %dir %attr(-,root,haproxy) %{_sysconfdir}/%{pkg_name} ++++++ _service ++++++ --- /var/tmp/diff_new_pack.FBSw9i/_old 2019-09-25 01:50:26.009600795 +0200 +++ /var/tmp/diff_new_pack.FBSw9i/_new 2019-09-25 01:50:26.009600795 +0200 @@ -6,7 +6,7 @@ <param name="versionformat">@PARENT_TAG@+git@TAG_OFFSET@.%h</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> - <param name="revision">v2.0.5</param> + <param name="revision">v2.0.6</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.FBSw9i/_old 2019-09-25 01:50:26.025600794 +0200 +++ /var/tmp/diff_new_pack.FBSw9i/_new 2019-09-25 01:50:26.025600794 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-2.0.git</param> - <param name="changesrevision">d905f49a0dbf78b69f24ee69df10b873680b92ea</param> + <param name="changesrevision">58706ab4bdbea3468253eddf07f2d58db43bfcb4</param> </service> </servicedata> \ No newline at end of file ++++++ haproxy-2.0.5+git0.d905f49a.tar.gz -> haproxy-2.0.6+git0.58706ab4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/CHANGELOG new/haproxy-2.0.6+git0.58706ab4/CHANGELOG --- old/haproxy-2.0.5+git0.d905f49a/CHANGELOG 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/CHANGELOG 2019-09-13 13:46:44.000000000 +0200 @@ -1,6 +1,44 @@ ChangeLog : =========== +2019/09/13 : 2.0.6 + - MINOR: debug: indicate the applet name when the task is task_run_applet() + - MINOR: tools: add append_prefixed_str() + - MINOR: lua: export applet and task handlers + - MEDIUM: debug: make the thread dump code show Lua backtraces + - BUG/MEDIUM: mux-h1: do not truncate trailing 0CRLF on buffer boundary + - BUG/MEDIUM: mux-h1: do not report errors on transfers ending on buffer full + - DOC: fixed typo in management.txt + - BUG/MINOR: mworker: disable SIGPROF on re-exec + - BUG/MEDIUM: listener/threads: fix an AB/BA locking issue in delete_listener() + - BUG/MEDIUM: url32 does not take the path part into account in the returned hash. + - BUG/MEDIUM: proto-http: Always start the parsing if there is no outgoing data + - BUG/MEDIUM: peers: local peer socket not bound. + - BUG/MINOR: http-ana: Reset response flags when 1xx messages are handled + - BUG/MINOR: h1: Properly reset h1m when parsing is restarted + - BUG/MINOR: mux-h1: Fix size evaluation of HTX messages after headers parsing + - BUG/MINOR: mux-h1: Don't stop anymore input processing when the max is reached + - BUG/MINOR: mux-h1: Be sure to update the count before adding EOM after trailers + - BUG/MEDIUM: cache: Properly copy headers splitted on several shctx blocks + - BUG/MEDIUM: cache: Don't cache objects if the size of headers is too big + - BUG/MINOR: checks: stop polling for write when we have nothing left to send + - BUG/MINOR: checks: start sending the request right after connect() + - BUG/MINOR: checks: make __event_chk_srv_r() report success before closing + - BUG/MINOR: checks: do not uselessly poll for reads before the connection is up + - MINOR: contrib/prometheus-exporter: Report DRAIN/MAINT/NOLB status for servers + - BUG/MINOR: lb/leastconn: ignore the server weights for empty servers + - BUG/MAJOR: ssl: ssl_sock was not fully initialized. + - BUG/MEDIUM: connection: don't keep more idle connections than ever needed + - MINOR: stats: report the number of idle connections for each server + - BUG/MINOR: listener: Fix a possible null pointer dereference + - BUG/MINOR: ssl: always check for ssl connection before getting its XPRT context + - BUG/MEDIUM: http: also reject messages where "chunked" is missing from transfer-enoding + - BUG/MINOR: filters: Properly set the HTTP status code on analysis error + - BUG/MINOR: acl: Fix memory leaks when an ACL expression is parsed + - BUG/MINOR: backend: Fix a possible null pointer dereference + - BUG/MINOR: Missing stat_field_names (since f21d17bb) + - MINOR: sample: Add UUID-fetch + 2019/08/16 : 2.0.5 - BUG/MEDIUM: stick-table: Wrong stick-table backends parsing. - BUG/MINOR: ssl: fix 0-RTT for BoringSSL diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/VERDATE new/haproxy-2.0.6+git0.58706ab4/VERDATE --- old/haproxy-2.0.5+git0.d905f49a/VERDATE 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/VERDATE 2019-09-13 13:46:44.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2019/08/16 +2019/09/13 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/VERSION new/haproxy-2.0.6+git0.58706ab4/VERSION --- old/haproxy-2.0.5+git0.d905f49a/VERSION 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/VERSION 2019-09-13 13:46:44.000000000 +0200 @@ -1 +1 @@ -2.0.5 +2.0.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/contrib/prometheus-exporter/service-prometheus.c new/haproxy-2.0.6+git0.58706ab4/contrib/prometheus-exporter/service-prometheus.c --- old/haproxy-2.0.5+git0.d905f49a/contrib/prometheus-exporter/service-prometheus.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/contrib/prometheus-exporter/service-prometheus.c 2019-09-13 13:46:44.000000000 +0200 @@ -659,7 +659,7 @@ [ST_F_ERESP] = IST("Total number of response errors."), [ST_F_WRETR] = IST("Total number of retry warnings."), [ST_F_WREDIS] = IST("Total number of redispatch warnings."), - [ST_F_STATUS] = IST("Current status of the service (frontend: 0=STOP, 1=UP, 2=FULL - backend/server: 0=DOWN, 1=UP)."), + [ST_F_STATUS] = IST("Current status of the service (frontend: 0=STOP, 1=UP, 2=FULL - backend: 0=DOWN, 1=UP - server: 0=DOWN, 1=UP, 2=MAINT, 3=DRAIN, 4=NOLB)."), [ST_F_WEIGHT] = IST("Service weight."), [ST_F_ACT] = IST("Current number of active servers."), [ST_F_BCK] = IST("Current number of backup servers."), @@ -1044,25 +1044,21 @@ [ST_F_CACHE_HITS] = IST("counter"), }; -/* Return the server status: 1=UP and 0=DOWN. */ +/* Return the server status: 0=DOWN, 1=UP, 2=MAINT, 3=DRAIN, 4=NOLB. */ static int promex_srv_status(struct server *sv) { - struct server *via, *ref; int state = 0; - /* we have "via" which is the tracked server as described in the configuration, - * and "ref" which is the checked server and the end of the chain. - */ - via = sv->track ? sv->track : sv; - ref = via; - while (ref->track) - ref = ref->track; - if (sv->cur_state == SRV_ST_RUNNING || sv->cur_state == SRV_ST_STARTING) { state = 1; if (sv->cur_admin & SRV_ADMF_DRAIN) - state = 0; + state = 3; } + else if (sv->cur_state == SRV_ST_STOPPING) + state = 4; + + if (sv->cur_admin & SRV_ADMF_MAINT) + state = 2; return state; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/doc/configuration.txt new/haproxy-2.0.6+git0.58706ab4/doc/configuration.txt --- old/haproxy-2.0.5+git0.d905f49a/doc/configuration.txt 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/doc/configuration.txt 2019-09-13 13:46:44.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 2.0 willy tarreau - 2019/08/16 + 2019/09/13 This document covers the configuration language as implemented in the version @@ -14770,6 +14770,11 @@ needed to take some routing decisions for example, or just for debugging purposes. This random must not be used for security purposes. +uuid([<version>]) : string + Returns a UUID following the RFC4122 standard. If the version is not + specified, a UUID version 4 (fully random) is returned. + Currently, only version 4 is supported. + srv_conn([<backend>/]<server>) : integer Returns an integer value corresponding to the number of currently established connections on the designated server, possibly including the connection being diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/doc/management.txt new/haproxy-2.0.6+git0.58706ab4/doc/management.txt --- old/haproxy-2.0.5+git0.d905f49a/doc/management.txt 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/doc/management.txt 2019-09-13 13:46:44.000000000 +0200 @@ -1549,8 +1549,8 @@ level "admin". enable dynamic-cookie backend <backend> - Enable the generation of dynamic cookies fot the backend <backend> - A secret key must also be provided + Enable the generation of dynamic cookies for the backend <backend>. + A secret key must also be provided. enable frontend <frontend> Resume a frontend which was temporarily stopped. It is possible that some of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/include/common/standard.h new/haproxy-2.0.6+git0.58706ab4/include/common/standard.h --- old/haproxy-2.0.5+git0.d905f49a/include/common/standard.h 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/include/common/standard.h 2019-09-13 13:46:44.000000000 +0200 @@ -1238,6 +1238,7 @@ * free(err); */ char *indent_msg(char **out, int level); +int append_prefixed_str(struct buffer *out, const char *in, const char *pfx, char eol, int first); /* removes environment variable <name> from the environment as found in * environ. This is only provided as an alternative for systems without diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/include/proto/hlua.h new/haproxy-2.0.6+git0.58706ab4/include/proto/hlua.h --- old/haproxy-2.0.5+git0.d905f49a/include/proto/hlua.h 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/include/proto/hlua.h 2019-09-13 13:46:44.000000000 +0200 @@ -27,6 +27,9 @@ void hlua_ctx_destroy(struct hlua *lua); void hlua_init(); int hlua_post_init(); +void hlua_applet_tcp_fct(struct appctx *ctx); +void hlua_applet_http_fct(struct appctx *ctx); +struct task *hlua_process_task(struct task *task, void *context, unsigned short state); #else /* USE_LUA */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/include/proto/server.h new/haproxy-2.0.6+git0.58706ab4/include/proto/server.h --- old/haproxy-2.0.5+git0.d905f49a/include/proto/server.h 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/include/proto/server.h 2019-09-13 13:46:44.000000000 +0200 @@ -249,6 +249,7 @@ { if (srv && srv->pool_purge_delay > 0 && (srv->max_idle_conns == -1 || srv->max_idle_conns > srv->curr_idle_conns) && + (srv->cur_sess + srv->curr_idle_conns <= srv->counters.cur_sess_max) && !(conn->flags & CO_FL_PRIVATE) && ((srv->proxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) && !conn->mux->used_streams(conn) && conn->mux->avail_streams(conn) && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/include/types/stats.h new/haproxy-2.0.6+git0.58706ab4/include/types/stats.h --- old/haproxy-2.0.5+git0.d905f49a/include/types/stats.h 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/include/types/stats.h 2019-09-13 13:46:44.000000000 +0200 @@ -415,6 +415,8 @@ ST_F_REUSE, ST_F_CACHE_LOOKUPS, ST_F_CACHE_HITS, + ST_F_SRV_ICUR, + ST_F_SRV_ILIM, /* must always be the last one */ ST_F_TOTAL_FIELDS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/acl.c new/haproxy-2.0.6+git0.58706ab4/src/acl.c --- old/haproxy-2.0.5+git0.d905f49a/src/acl.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/acl.c 2019-09-13 13:46:44.000000000 +0200 @@ -342,6 +342,8 @@ goto out_free_smp; } } + free(ckw); + ckw = NULL; } else { /* This is not an ACL keyword, so we hope this is a sample fetch @@ -360,7 +362,7 @@ expr = calloc(1, sizeof(*expr)); if (!expr) { memprintf(err, "out of memory when parsing ACL expression"); - goto out_return; + goto out_free_smp; } pattern_init_head(&expr->pat); @@ -678,8 +680,8 @@ out_free_expr: prune_acl_expr(expr); free(expr); - free(ckw); out_free_smp: + free(ckw); free(smp); out_return: return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/backend.c new/haproxy-2.0.6+git0.58706ab4/src/backend.c --- old/haproxy-2.0.5+git0.d905f49a/src/backend.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/backend.c 2019-09-13 13:46:44.000000000 +0200 @@ -1337,7 +1337,7 @@ } } if (((!reuse || (srv_conn && !(srv_conn->flags & CO_FL_CONNECTED))) - && ha_used_fds > global.tune.pool_high_count) && srv->idle_orphan_conns) { + && ha_used_fds > global.tune.pool_high_count) && srv && srv->idle_orphan_conns) { struct connection *tokill_conn; /* We can't reuse a connection, and e have more FDs than deemd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/cache.c new/haproxy-2.0.6+git0.58706ab4/src/cache.c --- old/haproxy-2.0.5+git0.d905f49a/src/cache.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/cache.c 2019-09-13 13:46:44.000000000 +0200 @@ -721,6 +721,7 @@ if (IS_HTX_STRM(s)) { struct htx *htx = htxbuf(&s->res.buf); struct http_hdr_ctx ctx; + size_t hdrs_len = 0; int32_t pos; /* Do not cache too big objects. */ @@ -755,11 +756,17 @@ enum htx_blk_type type = htx_get_blk_type(blk); uint32_t sz = htx_get_blksz(blk); + hdrs_len += sizeof(*blk) + sz; chunk_memcat(&trash, (char *)&blk->info, sizeof(blk->info)); chunk_memcat(&trash, htx_get_blk_ptr(htx, blk), sz); if (type == HTX_BLK_EOH) break; } + + /* Do not cache objects if the headers are too big. */ + if (hdrs_len > htx->size - global.tune.maxrewrite) + goto out; + } else { struct hdr_ctx ctx; @@ -789,6 +796,10 @@ } http_remove_header2(msg, &txn->hdr_idx, &ctx); } + + /* Do not cache objects if the headers are too big. */ + if (msg->sov > c_size(txn->rsp.chn) - global.tune.maxrewrite) + goto out; } shctx_lock(shctx); @@ -899,6 +910,7 @@ struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0]; struct shared_context *shctx = shctx_ptr(cconf->c.cache); struct htx_blk *blk; + char *ptr; unsigned int max, total; uint32_t blksz; @@ -917,12 +929,14 @@ blk->info = info; total = 4; + ptr = htx_get_blk_ptr(htx, blk); while (blksz) { max = MIN(blksz, shctx->block_size - offset); - memcpy(htx_get_blk_ptr(htx, blk), (const char *)shblk->data + offset, max); + memcpy(ptr, (const char *)shblk->data + offset, max); offset += max; blksz -= max; total += max; + ptr += max; if (blksz || offset == shctx->block_size) { shblk = LIST_NEXT(&shblk->list, typeof(shblk), list); offset = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/cfgparse.c new/haproxy-2.0.6+git0.58706ab4/src/cfgparse.c --- old/haproxy-2.0.5+git0.d905f49a/src/cfgparse.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/cfgparse.c 2019-09-13 13:46:44.000000000 +0200 @@ -2747,6 +2747,10 @@ mrule->table.t = target; stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL); stktable_alloc_data_type(target, STKTABLE_DT_SERVER_NAME, NULL); + if (!in_proxies_list(target->proxies_list, curproxy)) { + curproxy->next_stkt_ref = target->proxies_list; + target->proxies_list = curproxy; + } } } @@ -2781,6 +2785,10 @@ mrule->table.t = target; stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL); stktable_alloc_data_type(target, STKTABLE_DT_SERVER_NAME, NULL); + if (!in_proxies_list(target->proxies_list, curproxy)) { + curproxy->next_stkt_ref = target->proxies_list; + target->proxies_list = curproxy; + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/checks.c new/haproxy-2.0.6+git0.58706ab4/src/checks.c --- old/haproxy-2.0.5+git0.d905f49a/src/checks.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/checks.c 2019-09-13 13:46:44.000000000 +0200 @@ -791,6 +791,9 @@ } } + if (!b_data(&check->bo)) + conn_xprt_stop_send(conn); + /* full request sent, we allow up to <timeout.check> if nonzero for a response */ if (s->proxy->timeout.check) { t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check); @@ -1375,7 +1378,13 @@ } default: - /* for other checks (eg: pure TCP), delegate to the main task */ + /* good connection is enough for pure TCP check */ + if ((conn->flags & CO_FL_CONNECTED) && !check->type) { + if (check->use_ssl) + set_server_check_status(check, HCHK_STATUS_L6OK, NULL); + else + set_server_check_status(check, HCHK_STATUS_L4OK, NULL); + } break; } /* switch */ @@ -1438,8 +1447,12 @@ ret = tcpcheck_main(check); cs = check->cs; conn = cs->conn; - } else if (!(check->wait_list.events & SUB_RETRY_SEND)) - __event_srv_chk_w(cs); + } else { + if (!(check->wait_list.events & SUB_RETRY_SEND)) + __event_srv_chk_w(cs); + if (!(check->wait_list.events & SUB_RETRY_RECV)) + __event_srv_chk_r(cs); + } if (unlikely(conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) { /* We may get error reports bypassing the I/O handlers, typically @@ -2243,8 +2256,16 @@ t->expire = tick_first(t->expire, t_con); } - if (check->type) - __event_srv_chk_r(cs); + if (check->type) { + /* send the request if we have one. We avoid receiving + * if not connected, unless we didn't subscribe for + * sending since otherwise we won't be woken up. + */ + __event_srv_chk_w(cs); + if (!(conn->flags & CO_FL_WAIT_L4_CONN) || + !(check->wait_list.events & SUB_RETRY_SEND)) + __event_srv_chk_r(cs); + } task_set_affinity(t, tid_bit); goto reschedule; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/debug.c new/haproxy-2.0.6+git0.58706ab4/src/debug.c --- old/haproxy-2.0.5+git0.d905f49a/src/debug.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/debug.c 2019-09-13 13:46:44.000000000 +0200 @@ -26,6 +26,7 @@ #include <proto/cli.h> #include <proto/fd.h> +#include <proto/hlua.h> #include <proto/stream_interface.h> #include <proto/task.h> @@ -90,6 +91,8 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx) { const struct stream *s = NULL; + const struct appctx __maybe_unused *appctx = NULL; + struct hlua __maybe_unused *hlua = NULL; if (!task) { chunk_appendf(buf, "0\n"); @@ -110,15 +113,23 @@ task->call_date ? " ns ago" : ""); chunk_appendf(buf, "%s" - " fct=%p (%s) ctx=%p\n", + " fct=%p (%s) ctx=%p", pfx, task->process, task->process == process_stream ? "process_stream" : task->process == task_run_applet ? "task_run_applet" : task->process == si_cs_io_cb ? "si_cs_io_cb" : +#ifdef USE_LUA + task->process == hlua_process_task ? "hlua_process_task" : +#endif "?", task->context); + if (task->process == task_run_applet && (appctx = task->context)) + chunk_appendf(buf, "(%s)\n", appctx->applet->name); + else + chunk_appendf(buf, "\n"); + if (task->process == process_stream && task->context) s = (struct stream *)task->context; else if (task->process == task_run_applet && task->context) @@ -128,6 +139,30 @@ if (s) stream_dump(buf, s, pfx, '\n'); + +#ifdef USE_LUA + hlua = NULL; + if (s && (hlua = s->hlua)) { + chunk_appendf(buf, "%sCurrent executing Lua from a stream analyser -- ", pfx); + } + else if (task->process == hlua_process_task && (hlua = task->context)) { + chunk_appendf(buf, "%sCurrent executing a Lua task -- ", pfx); + } + else if (task->process == task_run_applet && (appctx = task->context) && + (appctx->applet->fct == hlua_applet_tcp_fct && (hlua = appctx->ctx.hlua_apptcp.hlua))) { + chunk_appendf(buf, "%sCurrent executing a Lua TCP service -- ", pfx); + } + else if (task->process == task_run_applet && (appctx = task->context) && + (appctx->applet->fct == hlua_applet_http_fct && (hlua = appctx->ctx.hlua_apphttp.hlua))) { + chunk_appendf(buf, "%sCurrent executing a Lua HTTP service -- ", pfx); + } + + if (hlua) { + luaL_traceback(hlua->T, hlua->T, NULL, 0); + if (!append_prefixed_str(buf, lua_tostring(hlua->T, -1), pfx, '\n', 1)) + b_putchr(buf, '\n'); + } +#endif } /* This function dumps all profiling settings. It returns 0 if the output diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/filters.c new/haproxy-2.0.6+git0.58706ab4/src/filters.c --- old/haproxy-2.0.5+git0.d905f49a/src/filters.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/filters.c 2019-09-13 13:46:44.000000000 +0200 @@ -1190,6 +1190,7 @@ unsigned int an_bit, int ret) { int finst; + int status = 0; if (ret < 0) goto return_bad_req; @@ -1211,21 +1212,23 @@ if (!(chn->flags & CF_ISRESP)) { s->req.analysers &= AN_REQ_FLT_END; finst = SF_FINST_R; + status = 400; /* FIXME: incr counters */ } else { s->res.analysers &= AN_RES_FLT_END; finst = SF_FINST_H; + status = 502; /* FIXME: incr counters */ } if (s->txn) { /* Do not do that when we are waiting for the next request */ - if (s->txn->status) + if (s->txn->status > 0) http_reply_and_close(s, s->txn->status, NULL); else { - s->txn->status = 400; - http_reply_and_close(s, 400, http_error_message(s)); + s->txn->status = status; + http_reply_and_close(s, status, http_error_message(s)); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/h1.c new/haproxy-2.0.6+git0.58706ab4/src/h1.c --- old/haproxy-2.0.5+git0.d905f49a/src/h1.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/h1.c 2019-09-13 13:46:44.000000000 +0200 @@ -935,7 +935,8 @@ return -2; restart: - h1m->next = 0; + h1m->flags &= ~(H1_MF_VER_11|H1_MF_CLEN|H1_MF_XFER_ENC|H1_MF_CHNK|H1_MF_CONN_KAL|H1_MF_CONN_CLO|H1_MF_CONN_UPG); + h1m->curr_len = h1m->body_len = h1m->next = 0; if (h1m->flags & H1_MF_RESP) h1m->state = H1_MSG_RPBEFORE; else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/haproxy.c new/haproxy-2.0.6+git0.58706ab4/src/haproxy.c --- old/haproxy-2.0.5+git0.d905f49a/src/haproxy.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/haproxy.c 2019-09-13 13:46:44.000000000 +0200 @@ -695,6 +695,7 @@ } ha_warning("Reexecuting Master process\n"); + signal(SIGPROF, SIG_IGN); execvp(next_argv[0], next_argv); ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/hlua.c new/haproxy-2.0.6+git0.58706ab4/src/hlua.c --- old/haproxy-2.0.5+git0.d905f49a/src/hlua.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/hlua.c 2019-09-13 13:46:44.000000000 +0200 @@ -6237,7 +6237,7 @@ * Task wrapper are longjmp safe because the only one Lua code * executed is the safe hlua_ctx_resume(); */ -static struct task *hlua_process_task(struct task *task, void *context, unsigned short state) +struct task *hlua_process_task(struct task *task, void *context, unsigned short state) { struct hlua *hlua = context; enum hlua_exec status; @@ -7045,7 +7045,7 @@ return 1; } -static void hlua_applet_tcp_fct(struct appctx *ctx) +void hlua_applet_tcp_fct(struct appctx *ctx) { struct stream_interface *si = ctx->owner; struct stream *strm = si_strm(si); @@ -7417,7 +7417,7 @@ goto done; } -static void hlua_applet_http_fct(struct appctx *ctx) +void hlua_applet_http_fct(struct appctx *ctx) { struct stream_interface *si = ctx->owner; struct stream *strm = si_strm(si); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/http_fetch.c new/haproxy-2.0.6+git0.58706ab4/src/http_fetch.c --- old/haproxy-2.0.5+git0.d905f49a/src/http_fetch.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/http_fetch.c 2019-09-13 13:46:44.000000000 +0200 @@ -2735,10 +2735,6 @@ /* now retrieve the path */ sl = http_get_stline(htx); path = http_get_path(htx_sl_req_uri(sl)); - while (path.len > 0 && *(path.ptr) != '?') { - path.ptr++; - path.len--; - } if (path.len && *(path.ptr) == '/') { while (path.len--) hash = *(path.ptr++) + (hash << 6) + (hash << 16) - hash; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/lb_fwlc.c new/haproxy-2.0.6+git0.58706ab4/src/lb_fwlc.c --- old/haproxy-2.0.5+git0.d905f49a/src/lb_fwlc.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/lb_fwlc.c 2019-09-13 13:46:44.000000000 +0200 @@ -48,13 +48,15 @@ * for using #conns+1 is to sort by weights in case the server is picked * and not before it is picked. This provides a better load accuracy for * low connection counts when weights differ and makes sure the round-robin - * applies between servers of highest weight first. + * applies between servers of highest weight first. However servers with no + * connection are always picked first so that under low loads, it's not + * always the single server with the highest weight that gets picked. * * The server's lock and the lbprm's lock must be held. */ static inline void fwlc_queue_srv(struct server *s) { - s->lb_node.key = (s->served + 1) * SRV_EWGHT_MAX / s->next_eweight; + s->lb_node.key = s->served ? (s->served + 1) * SRV_EWGHT_MAX / s->next_eweight : 0; eb32_insert(s->lb_tree, &s->lb_node); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/listener.c new/haproxy-2.0.6+git0.58706ab4/src/listener.c --- old/haproxy-2.0.5+git0.d905f49a/src/listener.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/listener.c 2019-09-13 13:46:44.000000000 +0200 @@ -595,17 +595,17 @@ */ void delete_listener(struct listener *listener) { + HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock); if (listener->state == LI_ASSIGNED) { listener->state = LI_INIT; - HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); LIST_DEL(&listener->proto_list); listener->proto->nb_listeners--; - HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); _HA_ATOMIC_SUB(&jobs, 1); _HA_ATOMIC_SUB(&listeners, 1); } HA_SPIN_UNLOCK(LISTENER_LOCK, &listener->lock); + HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); } /* Returns a suitable value for a listener's backlog. It uses the listener's, @@ -1065,7 +1065,7 @@ if (!LIST_ISEMPTY(&global_listener_queue)) dequeue_all_listeners(&global_listener_queue); - if (!LIST_ISEMPTY(&p->listener_queue) && + if (p && !LIST_ISEMPTY(&p->listener_queue) && (!p->fe_sps_lim || freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0) > 0)) dequeue_all_listeners(&p->listener_queue); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/mux_h1.c new/haproxy-2.0.6+git0.58706ab4/src/mux_h1.c --- old/haproxy-2.0.5+git0.d905f49a/src/mux_h1.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/mux_h1.c 2019-09-13 13:46:44.000000000 +0200 @@ -67,7 +67,8 @@ #define H1S_F_BUF_FLUSH 0x00000100 /* Flush input buffer and don't read more data */ #define H1S_F_SPLICED_DATA 0x00000200 /* Set when the kernel splicing is in used */ #define H1S_F_HAVE_I_TLR 0x00000800 /* Set during input process to know the trailers were processed */ -/* 0x00001000 .. 0x00002000 unused */ +#define H1S_F_APPEND_EOM 0x00001000 /* Send EOM to the HTX buffer */ +/* 0x00002000 .. 0x00002000 unused */ #define H1S_F_HAVE_O_CONN 0x00004000 /* Set during output process to know connection mode was processed */ /* H1 connection descriptor */ @@ -930,7 +931,7 @@ size_t sz; /* size of the HTX start-line */ - sz = sizeof(struct htx_sl) + h1sl->rq.m.len + h1sl->rq.u.len + h1sl->rq.v.len; + sz = sizeof(struct htx_blk) + sizeof(struct htx_sl) + h1sl->rq.m.len + h1sl->rq.u.len + h1sl->rq.v.len; sz += h1_eval_htx_hdrs_size(hdrs); return sz; } @@ -941,7 +942,7 @@ size_t sz; /* size of the HTX start-line */ - sz = sizeof(struct htx_sl) + h1sl->st.v.len + h1sl->st.c.len + h1sl->st.r.len; + sz = sizeof(struct htx_blk) + sizeof(struct htx_sl) + h1sl->st.v.len + h1sl->st.c.len + h1sl->st.r.len; sz += h1_eval_htx_hdrs_size(hdrs); return sz; } @@ -954,9 +955,12 @@ */ static size_t h1_process_eom(struct h1s *h1s, struct h1m *h1m, struct htx *htx, size_t max) { - if (max < sizeof(struct htx_blk) + 1 || !htx_add_endof(htx, HTX_BLK_EOM)) + if (max < sizeof(struct htx_blk) + 1 || !htx_add_endof(htx, HTX_BLK_EOM)) { + h1s->flags |= H1S_F_APPEND_EOM; return 0; + } + h1s->flags &= ~H1S_F_APPEND_EOM; h1m->state = H1_MSG_DONE; h1s->cs->flags |= CS_FL_EOI; return (sizeof(struct htx_blk) + 1); @@ -995,10 +999,11 @@ ret = h1_headers_to_hdr_list(b_peek(buf, *ofs), b_tail(buf), hdrs, sizeof(hdrs)/sizeof(hdrs[0]), h1m, &h1sl); if (ret <= 0) { - /* Incomplete or invalid message. If the buffer is full, it's an - * error because headers are too large to be handled by the - * parser. */ - if (ret < 0 || (!ret && !buf_room_for_htx_data(buf))) + /* Incomplete or invalid message. If the input buffer only + * contains headers and is full, which is detected by it being + * full and the offset to be zero, it's an error because + * headers are too large to be handled by the parser. */ + if (ret < 0 || (!ret && !*ofs && !buf_room_for_htx_data(buf))) goto error; goto end; } @@ -1339,10 +1344,11 @@ ret = h1_headers_to_hdr_list(b_peek(buf, *ofs), b_tail(buf), hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &tlr_h1m, NULL); if (ret <= 0) { - /* Incomplete or invalid trailers. If the buffer is full, it's - * an error because traliers are too large to be handled by the - * parser. */ - if (ret < 0 || (!ret && !buf_room_for_htx_data(buf))) + /* Incomplete or invalid trailers. If the input buffer only + * contains trailers and is full, which is detected by it being + * full and the offset to be zero, it's an error because + * trailers are too large to be handled by the parser. */ + if (ret < 0 || (!ret && !*ofs && !buf_room_for_htx_data(buf))) goto error; goto end; } @@ -1428,7 +1434,7 @@ if (!ret) break; } - if (!h1_process_eom(h1s, h1m, htx, count)) + else if (!h1_process_eom(h1s, h1m, htx, count)) break; } else if (h1m->state == H1_MSG_DONE) { @@ -1448,7 +1454,7 @@ } count -= htx_used_space(htx) - used; - } while (!(h1s->flags & errflag) && count); + } while (!(h1s->flags & errflag)); if (h1s->flags & errflag) goto parsing_err; @@ -1470,7 +1476,8 @@ else if (h1s_data_pending(h1s) && !htx_is_empty(htx)) h1s->cs->flags |= CS_FL_RCV_MORE | CS_FL_WANT_ROOM; - if ((h1s->flags & H1S_F_REOS) && (!h1s_data_pending(h1s) || htx_is_empty(htx))) { + if (((h1s->flags & (H1S_F_REOS|H1S_F_APPEND_EOM)) == H1S_F_REOS) && + (!h1s_data_pending(h1s) || htx_is_empty(htx))) { h1s->cs->flags |= CS_FL_EOS; if (h1m->state > H1_MSG_LAST_LF && h1m->state < H1_MSG_DONE) h1s->cs->flags |= CS_FL_ERROR; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/proto_http.c new/haproxy-2.0.6+git0.58706ab4/src/proto_http.c --- old/haproxy-2.0.5+git0.d905f49a/src/proto_http.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/proto_http.c 2019-09-13 13:46:44.000000000 +0200 @@ -598,7 +598,7 @@ */ if (c_data(req) && msg->msg_state < HTTP_MSG_ERROR) { if (txn->flags & TX_NOT_FIRST) { - if (unlikely(!channel_is_rewritable(req))) { + if (unlikely(!channel_is_rewritable(req) && co_data(req))) { if (req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) goto failed_keep_alive; /* some data has still not left the buffer, wake us once that's done */ @@ -1073,6 +1073,10 @@ } } + /* "chunked" mandatory if transfer-encoding is used */ + if (ctx.idx && !(msg->flags & HTTP_MSGF_TE_CHNK)) + goto return_bad_req; + /* Chunked requests must have their content-length removed */ ctx.idx = 0; if (msg->flags & HTTP_MSGF_TE_CHNK) { @@ -4230,7 +4234,7 @@ * data later, which is much more complicated. */ if (c_data(rep) && msg->msg_state < HTTP_MSG_ERROR) { - if (unlikely(!channel_is_rewritable(rep))) { + if (unlikely(!channel_is_rewritable(rep) && co_data(rep))) { /* some data has still not left the buffer, wake us once that's done */ if (rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) goto abort_response; @@ -4696,6 +4700,12 @@ } } + /* "chunked" mandatory if transfer-encoding is used */ + if (ctx.idx && !(msg->flags & HTTP_MSGF_TE_CHNK)) { + use_close_only = 1; + msg->flags &= ~(HTTP_MSGF_TE_CHNK | HTTP_MSGF_XFER_LEN); + } + /* Chunked responses must have their content-length removed */ ctx.idx = 0; if (use_close_only || (msg->flags & HTTP_MSGF_TE_CHNK)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/proto_htx.c new/haproxy-2.0.6+git0.58706ab4/src/proto_htx.c --- old/haproxy-2.0.5+git0.d905f49a/src/proto_htx.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/proto_htx.c 2019-09-13 13:46:44.000000000 +0200 @@ -1634,7 +1634,6 @@ * response which at least looks like HTTP. We have an indicator * of each header's length, so we can parse them quickly. */ - msg->msg_state = HTTP_MSG_BODY; BUG_ON(htx_get_first_type(htx) != HTX_BLK_RES_SL); sl = http_get_stline(htx); @@ -1710,6 +1709,7 @@ FLT_STRM_CB(s, flt_http_reset(s, msg)); htx->first = channel_htx_fwd_headers(rep, htx); msg->msg_state = HTTP_MSG_RPBEFORE; + msg->flags = 0; txn->status = 0; s->logs.t_data = -1; /* was not a response yet */ goto next_one; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/sample.c new/haproxy-2.0.6+git0.58706ab4/src/sample.c --- old/haproxy-2.0.5+git0.d905f49a/src/sample.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/sample.c 2019-09-13 13:46:44.000000000 +0200 @@ -3132,6 +3132,60 @@ return 1; } +// This function checks the "uuid" sample's arguments. +// Function won't get called when no parameter is specified (maybe a bug?) +static int smp_check_uuid(struct arg *args, char **err) +{ + if (!args[0].type) { + args[0].type = ARGT_SINT; + args[0].data.sint = 4; + } + else if (args[0].data.sint != 4) { + memprintf(err, "Unsupported UUID version: '%lld'", args[0].data.sint); + return 0; + } + + return 1; +} + +// Generate a RFC4122 UUID (default is v4 = fully random) +static int smp_fetch_uuid(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + if (args[0].data.sint == 4 || !args[0].type) { + uint32_t rnd[4] = { 0, 0, 0, 0 }; + uint64_t last = 0; + int byte = 0; + uint8_t bits = 0; + unsigned int rand_max_bits = my_flsl(RAND_MAX); + + while (byte < 4) { + while (bits < 32) { + last |= (uint64_t)random() << bits; + bits += rand_max_bits; + } + rnd[byte++] = last; + last >>= 32u; + bits -= 32; + } + + chunk_printf(&trash, "%8.8x-%4.4x-%4.4x-%4.4x-%12.12llx", + rnd[0], + rnd[1] & 0xFFFF, + ((rnd[1] >> 16u) & 0xFFF) | 0x4000, // highest 4 bits indicate the uuid version + (rnd[2] & 0x3FFF) | 0x8000, // the highest 2 bits indicate the UUID variant (10), + (long long)((rnd[2] >> 14u) | ((uint64_t) rnd[3] << 18u)) & 0xFFFFFFFFFFFFull + ); + + smp->data.type = SMP_T_STR; + smp->flags = SMP_F_VOL_TEST | SMP_F_MAY_CHANGE; + smp->data.u.str = trash; + return 1; + } + + // more implementations of other uuid formats possible here + return 0; +} + /* Note: must not be declared <const> as its list will be overwritten. * Note: fetches that may return multiple types must be declared as the lowest * common denominator, the type that can be casted into all other ones. For @@ -3150,6 +3204,7 @@ { "rand", smp_fetch_rand, ARG1(0,SINT), NULL, SMP_T_SINT, SMP_USE_INTRN }, { "stopping", smp_fetch_stopping, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN }, { "stopping", smp_fetch_stopping, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN }, + { "uuid", smp_fetch_uuid, ARG1(0, SINT), smp_check_uuid, SMP_T_STR, SMP_USE_INTRN }, { "cpu_calls", smp_fetch_cpu_calls, 0, NULL, SMP_T_SINT, SMP_USE_INTRN }, { "cpu_ns_avg", smp_fetch_cpu_ns_avg, 0, NULL, SMP_T_SINT, SMP_USE_INTRN }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/ssl_sock.c new/haproxy-2.0.6+git0.58706ab4/src/ssl_sock.c --- old/haproxy-2.0.5+git0.d905f49a/src/ssl_sock.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/ssl_sock.c 2019-09-13 13:46:44.000000000 +0200 @@ -5124,6 +5124,8 @@ ctx->conn = conn; ctx->send_wait = NULL; ctx->recv_wait = NULL; + ctx->xprt_st = 0; + ctx->xprt_ctx = NULL; /* Only work with sockets for now, this should be adapted when we'll * add QUIC support. @@ -6091,7 +6093,7 @@ /* used for ppv2 pkey alog (can be used for logging) */ int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; struct pkey_info *pkinfo; int bits = 0; int sig = TLSEXT_signature_anonymous; @@ -6099,7 +6101,7 @@ if (!ssl_sock_is_ssl(conn)) return 0; - + ctx = conn->xprt_ctx; pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index); if (pkinfo) { sig = pkinfo->sig; @@ -6150,13 +6152,14 @@ /* used for ppv2 cert signature (can be used for logging) */ const char *ssl_sock_get_cert_sig(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm; X509 *crt; if (!ssl_sock_is_ssl(conn)) return NULL; + ctx = conn->xprt_ctx; crt = SSL_get_certificate(ctx->ssl); if (!crt) return NULL; @@ -6168,10 +6171,11 @@ const char *ssl_sock_get_sni(struct connection *conn) { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return NULL; + ctx = conn->xprt_ctx; return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name); #else return NULL; @@ -6181,22 +6185,22 @@ /* used for logging/ppv2, may be changed for a sample fetch later */ const char *ssl_sock_get_cipher_name(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return NULL; - + ctx = conn->xprt_ctx; return SSL_get_cipher_name(ctx->ssl); } /* used for logging/ppv2, may be changed for a sample fetch later */ const char *ssl_sock_get_proto_version(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return NULL; - + ctx = conn->xprt_ctx; return SSL_get_version(ctx->ssl); } @@ -6402,11 +6406,11 @@ void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return; - + ctx = conn->xprt_ctx; SSL_set_alpn_protos(ctx->ssl, alpn, len); #endif } @@ -6417,12 +6421,13 @@ void ssl_sock_set_servername(struct connection *conn, const char *hostname) { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; char *prev_name; if (!ssl_sock_is_ssl(conn)) return; + ctx = conn->xprt_ctx; /* if the SNI changes, we must destroy the reusable context so that a * new connection will present a new SNI. As an optimization we could @@ -6447,7 +6452,7 @@ int ssl_sock_get_remote_common_name(struct connection *conn, struct buffer *dest) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; X509 *crt = NULL; X509_NAME *name; const char find_cn[] = "CN"; @@ -6459,6 +6464,7 @@ if (!ssl_sock_is_ssl(conn)) goto out; + ctx = conn->xprt_ctx; /* SSL_get_peer_certificate, it increase X509 * ref count */ crt = SSL_get_peer_certificate(ctx->ssl); @@ -6480,11 +6486,12 @@ /* returns 1 if client passed a certificate for this session, 0 if not */ int ssl_sock_get_cert_used_sess(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; X509 *crt = NULL; if (!ssl_sock_is_ssl(conn)) return 0; + ctx = conn->xprt_ctx; /* SSL_get_peer_certificate, it increase X509 * ref count */ crt = SSL_get_peer_certificate(ctx->ssl); @@ -6498,22 +6505,22 @@ /* returns 1 if client passed a certificate for this connection, 0 if not */ int ssl_sock_get_cert_used_conn(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return 0; - + ctx = conn->xprt_ctx; return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0; } /* returns result from SSL verify */ unsigned int ssl_sock_get_verify_result(struct connection *conn) { - struct ssl_sock_ctx *ctx = conn->xprt_ctx; + struct ssl_sock_ctx *ctx; if (!ssl_sock_is_ssl(conn)) return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION; - + ctx = conn->xprt_ctx; return (unsigned int)SSL_get_verify_result(ctx->ssl); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/standard.c new/haproxy-2.0.6+git0.58706ab4/src/standard.c --- old/haproxy-2.0.5+git0.d905f49a/src/standard.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/standard.c 2019-09-13 13:46:44.000000000 +0200 @@ -3709,6 +3709,41 @@ return ret; } +/* makes a copy of message <in> into <out>, with each line prefixed with <pfx> + * and end of lines replaced with <eol> if not 0. The first line to indent has + * to be indicated in <first> (starts at zero), so that it is possible to skip + * indenting the first line if it has to be appended after an existing message. + * Empty strings are never indented, and NULL strings are considered empty both + * for <in> and <pfx>. It returns non-zero if an EOL was appended as the last + * character, non-zero otherwise. + */ +int append_prefixed_str(struct buffer *out, const char *in, const char *pfx, char eol, int first) +{ + int bol, lf; + int pfxlen = pfx ? strlen(pfx) : 0; + + if (!in) + return 0; + + bol = 1; + lf = 0; + while (*in) { + if (bol && pfxlen) { + if (first > 0) + first--; + else + b_putblk(out, pfx, pfxlen); + bol = 0; + } + + lf = (*in == '\n'); + bol |= lf; + b_putchr(out, (lf && eol) ? eol : *in); + in++; + } + return lf; +} + /* removes environment variable <name> from the environment as found in * environ. This is only provided as an alternative for systems without * unsetenv() (old Solaris and AIX versions). THIS IS NOT THREAD SAFE. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.5+git0.d905f49a/src/stats.c new/haproxy-2.0.6+git0.58706ab4/src/stats.c --- old/haproxy-2.0.5+git0.d905f49a/src/stats.c 2019-08-16 16:52:47.000000000 +0200 +++ new/haproxy-2.0.6+git0.58706ab4/src/stats.c 2019-09-13 13:46:44.000000000 +0200 @@ -245,6 +245,8 @@ [ST_F_REUSE] = "reuse", [ST_F_CACHE_LOOKUPS] = "cache_lookups", [ST_F_CACHE_HITS] = "cache_hits", + [ST_F_SRV_ICUR] = "srv_icur", + [ST_F_SRV_ILIM] = "src_ilim" }; /* one line of info */ @@ -983,11 +985,23 @@ chunk_appendf(out, /* sessions: current, max, limit, total */ - "<td>%s</td><td>%s</td><td>%s</td>" + "<td><u>%s<div class=tips>" + "<table class=det>" + "<tr><th>Current active connections:</th><td>%s</td></tr>" + "<tr><th>Current idle connections:</th><td>%s</td></tr>" + "<tr><th>Active connections limit:</th><td>%s</td></tr>" + "<tr><th>Idle connections limit:</th><td>%s</td></tr>" + "</table></div></u>" + "</td><td>%s</td><td>%s</td>" "<td><u>%s<div class=tips><table class=det>" "<tr><th>Cum. sessions:</th><td>%s</td></tr>" "", - U2H(stats[ST_F_SCUR].u.u32), U2H(stats[ST_F_SMAX].u.u32), LIM2A(stats[ST_F_SLIM].u.u32, "-"), + U2H(stats[ST_F_SCUR].u.u32), + U2H(stats[ST_F_SCUR].u.u32), + U2H(stats[ST_F_SRV_ICUR].u.u32), + LIM2A(stats[ST_F_SLIM].u.u32, "-"), + stats[ST_F_SRV_ILIM].type ? U2H(stats[ST_F_SRV_ILIM].u.u32) : "-", + U2H(stats[ST_F_SMAX].u.u32), LIM2A(stats[ST_F_SLIM].u.u32, "-"), U2H(stats[ST_F_STOT].u.u64), U2H(stats[ST_F_STOT].u.u64)); @@ -1650,6 +1664,10 @@ if (sv->maxconn) stats[ST_F_SLIM] = mkf_u32(FO_CONFIG|FN_LIMIT, sv->maxconn); + stats[ST_F_SRV_ICUR] = mkf_u32(0, sv->curr_idle_conns); + if (sv->max_idle_conns != -1) + stats[ST_F_SRV_ILIM] = mkf_u32(FO_CONFIG|FN_LIMIT, sv->max_idle_conns); + stats[ST_F_STOT] = mkf_u64(FN_COUNTER, sv->counters.cum_sess); stats[ST_F_BIN] = mkf_u64(FN_COUNTER, sv->counters.bytes_in); stats[ST_F_BOUT] = mkf_u64(FN_COUNTER, sv->counters.bytes_out);
