mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
BUG/MAJOR: fix listening IP address storage for frontends
When compiled with GCC 6, the IP address specified for a frontend was ignored and HAProxy was listening on all addresses instead. This is caused by an incomplete copy of a "struct sockaddr_storage". With the GNU Libc, "struct sockaddr_storage" is defined as this: struct sockaddr_storage { sa_family_t ss_family; unsigned long int __ss_align; char __ss_padding[(128 - (2 * sizeof (unsigned long int)))]; }; Doing an aggregate copy (ss1 = ss2) is different than using memcpy(): only members of the aggregate have to be copied. Notably, padding can be or not be copied. In GCC 6, some optimizations use this fact and if a "struct sockaddr_storage" contains a "struct sockaddr_in", the port and the address are part of the padding (between sa_family and __ss_align) and can be not copied over. Therefore, we replace any aggregate copy by a memcpy(). There is another place using the same pattern. We also fix a function receiving a "struct sockaddr_storage" by copy instead of by reference. Since it only needs a read-only copy, the function is converted to request a reference.
This commit is contained in:
parent
29c44e1f1e
commit
6e61589573
@ -110,7 +110,7 @@ void http_set_status(unsigned int status, struct stream *s);
|
|||||||
int http_transform_header_str(struct stream* s, struct http_msg *msg, const char* name,
|
int http_transform_header_str(struct stream* s, struct http_msg *msg, const char* name,
|
||||||
unsigned int name_len, const char *str, struct my_regex *re,
|
unsigned int name_len, const char *str, struct my_regex *re,
|
||||||
int action);
|
int action);
|
||||||
void inet_set_tos(int fd, struct sockaddr_storage from, int tos);
|
void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos);
|
||||||
void http_perform_server_redirect(struct stream *s, struct stream_interface *si);
|
void http_perform_server_redirect(struct stream *s, struct stream_interface *si);
|
||||||
void http_return_srv_error(struct stream *s, struct stream_interface *si);
|
void http_return_srv_error(struct stream *s, struct stream_interface *si);
|
||||||
void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
|
void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
|
||||||
|
@ -287,7 +287,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* OK the address looks correct */
|
/* OK the address looks correct */
|
||||||
ss = *ss2;
|
memcpy(&ss, ss2, sizeof(ss));
|
||||||
|
|
||||||
for (; port <= end; port++) {
|
for (; port <= end; port++) {
|
||||||
l = calloc(1, sizeof(*l));
|
l = calloc(1, sizeof(*l));
|
||||||
|
@ -744,7 +744,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
|
|||||||
const char pp2_signature[] = PP2_SIGNATURE;
|
const char pp2_signature[] = PP2_SIGNATURE;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
|
struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
|
||||||
struct sockaddr_storage null_addr = {0};
|
struct sockaddr_storage null_addr = { .ss_family = 0 };
|
||||||
struct sockaddr_storage *src = &null_addr;
|
struct sockaddr_storage *src = &null_addr;
|
||||||
struct sockaddr_storage *dst = &null_addr;
|
struct sockaddr_storage *dst = &null_addr;
|
||||||
|
|
||||||
|
@ -4781,7 +4781,7 @@ __LJMP static int hlua_txn_set_tos(lua_State *L)
|
|||||||
tos = MAY_LJMP(luaL_checkinteger(L, 2));
|
tos = MAY_LJMP(luaL_checkinteger(L, 2));
|
||||||
|
|
||||||
if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
|
if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
|
||||||
inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, tos);
|
inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, tos);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3189,15 +3189,15 @@ int http_handle_stats(struct stream *s, struct channel *req)
|
|||||||
/* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets
|
/* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets
|
||||||
* (as per RFC3260 #4 and BCP37 #4.2 and #5.2).
|
* (as per RFC3260 #4 and BCP37 #4.2 and #5.2).
|
||||||
*/
|
*/
|
||||||
void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
|
void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos)
|
||||||
{
|
{
|
||||||
#ifdef IP_TOS
|
#ifdef IP_TOS
|
||||||
if (from.ss_family == AF_INET)
|
if (from->ss_family == AF_INET)
|
||||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6_TCLASS
|
#ifdef IPV6_TCLASS
|
||||||
if (from.ss_family == AF_INET6) {
|
if (from->ss_family == AF_INET6) {
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr))
|
if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)from)->sin6_addr))
|
||||||
/* v4-mapped addresses need IP_TOS */
|
/* v4-mapped addresses need IP_TOS */
|
||||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||||
else
|
else
|
||||||
@ -3363,7 +3363,7 @@ resume_execution:
|
|||||||
|
|
||||||
case ACT_HTTP_SET_TOS:
|
case ACT_HTTP_SET_TOS:
|
||||||
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn))
|
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn))
|
||||||
inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
|
inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_SET_MARK:
|
case ACT_HTTP_SET_MARK:
|
||||||
@ -3646,7 +3646,7 @@ resume_execution:
|
|||||||
|
|
||||||
case ACT_HTTP_SET_TOS:
|
case ACT_HTTP_SET_TOS:
|
||||||
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn))
|
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn))
|
||||||
inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
|
inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_SET_MARK:
|
case ACT_HTTP_SET_MARK:
|
||||||
|
@ -435,7 +435,7 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
|
|||||||
struct sockaddr_storage sa;
|
struct sockaddr_storage sa;
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
sa = src->source_addr;
|
memcpy(&sa, &src->source_addr, sizeof(sa));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* note: in case of retry, we may have to release a previously
|
/* note: in case of retry, we may have to release a previously
|
||||||
|
Loading…
x
Reference in New Issue
Block a user