diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/net/socket.c b/net/socket.c index 35dd7371752a..91d0c0254ffe 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -328,7 +328,7 @@ static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) | |||
328 | dentry->d_inode->i_ino); | 328 | dentry->d_inode->i_ino); |
329 | } | 329 | } |
330 | 330 | ||
331 | static struct dentry_operations sockfs_dentry_operations = { | 331 | static const struct dentry_operations sockfs_dentry_operations = { |
332 | .d_delete = sockfs_delete_dentry, | 332 | .d_delete = sockfs_delete_dentry, |
333 | .d_dname = sockfs_dname, | 333 | .d_dname = sockfs_dname, |
334 | }; | 334 | }; |
@@ -545,6 +545,18 @@ void sock_release(struct socket *sock) | |||
545 | sock->file = NULL; | 545 | sock->file = NULL; |
546 | } | 546 | } |
547 | 547 | ||
548 | int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, | ||
549 | union skb_shared_tx *shtx) | ||
550 | { | ||
551 | shtx->flags = 0; | ||
552 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
553 | shtx->hardware = 1; | ||
554 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
555 | shtx->software = 1; | ||
556 | return 0; | ||
557 | } | ||
558 | EXPORT_SYMBOL(sock_tx_timestamp); | ||
559 | |||
548 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | 560 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, |
549 | struct msghdr *msg, size_t size) | 561 | struct msghdr *msg, size_t size) |
550 | { | 562 | { |
@@ -595,33 +607,65 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
595 | return result; | 607 | return result; |
596 | } | 608 | } |
597 | 609 | ||
610 | static int ktime2ts(ktime_t kt, struct timespec *ts) | ||
611 | { | ||
612 | if (kt.tv64) { | ||
613 | *ts = ktime_to_timespec(kt); | ||
614 | return 1; | ||
615 | } else { | ||
616 | return 0; | ||
617 | } | ||
618 | } | ||
619 | |||
598 | /* | 620 | /* |
599 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) | 621 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) |
600 | */ | 622 | */ |
601 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | 623 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, |
602 | struct sk_buff *skb) | 624 | struct sk_buff *skb) |
603 | { | 625 | { |
604 | ktime_t kt = skb->tstamp; | 626 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
605 | 627 | struct timespec ts[3]; | |
606 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { | 628 | int empty = 1; |
607 | struct timeval tv; | 629 | struct skb_shared_hwtstamps *shhwtstamps = |
608 | /* Race occurred between timestamp enabling and packet | 630 | skb_hwtstamps(skb); |
609 | receiving. Fill in the current time for now. */ | 631 | |
610 | if (kt.tv64 == 0) | 632 | /* Race occurred between timestamp enabling and packet |
611 | kt = ktime_get_real(); | 633 | receiving. Fill in the current time for now. */ |
612 | skb->tstamp = kt; | 634 | if (need_software_tstamp && skb->tstamp.tv64 == 0) |
613 | tv = ktime_to_timeval(kt); | 635 | __net_timestamp(skb); |
614 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv); | 636 | |
615 | } else { | 637 | if (need_software_tstamp) { |
616 | struct timespec ts; | 638 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { |
617 | /* Race occurred between timestamp enabling and packet | 639 | struct timeval tv; |
618 | receiving. Fill in the current time for now. */ | 640 | skb_get_timestamp(skb, &tv); |
619 | if (kt.tv64 == 0) | 641 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
620 | kt = ktime_get_real(); | 642 | sizeof(tv), &tv); |
621 | skb->tstamp = kt; | 643 | } else { |
622 | ts = ktime_to_timespec(kt); | 644 | struct timespec ts; |
623 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts); | 645 | skb_get_timestampns(skb, &ts); |
646 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | ||
647 | sizeof(ts), &ts); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | |||
652 | memset(ts, 0, sizeof(ts)); | ||
653 | if (skb->tstamp.tv64 && | ||
654 | sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) { | ||
655 | skb_get_timestampns(skb, ts + 0); | ||
656 | empty = 0; | ||
624 | } | 657 | } |
658 | if (shhwtstamps) { | ||
659 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && | ||
660 | ktime2ts(shhwtstamps->syststamp, ts + 1)) | ||
661 | empty = 0; | ||
662 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && | ||
663 | ktime2ts(shhwtstamps->hwtstamp, ts + 2)) | ||
664 | empty = 0; | ||
665 | } | ||
666 | if (!empty) | ||
667 | put_cmsg(msg, SOL_SOCKET, | ||
668 | SCM_TIMESTAMPING, sizeof(ts), &ts); | ||
625 | } | 669 | } |
626 | 670 | ||
627 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 671 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
@@ -1030,6 +1074,13 @@ static int sock_fasync(int fd, struct file *filp, int on) | |||
1030 | 1074 | ||
1031 | lock_sock(sk); | 1075 | lock_sock(sk); |
1032 | 1076 | ||
1077 | spin_lock(&filp->f_lock); | ||
1078 | if (on) | ||
1079 | filp->f_flags |= FASYNC; | ||
1080 | else | ||
1081 | filp->f_flags &= ~FASYNC; | ||
1082 | spin_unlock(&filp->f_lock); | ||
1083 | |||
1033 | prev = &(sock->fasync_list); | 1084 | prev = &(sock->fasync_list); |
1034 | 1085 | ||
1035 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) | 1086 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) |
@@ -1485,8 +1536,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1485 | fd_install(newfd, newfile); | 1536 | fd_install(newfd, newfile); |
1486 | err = newfd; | 1537 | err = newfd; |
1487 | 1538 | ||
1488 | security_socket_post_accept(sock, newsock); | ||
1489 | |||
1490 | out_put: | 1539 | out_put: |
1491 | fput_light(sock->file, fput_needed); | 1540 | fput_light(sock->file, fput_needed); |
1492 | out: | 1541 | out: |