diff options
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 | } |
