diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2009-02-12 00:03:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 01:43:35 -0500 |
commit | 20d4947353be60e909e6b1a79d241457edd6833f (patch) | |
tree | 939ced518fc52e57df9ee9efb0cd14b6e26a3bc4 /net/compat.c | |
parent | ac45f602ee3d1b6f326f68bc0c2591ceebf05ba4 (diff) |
net: socket infrastructure for SO_TIMESTAMPING
The overlap with the old SO_TIMESTAMP[NS] options is handled so
that time stamping in software (net_enable_timestamp()) is
enabled when SO_TIMESTAMP[NS] and/or SO_TIMESTAMPING_RX_SOFTWARE
is set. It's disabled if all of these are off.
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/compat.c')
-rw-r--r-- | net/compat.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/net/compat.c b/net/compat.c index a3a2ba0fac08..8d739053afe4 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -216,7 +216,7 @@ Efault: | |||
216 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) | 216 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) |
217 | { | 217 | { |
218 | struct compat_timeval ctv; | 218 | struct compat_timeval ctv; |
219 | struct compat_timespec cts; | 219 | struct compat_timespec cts[3]; |
220 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; | 220 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; |
221 | struct compat_cmsghdr cmhdr; | 221 | struct compat_cmsghdr cmhdr; |
222 | int cmlen; | 222 | int cmlen; |
@@ -233,12 +233,17 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat | |||
233 | data = &ctv; | 233 | data = &ctv; |
234 | len = sizeof(ctv); | 234 | len = sizeof(ctv); |
235 | } | 235 | } |
236 | if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS) { | 236 | if (level == SOL_SOCKET && |
237 | (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { | ||
238 | int count = type == SCM_TIMESTAMPNS ? 1 : 3; | ||
239 | int i; | ||
237 | struct timespec *ts = (struct timespec *)data; | 240 | struct timespec *ts = (struct timespec *)data; |
238 | cts.tv_sec = ts->tv_sec; | 241 | for (i = 0; i < count; i++) { |
239 | cts.tv_nsec = ts->tv_nsec; | 242 | cts[i].tv_sec = ts[i].tv_sec; |
243 | cts[i].tv_nsec = ts[i].tv_nsec; | ||
244 | } | ||
240 | data = &cts; | 245 | data = &cts; |
241 | len = sizeof(cts); | 246 | len = sizeof(cts[0]) * count; |
242 | } | 247 | } |
243 | 248 | ||
244 | cmlen = CMSG_COMPAT_LEN(len); | 249 | cmlen = CMSG_COMPAT_LEN(len); |
@@ -455,7 +460,7 @@ int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | |||
455 | struct timeval tv; | 460 | struct timeval tv; |
456 | 461 | ||
457 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 462 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
458 | sock_enable_timestamp(sk); | 463 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
459 | tv = ktime_to_timeval(sk->sk_stamp); | 464 | tv = ktime_to_timeval(sk->sk_stamp); |
460 | if (tv.tv_sec == -1) | 465 | if (tv.tv_sec == -1) |
461 | return err; | 466 | return err; |
@@ -479,7 +484,7 @@ int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *usersta | |||
479 | struct timespec ts; | 484 | struct timespec ts; |
480 | 485 | ||
481 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 486 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
482 | sock_enable_timestamp(sk); | 487 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
483 | ts = ktime_to_timespec(sk->sk_stamp); | 488 | ts = ktime_to_timespec(sk->sk_stamp); |
484 | if (ts.tv_sec == -1) | 489 | if (ts.tv_sec == -1) |
485 | return err; | 490 | return err; |