diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-02 17:31:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-02 17:31:35 -0500 |
commit | b23dd4fe42b455af5c6e20966b7d6959fa8352ea (patch) | |
tree | bf97323eae9a8d084170e573ff2c0c40bc72c3cd | |
parent | 452edd598f60522c11f7f88fdbab27eb36509d1a (diff) |
ipv4: Make output route lookup return rtable directly.
Instead of on the stack.
Signed-off-by: David S. Miller <davem@davemloft.net>
36 files changed, 267 insertions, 224 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 8aba0ba57de5..2d749937a969 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
@@ -193,10 +193,11 @@ static int addr4_resolve(struct sockaddr_in *src_in, | |||
193 | fl.nl_u.ip4_u.saddr = src_ip; | 193 | fl.nl_u.ip4_u.saddr = src_ip; |
194 | fl.oif = addr->bound_dev_if; | 194 | fl.oif = addr->bound_dev_if; |
195 | 195 | ||
196 | ret = ip_route_output_key(&init_net, &rt, &fl); | 196 | rt = ip_route_output_key(&init_net, &fl); |
197 | if (ret) | 197 | if (IS_ERR(rt)) { |
198 | ret = PTR_ERR(rt); | ||
198 | goto out; | 199 | goto out; |
199 | 200 | } | |
200 | src_in->sin_family = AF_INET; | 201 | src_in->sin_family = AF_INET; |
201 | src_in->sin_addr.s_addr = rt->rt_src; | 202 | src_in->sin_addr.s_addr = rt->rt_src; |
202 | 203 | ||
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index e654285aa6ba..e0ccbc53fbcc 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c | |||
@@ -354,7 +354,8 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip, | |||
354 | } | 354 | } |
355 | }; | 355 | }; |
356 | 356 | ||
357 | if (ip_route_output_flow(&init_net, &rt, &fl, NULL)) | 357 | rt = ip_route_output_flow(&init_net, &fl, NULL); |
358 | if (IS_ERR(rt)) | ||
358 | return NULL; | 359 | return NULL; |
359 | return rt; | 360 | return rt; |
360 | } | 361 | } |
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 7e0484f18db5..77b0eef2aad9 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -331,7 +331,8 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip, | |||
331 | } | 331 | } |
332 | }; | 332 | }; |
333 | 333 | ||
334 | if (ip_route_output_flow(&init_net, &rt, &fl, NULL)) | 334 | rt = ip_route_output_flow(&init_net, &fl, NULL); |
335 | if (IS_ERR(rt)) | ||
335 | return NULL; | 336 | return NULL; |
336 | return rt; | 337 | return rt; |
337 | } | 338 | } |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index ec3aa11c36cb..e81599cb1fe6 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -1112,7 +1112,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1112 | 1112 | ||
1113 | memset(&fl, 0, sizeof fl); | 1113 | memset(&fl, 0, sizeof fl); |
1114 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); | 1114 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); |
1115 | if (ip_route_output_key(&init_net, &rt, &fl)) { | 1115 | rt = ip_route_output_key(&init_net, &fl); |
1116 | if (IS_ERR(rt)) { | ||
1116 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", | 1117 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", |
1117 | __func__, dst_ip); | 1118 | __func__, dst_ip); |
1118 | return rc; | 1119 | return rc; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 584f97b73060..0592e6da15a6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2681,7 +2681,7 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_ | |||
2681 | 2681 | ||
2682 | static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | 2682 | static void bond_arp_send_all(struct bonding *bond, struct slave *slave) |
2683 | { | 2683 | { |
2684 | int i, vlan_id, rv; | 2684 | int i, vlan_id; |
2685 | __be32 *targets = bond->params.arp_targets; | 2685 | __be32 *targets = bond->params.arp_targets; |
2686 | struct vlan_entry *vlan; | 2686 | struct vlan_entry *vlan; |
2687 | struct net_device *vlan_dev; | 2687 | struct net_device *vlan_dev; |
@@ -2708,8 +2708,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2708 | fl.fl4_dst = targets[i]; | 2708 | fl.fl4_dst = targets[i]; |
2709 | fl.fl4_tos = RTO_ONLINK; | 2709 | fl.fl4_tos = RTO_ONLINK; |
2710 | 2710 | ||
2711 | rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl); | 2711 | rt = ip_route_output_key(dev_net(bond->dev), &fl); |
2712 | if (rv) { | 2712 | if (IS_ERR(rt)) { |
2713 | if (net_ratelimit()) { | 2713 | if (net_ratelimit()) { |
2714 | pr_warning("%s: no route to arp_ip_target %pI4\n", | 2714 | pr_warning("%s: no route to arp_ip_target %pI4\n", |
2715 | bond->dev->name, &fl.fl4_dst); | 2715 | bond->dev->name, &fl.fl4_dst); |
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 5274de3e1bb9..25f08880ae0f 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -3397,9 +3397,12 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr, | |||
3397 | memset(&fl, 0, sizeof(fl)); | 3397 | memset(&fl, 0, sizeof(fl)); |
3398 | fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr; | 3398 | fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr; |
3399 | 3399 | ||
3400 | err = ip_route_output_key(&init_net, &rt, &fl); | 3400 | rt = ip_route_output_key(&init_net, &fl); |
3401 | if (!err) | 3401 | err = 0; |
3402 | if (!IS_ERR(rt)) | ||
3402 | *dst = &rt->dst; | 3403 | *dst = &rt->dst; |
3404 | else | ||
3405 | err = PTR_ERR(rt); | ||
3403 | return err; | 3406 | return err; |
3404 | #else | 3407 | #else |
3405 | return -ENETUNREACH; | 3408 | return -ENETUNREACH; |
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c index 164cfad6ce79..1af549c89d51 100644 --- a/drivers/net/pptp.c +++ b/drivers/net/pptp.c | |||
@@ -175,7 +175,6 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
175 | struct pptp_opt *opt = &po->proto.pptp; | 175 | struct pptp_opt *opt = &po->proto.pptp; |
176 | struct pptp_gre_header *hdr; | 176 | struct pptp_gre_header *hdr; |
177 | unsigned int header_len = sizeof(*hdr); | 177 | unsigned int header_len = sizeof(*hdr); |
178 | int err = 0; | ||
179 | int islcp; | 178 | int islcp; |
180 | int len; | 179 | int len; |
181 | unsigned char *data; | 180 | unsigned char *data; |
@@ -198,8 +197,8 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
198 | .saddr = opt->src_addr.sin_addr.s_addr, | 197 | .saddr = opt->src_addr.sin_addr.s_addr, |
199 | .tos = RT_TOS(0) } }, | 198 | .tos = RT_TOS(0) } }, |
200 | .proto = IPPROTO_GRE }; | 199 | .proto = IPPROTO_GRE }; |
201 | err = ip_route_output_key(&init_net, &rt, &fl); | 200 | rt = ip_route_output_key(&init_net, &fl); |
202 | if (err) | 201 | if (IS_ERR(rt)) |
203 | goto tx_error; | 202 | goto tx_error; |
204 | } | 203 | } |
205 | tdev = rt->dst.dev; | 204 | tdev = rt->dst.dev; |
@@ -477,7 +476,8 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
477 | .tos = RT_CONN_FLAGS(sk) } }, | 476 | .tos = RT_CONN_FLAGS(sk) } }, |
478 | .proto = IPPROTO_GRE }; | 477 | .proto = IPPROTO_GRE }; |
479 | security_sk_classify_flow(sk, &fl); | 478 | security_sk_classify_flow(sk, &fl); |
480 | if (ip_route_output_key(&init_net, &rt, &fl)) { | 479 | rt = ip_route_output_key(&init_net, &fl); |
480 | if (IS_ERR(rt)) { | ||
481 | error = -EHOSTUNREACH; | 481 | error = -EHOSTUNREACH; |
482 | goto end; | 482 | goto end; |
483 | } | 483 | } |
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 261aa817bdd5..889199aa1f5b 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c | |||
@@ -470,7 +470,8 @@ static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr, | |||
470 | } | 470 | } |
471 | }; | 471 | }; |
472 | 472 | ||
473 | if (ip_route_output_flow(&init_net, &rt, &fl, NULL)) | 473 | rt = ip_route_output_flow(&init_net, &fl, NULL); |
474 | if (IS_ERR(rt)) | ||
474 | return NULL; | 475 | return NULL; |
475 | 476 | ||
476 | return rt; | 477 | return rt; |
diff --git a/include/net/route.h b/include/net/route.h index 707cfc8eccdc..088a1867348f 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -118,9 +118,10 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, | |||
118 | __be32 src, struct net_device *dev); | 118 | __be32 src, struct net_device *dev); |
119 | extern void rt_cache_flush(struct net *net, int how); | 119 | extern void rt_cache_flush(struct net *net, int how); |
120 | extern void rt_cache_flush_batch(struct net *net); | 120 | extern void rt_cache_flush_batch(struct net *net); |
121 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); | 121 | extern struct rtable *__ip_route_output_key(struct net *, const struct flowi *flp); |
122 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); | 122 | extern struct rtable *ip_route_output_key(struct net *, struct flowi *flp); |
123 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk); | 123 | extern struct rtable *ip_route_output_flow(struct net *, struct flowi *flp, |
124 | struct sock *sk); | ||
124 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); | 125 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); |
125 | 126 | ||
126 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, | 127 | 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) | |||
166 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; | 167 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; |
167 | } | 168 | } |
168 | 169 | ||
169 | static inline int ip_route_connect(struct rtable **rp, __be32 dst, | 170 | static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, |
170 | __be32 src, u32 tos, int oif, u8 protocol, | 171 | int oif, u8 protocol, |
171 | __be16 sport, __be16 dport, struct sock *sk, | 172 | __be16 sport, __be16 dport, |
172 | bool can_sleep) | 173 | struct sock *sk, bool can_sleep) |
173 | { | 174 | { |
174 | struct flowi fl = { .oif = oif, | 175 | struct flowi fl = { .oif = oif, |
175 | .mark = sk->sk_mark, | 176 | .mark = sk->sk_mark, |
@@ -179,8 +180,8 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, | |||
179 | .proto = protocol, | 180 | .proto = protocol, |
180 | .fl_ip_sport = sport, | 181 | .fl_ip_sport = sport, |
181 | .fl_ip_dport = dport }; | 182 | .fl_ip_dport = dport }; |
182 | int err; | ||
183 | struct net *net = sock_net(sk); | 183 | struct net *net = sock_net(sk); |
184 | struct rtable *rt; | ||
184 | 185 | ||
185 | if (inet_sk(sk)->transparent) | 186 | if (inet_sk(sk)->transparent) |
186 | fl.flags |= FLOWI_FLAG_ANYSRC; | 187 | fl.flags |= FLOWI_FLAG_ANYSRC; |
@@ -190,29 +191,29 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, | |||
190 | fl.flags |= FLOWI_FLAG_CAN_SLEEP; | 191 | fl.flags |= FLOWI_FLAG_CAN_SLEEP; |
191 | 192 | ||
192 | if (!dst || !src) { | 193 | if (!dst || !src) { |
193 | err = __ip_route_output_key(net, rp, &fl); | 194 | rt = __ip_route_output_key(net, &fl); |
194 | if (err) | 195 | if (IS_ERR(rt)) |
195 | return err; | 196 | return rt; |
196 | fl.fl4_dst = (*rp)->rt_dst; | 197 | fl.fl4_dst = rt->rt_dst; |
197 | fl.fl4_src = (*rp)->rt_src; | 198 | fl.fl4_src = rt->rt_src; |
198 | ip_rt_put(*rp); | 199 | ip_rt_put(rt); |
199 | *rp = NULL; | ||
200 | } | 200 | } |
201 | security_sk_classify_flow(sk, &fl); | 201 | security_sk_classify_flow(sk, &fl); |
202 | return ip_route_output_flow(net, rp, &fl, sk); | 202 | return ip_route_output_flow(net, &fl, sk); |
203 | } | 203 | } |
204 | 204 | ||
205 | static inline int ip_route_newports(struct rtable **rp, u8 protocol, | 205 | static inline struct rtable *ip_route_newports(struct rtable *rt, |
206 | __be16 orig_sport, __be16 orig_dport, | 206 | u8 protocol, __be16 orig_sport, |
207 | __be16 sport, __be16 dport, struct sock *sk) | 207 | __be16 orig_dport, __be16 sport, |
208 | __be16 dport, struct sock *sk) | ||
208 | { | 209 | { |
209 | if (sport != orig_sport || dport != orig_dport) { | 210 | if (sport != orig_sport || dport != orig_dport) { |
210 | struct flowi fl = { .oif = (*rp)->fl.oif, | 211 | struct flowi fl = { .oif = rt->fl.oif, |
211 | .mark = (*rp)->fl.mark, | 212 | .mark = rt->fl.mark, |
212 | .fl4_dst = (*rp)->fl.fl4_dst, | 213 | .fl4_dst = rt->fl.fl4_dst, |
213 | .fl4_src = (*rp)->fl.fl4_src, | 214 | .fl4_src = rt->fl.fl4_src, |
214 | .fl4_tos = (*rp)->fl.fl4_tos, | 215 | .fl4_tos = rt->fl.fl4_tos, |
215 | .proto = (*rp)->fl.proto, | 216 | .proto = rt->fl.proto, |
216 | .fl_ip_sport = sport, | 217 | .fl_ip_sport = sport, |
217 | .fl_ip_dport = dport }; | 218 | .fl_ip_dport = dport }; |
218 | 219 | ||
@@ -220,12 +221,11 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol, | |||
220 | fl.flags |= FLOWI_FLAG_ANYSRC; | 221 | fl.flags |= FLOWI_FLAG_ANYSRC; |
221 | if (protocol == IPPROTO_TCP) | 222 | if (protocol == IPPROTO_TCP) |
222 | fl.flags |= FLOWI_FLAG_PRECOW_METRICS; | 223 | fl.flags |= FLOWI_FLAG_PRECOW_METRICS; |
223 | ip_rt_put(*rp); | 224 | ip_rt_put(rt); |
224 | *rp = NULL; | ||
225 | security_sk_classify_flow(sk, &fl); | 225 | security_sk_classify_flow(sk, &fl); |
226 | return ip_route_output_flow(sock_net(sk), rp, &fl, sk); | 226 | return ip_route_output_flow(sock_net(sk), &fl, sk); |
227 | } | 227 | } |
228 | return 0; | 228 | return rt; |
229 | } | 229 | } |
230 | 230 | ||
231 | extern void rt_bind_peer(struct rtable *rt, int create); | 231 | extern void rt_bind_peer(struct rtable *rt, int create); |
diff --git a/net/atm/clip.c b/net/atm/clip.c index d257da50fcfb..810a1294eddb 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -520,9 +520,9 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip) | |||
520 | unlink_clip_vcc(clip_vcc); | 520 | unlink_clip_vcc(clip_vcc); |
521 | return 0; | 521 | return 0; |
522 | } | 522 | } |
523 | error = ip_route_output_key(&init_net, &rt, &fl); | 523 | rt = ip_route_output_key(&init_net, &fl); |
524 | if (error) | 524 | if (IS_ERR(rt)) |
525 | return error; | 525 | return PTR_ERR(rt); |
526 | neigh = __neigh_lookup(&clip_tbl, &ip, rt->dst.dev, 1); | 526 | neigh = __neigh_lookup(&clip_tbl, &ip, rt->dst.dev, 1); |
527 | ip_rt_put(rt); | 527 | ip_rt_put(rt); |
528 | if (!neigh) | 528 | if (!neigh) |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 4b5b66d07bba..45b57b173f70 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -428,14 +428,15 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
428 | if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev)) | 428 | if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev)) |
429 | goto free_skb; | 429 | goto free_skb; |
430 | 430 | ||
431 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 431 | rt = ip_route_output_key(dev_net(dev), &fl); |
432 | if (!IS_ERR(rt)) { | ||
432 | /* - Bridged-and-DNAT'ed traffic doesn't | 433 | /* - Bridged-and-DNAT'ed traffic doesn't |
433 | * require ip_forwarding. */ | 434 | * require ip_forwarding. */ |
434 | if (((struct dst_entry *)rt)->dev == dev) { | 435 | if (rt->dst.dev == dev) { |
435 | skb_dst_set(skb, (struct dst_entry *)rt); | 436 | skb_dst_set(skb, &rt->dst); |
436 | goto bridged_dnat; | 437 | goto bridged_dnat; |
437 | } | 438 | } |
438 | dst_release((struct dst_entry *)rt); | 439 | ip_rt_put(rt); |
439 | } | 440 | } |
440 | free_skb: | 441 | free_skb: |
441 | kfree_skb(skb); | 442 | kfree_skb(skb); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index a8ff95502081..7882377bc62e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -46,7 +46,6 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
46 | __be16 orig_sport, orig_dport; | 46 | __be16 orig_sport, orig_dport; |
47 | struct rtable *rt; | 47 | struct rtable *rt; |
48 | __be32 daddr, nexthop; | 48 | __be32 daddr, nexthop; |
49 | int tmp; | ||
50 | int err; | 49 | int err; |
51 | 50 | ||
52 | dp->dccps_role = DCCP_ROLE_CLIENT; | 51 | dp->dccps_role = DCCP_ROLE_CLIENT; |
@@ -66,12 +65,12 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
66 | 65 | ||
67 | orig_sport = inet->inet_sport; | 66 | orig_sport = inet->inet_sport; |
68 | orig_dport = usin->sin_port; | 67 | orig_dport = usin->sin_port; |
69 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, | 68 | rt = ip_route_connect(nexthop, inet->inet_saddr, |
70 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 69 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
71 | IPPROTO_DCCP, | 70 | IPPROTO_DCCP, |
72 | orig_sport, orig_dport, sk, true); | 71 | orig_sport, orig_dport, sk, true); |
73 | if (tmp < 0) | 72 | if (IS_ERR(rt)) |
74 | return tmp; | 73 | return PTR_ERR(rt); |
75 | 74 | ||
76 | if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { | 75 | if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { |
77 | ip_rt_put(rt); | 76 | ip_rt_put(rt); |
@@ -102,12 +101,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
102 | if (err != 0) | 101 | if (err != 0) |
103 | goto failure; | 102 | goto failure; |
104 | 103 | ||
105 | err = ip_route_newports(&rt, IPPROTO_DCCP, | 104 | rt = ip_route_newports(rt, IPPROTO_DCCP, |
106 | orig_sport, orig_dport, | 105 | orig_sport, orig_dport, |
107 | inet->inet_sport, inet->inet_dport, sk); | 106 | inet->inet_sport, inet->inet_dport, sk); |
108 | if (err != 0) | 107 | if (IS_ERR(rt)) { |
108 | rt = NULL; | ||
109 | goto failure; | 109 | goto failure; |
110 | 110 | } | |
111 | /* OK, now commit destination to socket. */ | 111 | /* OK, now commit destination to socket. */ |
112 | sk_setup_caps(sk, &rt->dst); | 112 | sk_setup_caps(sk, &rt->dst); |
113 | 113 | ||
@@ -475,7 +475,8 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, | |||
475 | }; | 475 | }; |
476 | 476 | ||
477 | security_skb_classify_flow(skb, &fl); | 477 | security_skb_classify_flow(skb, &fl); |
478 | if (ip_route_output_flow(net, &rt, &fl, sk)) { | 478 | rt = ip_route_output_flow(net, &fl, sk); |
479 | if (IS_ERR(rt)) { | ||
479 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | 480 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); |
480 | return NULL; | 481 | return NULL; |
481 | } | 482 | } |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 44513bb8ac2e..35a502055018 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1101,23 +1101,20 @@ int sysctl_ip_dynaddr __read_mostly; | |||
1101 | static int inet_sk_reselect_saddr(struct sock *sk) | 1101 | static int inet_sk_reselect_saddr(struct sock *sk) |
1102 | { | 1102 | { |
1103 | struct inet_sock *inet = inet_sk(sk); | 1103 | struct inet_sock *inet = inet_sk(sk); |
1104 | int err; | ||
1105 | struct rtable *rt; | ||
1106 | __be32 old_saddr = inet->inet_saddr; | 1104 | __be32 old_saddr = inet->inet_saddr; |
1107 | __be32 new_saddr; | ||
1108 | __be32 daddr = inet->inet_daddr; | 1105 | __be32 daddr = inet->inet_daddr; |
1106 | struct rtable *rt; | ||
1107 | __be32 new_saddr; | ||
1109 | 1108 | ||
1110 | if (inet->opt && inet->opt->srr) | 1109 | if (inet->opt && inet->opt->srr) |
1111 | daddr = inet->opt->faddr; | 1110 | daddr = inet->opt->faddr; |
1112 | 1111 | ||
1113 | /* Query new route. */ | 1112 | /* Query new route. */ |
1114 | err = ip_route_connect(&rt, daddr, 0, | 1113 | rt = ip_route_connect(daddr, 0, RT_CONN_FLAGS(sk), |
1115 | RT_CONN_FLAGS(sk), | 1114 | sk->sk_bound_dev_if, sk->sk_protocol, |
1116 | sk->sk_bound_dev_if, | 1115 | inet->inet_sport, inet->inet_dport, sk, false); |
1117 | sk->sk_protocol, | 1116 | if (IS_ERR(rt)) |
1118 | inet->inet_sport, inet->inet_dport, sk, false); | 1117 | return PTR_ERR(rt); |
1119 | if (err) | ||
1120 | return err; | ||
1121 | 1118 | ||
1122 | sk_setup_caps(sk, &rt->dst); | 1119 | sk_setup_caps(sk, &rt->dst); |
1123 | 1120 | ||
@@ -1160,7 +1157,7 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1160 | daddr = inet->inet_daddr; | 1157 | daddr = inet->inet_daddr; |
1161 | if (inet->opt && inet->opt->srr) | 1158 | if (inet->opt && inet->opt->srr) |
1162 | daddr = inet->opt->faddr; | 1159 | daddr = inet->opt->faddr; |
1163 | { | 1160 | { |
1164 | struct flowi fl = { | 1161 | struct flowi fl = { |
1165 | .oif = sk->sk_bound_dev_if, | 1162 | .oif = sk->sk_bound_dev_if, |
1166 | .mark = sk->sk_mark, | 1163 | .mark = sk->sk_mark, |
@@ -1174,11 +1171,14 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1174 | }; | 1171 | }; |
1175 | 1172 | ||
1176 | security_sk_classify_flow(sk, &fl); | 1173 | security_sk_classify_flow(sk, &fl); |
1177 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk); | 1174 | rt = ip_route_output_flow(sock_net(sk), &fl, sk); |
1178 | } | 1175 | } |
1179 | if (!err) | 1176 | if (!IS_ERR(rt)) { |
1177 | err = 0; | ||
1180 | sk_setup_caps(sk, &rt->dst); | 1178 | sk_setup_caps(sk, &rt->dst); |
1181 | else { | 1179 | } else { |
1180 | err = PTR_ERR(rt); | ||
1181 | |||
1182 | /* Routing failed... */ | 1182 | /* Routing failed... */ |
1183 | sk->sk_route_caps = 0; | 1183 | sk->sk_route_caps = 0; |
1184 | /* | 1184 | /* |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 7927589813b5..fa9988da1da4 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -440,7 +440,8 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) | |||
440 | /*unsigned long now; */ | 440 | /*unsigned long now; */ |
441 | struct net *net = dev_net(dev); | 441 | struct net *net = dev_net(dev); |
442 | 442 | ||
443 | if (ip_route_output_key(net, &rt, &fl) < 0) | 443 | rt = ip_route_output_key(net, &fl); |
444 | if (IS_ERR(rt)) | ||
444 | return 1; | 445 | return 1; |
445 | if (rt->dst.dev != dev) { | 446 | if (rt->dst.dev != dev) { |
446 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); | 447 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); |
@@ -1063,10 +1064,10 @@ static int arp_req_set(struct net *net, struct arpreq *r, | |||
1063 | if (dev == NULL) { | 1064 | if (dev == NULL) { |
1064 | struct flowi fl = { .fl4_dst = ip, | 1065 | struct flowi fl = { .fl4_dst = ip, |
1065 | .fl4_tos = RTO_ONLINK }; | 1066 | .fl4_tos = RTO_ONLINK }; |
1066 | struct rtable *rt; | 1067 | struct rtable *rt = ip_route_output_key(net, &fl); |
1067 | err = ip_route_output_key(net, &rt, &fl); | 1068 | |
1068 | if (err != 0) | 1069 | if (IS_ERR(rt)) |
1069 | return err; | 1070 | return PTR_ERR(rt); |
1070 | dev = rt->dst.dev; | 1071 | dev = rt->dst.dev; |
1071 | ip_rt_put(rt); | 1072 | ip_rt_put(rt); |
1072 | if (!dev) | 1073 | if (!dev) |
@@ -1177,7 +1178,6 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r, | |||
1177 | static int arp_req_delete(struct net *net, struct arpreq *r, | 1178 | static int arp_req_delete(struct net *net, struct arpreq *r, |
1178 | struct net_device *dev) | 1179 | struct net_device *dev) |
1179 | { | 1180 | { |
1180 | int err; | ||
1181 | __be32 ip; | 1181 | __be32 ip; |
1182 | 1182 | ||
1183 | if (r->arp_flags & ATF_PUBL) | 1183 | if (r->arp_flags & ATF_PUBL) |
@@ -1187,10 +1187,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r, | |||
1187 | if (dev == NULL) { | 1187 | if (dev == NULL) { |
1188 | struct flowi fl = { .fl4_dst = ip, | 1188 | struct flowi fl = { .fl4_dst = ip, |
1189 | .fl4_tos = RTO_ONLINK }; | 1189 | .fl4_tos = RTO_ONLINK }; |
1190 | struct rtable *rt; | 1190 | struct rtable *rt = ip_route_output_key(net, &fl); |
1191 | err = ip_route_output_key(net, &rt, &fl); | 1191 | if (IS_ERR(rt)) |
1192 | if (err != 0) | 1192 | return PTR_ERR(rt); |
1193 | return err; | ||
1194 | dev = rt->dst.dev; | 1193 | dev = rt->dst.dev; |
1195 | ip_rt_put(rt); | 1194 | ip_rt_put(rt); |
1196 | if (!dev) | 1195 | if (!dev) |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index eaee1edd2dd7..85bd24ca4f6d 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
@@ -46,11 +46,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
46 | if (!saddr) | 46 | if (!saddr) |
47 | saddr = inet->mc_addr; | 47 | saddr = inet->mc_addr; |
48 | } | 48 | } |
49 | err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr, | 49 | rt = ip_route_connect(usin->sin_addr.s_addr, saddr, |
50 | RT_CONN_FLAGS(sk), oif, | 50 | RT_CONN_FLAGS(sk), oif, |
51 | sk->sk_protocol, | 51 | sk->sk_protocol, |
52 | inet->inet_sport, usin->sin_port, sk, true); | 52 | inet->inet_sport, usin->sin_port, sk, true); |
53 | if (err) { | 53 | if (IS_ERR(rt)) { |
54 | err = PTR_ERR(rt); | ||
54 | if (err == -ENETUNREACH) | 55 | if (err == -ENETUNREACH) |
55 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 56 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
56 | return err; | 57 | return err; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index c23bd8cdeee0..994a785d98f9 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -358,7 +358,8 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
358 | .fl4_tos = RT_TOS(ip_hdr(skb)->tos), | 358 | .fl4_tos = RT_TOS(ip_hdr(skb)->tos), |
359 | .proto = IPPROTO_ICMP }; | 359 | .proto = IPPROTO_ICMP }; |
360 | security_skb_classify_flow(skb, &fl); | 360 | security_skb_classify_flow(skb, &fl); |
361 | if (ip_route_output_key(net, &rt, &fl)) | 361 | rt = ip_route_output_key(net, &fl); |
362 | if (IS_ERR(rt)) | ||
362 | goto out_unlock; | 363 | goto out_unlock; |
363 | } | 364 | } |
364 | if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, | 365 | 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, | |||
388 | int err; | 389 | int err; |
389 | 390 | ||
390 | security_skb_classify_flow(skb_in, &fl); | 391 | security_skb_classify_flow(skb_in, &fl); |
391 | err = __ip_route_output_key(net, &rt, &fl); | 392 | rt = __ip_route_output_key(net, &fl); |
392 | if (err) | 393 | if (IS_ERR(rt)) |
393 | return ERR_PTR(err); | 394 | return rt; |
394 | 395 | ||
395 | /* No need to clone since we're just using its address. */ | 396 | /* No need to clone since we're just using its address. */ |
396 | rt2 = rt; | 397 | rt2 = rt; |
@@ -412,15 +413,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, | |||
412 | goto relookup_failed; | 413 | goto relookup_failed; |
413 | 414 | ||
414 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) { | 415 | if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) { |
415 | err = __ip_route_output_key(net, &rt2, &fl); | 416 | rt2 = __ip_route_output_key(net, &fl); |
417 | if (IS_ERR(rt2)) | ||
418 | err = PTR_ERR(rt2); | ||
416 | } else { | 419 | } else { |
417 | struct flowi fl2 = {}; | 420 | struct flowi fl2 = {}; |
418 | unsigned long orefdst; | 421 | unsigned long orefdst; |
419 | 422 | ||
420 | fl2.fl4_dst = fl.fl4_src; | 423 | fl2.fl4_dst = fl.fl4_src; |
421 | err = ip_route_output_key(net, &rt2, &fl2); | 424 | rt2 = ip_route_output_key(net, &fl2); |
422 | if (err) | 425 | if (IS_ERR(rt2)) { |
426 | err = PTR_ERR(rt2); | ||
423 | goto relookup_failed; | 427 | goto relookup_failed; |
428 | } | ||
424 | /* Ugh! */ | 429 | /* Ugh! */ |
425 | orefdst = skb_in->_skb_refdst; /* save old refdst */ | 430 | orefdst = skb_in->_skb_refdst; /* save old refdst */ |
426 | err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, | 431 | err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index e0e77e297de3..44ba9068b72f 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -325,7 +325,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
325 | struct flowi fl = { .oif = dev->ifindex, | 325 | struct flowi fl = { .oif = dev->ifindex, |
326 | .fl4_dst = IGMPV3_ALL_MCR, | 326 | .fl4_dst = IGMPV3_ALL_MCR, |
327 | .proto = IPPROTO_IGMP }; | 327 | .proto = IPPROTO_IGMP }; |
328 | if (ip_route_output_key(net, &rt, &fl)) { | 328 | rt = ip_route_output_key(net, &fl); |
329 | if (IS_ERR(rt)) { | ||
329 | kfree_skb(skb); | 330 | kfree_skb(skb); |
330 | return NULL; | 331 | return NULL; |
331 | } | 332 | } |
@@ -670,7 +671,8 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
670 | struct flowi fl = { .oif = dev->ifindex, | 671 | struct flowi fl = { .oif = dev->ifindex, |
671 | .fl4_dst = dst, | 672 | .fl4_dst = dst, |
672 | .proto = IPPROTO_IGMP }; | 673 | .proto = IPPROTO_IGMP }; |
673 | if (ip_route_output_key(net, &rt, &fl)) | 674 | rt = ip_route_output_key(net, &fl); |
675 | if (IS_ERR(rt)) | ||
674 | return -1; | 676 | return -1; |
675 | } | 677 | } |
676 | if (rt->rt_src == 0) { | 678 | if (rt->rt_src == 0) { |
@@ -1440,7 +1442,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev) | |||
1440 | static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) | 1442 | static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) |
1441 | { | 1443 | { |
1442 | struct flowi fl = { .fl4_dst = imr->imr_multiaddr.s_addr }; | 1444 | struct flowi fl = { .fl4_dst = imr->imr_multiaddr.s_addr }; |
1443 | struct rtable *rt; | ||
1444 | struct net_device *dev = NULL; | 1445 | struct net_device *dev = NULL; |
1445 | struct in_device *idev = NULL; | 1446 | struct in_device *idev = NULL; |
1446 | 1447 | ||
@@ -1454,9 +1455,12 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) | |||
1454 | return NULL; | 1455 | return NULL; |
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | if (!dev && !ip_route_output_key(net, &rt, &fl)) { | 1458 | if (!dev) { |
1458 | dev = rt->dst.dev; | 1459 | struct rtable *rt = ip_route_output_key(net, &fl); |
1459 | ip_rt_put(rt); | 1460 | if (!IS_ERR(rt)) { |
1461 | dev = rt->dst.dev; | ||
1462 | ip_rt_put(rt); | ||
1463 | } | ||
1460 | } | 1464 | } |
1461 | if (dev) { | 1465 | if (dev) { |
1462 | imr->imr_ifindex = dev->ifindex; | 1466 | imr->imr_ifindex = dev->ifindex; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 7f85d4aec26a..e4e301a61c5b 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -369,7 +369,8 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, | |||
369 | struct net *net = sock_net(sk); | 369 | struct net *net = sock_net(sk); |
370 | 370 | ||
371 | security_req_classify_flow(req, &fl); | 371 | security_req_classify_flow(req, &fl); |
372 | if (ip_route_output_flow(net, &rt, &fl, sk)) | 372 | rt = ip_route_output_flow(net, &fl, sk); |
373 | if (IS_ERR(rt)) | ||
373 | goto no_route; | 374 | goto no_route; |
374 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 375 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) |
375 | goto route_err; | 376 | goto route_err; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 6613edfac28c..f9af98dd7561 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -778,7 +778,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
778 | .proto = IPPROTO_GRE, | 778 | .proto = IPPROTO_GRE, |
779 | .fl_gre_key = tunnel->parms.o_key | 779 | .fl_gre_key = tunnel->parms.o_key |
780 | }; | 780 | }; |
781 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 781 | rt = ip_route_output_key(dev_net(dev), &fl); |
782 | if (IS_ERR(rt)) { | ||
782 | dev->stats.tx_carrier_errors++; | 783 | dev->stats.tx_carrier_errors++; |
783 | goto tx_error; | 784 | goto tx_error; |
784 | } | 785 | } |
@@ -953,9 +954,9 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) | |||
953 | .proto = IPPROTO_GRE, | 954 | .proto = IPPROTO_GRE, |
954 | .fl_gre_key = tunnel->parms.o_key | 955 | .fl_gre_key = tunnel->parms.o_key |
955 | }; | 956 | }; |
956 | struct rtable *rt; | 957 | struct rtable *rt = ip_route_output_key(dev_net(dev), &fl); |
957 | 958 | ||
958 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 959 | if (!IS_ERR(rt)) { |
959 | tdev = rt->dst.dev; | 960 | tdev = rt->dst.dev; |
960 | ip_rt_put(rt); | 961 | ip_rt_put(rt); |
961 | } | 962 | } |
@@ -1215,9 +1216,9 @@ static int ipgre_open(struct net_device *dev) | |||
1215 | .proto = IPPROTO_GRE, | 1216 | .proto = IPPROTO_GRE, |
1216 | .fl_gre_key = t->parms.o_key | 1217 | .fl_gre_key = t->parms.o_key |
1217 | }; | 1218 | }; |
1218 | struct rtable *rt; | 1219 | struct rtable *rt = ip_route_output_key(dev_net(dev), &fl); |
1219 | 1220 | ||
1220 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) | 1221 | if (IS_ERR(rt)) |
1221 | return -EADDRNOTAVAIL; | 1222 | return -EADDRNOTAVAIL; |
1222 | dev = rt->dst.dev; | 1223 | dev = rt->dst.dev; |
1223 | ip_rt_put(rt); | 1224 | ip_rt_put(rt); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 33316b3534ca..171f483b21d5 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -355,7 +355,8 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
355 | * itself out. | 355 | * itself out. |
356 | */ | 356 | */ |
357 | security_sk_classify_flow(sk, &fl); | 357 | security_sk_classify_flow(sk, &fl); |
358 | if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk)) | 358 | rt = ip_route_output_flow(sock_net(sk), &fl, sk); |
359 | if (IS_ERR(rt)) | ||
359 | goto no_route; | 360 | goto no_route; |
360 | } | 361 | } |
361 | sk_setup_caps(sk, &rt->dst); | 362 | 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 | |||
1489 | .proto = sk->sk_protocol, | 1490 | .proto = sk->sk_protocol, |
1490 | .flags = ip_reply_arg_flowi_flags(arg) }; | 1491 | .flags = ip_reply_arg_flowi_flags(arg) }; |
1491 | security_skb_classify_flow(skb, &fl); | 1492 | security_skb_classify_flow(skb, &fl); |
1492 | if (ip_route_output_key(sock_net(sk), &rt, &fl)) | 1493 | rt = ip_route_output_key(sock_net(sk), &fl); |
1494 | if (IS_ERR(rt)) | ||
1493 | return; | 1495 | return; |
1494 | } | 1496 | } |
1495 | 1497 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 988f52fba54a..e1e17576baa6 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -469,7 +469,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
469 | .proto = IPPROTO_IPIP | 469 | .proto = IPPROTO_IPIP |
470 | }; | 470 | }; |
471 | 471 | ||
472 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 472 | rt = ip_route_output_key(dev_net(dev), &fl); |
473 | if (IS_ERR(rt)) { | ||
473 | dev->stats.tx_carrier_errors++; | 474 | dev->stats.tx_carrier_errors++; |
474 | goto tx_error_icmp; | 475 | goto tx_error_icmp; |
475 | } | 476 | } |
@@ -590,9 +591,9 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) | |||
590 | .fl4_tos = RT_TOS(iph->tos), | 591 | .fl4_tos = RT_TOS(iph->tos), |
591 | .proto = IPPROTO_IPIP | 592 | .proto = IPPROTO_IPIP |
592 | }; | 593 | }; |
593 | struct rtable *rt; | 594 | struct rtable *rt = ip_route_output_key(dev_net(dev), &fl); |
594 | 595 | ||
595 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 596 | if (!IS_ERR(rt)) { |
596 | tdev = rt->dst.dev; | 597 | tdev = rt->dst.dev; |
597 | ip_rt_put(rt); | 598 | ip_rt_put(rt); |
598 | } | 599 | } |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8b65a12654e7..26ca2f2d37ce 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -1618,8 +1618,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1618 | .fl4_tos = RT_TOS(iph->tos), | 1618 | .fl4_tos = RT_TOS(iph->tos), |
1619 | .proto = IPPROTO_IPIP | 1619 | .proto = IPPROTO_IPIP |
1620 | }; | 1620 | }; |
1621 | 1621 | rt = ip_route_output_key(net, &fl); | |
1622 | if (ip_route_output_key(net, &rt, &fl)) | 1622 | if (IS_ERR(rt)) |
1623 | goto out_free; | 1623 | goto out_free; |
1624 | encap = sizeof(struct iphdr); | 1624 | encap = sizeof(struct iphdr); |
1625 | } else { | 1625 | } else { |
@@ -1629,8 +1629,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1629 | .fl4_tos = RT_TOS(iph->tos), | 1629 | .fl4_tos = RT_TOS(iph->tos), |
1630 | .proto = IPPROTO_IPIP | 1630 | .proto = IPPROTO_IPIP |
1631 | }; | 1631 | }; |
1632 | 1632 | rt = ip_route_output_key(net, &fl); | |
1633 | if (ip_route_output_key(net, &rt, &fl)) | 1633 | if (IS_ERR(rt)) |
1634 | goto out_free; | 1634 | goto out_free; |
1635 | } | 1635 | } |
1636 | 1636 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 9770bb427952..67bf709180de 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -38,7 +38,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
38 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; | 38 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
39 | fl.mark = skb->mark; | 39 | fl.mark = skb->mark; |
40 | fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; | 40 | fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; |
41 | if (ip_route_output_key(net, &rt, &fl) != 0) | 41 | rt = ip_route_output_key(net, &fl); |
42 | if (IS_ERR(rt)) | ||
42 | return -1; | 43 | return -1; |
43 | 44 | ||
44 | /* Drop old route. */ | 45 | /* Drop old route. */ |
@@ -48,7 +49,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
48 | /* non-local src, find valid iif to satisfy | 49 | /* non-local src, find valid iif to satisfy |
49 | * rp-filter when calling ip_route_input. */ | 50 | * rp-filter when calling ip_route_input. */ |
50 | fl.fl4_dst = iph->saddr; | 51 | fl.fl4_dst = iph->saddr; |
51 | if (ip_route_output_key(net, &rt, &fl) != 0) | 52 | rt = ip_route_output_key(net, &fl); |
53 | if (IS_ERR(rt)) | ||
52 | return -1; | 54 | return -1; |
53 | 55 | ||
54 | orefdst = skb->_skb_refdst; | 56 | orefdst = skb->_skb_refdst; |
@@ -221,7 +223,11 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
221 | 223 | ||
222 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) | 224 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) |
223 | { | 225 | { |
224 | return ip_route_output_key(&init_net, (struct rtable **)dst, fl); | 226 | struct rtable *rt = ip_route_output_key(&init_net, fl); |
227 | if (IS_ERR(rt)) | ||
228 | return PTR_ERR(rt); | ||
229 | *dst = &rt->dst; | ||
230 | return 0; | ||
225 | } | 231 | } |
226 | 232 | ||
227 | static const struct nf_afinfo nf_ip_afinfo = { | 233 | static const struct nf_afinfo nf_ip_afinfo = { |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index d7a2d1eaec09..467d570d087a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -564,10 +564,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
564 | } | 564 | } |
565 | 565 | ||
566 | security_sk_classify_flow(sk, &fl); | 566 | security_sk_classify_flow(sk, &fl); |
567 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk); | 567 | rt = ip_route_output_flow(sock_net(sk), &fl, sk); |
568 | if (IS_ERR(rt)) { | ||
569 | err = PTR_ERR(rt); | ||
570 | goto done; | ||
571 | } | ||
568 | } | 572 | } |
569 | if (err) | ||
570 | goto done; | ||
571 | 573 | ||
572 | err = -EACCES; | 574 | err = -EACCES; |
573 | if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST)) | 575 | if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST)) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 63d37004ee66..5090e956f6b8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1014,8 +1014,8 @@ static int slow_chain_length(const struct rtable *head) | |||
1014 | return length >> FRACT_BITS; | 1014 | return length >> FRACT_BITS; |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | static int rt_intern_hash(unsigned hash, struct rtable *rt, | 1017 | static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt, |
1018 | struct rtable **rp, struct sk_buff *skb, int ifindex) | 1018 | struct sk_buff *skb, int ifindex) |
1019 | { | 1019 | { |
1020 | struct rtable *rth, *cand; | 1020 | struct rtable *rth, *cand; |
1021 | struct rtable __rcu **rthp, **candp; | 1021 | struct rtable __rcu **rthp, **candp; |
@@ -1056,7 +1056,7 @@ restart: | |||
1056 | printk(KERN_WARNING | 1056 | printk(KERN_WARNING |
1057 | "Neighbour table failure & not caching routes.\n"); | 1057 | "Neighbour table failure & not caching routes.\n"); |
1058 | ip_rt_put(rt); | 1058 | ip_rt_put(rt); |
1059 | return err; | 1059 | return ERR_PTR(err); |
1060 | } | 1060 | } |
1061 | } | 1061 | } |
1062 | 1062 | ||
@@ -1093,11 +1093,9 @@ restart: | |||
1093 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1093 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1094 | 1094 | ||
1095 | rt_drop(rt); | 1095 | rt_drop(rt); |
1096 | if (rp) | 1096 | if (skb) |
1097 | *rp = rth; | ||
1098 | else | ||
1099 | skb_dst_set(skb, &rth->dst); | 1097 | skb_dst_set(skb, &rth->dst); |
1100 | return 0; | 1098 | return rth; |
1101 | } | 1099 | } |
1102 | 1100 | ||
1103 | if (!atomic_read(&rth->dst.__refcnt)) { | 1101 | if (!atomic_read(&rth->dst.__refcnt)) { |
@@ -1154,7 +1152,7 @@ restart: | |||
1154 | 1152 | ||
1155 | if (err != -ENOBUFS) { | 1153 | if (err != -ENOBUFS) { |
1156 | rt_drop(rt); | 1154 | rt_drop(rt); |
1157 | return err; | 1155 | return ERR_PTR(err); |
1158 | } | 1156 | } |
1159 | 1157 | ||
1160 | /* Neighbour tables are full and nothing | 1158 | /* Neighbour tables are full and nothing |
@@ -1175,7 +1173,7 @@ restart: | |||
1175 | if (net_ratelimit()) | 1173 | if (net_ratelimit()) |
1176 | printk(KERN_WARNING "ipv4: Neighbour table overflow.\n"); | 1174 | printk(KERN_WARNING "ipv4: Neighbour table overflow.\n"); |
1177 | rt_drop(rt); | 1175 | rt_drop(rt); |
1178 | return -ENOBUFS; | 1176 | return ERR_PTR(-ENOBUFS); |
1179 | } | 1177 | } |
1180 | } | 1178 | } |
1181 | 1179 | ||
@@ -1201,11 +1199,9 @@ restart: | |||
1201 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1199 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1202 | 1200 | ||
1203 | skip_hashing: | 1201 | skip_hashing: |
1204 | if (rp) | 1202 | if (skb) |
1205 | *rp = rt; | ||
1206 | else | ||
1207 | skb_dst_set(skb, &rt->dst); | 1203 | skb_dst_set(skb, &rt->dst); |
1208 | return 0; | 1204 | return rt; |
1209 | } | 1205 | } |
1210 | 1206 | ||
1211 | static atomic_t __rt_peer_genid = ATOMIC_INIT(0); | 1207 | static atomic_t __rt_peer_genid = ATOMIC_INIT(0); |
@@ -1896,7 +1892,10 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1896 | RT_CACHE_STAT_INC(in_slow_mc); | 1892 | RT_CACHE_STAT_INC(in_slow_mc); |
1897 | 1893 | ||
1898 | hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); | 1894 | hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); |
1899 | return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex); | 1895 | rth = rt_intern_hash(hash, rth, skb, dev->ifindex); |
1896 | err = 0; | ||
1897 | if (IS_ERR(rth)) | ||
1898 | err = PTR_ERR(rth); | ||
1900 | 1899 | ||
1901 | e_nobufs: | 1900 | e_nobufs: |
1902 | return -ENOBUFS; | 1901 | return -ENOBUFS; |
@@ -2051,7 +2050,10 @@ static int ip_mkroute_input(struct sk_buff *skb, | |||
2051 | /* put it into the cache */ | 2050 | /* put it into the cache */ |
2052 | hash = rt_hash(daddr, saddr, fl->iif, | 2051 | hash = rt_hash(daddr, saddr, fl->iif, |
2053 | rt_genid(dev_net(rth->dst.dev))); | 2052 | rt_genid(dev_net(rth->dst.dev))); |
2054 | return rt_intern_hash(hash, rth, NULL, skb, fl->iif); | 2053 | rth = rt_intern_hash(hash, rth, skb, fl->iif); |
2054 | if (IS_ERR(rth)) | ||
2055 | return PTR_ERR(rth); | ||
2056 | return 0; | ||
2055 | } | 2057 | } |
2056 | 2058 | ||
2057 | /* | 2059 | /* |
@@ -2194,7 +2196,10 @@ local_input: | |||
2194 | } | 2196 | } |
2195 | rth->rt_type = res.type; | 2197 | rth->rt_type = res.type; |
2196 | hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); | 2198 | hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); |
2197 | err = rt_intern_hash(hash, rth, NULL, skb, fl.iif); | 2199 | rth = rt_intern_hash(hash, rth, skb, fl.iif); |
2200 | err = 0; | ||
2201 | if (IS_ERR(rth)) | ||
2202 | err = PTR_ERR(rth); | ||
2198 | goto out; | 2203 | goto out; |
2199 | 2204 | ||
2200 | no_route: | 2205 | no_route: |
@@ -2422,8 +2427,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2422 | * called with rcu_read_lock(); | 2427 | * called with rcu_read_lock(); |
2423 | */ | 2428 | */ |
2424 | 2429 | ||
2425 | static int ip_route_output_slow(struct net *net, struct rtable **rp, | 2430 | static struct rtable *ip_route_output_slow(struct net *net, |
2426 | const struct flowi *oldflp) | 2431 | const struct flowi *oldflp) |
2427 | { | 2432 | { |
2428 | u32 tos = RT_FL_TOS(oldflp); | 2433 | u32 tos = RT_FL_TOS(oldflp); |
2429 | struct flowi fl = { .fl4_dst = oldflp->fl4_dst, | 2434 | struct flowi fl = { .fl4_dst = oldflp->fl4_dst, |
@@ -2438,8 +2443,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2438 | unsigned int flags = 0; | 2443 | unsigned int flags = 0; |
2439 | struct net_device *dev_out = NULL; | 2444 | struct net_device *dev_out = NULL; |
2440 | struct rtable *rth; | 2445 | struct rtable *rth; |
2441 | int err; | ||
2442 | |||
2443 | 2446 | ||
2444 | res.fi = NULL; | 2447 | res.fi = NULL; |
2445 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 2448 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
@@ -2448,7 +2451,7 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2448 | 2451 | ||
2449 | rcu_read_lock(); | 2452 | rcu_read_lock(); |
2450 | if (oldflp->fl4_src) { | 2453 | if (oldflp->fl4_src) { |
2451 | err = -EINVAL; | 2454 | rth = ERR_PTR(-EINVAL); |
2452 | if (ipv4_is_multicast(oldflp->fl4_src) || | 2455 | if (ipv4_is_multicast(oldflp->fl4_src) || |
2453 | ipv4_is_lbcast(oldflp->fl4_src) || | 2456 | ipv4_is_lbcast(oldflp->fl4_src) || |
2454 | ipv4_is_zeronet(oldflp->fl4_src)) | 2457 | ipv4_is_zeronet(oldflp->fl4_src)) |
@@ -2499,13 +2502,13 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2499 | 2502 | ||
2500 | if (oldflp->oif) { | 2503 | if (oldflp->oif) { |
2501 | dev_out = dev_get_by_index_rcu(net, oldflp->oif); | 2504 | dev_out = dev_get_by_index_rcu(net, oldflp->oif); |
2502 | err = -ENODEV; | 2505 | rth = ERR_PTR(-ENODEV); |
2503 | if (dev_out == NULL) | 2506 | if (dev_out == NULL) |
2504 | goto out; | 2507 | goto out; |
2505 | 2508 | ||
2506 | /* RACE: Check return value of inet_select_addr instead. */ | 2509 | /* RACE: Check return value of inet_select_addr instead. */ |
2507 | if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) { | 2510 | if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) { |
2508 | err = -ENETUNREACH; | 2511 | rth = ERR_PTR(-ENETUNREACH); |
2509 | goto out; | 2512 | goto out; |
2510 | } | 2513 | } |
2511 | if (ipv4_is_local_multicast(oldflp->fl4_dst) || | 2514 | if (ipv4_is_local_multicast(oldflp->fl4_dst) || |
@@ -2563,7 +2566,7 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2563 | res.type = RTN_UNICAST; | 2566 | res.type = RTN_UNICAST; |
2564 | goto make_route; | 2567 | goto make_route; |
2565 | } | 2568 | } |
2566 | err = -ENETUNREACH; | 2569 | rth = ERR_PTR(-ENETUNREACH); |
2567 | goto out; | 2570 | goto out; |
2568 | } | 2571 | } |
2569 | 2572 | ||
@@ -2598,23 +2601,20 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2598 | 2601 | ||
2599 | make_route: | 2602 | make_route: |
2600 | rth = __mkroute_output(&res, &fl, oldflp, dev_out, flags); | 2603 | rth = __mkroute_output(&res, &fl, oldflp, dev_out, flags); |
2601 | if (IS_ERR(rth)) | 2604 | if (!IS_ERR(rth)) { |
2602 | err = PTR_ERR(rth); | ||
2603 | else { | ||
2604 | unsigned int hash; | 2605 | unsigned int hash; |
2605 | 2606 | ||
2606 | hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, | 2607 | hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, |
2607 | rt_genid(dev_net(dev_out))); | 2608 | rt_genid(dev_net(dev_out))); |
2608 | err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif); | 2609 | rth = rt_intern_hash(hash, rth, NULL, oldflp->oif); |
2609 | } | 2610 | } |
2610 | 2611 | ||
2611 | out: | 2612 | out: |
2612 | rcu_read_unlock(); | 2613 | rcu_read_unlock(); |
2613 | return err; | 2614 | return rth; |
2614 | } | 2615 | } |
2615 | 2616 | ||
2616 | int __ip_route_output_key(struct net *net, struct rtable **rp, | 2617 | struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp) |
2617 | const struct flowi *flp) | ||
2618 | { | 2618 | { |
2619 | struct rtable *rth; | 2619 | struct rtable *rth; |
2620 | unsigned int hash; | 2620 | unsigned int hash; |
@@ -2639,15 +2639,14 @@ int __ip_route_output_key(struct net *net, struct rtable **rp, | |||
2639 | dst_use(&rth->dst, jiffies); | 2639 | dst_use(&rth->dst, jiffies); |
2640 | RT_CACHE_STAT_INC(out_hit); | 2640 | RT_CACHE_STAT_INC(out_hit); |
2641 | rcu_read_unlock_bh(); | 2641 | rcu_read_unlock_bh(); |
2642 | *rp = rth; | 2642 | return rth; |
2643 | return 0; | ||
2644 | } | 2643 | } |
2645 | RT_CACHE_STAT_INC(out_hlist_search); | 2644 | RT_CACHE_STAT_INC(out_hlist_search); |
2646 | } | 2645 | } |
2647 | rcu_read_unlock_bh(); | 2646 | rcu_read_unlock_bh(); |
2648 | 2647 | ||
2649 | slow_output: | 2648 | slow_output: |
2650 | return ip_route_output_slow(net, rp, flp); | 2649 | return ip_route_output_slow(net, flp); |
2651 | } | 2650 | } |
2652 | EXPORT_SYMBOL_GPL(__ip_route_output_key); | 2651 | EXPORT_SYMBOL_GPL(__ip_route_output_key); |
2653 | 2652 | ||
@@ -2717,34 +2716,29 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2717 | return rt ? &rt->dst : ERR_PTR(-ENOMEM); | 2716 | return rt ? &rt->dst : ERR_PTR(-ENOMEM); |
2718 | } | 2717 | } |
2719 | 2718 | ||
2720 | int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp, | 2719 | struct rtable *ip_route_output_flow(struct net *net, struct flowi *flp, |
2721 | struct sock *sk) | 2720 | struct sock *sk) |
2722 | { | 2721 | { |
2723 | int err; | 2722 | struct rtable *rt = __ip_route_output_key(net, flp); |
2724 | 2723 | ||
2725 | if ((err = __ip_route_output_key(net, rp, flp)) != 0) | 2724 | if (IS_ERR(rt)) |
2726 | return err; | 2725 | return rt; |
2727 | 2726 | ||
2728 | if (flp->proto) { | 2727 | if (flp->proto) { |
2729 | if (!flp->fl4_src) | 2728 | if (!flp->fl4_src) |
2730 | flp->fl4_src = (*rp)->rt_src; | 2729 | flp->fl4_src = rt->rt_src; |
2731 | if (!flp->fl4_dst) | 2730 | if (!flp->fl4_dst) |
2732 | flp->fl4_dst = (*rp)->rt_dst; | 2731 | flp->fl4_dst = rt->rt_dst; |
2733 | *rp = (struct rtable *) xfrm_lookup(net, &(*rp)->dst, flp, sk, 0); | 2732 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, flp, sk, 0); |
2734 | if (IS_ERR(*rp)) { | ||
2735 | err = PTR_ERR(*rp); | ||
2736 | *rp = NULL; | ||
2737 | return err; | ||
2738 | } | ||
2739 | } | 2733 | } |
2740 | 2734 | ||
2741 | return 0; | 2735 | return rt; |
2742 | } | 2736 | } |
2743 | EXPORT_SYMBOL_GPL(ip_route_output_flow); | 2737 | EXPORT_SYMBOL_GPL(ip_route_output_flow); |
2744 | 2738 | ||
2745 | int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp) | 2739 | struct rtable *ip_route_output_key(struct net *net, struct flowi *flp) |
2746 | { | 2740 | { |
2747 | return ip_route_output_flow(net, rp, flp, NULL); | 2741 | return ip_route_output_flow(net, flp, NULL); |
2748 | } | 2742 | } |
2749 | EXPORT_SYMBOL(ip_route_output_key); | 2743 | EXPORT_SYMBOL(ip_route_output_key); |
2750 | 2744 | ||
@@ -2915,7 +2909,11 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2915 | .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, | 2909 | .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, |
2916 | .mark = mark, | 2910 | .mark = mark, |
2917 | }; | 2911 | }; |
2918 | err = ip_route_output_key(net, &rt, &fl); | 2912 | rt = ip_route_output_key(net, &fl); |
2913 | |||
2914 | err = 0; | ||
2915 | if (IS_ERR(rt)) | ||
2916 | err = PTR_ERR(rt); | ||
2919 | } | 2917 | } |
2920 | 2918 | ||
2921 | if (err) | 2919 | if (err) |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 47519205a014..0ad6ddf638a7 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -355,7 +355,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
355 | .fl_ip_sport = th->dest, | 355 | .fl_ip_sport = th->dest, |
356 | .fl_ip_dport = th->source }; | 356 | .fl_ip_dport = th->source }; |
357 | security_req_classify_flow(req, &fl); | 357 | security_req_classify_flow(req, &fl); |
358 | if (ip_route_output_key(sock_net(sk), &rt, &fl)) { | 358 | rt = ip_route_output_key(sock_net(sk), &fl); |
359 | if (IS_ERR(rt)) { | ||
359 | reqsk_free(req); | 360 | reqsk_free(req); |
360 | goto out; | 361 | goto out; |
361 | } | 362 | } |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 05bc6d9455fc..f7e6c2c2d2bb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -152,7 +152,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
152 | __be16 orig_sport, orig_dport; | 152 | __be16 orig_sport, orig_dport; |
153 | struct rtable *rt; | 153 | struct rtable *rt; |
154 | __be32 daddr, nexthop; | 154 | __be32 daddr, nexthop; |
155 | int tmp; | ||
156 | int err; | 155 | int err; |
157 | 156 | ||
158 | if (addr_len < sizeof(struct sockaddr_in)) | 157 | if (addr_len < sizeof(struct sockaddr_in)) |
@@ -170,14 +169,15 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
170 | 169 | ||
171 | orig_sport = inet->inet_sport; | 170 | orig_sport = inet->inet_sport; |
172 | orig_dport = usin->sin_port; | 171 | orig_dport = usin->sin_port; |
173 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, | 172 | rt = ip_route_connect(nexthop, inet->inet_saddr, |
174 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 173 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
175 | IPPROTO_TCP, | 174 | IPPROTO_TCP, |
176 | orig_sport, orig_dport, sk, true); | 175 | orig_sport, orig_dport, sk, true); |
177 | if (tmp < 0) { | 176 | if (IS_ERR(rt)) { |
178 | if (tmp == -ENETUNREACH) | 177 | err = PTR_ERR(rt); |
178 | if (err == -ENETUNREACH) | ||
179 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 179 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
180 | return tmp; | 180 | return err; |
181 | } | 181 | } |
182 | 182 | ||
183 | if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { | 183 | if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { |
@@ -236,12 +236,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
236 | if (err) | 236 | if (err) |
237 | goto failure; | 237 | goto failure; |
238 | 238 | ||
239 | err = ip_route_newports(&rt, IPPROTO_TCP, | 239 | rt = ip_route_newports(rt, IPPROTO_TCP, |
240 | orig_sport, orig_dport, | 240 | orig_sport, orig_dport, |
241 | inet->inet_sport, inet->inet_dport, sk); | 241 | inet->inet_sport, inet->inet_dport, sk); |
242 | if (err) | 242 | if (IS_ERR(rt)) { |
243 | err = PTR_ERR(rt); | ||
244 | rt = NULL; | ||
243 | goto failure; | 245 | goto failure; |
244 | 246 | } | |
245 | /* OK, now commit destination to socket. */ | 247 | /* OK, now commit destination to socket. */ |
246 | sk->sk_gso_type = SKB_GSO_TCPV4; | 248 | sk->sk_gso_type = SKB_GSO_TCPV4; |
247 | sk_setup_caps(sk, &rt->dst); | 249 | sk_setup_caps(sk, &rt->dst); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ed9a5b7bee53..95e0c2c194a1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -922,8 +922,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
922 | struct net *net = sock_net(sk); | 922 | struct net *net = sock_net(sk); |
923 | 923 | ||
924 | security_sk_classify_flow(sk, &fl); | 924 | security_sk_classify_flow(sk, &fl); |
925 | err = ip_route_output_flow(net, &rt, &fl, sk); | 925 | rt = ip_route_output_flow(net, &fl, sk); |
926 | if (err) { | 926 | if (IS_ERR(rt)) { |
927 | err = PTR_ERR(rt); | ||
927 | if (err == -ENETUNREACH) | 928 | if (err == -ENETUNREACH) |
928 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | 929 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); |
929 | goto out; | 930 | goto out; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 5f0f058dc376..45b821480427 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -26,18 +26,16 @@ static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, | |||
26 | .fl4_dst = daddr->a4, | 26 | .fl4_dst = daddr->a4, |
27 | .fl4_tos = tos, | 27 | .fl4_tos = tos, |
28 | }; | 28 | }; |
29 | struct dst_entry *dst; | ||
30 | struct rtable *rt; | 29 | struct rtable *rt; |
31 | int err; | ||
32 | 30 | ||
33 | if (saddr) | 31 | if (saddr) |
34 | fl.fl4_src = saddr->a4; | 32 | fl.fl4_src = saddr->a4; |
35 | 33 | ||
36 | err = __ip_route_output_key(net, &rt, &fl); | 34 | rt = __ip_route_output_key(net, &fl); |
37 | dst = &rt->dst; | 35 | if (!IS_ERR(rt)) |
38 | if (err) | 36 | return &rt->dst; |
39 | dst = ERR_PTR(err); | 37 | |
40 | return dst; | 38 | return ERR_CAST(rt); |
41 | } | 39 | } |
42 | 40 | ||
43 | static int xfrm4_get_saddr(struct net *net, | 41 | static int xfrm4_get_saddr(struct net *net, |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index da43038ae18e..02730ef26b0f 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -581,7 +581,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
581 | fl.fl4_dst = eiph->saddr; | 581 | fl.fl4_dst = eiph->saddr; |
582 | fl.fl4_tos = RT_TOS(eiph->tos); | 582 | fl.fl4_tos = RT_TOS(eiph->tos); |
583 | fl.proto = IPPROTO_IPIP; | 583 | fl.proto = IPPROTO_IPIP; |
584 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) | 584 | rt = ip_route_output_key(dev_net(skb->dev), &fl); |
585 | if (IS_ERR(rt)) | ||
585 | goto out; | 586 | goto out; |
586 | 587 | ||
587 | skb2->dev = rt->dst.dev; | 588 | skb2->dev = rt->dst.dev; |
@@ -593,12 +594,14 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
593 | fl.fl4_dst = eiph->daddr; | 594 | fl.fl4_dst = eiph->daddr; |
594 | fl.fl4_src = eiph->saddr; | 595 | fl.fl4_src = eiph->saddr; |
595 | fl.fl4_tos = eiph->tos; | 596 | fl.fl4_tos = eiph->tos; |
596 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | 597 | rt = ip_route_output_key(dev_net(skb->dev), &fl); |
598 | if (IS_ERR(rt) || | ||
597 | rt->dst.dev->type != ARPHRD_TUNNEL) { | 599 | rt->dst.dev->type != ARPHRD_TUNNEL) { |
598 | ip_rt_put(rt); | 600 | if (!IS_ERR(rt)) |
601 | ip_rt_put(rt); | ||
599 | goto out; | 602 | goto out; |
600 | } | 603 | } |
601 | skb_dst_set(skb2, (struct dst_entry *)rt); | 604 | skb_dst_set(skb2, &rt->dst); |
602 | } else { | 605 | } else { |
603 | ip_rt_put(rt); | 606 | ip_rt_put(rt); |
604 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, | 607 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b1599a345c10..b8c8adbd7cf6 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -738,7 +738,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
738 | .fl4_tos = RT_TOS(tos), | 738 | .fl4_tos = RT_TOS(tos), |
739 | .oif = tunnel->parms.link, | 739 | .oif = tunnel->parms.link, |
740 | .proto = IPPROTO_IPV6 }; | 740 | .proto = IPPROTO_IPV6 }; |
741 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 741 | rt = ip_route_output_key(dev_net(dev), &fl); |
742 | if (IS_ERR(rt)) { | ||
742 | dev->stats.tx_carrier_errors++; | 743 | dev->stats.tx_carrier_errors++; |
743 | goto tx_error_icmp; | 744 | goto tx_error_icmp; |
744 | } | 745 | } |
@@ -862,8 +863,9 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
862 | .fl4_tos = RT_TOS(iph->tos), | 863 | .fl4_tos = RT_TOS(iph->tos), |
863 | .oif = tunnel->parms.link, | 864 | .oif = tunnel->parms.link, |
864 | .proto = IPPROTO_IPV6 }; | 865 | .proto = IPPROTO_IPV6 }; |
865 | struct rtable *rt; | 866 | struct rtable *rt = ip_route_output_key(dev_net(dev), &fl); |
866 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 867 | |
868 | if (!IS_ERR(rt)) { | ||
867 | tdev = rt->dst.dev; | 869 | tdev = rt->dst.dev; |
868 | ip_rt_put(rt); | 870 | ip_rt_put(rt); |
869 | } | 871 | } |
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 5381cebe516d..2a698ff89db6 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
@@ -320,11 +320,12 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
320 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) | 320 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) |
321 | goto out; | 321 | goto out; |
322 | 322 | ||
323 | rc = ip_route_connect(&rt, lsa->l2tp_addr.s_addr, saddr, | 323 | rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr, |
324 | RT_CONN_FLAGS(sk), oif, | 324 | RT_CONN_FLAGS(sk), oif, |
325 | IPPROTO_L2TP, | 325 | IPPROTO_L2TP, |
326 | 0, 0, sk, true); | 326 | 0, 0, sk, true); |
327 | if (rc) { | 327 | if (IS_ERR(rt)) { |
328 | rc = PTR_ERR(rt); | ||
328 | if (rc == -ENETUNREACH) | 329 | if (rc == -ENETUNREACH) |
329 | IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES); | 330 | IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES); |
330 | goto out; | 331 | goto out; |
@@ -489,7 +490,8 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
489 | * itself out. | 490 | * itself out. |
490 | */ | 491 | */ |
491 | security_sk_classify_flow(sk, &fl); | 492 | security_sk_classify_flow(sk, &fl); |
492 | if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk)) | 493 | rt = ip_route_output_flow(sock_net(sk), &fl, sk); |
494 | if (IS_ERR(rt)) | ||
493 | goto no_route; | 495 | goto no_route; |
494 | } | 496 | } |
495 | sk_setup_caps(sk, &rt->dst); | 497 | sk_setup_caps(sk, &rt->dst); |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 6264219f0a42..878f6dd9dbad 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -103,7 +103,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
103 | .fl4_tos = rtos, | 103 | .fl4_tos = rtos, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | if (ip_route_output_key(net, &rt, &fl)) { | 106 | rt = ip_route_output_key(net, &fl); |
107 | if (IS_ERR(rt)) { | ||
107 | spin_unlock(&dest->dst_lock); | 108 | spin_unlock(&dest->dst_lock); |
108 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 109 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", |
109 | &dest->addr.ip); | 110 | &dest->addr.ip); |
@@ -121,7 +122,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
121 | .fl4_tos = rtos, | 122 | .fl4_tos = rtos, |
122 | }; | 123 | }; |
123 | 124 | ||
124 | if (ip_route_output_key(net, &rt, &fl)) { | 125 | rt = ip_route_output_key(net, &fl); |
126 | if (IS_ERR(rt)) { | ||
125 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 127 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", |
126 | &daddr); | 128 | &daddr); |
127 | return NULL; | 129 | return NULL; |
@@ -180,7 +182,8 @@ __ip_vs_reroute_locally(struct sk_buff *skb) | |||
180 | .mark = skb->mark, | 182 | .mark = skb->mark, |
181 | }; | 183 | }; |
182 | 184 | ||
183 | if (ip_route_output_key(net, &rt, &fl)) | 185 | rt = ip_route_output_key(net, &fl); |
186 | if (IS_ERR(rt)) | ||
184 | return 0; | 187 | return 0; |
185 | if (!(rt->rt_flags & RTCF_LOCAL)) { | 188 | if (!(rt->rt_flags & RTCF_LOCAL)) { |
186 | ip_rt_put(rt); | 189 | ip_rt_put(rt); |
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index 5128a6c4cb2c..624725b5286f 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c | |||
@@ -73,7 +73,8 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) | |||
73 | fl.fl4_dst = info->gw.ip; | 73 | fl.fl4_dst = info->gw.ip; |
74 | fl.fl4_tos = RT_TOS(iph->tos); | 74 | fl.fl4_tos = RT_TOS(iph->tos); |
75 | fl.fl4_scope = RT_SCOPE_UNIVERSE; | 75 | fl.fl4_scope = RT_SCOPE_UNIVERSE; |
76 | if (ip_route_output_key(net, &rt, &fl) != 0) | 76 | rt = ip_route_output_key(net, &fl); |
77 | if (IS_ERR(rt)) | ||
77 | return false; | 78 | return false; |
78 | 79 | ||
79 | skb_dst_drop(skb); | 80 | skb_dst_drop(skb); |
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index a53fb25a64ed..3620c569275f 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c | |||
@@ -37,7 +37,6 @@ static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer) | |||
37 | { | 37 | { |
38 | struct rtable *rt; | 38 | struct rtable *rt; |
39 | struct flowi fl; | 39 | struct flowi fl; |
40 | int ret; | ||
41 | 40 | ||
42 | peer->if_mtu = 1500; | 41 | peer->if_mtu = 1500; |
43 | 42 | ||
@@ -58,9 +57,9 @@ static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer) | |||
58 | BUG(); | 57 | BUG(); |
59 | } | 58 | } |
60 | 59 | ||
61 | ret = ip_route_output_key(&init_net, &rt, &fl); | 60 | rt = ip_route_output_key(&init_net, &fl); |
62 | if (ret < 0) { | 61 | if (IS_ERR(rt)) { |
63 | _leave(" [route err %d]", ret); | 62 | _leave(" [route err %ld]", PTR_ERR(rt)); |
64 | return; | 63 | return; |
65 | } | 64 | } |
66 | 65 | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index e58f9476f29c..4e55e6c49ec9 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -491,9 +491,9 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
492 | __func__, &fl.fl4_dst, &fl.fl4_src); | 492 | __func__, &fl.fl4_dst, &fl.fl4_src); |
493 | 493 | ||
494 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 494 | rt = ip_route_output_key(&init_net, &fl); |
495 | if (!IS_ERR(rt)) | ||
495 | dst = &rt->dst; | 496 | dst = &rt->dst; |
496 | } | ||
497 | 497 | ||
498 | /* If there is no association or if a source address is passed, no | 498 | /* If there is no association or if a source address is passed, no |
499 | * more validation is required. | 499 | * more validation is required. |
@@ -535,7 +535,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
535 | (AF_INET == laddr->a.sa.sa_family)) { | 535 | (AF_INET == laddr->a.sa.sa_family)) { |
536 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; | 536 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; |
537 | fl.fl_ip_sport = laddr->a.v4.sin_port; | 537 | fl.fl_ip_sport = laddr->a.v4.sin_port; |
538 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 538 | rt = ip_route_output_key(&init_net, &fl); |
539 | if (!IS_ERR(rt)) { | ||
539 | dst = &rt->dst; | 540 | dst = &rt->dst; |
540 | goto out_unlock; | 541 | goto out_unlock; |
541 | } | 542 | } |