X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fnetwork%2Frecvmsg.c;h=03641625e8af79aea0aed96d6daa7d549a2c7efc;hb=63402be229facae2d0de9c5943a6ed25246fd021;hp=4f526659183defd2405ed6961b8ccca9e8ded1f5;hpb=feee98903cd8119d9a3db62589246a940f44a9f5;p=musl diff --git a/src/network/recvmsg.c b/src/network/recvmsg.c index 4f526659..03641625 100644 --- a/src/network/recvmsg.c +++ b/src/network/recvmsg.c @@ -1,11 +1,56 @@ #include #include +#include +#include +#include #include "syscall.h" -#include "libc.h" + +hidden void __convert_scm_timestamps(struct msghdr *, socklen_t); + +void __convert_scm_timestamps(struct msghdr *msg, socklen_t csize) +{ + if (SCM_TIMESTAMP == SCM_TIMESTAMP_OLD) return; + if (!msg->msg_control || !msg->msg_controllen) return; + + struct cmsghdr *cmsg, *last=0; + long tmp; + long long tvts[2]; + int type = 0; + + for (cmsg=CMSG_FIRSTHDR(msg); cmsg; cmsg=CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level==SOL_SOCKET) switch (cmsg->cmsg_type) { + case SCM_TIMESTAMP_OLD: + if (type) break; + type = SCM_TIMESTAMP; + goto common; + case SCM_TIMESTAMPNS_OLD: + type = SCM_TIMESTAMPNS; + common: + memcpy(&tmp, CMSG_DATA(cmsg), sizeof tmp); + tvts[0] = tmp; + memcpy(&tmp, CMSG_DATA(cmsg) + sizeof tmp, sizeof tmp); + tvts[1] = tmp; + break; + } + last = cmsg; + } + if (!last || !type) return; + if (CMSG_SPACE(sizeof tvts) > csize-msg->msg_controllen) { + msg->msg_flags |= MSG_CTRUNC; + return; + } + msg->msg_controllen += CMSG_SPACE(sizeof tvts); + cmsg = CMSG_NXTHDR(msg, last); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = type; + cmsg->cmsg_len = CMSG_LEN(sizeof tvts); + memcpy(CMSG_DATA(cmsg), &tvts, sizeof tvts); +} ssize_t recvmsg(int fd, struct msghdr *msg, int flags) { ssize_t r; + socklen_t orig_controllen = msg->msg_controllen; #if LONG_MAX > INT_MAX struct msghdr h, *orig = msg; if (msg) { @@ -15,6 +60,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) } #endif r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0); + if (r >= 0) __convert_scm_timestamps(msg, orig_controllen); #if LONG_MAX > INT_MAX if (orig) *orig = h; #endif