diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/ip_fragment.c | 11 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ip_sockglue.c | 33 | ||||
| -rw-r--r-- | net/ipv4/ping.c | 12 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 10 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 2 |
6 files changed, 46 insertions, 25 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index e5b6d0ddcb58..145a50c4d566 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -659,27 +659,30 @@ EXPORT_SYMBOL(ip_defrag); | |||
| 659 | struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) | 659 | struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) |
| 660 | { | 660 | { |
| 661 | struct iphdr iph; | 661 | struct iphdr iph; |
| 662 | int netoff; | ||
| 662 | u32 len; | 663 | u32 len; |
| 663 | 664 | ||
| 664 | if (skb->protocol != htons(ETH_P_IP)) | 665 | if (skb->protocol != htons(ETH_P_IP)) |
| 665 | return skb; | 666 | return skb; |
| 666 | 667 | ||
| 667 | if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) | 668 | netoff = skb_network_offset(skb); |
| 669 | |||
| 670 | if (skb_copy_bits(skb, netoff, &iph, sizeof(iph)) < 0) | ||
| 668 | return skb; | 671 | return skb; |
| 669 | 672 | ||
| 670 | if (iph.ihl < 5 || iph.version != 4) | 673 | if (iph.ihl < 5 || iph.version != 4) |
| 671 | return skb; | 674 | return skb; |
| 672 | 675 | ||
| 673 | len = ntohs(iph.tot_len); | 676 | len = ntohs(iph.tot_len); |
| 674 | if (skb->len < len || len < (iph.ihl * 4)) | 677 | if (skb->len < netoff + len || len < (iph.ihl * 4)) |
| 675 | return skb; | 678 | return skb; |
| 676 | 679 | ||
| 677 | if (ip_is_fragment(&iph)) { | 680 | if (ip_is_fragment(&iph)) { |
| 678 | skb = skb_share_check(skb, GFP_ATOMIC); | 681 | skb = skb_share_check(skb, GFP_ATOMIC); |
| 679 | if (skb) { | 682 | if (skb) { |
| 680 | if (!pskb_may_pull(skb, iph.ihl*4)) | 683 | if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) |
| 681 | return skb; | 684 | return skb; |
| 682 | if (pskb_trim_rcsum(skb, len)) | 685 | if (pskb_trim_rcsum(skb, netoff + len)) |
| 683 | return skb; | 686 | return skb; |
| 684 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 687 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
| 685 | if (ip_defrag(skb, user)) | 688 | if (ip_defrag(skb, user)) |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d68199d9b2b0..a7aea2048a0d 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -888,7 +888,8 @@ static int __ip_append_data(struct sock *sk, | |||
| 888 | cork->length += length; | 888 | cork->length += length; |
| 889 | if (((length > mtu) || (skb && skb_is_gso(skb))) && | 889 | if (((length > mtu) || (skb && skb_is_gso(skb))) && |
| 890 | (sk->sk_protocol == IPPROTO_UDP) && | 890 | (sk->sk_protocol == IPPROTO_UDP) && |
| 891 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { | 891 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && |
| 892 | (sk->sk_type == SOCK_DGRAM)) { | ||
| 892 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, | 893 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
| 893 | hh_len, fragheaderlen, transhdrlen, | 894 | hh_len, fragheaderlen, transhdrlen, |
| 894 | maxfraglen, flags); | 895 | maxfraglen, flags); |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 31d8c71986b4..5cd99271d3a6 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -432,17 +432,32 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf | |||
| 432 | kfree_skb(skb); | 432 | kfree_skb(skb); |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | static bool ipv4_pktinfo_prepare_errqueue(const struct sock *sk, | 435 | /* IPv4 supports cmsg on all imcp errors and some timestamps |
| 436 | const struct sk_buff *skb, | 436 | * |
| 437 | int ee_origin) | 437 | * Timestamp code paths do not initialize the fields expected by cmsg: |
| 438 | * the PKTINFO fields in skb->cb[]. Fill those in here. | ||
| 439 | */ | ||
| 440 | static bool ipv4_datagram_support_cmsg(const struct sock *sk, | ||
| 441 | struct sk_buff *skb, | ||
| 442 | int ee_origin) | ||
| 438 | { | 443 | { |
| 439 | struct in_pktinfo *info = PKTINFO_SKB_CB(skb); | 444 | struct in_pktinfo *info; |
| 445 | |||
| 446 | if (ee_origin == SO_EE_ORIGIN_ICMP) | ||
| 447 | return true; | ||
| 440 | 448 | ||
| 441 | if ((ee_origin != SO_EE_ORIGIN_TIMESTAMPING) || | 449 | if (ee_origin == SO_EE_ORIGIN_LOCAL) |
| 442 | (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG)) || | 450 | return false; |
| 451 | |||
| 452 | /* Support IP_PKTINFO on tstamp packets if requested, to correlate | ||
| 453 | * timestamp with egress dev. Not possible for packets without dev | ||
| 454 | * or without payload (SOF_TIMESTAMPING_OPT_TSONLY). | ||
| 455 | */ | ||
| 456 | if ((!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG)) || | ||
| 443 | (!skb->dev)) | 457 | (!skb->dev)) |
| 444 | return false; | 458 | return false; |
| 445 | 459 | ||
| 460 | info = PKTINFO_SKB_CB(skb); | ||
| 446 | info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr; | 461 | info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr; |
| 447 | info->ipi_ifindex = skb->dev->ifindex; | 462 | info->ipi_ifindex = skb->dev->ifindex; |
| 448 | return true; | 463 | return true; |
| @@ -483,7 +498,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 483 | 498 | ||
| 484 | serr = SKB_EXT_ERR(skb); | 499 | serr = SKB_EXT_ERR(skb); |
| 485 | 500 | ||
| 486 | if (sin && skb->len) { | 501 | if (sin && serr->port) { |
| 487 | sin->sin_family = AF_INET; | 502 | sin->sin_family = AF_INET; |
| 488 | sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + | 503 | sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + |
| 489 | serr->addr_offset); | 504 | serr->addr_offset); |
| @@ -496,9 +511,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 496 | sin = &errhdr.offender; | 511 | sin = &errhdr.offender; |
| 497 | memset(sin, 0, sizeof(*sin)); | 512 | memset(sin, 0, sizeof(*sin)); |
| 498 | 513 | ||
| 499 | if (skb->len && | 514 | if (ipv4_datagram_support_cmsg(sk, skb, serr->ee.ee_origin)) { |
| 500 | (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | ||
| 501 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin))) { | ||
| 502 | sin->sin_family = AF_INET; | 515 | sin->sin_family = AF_INET; |
| 503 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 516 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
| 504 | if (inet_sk(sk)->cmsg_flags) | 517 | if (inet_sk(sk)->cmsg_flags) |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index e9f66e1cda50..208d5439e59b 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
| @@ -259,6 +259,9 @@ int ping_init_sock(struct sock *sk) | |||
| 259 | kgid_t low, high; | 259 | kgid_t low, high; |
| 260 | int ret = 0; | 260 | int ret = 0; |
| 261 | 261 | ||
| 262 | if (sk->sk_family == AF_INET6) | ||
| 263 | sk->sk_ipv6only = 1; | ||
| 264 | |||
| 262 | inet_get_ping_group_range_net(net, &low, &high); | 265 | inet_get_ping_group_range_net(net, &low, &high); |
| 263 | if (gid_lte(low, group) && gid_lte(group, high)) | 266 | if (gid_lte(low, group) && gid_lte(group, high)) |
| 264 | return 0; | 267 | return 0; |
| @@ -305,6 +308,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, | |||
| 305 | if (addr_len < sizeof(*addr)) | 308 | if (addr_len < sizeof(*addr)) |
| 306 | return -EINVAL; | 309 | return -EINVAL; |
| 307 | 310 | ||
| 311 | if (addr->sin_family != AF_INET && | ||
| 312 | !(addr->sin_family == AF_UNSPEC && | ||
| 313 | addr->sin_addr.s_addr == htonl(INADDR_ANY))) | ||
| 314 | return -EAFNOSUPPORT; | ||
| 315 | |||
| 308 | pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", | 316 | pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", |
| 309 | sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); | 317 | sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); |
| 310 | 318 | ||
| @@ -330,7 +338,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, | |||
| 330 | return -EINVAL; | 338 | return -EINVAL; |
| 331 | 339 | ||
| 332 | if (addr->sin6_family != AF_INET6) | 340 | if (addr->sin6_family != AF_INET6) |
| 333 | return -EINVAL; | 341 | return -EAFNOSUPPORT; |
| 334 | 342 | ||
| 335 | pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", | 343 | pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", |
| 336 | sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); | 344 | sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); |
| @@ -716,7 +724,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
| 716 | if (msg->msg_namelen < sizeof(*usin)) | 724 | if (msg->msg_namelen < sizeof(*usin)) |
| 717 | return -EINVAL; | 725 | return -EINVAL; |
| 718 | if (usin->sin_family != AF_INET) | 726 | if (usin->sin_family != AF_INET) |
| 719 | return -EINVAL; | 727 | return -EAFNOSUPPORT; |
| 720 | daddr = usin->sin_addr.s_addr; | 728 | daddr = usin->sin_addr.s_addr; |
| 721 | /* no remote port */ | 729 | /* no remote port */ |
| 722 | } else { | 730 | } else { |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9d72a0fcd928..995a2259bcfc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -835,17 +835,13 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, | |||
| 835 | int large_allowed) | 835 | int large_allowed) |
| 836 | { | 836 | { |
| 837 | struct tcp_sock *tp = tcp_sk(sk); | 837 | struct tcp_sock *tp = tcp_sk(sk); |
| 838 | u32 new_size_goal, size_goal, hlen; | 838 | u32 new_size_goal, size_goal; |
| 839 | 839 | ||
| 840 | if (!large_allowed || !sk_can_gso(sk)) | 840 | if (!large_allowed || !sk_can_gso(sk)) |
| 841 | return mss_now; | 841 | return mss_now; |
| 842 | 842 | ||
| 843 | /* Maybe we should/could use sk->sk_prot->max_header here ? */ | 843 | /* Note : tcp_tso_autosize() will eventually split this later */ |
| 844 | hlen = inet_csk(sk)->icsk_af_ops->net_header_len + | 844 | new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER; |
| 845 | inet_csk(sk)->icsk_ext_hdr_len + | ||
| 846 | tp->tcp_header_len; | ||
| 847 | |||
| 848 | new_size_goal = sk->sk_gso_max_size - 1 - hlen; | ||
| 849 | new_size_goal = tcp_bound_to_half_wnd(tp, new_size_goal); | 845 | new_size_goal = tcp_bound_to_half_wnd(tp, new_size_goal); |
| 850 | 846 | ||
| 851 | /* We try hard to avoid divides here */ | 847 | /* We try hard to avoid divides here */ |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8fdd27b17306..fb4cf8b8e121 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -4770,7 +4770,7 @@ static bool tcp_should_expand_sndbuf(const struct sock *sk) | |||
| 4770 | return false; | 4770 | return false; |
| 4771 | 4771 | ||
| 4772 | /* If we filled the congestion window, do not expand. */ | 4772 | /* If we filled the congestion window, do not expand. */ |
| 4773 | if (tp->packets_out >= tp->snd_cwnd) | 4773 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) |
| 4774 | return false; | 4774 | return false; |
| 4775 | 4775 | ||
| 4776 | return true; | 4776 | return true; |
