[-]
[+]
|
Changed |
_service
|
@@ -3,5 +3,5 @@
- <param name="protocol">http</param><param name="host">haproxy.1wt.eu</param><param name="path">/download/1.5/src/haproxy-1.5.10.tar.gz</param></service>
+ <param name="protocol">http</param><param name="host">haproxy.1wt.eu</param><param name="path">/download/1.5/src/haproxy-1.5.11.tar.gz</param></service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/CHANGELOG
^
|
@@ -1,6 +1,27 @@
ChangeLog :
===========
+2015/02/01 : 1.5.11
+ - BUG/MEDIUM: backend: correctly detect the domain when use_domain_only is used
+ - MINOR: ssl: load certificates in alphabetical order
+ - BUG/MINOR: checks: prevent http keep-alive with http-check expect
+ - BUG/MEDIUM: Do not set agent health to zero if server is disabled in config
+ - MEDIUM/BUG: Only explicitly report "DOWN (agent)" if the agent health is zero
+ - BUG/MINOR: stats:Fix incorrect printf type.
+ - DOC: add missing entry for log-format and clarify the text
+ - BUG/MEDIUM: http: fix header removal when previous header ends with pure LF
+ - BUG/MEDIUM: channel: fix possible integer overflow on reserved size computation
+ - BUG/MINOR: channel: compare to_forward with buf->i, not buf->size
+ - MINOR: channel: add channel_in_transit()
+ - MEDIUM: channel: make buffer_reserved() use channel_in_transit()
+ - MEDIUM: channel: make bi_avail() use channel_in_transit()
+ - BUG/MEDIUM: channel: don't schedule data in transit for leaving until connected
+ - BUG/MAJOR: log: don't try to emit a log if no logger is set
+ - BUG/MINOR: args: add missing entry for ARGT_MAP in arg_type_names
+ - BUG/MEDIUM: http: make http-request set-header compute the string before removal
+ - BUG/MINOR: http: fix incorrect header value offset in replace-hdr/replace-value
+ - BUG/MINOR: http: abort request processing on filter failure
+
2014/12/31 : 1.5.10
- DOC: fix a few typos
- BUG/MINOR: http: fix typo: "401 Unauthorized" => "407 Unauthorized"
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/README
^
|
@@ -1,9 +1,9 @@
----------------------
HAProxy how-to
----------------------
- version 1.5.10
+ version 1.5.11
willy tarreau
- 2014/12/31
+ 2015/02/01
1) How to build it
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/VERDATE
^
|
@@ -1,2 +1,2 @@
$Format:%ci$
-2014/12/31
+2015/01/31
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/VERSION
^
|
@@ -1 +1 @@
-1.5.10
+1.5.11
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/doc/configuration.txt
^
|
@@ -2,9 +2,9 @@
HAProxy
Configuration Manual
----------------------
- version 1.5.10
+ version 1.5.11
willy tarreau
- 2014/12/31
+ 2015/02/01
This document covers the configuration language as implemented in the version
@@ -1323,6 +1323,7 @@
id - X X X
ignore-persist - X X X
log (*) X X X X
+log-format X X X -
max-keep-alive-queue X - X X
maxconn X X X -
mode X X X X
@@ -2855,6 +2856,10 @@
waste some CPU cycles, especially when regular expressions are used, and that
it is always better to focus the checks on smaller resources.
+ Also "http-check expect" doesn't support HTTP keep-alive. Keep in mind that it
+ will automatically append a "Connection: close" header, meaning that this
+ header should not be present in the request provided by "option httpchk".
+
Last, if "http-check expect" is combined with "http-check disable-on-404",
then this last one has precedence when the server responds with 404.
@@ -2983,7 +2988,8 @@
- "set-header" does the same as "add-header" except that the header name
is first removed if it existed. This is useful when passing security
information to the server, where the header must not be manipulated by
- external users.
+ external users. Note that the new value is computed before the removal so
+ it is possible to concatenate a value to an existing header.
- "del-header" removes all HTTP header fields whose name is specified in
<name>.
@@ -3475,9 +3481,15 @@
log-format <string>
- Allows you to custom a log line.
+ Specifies the log format string to use for traffic logs
+ May be used in sections: defaults | frontend | listen | backend
+ yes | yes | yes | no
- See also : Custom Log Format (8.2.4)
+ This directive specifies the log format string that will be used for all logs
+ resulting from traffic passing through the frontend using this line. If the
+ directive is used in a defaults section, all subsequent frontends will use
+ the same log format. Please see section 8.2.4 which covers the log format
+ string in depth.
max-keep-alive-queue <value>
@@ -8315,20 +8327,21 @@
are loaded.
If a directory name is used instead of a PEM file, then all files found in
- that directory will be loaded unless their name ends with '.issuer' or
- '.ocsp' (reserved extensions). This directive may be specified multiple times
- in order to load certificates from multiple files or directories. The
- certificates will be presented to clients who provide a valid TLS Server Name
- Indication field matching one of their CN or alt subjects. Wildcards are
- supported, where a wildcard character '*' is used instead of the first
- hostname component (eg: *.example.org matches www.example.org but not
+ that directory will be loaded in alphabetic order unless their name ends with
+ '.issuer' or '.ocsp' (reserved extensions). This directive may be specified
+ multiple times in order to load certificates from multiple files or
+ directories. The certificates will be presented to clients who provide a valid
+ TLS Server Name Indication field matching one of their CN or alt subjects.
+ Wildcards are supported, where a wildcard character '*' is used instead of the
+ first hostname component (eg: *.example.org matches www.example.org but not
www.sub.example.org).
If no SNI is provided by the client or if the SSL library does not support
TLS extensions, or if the client provides an SNI hostname which does not
match any certificate, then the first loaded certificate will be presented.
This means that when loading certificates from a directory, it is highly
- recommended to load the default one first as a file.
+ recommended to load the default one first as a file or to ensure that it will
+ always be the first one in the directory.
Note that the same cert may be loaded multiple times without side effects.
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/examples/haproxy.spec
^
|
@@ -1,6 +1,6 @@
Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments
Name: haproxy
-Version: 1.5.10
+Version: 1.5.11
Release: 1
License: GPL
Group: System Environment/Daemons
@@ -76,6 +76,9 @@
%attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name}
%changelog
+* Sun Feb 1 2015 Willy Tarreau <w@1wt.eu>
+- updated to 1.5.11
+
* Wed Dec 31 2014 Willy Tarreau <w@1wt.eu>
- updated to 1.5.10
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/include/proto/channel.h
^
|
@@ -118,6 +118,41 @@
return rem >= 0;
}
+/* Tells whether data are likely to leave the buffer. This is used to know when
+ * we can safely ignore the reserve since we know we cannot retry a connection.
+ * It returns zero if data are blocked, non-zero otherwise.
+ */
+static inline int channel_may_send(const struct channel *chn)
+{
+ return chn->cons->state == SI_ST_EST;
+}
+
+/* Returns the amount of bytes from the channel that are already scheduled for
+ * leaving (buf->o) or that are still part of the input and expected to be sent
+ * soon as covered by to_forward. This is useful to know by how much we can
+ * shrink the rewrite reserve during forwards. Buffer data are not considered
+ * in transit until the channel is connected, so that the reserve remains
+ * protected.
+ */
+static inline int channel_in_transit(const struct channel *chn)
+{
+ int ret;
+
+ if (!channel_may_send(chn))
+ return 0;
+
+ /* below, this is min(i, to_forward) optimized for the fast case */
+ if (chn->to_forward >= chn->buf->i ||
+ (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->i)) &&
+ chn->to_forward == CHN_INFINITE_FORWARD))
+ ret = chn->buf->i;
+ else
+ ret = chn->to_forward;
+
+ ret += chn->buf->o;
+ return ret;
+}
+
/* Returns non-zero if the buffer input is considered full. This is used to
* decide when to stop reading into a buffer when we want to ensure that we
* leave the reserve untouched after all pending outgoing data are forwarded.
@@ -136,10 +171,13 @@
if (!rem)
return 1; /* buffer already full */
- if (chn->to_forward >= chn->buf->size ||
- (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->size)) && // just there to ensure gcc
- chn->to_forward == CHN_INFINITE_FORWARD)) // avoids the useless second
- return 0; // test whenever possible
+ /* now we know there's some room left, verify if we're touching
+ * the reserve with some permanent input data.
+ */
+ if (chn->to_forward >= chn->buf->i ||
+ (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->i)) && // just there to ensure gcc
+ chn->to_forward == CHN_INFINITE_FORWARD)) // avoids the useless second
+ return 0; // test whenever possible
rem -= global.tune.maxrewrite;
rem += chn->buf->o;
@@ -258,17 +296,17 @@
* buffer, which ensures that once all pending data are forwarded, the
* buffer still has global.tune.maxrewrite bytes free. The result is
* between 0 and global.tune.maxrewrite, which is itself smaller than
- * any chn->size.
+ * any chn->size. Special care is taken to avoid any possible integer
+ * overflow in the operations.
*/
static inline int buffer_reserved(const struct channel *chn)
{
- int ret = global.tune.maxrewrite - chn->to_forward - chn->buf->o;
+ int reserved;
- if (chn->to_forward == CHN_INFINITE_FORWARD)
- return 0;
- if (ret <= 0)
- return 0;
- return ret;
+ reserved = global.tune.maxrewrite - channel_in_transit(chn);
+ if (reserved < 0)
+ reserved = 0;
+ return reserved;
}
/* Return the max number of bytes the buffer can contain so that once all the
@@ -287,28 +325,12 @@
*/
static inline int bi_avail(const struct channel *chn)
{
- int rem = chn->buf->size;
- int rem2;
+ int ret;
- rem -= chn->buf->o;
- rem -= chn->buf->i;
- if (!rem)
- return rem; /* buffer already full */
-
- if (chn->to_forward >= chn->buf->size ||
- (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->size)) && // just there to ensure gcc
- chn->to_forward == CHN_INFINITE_FORWARD)) // avoids the useless second
- return rem; // test whenever possible
-
- rem2 = rem - global.tune.maxrewrite;
- rem2 += chn->buf->o;
- rem2 += chn->to_forward;
-
- if (rem > rem2)
- rem = rem2;
- if (rem > 0)
- return rem;
- return 0;
+ ret = buffer_max_len(chn) - chn->buf->i - chn->buf->o;
+ if (ret < 0)
+ ret = 0;
+ return ret;
}
/* Cut the "tail" of the channel's buffer, which means strip it to the length
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/arg.c
^
|
@@ -33,6 +33,7 @@
[ARGT_TAB] = "table",
[ARGT_SRV] = "server",
[ARGT_USR] = "user list",
+ [ARGT_MAP] = "map",
/* Unassigned types must never happen. Better crash during parsing if they do. */
};
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/backend.c
^
|
@@ -408,29 +408,33 @@
hash = gen_hash(px, p, len);
} else {
int dohash = 0;
- p += len - 1;
- start = end = p;
+ p += len;
/* special computation, use only main domain name, not tld/host
* going back from the end of string, start hashing at first
* dot stop at next.
* This is designed to work with the 'Host' header, and requires
* a special option to activate this.
*/
+ end = p;
while (len) {
- if (*p == '.') {
- if (!dohash) {
- dohash = 1;
- start = end = p - 1;
- }
- else
+ if (dohash) {
+ /* Rewind the pointer until the previous char
+ * is a dot, this will allow to set the start
+ * position of the domain. */
+ if (*(p - 1) == '.')
break;
- } else {
- if (dohash)
- start--;
}
- len--;
+ else if (*p == '.') {
+ /* The pointer is rewinded to the dot before the
+ * tld, we memorize the end of the domain and
+ * can enter the domain processing. */
+ end = p;
+ dohash = 1;
+ }
p--;
+ len--;
}
+ start = p;
hash = gen_hash(px, start, (end - start));
}
if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/cfgparse.c
^
|
@@ -6851,7 +6851,6 @@
newsrv->admin |= SRV_ADMF_IMAINT;
newsrv->state = SRV_ST_STOPPED;
newsrv->check.health = 0;
- newsrv->agent.health = 0;
}
newsrv->track = srv;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/checks.c
^
|
@@ -1407,6 +1407,9 @@
else if ((check->type) == PR_O2_HTTP_CHK) {
if (s->proxy->options2 & PR_O2_CHK_SNDST)
bo_putblk(check->bo, trash.str, httpchk_build_status_header(s, trash.str, trash.size));
+ /* prevent HTTP keep-alive when "http-check expect" is used */
+ if (s->proxy->options2 & PR_O2_EXP_TYPE)
+ bo_putstr(check->bo, "Connection: close\r\n");
bo_putstr(check->bo, "\r\n");
*check->bo->p = '\0'; /* to make gdb output easier to read */
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/dumpstats.c
^
|
@@ -2492,7 +2492,7 @@
"Hard_maxconn: %d\n"
"CurrConns: %d\n"
"CumConns: %d\n"
- "CumReq: %d\n"
+ "CumReq: %u\n"
#ifdef USE_OPENSSL
"MaxSslConns: %d\n"
"CurrSslConns: %d\n"
@@ -3106,7 +3106,7 @@
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - sv->last_change, 1));
chunk_appendf(&trash, "MAINT");
}
- else if ((ref->agent.state & CHK_ST_ENABLED) && (ref->state == SRV_ST_STOPPED)) {
+ else if ((ref->agent.state & CHK_ST_ENABLED) && !(sv->agent.health) && (ref->state == SRV_ST_STOPPED)) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
/* DOWN (agent) */
chunk_appendf(&trash, srv_hlt_st[1], "GCC: your -Werror=format-security is bogus, annoying, and hides real bugs, I don't thank you, really!");
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/haproxy.c
^
|
@@ -216,7 +216,7 @@
void display_version()
{
printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n");
- printf("Copyright 2000-2014 Willy Tarreau <w@1wt.eu>\n\n");
+ printf("Copyright 2000-2015 Willy Tarreau <w@1wt.eu>\n\n");
}
void display_build_opts()
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/log.c
^
|
@@ -765,7 +765,7 @@
char *dataptr;
int data_len;
- if (level < 0 || format == NULL)
+ if (level < 0 || format == NULL || logline == NULL)
return;
dataptr = update_log_hdr(); /* update log header and skip it */
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/proto_http.c
^
|
@@ -731,7 +731,7 @@
if (idx->tail == ctx->idx)
idx->tail = ctx->prev;
ctx->idx = ctx->prev; /* walk back to the end of previous header */
- ctx->line -= idx->v[ctx->idx].len + idx->v[cur_idx].cr + 1;
+ ctx->line -= idx->v[ctx->idx].len + idx->v[ctx->idx].cr + 1;
ctx->val = idx->v[ctx->idx].len; /* point to end of previous header */
ctx->tws = ctx->vlen = 0;
return ctx->idx;
@@ -3250,7 +3250,7 @@
while (http_find_full_header2(name, name_len, buf, idx, ctx)) {
struct hdr_idx_elem *hdr = idx->v + ctx->idx;
int delta;
- char* val = (char*)ctx->line + name_len + 2;
+ char* val = (char*)ctx->line + ctx->val;
char* val_end = (char*)ctx->line + hdr->len;
char* reg_dst_buf;
uint reg_dst_buf_size;
@@ -3389,17 +3389,15 @@
break;
case HTTP_REQ_ACT_DEL_HDR:
- case HTTP_REQ_ACT_SET_HDR:
ctx.idx = 0;
/* remove all occurrences of the header */
while (http_find_header2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len,
txn->req.chn->buf->p, &txn->hdr_idx, &ctx)) {
http_remove_header2(&txn->req, &txn->hdr_idx, &ctx);
}
- if (rule->action == HTTP_REQ_ACT_DEL_HDR)
- break;
- /* now fall through to header addition */
+ break;
+ case HTTP_REQ_ACT_SET_HDR:
case HTTP_REQ_ACT_ADD_HDR:
chunk_printf(&trash, "%s: ", rule->arg.hdr_add.name);
memcpy(trash.str, rule->arg.hdr_add.name, rule->arg.hdr_add.name_len);
@@ -3407,6 +3405,16 @@
trash.str[trash.len++] = ':';
trash.str[trash.len++] = ' ';
trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.hdr_add.fmt);
+
+ if (rule->action == HTTP_REQ_ACT_SET_HDR) {
+ /* remove all occurrences of the header */
+ ctx.idx = 0;
+ while (http_find_header2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len,
+ txn->req.chn->buf->p, &txn->hdr_idx, &ctx)) {
+ http_remove_header2(&txn->req, &txn->hdr_idx, &ctx);
+ }
+ }
+
http_header_add_tail2(&txn->req, &txn->hdr_idx, trash.str, trash.len);
break;
@@ -3578,17 +3586,15 @@
break;
case HTTP_RES_ACT_DEL_HDR:
- case HTTP_RES_ACT_SET_HDR:
ctx.idx = 0;
/* remove all occurrences of the header */
while (http_find_header2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len,
txn->rsp.chn->buf->p, &txn->hdr_idx, &ctx)) {
http_remove_header2(&txn->rsp, &txn->hdr_idx, &ctx);
}
- if (rule->action == HTTP_RES_ACT_DEL_HDR)
- break;
- /* now fall through to header addition */
+ break;
+ case HTTP_RES_ACT_SET_HDR:
case HTTP_RES_ACT_ADD_HDR:
chunk_printf(&trash, "%s: ", rule->arg.hdr_add.name);
memcpy(trash.str, rule->arg.hdr_add.name, rule->arg.hdr_add.name_len);
@@ -3596,6 +3602,15 @@
trash.str[trash.len++] = ':';
trash.str[trash.len++] = ' ';
trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.hdr_add.fmt);
+
+ if (rule->action == HTTP_RES_ACT_SET_HDR) {
+ /* remove all occurrences of the header */
+ ctx.idx = 0;
+ while (http_find_header2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len,
+ txn->rsp.chn->buf->p, &txn->hdr_idx, &ctx)) {
+ http_remove_header2(&txn->rsp, &txn->hdr_idx, &ctx);
+ }
+ }
http_header_add_tail2(&txn->rsp, &txn->hdr_idx, trash.str, trash.len);
break;
@@ -7045,7 +7060,8 @@
/* The filter did not match the request, it can be
* iterated through all headers.
*/
- apply_filter_to_req_headers(s, req, exp);
+ if (unlikely(apply_filter_to_req_headers(s, req, exp) < 0))
+ return -1;
}
}
return 0;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/server.c
^
|
@@ -1223,7 +1223,6 @@
newsrv->state = SRV_ST_STOPPED;
newsrv->check.state |= CHK_ST_PAUSED;
newsrv->check.health = 0;
- newsrv->agent.health = 0;
cur_arg += 1;
}
else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5.11.tar.gz/src/ssl_sock.c
^
|
@@ -1308,7 +1308,8 @@
int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
{
- struct dirent *de;
+ struct dirent **de_list;
+ int i, n;
DIR *dir;
struct stat buf;
char *end;
@@ -1322,21 +1323,34 @@
for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
*end = 0;
- while ((de = readdir(dir))) {
- end = strrchr(de->d_name, '.');
- if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp")))
- continue;
-
- snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
- if (stat(fp, &buf) != 0) {
- memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
- err && *err ? *err : "", fp, strerror(errno));
- cfgerr++;
- continue;
+ n = scandir(path, &de_list, 0, alphasort);
+ if (n < 0) {
+ memprintf(err, "%sunable to scan directory '%s' : %s.\n",
+ err && *err ? *err : "", path, strerror(errno));
+ cfgerr++;
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ struct dirent *de = de_list[i];
+
+ end = strrchr(de->d_name, '.');
+ if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp")))
+ goto ignore_entry;
+
+ snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
+ if (stat(fp, &buf) != 0) {
+ memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
+ err && *err ? *err : "", fp, strerror(errno));
+ cfgerr++;
+ goto ignore_entry;
+ }
+ if (!S_ISREG(buf.st_mode))
+ goto ignore_entry;
+ cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
+ ignore_entry:
+ free(de);
}
- if (!S_ISREG(buf.st_mode))
- continue;
- cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
+ free(de_list);
}
closedir(dir);
return cfgerr;
|