diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/af_inet.c | 5 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 14 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 25 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 60 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_MASQUERADE.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 14 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ecn.c | 7 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_rule.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 4 | ||||
-rw-r--r-- | net/ipv4/ping.c | 1 | ||||
-rw-r--r-- | net/ipv4/route.c | 82 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv4/udp.c | 13 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 7 |
22 files changed, 128 insertions, 145 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9c1926027a26..ef1528af7abf 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 | ||
@@ -676,6 +678,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags) | |||
676 | 678 | ||
677 | lock_sock(sk2); | 679 | lock_sock(sk2); |
678 | 680 | ||
681 | sock_rps_record_flow(sk2); | ||
679 | WARN_ON(!((1 << sk2->sk_state) & | 682 | WARN_ON(!((1 << sk2->sk_state) & |
680 | (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); | 683 | (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); |
681 | 684 | ||
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6ffe94ca5bc9..3267d3898437 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc) | |||
437 | return 0; | 437 | return 0; |
438 | if (cc == len) | 438 | if (cc == len) |
439 | return 1; | 439 | return 1; |
440 | if (op->yes < 4) | 440 | if (op->yes < 4 || op->yes & 3) |
441 | return 0; | 441 | return 0; |
442 | len -= op->yes; | 442 | len -= op->yes; |
443 | bc += op->yes; | 443 | bc += op->yes; |
@@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc) | |||
447 | 447 | ||
448 | static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) | 448 | static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) |
449 | { | 449 | { |
450 | const unsigned char *bc = bytecode; | 450 | const void *bc = bytecode; |
451 | int len = bytecode_len; | 451 | int len = bytecode_len; |
452 | 452 | ||
453 | while (len > 0) { | 453 | while (len > 0) { |
454 | struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; | 454 | const struct inet_diag_bc_op *op = bc; |
455 | 455 | ||
456 | //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); | 456 | //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); |
457 | switch (op->code) { | 457 | switch (op->code) { |
@@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) | |||
462 | case INET_DIAG_BC_S_LE: | 462 | case INET_DIAG_BC_S_LE: |
463 | case INET_DIAG_BC_D_GE: | 463 | case INET_DIAG_BC_D_GE: |
464 | case INET_DIAG_BC_D_LE: | 464 | case INET_DIAG_BC_D_LE: |
465 | if (op->yes < 4 || op->yes > len + 4) | ||
466 | return -EINVAL; | ||
467 | case INET_DIAG_BC_JMP: | 465 | case INET_DIAG_BC_JMP: |
468 | if (op->no < 4 || op->no > len + 4) | 466 | if (op->no < 4 || op->no > len + 4 || op->no & 3) |
469 | return -EINVAL; | 467 | return -EINVAL; |
470 | if (op->no < len && | 468 | if (op->no < len && |
471 | !valid_cc(bytecode, bytecode_len, len - op->no)) | 469 | !valid_cc(bytecode, bytecode_len, len - op->no)) |
472 | return -EINVAL; | 470 | return -EINVAL; |
473 | break; | 471 | break; |
474 | case INET_DIAG_BC_NOP: | 472 | case INET_DIAG_BC_NOP: |
475 | if (op->yes < 4 || op->yes > len + 4) | ||
476 | return -EINVAL; | ||
477 | break; | 473 | break; |
478 | default: | 474 | default: |
479 | return -EINVAL; | 475 | return -EINVAL; |
480 | } | 476 | } |
477 | if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) | ||
478 | return -EINVAL; | ||
481 | bc += op->yes; | 479 | bc += op->yes; |
482 | len -= op->yes; | 480 | len -= op->yes; |
483 | } | 481 | } |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 98af3697c718..84f26e8e6c60 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -799,9 +799,9 @@ static int __ip_append_data(struct sock *sk, | |||
799 | int csummode = CHECKSUM_NONE; | 799 | int csummode = CHECKSUM_NONE; |
800 | struct rtable *rt = (struct rtable *)cork->dst; | 800 | struct rtable *rt = (struct rtable *)cork->dst; |
801 | 801 | ||
802 | exthdrlen = transhdrlen ? rt->dst.header_len : 0; | 802 | skb = skb_peek_tail(queue); |
803 | length += exthdrlen; | 803 | |
804 | transhdrlen += exthdrlen; | 804 | exthdrlen = !skb ? rt->dst.header_len : 0; |
805 | mtu = cork->fragsize; | 805 | mtu = cork->fragsize; |
806 | 806 | ||
807 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 807 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
@@ -825,12 +825,10 @@ static int __ip_append_data(struct sock *sk, | |||
825 | !exthdrlen) | 825 | !exthdrlen) |
826 | csummode = CHECKSUM_PARTIAL; | 826 | csummode = CHECKSUM_PARTIAL; |
827 | 827 | ||
828 | skb = skb_peek_tail(queue); | ||
829 | |||
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 4614babdc45f..2e97e3ec1eb7 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/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d2c1311cb28d..5c9b9d963918 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
203 | else | 203 | else |
204 | pmsg->outdev_name[0] = '\0'; | 204 | pmsg->outdev_name[0] = '\0'; |
205 | 205 | ||
206 | if (entry->indev && entry->skb->dev) { | 206 | if (entry->indev && entry->skb->dev && |
207 | entry->skb->mac_header != entry->skb->network_header) { | ||
207 | pmsg->hw_type = entry->skb->dev->type; | 208 | pmsg->hw_type = entry->skb->dev->type; |
208 | pmsg->hw_addrlen = dev_parse_header(entry->skb, | 209 | pmsg->hw_addrlen = dev_parse_header(entry->skb, |
209 | pmsg->hw_addr); | 210 | pmsg->hw_addr); |
@@ -402,7 +403,8 @@ ipq_dev_drop(int ifindex) | |||
402 | static inline void | 403 | static inline void |
403 | __ipq_rcv_skb(struct sk_buff *skb) | 404 | __ipq_rcv_skb(struct sk_buff *skb) |
404 | { | 405 | { |
405 | int status, type, pid, flags, nlmsglen, skblen; | 406 | int status, type, pid, flags; |
407 | unsigned int nlmsglen, skblen; | ||
406 | struct nlmsghdr *nlh; | 408 | struct nlmsghdr *nlh; |
407 | 409 | ||
408 | skblen = skb->len; | 410 | skblen = skb->len; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 764743843503..24e556e83a3b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -566,7 +566,7 @@ check_entry(const struct ipt_entry *e, const char *name) | |||
566 | const struct xt_entry_target *t; | 566 | const struct xt_entry_target *t; |
567 | 567 | ||
568 | if (!ip_checkentry(&e->ip)) { | 568 | if (!ip_checkentry(&e->ip)) { |
569 | duprintf("ip check failed %p %s.\n", e, par->match->name); | 569 | duprintf("ip check failed %p %s.\n", e, name); |
570 | return -EINVAL; | 570 | return -EINVAL; |
571 | } | 571 | } |
572 | 572 | ||
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index d609ac3cb9a4..5c9e97c79017 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -307,7 +307,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
307 | * error messages (RELATED) and information requests (see below) */ | 307 | * error messages (RELATED) and information requests (see below) */ |
308 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP && | 308 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP && |
309 | (ctinfo == IP_CT_RELATED || | 309 | (ctinfo == IP_CT_RELATED || |
310 | ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)) | 310 | ctinfo == IP_CT_RELATED_REPLY)) |
311 | return XT_CONTINUE; | 311 | return XT_CONTINUE; |
312 | 312 | ||
313 | /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, | 313 | /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, |
@@ -321,12 +321,12 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
321 | ct->mark = hash; | 321 | ct->mark = hash; |
322 | break; | 322 | break; |
323 | case IP_CT_RELATED: | 323 | case IP_CT_RELATED: |
324 | case IP_CT_RELATED+IP_CT_IS_REPLY: | 324 | case IP_CT_RELATED_REPLY: |
325 | /* FIXME: we don't handle expectations at the | 325 | /* FIXME: we don't handle expectations at the |
326 | * moment. they can arrive on a different node than | 326 | * moment. they can arrive on a different node than |
327 | * the master connection (e.g. FTP passive mode) */ | 327 | * the master connection (e.g. FTP passive mode) */ |
328 | case IP_CT_ESTABLISHED: | 328 | case IP_CT_ESTABLISHED: |
329 | case IP_CT_ESTABLISHED+IP_CT_IS_REPLY: | 329 | case IP_CT_ESTABLISHED_REPLY: |
330 | break; | 330 | break; |
331 | default: | 331 | default: |
332 | break; | 332 | break; |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index d2ed9dc74ebc..9931152a78b5 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -60,7 +60,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
60 | nat = nfct_nat(ct); | 60 | nat = nfct_nat(ct); |
61 | 61 | ||
62 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | 62 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || |
63 | ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); | 63 | ctinfo == IP_CT_RELATED_REPLY)); |
64 | 64 | ||
65 | /* Source address is 0.0.0.0 - locally generated packet that is | 65 | /* Source address is 0.0.0.0 - locally generated packet that is |
66 | * probably not supposed to be masqueraded. | 66 | * probably not supposed to be masqueraded. |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 1ff79e557f96..51f13f8ec724 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/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index af6e9c778345..2b57e52c746c 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -25,7 +25,8 @@ MODULE_LICENSE("GPL"); | |||
25 | static inline bool match_ip(const struct sk_buff *skb, | 25 | static inline bool match_ip(const struct sk_buff *skb, |
26 | const struct ipt_ecn_info *einfo) | 26 | const struct ipt_ecn_info *einfo) |
27 | { | 27 | { |
28 | return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; | 28 | return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^ |
29 | !!(einfo->invert & IPT_ECN_OP_MATCH_IP); | ||
29 | } | 30 | } |
30 | 31 | ||
31 | static inline bool match_tcp(const struct sk_buff *skb, | 32 | static inline bool match_tcp(const struct sk_buff *skb, |
@@ -76,8 +77,6 @@ static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
76 | return false; | 77 | return false; |
77 | 78 | ||
78 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { | 79 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { |
79 | if (ip_hdr(skb)->protocol != IPPROTO_TCP) | ||
80 | return false; | ||
81 | if (!match_tcp(skb, info, &par->hotdrop)) | 80 | if (!match_tcp(skb, info, &par->hotdrop)) |
82 | return false; | 81 | return false; |
83 | } | 82 | } |
@@ -97,7 +96,7 @@ static int ecn_mt_check(const struct xt_mtchk_param *par) | |||
97 | return -EINVAL; | 96 | return -EINVAL; |
98 | 97 | ||
99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && | 98 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && |
100 | ip->proto != IPPROTO_TCP) { | 99 | (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) { |
101 | pr_info("cannot match TCP bits in rule for non-tcp packets\n"); | 100 | pr_info("cannot match TCP bits in rule for non-tcp packets\n"); |
102 | return -EINVAL; | 101 | return -EINVAL; |
103 | } | 102 | } |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 5a03c02af999..de9da21113a1 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -101,7 +101,7 @@ static unsigned int ipv4_confirm(unsigned int hooknum, | |||
101 | 101 | ||
102 | /* This is where we call the helper: as the packet goes out. */ | 102 | /* This is where we call the helper: as the packet goes out. */ |
103 | ct = nf_ct_get(skb, &ctinfo); | 103 | ct = nf_ct_get(skb, &ctinfo); |
104 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) | 104 | if (!ct || ctinfo == IP_CT_RELATED_REPLY) |
105 | goto out; | 105 | goto out; |
106 | 106 | ||
107 | help = nfct_help(ct); | 107 | help = nfct_help(ct); |
@@ -121,7 +121,9 @@ static unsigned int ipv4_confirm(unsigned int hooknum, | |||
121 | return ret; | 121 | return ret; |
122 | } | 122 | } |
123 | 123 | ||
124 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { | 124 | /* adjust seqs for loopback traffic only in outgoing direction */ |
125 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && | ||
126 | !nf_is_loopback_packet(skb)) { | ||
125 | typeof(nf_nat_seq_adjust_hook) seq_adjust; | 127 | typeof(nf_nat_seq_adjust_hook) seq_adjust; |
126 | 128 | ||
127 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); | 129 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7404bde95994..ab5b27a2916f 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -160,7 +160,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, | |||
160 | /* Update skb to refer to this connection */ | 160 | /* Update skb to refer to this connection */ |
161 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; | 161 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; |
162 | skb->nfctinfo = *ctinfo; | 162 | skb->nfctinfo = *ctinfo; |
163 | return -NF_ACCEPT; | 163 | return NF_ACCEPT; |
164 | } | 164 | } |
165 | 165 | ||
166 | /* Small and modified version of icmp_rcv */ | 166 | /* Small and modified version of icmp_rcv */ |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 9c71b2755ce3..3346de5d94d0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -433,7 +433,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
433 | 433 | ||
434 | /* Must be RELATED */ | 434 | /* Must be RELATED */ |
435 | NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || | 435 | NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || |
436 | skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); | 436 | skb->nfctinfo == IP_CT_RELATED_REPLY); |
437 | 437 | ||
438 | /* Redirects on non-null nats must be dropped, else they'll | 438 | /* Redirects on non-null nats must be dropped, else they'll |
439 | start talking to each other without our translation, and be | 439 | start talking to each other without our translation, and be |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 99cfa28b6d38..ebc5f8894f99 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -160,7 +160,7 @@ static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data | |||
160 | 160 | ||
161 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 161 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
162 | if (!(rt->rt_flags & RTCF_LOCAL) && | 162 | if (!(rt->rt_flags & RTCF_LOCAL) && |
163 | skb->dev->features & NETIF_F_V4_CSUM) { | 163 | (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { |
164 | skb->ip_summed = CHECKSUM_PARTIAL; | 164 | skb->ip_summed = CHECKSUM_PARTIAL; |
165 | skb->csum_start = skb_headroom(skb) + | 165 | skb->csum_start = skb_headroom(skb) + |
166 | skb_network_offset(skb) + | 166 | skb_network_offset(skb) + |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 21c30426480b..733c9abc1cbd 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -53,7 +53,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
53 | 53 | ||
54 | /* Connection must be valid and new. */ | 54 | /* Connection must be valid and new. */ |
55 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | 55 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || |
56 | ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); | 56 | ctinfo == IP_CT_RELATED_REPLY)); |
57 | NF_CT_ASSERT(par->out != NULL); | 57 | NF_CT_ASSERT(par->out != NULL); |
58 | 58 | ||
59 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); | 59 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 7317bdf1d457..483b76d042da 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -116,7 +116,7 @@ nf_nat_fn(unsigned int hooknum, | |||
116 | 116 | ||
117 | switch (ctinfo) { | 117 | switch (ctinfo) { |
118 | case IP_CT_RELATED: | 118 | case IP_CT_RELATED: |
119 | case IP_CT_RELATED+IP_CT_IS_REPLY: | 119 | case IP_CT_RELATED_REPLY: |
120 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { | 120 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
121 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, | 121 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, |
122 | hooknum, skb)) | 122 | hooknum, skb)) |
@@ -144,7 +144,7 @@ nf_nat_fn(unsigned int hooknum, | |||
144 | default: | 144 | default: |
145 | /* ESTABLISHED */ | 145 | /* ESTABLISHED */ |
146 | NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || | 146 | NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || |
147 | ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); | 147 | ctinfo == IP_CT_ESTABLISHED_REPLY); |
148 | } | 148 | } |
149 | 149 | ||
150 | return nf_nat_packet(ct, ctinfo, hooknum, skb); | 150 | return nf_nat_packet(ct, ctinfo, hooknum, skb); |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 9aaa67165f42..39b403f854c6 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/proc_fs.h> | 41 | #include <linux/proc_fs.h> |
42 | #include <net/sock.h> | 42 | #include <net/sock.h> |
43 | #include <net/ping.h> | 43 | #include <net/ping.h> |
44 | #include <net/icmp.h> | ||
45 | #include <net/udp.h> | 44 | #include <net/udp.h> |
46 | #include <net/route.h> | 45 | #include <net/route.h> |
47 | #include <net/inet_common.h> | 46 | #include <net/inet_common.h> |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 52b0b956508b..aa13ef105110 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1316,6 +1316,23 @@ reject_redirect: | |||
1316 | ; | 1316 | ; |
1317 | } | 1317 | } |
1318 | 1318 | ||
1319 | static bool peer_pmtu_expired(struct inet_peer *peer) | ||
1320 | { | ||
1321 | unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); | ||
1322 | |||
1323 | return orig && | ||
1324 | time_after_eq(jiffies, orig) && | ||
1325 | cmpxchg(&peer->pmtu_expires, orig, 0) == orig; | ||
1326 | } | ||
1327 | |||
1328 | static bool peer_pmtu_cleaned(struct inet_peer *peer) | ||
1329 | { | ||
1330 | unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); | ||
1331 | |||
1332 | return orig && | ||
1333 | cmpxchg(&peer->pmtu_expires, orig, 0) == orig; | ||
1334 | } | ||
1335 | |||
1319 | static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) | 1336 | static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) |
1320 | { | 1337 | { |
1321 | struct rtable *rt = (struct rtable *)dst; | 1338 | struct rtable *rt = (struct rtable *)dst; |
@@ -1331,14 +1348,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) | |||
1331 | rt_genid(dev_net(dst->dev))); | 1348 | rt_genid(dev_net(dst->dev))); |
1332 | rt_del(hash, rt); | 1349 | rt_del(hash, rt); |
1333 | ret = NULL; | 1350 | ret = NULL; |
1334 | } else if (rt->peer && | 1351 | } else if (rt->peer && peer_pmtu_expired(rt->peer)) { |
1335 | rt->peer->pmtu_expires && | 1352 | dst_metric_set(dst, RTAX_MTU, rt->peer->pmtu_orig); |
1336 | time_after_eq(jiffies, rt->peer->pmtu_expires)) { | ||
1337 | unsigned long orig = rt->peer->pmtu_expires; | ||
1338 | |||
1339 | if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) | ||
1340 | dst_metric_set(dst, RTAX_MTU, | ||
1341 | rt->peer->pmtu_orig); | ||
1342 | } | 1353 | } |
1343 | } | 1354 | } |
1344 | return ret; | 1355 | return ret; |
@@ -1531,8 +1542,10 @@ unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, | |||
1531 | 1542 | ||
1532 | static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer) | 1543 | static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer) |
1533 | { | 1544 | { |
1534 | unsigned long expires = peer->pmtu_expires; | 1545 | unsigned long expires = ACCESS_ONCE(peer->pmtu_expires); |
1535 | 1546 | ||
1547 | if (!expires) | ||
1548 | return; | ||
1536 | if (time_before(jiffies, expires)) { | 1549 | if (time_before(jiffies, expires)) { |
1537 | u32 orig_dst_mtu = dst_mtu(dst); | 1550 | u32 orig_dst_mtu = dst_mtu(dst); |
1538 | if (peer->pmtu_learned < orig_dst_mtu) { | 1551 | if (peer->pmtu_learned < orig_dst_mtu) { |
@@ -1555,10 +1568,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1555 | rt_bind_peer(rt, rt->rt_dst, 1); | 1568 | rt_bind_peer(rt, rt->rt_dst, 1); |
1556 | peer = rt->peer; | 1569 | peer = rt->peer; |
1557 | if (peer) { | 1570 | if (peer) { |
1571 | unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); | ||
1572 | |||
1558 | if (mtu < ip_rt_min_pmtu) | 1573 | if (mtu < ip_rt_min_pmtu) |
1559 | mtu = ip_rt_min_pmtu; | 1574 | mtu = ip_rt_min_pmtu; |
1560 | if (!peer->pmtu_expires || mtu < peer->pmtu_learned) { | 1575 | if (!pmtu_expires || mtu < peer->pmtu_learned) { |
1561 | unsigned long pmtu_expires; | ||
1562 | 1576 | ||
1563 | pmtu_expires = jiffies + ip_rt_mtu_expires; | 1577 | pmtu_expires = jiffies + ip_rt_mtu_expires; |
1564 | if (!pmtu_expires) | 1578 | if (!pmtu_expires) |
@@ -1612,13 +1626,14 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1612 | rt_bind_peer(rt, rt->rt_dst, 0); | 1626 | rt_bind_peer(rt, rt->rt_dst, 0); |
1613 | 1627 | ||
1614 | peer = rt->peer; | 1628 | peer = rt->peer; |
1615 | if (peer && peer->pmtu_expires) | 1629 | if (peer) { |
1616 | check_peer_pmtu(dst, peer); | 1630 | check_peer_pmtu(dst, peer); |
1617 | 1631 | ||
1618 | if (peer && peer->redirect_learned.a4 && | 1632 | if (peer->redirect_learned.a4 && |
1619 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1633 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1620 | if (check_peer_redir(dst, peer)) | 1634 | if (check_peer_redir(dst, peer)) |
1621 | return NULL; | 1635 | return NULL; |
1636 | } | ||
1622 | } | 1637 | } |
1623 | 1638 | ||
1624 | rt->rt_peer_genid = rt_peer_genid(); | 1639 | rt->rt_peer_genid = rt_peer_genid(); |
@@ -1649,14 +1664,8 @@ static void ipv4_link_failure(struct sk_buff *skb) | |||
1649 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); | 1664 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); |
1650 | 1665 | ||
1651 | rt = skb_rtable(skb); | 1666 | rt = skb_rtable(skb); |
1652 | if (rt && | 1667 | if (rt && rt->peer && peer_pmtu_cleaned(rt->peer)) |
1653 | rt->peer && | 1668 | dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); |
1654 | rt->peer->pmtu_expires) { | ||
1655 | unsigned long orig = rt->peer->pmtu_expires; | ||
1656 | |||
1657 | if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) | ||
1658 | dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); | ||
1659 | } | ||
1660 | } | 1669 | } |
1661 | 1670 | ||
1662 | static int ip_rt_bug(struct sk_buff *skb) | 1671 | static int ip_rt_bug(struct sk_buff *skb) |
@@ -1770,8 +1779,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, | |||
1770 | sizeof(u32) * RTAX_MAX); | 1779 | sizeof(u32) * RTAX_MAX); |
1771 | dst_init_metrics(&rt->dst, peer->metrics, false); | 1780 | dst_init_metrics(&rt->dst, peer->metrics, false); |
1772 | 1781 | ||
1773 | if (peer->pmtu_expires) | 1782 | check_peer_pmtu(&rt->dst, peer); |
1774 | check_peer_pmtu(&rt->dst, peer); | ||
1775 | if (peer->redirect_learned.a4 && | 1783 | if (peer->redirect_learned.a4 && |
1776 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1784 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1777 | rt->rt_gateway = peer->redirect_learned.a4; | 1785 | rt->rt_gateway = peer->redirect_learned.a4; |
@@ -1894,9 +1902,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1894 | 1902 | ||
1895 | hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); | 1903 | hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); |
1896 | rth = rt_intern_hash(hash, rth, skb, dev->ifindex); | 1904 | rth = rt_intern_hash(hash, rth, skb, dev->ifindex); |
1897 | err = 0; | 1905 | return IS_ERR(rth) ? PTR_ERR(rth) : 0; |
1898 | if (IS_ERR(rth)) | ||
1899 | err = PTR_ERR(rth); | ||
1900 | 1906 | ||
1901 | e_nobufs: | 1907 | e_nobufs: |
1902 | return -ENOBUFS; | 1908 | return -ENOBUFS; |
@@ -2775,7 +2781,8 @@ static int rt_fill_info(struct net *net, | |||
2775 | struct rtable *rt = skb_rtable(skb); | 2781 | struct rtable *rt = skb_rtable(skb); |
2776 | struct rtmsg *r; | 2782 | struct rtmsg *r; |
2777 | struct nlmsghdr *nlh; | 2783 | struct nlmsghdr *nlh; |
2778 | long expires; | 2784 | long expires = 0; |
2785 | const struct inet_peer *peer = rt->peer; | ||
2779 | u32 id = 0, ts = 0, tsage = 0, error; | 2786 | u32 id = 0, ts = 0, tsage = 0, error; |
2780 | 2787 | ||
2781 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); | 2788 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); |
@@ -2823,15 +2830,16 @@ static int rt_fill_info(struct net *net, | |||
2823 | NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark); | 2830 | NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark); |
2824 | 2831 | ||
2825 | error = rt->dst.error; | 2832 | error = rt->dst.error; |
2826 | expires = (rt->peer && rt->peer->pmtu_expires) ? | 2833 | if (peer) { |
2827 | rt->peer->pmtu_expires - jiffies : 0; | ||
2828 | if (rt->peer) { | ||
2829 | inet_peer_refcheck(rt->peer); | 2834 | inet_peer_refcheck(rt->peer); |
2830 | id = atomic_read(&rt->peer->ip_id_count) & 0xffff; | 2835 | id = atomic_read(&peer->ip_id_count) & 0xffff; |
2831 | if (rt->peer->tcp_ts_stamp) { | 2836 | if (peer->tcp_ts_stamp) { |
2832 | ts = rt->peer->tcp_ts; | 2837 | ts = peer->tcp_ts; |
2833 | tsage = get_seconds() - rt->peer->tcp_ts_stamp; | 2838 | tsage = get_seconds() - peer->tcp_ts_stamp; |
2834 | } | 2839 | } |
2840 | expires = ACCESS_ONCE(peer->pmtu_expires); | ||
2841 | if (expires) | ||
2842 | expires -= jiffies; | ||
2835 | } | 2843 | } |
2836 | 2844 | ||
2837 | if (rt_is_input_route(rt)) { | 2845 | if (rt_is_input_route(rt)) { |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 054a59d21eb0..46febcacb729 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/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a7d6671e33b8..708dc203b034 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1589,6 +1589,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1589 | goto discard; | 1589 | goto discard; |
1590 | 1590 | ||
1591 | if (nsk != sk) { | 1591 | if (nsk != sk) { |
1592 | sock_rps_save_rxhash(nsk, skb->rxhash); | ||
1592 | if (tcp_child_process(sk, nsk, skb)) { | 1593 | if (tcp_child_process(sk, nsk, skb)) { |
1593 | rsk = nsk; | 1594 | rsk = nsk; |
1594 | goto reset; | 1595 | goto reset; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index abca870d8ff6..198f75b7bdd3 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 2d51840e53a1..327a617d594c 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: |