diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 84f26e8e6c6..8c6563361ab 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -122,6 +122,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) | |||
122 | newskb->pkt_type = PACKET_LOOPBACK; | 122 | newskb->pkt_type = PACKET_LOOPBACK; |
123 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 123 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
124 | WARN_ON(!skb_dst(newskb)); | 124 | WARN_ON(!skb_dst(newskb)); |
125 | skb_dst_force(newskb); | ||
125 | netif_rx_ni(newskb); | 126 | netif_rx_ni(newskb); |
126 | return 0; | 127 | return 0; |
127 | } | 128 | } |
@@ -182,6 +183,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
182 | struct rtable *rt = (struct rtable *)dst; | 183 | struct rtable *rt = (struct rtable *)dst; |
183 | struct net_device *dev = dst->dev; | 184 | struct net_device *dev = dst->dev; |
184 | unsigned int hh_len = LL_RESERVED_SPACE(dev); | 185 | unsigned int hh_len = LL_RESERVED_SPACE(dev); |
186 | struct neighbour *neigh; | ||
185 | 187 | ||
186 | if (rt->rt_type == RTN_MULTICAST) { | 188 | if (rt->rt_type == RTN_MULTICAST) { |
187 | IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); | 189 | IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); |
@@ -203,10 +205,15 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
203 | skb = skb2; | 205 | skb = skb2; |
204 | } | 206 | } |
205 | 207 | ||
206 | if (dst->hh) | 208 | rcu_read_lock(); |
207 | return neigh_hh_output(dst->hh, skb); | 209 | neigh = dst_get_neighbour(dst); |
208 | else if (dst->neighbour) | 210 | if (neigh) { |
209 | return dst->neighbour->output(skb); | 211 | int res = neigh_output(neigh, skb); |
212 | |||
213 | rcu_read_unlock(); | ||
214 | return res; | ||
215 | } | ||
216 | rcu_read_unlock(); | ||
210 | 217 | ||
211 | if (net_ratelimit()) | 218 | if (net_ratelimit()) |
212 | printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n"); | 219 | printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n"); |
@@ -489,7 +496,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
489 | 496 | ||
490 | if (first_len - hlen > mtu || | 497 | if (first_len - hlen > mtu || |
491 | ((first_len - hlen) & 7) || | 498 | ((first_len - hlen) & 7) || |
492 | (iph->frag_off & htons(IP_MF|IP_OFFSET)) || | 499 | ip_is_fragment(iph) || |
493 | skb_cloned(skb)) | 500 | skb_cloned(skb)) |
494 | goto slow_path; | 501 | goto slow_path; |
495 | 502 | ||
@@ -734,7 +741,7 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
734 | int getfrag(void *from, char *to, int offset, int len, | 741 | int getfrag(void *from, char *to, int offset, int len, |
735 | int odd, struct sk_buff *skb), | 742 | int odd, struct sk_buff *skb), |
736 | void *from, int length, int hh_len, int fragheaderlen, | 743 | void *from, int length, int hh_len, int fragheaderlen, |
737 | int transhdrlen, int mtu, unsigned int flags) | 744 | int transhdrlen, int maxfraglen, unsigned int flags) |
738 | { | 745 | { |
739 | struct sk_buff *skb; | 746 | struct sk_buff *skb; |
740 | int err; | 747 | int err; |
@@ -767,7 +774,7 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
767 | skb->csum = 0; | 774 | skb->csum = 0; |
768 | 775 | ||
769 | /* specify the length of each IP datagram fragment */ | 776 | /* specify the length of each IP datagram fragment */ |
770 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; | 777 | skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen; |
771 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 778 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
772 | __skb_queue_tail(queue, skb); | 779 | __skb_queue_tail(queue, skb); |
773 | } | 780 | } |
@@ -831,7 +838,7 @@ static int __ip_append_data(struct sock *sk, | |||
831 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { | 838 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { |
832 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, | 839 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
833 | hh_len, fragheaderlen, transhdrlen, | 840 | hh_len, fragheaderlen, transhdrlen, |
834 | mtu, flags); | 841 | maxfraglen, flags); |
835 | if (err) | 842 | if (err) |
836 | goto error; | 843 | goto error; |
837 | return 0; | 844 | return 0; |