summaryrefslogtreecommitdiff
path: root/net/ipv6
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-31 15:22:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-31 15:22:44 -0700
commit1a4ceab195e66bce9c1638fdded6d92988100ba4 (patch)
tree3ec17bd66fb3ac1429131e373cc8d99550d5451a /net/ipv6
parent83f89ca755c9f783b8229d968c4e9d2c660ca427 (diff)
parent6a32e4f9dd9219261f8856f817e6655114cfec2f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (27 commits) vlan: allow nested vlan_do_receive() ipv6: fix route lookup in addrconf_prefix_rcv() bonding: eliminate bond_close race conditions qlcnic: fix beacon and LED test. qlcnic: Updated License file qlcnic: updated reset sequence qlcnic: reset loopback mode if promiscous mode setting fails. qlcnic: skip IDC ack check in fw reset path. i825xx: Fix incorrect dependency for BVME6000_NET ipv6: fix route error binding peer in func icmp6_dst_alloc ipv6: fix error propagation in ip6_ufo_append_data() stmmac: update normal descriptor structure (v2) stmmac: fix NULL pointer dereference in capabilities fixup (v2) stmmac: fix a bug while checking the HW cap reg (v2) be2net: Changing MAC Address of a VF was broken. be2net: Refactored be_cmds.c file. bnx2x: update driver version to 1.70.30-0 bnx2x: use FW 7.0.29.0 bnx2x: Enable changing speed when port type is PORT_DA bnx2x: Fix 54618se LED behavior ...
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c43
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/ip6_output.c9
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/ipv6/tcp_ipv6.c17
5 files changed, 54 insertions, 20 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e39239e6426e..d0611a5de45f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1713,6 +1713,40 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
ip6_route_add(&cfg);
}
+
+static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
+ int plen,
+ const struct net_device *dev,
+ u32 flags, u32 noflags)
+{
+ struct fib6_node *fn;
+ struct rt6_info *rt = NULL;
+ struct fib6_table *table;
+
+ table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX);
+ if (table == NULL)
+ return NULL;
+
+ write_lock_bh(&table->tb6_lock);
+ fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
+ if (!fn)
+ goto out;
+ for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
+ if (rt->rt6i_dev->ifindex != dev->ifindex)
+ continue;
+ if ((rt->rt6i_flags & flags) != flags)
+ continue;
+ if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0))
+ continue;
+ dst_hold(&rt->dst);
+ break;
+ }
+out:
+ write_unlock_bh(&table->tb6_lock);
+ return rt;
+}
+
+
/* Create "default" multicast route to the interface */
static void addrconf_add_mroute(struct net_device *dev)
@@ -1842,10 +1876,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (addrconf_finite_timeout(rt_expires))
rt_expires *= HZ;
- rt = rt6_lookup(net, &pinfo->prefix, NULL,
- dev->ifindex, 1);
+ rt = addrconf_get_prefix_route(&pinfo->prefix,
+ pinfo->prefix_len,
+ dev,
+ RTF_ADDRCONF | RTF_PREFIX_RT,
+ RTF_GATEWAY | RTF_DEFAULT);
- if (rt && addrconf_is_prefix_route(rt)) {
+ if (rt) {
/* Autoconf prefix route */
if (valid_lft == 0) {
ip6_del_rt(rt);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 2916200f90c1..fee46d5a2f12 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -248,7 +248,7 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
/* Restore final destination back after routing done */
ipv6_addr_copy(&fl6.daddr, &np->daddr);
- res = ip6_xmit(sk, skb, &fl6, np->opt);
+ res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
rcu_read_unlock();
return res;
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 1c9bf8b5c30a..84d0bd5cac93 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -180,7 +180,7 @@ int ip6_output(struct sk_buff *skb)
*/
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- struct ipv6_txoptions *opt)
+ struct ipv6_txoptions *opt, int tclass)
{
struct net *net = sock_net(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -190,7 +190,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
u8 proto = fl6->flowi6_proto;
int seg_len = skb->len;
int hlimit = -1;
- int tclass = 0;
u32 mtu;
if (opt) {
@@ -228,10 +227,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
/*
* Fill in the IPv6 header
*/
- if (np) {
- tclass = np->tclass;
+ if (np)
hlimit = np->hop_limit;
- }
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
@@ -1126,7 +1123,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
hh_len + fragheaderlen + transhdrlen + 20,
(flags & MSG_DONTWAIT), &err);
if (skb == NULL)
- return -ENOMEM;
+ return err;
/* reserve space for Hardware header */
skb_reserve(skb, hh_len);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index fb545edef6ea..57b82dc1ae91 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1086,11 +1086,10 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
rt->dst.output = ip6_output;
dst_set_neighbour(&rt->dst, neigh);
atomic_set(&rt->dst.__refcnt, 1);
- dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
-
ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128;
rt->rt6i_idev = idev;
+ dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
spin_lock_bh(&icmp6_dst_lock);
rt->dst.next = icmp6_dst_gc_list;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c8683fcc487a..10b2b3165a1a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -513,7 +513,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
- err = ip6_xmit(sk, skb, &fl6, opt);
+ err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
err = net_xmit_eval(err);
}
@@ -979,7 +979,7 @@ static int tcp6_gro_complete(struct sk_buff *skb)
}
static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
- u32 ts, struct tcp_md5sig_key *key, int rst)
+ u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
{
const struct tcphdr *th = tcp_hdr(skb);
struct tcphdr *t1;
@@ -1060,7 +1060,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
if (!IS_ERR(dst)) {
skb_dst_set(buff, dst);
- ip6_xmit(ctl_sk, buff, &fl6, NULL);
+ ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
if (rst)
TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
@@ -1093,13 +1093,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
(th->doff << 2);
- tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1);
+ tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);
}
static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
- struct tcp_md5sig_key *key)
+ struct tcp_md5sig_key *key, u8 tclass)
{
- tcp_v6_send_response(skb, seq, ack, win, ts, key, 0);
+ tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass);
}
static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -1109,7 +1109,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
- tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw));
+ tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
+ tw->tw_tclass);
inet_twsk_put(tw);
}
@@ -1118,7 +1119,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
- tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr));
+ tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
}