diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index c490d798f..247ba58f5 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -83,6 +83,7 @@ struct protocol { int (*drain)(int fd); /* indicates whether we can safely close the fd */ int (*pause)(struct listener *l); /* temporarily pause this listener for a soft restart */ void (*add)(struct listener *l, int port); /* add a listener for this protocol and port */ + int (*addrcmp)(const struct sockaddr_storage *, const struct sockaddr_storage *); /* compare addresses (like memcmp) */ struct list listeners; /* list of listeners using this protocol (under proto_lock) */ int nb_listeners; /* number of listeners (under proto_lock) */ diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 5d1bc1ec7..17da4033d 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -67,6 +68,7 @@ static struct protocol proto_tcpv4 = { .get_dst = tcp_get_dst, .pause = tcp_pause_listener, .add = tcpv4_add_listener, + .addrcmp = sock_inet4_addrcmp, .listeners = LIST_HEAD_INIT(proto_tcpv4.listeners), .nb_listeners = 0, }; @@ -92,6 +94,7 @@ static struct protocol proto_tcpv6 = { .get_dst = tcp_get_dst, .pause = tcp_pause_listener, .add = tcpv6_add_listener, + .addrcmp = sock_inet6_addrcmp, .listeners = LIST_HEAD_INIT(proto_tcpv6.listeners), .nb_listeners = 0, }; @@ -610,35 +613,6 @@ int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir) } } -/* XXX: Should probably be elsewhere */ -static int compare_sockaddr(struct sockaddr_storage *a, struct sockaddr_storage *b) -{ - if (a->ss_family != b->ss_family) { - return (-1); - } - switch (a->ss_family) { - case AF_INET: - { - struct sockaddr_in *a4 = (void *)a, *b4 = (void *)b; - if (a4->sin_port != b4->sin_port) - return (-1); - return (memcmp(&a4->sin_addr, &b4->sin_addr, - sizeof(a4->sin_addr))); - } - case AF_INET6: - { - struct sockaddr_in6 *a6 = (void *)a, *b6 = (void *)b; - if (a6->sin6_port != b6->sin6_port) - return (-1); - return (memcmp(&a6->sin6_addr, &b6->sin6_addr, - sizeof(a6->sin6_addr))); - } - default: - return (-1); - } - -} - /* 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 . @@ -747,7 +721,7 @@ static int tcp_find_compatible_fd(struct listener *l) options &= ~LI_O_V4V6; while (xfer_sock) { - if (!compare_sockaddr(&xfer_sock->addr, &l->addr)) { + if (!l->proto->addrcmp(&xfer_sock->addr, &l->addr)) { if ((l->interface == NULL && xfer_sock->iface == NULL) || (l->interface != NULL && xfer_sock->iface != NULL && !strcmp(l->interface, xfer_sock->iface))) { diff --git a/src/proto_udp.c b/src/proto_udp.c index 0c14817f5..0bd903fb5 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include static int udp_bind_listeners(struct protocol *proto, char *errmsg, int errlen); @@ -63,6 +64,7 @@ static struct protocol proto_udp4 = { .get_dst = udp_get_dst, .pause = udp_pause_listener, .add = udp4_add_listener, + .addrcmp = sock_inet4_addrcmp, .listeners = LIST_HEAD_INIT(proto_udp4.listeners), .nb_listeners = 0, }; @@ -88,6 +90,7 @@ static struct protocol proto_udp6 = { .get_dst = udp_get_dst, .pause = udp_pause_listener, .add = udp6_add_listener, + .addrcmp = sock_inet6_addrcmp, .listeners = LIST_HEAD_INIT(proto_udp6.listeners), .nb_listeners = 0, }; diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 0e1cfc62a..f0cf99988 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ static struct protocol proto_unix = { .get_dst = sock_get_dst, .pause = uxst_pause_listener, .add = uxst_add_listener, + .addrcmp = sock_unix_addrcmp, .listeners = LIST_HEAD_INIT(proto_unix.listeners), .nb_listeners = 0, }; @@ -88,37 +90,13 @@ static int uxst_find_compatible_fd(struct listener *l) int ret = -1; while (xfer_sock) { - struct sockaddr_un *un1 = (void *)&l->addr; - struct sockaddr_un *un2 = (void *)&xfer_sock->addr; - /* * The bound socket's path as returned by getsockaddr * will be the temporary name .XXXXX.tmp, * so we can't just compare the two names */ - if (xfer_sock->addr.ss_family == AF_UNIX && - strncmp(un1->sun_path, un2->sun_path, - strlen(un1->sun_path)) == 0) { - char *after_sockname = un2->sun_path + - strlen(un1->sun_path); - /* Make a reasonable effort to check that - * it is indeed a haproxy-generated temporary - * name, it's not perfect, but probably good enough. - */ - if (after_sockname[0] == '.') { - after_sockname++; - while (after_sockname[0] >= '0' && - after_sockname[0] <= '9') - after_sockname++; - if (!strcmp(after_sockname, ".tmp")) - break; - /* abns sockets sun_path starts with a \0 */ - } else if (un1->sun_path[0] == 0 - && un2->sun_path[0] == 0 - && !memcmp(&un1->sun_path[1], &un2->sun_path[1], - sizeof(un1->sun_path) - 1)) + if (!l->proto->addrcmp(&xfer_sock->addr, &l->addr)) break; - } xfer_sock = xfer_sock->next; } if (xfer_sock != NULL) {