diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index b35de4dad6..5b76948c06 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1171,6 +1171,24 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng return NULL; } +void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len) { + struct cmsghdr *cmsg; + + assert(mh); + assert(buf); + assert(buf_len > 0); + + /* This is similar to cmsg_find_data(), but copy the found data to buf. This should be typically used + * when reading possibly unaligned data such as timestamp, as time_t is 64bit and size_t is 32bit on + * RISCV32. See issue #27241. */ + + cmsg = cmsg_find(mh, level, type, CMSG_LEN(buf_len)); + if (!cmsg) + return NULL; + + return memcpy_safe(buf, CMSG_DATA(cmsg), buf_len); +} + int socket_ioctl_fd(void) { int fd; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index d6d63a4f33..b323b1b99f 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -189,11 +189,16 @@ int flush_accept(int fd); }) struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length); +void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len); /* Type-safe, dereferencing version of cmsg_find() */ #define CMSG_FIND_DATA(mh, level, type, ctype) \ CMSG_TYPED_DATA(cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))), ctype) +/* Type-safe version of cmsg_find_and_copy_data() */ +#define CMSG_FIND_AND_COPY_DATA(mh, level, type, ctype) \ + (ctype*) cmsg_find_and_copy_data(mh, level, type, &(ctype){}, sizeof(ctype)) + /* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr" * structures. */