]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjproject: Fix DTLS client check failing on some platforms
authorAlbrecht Oster <albrecht@oster.online>
Thu, 10 Apr 2025 21:54:00 +0000 (23:54 +0200)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Mon, 21 Apr 2025 14:46:02 +0000 (14:46 +0000)
Certain platforms (mainly BSD derivatives) have an additional length
field in `sockaddr_in6` and `sockaddr_in`.
`ast_sockaddr_from_pj_sockaddr()` does not take this field into account
when copying over values from the `pj_sockaddr` into the `ast_sockaddr`.
The resulting `ast_sockaddr` will have an uninitialized value for
`sin6_len`/`sin_len` while the other `ast_sockaddr` (not converted from
a `pj_sockaddr`) to check against in `ast_sockaddr_pj_sockaddr_cmp()`
has the correct length value set.

This has the effect that `ast_sockaddr_cmp()` will always indicate
an address mismatch, because it does a bitwise comparison, and all DTLS
packets are dropped even if addresses and ports match.

`ast_sockaddr_from_pj_sockaddr()` now checks whether the length fields
are available on the current platform and sets the values accordingly.

Resolves: #505

configure
configure.ac
include/asterisk/autoconfig.h.in
res/res_pjproject.c

index 979c6d6454ef0826327c300563f2694e453dba54..d35e13c1d56d7158e688b29c496f345fac9c81d2 100755 (executable)
--- a/configure
+++ b/configure
@@ -28233,6 +28233,25 @@ printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIMESPEC 1" >>confdefs.h
 stat_nsec_found=yes
 fi
 
+ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" "#include <netinet/in.h>
+"
+if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1" >>confdefs.h
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "#include <netinet/in.h>
+"
+if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1" >>confdefs.h
+
+
+fi
+
 
 if test "${stat_nsec_found}" != yes; then
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot determine nanosecond field of struct stat" >&5
index 8c9ade2746ea04fce6e9ecec340740e87412a805..2a16142b98b4548a13f6f905240b414c6de7774d 100644 (file)
@@ -853,6 +853,7 @@ AC_C_VOLATILE
 AC_CHECK_TYPES([ptrdiff_t])
 stat_nsec_found=no
 AC_CHECK_MEMBERS([struct stat.st_mtim, struct stat.st_mtimensec, struct stat.st_mtimespec], [stat_nsec_found=yes], [], [[#include <sys/stat.h>]])
+AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_len, struct sockaddr_in.sin_len], [], [], [[#include <netinet/in.h>]])
 
 if test "${stat_nsec_found}" != yes; then
        AC_MSG_WARN(Cannot determine nanosecond field of struct stat)
index e52cd6eecb8f83eac86602ec8df66a0a8d2e7d08..1df046852d349b2223951e282fc67ff5d7b3bd56 100644 (file)
 /* Define to 1 if 'ifr_ifru.ifru_hwaddr' is a member of 'struct ifreq'. */
 #undef HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR
 
+/* Define to 1 if 'sin6_len' is a member of 'struct sockaddr_in6'. */
+#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
+
+/* Define to 1 if 'sin_len' is a member of 'struct sockaddr_in'. */
+#undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+
 /* Define to 1 if 'uid' is a member of 'struct sockpeercred'. */
 #undef HAVE_STRUCT_SOCKPEERCRED_UID
 
index 0feb1bbda428c4113367f76dc10c3dda21f465c4..80ba7e1828c5fa40ebedb3c783d9e794f0215a27 100644 (file)
@@ -560,6 +560,9 @@ int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *
 {
        if (pjaddr->addr.sa_family == pj_AF_INET()) {
                struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
+#if defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
+               sin->sin_len = sizeof(struct sockaddr_in);
+#endif
                sin->sin_family = AF_INET;
 #if defined(HAVE_PJPROJECT_BUNDLED) && !defined(HAVE_PJPROJECT_BUNDLED_OOT)
                sin->sin_addr = pjaddr->ipv4.sin_addr;
@@ -571,6 +574,9 @@ int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *
                addr->len = sizeof(struct sockaddr_in);
        } else if (pjaddr->addr.sa_family == pj_AF_INET6()) {
                struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;
+#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN)
+               sin->sin6_len = sizeof(struct sockaddr_in6);
+#endif
                sin->sin6_family   = AF_INET6;
                sin->sin6_port     = pjaddr->ipv6.sin6_port;
                sin->sin6_flowinfo = pjaddr->ipv6.sin6_flowinfo;