Commit b23dd4fe authored by David S. Miller's avatar David S. Miller

ipv4: Make output route lookup return rtable directly.

Instead of on the stack.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 452edd59
......@@ -193,10 +193,11 @@ static int addr4_resolve(struct sockaddr_in *src_in,
fl.nl_u.ip4_u.saddr = src_ip;
fl.oif = addr->bound_dev_if;
ret = ip_route_output_key(&init_net, &rt, &fl);
if (ret)
rt = ip_route_output_key(&init_net, &fl);
if (IS_ERR(rt)) {
ret = PTR_ERR(rt);
goto out;
}
src_in->sin_family = AF_INET;
src_in->sin_addr.s_addr = rt->rt_src;
......
......@@ -354,7 +354,8 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
}
};
if (ip_route_output_flow(&init_net, &rt, &fl, NULL))
rt = ip_route_output_flow(&init_net, &fl, NULL);
if (IS_ERR(rt))
return NULL;
return rt;
}
......
......@@ -331,7 +331,8 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip,
}
};
if (ip_route_output_flow(&init_net, &rt, &fl, NULL))
rt = ip_route_output_flow(&init_net, &fl, NULL);
if (IS_ERR(rt))
return NULL;
return rt;
}
......
......@@ -1112,7 +1112,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
memset(&fl, 0, sizeof fl);
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
if (ip_route_output_key(&init_net, &rt, &fl)) {
rt = ip_route_output_key(&init_net, &fl);
if (IS_ERR(rt)) {
printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
__func__, dst_ip);
return rc;
......
......@@ -2681,7 +2681,7 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
{
int i, vlan_id, rv;
int i, vlan_id;
__be32 *targets = bond->params.arp_targets;
struct vlan_entry *vlan;
struct net_device *vlan_dev;
......@@ -2708,8 +2708,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
fl.fl4_dst = targets[i];
fl.fl4_tos = RTO_ONLINK;
rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl);
if (rv) {
rt = ip_route_output_key(dev_net(bond->dev), &fl);
if (IS_ERR(rt)) {
if (net_ratelimit()) {
pr_warning("%s: no route to arp_ip_target %pI4\n",
bond->dev->name, &fl.fl4_dst);
......
......@@ -3397,9 +3397,12 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
memset(&fl, 0, sizeof(fl));
fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr;
err = ip_route_output_key(&init_net, &rt, &fl);
if (!err)
rt = ip_route_output_key(&init_net, &fl);
err = 0;
if (!IS_ERR(rt))
*dst = &rt->dst;
else
err = PTR_ERR(rt);
return err;
#else
return -ENETUNREACH;
......
......@@ -175,7 +175,6 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
struct pptp_opt *opt = &po->proto.pptp;
struct pptp_gre_header *hdr;
unsigned int header_len = sizeof(*hdr);
int err = 0;
int islcp;
int len;
unsigned char *data;
......@@ -198,8 +197,8 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
.saddr = opt->src_addr.sin_addr.s_addr,
.tos = RT_TOS(0) } },
.proto = IPPROTO_GRE };
err = ip_route_output_key(&init_net, &rt, &fl);
if (err)
rt = ip_route_output_key(&init_net, &fl);
if (IS_ERR(rt))
goto tx_error;
}
tdev = rt->dst.dev;
......@@ -477,7 +476,8 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_GRE };
security_sk_classify_flow(sk, &fl);
if (ip_route_output_key(&init_net, &rt, &fl)) {
rt = ip_route_output_key(&init_net, &fl);
if (IS_ERR(rt)) {
error = -EHOSTUNREACH;
goto end;
}
......
......@@ -470,7 +470,8 @@ static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
}
};
if (ip_route_output_flow(&init_net, &rt, &fl, NULL))
rt = ip_route_output_flow(&init_net, &fl, NULL);
if (IS_ERR(rt))
return NULL;
return rt;
......
......@@ -118,9 +118,10 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
__be32 src, struct net_device *dev);
extern void rt_cache_flush(struct net *net, int how);
extern void rt_cache_flush_batch(struct net *net);
extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp);
extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp);
extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk);
extern struct rtable *__ip_route_output_key(struct net *, const struct flowi *flp);
extern struct rtable *ip_route_output_key(struct net *, struct flowi *flp);
extern struct rtable *ip_route_output_flow(struct net *, struct flowi *flp,
struct sock *sk);
extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig);
extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src,
......@@ -166,10 +167,10 @@ static inline char rt_tos2priority(u8 tos)
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}
static inline int ip_route_connect(struct rtable **rp, __be32 dst,
__be32 src, u32 tos, int oif, u8 protocol,
__be16 sport, __be16 dport, struct sock *sk,
bool can_sleep)
static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos,
int oif, u8 protocol,
__be16 sport, __be16 dport,
struct sock *sk, bool can_sleep)
{
struct flowi fl = { .oif = oif,
.mark = sk->sk_mark,
......@@ -179,8 +180,8 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
.proto = protocol,
.fl_ip_sport = sport,
.fl_ip_dport = dport };
int err;
struct net *net = sock_net(sk);
struct rtable *rt;
if (inet_sk(sk)->transparent)
fl.flags |= FLOWI_FLAG_ANYSRC;
......@@ -190,29 +191,29 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
fl.flags |= FLOWI_FLAG_CAN_SLEEP;
if (!dst || !src) {
err = __ip_route_output_key(net, rp, &fl);
if (err)
return err;
fl.fl4_dst = (*rp)->rt_dst;
fl.fl4_src = (*rp)->rt_src;
ip_rt_put(*rp);
*rp = NULL;
rt = __ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return rt;
fl.fl4_dst = rt->rt_dst;
fl.fl4_src = rt->rt_src;
ip_rt_put(rt);
}
security_sk_classify_flow(sk, &fl);
return ip_route_output_flow(net, rp, &fl, sk);
return ip_route_output_flow(net, &fl, sk);
}
static inline int ip_route_newports(struct rtable **rp, u8 protocol,
__be16 orig_sport, __be16 orig_dport,
__be16 sport, __be16 dport, struct sock *sk)
static inline struct rtable *ip_route_newports(struct rtable *rt,
u8 protocol, __be16 orig_sport,
__be16 orig_dport, __be16 sport,
__be16 dport, struct sock *sk)
{
if (sport != orig_sport || dport != orig_dport) {
struct flowi fl = { .oif = (*rp)->fl.oif,
.mark = (*rp)->fl.mark,
.fl4_dst = (*rp)->fl.fl4_dst,
.fl4_src = (*rp)->fl.fl4_src,
.fl4_tos = (*rp)->fl.fl4_tos,
.proto = (*rp)->fl.proto,
struct flowi fl = { .oif = rt->fl.oif,
.mark = rt->fl.mark,
.fl4_dst = rt->fl.fl4_dst,
.fl4_src = rt->fl.fl4_src,
.fl4_tos = rt->fl.fl4_tos,
.proto = rt->fl.proto,
.fl_ip_sport = sport,
.fl_ip_dport = dport };
......@@ -220,12 +221,11 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
fl.flags |= FLOWI_FLAG_ANYSRC;
if (protocol == IPPROTO_TCP)
fl.flags |= FLOWI_FLAG_PRECOW_METRICS;
ip_rt_put(*rp);
*rp = NULL;
ip_rt_put(rt);
security_sk_classify_flow(sk, &fl);
return ip_route_output_flow(sock_net(sk), rp, &fl, sk);
return ip_route_output_flow(sock_net(sk), &fl, sk);
}
return 0;
return rt;
}
extern void rt_bind_peer(struct rtable *rt, int create);
......
......@@ -520,9 +520,9 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
unlink_clip_vcc(clip_vcc);
return 0;
}
error = ip_route_output_key(&init_net, &rt, &fl);
if (error)
return error;
rt = ip_route_output_key(&init_net, &fl);
if (IS_ERR(rt))
return PTR_ERR(rt);
neigh = __neigh_lookup(&clip_tbl, &ip, rt->dst.dev, 1);
ip_rt_put(rt);
if (!neigh)
......
......@@ -428,14 +428,15 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
goto free_skb;
if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
rt = ip_route_output_key(dev_net(dev), &fl);
if (!IS_ERR(rt)) {
/* - Bridged-and-DNAT'ed traffic doesn't
* require ip_forwarding. */
if (((struct dst_entry *)rt)->dev == dev) {
skb_dst_set(skb, (struct dst_entry *)rt);
if (rt->dst.dev == dev) {
skb_dst_set(skb, &rt->dst);
goto bridged_dnat;
}
dst_release((struct dst_entry *)rt);
ip_rt_put(rt);
}
free_skb:
kfree_skb(skb);
......
......@@ -46,7 +46,6 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
__be16 orig_sport, orig_dport;
struct rtable *rt;
__be32 daddr, nexthop;
int tmp;
int err;
dp->dccps_role = DCCP_ROLE_CLIENT;
......@@ -66,12 +65,12 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
orig_sport = inet->inet_sport;
orig_dport = usin->sin_port;
tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr,
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_DCCP,
orig_sport, orig_dport, sk, true);
if (tmp < 0)
return tmp;
rt = ip_route_connect(nexthop, inet->inet_saddr,
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_DCCP,
orig_sport, orig_dport, sk, true);
if (IS_ERR(rt))
return PTR_ERR(rt);
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
ip_rt_put(rt);
......@@ -102,12 +101,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (err != 0)
goto failure;
err = ip_route_newports(&rt, IPPROTO_DCCP,
orig_sport, orig_dport,
inet->inet_sport, inet->inet_dport, sk);
if (err != 0)
rt = ip_route_newports(rt, IPPROTO_DCCP,
orig_sport, orig_dport,
inet->inet_sport, inet->inet_dport, sk);
if (IS_ERR(rt)) {
rt = NULL;
goto failure;
}
/* OK, now commit destination to socket. */
sk_setup_caps(sk, &rt->dst);
......@@ -475,7 +475,8 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
};
security_skb_classify_flow(skb, &fl);
if (ip_route_output_flow(net, &rt, &fl, sk)) {
rt = ip_route_output_flow(net, &fl, sk);
if (IS_ERR(rt)) {
IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
return NULL;
}
......
......@@ -1101,23 +1101,20 @@ int sysctl_ip_dynaddr __read_mostly;
static int inet_sk_reselect_saddr(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
int err;
struct rtable *rt;
__be32 old_saddr = inet->inet_saddr;
__be32 new_saddr;
__be32 daddr = inet->inet_daddr;
struct rtable *rt;
__be32 new_saddr;
if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;
/* Query new route. */
err = ip_route_connect(&rt, daddr, 0,
RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if,
sk->sk_protocol,
inet->inet_sport, inet->inet_dport, sk, false);
if (err)
return err;
rt = ip_route_connect(daddr, 0, RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if, sk->sk_protocol,
inet->inet_sport, inet->inet_dport, sk, false);
if (IS_ERR(rt))
return PTR_ERR(rt);
sk_setup_caps(sk, &rt->dst);
......@@ -1160,7 +1157,7 @@ int inet_sk_rebuild_header(struct sock *sk)
daddr = inet->inet_daddr;
if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr;
{
{
struct flowi fl = {
.oif = sk->sk_bound_dev_if,
.mark = sk->sk_mark,
......@@ -1174,11 +1171,14 @@ int inet_sk_rebuild_header(struct sock *sk)
};
security_sk_classify_flow(sk, &fl);
err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk);
}
if (!err)
rt = ip_route_output_flow(sock_net(sk), &fl, sk);
}
if (!IS_ERR(rt)) {
err = 0;
sk_setup_caps(sk, &rt->dst);
else {
} else {
err = PTR_ERR(rt);
/* Routing failed... */
sk->sk_route_caps = 0;
/*
......
......@@ -440,7 +440,8 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
/*unsigned long now; */
struct net *net = dev_net(dev);
if (ip_route_output_key(net, &rt, &fl) < 0)
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return 1;
if (rt->dst.dev != dev) {
NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER);
......@@ -1063,10 +1064,10 @@ static int arp_req_set(struct net *net, struct arpreq *r,
if (dev == NULL) {
struct flowi fl = { .fl4_dst = ip,
.fl4_tos = RTO_ONLINK };
struct rtable *rt;
err = ip_route_output_key(net, &rt, &fl);
if (err != 0)
return err;
struct rtable *rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return PTR_ERR(rt);
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev)
......@@ -1177,7 +1178,6 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r,
static int arp_req_delete(struct net *net, struct arpreq *r,
struct net_device *dev)
{
int err;
__be32 ip;
if (r->arp_flags & ATF_PUBL)
......@@ -1187,10 +1187,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
if (dev == NULL) {
struct flowi fl = { .fl4_dst = ip,
.fl4_tos = RTO_ONLINK };
struct rtable *rt;
err = ip_route_output_key(net, &rt, &fl);
if (err != 0)
return err;
struct rtable *rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return PTR_ERR(rt);
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev)
......
......@@ -46,11 +46,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (!saddr)
saddr = inet->mc_addr;
}
err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
RT_CONN_FLAGS(sk), oif,
sk->sk_protocol,
inet->inet_sport, usin->sin_port, sk, true);
if (err) {
rt = ip_route_connect(usin->sin_addr.s_addr, saddr,
RT_CONN_FLAGS(sk), oif,
sk->sk_protocol,
inet->inet_sport, usin->sin_port, sk, true);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
if (err == -ENETUNREACH)
IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
return err;
......
......@@ -358,7 +358,8 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
.fl4_tos = RT_TOS(ip_hdr(skb)->tos),
.proto = IPPROTO_ICMP };
security_skb_classify_flow(skb, &fl);
if (ip_route_output_key(net, &rt, &fl))
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
goto out_unlock;
}
if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
......@@ -388,9 +389,9 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
int err;
security_skb_classify_flow(skb_in, &fl);
err = __ip_route_output_key(net, &rt, &fl);
if (err)
return ERR_PTR(err);
rt = __ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return rt;
/* No need to clone since we're just using its address. */
rt2 = rt;
......@@ -412,15 +413,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
goto relookup_failed;
if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) {
err = __ip_route_output_key(net, &rt2, &fl);
rt2 = __ip_route_output_key(net, &fl);
if (IS_ERR(rt2))
err = PTR_ERR(rt2);
} else {
struct flowi fl2 = {};
unsigned long orefdst;
fl2.fl4_dst = fl.fl4_src;
err = ip_route_output_key(net, &rt2, &fl2);
if (err)
rt2 = ip_route_output_key(net, &fl2);
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,
......
......@@ -325,7 +325,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
struct flowi fl = { .oif = dev->ifindex,
.fl4_dst = IGMPV3_ALL_MCR,
.proto = IPPROTO_IGMP };
if (ip_route_output_key(net, &rt, &fl)) {
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt)) {
kfree_skb(skb);
return NULL;
}
......@@ -670,7 +671,8 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
struct flowi fl = { .oif = dev->ifindex,
.fl4_dst = dst,
.proto = IPPROTO_IGMP };
if (ip_route_output_key(net, &rt, &fl))
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return -1;
}
if (rt->rt_src == 0) {
......@@ -1440,7 +1442,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
{
struct flowi fl = { .fl4_dst = imr->imr_multiaddr.s_addr };
struct rtable *rt;
struct net_device *dev = NULL;
struct in_device *idev = NULL;
......@@ -1454,9 +1455,12 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
return NULL;
}
if (!dev && !ip_route_output_key(net, &rt, &fl)) {
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev) {
struct rtable *rt = ip_route_output_key(net, &fl);
if (!IS_ERR(rt)) {
dev = rt->dst.dev;
ip_rt_put(rt);
}
}
if (dev) {
imr->imr_ifindex = dev->ifindex;
......
......@@ -369,7 +369,8 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
struct net *net = sock_net(sk);
security_req_classify_flow(req, &fl);
if (ip_route_output_flow(net, &rt, &fl, sk))
rt = ip_route_output_flow(net, &fl, sk);
if (IS_ERR(rt))
goto no_route;
if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto route_err;
......
......@@ -778,7 +778,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
.proto = IPPROTO_GRE,
.fl_gre_key = tunnel->parms.o_key
};
if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
rt = ip_route_output_key(dev_net(dev), &fl);
if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
goto tx_error;
}
......@@ -953,9 +954,9 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
.proto = IPPROTO_GRE,
.fl_gre_key = tunnel->parms.o_key
};
struct rtable *rt;
struct rtable *rt = ip_route_output_key(dev_net(dev), &fl);
if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
if (!IS_ERR(rt)) {
tdev = rt->dst.dev;
ip_rt_put(rt);
}
......@@ -1215,9 +1216,9 @@ static int ipgre_open(struct net_device *dev)
.proto = IPPROTO_GRE,
.fl_gre_key = t->parms.o_key
};
struct rtable *rt;
struct rtable *rt = ip_route_output_key(dev_net(dev), &fl);
if (ip_route_output_key(dev_net(dev), &rt, &fl))
if (IS_ERR(rt))
return -EADDRNOTAVAIL;
dev = rt->dst.dev;
ip_rt_put(rt);
......
......@@ -355,7 +355,8 @@ int ip_queue_xmit(struct sk_buff *skb)
* itself out.
*/
security_sk_classify_flow(sk, &fl);
if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk))
rt = ip_route_output_flow(sock_net(sk), &fl, sk);
if (IS_ERR(rt))
goto no_route;
}
sk_setup_caps(sk, &rt->dst);
......@@ -1489,7 +1490,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
.proto = sk->sk_protocol,
.flags = ip_reply_arg_flowi_flags(arg) };
security_skb_classify_flow(skb, &fl);
if (ip_route_output_key(sock_net(sk), &rt, &fl))
rt = ip_route_output_key(sock_net(sk), &fl);
if (IS_ERR(rt))
return;
}
......
......@@ -469,7 +469,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
.proto = IPPROTO_IPIP
};
if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
rt = ip_route_output_key(dev_net(dev), &fl);
if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}
......@@ -590,9 +591,9 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
.fl4_tos = RT_TOS(iph->tos),
.proto = IPPROTO_IPIP
};
struct rtable *rt;
struct rtable *rt = ip_route_output_key(dev_net(dev), &fl);
if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
if (!IS_ERR(rt)) {
tdev = rt->dst.dev;
ip_rt_put(rt);
}
......
......@@ -1618,8 +1618,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
.fl4_tos = RT_TOS(iph->tos),
.proto = IPPROTO_IPIP
};
if (ip_route_output_key(net, &rt, &fl))
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
goto out_free;
encap = sizeof(struct iphdr);
} else {
......@@ -1629,8 +1629,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
.fl4_tos = RT_TOS(iph->tos),
.proto = IPPROTO_IPIP
};
if (ip_route_output_key(net, &rt, &fl))
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
goto out_free;
}
......
......@@ -38,7 +38,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
fl.mark = skb->mark;
fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
if (ip_route_output_key(net, &rt, &fl) != 0)
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return -1;
/* Drop old route. */
......@@ -48,7 +49,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
/* non-local src, find valid iif to satisfy
* rp-filter when calling ip_route_input. */
fl.fl4_dst = iph->saddr;
if (ip_route_output_key(net, &rt, &fl) != 0)
rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt))
return -1;
orefdst = skb->_skb_refdst;
......@@ -221,7 +223,11 @@ 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)
{
return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
struct rtable *rt = ip_route_output_key(&init_net, fl);
if (IS_ERR(rt))