Miao Wang
2025-Jul-03 09:49 UTC
[syslinux] [PATCH tftp-hpa 0/2] Fix issues when tftpd is running on multi-homed servers.
When tftpd is running on servers with mulitple addresses, if the client is reaching the server via an address which is not prefered as a source address when the server is sending the replying packets, the communation will fail, since the client is recving packets from unexpected source address and rejecting them. This series contains to patches, the first of which fixes the feature test macros left out during modernize autoconf, and the second of which fixes the issue in myrecvfrom() which cannot reliably obtain the local address used to receive the request packets. Signed-off-by: Miao Wang <shankerwangmiao at gmail.com> --- Miao Wang (2): autoconf: add back feature macros about structs tftpd: determine recving socket address family using getsocksopt configure.ac | 17 +++++++++++++---- tftpd/recvfrom.c | 11 ++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) --- base-commit: 2c86ff58dcc003107b47f2d35aa0fdc4a3fd95e1 change-id: 20250703-myrecvfrom-e417379573e7 Best regards, -- Miao Wang <shankerwangmiao at gmail.com>
Miao Wang
2025-Jul-03 09:49 UTC
[syslinux] [PATCH tftp-hpa 1/2] autoconf: add back feature macros about structs
In commit fefaa2cc5c2a ("autoconf: modernize and modularize"), the following macros were left out: - HAVE_MSGHDR_MSG_CONTROL: for the availability of struct msghdr.msg_control; - HAVE_STRUCT_IN_PKTINFO: for the availability of struct in_pktinfo; - HAVE_STRUCT_ADDRINFO: for the availability of struct addrinfo; - HAVE_STRUCT_IN6_PKTINFO: for the availability of struct in6_pktinfo; myrecvfrom() is depending on these macros to select the correct procedure to obtain the local IP address used when receving packets. Without these macros, myrecvfrom() is unable to determin the local IP addrss used, and tftpd thus cannot sent replies to the client using the correct source address. This will cause issue when the server can be reached via more than one addresses, and the automatically selected source address is not the one that is used by the client to reach the tftp server. Fixes: fefaa2cc5c2a ("autoconf: modernize and modularize") --- configure.ac | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index deaa4fc9231257bfacb8cc627062cea5d5cebdcb..9a298c223d7df420c723821cfa54735aef8a981a 100644 --- a/configure.ac +++ b/configure.ac @@ -118,9 +118,15 @@ dnl Solaris 8 has [u]intmax_t but not strtoumax(). How utterly braindamaged. AC_CHECK_FUNCS(strtoumax) AC_CHECK_FUNCS(strtoull) -AC_CHECK_MEMBERS(struct msghdr.msg_control) -AC_CHECK_MEMBERS(struct in_pktinfo.ipi_addr) -AC_CHECK_MEMBERS(struct addrinfo.ai_addr) +AC_CHECK_MEMBERS(struct msghdr.msg_control, + [AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL, 1, [Define if struct msghdr has the msg_control field.])], + []) +AC_CHECK_MEMBERS(struct in_pktinfo.ipi_addr, + [AC_DEFINE(HAVE_STRUCT_IN_PKTINFO, 1, [Define if struct in_pktinfo is defined.])], + []) +AC_CHECK_MEMBERS(struct addrinfo.ai_addr, + [AC_DEFINE(HAVE_STRUCT_ADDRINFO, 1, [Define if struct addrinfo is defined.])], + []) AC_CHECK_DECLS([O_NONBLOCK, O_BINARY, O_TEXT]) AC_CHECK_DECLS([F_SETLK]) @@ -230,7 +236,10 @@ PA_ARG_DISABLED([ipv6], [AC_MSG_RESULT(disabled)], [AS_IF([test x"$ac_cv_member_struct_sockaddr_in6_sin6_addr$ac_cv_member_struct_addrinfo_ai_addr" = xyesyes], [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_IPV6, 1, [define if IPv6 support is enabled])], + AC_DEFINE(HAVE_IPV6, 1, [define if IPv6 support is enabled]) + AC_CHECK_MEMBERS([struct in6_pktinfo.ipi6_addr], + [AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO, 1, [define if IPv6 packet info is available])], + [])], [AC_MSG_RESULT(no) AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])])]) -- 2.49.0
Miao Wang
2025-Jul-03 09:49 UTC
[syslinux] [PATCH tftp-hpa 2/2] tftpd: determine recving socket address family using getsocksopt
Currently, in myrecvfrom(), the address family of socket s is determined by the address information pointed by from. However, from is assigned to point to a file-scope variable in tftpd.c, which is initialized to zero upon start. myrecvfrom() cannot thus determine the address family of s when serving the first client and can result in a wrong result when the address family of two consecutive requests are different. This commit explicitly obtain the address family of the recving socket using getsocksopt and fixes the above issue. Fixes: 28f22b6591c ("Add support for IPv6 in the server and client.") --- tftpd/recvfrom.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tftpd/recvfrom.c b/tftpd/recvfrom.c index 320678d1b132af0cdd7e1eb7640b7fbf7089f337..1b516b367536bc379b1a0a88edbc7ac61d2ad825 100644 --- a/tftpd/recvfrom.c +++ b/tftpd/recvfrom.c @@ -169,19 +169,24 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, #ifdef HAVE_STRUCT_IN6_PKTINFO struct in6_pktinfo pktinfo6; #endif + sa_family_t family; + + if ((n = getsockopt(s, SOL_SOCKET, SO_DOMAIN, &family, &(socklen_t){sizeof(family)})) < 0) { + return n; /* Error */ + } /* Try to enable getting the return address */ #ifdef IP_RECVDSTADDR - if (from->sa.sa_family == AF_INET) + if (family == AF_INET) setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)); #endif #ifdef IP_PKTINFO - if (from->sa.sa_family == AF_INET) + if (family == AF_INET) setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)); #endif #ifdef HAVE_IPV6 #ifdef IPV6_RECVPKTINFO - if (from->sa.sa_family == AF_INET6) + if (family == AF_INET6) setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); #endif #endif -- 2.49.0