#define SO_PEERSEC 30
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 19
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* __ASM_AVR32_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_IA64_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_M32R_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_SNDBUFFORCE 31
#define SO_RCVBUFFORCE 33
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#ifdef __KERNEL__
#define SO_PEERCRED 0x4011
#define SO_TIMESTAMP 0x4012
#define SCM_TIMESTAMP SO_TIMESTAMP
+#define SO_TIMESTAMPNS 0x4013
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x4016
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_POWERPC_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* __ASM_SH_SOCKET_H */
#define SO_PEERSEC 0x001e
#define SO_PASSSEC 0x001f
+#define SO_TIMESTAMPNS 0x0021
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_PEERSEC 0x001e
#define SO_PASSSEC 0x001f
+#define SO_TIMESTAMPNS 0x0021
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* __V850_SOCKET_H__ */
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _ASM_SOCKET_H */
#define SO_ACCEPTCONN 30
#define SO_PEERSEC 31
#define SO_PASSSEC 34
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#endif /* _XTENSA_SOCKET_H */
SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
SOCK_DBG, /* %SO_DEBUG setting */
SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
+ SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */
SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
};
return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
}
+extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
+
static __inline__ void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
{
ktime_t kt = skb->tstamp;
- if (sock_flag(sk, SOCK_RCVTSTAMP)) {
- struct timeval tv;
- /* Race occurred between timestamp enabling and packet
- receiving. Fill in the current time for now. */
- if (kt.tv64 == 0)
- kt = ktime_get_real();
- skb->tstamp = kt;
- tv = ktime_to_timeval(kt);
- put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(tv), &tv);
- } else
+ if (sock_flag(sk, SOCK_RCVTSTAMP))
+ __sock_recv_timestamp(msg, sk, skb);
+ else
sk->sk_stamp = kt;
}
int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
{
struct compat_timeval ctv;
+ struct compat_timespec cts;
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
struct compat_cmsghdr cmhdr;
int cmlen;
ctv.tv_sec = tv->tv_sec;
ctv.tv_usec = tv->tv_usec;
data = &ctv;
- len = sizeof(struct compat_timeval);
+ len = sizeof(ctv);
+ }
+ if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) {
+ struct timespec *ts = (struct timespec *)data;
+ cts.tv_sec = ts->tv_sec;
+ cts.tv_nsec = ts->tv_nsec;
+ data = &cts;
+ len = sizeof(cts);
}
cmlen = CMSG_COMPAT_LEN(len);
break;
case SO_TIMESTAMP:
+ case SO_TIMESTAMPNS:
if (valbool) {
+ if (optname == SO_TIMESTAMP)
+ sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
+ else
+ sock_set_flag(sk, SOCK_RCVTSTAMPNS);
sock_set_flag(sk, SOCK_RCVTSTAMP);
sock_enable_timestamp(sk);
- } else
+ } else {
sock_reset_flag(sk, SOCK_RCVTSTAMP);
+ sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
+ }
break;
case SO_RCVLOWAT:
break;
case SO_TIMESTAMP:
- v.val = sock_flag(sk, SOCK_RCVTSTAMP);
+ v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
+ !sock_flag(sk, SOCK_RCVTSTAMPNS);
+ break;
+
+ case SO_TIMESTAMPNS:
+ v.val = sock_flag(sk, SOCK_RCVTSTAMPNS);
break;
case SO_RCVTIMEO:
return result;
}
+/*
+ * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
+ */
+void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb)
+{
+ ktime_t kt = skb->tstamp;
+
+ if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
+ struct timeval tv;
+ /* Race occurred between timestamp enabling and packet
+ receiving. Fill in the current time for now. */
+ if (kt.tv64 == 0)
+ kt = ktime_get_real();
+ skb->tstamp = kt;
+ tv = ktime_to_timeval(kt);
+ put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
+ } else {
+ struct timespec ts;
+ /* Race occurred between timestamp enabling and packet
+ receiving. Fill in the current time for now. */
+ if (kt.tv64 == 0)
+ kt = ktime_get_real();
+ skb->tstamp = kt;
+ ts = ktime_to_timespec(kt);
+ put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
+ }
+}
+
static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{