diff --git a/Makefile b/Makefile index 2372af21d..7649998df 100644 --- a/Makefile +++ b/Makefile @@ -820,7 +820,7 @@ OBJS = src/mux_fcgi.o src/mux_h1.o src/mux_h2.o src/backend.o \ src/eb64tree.o src/dict.o src/shctx.o src/ebimtree.o \ src/eb32tree.o src/ebtree.o src/dgram.o src/proto_udp.o \ src/hpack-huff.o src/cfgparse-tcp.o src/base64.o src/version.o \ - src/cfgparse-unix.o + src/cfgparse-unix.o src/sock.o ifneq ($(TRACE),) OBJS += src/calltrace.o diff --git a/include/haproxy/proto_tcp.h b/include/haproxy/proto_tcp.h index 38c02c73d..2e2030911 100644 --- a/include/haproxy/proto_tcp.h +++ b/include/haproxy/proto_tcp.h @@ -31,7 +31,6 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote); int tcp_pause_listener(struct listener *l); int tcp_connect_server(struct connection *conn, int flags); -int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); int tcp_is_foreign(int fd, sa_family_t family); diff --git a/include/haproxy/proto_udp.h b/include/haproxy/proto_udp.h index 5e2516621..31e6a9052 100644 --- a/include/haproxy/proto_udp.h +++ b/include/haproxy/proto_udp.h @@ -27,6 +27,7 @@ int udp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote); int udp_pause_listener(struct listener *l); int udp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); +int udp6_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); int udp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); #endif /* _PROTO_PROTO_UDP_H */ diff --git a/include/haproxy/sock.h b/include/haproxy/sock.h new file mode 100644 index 000000000..79904e254 --- /dev/null +++ b/include/haproxy/sock.h @@ -0,0 +1,42 @@ +/* + * include/haproxy/sock.h + * This file contains declarations for native (BSD-compatible) sockets. + * + * Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, version 2.1 + * exclusively. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _HAPROXY_SOCK_H +#define _HAPROXY_SOCK_H + +#include +#include + +#include +#include + +int sock_create_server_socket(struct connection *conn); +int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); +int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); + +#endif /* _HAPROXY_SOCK_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 7ab6b50ec..5d1bc1ec7 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -62,7 +63,7 @@ static struct protocol proto_tcpv4 = { .bind_all = tcp_bind_listeners, .unbind_all = unbind_all_listeners, .enable_all = enable_all_listeners, - .get_src = tcp_get_src, + .get_src = sock_get_src, .get_dst = tcp_get_dst, .pause = tcp_pause_listener, .add = tcpv4_add_listener, @@ -87,7 +88,7 @@ static struct protocol proto_tcpv6 = { .bind_all = tcp_bind_listeners, .unbind_all = unbind_all_listeners, .enable_all = enable_all_listeners, - .get_src = tcp_get_src, + .get_src = sock_get_src, .get_dst = tcp_get_dst, .pause = tcp_pause_listener, .add = tcpv6_add_listener, @@ -226,22 +227,6 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so return 0; } -/* conn->dst MUST be valid */ -static int create_server_socket(struct connection *conn) -{ - const struct netns_entry *ns = NULL; - -#ifdef USE_NS - if (objt_server(conn->target)) { - if (__objt_server(conn->target)->flags & SRV_F_USE_NS_FROM_PP) - ns = conn->proxy_netns; - else - ns = __objt_server(conn->target)->netns; - } -#endif - return my_socketat(ns, conn->dst->ss_family, SOCK_STREAM, IPPROTO_TCP); -} - /* * This function initiates a TCP connection establishment to the target assigned * to connection using (si->{target,dst}). A source address may be @@ -310,7 +295,7 @@ int tcp_connect_server(struct connection *conn, int flags) return SF_ERR_INTERNAL; } - fd = conn->handle.fd = create_server_socket(conn); + fd = conn->handle.fd = sock_create_server_socket(conn); if (fd == -1) { qfprintf(stderr, "Cannot get a server socket.\n"); @@ -594,21 +579,6 @@ int tcp_connect_server(struct connection *conn, int flags) } -/* - * Retrieves the source address for the socket , with indicating - * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of - * success, -1 in case of error. The socket's source address is stored in - * for bytes. - */ -int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir) -{ - if (dir) - return getsockname(fd, sa, &salen); - else - return getpeername(fd, sa, &salen); -} - - /* * Retrieves the original destination address for the socket , with * indicating if we're a listener (=0) or an initiator (!=0). In the case of a diff --git a/src/proto_udp.c b/src/proto_udp.c index e2a854d21..0c14817f5 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include static int udp_bind_listeners(struct protocol *proto, char *errmsg, int errlen); @@ -83,7 +84,7 @@ static struct protocol proto_udp6 = { .bind_all = udp_bind_listeners, .unbind_all = unbind_all_listeners, .enable_all = enable_all_listeners, - .get_src = udp_get_src, + .get_src = udp6_get_src, .get_dst = udp_get_dst, .pause = udp_pause_listener, .add = udp6_add_listener, @@ -103,21 +104,29 @@ int udp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir) { int ret; - if (dir) - ret = getsockname(fd, sa, &salen); - else - ret = getpeername(fd, sa, &salen); - - if (!ret) { - if (sa->sa_family == AF_INET) - sa->sa_family = AF_CUST_UDP4; - else if (sa->sa_family == AF_INET6) - sa->sa_family = AF_CUST_UDP6; - } + ret = sock_get_src(fd, sa, salen, dir); + if (!ret) + sa->sa_family = AF_CUST_UDP4; return ret; } +/* + * Retrieves the source address for the socket , with indicating + * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of + * success, -1 in case of error. The socket's source address is stored in + * for bytes. + */ +int udp6_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir) +{ + int ret; + + ret = sock_get_src(fd, sa, salen, dir); + if (!ret) + sa->sa_family = AF_CUST_UDP6; + + return ret; +} /* * Retrieves the original destination address for the socket , with diff --git a/src/proto_uxst.c b/src/proto_uxst.c index f64c890ab..0e1cfc62a 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,6 @@ static int uxst_unbind_listeners(struct protocol *proto); static int uxst_connect_server(struct connection *conn, int flags); static void uxst_add_listener(struct listener *listener, int port); static int uxst_pause_listener(struct listener *l); -static int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); -static int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_unix = { @@ -63,8 +62,8 @@ static struct protocol proto_unix = { .unbind_all = uxst_unbind_listeners, .enable_all = enable_all_listeners, .disable_all = disable_all_listeners, - .get_src = uxst_get_src, - .get_dst = uxst_get_dst, + .get_src = sock_get_src, + .get_dst = sock_get_dst, .pause = uxst_pause_listener, .add = uxst_add_listener, .listeners = LIST_HEAD_INIT(proto_unix.listeners), @@ -77,35 +76,6 @@ INITCALL1(STG_REGISTER, protocol_register, &proto_unix); * 1) low-level socket functions ********************************/ -/* - * Retrieves the source address for the socket , with indicating - * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of - * success, -1 in case of error. The socket's source address is stored in - * for bytes. - */ -static int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir) -{ - if (dir) - return getsockname(fd, sa, &salen); - else - return getpeername(fd, sa, &salen); -} - - -/* - * Retrieves the original destination address for the socket , with - * indicating if we're a listener (=0) or an initiator (!=0). It returns 0 in - * case of success, -1 in case of error. The socket's source address is stored - * in for bytes. - */ -static int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir) -{ - if (dir) - return getpeername(fd, sa, &salen); - else - return getsockname(fd, sa, &salen); -} - /******************************** * 2) listener-oriented functions diff --git a/src/sock.c b/src/sock.c new file mode 100644 index 000000000..2eb4b6fd5 --- /dev/null +++ b/src/sock.c @@ -0,0 +1,85 @@ +/* + * Generic code for native (BSD-compatible) sockets + * + * Copyright 2000-2020 Willy Tarreau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +/* Create a socket to connect to the server in conn->dst (which MUST be valid), + * using the configured namespace if needed, or the one passed by the proxy + * protocol if required to do so. It ultimately calls socket() or socketat() + * and returns the FD or error code. + */ +int sock_create_server_socket(struct connection *conn) +{ + const struct netns_entry *ns = NULL; + +#ifdef USE_NS + if (objt_server(conn->target)) { + if (__objt_server(conn->target)->flags & SRV_F_USE_NS_FROM_PP) + ns = conn->proxy_netns; + else + ns = __objt_server(conn->target)->netns; + } +#endif + return my_socketat(ns, conn->dst->ss_family, SOCK_STREAM, 0); +} + +/* + * Retrieves the source address for the socket , with indicating + * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of + * success, -1 in case of error. The socket's source address is stored in + * for bytes. + */ +int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir) +{ + if (dir) + return getsockname(fd, sa, &salen); + else + return getpeername(fd, sa, &salen); +} + +/* + * Retrieves the original destination address for the socket , with + * indicating if we're a listener (=0) or an initiator (!=0). It returns 0 in + * case of success, -1 in case of error. The socket's source address is stored + * in for bytes. + */ +int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir) +{ + if (dir) + return getpeername(fd, sa, &salen); + else + return getsockname(fd, sa, &salen); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */