summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2020-09-01 16:23:29 +0200
committerWilly Tarreau <w@1wt.eu>2020-09-01 17:11:46 +0200
commitc1c7114d8af2b7f94bfd41684a9f27e0f01bc560 (patch)
treef2c8873e39723f4d184b659b1d46e925f1cf91a1
parent09195b82cf51176739fa019ae9d1d15719eef10d (diff)
downloadhaproxy-20200901-split-protos-7.tar.gz
MEDIUM: udp: make use of sock_inet_bind_listener()20200901-split-protos-7
This removes all the AF_INET-specific code from udp_bind_listener() and now simply relies on sock_inet_bind_listener() to do the same job. The function is now basically just a wrapper around sock_inet_bind_receiver().
-rw-r--r--src/proto_udp.c124
1 files changed, 19 insertions, 105 deletions
diff --git a/src/proto_udp.c b/src/proto_udp.c
index 3e0a227b7..c80d0b6f1 100644
--- a/src/proto_udp.c
+++ b/src/proto_udp.c
@@ -182,14 +182,9 @@ int udp6_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
*/
int udp_bind_listener(struct listener *listener, char *errmsg, int errlen)
{
- __label__ udp_return, udp_close_return;
- int fd, err;
- const char *msg = NULL;
- /* copy listener addr because sometimes we need to switch family */
- struct sockaddr_storage addr_inet = listener->rx.addr;
-
- /* force to classic sock family */
- addr_inet.ss_family = listener->rx.proto->sock_family;
+ int err = ERR_NONE;
+ void *handler = NULL;
+ char *msg = NULL;
/* ensure we never return garbage */
if (errlen)
@@ -198,116 +193,35 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen)
if (listener->state != LI_ASSIGNED)
return ERR_NONE; /* already bound */
- err = ERR_NONE;
-
- if (listener->rx.options & RX_O_BOUND)
- goto bound;
-
- /* TODO: Implement reuse fd. Take care that to identify fd to reuse
- * listeners uses a special AF_CUST_ family and we MUST consider
- * IPPROTO (sockaddr is not enough)
- */
-
- fd = my_socketat(listener->rx.netns, listener->rx.proto->sock_family, listener->rx.proto->sock_type, listener->rx.proto->sock_prot);
- if (fd == -1) {
- err |= ERR_RETRYABLE | ERR_ALERT;
- msg = "cannot create listening socket";
- goto udp_return;
- }
-
- if (fd >= global.maxsock) {
- err |= ERR_FATAL | ERR_ABORT | ERR_ALERT;
- msg = "not enough free sockets (raise '-n' parameter)";
- goto udp_close_return;
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+ switch (listener->bind_conf->frontend->mode) {
+ case PR_MODE_SYSLOG:
+ handler = syslog_fd_handler;
+ break;
+ default:
err |= ERR_FATAL | ERR_ALERT;
- msg = "cannot make socket non-blocking";
- goto udp_close_return;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
- /* not fatal but should be reported */
- msg = "cannot do so_reuseaddr";
- err |= ERR_ALERT;
+ msg = "UDP is not yet supported on this proxy mode";
+ goto udp_return;
}
-#ifdef SO_REUSEPORT
- /* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of
- * Linux, it might return an error that we will silently ignore.
- */
- if (global.tune.options & GTUNE_USE_REUSEPORT)
- setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
-#endif
-
- if (listener->options & LI_O_FOREIGN) {
- switch (addr_inet.ss_family) {
- case AF_INET:
- if (!sock_inet4_make_foreign(fd)) {
- msg = "cannot make listening socket transparent";
- err |= ERR_ALERT;
- }
- break;
- case AF_INET6:
- if (!sock_inet6_make_foreign(fd)) {
- msg = "cannot make listening socket transparent";
- err |= ERR_ALERT;
- }
- break;
- }
- }
+ err = sock_inet_bind_receiver(&listener->rx,
+ handler, listener,
+ listener->bind_conf->bind_thread, &msg);
-#ifdef SO_BINDTODEVICE
- /* Note: this might fail if not CAP_NET_RAW */
- if (listener->rx.interface) {
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
- listener->rx.interface, strlen(listener->rx.interface) + 1) == -1) {
- msg = "cannot bind listener to device";
- err |= ERR_WARN;
- }
- }
-#endif
-#if defined(IPV6_V6ONLY)
- if (listener->options & LI_O_V6ONLY)
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
- else if (listener->options & LI_O_V4V6)
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
-#endif
-
- if (bind(fd, (struct sockaddr *)&addr_inet, listener->rx.proto->sock_addrlen) < 0) {
- err |= ERR_RETRYABLE | ERR_ALERT;
- msg = "cannot bind socket";
- goto udp_close_return;
+ if (err != ERR_NONE) {
+ snprintf(errmsg, errlen, "%s", msg);
+ free(msg); msg = NULL;
+ return err;
}
- listener->rx.options |= RX_O_BOUND;
-
- bound:
- /* the socket is ready */
- listener->rx.fd = fd;
listener->state = LI_LISTEN;
- if (listener->bind_conf->frontend->mode == PR_MODE_SYSLOG)
- fd_insert(fd, listener, syslog_fd_handler,
- thread_mask(listener->bind_conf->bind_thread) & all_threads_mask);
- else {
- err |= ERR_FATAL | ERR_ALERT;
- msg = "UDP is not yet supported on this proxy mode";
- goto udp_close_return;
- }
-
udp_return:
if (msg && errlen) {
char pn[INET6_ADDRSTRLEN];
- addr_to_str(&addr_inet, pn, sizeof(pn));
- snprintf(errmsg, errlen, "%s [%s:%d]", msg, pn, get_host_port(&addr_inet));
+ addr_to_str(&listener->rx.addr, pn, sizeof(pn));
+ snprintf(errmsg, errlen, "%s [%s:%d]", msg, pn, get_host_port(&listener->rx.addr));
}
return err;
-
- udp_close_return:
- close(fd);
- goto udp_return;
}
/* This function creates all UDP sockets bound to the protocol entry <proto>.