]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
1 | #include <sys/socket.h> |
2 | #include <limits.h> | |
575e1579 DG |
3 | #include <time.h> |
4 | #include <sys/time.h> | |
5 | #include <string.h> | |
320054e8 DG |
6 | #include "syscall.h" |
7 | ||
575e1579 DG |
8 | hidden void __convert_scm_timestamps(struct msghdr *, socklen_t); |
9 | ||
10 | void __convert_scm_timestamps(struct msghdr *msg, socklen_t csize) | |
11 | { | |
12 | if (SCM_TIMESTAMP == SCM_TIMESTAMP_OLD) return; | |
13 | if (!msg->msg_control || !msg->msg_controllen) return; | |
14 | ||
15 | struct cmsghdr *cmsg, *last=0; | |
16 | long tmp; | |
17 | long long tvts[2]; | |
18 | int type = 0; | |
19 | ||
20 | for (cmsg=CMSG_FIRSTHDR(msg); cmsg; cmsg=CMSG_NXTHDR(msg, cmsg)) { | |
21 | if (cmsg->cmsg_level==SOL_SOCKET) switch (cmsg->cmsg_type) { | |
22 | case SCM_TIMESTAMP_OLD: | |
23 | if (type) break; | |
24 | type = SCM_TIMESTAMP; | |
25 | goto common; | |
26 | case SCM_TIMESTAMPNS_OLD: | |
27 | type = SCM_TIMESTAMPNS; | |
28 | common: | |
29 | memcpy(&tmp, CMSG_DATA(cmsg), sizeof tmp); | |
30 | tvts[0] = tmp; | |
31 | memcpy(&tmp, CMSG_DATA(cmsg) + sizeof tmp, sizeof tmp); | |
32 | tvts[1] = tmp; | |
33 | break; | |
34 | } | |
35 | last = cmsg; | |
36 | } | |
37 | if (!last || !type) return; | |
38 | if (CMSG_SPACE(sizeof tvts) > csize-msg->msg_controllen) { | |
39 | msg->msg_flags |= MSG_CTRUNC; | |
40 | return; | |
41 | } | |
42 | msg->msg_controllen += CMSG_SPACE(sizeof tvts); | |
43 | cmsg = CMSG_NXTHDR(msg, last); | |
44 | cmsg->cmsg_level = SOL_SOCKET; | |
45 | cmsg->cmsg_type = type; | |
46 | cmsg->cmsg_len = CMSG_LEN(sizeof tvts); | |
47 | memcpy(CMSG_DATA(cmsg), &tvts, sizeof tvts); | |
48 | } | |
49 | ||
320054e8 DG |
50 | ssize_t recvmsg(int fd, struct msghdr *msg, int flags) |
51 | { | |
52 | ssize_t r; | |
575e1579 | 53 | socklen_t orig_controllen = msg->msg_controllen; |
320054e8 DG |
54 | #if LONG_MAX > INT_MAX |
55 | struct msghdr h, *orig = msg; | |
56 | if (msg) { | |
57 | h = *msg; | |
58 | h.__pad1 = h.__pad2 = 0; | |
59 | msg = &h; | |
60 | } | |
61 | #endif | |
62 | r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0); | |
575e1579 | 63 | if (r >= 0) __convert_scm_timestamps(msg, orig_controllen); |
320054e8 DG |
64 | #if LONG_MAX > INT_MAX |
65 | if (orig) *orig = h; | |
66 | #endif | |
67 | return r; | |
68 | } |