diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 44 |
1 files changed, 18 insertions, 26 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 451f97c42eb..cc52679790b 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -113,19 +113,6 @@ int ip_local_out(struct sk_buff *skb) | |||
113 | } | 113 | } |
114 | EXPORT_SYMBOL_GPL(ip_local_out); | 114 | EXPORT_SYMBOL_GPL(ip_local_out); |
115 | 115 | ||
116 | /* dev_loopback_xmit for use with netfilter. */ | ||
117 | static int ip_dev_loopback_xmit(struct sk_buff *newskb) | ||
118 | { | ||
119 | skb_reset_mac_header(newskb); | ||
120 | __skb_pull(newskb, skb_network_offset(newskb)); | ||
121 | newskb->pkt_type = PACKET_LOOPBACK; | ||
122 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | ||
123 | WARN_ON(!skb_dst(newskb)); | ||
124 | skb_dst_force(newskb); | ||
125 | netif_rx_ni(newskb); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) | 116 | static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) |
130 | { | 117 | { |
131 | int ttl = inet->uc_ttl; | 118 | int ttl = inet->uc_ttl; |
@@ -183,6 +170,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
183 | struct net_device *dev = dst->dev; | 170 | struct net_device *dev = dst->dev; |
184 | unsigned int hh_len = LL_RESERVED_SPACE(dev); | 171 | unsigned int hh_len = LL_RESERVED_SPACE(dev); |
185 | struct neighbour *neigh; | 172 | struct neighbour *neigh; |
173 | u32 nexthop; | ||
186 | 174 | ||
187 | if (rt->rt_type == RTN_MULTICAST) { | 175 | if (rt->rt_type == RTN_MULTICAST) { |
188 | IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); | 176 | IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); |
@@ -200,19 +188,22 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
200 | } | 188 | } |
201 | if (skb->sk) | 189 | if (skb->sk) |
202 | skb_set_owner_w(skb2, skb->sk); | 190 | skb_set_owner_w(skb2, skb->sk); |
203 | kfree_skb(skb); | 191 | consume_skb(skb); |
204 | skb = skb2; | 192 | skb = skb2; |
205 | } | 193 | } |
206 | 194 | ||
207 | rcu_read_lock(); | 195 | rcu_read_lock_bh(); |
208 | neigh = dst_get_neighbour_noref(dst); | 196 | nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr; |
197 | neigh = __ipv4_neigh_lookup_noref(dev, nexthop); | ||
198 | if (unlikely(!neigh)) | ||
199 | neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); | ||
209 | if (neigh) { | 200 | if (neigh) { |
210 | int res = neigh_output(neigh, skb); | 201 | int res = dst_neigh_output(dst, neigh, skb); |
211 | 202 | ||
212 | rcu_read_unlock(); | 203 | rcu_read_unlock_bh(); |
213 | return res; | 204 | return res; |
214 | } | 205 | } |
215 | rcu_read_unlock(); | 206 | rcu_read_unlock_bh(); |
216 | 207 | ||
217 | net_dbg_ratelimited("%s: No header cache and no neighbour!\n", | 208 | net_dbg_ratelimited("%s: No header cache and no neighbour!\n", |
218 | __func__); | 209 | __func__); |
@@ -281,7 +272,7 @@ int ip_mc_output(struct sk_buff *skb) | |||
281 | if (newskb) | 272 | if (newskb) |
282 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, | 273 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
283 | newskb, NULL, newskb->dev, | 274 | newskb, NULL, newskb->dev, |
284 | ip_dev_loopback_xmit); | 275 | dev_loopback_xmit); |
285 | } | 276 | } |
286 | 277 | ||
287 | /* Multicasts with ttl 0 must not go beyond the host */ | 278 | /* Multicasts with ttl 0 must not go beyond the host */ |
@@ -296,7 +287,7 @@ int ip_mc_output(struct sk_buff *skb) | |||
296 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 287 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
297 | if (newskb) | 288 | if (newskb) |
298 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, | 289 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, |
299 | NULL, newskb->dev, ip_dev_loopback_xmit); | 290 | NULL, newskb->dev, dev_loopback_xmit); |
300 | } | 291 | } |
301 | 292 | ||
302 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, | 293 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, |
@@ -709,7 +700,7 @@ slow_path: | |||
709 | 700 | ||
710 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGCREATES); | 701 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGCREATES); |
711 | } | 702 | } |
712 | kfree_skb(skb); | 703 | consume_skb(skb); |
713 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGOKS); | 704 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGOKS); |
714 | return err; | 705 | return err; |
715 | 706 | ||
@@ -1472,13 +1463,14 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, | |||
1472 | 1463 | ||
1473 | /* | 1464 | /* |
1474 | * Generic function to send a packet as reply to another packet. | 1465 | * Generic function to send a packet as reply to another packet. |
1475 | * Used to send TCP resets so far. ICMP should use this function too. | 1466 | * Used to send TCP resets so far. |
1476 | * | 1467 | * |
1477 | * Should run single threaded per socket because it uses the sock | 1468 | * Should run single threaded per socket because it uses the sock |
1478 | * structure to pass arguments. | 1469 | * structure to pass arguments. |
1479 | */ | 1470 | */ |
1480 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, | 1471 | void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, |
1481 | const struct ip_reply_arg *arg, unsigned int len) | 1472 | __be32 saddr, const struct ip_reply_arg *arg, |
1473 | unsigned int len) | ||
1482 | { | 1474 | { |
1483 | struct inet_sock *inet = inet_sk(sk); | 1475 | struct inet_sock *inet = inet_sk(sk); |
1484 | struct ip_options_data replyopts; | 1476 | struct ip_options_data replyopts; |
@@ -1504,7 +1496,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, | |||
1504 | RT_TOS(arg->tos), | 1496 | RT_TOS(arg->tos), |
1505 | RT_SCOPE_UNIVERSE, sk->sk_protocol, | 1497 | RT_SCOPE_UNIVERSE, sk->sk_protocol, |
1506 | ip_reply_arg_flowi_flags(arg), | 1498 | ip_reply_arg_flowi_flags(arg), |
1507 | daddr, rt->rt_spec_dst, | 1499 | daddr, saddr, |
1508 | tcp_hdr(skb)->source, tcp_hdr(skb)->dest); | 1500 | tcp_hdr(skb)->source, tcp_hdr(skb)->dest); |
1509 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); | 1501 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); |
1510 | rt = ip_route_output_key(sock_net(sk), &fl4); | 1502 | rt = ip_route_output_key(sock_net(sk), &fl4); |