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 */
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 */
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 */
.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,
.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,
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>.
.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,
{
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;
}
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;
+ }
+}