]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sock_inet: implement sock_inet_get_dst()
authorWilly Tarreau <w@1wt.eu>
Fri, 28 Aug 2020 13:19:45 +0000 (15:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Aug 2020 16:51:36 +0000 (18:51 +0200)
This one is common to the TCPv4 and UDPv4 code, it retrieves the
destination address of a socket, taking care of the possiblity that for
an incoming connection the traffic was possibly redirected. The TCP and
UDP definitions were updated to rely on it and remove duplicated code.

include/haproxy/proto_tcp.h
include/haproxy/proto_udp.h
include/haproxy/sock_inet.h
src/proto_tcp.c
src/proto_udp.c
src/sock_inet.c

index 2e20309116050db479ba3cdac85154f870f02255..8e57acfd6867353614e97458ea6ce504abae75b1 100644 (file)
@@ -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_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 int tcp_is_foreign(int fd, sa_family_t family);
 
 #endif /* _HAPROXY_PROTO_TCP_H */
index 31e6a90523779094e6e2b6bcc6b0dc8086476087..6b91cea7c38715e09ee28dcdf36cd10ec30b5c39 100644 (file)
@@ -29,6 +29,7 @@ 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);
+int udp6_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 
 #endif /* _PROTO_PROTO_UDP_H */
 
index 814ae58393a14dffcddeb4208ec2fd6fbf7509ad..8b1de095a398743b5c6def8ca3d3187f272cce0e 100644 (file)
@@ -29,5 +29,6 @@
 
 int sock_inet4_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
 int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
+int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 
 #endif /* _HAPROXY_SOCK_INET_H */
index 17da4033d484f747c40e84a38435995d8e0879b7..675c686eee26e6c3ada0cd1a525b38c318b2ad77 100644 (file)
@@ -65,7 +65,7 @@ static struct protocol proto_tcpv4 = {
        .unbind_all = unbind_all_listeners,
        .enable_all = enable_all_listeners,
        .get_src = sock_get_src,
-       .get_dst = tcp_get_dst,
+       .get_dst = sock_inet_get_dst,
        .pause = tcp_pause_listener,
        .add = tcpv4_add_listener,
        .addrcmp = sock_inet4_addrcmp,
@@ -91,7 +91,7 @@ static struct protocol proto_tcpv6 = {
        .unbind_all = unbind_all_listeners,
        .enable_all = enable_all_listeners,
        .get_src = sock_get_src,
-       .get_dst = tcp_get_dst,
+       .get_dst = sock_get_dst,
        .pause = tcp_pause_listener,
        .add = tcpv6_add_listener,
        .addrcmp = sock_inet6_addrcmp,
@@ -581,38 +581,6 @@ int tcp_connect_server(struct connection *conn, int flags)
        return SF_ERR_NONE;  /* connection is OK */
 }
 
-
-/*
- * Retrieves the original destination address for the socket <fd>, with <dir>
- * indicating if we're a listener (=0) or an initiator (!=0). In the case of a
- * listener, if the original destination address was translated, the original
- * address is retrieved. It returns 0 in case of success, -1 in case of error.
- * The socket's source address is stored in <sa> for <salen> bytes.
- */
-int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
-{
-       if (dir)
-               return getpeername(fd, sa, &salen);
-       else {
-               int ret = getsockname(fd, sa, &salen);
-
-               if (ret < 0)
-                       return ret;
-
-#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
-               /* For TPROXY and Netfilter's NAT, we can retrieve the original
-                * IPv4 address before DNAT/REDIRECT. We must not do that with
-                * other families because v6-mapped IPv4 addresses are still
-                * reported as v4.
-                */
-               if (((struct sockaddr_storage *)sa)->ss_family == AF_INET
-                   && getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
-                       return 0;
-#endif
-               return ret;
-       }
-}
-
 /* Returns true if the passed FD corresponds to a socket bound with LI_O_FOREIGN
  * according to the various supported socket options. The socket's address family
  * must be passed in <family>.
index 0bd903fb5b35051e0861e1b4b4a528cace167221..96b878a345528bfe2896d14ad28d180e6261c9e6 100644 (file)
@@ -87,7 +87,7 @@ static struct protocol proto_udp6 = {
        .unbind_all = unbind_all_listeners,
        .enable_all = enable_all_listeners,
        .get_src = udp6_get_src,
-       .get_dst = udp_get_dst,
+       .get_dst = udp6_get_dst,
        .pause = udp_pause_listener,
        .add = udp6_add_listener,
        .addrcmp = sock_inet6_addrcmp,
@@ -142,34 +142,27 @@ int udp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
 {
        int ret;
 
-       if (dir)
-               ret = getpeername(fd, sa, &salen);
-       else {
-               ret = getsockname(fd, sa, &salen);
-
-               if (ret < 0)
-                       return ret;
-
-#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
-               /* For TPROXY and Netfilter's NAT, we can retrieve the original
-                * IPv4 address before DNAT/REDIRECT. We must not do that with
-                * other families because v6-mapped IPv4 addresses are still
-                * reported as v4.
-                */
-               if (((struct sockaddr_storage *)sa)->ss_family == AF_INET
-                   && getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0) {
-                       sa->sa_family = AF_CUST_UDP4;
-                       return 0;
-               }
-#endif
-       }
+       ret = sock_inet_get_dst(fd, sa, salen, dir);
+       if (!ret)
+               sa->sa_family = AF_CUST_UDP4;
 
-       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;
-       }
+       return ret;
+}
+
+/*
+ * Retrieves the original destination address for the socket <fd>, with <dir>
+ * indicating if we're a listener (=0) or an initiator (!=0). In the case of a
+ * listener, if the original destination address was translated, the original
+ * address is retrieved. It returns 0 in case of success, -1 in case of error.
+ * The socket's source address is stored in <sa> for <salen> bytes.
+ */
+int udp6_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       int ret;
+
+       ret = sock_get_dst(fd, sa, salen, dir);
+       if (!ret)
+               sa->sa_family = AF_CUST_UDP6;
 
        return ret;
 }
index 21a024ab4b459f84ce1ed2713200d9a074ce422e..b82a920addc7febb548e69f7d840c4829fbdf5ab 100644 (file)
@@ -75,3 +75,34 @@ int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_s
 
        return memcmp(&a6->sin6_addr, &b6->sin6_addr, sizeof(a6->sin6_addr));
 }
+
+/*
+ * Retrieves the original destination address for the socket <fd> which must be
+ * of family AF_INET (not AF_INET6), with <dir> indicating if we're a listener
+ * (=0) or an initiator (!=0). In the case of a listener, if the original
+ * destination address was translated, the original address is retrieved. It
+ * returns 0 in case of success, -1 in case of error. The socket's source
+ * address is stored in <sa> for <salen> bytes.
+ */
+int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       if (dir)
+               return getpeername(fd, sa, &salen);
+       else {
+               int ret = getsockname(fd, sa, &salen);
+
+               if (ret < 0)
+                       return ret;
+
+#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
+               /* For TPROXY and Netfilter's NAT, we can retrieve the original
+                * IPv4 address before DNAT/REDIRECT. We must not do that with
+                * other families because v6-mapped IPv4 addresses are still
+                * reported as v4.
+                */
+               if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
+                       return 0;
+#endif
+               return ret;
+       }
+}