diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/af_inet.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 19 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 60 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 14 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 10 | ||||
-rw-r--r-- | net/ipv4/udp.c | 13 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 7 |
7 files changed, 50 insertions, 77 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index eae1f676f87..ef1528af7ab 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -465,8 +465,10 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
465 | if (addr_len < sizeof(struct sockaddr_in)) | 465 | if (addr_len < sizeof(struct sockaddr_in)) |
466 | goto out; | 466 | goto out; |
467 | 467 | ||
468 | if (addr->sin_family != AF_INET) | 468 | if (addr->sin_family != AF_INET) { |
469 | err = -EAFNOSUPPORT; | ||
469 | goto out; | 470 | goto out; |
471 | } | ||
470 | 472 | ||
471 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); | 473 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); |
472 | 474 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a8024eaa0e8..84f26e8e6c6 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -802,8 +802,6 @@ static int __ip_append_data(struct sock *sk, | |||
802 | skb = skb_peek_tail(queue); | 802 | skb = skb_peek_tail(queue); |
803 | 803 | ||
804 | exthdrlen = !skb ? rt->dst.header_len : 0; | 804 | exthdrlen = !skb ? rt->dst.header_len : 0; |
805 | length += exthdrlen; | ||
806 | transhdrlen += exthdrlen; | ||
807 | mtu = cork->fragsize; | 805 | mtu = cork->fragsize; |
808 | 806 | ||
809 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 807 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
@@ -830,7 +828,7 @@ static int __ip_append_data(struct sock *sk, | |||
830 | cork->length += length; | 828 | cork->length += length; |
831 | if (((length > mtu) || (skb && skb_is_gso(skb))) && | 829 | if (((length > mtu) || (skb && skb_is_gso(skb))) && |
832 | (sk->sk_protocol == IPPROTO_UDP) && | 830 | (sk->sk_protocol == IPPROTO_UDP) && |
833 | (rt->dst.dev->features & NETIF_F_UFO)) { | 831 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { |
834 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, | 832 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
835 | hh_len, fragheaderlen, transhdrlen, | 833 | hh_len, fragheaderlen, transhdrlen, |
836 | mtu, flags); | 834 | mtu, flags); |
@@ -883,17 +881,16 @@ alloc_new_skb: | |||
883 | else | 881 | else |
884 | alloclen = fraglen; | 882 | alloclen = fraglen; |
885 | 883 | ||
884 | alloclen += exthdrlen; | ||
885 | |||
886 | /* The last fragment gets additional space at tail. | 886 | /* The last fragment gets additional space at tail. |
887 | * Note, with MSG_MORE we overallocate on fragments, | 887 | * Note, with MSG_MORE we overallocate on fragments, |
888 | * because we have no idea what fragment will be | 888 | * because we have no idea what fragment will be |
889 | * the last. | 889 | * the last. |
890 | */ | 890 | */ |
891 | if (datalen == length + fraggap) { | 891 | if (datalen == length + fraggap) |
892 | alloclen += rt->dst.trailer_len; | 892 | alloclen += rt->dst.trailer_len; |
893 | /* make sure mtu is not reached */ | 893 | |
894 | if (datalen > mtu - fragheaderlen - rt->dst.trailer_len) | ||
895 | datalen -= ALIGN(rt->dst.trailer_len, 8); | ||
896 | } | ||
897 | if (transhdrlen) { | 894 | if (transhdrlen) { |
898 | skb = sock_alloc_send_skb(sk, | 895 | skb = sock_alloc_send_skb(sk, |
899 | alloclen + hh_len + 15, | 896 | alloclen + hh_len + 15, |
@@ -926,11 +923,11 @@ alloc_new_skb: | |||
926 | /* | 923 | /* |
927 | * Find where to start putting bytes. | 924 | * Find where to start putting bytes. |
928 | */ | 925 | */ |
929 | data = skb_put(skb, fraglen); | 926 | data = skb_put(skb, fraglen + exthdrlen); |
930 | skb_set_network_header(skb, exthdrlen); | 927 | skb_set_network_header(skb, exthdrlen); |
931 | skb->transport_header = (skb->network_header + | 928 | skb->transport_header = (skb->network_header + |
932 | fragheaderlen); | 929 | fragheaderlen); |
933 | data += fragheaderlen; | 930 | data += fragheaderlen + exthdrlen; |
934 | 931 | ||
935 | if (fraggap) { | 932 | if (fraggap) { |
936 | skb->csum = skb_copy_and_csum_bits( | 933 | skb->csum = skb_copy_and_csum_bits( |
@@ -1064,7 +1061,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, | |||
1064 | */ | 1061 | */ |
1065 | *rtp = NULL; | 1062 | *rtp = NULL; |
1066 | cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? | 1063 | cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? |
1067 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); | 1064 | rt->dst.dev->mtu : dst_mtu(&rt->dst); |
1068 | cork->dst = &rt->dst; | 1065 | cork->dst = &rt->dst; |
1069 | cork->length = 0; | 1066 | cork->length = 0; |
1070 | cork->tx_flags = ipc->tx_flags; | 1067 | cork->tx_flags = ipc->tx_flags; |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 4614babdc45..2e97e3ec1eb 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -17,51 +17,35 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
17 | const struct iphdr *iph = ip_hdr(skb); | 17 | const struct iphdr *iph = ip_hdr(skb); |
18 | struct rtable *rt; | 18 | struct rtable *rt; |
19 | struct flowi4 fl4 = {}; | 19 | struct flowi4 fl4 = {}; |
20 | unsigned long orefdst; | 20 | __be32 saddr = iph->saddr; |
21 | __u8 flags = 0; | ||
21 | unsigned int hh_len; | 22 | unsigned int hh_len; |
22 | unsigned int type; | ||
23 | 23 | ||
24 | type = inet_addr_type(net, iph->saddr); | 24 | if (!skb->sk && addr_type != RTN_LOCAL) { |
25 | if (skb->sk && inet_sk(skb->sk)->transparent) | 25 | if (addr_type == RTN_UNSPEC) |
26 | type = RTN_LOCAL; | 26 | addr_type = inet_addr_type(net, saddr); |
27 | if (addr_type == RTN_UNSPEC) | 27 | if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST) |
28 | addr_type = type; | 28 | flags |= FLOWI_FLAG_ANYSRC; |
29 | else | ||
30 | saddr = 0; | ||
31 | } | ||
29 | 32 | ||
30 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause | 33 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause |
31 | * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. | 34 | * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. |
32 | */ | 35 | */ |
33 | if (addr_type == RTN_LOCAL) { | 36 | fl4.daddr = iph->daddr; |
34 | fl4.daddr = iph->daddr; | 37 | fl4.saddr = saddr; |
35 | if (type == RTN_LOCAL) | 38 | fl4.flowi4_tos = RT_TOS(iph->tos); |
36 | fl4.saddr = iph->saddr; | 39 | fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
37 | fl4.flowi4_tos = RT_TOS(iph->tos); | 40 | fl4.flowi4_mark = skb->mark; |
38 | fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; | 41 | fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : flags; |
39 | fl4.flowi4_mark = skb->mark; | 42 | rt = ip_route_output_key(net, &fl4); |
40 | fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; | 43 | if (IS_ERR(rt)) |
41 | rt = ip_route_output_key(net, &fl4); | 44 | return -1; |
42 | if (IS_ERR(rt)) | ||
43 | return -1; | ||
44 | |||
45 | /* Drop old route. */ | ||
46 | skb_dst_drop(skb); | ||
47 | skb_dst_set(skb, &rt->dst); | ||
48 | } else { | ||
49 | /* non-local src, find valid iif to satisfy | ||
50 | * rp-filter when calling ip_route_input. */ | ||
51 | fl4.daddr = iph->saddr; | ||
52 | rt = ip_route_output_key(net, &fl4); | ||
53 | if (IS_ERR(rt)) | ||
54 | return -1; | ||
55 | 45 | ||
56 | orefdst = skb->_skb_refdst; | 46 | /* Drop old route. */ |
57 | if (ip_route_input(skb, iph->daddr, iph->saddr, | 47 | skb_dst_drop(skb); |
58 | RT_TOS(iph->tos), rt->dst.dev) != 0) { | 48 | skb_dst_set(skb, &rt->dst); |
59 | dst_release(&rt->dst); | ||
60 | return -1; | ||
61 | } | ||
62 | dst_release(&rt->dst); | ||
63 | refdst_drop(orefdst); | ||
64 | } | ||
65 | 49 | ||
66 | if (skb_dst(skb)->error) | 50 | if (skb_dst(skb)->error) |
67 | return -1; | 51 | return -1; |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 1ff79e557f9..51f13f8ec72 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -40,7 +40,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
40 | struct iphdr *niph; | 40 | struct iphdr *niph; |
41 | const struct tcphdr *oth; | 41 | const struct tcphdr *oth; |
42 | struct tcphdr _otcph, *tcph; | 42 | struct tcphdr _otcph, *tcph; |
43 | unsigned int addr_type; | ||
44 | 43 | ||
45 | /* IP header checks: fragment. */ | 44 | /* IP header checks: fragment. */ |
46 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | 45 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) |
@@ -55,6 +54,9 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
55 | if (oth->rst) | 54 | if (oth->rst) |
56 | return; | 55 | return; |
57 | 56 | ||
57 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
58 | return; | ||
59 | |||
58 | /* Check checksum */ | 60 | /* Check checksum */ |
59 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | 61 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) |
60 | return; | 62 | return; |
@@ -101,19 +103,11 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
101 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | 103 | nskb->csum_start = (unsigned char *)tcph - nskb->head; |
102 | nskb->csum_offset = offsetof(struct tcphdr, check); | 104 | nskb->csum_offset = offsetof(struct tcphdr, check); |
103 | 105 | ||
104 | addr_type = RTN_UNSPEC; | ||
105 | if (hook != NF_INET_FORWARD | ||
106 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
107 | || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) | ||
108 | #endif | ||
109 | ) | ||
110 | addr_type = RTN_LOCAL; | ||
111 | |||
112 | /* ip_route_me_harder expects skb->dst to be set */ | 106 | /* ip_route_me_harder expects skb->dst to be set */ |
113 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | 107 | skb_dst_set_noref(nskb, skb_dst(oldskb)); |
114 | 108 | ||
115 | nskb->protocol = htons(ETH_P_IP); | 109 | nskb->protocol = htons(ETH_P_IP); |
116 | if (ip_route_me_harder(nskb, addr_type)) | 110 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) |
117 | goto free_nskb; | 111 | goto free_nskb; |
118 | 112 | ||
119 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | 113 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 054a59d21eb..46febcacb72 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -3220,7 +3220,7 @@ __setup("thash_entries=", set_thash_entries); | |||
3220 | void __init tcp_init(void) | 3220 | void __init tcp_init(void) |
3221 | { | 3221 | { |
3222 | struct sk_buff *skb = NULL; | 3222 | struct sk_buff *skb = NULL; |
3223 | unsigned long nr_pages, limit; | 3223 | unsigned long limit; |
3224 | int i, max_share, cnt; | 3224 | int i, max_share, cnt; |
3225 | unsigned long jiffy = jiffies; | 3225 | unsigned long jiffy = jiffies; |
3226 | 3226 | ||
@@ -3277,13 +3277,7 @@ void __init tcp_init(void) | |||
3277 | sysctl_tcp_max_orphans = cnt / 2; | 3277 | sysctl_tcp_max_orphans = cnt / 2; |
3278 | sysctl_max_syn_backlog = max(128, cnt / 256); | 3278 | sysctl_max_syn_backlog = max(128, cnt / 256); |
3279 | 3279 | ||
3280 | /* Set the pressure threshold to be a fraction of global memory that | 3280 | limit = nr_free_buffer_pages() / 8; |
3281 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of | ||
3282 | * memory, with a floor of 128 pages. | ||
3283 | */ | ||
3284 | nr_pages = totalram_pages - totalhigh_pages; | ||
3285 | limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | ||
3286 | limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
3287 | limit = max(limit, 128UL); | 3281 | limit = max(limit, 128UL); |
3288 | sysctl_tcp_mem[0] = limit / 4 * 3; | 3282 | sysctl_tcp_mem[0] = limit / 4 * 3; |
3289 | sysctl_tcp_mem[1] = limit; | 3283 | sysctl_tcp_mem[1] = limit; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index abca870d8ff..198f75b7bdd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1249,6 +1249,9 @@ csum_copy_err: | |||
1249 | 1249 | ||
1250 | if (noblock) | 1250 | if (noblock) |
1251 | return -EAGAIN; | 1251 | return -EAGAIN; |
1252 | |||
1253 | /* starting over for a new packet */ | ||
1254 | msg->msg_flags &= ~MSG_TRUNC; | ||
1252 | goto try_again; | 1255 | goto try_again; |
1253 | } | 1256 | } |
1254 | 1257 | ||
@@ -2206,16 +2209,10 @@ void __init udp_table_init(struct udp_table *table, const char *name) | |||
2206 | 2209 | ||
2207 | void __init udp_init(void) | 2210 | void __init udp_init(void) |
2208 | { | 2211 | { |
2209 | unsigned long nr_pages, limit; | 2212 | unsigned long limit; |
2210 | 2213 | ||
2211 | udp_table_init(&udp_table, "UDP"); | 2214 | udp_table_init(&udp_table, "UDP"); |
2212 | /* Set the pressure threshold up by the same strategy of TCP. It is a | 2215 | limit = nr_free_buffer_pages() / 8; |
2213 | * fraction of global memory that is up to 1/2 at 256 MB, decreasing | ||
2214 | * toward zero with the amount of memory, with a floor of 128 pages. | ||
2215 | */ | ||
2216 | nr_pages = totalram_pages - totalhigh_pages; | ||
2217 | limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | ||
2218 | limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
2219 | limit = max(limit, 128UL); | 2216 | limit = max(limit, 128UL); |
2220 | sysctl_udp_mem[0] = limit / 4 * 3; | 2217 | sysctl_udp_mem[0] = limit / 4 * 3; |
2221 | sysctl_udp_mem[1] = limit; | 2218 | sysctl_udp_mem[1] = limit; |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 2d51840e53a..327a617d594 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -32,7 +32,12 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) | |||
32 | dst = skb_dst(skb); | 32 | dst = skb_dst(skb); |
33 | mtu = dst_mtu(dst); | 33 | mtu = dst_mtu(dst); |
34 | if (skb->len > mtu) { | 34 | if (skb->len > mtu) { |
35 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); | 35 | if (skb->sk) |
36 | ip_local_error(skb->sk, EMSGSIZE, ip_hdr(skb)->daddr, | ||
37 | inet_sk(skb->sk)->inet_dport, mtu); | ||
38 | else | ||
39 | icmp_send(skb, ICMP_DEST_UNREACH, | ||
40 | ICMP_FRAG_NEEDED, htonl(mtu)); | ||
36 | ret = -EMSGSIZE; | 41 | ret = -EMSGSIZE; |
37 | } | 42 | } |
38 | out: | 43 | out: |