summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-12 01:12:47 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-12 15:08:48 -0800
commit9d6ec938019c6b16cb9ec96598ebe8f20de435fe (patch)
tree9b850eb7fd48a6e5ffc15f47afd2e3edc93f5290 /net/ipv4
parent68a5e3dd0a0056d8b349f9eea3756adda53ec17a (diff)
ipv4: Use flowi4 in public route lookup interfaces.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/icmp.c59
-rw-r--r--net/ipv4/inet_connection_sock.c26
-rw-r--r--net/ipv4/ip_output.c22
-rw-r--r--net/ipv4/netfilter.c26
-rw-r--r--net/ipv4/raw.c32
-rw-r--r--net/ipv4/route.c36
-rw-r--r--net/ipv4/syncookies.c24
-rw-r--r--net/ipv4/udp.c26
-rw-r--r--net/ipv4/xfrm4_policy.c10
9 files changed, 134 insertions, 127 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 8d091954625b..8eca3c28cbc3 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -353,14 +353,14 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
daddr = icmp_param->replyopts.faddr;
}
{
- struct flowi fl = {
- .fl4_dst = daddr,
- .fl4_src = rt->rt_spec_dst,
- .fl4_tos = RT_TOS(ip_hdr(skb)->tos),
- .flowi_proto = IPPROTO_ICMP,
+ struct flowi4 fl4 = {
+ .daddr = daddr,
+ .saddr = rt->rt_spec_dst,
+ .flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
+ .flowi4_proto = IPPROTO_ICMP,
};
- security_skb_classify_flow(skb, &fl);
- rt = ip_route_output_key(net, &fl);
+ security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
goto out_unlock;
}
@@ -378,30 +378,31 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
int type, int code,
struct icmp_bxm *param)
{
- struct flowi fl = {
- .fl4_dst = (param->replyopts.srr ?
- param->replyopts.faddr : iph->saddr),
- .fl4_src = saddr,
- .fl4_tos = RT_TOS(tos),
- .flowi_proto = IPPROTO_ICMP,
- .fl4_icmp_type = type,
- .fl4_icmp_code = code,
+ struct flowi4 fl4 = {
+ .daddr = (param->replyopts.srr ?
+ param->replyopts.faddr : iph->saddr),
+ .saddr = saddr,
+ .flowi4_tos = RT_TOS(tos),
+ .flowi4_proto = IPPROTO_ICMP,
+ .uli.icmpt.type = type,
+ .uli.icmpt.code = code,
};
struct rtable *rt, *rt2;
int err;
- security_skb_classify_flow(skb_in, &fl);
- rt = __ip_route_output_key(net, &fl);
+ security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4));
+ rt = __ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
return rt;
/* No need to clone since we're just using its address. */
rt2 = rt;
- if (!fl.fl4_src)
- fl.fl4_src = rt->rt_src;
+ if (!fl4.saddr)
+ fl4.saddr = rt->rt_src;
- rt = (struct rtable *) xfrm_lookup(net, &rt->dst, &fl, NULL, 0);
+ rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
+ flowi4_to_flowi(&fl4), NULL, 0);
if (!IS_ERR(rt)) {
if (rt != rt2)
return rt;
@@ -410,27 +411,27 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
} else
return rt;
- err = xfrm_decode_session_reverse(skb_in, &fl, AF_INET);
+ err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET);
if (err)
goto relookup_failed;
- if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) {
- rt2 = __ip_route_output_key(net, &fl);
+ if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) {
+ rt2 = __ip_route_output_key(net, &fl4);
if (IS_ERR(rt2))
err = PTR_ERR(rt2);
} else {
- struct flowi fl2 = {};
+ struct flowi4 fl4_2 = {};
unsigned long orefdst;
- fl2.fl4_dst = fl.fl4_src;
- rt2 = ip_route_output_key(net, &fl2);
+ fl4_2.daddr = fl4.saddr;
+ rt2 = ip_route_output_key(net, &fl4_2);
if (IS_ERR(rt2)) {
err = PTR_ERR(rt2);
goto relookup_failed;
}
/* Ugh! */
orefdst = skb_in->_skb_refdst; /* save old refdst */
- err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
+ err = ip_route_input(skb_in, fl4.daddr, fl4.saddr,
RT_TOS(tos), rt2->dst.dev);
dst_release(&rt2->dst);
@@ -441,7 +442,9 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
if (err)
goto relookup_failed;
- rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, &fl, NULL, XFRM_LOOKUP_ICMP);
+ rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
+ flowi4_to_flowi(&fl4), NULL,
+ XFRM_LOOKUP_ICMP);
if (!IS_ERR(rt2)) {
dst_release(&rt->dst);
rt = rt2;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 10a8e9523578..beecc1272169 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -356,22 +356,22 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
struct rtable *rt;
const struct inet_request_sock *ireq = inet_rsk(req);
struct ip_options *opt = inet_rsk(req)->opt;
- struct flowi fl = {
- .flowi_oif = sk->sk_bound_dev_if,
- .flowi_mark = sk->sk_mark,
- .fl4_dst = ((opt && opt->srr) ?
- opt->faddr : ireq->rmt_addr),
- .fl4_src = ireq->loc_addr,
- .fl4_tos = RT_CONN_FLAGS(sk),
- .flowi_proto = sk->sk_protocol,
- .flowi_flags = inet_sk_flowi_flags(sk),
- .fl4_sport = inet_sk(sk)->inet_sport,
- .fl4_dport = ireq->rmt_port,
+ struct flowi4 fl4 = {
+ .flowi4_oif = sk->sk_bound_dev_if,
+ .flowi4_mark = sk->sk_mark,
+ .daddr = ((opt && opt->srr) ?
+ opt->faddr : ireq->rmt_addr),
+ .saddr = ireq->loc_addr,
+ .flowi4_tos = RT_CONN_FLAGS(sk),
+ .flowi4_proto = sk->sk_protocol,
+ .flowi4_flags = inet_sk_flowi_flags(sk),
+ .uli.ports.sport = inet_sk(sk)->inet_sport,
+ .uli.ports.dport = ireq->rmt_port,
};
struct net *net = sock_net(sk);
- security_req_classify_flow(req, &fl);
- rt = ip_route_output_flow(net, &fl, sk);
+ security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt))
goto no_route;
if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 67e5f7130322..2b9cc40397ee 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1474,18 +1474,18 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
}
{
- struct flowi fl = {
- .flowi_oif = arg->bound_dev_if,
- .fl4_dst = daddr,
- .fl4_src = rt->rt_spec_dst,
- .fl4_tos = RT_TOS(ip_hdr(skb)->tos),
- .fl4_sport = tcp_hdr(skb)->dest,
- .fl4_dport = tcp_hdr(skb)->source,
- .flowi_proto = sk->sk_protocol,
- .flowi_flags = ip_reply_arg_flowi_flags(arg),
+ struct flowi4 fl4 = {
+ .flowi4_oif = arg->bound_dev_if,
+ .daddr = daddr,
+ .saddr = rt->rt_spec_dst,
+ .flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
+ .uli.ports.sport = tcp_hdr(skb)->dest,
+ .uli.ports.dport = tcp_hdr(skb)->source,
+ .flowi4_proto = sk->sk_protocol,
+ .flowi4_flags = ip_reply_arg_flowi_flags(arg),
};
- security_skb_classify_flow(skb, &fl);
- rt = ip_route_output_key(sock_net(sk), &fl);
+ security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt))
return;
}
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 6f40ba511c6b..f3c0b549b8e1 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -16,7 +16,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
struct net *net = dev_net(skb_dst(skb)->dev);
const struct iphdr *iph = ip_hdr(skb);
struct rtable *rt;
- struct flowi fl = {};
+ struct flowi4 fl4 = {};
unsigned long orefdst;
unsigned int hh_len;
unsigned int type;
@@ -31,14 +31,14 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
* packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook.
*/
if (addr_type == RTN_LOCAL) {
- fl.fl4_dst = iph->daddr;
+ fl4.daddr = iph->daddr;
if (type == RTN_LOCAL)
- fl.fl4_src = iph->saddr;
- fl.fl4_tos = RT_TOS(iph->tos);
- fl.flowi_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
- fl.flowi_mark = skb->mark;
- fl.flowi_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
- rt = ip_route_output_key(net, &fl);
+ fl4.saddr = iph->saddr;
+ fl4.flowi4_tos = RT_TOS(iph->tos);
+ fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+ fl4.flowi4_mark = skb->mark;
+ fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+ rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
return -1;
@@ -48,8 +48,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
} else {
/* non-local src, find valid iif to satisfy
* rp-filter when calling ip_route_input. */
- fl.fl4_dst = iph->saddr;
- rt = ip_route_output_key(net, &fl);
+ fl4.daddr = iph->saddr;
+ rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
return -1;
@@ -68,10 +68,10 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
#ifdef CONFIG_XFRM
if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
- xfrm_decode_session(skb, &fl, AF_INET) == 0) {
+ xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
struct dst_entry *dst = skb_dst(skb);
skb_dst_set(skb, NULL);
- dst = xfrm_lookup(net, dst, &fl, skb->sk, 0);
+ dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0);
if (IS_ERR(dst))
return -1;
skb_dst_set(skb, dst);
@@ -223,7 +223,7 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
{
- struct rtable *rt = ip_route_output_key(&init_net, fl);
+ struct rtable *rt = ip_route_output_key(&init_net, &fl->u.ip4);
if (IS_ERR(rt))
return PTR_ERR(rt);
*dst = &rt->dst;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 333b826c1871..452e178d962d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -402,7 +402,7 @@ error:
return err;
}
-static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
{
struct iovec *iov;
u8 __user *type = NULL;
@@ -418,7 +418,7 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
if (!iov)
continue;
- switch (fl->flowi_proto) {
+ switch (fl4->flowi4_proto) {
case IPPROTO_ICMP:
/* check if one-byte field is readable or not. */
if (iov->iov_base && iov->iov_len < 1)
@@ -433,8 +433,8 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
code = iov->iov_base;
if (type && code) {
- if (get_user(fl->fl4_icmp_type, type) ||
- get_user(fl->fl4_icmp_code, code))
+ if (get_user(fl4->uli.icmpt.type, type) ||
+ get_user(fl4->uli.icmpt.code, code))
return -EFAULT;
probed = 1;
}
@@ -548,23 +548,25 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
{
- struct flowi fl = { .flowi_oif = ipc.oif,
- .flowi_mark = sk->sk_mark,
- .fl4_dst = daddr,
- .fl4_src = saddr,
- .fl4_tos = tos,
- .flowi_proto = inet->hdrincl ? IPPROTO_RAW :
- sk->sk_protocol,
- .flowi_flags = FLOWI_FLAG_CAN_SLEEP,
+ struct flowi4 fl4 = {
+ .flowi4_oif = ipc.oif,
+ .flowi4_mark = sk->sk_mark,
+ .daddr = daddr,
+ .saddr = saddr,
+ .flowi4_tos = tos,
+ .flowi4_proto = (inet->hdrincl ?
+ IPPROTO_RAW :
+ sk->sk_protocol),
+ .flowi4_flags = FLOWI_FLAG_CAN_SLEEP,
};
if (!inet->hdrincl) {
- err = raw_probe_proto_opt(&fl, msg);
+ err = raw_probe_proto_opt(&fl4, msg);
if (err)
goto done;
}
- security_sk_classify_flow(sk, &fl);
- rt = ip_route_output_flow(sock_net(sk), &fl, sk);
+ security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
goto done;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9e938f95cea8..5655095a89e0 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2626,7 +2626,7 @@ out:
return rth;
}
-struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp)
+struct rtable *__ip_route_output_key(struct net *net, const struct flowi4 *flp4)
{
struct rtable *rth;
unsigned int hash;
@@ -2634,17 +2634,17 @@ struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp)
if (!rt_caching(net))
goto slow_output;
- hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->flowi_oif, rt_genid(net));
+ hash = rt_hash(flp4->daddr, flp4->saddr, flp4->flowi4_oif, rt_genid(net));
rcu_read_lock_bh();
for (rth = rcu_dereference_bh(rt_hash_table[hash].chain); rth;
rth = rcu_dereference_bh(rth->dst.rt_next)) {
- if (rth->rt_key_dst == flp->fl4_dst &&
- rth->rt_key_src == flp->fl4_src &&
+ if (rth->rt_key_dst == flp4->daddr &&
+ rth->rt_key_src == flp4->saddr &&
rt_is_output_route(rth) &&
- rth->rt_oif == flp->flowi_oif &&
- rth->rt_mark == flp->flowi_mark &&
- !((rth->rt_tos ^ flp->fl4_tos) &
+ rth->rt_oif == flp4->flowi4_oif &&
+ rth->rt_mark == flp4->flowi4_mark &&
+ !((rth->rt_tos ^ flp4->flowi4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK)) &&
net_eq(dev_net(rth->dst.dev), net) &&
!rt_is_expired(rth)) {
@@ -2658,7 +2658,7 @@ struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp)
rcu_read_unlock_bh();
slow_output:
- return ip_route_output_slow(net, &flp->u.ip4);
+ return ip_route_output_slow(net, flp4);
}
EXPORT_SYMBOL_GPL(__ip_route_output_key);
@@ -2733,20 +2733,22 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
return rt ? &rt->dst : ERR_PTR(-ENOMEM);
}
-struct rtable *ip_route_output_flow(struct net *net, struct flowi *flp,
+struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
struct sock *sk)
{
- struct rtable *rt = __ip_route_output_key(net, flp);
+ struct rtable *rt = __ip_route_output_key(net, flp4);
if (IS_ERR(rt))
return rt;
- if (flp->flowi_proto) {
- if (!flp->fl4_src)
- flp->fl4_src = rt->rt_src;
- if (!flp->fl4_dst)
- flp->fl4_dst = rt->rt_dst;
- rt = (struct rtable *) xfrm_lookup(net, &rt->dst, flp, sk, 0);
+ if (flp4->flowi4_proto) {
+ if (!flp4->saddr)
+ flp4->saddr = rt->rt_src;
+ if (!flp4->daddr)
+ flp4->daddr = rt->rt_dst;
+ rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
+ flowi4_to_flowi(flp4),
+ sk, 0);
}
return rt;
@@ -2920,7 +2922,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
.flowi4_mark = mark,
};
- rt = ip_route_output_key(net, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_key(net, &fl4);
err = 0;
if (IS_ERR(rt))
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index d90529d45ee6..e3b5b754311c 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -345,19 +345,19 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
* no easy way to do this.
*/
{
- struct flowi fl = {
- .flowi_mark = sk->sk_mark,
- .fl4_dst = ((opt && opt->srr) ?
- opt->faddr : ireq->rmt_addr),
- .fl4_src = ireq->loc_addr,
- .fl4_tos = RT_CONN_FLAGS(sk),
- .flowi_proto = IPPROTO_TCP,
- .flowi_flags = inet_sk_flowi_flags(sk),
- .fl4_sport = th->dest,
- .fl4_dport = th->source,
+ struct flowi4 fl4 = {
+ .flowi4_mark = sk->sk_mark,
+ .daddr = ((opt && opt->srr) ?
+ opt->faddr : ireq->rmt_addr),
+ .saddr = ireq->loc_addr,
+ .flowi4_tos = RT_CONN_FLAGS(sk),
+ .flowi4_proto = IPPROTO_TCP,
+ .flowi4_flags = inet_sk_flowi_flags(sk),
+ .uli.ports.sport = th->dest,
+ .uli.ports.dport = th->source,
};
- security_req_classify_flow(req, &fl);
- rt = ip_route_output_key(sock_net(sk), &fl);
+ security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt)) {
reqsk_free(req);
goto out;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 116e4a8bfb73..25c080798bd0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -908,22 +908,22 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
rt = (struct rtable *)sk_dst_check(sk, 0);
if (rt == NULL) {
- struct flowi fl = {
- .flowi_oif = ipc.oif,
- .flowi_mark = sk->sk_mark,
- .fl4_dst = faddr,
- .fl4_src = saddr,
- .fl4_tos = tos,
- .flowi_proto = sk->sk_protocol,
- .flowi_flags = (inet_sk_flowi_flags(sk) |
- FLOWI_FLAG_CAN_SLEEP),
- .fl4_sport = inet->inet_sport,
- .fl4_dport = dport,
+ struct flowi4 fl4 = {
+ .flowi4_oif = ipc.oif,
+ .flowi4_mark = sk->sk_mark,
+ .daddr = faddr,
+ .saddr = saddr,
+ .flowi4_tos = tos,
+ .flowi4_proto = sk->sk_protocol,
+ .flowi4_flags = (inet_sk_flowi_flags(sk) |
+ FLOWI_FLAG_CAN_SLEEP),
+ .uli.ports.sport = inet->inet_sport,
+ .uli.ports.dport = dport,
};
struct net *net = sock_net(sk);
- security_sk_classify_flow(sk, &fl);
- rt = ip_route_output_flow(net, &fl, sk);
+ security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
rt = NULL;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index b7b0921b425d..b111f468fa29 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -22,16 +22,16 @@ static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
const xfrm_address_t *saddr,
const xfrm_address_t *daddr)
{
- struct flowi fl = {
- .fl4_dst = daddr->a4,
- .fl4_tos = tos,
+ struct flowi4 fl4 = {
+ .daddr = daddr->a4,
+ .flowi4_tos = tos,
};
struct rtable *rt;
if (saddr)
- fl.fl4_src = saddr->a4;
+ fl4.saddr = saddr->a4;
- rt = __ip_route_output_key(net, &fl);
+ rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt))
return &rt->dst;