From: Willy Tarreau Date: Fri, 28 Aug 2020 10:07:22 +0000 (+0200) Subject: REORG: sock: start to move some generic socket code to sock.c X-Git-Tag: v2.3-dev4~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=18b7df7a2bbc513d58414cd1afd3ec00340a644c;p=thirdparty%2Fhaproxy.git REORG: sock: start to move some generic socket code to sock.c The new file sock.c will contain generic code for standard sockets relying on file descriptors. We currently have way too much duplication between proto_uxst, proto_tcp, proto_sockpair and proto_udp. For now only get_src, get_dst and sock_create_server_socket were moved, and are used where appropriate. --- diff --git a/Makefile b/Makefile index 2372af21dc..7649998df3 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 38c02c73df..2e20309116 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 5e25166218..31e6a90523 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 0000000000..79904e254b --- /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 7ab6b50ecd..5d1bc1ec78 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 e2a854d210..0c14817f5d 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 f64c890ab2..0e1cfc62a2 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 0000000000..2eb4b6fd5d --- /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: + */