diff options
author | David S. Miller <davem@davemloft.net> | 2011-12-02 13:49:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-02 13:49:21 -0500 |
commit | b3613118eb30a589d971e4eccbbb2a1314f5dfd4 (patch) | |
tree | 868c1ee59e1b5c19a4f2e43716400d0001a994e5 /net/ipv4 | |
parent | 7505afe28c16a8d386624930a018d0052c75d687 (diff) | |
parent | 5983fe2b29df5885880d7fa3b91aca306c7564ef (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/devinet.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 3 | ||||
-rw-r--r-- | net/ipv4/route.c | 44 | ||||
-rw-r--r-- | net/ipv4/udp.c | 15 |
4 files changed, 49 insertions, 18 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index c6b5092f29a1..65f01dc47565 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1490,7 +1490,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write, | |||
1490 | void __user *buffer, | 1490 | void __user *buffer, |
1491 | size_t *lenp, loff_t *ppos) | 1491 | size_t *lenp, loff_t *ppos) |
1492 | { | 1492 | { |
1493 | int old_value = *(int *)ctl->data; | ||
1493 | int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 1494 | int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
1495 | int new_value = *(int *)ctl->data; | ||
1494 | 1496 | ||
1495 | if (write) { | 1497 | if (write) { |
1496 | struct ipv4_devconf *cnf = ctl->extra1; | 1498 | struct ipv4_devconf *cnf = ctl->extra1; |
@@ -1501,6 +1503,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write, | |||
1501 | 1503 | ||
1502 | if (cnf == net->ipv4.devconf_dflt) | 1504 | if (cnf == net->ipv4.devconf_dflt) |
1503 | devinet_copy_dflt_conf(net, i); | 1505 | devinet_copy_dflt_conf(net, i); |
1506 | if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1) | ||
1507 | if ((new_value == 0) && (old_value != 0)) | ||
1508 | rt_cache_flush(net, 0); | ||
1504 | } | 1509 | } |
1505 | 1510 | ||
1506 | return ret; | 1511 | return ret; |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 9899619ab9b8..4f47e064e262 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -64,7 +64,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
64 | /* Change in oif may mean change in hh_len. */ | 64 | /* Change in oif may mean change in hh_len. */ |
65 | hh_len = skb_dst(skb)->dev->hard_header_len; | 65 | hh_len = skb_dst(skb)->dev->hard_header_len; |
66 | if (skb_headroom(skb) < hh_len && | 66 | if (skb_headroom(skb) < hh_len && |
67 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) | 67 | pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)), |
68 | 0, GFP_ATOMIC)) | ||
68 | return -1; | 69 | return -1; |
69 | 70 | ||
70 | return 0; | 71 | return 0; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9a20663d5969..7047069cf967 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -130,6 +130,7 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; | |||
130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; | 130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; |
131 | static int ip_rt_min_advmss __read_mostly = 256; | 131 | static int ip_rt_min_advmss __read_mostly = 256; |
132 | static int rt_chain_length_max __read_mostly = 20; | 132 | static int rt_chain_length_max __read_mostly = 20; |
133 | static int redirect_genid; | ||
133 | 134 | ||
134 | /* | 135 | /* |
135 | * Interface to generic destination cache. | 136 | * Interface to generic destination cache. |
@@ -415,9 +416,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) | |||
415 | else { | 416 | else { |
416 | struct rtable *r = v; | 417 | struct rtable *r = v; |
417 | struct neighbour *n; | 418 | struct neighbour *n; |
418 | int len; | 419 | int len, HHUptod; |
419 | 420 | ||
421 | rcu_read_lock(); | ||
420 | n = dst_get_neighbour(&r->dst); | 422 | n = dst_get_neighbour(&r->dst); |
423 | HHUptod = (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0; | ||
424 | rcu_read_unlock(); | ||
425 | |||
421 | seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" | 426 | seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" |
422 | "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", | 427 | "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", |
423 | r->dst.dev ? r->dst.dev->name : "*", | 428 | r->dst.dev ? r->dst.dev->name : "*", |
@@ -431,7 +436,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) | |||
431 | dst_metric(&r->dst, RTAX_RTTVAR)), | 436 | dst_metric(&r->dst, RTAX_RTTVAR)), |
432 | r->rt_key_tos, | 437 | r->rt_key_tos, |
433 | -1, | 438 | -1, |
434 | (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0, | 439 | HHUptod, |
435 | r->rt_spec_dst, &len); | 440 | r->rt_spec_dst, &len); |
436 | 441 | ||
437 | seq_printf(seq, "%*s\n", 127 - len, ""); | 442 | seq_printf(seq, "%*s\n", 127 - len, ""); |
@@ -836,6 +841,7 @@ static void rt_cache_invalidate(struct net *net) | |||
836 | 841 | ||
837 | get_random_bytes(&shuffle, sizeof(shuffle)); | 842 | get_random_bytes(&shuffle, sizeof(shuffle)); |
838 | atomic_add(shuffle + 1U, &net->ipv4.rt_genid); | 843 | atomic_add(shuffle + 1U, &net->ipv4.rt_genid); |
844 | redirect_genid++; | ||
839 | } | 845 | } |
840 | 846 | ||
841 | /* | 847 | /* |
@@ -1385,8 +1391,10 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | |||
1385 | 1391 | ||
1386 | peer = rt->peer; | 1392 | peer = rt->peer; |
1387 | if (peer) { | 1393 | if (peer) { |
1388 | if (peer->redirect_learned.a4 != new_gw) { | 1394 | if (peer->redirect_learned.a4 != new_gw || |
1395 | peer->redirect_genid != redirect_genid) { | ||
1389 | peer->redirect_learned.a4 = new_gw; | 1396 | peer->redirect_learned.a4 = new_gw; |
1397 | peer->redirect_genid = redirect_genid; | ||
1390 | atomic_inc(&__rt_peer_genid); | 1398 | atomic_inc(&__rt_peer_genid); |
1391 | } | 1399 | } |
1392 | check_peer_redir(&rt->dst, peer); | 1400 | check_peer_redir(&rt->dst, peer); |
@@ -1679,12 +1687,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1679 | } | 1687 | } |
1680 | 1688 | ||
1681 | 1689 | ||
1682 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | 1690 | static struct rtable *ipv4_validate_peer(struct rtable *rt) |
1683 | { | 1691 | { |
1684 | struct rtable *rt = (struct rtable *) dst; | ||
1685 | |||
1686 | if (rt_is_expired(rt)) | ||
1687 | return NULL; | ||
1688 | if (rt->rt_peer_genid != rt_peer_genid()) { | 1692 | if (rt->rt_peer_genid != rt_peer_genid()) { |
1689 | struct inet_peer *peer; | 1693 | struct inet_peer *peer; |
1690 | 1694 | ||
@@ -1693,17 +1697,29 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1693 | 1697 | ||
1694 | peer = rt->peer; | 1698 | peer = rt->peer; |
1695 | if (peer) { | 1699 | if (peer) { |
1696 | check_peer_pmtu(dst, peer); | 1700 | check_peer_pmtu(&rt->dst, peer); |
1697 | 1701 | ||
1702 | if (peer->redirect_genid != redirect_genid) | ||
1703 | peer->redirect_learned.a4 = 0; | ||
1698 | if (peer->redirect_learned.a4 && | 1704 | if (peer->redirect_learned.a4 && |
1699 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1705 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1700 | if (check_peer_redir(dst, peer)) | 1706 | if (check_peer_redir(&rt->dst, peer)) |
1701 | return NULL; | 1707 | return NULL; |
1702 | } | 1708 | } |
1703 | } | 1709 | } |
1704 | 1710 | ||
1705 | rt->rt_peer_genid = rt_peer_genid(); | 1711 | rt->rt_peer_genid = rt_peer_genid(); |
1706 | } | 1712 | } |
1713 | return rt; | ||
1714 | } | ||
1715 | |||
1716 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | ||
1717 | { | ||
1718 | struct rtable *rt = (struct rtable *) dst; | ||
1719 | |||
1720 | if (rt_is_expired(rt)) | ||
1721 | return NULL; | ||
1722 | dst = (struct dst_entry *) ipv4_validate_peer(rt); | ||
1707 | return dst; | 1723 | return dst; |
1708 | } | 1724 | } |
1709 | 1725 | ||
@@ -1851,6 +1867,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, | |||
1851 | dst_init_metrics(&rt->dst, peer->metrics, false); | 1867 | dst_init_metrics(&rt->dst, peer->metrics, false); |
1852 | 1868 | ||
1853 | check_peer_pmtu(&rt->dst, peer); | 1869 | check_peer_pmtu(&rt->dst, peer); |
1870 | if (peer->redirect_genid != redirect_genid) | ||
1871 | peer->redirect_learned.a4 = 0; | ||
1854 | if (peer->redirect_learned.a4 && | 1872 | if (peer->redirect_learned.a4 && |
1855 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1873 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1856 | rt->rt_gateway = peer->redirect_learned.a4; | 1874 | rt->rt_gateway = peer->redirect_learned.a4; |
@@ -2356,6 +2374,9 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2356 | rth->rt_mark == skb->mark && | 2374 | rth->rt_mark == skb->mark && |
2357 | net_eq(dev_net(rth->dst.dev), net) && | 2375 | net_eq(dev_net(rth->dst.dev), net) && |
2358 | !rt_is_expired(rth)) { | 2376 | !rt_is_expired(rth)) { |
2377 | rth = ipv4_validate_peer(rth); | ||
2378 | if (!rth) | ||
2379 | continue; | ||
2359 | if (noref) { | 2380 | if (noref) { |
2360 | dst_use_noref(&rth->dst, jiffies); | 2381 | dst_use_noref(&rth->dst, jiffies); |
2361 | skb_dst_set_noref(skb, &rth->dst); | 2382 | skb_dst_set_noref(skb, &rth->dst); |
@@ -2731,6 +2752,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) | |||
2731 | (IPTOS_RT_MASK | RTO_ONLINK)) && | 2752 | (IPTOS_RT_MASK | RTO_ONLINK)) && |
2732 | net_eq(dev_net(rth->dst.dev), net) && | 2753 | net_eq(dev_net(rth->dst.dev), net) && |
2733 | !rt_is_expired(rth)) { | 2754 | !rt_is_expired(rth)) { |
2755 | rth = ipv4_validate_peer(rth); | ||
2756 | if (!rth) | ||
2757 | continue; | ||
2734 | dst_use(&rth->dst, jiffies); | 2758 | dst_use(&rth->dst, jiffies); |
2735 | RT_CACHE_STAT_INC(out_hit); | 2759 | RT_CACHE_STAT_INC(out_hit); |
2736 | rcu_read_unlock_bh(); | 2760 | rcu_read_unlock_bh(); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b867ea23ece9..ad481b32f1e3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1164,7 +1164,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1164 | struct inet_sock *inet = inet_sk(sk); | 1164 | struct inet_sock *inet = inet_sk(sk); |
1165 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | 1165 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; |
1166 | struct sk_buff *skb; | 1166 | struct sk_buff *skb; |
1167 | unsigned int ulen; | 1167 | unsigned int ulen, copied; |
1168 | int peeked; | 1168 | int peeked; |
1169 | int err; | 1169 | int err; |
1170 | int is_udplite = IS_UDPLITE(sk); | 1170 | int is_udplite = IS_UDPLITE(sk); |
@@ -1186,9 +1186,10 @@ try_again: | |||
1186 | goto out; | 1186 | goto out; |
1187 | 1187 | ||
1188 | ulen = skb->len - sizeof(struct udphdr); | 1188 | ulen = skb->len - sizeof(struct udphdr); |
1189 | if (len > ulen) | 1189 | copied = len; |
1190 | len = ulen; | 1190 | if (copied > ulen) |
1191 | else if (len < ulen) | 1191 | copied = ulen; |
1192 | else if (copied < ulen) | ||
1192 | msg->msg_flags |= MSG_TRUNC; | 1193 | msg->msg_flags |= MSG_TRUNC; |
1193 | 1194 | ||
1194 | /* | 1195 | /* |
@@ -1197,14 +1198,14 @@ try_again: | |||
1197 | * coverage checksum (UDP-Lite), do it before the copy. | 1198 | * coverage checksum (UDP-Lite), do it before the copy. |
1198 | */ | 1199 | */ |
1199 | 1200 | ||
1200 | if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { | 1201 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
1201 | if (udp_lib_checksum_complete(skb)) | 1202 | if (udp_lib_checksum_complete(skb)) |
1202 | goto csum_copy_err; | 1203 | goto csum_copy_err; |
1203 | } | 1204 | } |
1204 | 1205 | ||
1205 | if (skb_csum_unnecessary(skb)) | 1206 | if (skb_csum_unnecessary(skb)) |
1206 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 1207 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
1207 | msg->msg_iov, len); | 1208 | msg->msg_iov, copied); |
1208 | else { | 1209 | else { |
1209 | err = skb_copy_and_csum_datagram_iovec(skb, | 1210 | err = skb_copy_and_csum_datagram_iovec(skb, |
1210 | sizeof(struct udphdr), | 1211 | sizeof(struct udphdr), |
@@ -1233,7 +1234,7 @@ try_again: | |||
1233 | if (inet->cmsg_flags) | 1234 | if (inet->cmsg_flags) |
1234 | ip_cmsg_recv(msg, skb); | 1235 | ip_cmsg_recv(msg, skb); |
1235 | 1236 | ||
1236 | err = len; | 1237 | err = copied; |
1237 | if (flags & MSG_TRUNC) | 1238 | if (flags & MSG_TRUNC) |
1238 | err = ulen; | 1239 | err = ulen; |
1239 | 1240 | ||