aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-02-03 11:17:31 -0800
committerDavid S. Miller <davem@davemloft.net>2019-02-03 11:17:31 -0800
commita98dc6aee784a5daf84a4781dcf02feab9ad5999 (patch)
tree0d0f94364c0828ae5b6dc99b7b374fd120b2e6e5 /net/ipv4
parentcxgb4/cxgb4vf: Program hash region for {t4/t4vf}_change_mac() (diff)
parentsock: Add SO_RCVTIMEO_NEW and SO_SNDTIMEO_NEW (diff)
downloadlinux-dev-a98dc6aee784a5daf84a4781dcf02feab9ad5999.tar.xz
linux-dev-a98dc6aee784a5daf84a4781dcf02feab9ad5999.zip
Merge branch 'net-y2038-safe-socket-timestamps'
Deepa Dinamani says: ==================== net: y2038-safe socket timestamps The series introduces new socket timestamps that are y2038 safe. The time data types used for the existing socket timestamp options: SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTAMPING are not y2038 safe. The series introduces SO_TIMESTAMP_NEW, SO_TIMESTAMPNS_NEW and SO_TIMESTAMPING_NEW to replace these. These new timestamps can be used on all architectures. The alternative considered was to extend the sys_setsockopt() by using the flags. We did not receive any strong opinions about either of the approaches. Hence, this was chosen, as glibc folks preferred this. The series does not deal with updating the internal kernel socket calls like rxrpc to make them y2038 safe. This will be dealt with separately. Note that the timestamps behavior already does not match the man page specific behavior: SIOCGSTAMP This ioctl should only be used if the socket option SO_TIMESTAMP is not set on the socket. Otherwise, it returns the timestamp of the last packet that was received while SO_TIMESTAMP was not set, or it fails if no such packet has been received, (i.e., ioctl(2) returns -1 with errno set to ENOENT). The recommendation is to update the man page to remove the above statement. The overview of the socket timestamp series is as below: 1. Delete asm specific socket.h when possible. 2. Support SO/SCM_TIMESTAMP* options only in userspace. 3. Rename current SO/SCM_TIMESTAMP* to SO/SCM_TIMESTAMP*_OLD. 3. Alter socket options so that SOCK_RCVTSTAMPNS does not rely on SOCK_RCVTSTAMP. 4. Introduce y2038 safe types for socket timestamp. 5. Introduce new y2038 safe socket options SO/SCM_TIMESTAMP*_NEW. 6. Intorduce new y2038 safe socket timeout options. Changes since v4: * Fixed the typo in calling sock_get_timeout() Changes since v3: * Rebased onto net-next and fixups as per review comments * Merged the socket timeout series * Integrated Arnd's patch to simplify compat handling of timeout syscalls Changes since v2: * Removed extra functions to reduce diff churn as per code review Changes since v1: * Dropped the change to disentangle sock flags * Renamed sock_timeval to __kernel_sock_timeval * Updated a few comments * Added documentation changes ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6f8d292ad501..cab6b2f2f61d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1844,57 +1844,78 @@ out:
#endif
static void tcp_update_recv_tstamps(struct sk_buff *skb,
- struct scm_timestamping *tss)
+ struct scm_timestamping_internal *tss)
{
if (skb->tstamp)
- tss->ts[0] = ktime_to_timespec(skb->tstamp);
+ tss->ts[0] = ktime_to_timespec64(skb->tstamp);
else
- tss->ts[0] = (struct timespec) {0};
+ tss->ts[0] = (struct timespec64) {0};
if (skb_hwtstamps(skb)->hwtstamp)
- tss->ts[2] = ktime_to_timespec(skb_hwtstamps(skb)->hwtstamp);
+ tss->ts[2] = ktime_to_timespec64(skb_hwtstamps(skb)->hwtstamp);
else
- tss->ts[2] = (struct timespec) {0};
+ tss->ts[2] = (struct timespec64) {0};
}
/* Similar to __sock_recv_timestamp, but does not require an skb */
static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
- struct scm_timestamping *tss)
+ struct scm_timestamping_internal *tss)
{
- struct timeval tv;
+ int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
bool has_timestamping = false;
if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {
if (sock_flag(sk, SOCK_RCVTSTAMP)) {
if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
- put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
- sizeof(tss->ts[0]), &tss->ts[0]);
- } else {
- tv.tv_sec = tss->ts[0].tv_sec;
- tv.tv_usec = tss->ts[0].tv_nsec / 1000;
+ if (new_tstamp) {
+ struct __kernel_timespec kts = {tss->ts[0].tv_sec, tss->ts[0].tv_nsec};
+
+ put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
+ sizeof(kts), &kts);
+ } else {
+ struct timespec ts_old = timespec64_to_timespec(tss->ts[0]);
- put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
- sizeof(tv), &tv);
+ put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
+ sizeof(ts_old), &ts_old);
+ }
+ } else {
+ if (new_tstamp) {
+ struct __kernel_sock_timeval stv;
+
+ stv.tv_sec = tss->ts[0].tv_sec;
+ stv.tv_usec = tss->ts[0].tv_nsec / 1000;
+ put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
+ sizeof(stv), &stv);
+ } else {
+ struct __kernel_old_timeval tv;
+
+ tv.tv_sec = tss->ts[0].tv_sec;
+ tv.tv_usec = tss->ts[0].tv_nsec / 1000;
+ put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
+ sizeof(tv), &tv);
+ }
}
}
if (sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE)
has_timestamping = true;
else
- tss->ts[0] = (struct timespec) {0};
+ tss->ts[0] = (struct timespec64) {0};
}
if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) {
if (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)
has_timestamping = true;
else
- tss->ts[2] = (struct timespec) {0};
+ tss->ts[2] = (struct timespec64) {0};
}
if (has_timestamping) {
- tss->ts[1] = (struct timespec) {0};
- put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING,
- sizeof(*tss), tss);
+ tss->ts[1] = (struct timespec64) {0};
+ if (sock_flag(sk, SOCK_TSTAMP_NEW))
+ put_cmsg_scm_timestamping64(msg, tss);
+ else
+ put_cmsg_scm_timestamping(msg, tss);
}
}
@@ -1935,7 +1956,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
long timeo;
struct sk_buff *skb, *last;
u32 urg_hole = 0;
- struct scm_timestamping tss;
+ struct scm_timestamping_internal tss;
bool has_tss = false;
bool has_cmsg;