diff options
-rw-r--r-- | include/net/tcp.h | 3 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 33 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 35 |
3 files changed, 35 insertions, 36 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 92faa6a7ea97..aaf5de9448c9 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -432,8 +432,7 @@ extern int tcp_disconnect(struct sock *sk, int flags); | |||
432 | 432 | ||
433 | void tcp_connect_init(struct sock *sk); | 433 | void tcp_connect_init(struct sock *sk); |
434 | void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); | 434 | void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); |
435 | int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, | 435 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); |
436 | int hdrlen, bool *fragstolen); | ||
437 | 436 | ||
438 | /* From syncookies.c */ | 437 | /* From syncookies.c */ |
439 | extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | 438 | extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 565406287f6f..86e2cf2ff770 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -978,39 +978,6 @@ static inline int select_size(const struct sock *sk, bool sg) | |||
978 | return tmp; | 978 | return tmp; |
979 | } | 979 | } |
980 | 980 | ||
981 | static int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | ||
982 | { | ||
983 | struct sk_buff *skb; | ||
984 | struct tcphdr *th; | ||
985 | bool fragstolen; | ||
986 | |||
987 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); | ||
988 | if (!skb) | ||
989 | goto err; | ||
990 | |||
991 | th = (struct tcphdr *)skb_put(skb, sizeof(*th)); | ||
992 | skb_reset_transport_header(skb); | ||
993 | memset(th, 0, sizeof(*th)); | ||
994 | |||
995 | if (memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size)) | ||
996 | goto err_free; | ||
997 | |||
998 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; | ||
999 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + size; | ||
1000 | TCP_SKB_CB(skb)->ack_seq = tcp_sk(sk)->snd_una - 1; | ||
1001 | |||
1002 | if (tcp_queue_rcv(sk, skb, sizeof(*th), &fragstolen)) { | ||
1003 | WARN_ON_ONCE(fragstolen); /* should not happen */ | ||
1004 | __kfree_skb(skb); | ||
1005 | } | ||
1006 | return size; | ||
1007 | |||
1008 | err_free: | ||
1009 | kfree_skb(skb); | ||
1010 | err: | ||
1011 | return -ENOMEM; | ||
1012 | } | ||
1013 | |||
1014 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 981 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
1015 | size_t size) | 982 | size_t size) |
1016 | { | 983 | { |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index eb58b94301ec..7c6c99dcc962 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4746,7 +4746,7 @@ end: | |||
4746 | skb_set_owner_r(skb, sk); | 4746 | skb_set_owner_r(skb, sk); |
4747 | } | 4747 | } |
4748 | 4748 | ||
4749 | int tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int hdrlen, | 4749 | static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int hdrlen, |
4750 | bool *fragstolen) | 4750 | bool *fragstolen) |
4751 | { | 4751 | { |
4752 | int eaten; | 4752 | int eaten; |
@@ -4763,6 +4763,39 @@ int tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int hdrlen, | |||
4763 | return eaten; | 4763 | return eaten; |
4764 | } | 4764 | } |
4765 | 4765 | ||
4766 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | ||
4767 | { | ||
4768 | struct sk_buff *skb; | ||
4769 | struct tcphdr *th; | ||
4770 | bool fragstolen; | ||
4771 | |||
4772 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); | ||
4773 | if (!skb) | ||
4774 | goto err; | ||
4775 | |||
4776 | th = (struct tcphdr *)skb_put(skb, sizeof(*th)); | ||
4777 | skb_reset_transport_header(skb); | ||
4778 | memset(th, 0, sizeof(*th)); | ||
4779 | |||
4780 | if (memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size)) | ||
4781 | goto err_free; | ||
4782 | |||
4783 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; | ||
4784 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + size; | ||
4785 | TCP_SKB_CB(skb)->ack_seq = tcp_sk(sk)->snd_una - 1; | ||
4786 | |||
4787 | if (tcp_queue_rcv(sk, skb, sizeof(*th), &fragstolen)) { | ||
4788 | WARN_ON_ONCE(fragstolen); /* should not happen */ | ||
4789 | __kfree_skb(skb); | ||
4790 | } | ||
4791 | return size; | ||
4792 | |||
4793 | err_free: | ||
4794 | kfree_skb(skb); | ||
4795 | err: | ||
4796 | return -ENOMEM; | ||
4797 | } | ||
4798 | |||
4766 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | 4799 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) |
4767 | { | 4800 | { |
4768 | const struct tcphdr *th = tcp_hdr(skb); | 4801 | const struct tcphdr *th = tcp_hdr(skb); |