linux(4): Handle SO_TIMESTAMPNS socket option
The SO_TIMESTAMPNS enables or disables the receiving of the SCM_TIMESTAMPNS control message. The cmsg_data field is a struct timespec. To distinguish between SO_TIMESTAMP and SO_TIMESTAMPNS in the recvmsg() map the last one to the SO_BINTIME and convert bintime to the timespec. In the rest, implementation is identical to the SO_TIMESTAMP. MFC after: 2 weeks
This commit is contained in:
parent
0e26e54bdf
commit
71bc8bcf66
@ -77,6 +77,7 @@ struct linux_pemuldata {
|
||||
uint32_t ptrace_flags; /* used by ptrace(2) */
|
||||
uint32_t oom_score_adj; /* /proc/self/oom_score_adj */
|
||||
uint32_t so_timestamp; /* requested timeval */
|
||||
uint32_t so_timestampns; /* requested timespec */
|
||||
};
|
||||
|
||||
#define LINUX_PEM_XLOCK(p) sx_xlock(&(p)->pem_sx)
|
||||
|
@ -551,6 +551,9 @@ linux_to_bsd_so_sockopt(int opt)
|
||||
case LINUX_SO_TIMESTAMPO:
|
||||
case LINUX_SO_TIMESTAMPN:
|
||||
return (SO_TIMESTAMP);
|
||||
case LINUX_SO_TIMESTAMPNSO:
|
||||
case LINUX_SO_TIMESTAMPNSN:
|
||||
return (SO_BINTIME);
|
||||
case LINUX_SO_ACCEPTCONN:
|
||||
return (SO_ACCEPTCONN);
|
||||
case LINUX_SO_PROTOCOL:
|
||||
@ -661,6 +664,8 @@ bsd_to_linux_cmsg_type(struct proc *p, int cmsg_type)
|
||||
return (LINUX_SCM_CREDENTIALS);
|
||||
case SCM_TIMESTAMP:
|
||||
return (pem->so_timestamp);
|
||||
case SCM_BINTIME:
|
||||
return (pem->so_timestampns);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
@ -1554,6 +1559,7 @@ recvmsg_scm_rights(struct thread *td, l_uint flags, socklen_t *datalen,
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
recvmsg_scm_creds(socklen_t *datalen, void **data, void **udata)
|
||||
{
|
||||
@ -1632,6 +1638,53 @@ _Static_assert(sizeof(struct timeval) == sizeof(l_timeval),
|
||||
"scm_timestamp sizeof l_timeval");
|
||||
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
|
||||
|
||||
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
|
||||
static int
|
||||
recvmsg_scm_timestampns(l_int msg_type, socklen_t *datalen, void **data,
|
||||
void **udata)
|
||||
{
|
||||
struct l_timespec64 ts64;
|
||||
struct l_timespec ts32;
|
||||
struct timespec ts;
|
||||
socklen_t len;
|
||||
void *buf;
|
||||
|
||||
if (msg_type == LINUX_SCM_TIMESTAMPNSO)
|
||||
len = sizeof(ts32);
|
||||
else
|
||||
len = sizeof(ts64);
|
||||
|
||||
buf = malloc(len, M_LINUX, M_WAITOK);
|
||||
bintime2timespec(*data, &ts);
|
||||
if (msg_type == LINUX_SCM_TIMESTAMPNSO) {
|
||||
ts32.tv_sec = ts.tv_sec;
|
||||
ts32.tv_nsec = ts.tv_nsec;
|
||||
memmove(buf, &ts32, len);
|
||||
} else {
|
||||
ts64.tv_sec = ts.tv_sec;
|
||||
ts64.tv_nsec = ts.tv_nsec;
|
||||
memmove(buf, &ts64, len);
|
||||
}
|
||||
*data = *udata = buf;
|
||||
*datalen = len;
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
static int
|
||||
recvmsg_scm_timestampns(l_int msg_type, socklen_t *datalen, void **data,
|
||||
void **udata)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
bintime2timespec(*data, &ts);
|
||||
memmove(*data, &ts, sizeof(struct timespec));
|
||||
*datalen = sizeof(struct timespec);
|
||||
return (0);
|
||||
}
|
||||
_Static_assert(sizeof(struct bintime) >= sizeof(struct timespec),
|
||||
"scm_timestampns sizeof timespec");
|
||||
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
|
||||
|
||||
static int
|
||||
linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
l_uint flags, struct msghdr *msg)
|
||||
@ -1755,6 +1808,11 @@ linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
&datalen, &data, &udata);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SCM_BINTIME:
|
||||
error = recvmsg_scm_timestampns(linux_cmsg->cmsg_type,
|
||||
&datalen, &data, &udata);
|
||||
break;
|
||||
}
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
@ -1960,6 +2018,10 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
|
||||
pem = pem_find(p);
|
||||
pem->so_timestamp = args->optname;
|
||||
break;
|
||||
case SO_BINTIME:
|
||||
pem = pem_find(p);
|
||||
pem->so_timestampns = args->optname;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -189,6 +189,8 @@ int linux_accept(struct thread *td, struct linux_accept_args *args);
|
||||
#endif
|
||||
#define LINUX_SO_TIMESTAMPO 29
|
||||
#define LINUX_SO_TIMESTAMPN 63
|
||||
#define LINUX_SO_TIMESTAMPNSO 35
|
||||
#define LINUX_SO_TIMESTAMPNSN 64
|
||||
#define LINUX_SO_ACCEPTCONN 30
|
||||
#define LINUX_SO_PEERSEC 31
|
||||
#define LINUX_SO_SNDBUFFORCE 32
|
||||
@ -203,6 +205,8 @@ int linux_accept(struct thread *td, struct linux_accept_args *args);
|
||||
#define LINUX_SCM_CREDENTIALS 0x02
|
||||
#define LINUX_SCM_TIMESTAMPO LINUX_SO_TIMESTAMPO
|
||||
#define LINUX_SCM_TIMESTAMPN LINUX_SO_TIMESTAMPN
|
||||
#define LINUX_SCM_TIMESTAMPNSO LINUX_SO_TIMESTAMPNSO
|
||||
#define LINUX_SCM_TIMESTAMPNSN LINUX_SO_TIMESTAMPNSN
|
||||
|
||||
/* Socket options */
|
||||
#define LINUX_IP_TOS 1
|
||||
|
Loading…
Reference in New Issue
Block a user