From: Arran Cudbard-Bell Date: Sun, 16 Apr 2023 09:20:32 +0000 (+1000) Subject: Use the existing bind function for binding client sockets to interfaces, ipaddrs... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ebc5596d5e71f20bbadbfc6ae22177544b10c455;p=thirdparty%2Ffreeradius-server.git Use the existing bind function for binding client sockets to interfaces, ipaddrs, and ports --- diff --git a/src/bin/dhcpclient.c b/src/bin/dhcpclient.c index 30b969ad0cf..42293bdcf12 100644 --- a/src/bin/dhcpclient.c +++ b/src/bin/dhcpclient.c @@ -366,7 +366,7 @@ static int send_with_socket(fr_radius_packet_t **reply, fr_radius_packet_t *requ return -1; } - if (fr_socket_bind(sockfd, &request->socket.inet.src_ipaddr, &request->socket.inet.src_port, NULL) < 0) { + if (fr_socket_bind(sockfd, NULL, &request->socket.inet.src_ipaddr, &request->socket.inet.src_port) < 0) { ERROR("Error binding socket - %s", fr_strerror()); return -1; } diff --git a/src/bin/radclient.c b/src/bin/radclient.c index 22829774a65..d51f9a52c1a 100644 --- a/src/bin/radclient.c +++ b/src/bin/radclient.c @@ -949,7 +949,7 @@ static int send_one_packet(rc_request_t *request) return -1; } - if (fr_socket_bind(mysockfd, &client_ipaddr, &port, NULL) < 0) { + if (fr_socket_bind(mysockfd, NULL, &client_ipaddr, &port) < 0) { fr_perror("Error binding socket"); return -1; } @@ -1787,7 +1787,7 @@ int main(int argc, char **argv) return -1; } - if (fr_socket_bind(sockfd, &client_ipaddr, &client_port, NULL) < 0) { + if (fr_socket_bind(sockfd, NULL, &client_ipaddr, &client_port) < 0) { fr_perror("Error binding socket"); return -1; } @@ -1800,7 +1800,7 @@ int main(int argc, char **argv) return -1; } - if (fr_socket_bind(coafd, &client_ipaddr, &coa_port, NULL) < 0) { + if (fr_socket_bind(coafd, NULL, &client_ipaddr, &coa_port) < 0) { fr_perror("Error binding socket"); return -1; } diff --git a/src/lib/util/socket.c b/src/lib/util/socket.c index e6fc0fd40ca..7c9aea7b158 100644 --- a/src/lib/util/socket.c +++ b/src/lib/util/socket.c @@ -209,6 +209,255 @@ static int socket_dont_fragment(UNUSED int sockfd, UNUSED int af) } #endif /* lots of things */ +/** Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface. + * + * Use one of: + * - fr_socket_server_udp - for non-connected socket. + * - fr_socket_server_tcp + * ...to open a file descriptor, then call this function to bind the socket to an IP address. + * + * @param[in] sockfd the socket which opened by fr_socket_server_*. + * @param[in] ifname to bind to. + * @param[in,out] src_ipaddr The IP address to bind to. Will be updated to the IP address + * that was actually bound to. Pass NULL to just bind to an interface. + * @param[in] src_port the port to bind to. NULL if any port is allowed. + + * @return + * - 0 on success + * - -1 on failure. + */ +int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port) +{ + int ret; + uint16_t my_port = 0; + fr_ipaddr_t my_ipaddr; + struct sockaddr_storage salocal; + socklen_t salen; + + /* + * Clear the thread local error stack as we may + * push multiple errors onto the stack, and this + * is likely to be the function which returns + * the "original" error. + */ + fr_strerror_clear(); + + if (src_port) my_port = *src_port; + if (src_ipaddr) { + my_ipaddr = *src_ipaddr; + } else { + my_ipaddr = (fr_ipaddr_t) { + .af = AF_UNSPEC + }; + } + +#ifdef HAVE_CAPABILITY_H + /* + * If we're binding to a special port as non-root, then + * check capabilities. If we're root, we already have + * equivalent capabilities so we don't need to check. + */ + if (src_port && (*src_port < 1024) && (geteuid() != 0)) { + (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE); /* Sets error on failure, which will be seen if the bind fails */ + } +#endif + + /* + * Bind to a device BEFORE touching IP addresses. + */ + if (ifname) { +#ifdef HAVE_NET_IF_H + uint32_t scope_id; + + scope_id = if_nametoindex(ifname); + if (!scope_id) { + fr_strerror_printf_push("Failed finding interface %s: %s", ifname, fr_syserror(errno)); + return -1; + } + + /* + * If the scope ID hasn't already been set, then + * set it. This allows us to get the scope from the interface name. + */ + if ((my_ipaddr.scope_id != 0) && (scope_id != my_ipaddr.scope_id)) { + fr_strerror_printf_push("Cannot bind to interface %s: Socket is already bound " + "to another interface", ifname); + return -1; + } +#endif + +#ifdef SO_BINDTODEVICE + /* + * The caller didn't specify a scope_id, but we + * have one from above. Call "bind to device", + * and set the scope_id. + */ + if (!my_ipaddr.scope_id) { + /* + * The internet hints that CAP_NET_RAW + * is required to use SO_BINDTODEVICE. + * + * This function also sets fr_strerror() + * on failure, which will be seen if the + * bind fails. If the bind succeeds, + * then we don't really care that the + * capability change has failed. We must + * already have that capability. + */ +#ifdef HAVE_CAPABILITY_H + (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE); +#endif + ret = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)); + if (ret < 0) { + fr_strerror_printf_push("Bind failed on interface %s: %s", + ifname, fr_syserror(errno)); + return -1; + } /* else it worked. */ + + /* + * Set the scope ID. + */ + my_ipaddr.scope_id = scope_id; + } + /* + * SO_BINDTODEVICE succeeded, so we're always + * bound to the socket. + */ + +#elif defined(IP_BOUND_IF) + { + int idx = if_nametoindex(ifname); + if (idx == 0) { + error: + fr_strerror_printf("Failed binding socket to %s: %s", ifname, fr_syserror(errno)); + return -1; + } + if (unlikely(setsockopt(sockfd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)) < 0)) goto error; + } +#else + { + struct ifaddrs *list = NULL; + bool bound = false; + + /* + * Troll through all interfaces to see if there's + */ + if (getifaddrs(&list) == 0) { + struct ifaddrs *i; + + for (i = list; i != NULL; i = i->ifa_next) { + if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, ifname) == 0)) { + /* + * IPv4, and there's either no src_ip, OR src_ip is INADDR_ANY, + * it's a match. + * + * We also update my_ipaddr to point to this particular IP, + * so that we can later bind() to it. This gets us the same + * effect as SO_BINDTODEVICE. + */ + if ((i->ifa_addr->sa_family == AF_INET) && + (!src_ipaddr || fr_ipaddr_is_inaddr_any(src_ipaddr))) { + (void) fr_ipaddr_from_sockaddr(&my_ipaddr, NULL, + (struct sockaddr_storage *) i->ifa_addr, + sizeof(struct sockaddr_in)); + my_ipaddr.scope_id = scope_id; + bound = true; + break; + } + + /* + * The caller specified a source IP, and we find a matching + * address family. Allow it. + * + * Note that we do NOT check for matching IPs here. If we did, + * then binding to an interface and the *wrong* IP would get us + * a "bind to device is unsupported" message. + * + * Instead we say "yes, we found a matching interface", and then + * allow the bind() call below to run. If that fails, we get a + * "Can't assign requested address" error, which is more informative. + */ + if (src_ipaddr && (src_ipaddr->af == i->ifa_addr->sa_family)) { + my_ipaddr.scope_id = scope_id; + bound = true; + break; + } + } + } + + freeifaddrs(list); + + if (!bound) { + /* + * IPv4: no link local addresses, + * and no bind to device. + */ + fr_strerror_printf_push("Bind to interface %s failed: Unable to match " + "interface with the given IP address.", ifname); + return -1; + } + } else { + fr_strerror_printf_push("Bind to interface %s failed, unable to get list of interfaces: %s", + ifname, fr_syserror(errno)); + return -1; + } + } +#endif + } /* else no interface was passed in */ + + /* + * Don't bind to an IP address if there's no src IP address. + */ + if (my_ipaddr.af == AF_UNSPEC) goto done; + + /* + * Set up sockaddr stuff. + */ + if (fr_ipaddr_to_sockaddr(&salocal, &salen, &my_ipaddr, my_port) < 0) return -1; + + ret = bind(sockfd, (struct sockaddr *) &salocal, salen); + if (ret < 0) { + fr_strerror_printf_push("Bind failed with source address %pV:%pV on interface %s: %s", + src_ipaddr ? fr_box_ipaddr(*src_ipaddr) : fr_box_strvalue("*"), + src_port ? fr_box_int16(*src_port) : fr_box_strvalue("*"), + ifname ? ifname : "*", + fr_syserror(errno)); + return ret; + } + + if (!src_port) goto done; + + /* + * FreeBSD jail issues. We bind to 0.0.0.0, but the + * kernel instead binds us to a 1.2.3.4. So once the + * socket is bound, ask it what it's IP address is. + * + * @todo - Uh... we don't update src_ipaddr with the new + * IP address. This means that we don't tell the caller + * what IP address we're bound to. That seems wrong. + */ + salen = sizeof(salocal); + memset(&salocal, 0, salen); + if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) { + fr_strerror_printf_push("Failed getting socket name: %s", fr_syserror(errno)); + return -1; + } + + if (fr_ipaddr_from_sockaddr(&my_ipaddr, &my_port, &salocal, salen) < 0) return -1; + *src_port = my_port; + *src_ipaddr = my_ipaddr; + +done: +#ifdef HAVE_CAPABILITY_H + /* + * Clear any errors we may have produced in the + * capabilities check. + */ + fr_strerror_clear(); +#endif + return 0; +} + #ifdef HAVE_SYS_UN_H /** Open a Unix socket * @@ -389,32 +638,6 @@ int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t * return -1; } - /* - * Bind to a specific interface - */ - if (ifname && (socket_bind_ifname(sockfd, ifname) < 0)) goto error; - - /* - * Allow the caller to bind us to a specific source IP. - */ - if (src_ipaddr && (src_ipaddr->af != AF_UNSPEC)) { - /* - * Ensure don't fragment bit is set - */ - if (socket_dont_fragment(sockfd, src_ipaddr->af) < 0) goto error; - - if (fr_ipaddr_to_sockaddr(&salocal, &salen, src_ipaddr, 0) < 0) { - close(sockfd); - return -1; - } - - if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) { - fr_strerror_printf("Failure binding to IP: %s", fr_syserror(errno)); - close(sockfd); - return -1; - } - } - /* * Although we ignore SIGPIPE, some operating systems * like BSD and OSX ignore the ignoring. @@ -431,27 +654,7 @@ int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t * } #endif - /* - * FreeBSD jail issues. We bind to 0.0.0.0, but the - * kernel instead binds us to a 1.2.3.4. So once the - * socket is bound, ask it what it's IP address is. - * - * If the caller asks for only one, well, too bad. - */ - if (src_ipaddr && src_port) { - salen = sizeof(salocal); - memset(&salocal, 0, salen); - if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) { - close(sockfd); - fr_strerror_printf("Failed getting socket name: %s", fr_syserror(errno)); - return -1; - } - - if (fr_ipaddr_from_sockaddr(src_ipaddr, src_port, &salocal, salen) < 0) { - close(sockfd); - return -1; - } - } + if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, src_port) < 0)) goto error; /* * And now get our destination @@ -509,7 +712,7 @@ int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t * * - FD on success * - -1 on failure. */ -int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t const *src_ipaddr, +int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async) { int sockfd; @@ -530,26 +733,7 @@ int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t const *src_ipaddr, return -1; } - /* - * Bind to a specific interface - */ - if (ifname && (socket_bind_ifname(sockfd, ifname) < 0)) goto error; - - /* - * Allow the caller to bind us to a specific source IP. - */ - if (src_ipaddr && (src_ipaddr->af != AF_UNSPEC)) { - if (fr_ipaddr_to_sockaddr(&salocal, &salen, src_ipaddr, 0) < 0) { - close(sockfd); - return -1; - } - - if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) { - fr_strerror_printf("Failure binding to IP: %s", fr_syserror(errno)); - close(sockfd); - return -1; - } - } + if (unlikely(fr_socket_bind(sockfd, ifname, src_ipaddr, NULL) < 0)) goto error; if (fr_ipaddr_to_sockaddr(&salocal, &salen, dst_ipaddr, dst_port) < 0) { close(sockfd); @@ -837,241 +1021,3 @@ int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char return sockfd; } - -/** Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface. - * - * Use one of: - * - fr_socket_client_udp - for a connected socket. - * - fr_socket_server_udp - for non-connected socket. - * - fr_socket_server_tcp - * ...to open a file descriptor, then call this function to bind the socket to an IP address. - * - * @param[in] sockfd the socket which opened by fr_socket_server_*. - * @param[in,out] src_ipaddr The IP address to bind to. NULL to just bind to an interface. - * @param[in] src_port the port to bind to. NULL if any port is allowed. - * @param[in] interface to bind to. - * @return - * - 0 on success - * - -1 on failure. - */ -int fr_socket_bind(int sockfd, fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *interface) -{ - int ret; - uint16_t my_port = 0; - fr_ipaddr_t my_ipaddr; - struct sockaddr_storage salocal; - socklen_t salen; - - /* - * Clear the thread local error stack as we may - * push multiple errors onto the stack, and this - * is likely to be the function which returns - * the "original" error. - */ - fr_strerror_clear(); - - if (src_port) my_port = *src_port; - if (src_ipaddr) { - my_ipaddr = *src_ipaddr; - } else { - my_ipaddr = (fr_ipaddr_t) { - .af = AF_UNSPEC - }; - } - -#ifdef HAVE_CAPABILITY_H - /* - * If we're binding to a special port as non-root, then - * check capabilities. If we're root, we already have - * equivalent capabilities so we don't need to check. - */ - if (src_port && (*src_port < 1024) && (geteuid() != 0)) { - (void)fr_cap_enable(CAP_NET_BIND_SERVICE, CAP_EFFECTIVE); /* Sets error on failure, which will be seen if the bind fails */ - } -#endif - - /* - * Bind to a device BEFORE touching IP addresses. - */ - if (interface) { -#ifdef HAVE_NET_IF_H - uint32_t scope_id; - - scope_id = if_nametoindex(interface); - if (!scope_id) { - fr_strerror_printf_push("Failed finding interface %s: %s", - interface, fr_syserror(errno)); - return -1; - } - - /* - * If the scope ID hasn't already been set, then - * set it. This allows us to get the scope from the interface name. - */ - if ((my_ipaddr.scope_id != 0) && (scope_id != my_ipaddr.scope_id)) { - fr_strerror_printf_push("Cannot bind to interface %s: Socket is already bound " - "to another interface", interface); - return -1; - } -#endif - -#ifdef SO_BINDTODEVICE - /* - * The caller didn't specify a scope_id, but we - * have one from above. Call "bind to device", - * and set the scope_id. - */ - if (!my_ipaddr.scope_id) { - /* - * The internet hints that CAP_NET_RAW - * is required to use SO_BINDTODEVICE. - * - * This function also sets fr_strerror() - * on failure, which will be seen if the - * bind fails. If the bind succeeds, - * then we don't really care that the - * capability change has failed. We must - * already have that capability. - */ -#ifdef HAVE_CAPABILITY_H - (void)fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE); -#endif - ret = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)); - if (ret < 0) { - fr_strerror_printf_push("Bind failed on interface %s: %s", - interface, fr_syserror(errno)); - return -1; - } /* else it worked. */ - - /* - * Set the scope ID. - */ - my_ipaddr.scope_id = scope_id; - } - /* - * SO_BINDTODEVICE succeeded, so we're always - * bound to the socket. - */ - -#else - { - struct ifaddrs *list = NULL; - bool bound = false; - - /* - * Troll through all interfaces to see if there's - */ - if (getifaddrs(&list) == 0) { - struct ifaddrs *i; - - for (i = list; i != NULL; i = i->ifa_next) { - if (i->ifa_addr && i->ifa_name && (strcmp(i->ifa_name, interface) == 0)) { - /* - * IPv4, and there's either no src_ip, OR src_ip is INADDR_ANY, - * it's a match. - * - * We also update my_ipaddr to point to this particular IP, - * so that we can later bind() to it. This gets us the same - * effect as SO_BINDTODEVICE. - */ - if ((i->ifa_addr->sa_family == AF_INET) && - (!src_ipaddr || fr_ipaddr_is_inaddr_any(src_ipaddr))) { - (void) fr_ipaddr_from_sockaddr(&my_ipaddr, NULL, - (struct sockaddr_storage *) i->ifa_addr, - sizeof(struct sockaddr_in)); - my_ipaddr.scope_id = scope_id; - bound = true; - break; - } - - /* - * The caller specified a source IP, and we find a matching - * address family. Allow it. - * - * Note that we do NOT check for matching IPs here. If we did, - * then binding to an interface and the *wrong* IP would get us - * a "bind to device is unsupported" message. - * - * Instead we say "yes, we found a matching interface", and then - * allow the bind() call below to run. If that fails, we get a - * "Can't assign requested address" error, which is more informative. - */ - if (src_ipaddr && (src_ipaddr->af == i->ifa_addr->sa_family)) { - my_ipaddr.scope_id = scope_id; - bound = true; - break; - } - } - } - - freeifaddrs(list); - - if (!bound) { - /* - * IPv4: no link local addresses, - * and no bind to device. - */ - fr_strerror_printf_push("Bind to interface %s failed: Unable to match " - "interface with the given IP address.", interface); - return -1; - } - } else { - fr_strerror_printf_push("Bind to interface %s failed, unable to get list of interfaces: %s", - interface, fr_syserror(errno)); - return -1; - } - } -#endif - } /* else no interface was passed in */ - - /* - * Don't bind to an IP address if there's no src IP address. - */ - if (my_ipaddr.af == AF_UNSPEC) goto done; - - /* - * Set up sockaddr stuff. - */ - if (fr_ipaddr_to_sockaddr(&salocal, &salen, &my_ipaddr, my_port) < 0) return -1; - - ret = bind(sockfd, (struct sockaddr *) &salocal, salen); - if (ret < 0) { - fr_strerror_printf_push("Bind failed with source address %pV:%pV on interface %s: %s", - src_ipaddr ? fr_box_ipaddr(*src_ipaddr) : fr_box_strvalue("*"), - src_port ? fr_box_int16(*src_port) : fr_box_strvalue("*"), - interface ? interface : "*", - fr_syserror(errno)); - return ret; - } - - if (!src_port) goto done; - - /* - * FreeBSD jail issues. We bind to 0.0.0.0, but the - * kernel instead binds us to a 1.2.3.4. So once the - * socket is bound, ask it what it's IP address is. - * - * @todo - Uh... we don't update src_ipaddr with the new - * IP address. This means that we don't tell the caller - * what IP address we're bound to. That seems wrong. - */ - salen = sizeof(salocal); - memset(&salocal, 0, salen); - if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) { - fr_strerror_printf_push("Failed getting socket name: %s", fr_syserror(errno)); - return -1; - } - - if (fr_ipaddr_from_sockaddr(&my_ipaddr, &my_port, &salocal, salen) < 0) return -1; - *src_port = my_port; - -done: -#ifdef HAVE_CAPABILITY_H - /* - * Clear any errors we may have produced in the - * capabilities check. - */ - fr_strerror_clear(); -#endif - return 0; -} diff --git a/src/lib/util/socket.h b/src/lib/util/socket.h index 2a59f451a20..d05c9f19501 100644 --- a/src/lib/util/socket.h +++ b/src/lib/util/socket.h @@ -302,7 +302,7 @@ int fr_socket_client_unix(char const *path, bool async); int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async); -int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t const *src_ipaddr, +int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async); int fr_socket_wait_for_connect(int sockfd, fr_time_delta_t timeout); @@ -310,7 +310,7 @@ int fr_socket_server_udp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const int fr_socket_server_tcp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const *port_name, bool async); -int fr_socket_bind(int sockfd, fr_ipaddr_t const *ipaddr, uint16_t *port, char const *interface); +int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port); #ifdef __cplusplus } diff --git a/src/lib/util/udp_queue.c b/src/lib/util/udp_queue.c index 93a2861c7f7..7ab8736076e 100644 --- a/src/lib/util/udp_queue.c +++ b/src/lib/util/udp_queue.c @@ -95,9 +95,10 @@ static int _udp_queue_entry_free(fr_udp_queue_entry_t *entry) fr_udp_queue_t *fr_udp_queue_alloc(TALLOC_CTX *ctx, fr_udp_queue_config_t const *config, fr_event_list_t *el, fr_udp_queue_resume_t resume) { - fr_udp_queue_t *uq; - int fd; - uint16_t port = config->port; + fr_udp_queue_t *uq; + int fd; + fr_ipaddr_t ipaddr = config->ipaddr; + uint16_t port = config->port; /* * Open the socket. @@ -123,7 +124,7 @@ fr_udp_queue_t *fr_udp_queue_alloc(TALLOC_CTX *ctx, fr_udp_queue_config_t const * Bind to the given interface. */ if (config->interface && - (fr_socket_bind(fd, &config->ipaddr, &port, config->interface) < 0)) goto error; + (fr_socket_bind(fd, config->interface, &ipaddr, &port) < 0)) goto error; #ifdef SO_SNDBUF /* diff --git a/src/listen/bfd/proto_bfd_udp.c b/src/listen/bfd/proto_bfd_udp.c index 5b182fcae26..2022335201b 100644 --- a/src/listen/bfd/proto_bfd_udp.c +++ b/src/listen/bfd/proto_bfd_udp.c @@ -248,6 +248,7 @@ static int mod_open(fr_listen_t *li) proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t); int sockfd; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); @@ -308,7 +309,7 @@ static int mod_open(fr_listen_t *li) /* * @todo - cache ifindex for use with udpfromto. */ - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/listen/dhcpv4/proto_dhcpv4_udp.c b/src/listen/dhcpv4/proto_dhcpv4_udp.c index 4ec35d45247..0b5b8b6bc24 100644 --- a/src/listen/dhcpv4/proto_dhcpv4_udp.c +++ b/src/listen/dhcpv4/proto_dhcpv4_udp.c @@ -502,6 +502,7 @@ static int mod_open(fr_listen_t *li) proto_dhcpv4_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_dhcpv4_udp_thread_t); int sockfd, rcode; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); @@ -548,7 +549,7 @@ static int mod_open(fr_listen_t *li) } } - rcode = fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface); + rcode = fr_socket_bind(sockfd, inst->interface, &ipaddr, &port); if (rcode < 0) { close(sockfd); PERROR("Failed binding socket"); diff --git a/src/listen/dhcpv6/proto_dhcpv6_udp.c b/src/listen/dhcpv6/proto_dhcpv6_udp.c index 45ac1bf31fe..8889561b579 100644 --- a/src/listen/dhcpv6/proto_dhcpv6_udp.c +++ b/src/listen/dhcpv6/proto_dhcpv6_udp.c @@ -283,6 +283,7 @@ static int mod_open(fr_listen_t *li) proto_dhcpv6_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_dhcpv6_udp_thread_t); int sockfd, rcode; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); @@ -323,7 +324,7 @@ static int mod_open(fr_listen_t *li) * SUID up is really only needed if interface is set, OR port <1024. */ rad_suid_up(); - rcode = fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface); + rcode = fr_socket_bind(sockfd, inst->interface, &ipaddr, &port); rad_suid_down(); if (rcode < 0) { PERROR("Failed binding socket"); diff --git a/src/listen/dns/proto_dns_udp.c b/src/listen/dns/proto_dns_udp.c index 2f0bc52eeab..527abb50bf8 100644 --- a/src/listen/dns/proto_dns_udp.c +++ b/src/listen/dns/proto_dns_udp.c @@ -258,6 +258,7 @@ static int mod_open(fr_listen_t *li) proto_dns_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_dns_udp_thread_t); int sockfd, rcode; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, "domain", true); @@ -287,7 +288,7 @@ static int mod_open(fr_listen_t *li) * SUID up is really only needed if interface is set, OR port <1024. */ rad_suid_up(); - rcode = fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface); + rcode = fr_socket_bind(sockfd, inst->interface, &ipaddr, &port); rad_suid_down(); if (rcode < 0) { PERROR("Failed binding socket"); diff --git a/src/listen/radius/#proto_radius_tcp.c# b/src/listen/radius/#proto_radius_tcp.c# index 632140e2964..8da17bde0d1 100644 --- a/src/listen/radius/#proto_radius_tcp.c# +++ b/src/listen/radius/#proto_radius_tcp.c# @@ -303,7 +303,7 @@ static int mod_open(fr_listen_t *li) (void) fr_nonblock(sockfd); - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &inst->ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/listen/radius/proto_radius_tcp.c b/src/listen/radius/proto_radius_tcp.c index 4230d8ab0e0..60037c9dffe 100644 --- a/src/listen/radius/proto_radius_tcp.c +++ b/src/listen/radius/proto_radius_tcp.c @@ -290,6 +290,7 @@ static int mod_open(fr_listen_t *li) proto_radius_tcp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_radius_tcp_thread_t); int sockfd; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; fr_assert(!thread->connection); @@ -303,7 +304,7 @@ static int mod_open(fr_listen_t *li) (void) fr_nonblock(sockfd); - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/listen/radius/proto_radius_udp.c b/src/listen/radius/proto_radius_udp.c index 5fc26207132..803678a8c31 100644 --- a/src/listen/radius/proto_radius_udp.c +++ b/src/listen/radius/proto_radius_udp.c @@ -293,6 +293,7 @@ static int mod_open(fr_listen_t *li) proto_radius_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_radius_udp_thread_t); int sockfd; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); @@ -339,7 +340,7 @@ static int mod_open(fr_listen_t *li) } #endif - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/listen/tacacs/proto_tacacs_tcp.c b/src/listen/tacacs/proto_tacacs_tcp.c index 0f6ec7ab716..5b9da28b289 100644 --- a/src/listen/tacacs/proto_tacacs_tcp.c +++ b/src/listen/tacacs/proto_tacacs_tcp.c @@ -302,6 +302,7 @@ static int mod_open(fr_listen_t *li) proto_tacacs_tcp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_tacacs_tcp_thread_t); int sockfd; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; fr_assert(!thread->connection); @@ -315,7 +316,7 @@ static int mod_open(fr_listen_t *li) (void) fr_nonblock(sockfd); - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/listen/vmps/proto_vmps_udp.c b/src/listen/vmps/proto_vmps_udp.c index d550080147d..60bce56cf50 100644 --- a/src/listen/vmps/proto_vmps_udp.c +++ b/src/listen/vmps/proto_vmps_udp.c @@ -285,6 +285,7 @@ static int mod_open(fr_listen_t *li) proto_vmps_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_vmps_udp_thread_t); int sockfd; + fr_ipaddr_t ipaddr = inst->ipaddr; uint16_t port = inst->port; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); @@ -309,7 +310,7 @@ static int mod_open(fr_listen_t *li) } } - if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { + if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; diff --git a/src/modules/rlm_icmp/rlm_icmp.c b/src/modules/rlm_icmp/rlm_icmp.c index 568ced49722..04423cd6e0e 100644 --- a/src/modules/rlm_icmp/rlm_icmp.c +++ b/src/modules/rlm_icmp/rlm_icmp.c @@ -468,7 +468,7 @@ static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx) /* * Only bind if we have a src and interface. */ - if (src && inst->interface && (fr_socket_bind(fd, src, NULL, inst->interface) < 0)) { + if (src && inst->interface && (fr_socket_bind(fd, inst->interface, src, NULL) < 0)) { close(fd); return -1; } diff --git a/src/tests/util/radius1_test.c b/src/tests/util/radius1_test.c index a65a981df4e..8c7c6901ec9 100644 --- a/src/tests/util/radius1_test.c +++ b/src/tests/util/radius1_test.c @@ -247,7 +247,7 @@ static void master_process(TALLOC_CTX *ctx) fr_exit_now(EXIT_FAILURE); } - if (fr_socket_bind(sockfd, &my_ipaddr, &my_port, NULL) < 0) { + if (fr_socket_bind(sockfd, NULL, &my_ipaddr, &my_port) < 0) { fr_perror("radius_test: Failed binding to socket"); fr_exit_now(EXIT_FAILURE); } diff --git a/src/tests/util/radius_schedule_test.c b/src/tests/util/radius_schedule_test.c index 64e3b357bc5..de0c92bfd6c 100644 --- a/src/tests/util/radius_schedule_test.c +++ b/src/tests/util/radius_schedule_test.c @@ -119,7 +119,7 @@ static int test_open(void *ctx, UNUSED void const *master_ctx) fr_exit_now(EXIT_FAILURE); } - if (fr_socket_bind(io_ctx->sockfd, &io_ctx->ipaddr, &io_ctx->port, NULL) < 0) { + if (fr_socket_bind(io_ctx->sockfd, NULL, &io_ctx->ipaddr, &io_ctx->port) < 0) { fr_perror("radius_test: Failed binding to socket"); fr_exit_now(EXIT_FAILURE); }