diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 33b7dffa7732..c5376c725503 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #include <linux/poll.h> | 86 | #include <linux/poll.h> |
87 | #include <linux/netfilter_ipv4.h> | 87 | #include <linux/netfilter_ipv4.h> |
88 | #include <linux/random.h> | 88 | #include <linux/random.h> |
89 | #include <linux/slab.h> | ||
89 | 90 | ||
90 | #include <asm/uaccess.h> | 91 | #include <asm/uaccess.h> |
91 | #include <asm/system.h> | 92 | #include <asm/system.h> |
@@ -153,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) | |||
153 | WARN_ON(sk->sk_forward_alloc); | 154 | WARN_ON(sk->sk_forward_alloc); |
154 | 155 | ||
155 | kfree(inet->opt); | 156 | kfree(inet->opt); |
156 | dst_release(sk->sk_dst_cache); | 157 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
157 | sk_refcnt_debug_dec(sk); | 158 | sk_refcnt_debug_dec(sk); |
158 | } | 159 | } |
159 | EXPORT_SYMBOL(inet_sock_destruct); | 160 | EXPORT_SYMBOL(inet_sock_destruct); |
@@ -418,6 +419,8 @@ int inet_release(struct socket *sock) | |||
418 | if (sk) { | 419 | if (sk) { |
419 | long timeout; | 420 | long timeout; |
420 | 421 | ||
422 | inet_rps_reset_flow(sk); | ||
423 | |||
421 | /* Applications forget to leave groups before exiting */ | 424 | /* Applications forget to leave groups before exiting */ |
422 | ip_mc_drop_socket(sk); | 425 | ip_mc_drop_socket(sk); |
423 | 426 | ||
@@ -530,6 +533,8 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, | |||
530 | { | 533 | { |
531 | struct sock *sk = sock->sk; | 534 | struct sock *sk = sock->sk; |
532 | 535 | ||
536 | if (addr_len < sizeof(uaddr->sa_family)) | ||
537 | return -EINVAL; | ||
533 | if (uaddr->sa_family == AF_UNSPEC) | 538 | if (uaddr->sa_family == AF_UNSPEC) |
534 | return sk->sk_prot->disconnect(sk, flags); | 539 | return sk->sk_prot->disconnect(sk, flags); |
535 | 540 | ||
@@ -573,6 +578,9 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, | |||
573 | int err; | 578 | int err; |
574 | long timeo; | 579 | long timeo; |
575 | 580 | ||
581 | if (addr_len < sizeof(uaddr->sa_family)) | ||
582 | return -EINVAL; | ||
583 | |||
576 | lock_sock(sk); | 584 | lock_sock(sk); |
577 | 585 | ||
578 | if (uaddr->sa_family == AF_UNSPEC) { | 586 | if (uaddr->sa_family == AF_UNSPEC) { |
@@ -714,6 +722,8 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
714 | { | 722 | { |
715 | struct sock *sk = sock->sk; | 723 | struct sock *sk = sock->sk; |
716 | 724 | ||
725 | inet_rps_record_flow(sk); | ||
726 | |||
717 | /* We may need to bind the socket. */ | 727 | /* We may need to bind the socket. */ |
718 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
719 | return -EAGAIN; | 729 | return -EAGAIN; |
@@ -722,12 +732,13 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
722 | } | 732 | } |
723 | EXPORT_SYMBOL(inet_sendmsg); | 733 | EXPORT_SYMBOL(inet_sendmsg); |
724 | 734 | ||
725 | |||
726 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | 735 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, |
727 | size_t size, int flags) | 736 | size_t size, int flags) |
728 | { | 737 | { |
729 | struct sock *sk = sock->sk; | 738 | struct sock *sk = sock->sk; |
730 | 739 | ||
740 | inet_rps_record_flow(sk); | ||
741 | |||
731 | /* We may need to bind the socket. */ | 742 | /* We may need to bind the socket. */ |
732 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
733 | return -EAGAIN; | 744 | return -EAGAIN; |
@@ -737,6 +748,22 @@ static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | |||
737 | return sock_no_sendpage(sock, page, offset, size, flags); | 748 | return sock_no_sendpage(sock, page, offset, size, flags); |
738 | } | 749 | } |
739 | 750 | ||
751 | int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | ||
752 | size_t size, int flags) | ||
753 | { | ||
754 | struct sock *sk = sock->sk; | ||
755 | int addr_len = 0; | ||
756 | int err; | ||
757 | |||
758 | inet_rps_record_flow(sk); | ||
759 | |||
760 | err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, | ||
761 | flags & ~MSG_DONTWAIT, &addr_len); | ||
762 | if (err >= 0) | ||
763 | msg->msg_namelen = addr_len; | ||
764 | return err; | ||
765 | } | ||
766 | EXPORT_SYMBOL(inet_recvmsg); | ||
740 | 767 | ||
741 | int inet_shutdown(struct socket *sock, int how) | 768 | int inet_shutdown(struct socket *sock, int how) |
742 | { | 769 | { |
@@ -866,7 +893,7 @@ const struct proto_ops inet_stream_ops = { | |||
866 | .setsockopt = sock_common_setsockopt, | 893 | .setsockopt = sock_common_setsockopt, |
867 | .getsockopt = sock_common_getsockopt, | 894 | .getsockopt = sock_common_getsockopt, |
868 | .sendmsg = tcp_sendmsg, | 895 | .sendmsg = tcp_sendmsg, |
869 | .recvmsg = sock_common_recvmsg, | 896 | .recvmsg = inet_recvmsg, |
870 | .mmap = sock_no_mmap, | 897 | .mmap = sock_no_mmap, |
871 | .sendpage = tcp_sendpage, | 898 | .sendpage = tcp_sendpage, |
872 | .splice_read = tcp_splice_read, | 899 | .splice_read = tcp_splice_read, |
@@ -893,7 +920,7 @@ const struct proto_ops inet_dgram_ops = { | |||
893 | .setsockopt = sock_common_setsockopt, | 920 | .setsockopt = sock_common_setsockopt, |
894 | .getsockopt = sock_common_getsockopt, | 921 | .getsockopt = sock_common_getsockopt, |
895 | .sendmsg = inet_sendmsg, | 922 | .sendmsg = inet_sendmsg, |
896 | .recvmsg = sock_common_recvmsg, | 923 | .recvmsg = inet_recvmsg, |
897 | .mmap = sock_no_mmap, | 924 | .mmap = sock_no_mmap, |
898 | .sendpage = inet_sendpage, | 925 | .sendpage = inet_sendpage, |
899 | #ifdef CONFIG_COMPAT | 926 | #ifdef CONFIG_COMPAT |
@@ -923,7 +950,7 @@ static const struct proto_ops inet_sockraw_ops = { | |||
923 | .setsockopt = sock_common_setsockopt, | 950 | .setsockopt = sock_common_setsockopt, |
924 | .getsockopt = sock_common_getsockopt, | 951 | .getsockopt = sock_common_getsockopt, |
925 | .sendmsg = inet_sendmsg, | 952 | .sendmsg = inet_sendmsg, |
926 | .recvmsg = sock_common_recvmsg, | 953 | .recvmsg = inet_recvmsg, |
927 | .mmap = sock_no_mmap, | 954 | .mmap = sock_no_mmap, |
928 | .sendpage = inet_sendpage, | 955 | .sendpage = inet_sendpage, |
929 | #ifdef CONFIG_COMPAT | 956 | #ifdef CONFIG_COMPAT |
@@ -1401,10 +1428,10 @@ EXPORT_SYMBOL_GPL(snmp_fold_field); | |||
1401 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) | 1428 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) |
1402 | { | 1429 | { |
1403 | BUG_ON(ptr == NULL); | 1430 | BUG_ON(ptr == NULL); |
1404 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1431 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1405 | if (!ptr[0]) | 1432 | if (!ptr[0]) |
1406 | goto err0; | 1433 | goto err0; |
1407 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1434 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1408 | if (!ptr[1]) | 1435 | if (!ptr[1]) |
1409 | goto err1; | 1436 | goto err1; |
1410 | return 0; | 1437 | return 0; |