aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-12-02 13:49:21 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-02 13:49:21 -0500
commitb3613118eb30a589d971e4eccbbb2a1314f5dfd4 (patch)
tree868c1ee59e1b5c19a4f2e43716400d0001a994e5 /net/ipv4
parent7505afe28c16a8d386624930a018d0052c75d687 (diff)
parent5983fe2b29df5885880d7fa3b91aca306c7564ef (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/devinet.c5
-rw-r--r--net/ipv4/netfilter.c3
-rw-r--r--net/ipv4/route.c44
-rw-r--r--net/ipv4/udp.c15
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;
130static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; 130static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20;
131static int ip_rt_min_advmss __read_mostly = 256; 131static int ip_rt_min_advmss __read_mostly = 256;
132static int rt_chain_length_max __read_mostly = 20; 132static int rt_chain_length_max __read_mostly = 20;
133static 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
1682static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1690static 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
1716static 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