aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r--net/ipv4/ip_output.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 0bc95f3977d2..ff302bde8890 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -206,7 +206,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
206 } 206 }
207 207
208 rcu_read_lock(); 208 rcu_read_lock();
209 neigh = dst_get_neighbour(dst); 209 neigh = dst_get_neighbour_noref(dst);
210 if (neigh) { 210 if (neigh) {
211 int res = neigh_output(neigh, skb); 211 int res = neigh_output(neigh, skb);
212 212
@@ -319,6 +319,20 @@ int ip_output(struct sk_buff *skb)
319 !(IPCB(skb)->flags & IPSKB_REROUTED)); 319 !(IPCB(skb)->flags & IPSKB_REROUTED));
320} 320}
321 321
322/*
323 * copy saddr and daddr, possibly using 64bit load/stores
324 * Equivalent to :
325 * iph->saddr = fl4->saddr;
326 * iph->daddr = fl4->daddr;
327 */
328static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4)
329{
330 BUILD_BUG_ON(offsetof(typeof(*fl4), daddr) !=
331 offsetof(typeof(*fl4), saddr) + sizeof(fl4->saddr));
332 memcpy(&iph->saddr, &fl4->saddr,
333 sizeof(fl4->saddr) + sizeof(fl4->daddr));
334}
335
322int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) 336int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
323{ 337{
324 struct sock *sk = skb->sk; 338 struct sock *sk = skb->sk;
@@ -381,8 +395,8 @@ packet_routed:
381 iph->frag_off = 0; 395 iph->frag_off = 0;
382 iph->ttl = ip_select_ttl(inet, &rt->dst); 396 iph->ttl = ip_select_ttl(inet, &rt->dst);
383 iph->protocol = sk->sk_protocol; 397 iph->protocol = sk->sk_protocol;
384 iph->saddr = fl4->saddr; 398 ip_copy_addrs(iph, fl4);
385 iph->daddr = fl4->daddr; 399
386 /* Transport layer set skb->h.foo itself. */ 400 /* Transport layer set skb->h.foo itself. */
387 401
388 if (inet_opt && inet_opt->opt.optlen) { 402 if (inet_opt && inet_opt->opt.optlen) {
@@ -1337,8 +1351,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
1337 ip_select_ident(iph, &rt->dst, sk); 1351 ip_select_ident(iph, &rt->dst, sk);
1338 iph->ttl = ttl; 1352 iph->ttl = ttl;
1339 iph->protocol = sk->sk_protocol; 1353 iph->protocol = sk->sk_protocol;
1340 iph->saddr = fl4->saddr; 1354 ip_copy_addrs(iph, fl4);
1341 iph->daddr = fl4->daddr;
1342 1355
1343 if (opt) { 1356 if (opt) {
1344 iph->ihl += opt->optlen>>2; 1357 iph->ihl += opt->optlen>>2;