diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
| -rw-r--r-- | net/ipv6/ip6_output.c | 37 | 
1 files changed, 21 insertions, 16 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 84d0bd5cac9..d97e07183ce 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -136,7 +136,7 @@ static int ip6_finish_output2(struct sk_buff *skb)  	}  	rcu_read_lock(); -	neigh = dst_get_neighbour(dst); +	neigh = dst_get_neighbour_noref(dst);  	if (neigh) {  		int res = neigh_output(neigh, skb); @@ -238,8 +238,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,  	hdr->nexthdr = proto;  	hdr->hop_limit = hlimit; -	ipv6_addr_copy(&hdr->saddr, &fl6->saddr); -	ipv6_addr_copy(&hdr->daddr, first_hop); +	hdr->saddr = fl6->saddr; +	hdr->daddr = *first_hop;  	skb->priority = sk->sk_priority;  	skb->mark = sk->sk_mark; @@ -290,8 +290,8 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,  	hdr->nexthdr = proto;  	hdr->hop_limit = np->hop_limit; -	ipv6_addr_copy(&hdr->saddr, saddr); -	ipv6_addr_copy(&hdr->daddr, daddr); +	hdr->saddr = *saddr; +	hdr->daddr = *daddr;  	return 0;  } @@ -329,10 +329,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)  {  	struct ipv6hdr *hdr = ipv6_hdr(skb);  	u8 nexthdr = hdr->nexthdr; +	__be16 frag_off;  	int offset;  	if (ipv6_ext_hdr(nexthdr)) { -		offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); +		offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off);  		if (offset < 0)  			return 0;  	} else @@ -462,7 +463,7 @@ int ip6_forward(struct sk_buff *skb)  	   send redirects to source routed frames.  	   We don't send redirects to frames decapsulated from IPsec.  	 */ -	n = dst_get_neighbour(dst); +	n = dst_get_neighbour_noref(dst);  	if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {  		struct in6_addr *target = NULL;  		struct rt6_info *rt; @@ -603,7 +604,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)  	static atomic_t ipv6_fragmentation_id;  	int old, new; -	if (rt) { +	if (rt && !(rt->dst.flags & DST_NOPEER)) {  		struct inet_peer *peer;  		if (!rt->rt6i_peer) @@ -631,6 +632,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  	struct ipv6hdr *tmp_hdr;  	struct frag_hdr *fh;  	unsigned int mtu, hlen, left, len; +	int hroom, troom;  	__be32 frag_id = 0;  	int ptr, offset = 0, err=0;  	u8 *prevhdr, nexthdr = 0; @@ -797,6 +799,8 @@ slow_path:  	 */  	*prevhdr = NEXTHDR_FRAGMENT; +	hroom = LL_RESERVED_SPACE(rt->dst.dev); +	troom = rt->dst.dev->needed_tailroom;  	/*  	 *	Keep copying data until we run out. @@ -815,7 +819,8 @@ slow_path:  		 *	Allocate buffer.  		 */ -		if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { +		if ((frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + +				      hroom + troom, GFP_ATOMIC)) == NULL) {  			NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");  			IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),  				      IPSTATS_MIB_FRAGFAILS); @@ -828,7 +833,7 @@ slow_path:  		 */  		ip6_copy_metadata(frag, skb); -		skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); +		skb_reserve(frag, hroom);  		skb_put(frag, len + hlen + sizeof(struct frag_hdr));  		skb_reset_network_header(frag);  		fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); @@ -978,7 +983,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,  	 * dst entry of the nexthop router  	 */  	rcu_read_lock(); -	n = dst_get_neighbour(*dst); +	n = dst_get_neighbour_noref(*dst);  	if (n && !(n->nud_state & NUD_VALID)) {  		struct inet6_ifaddr *ifp;  		struct flowi6 fl_gw6; @@ -1059,7 +1064,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,  	if (err)  		return ERR_PTR(err);  	if (final_dst) -		ipv6_addr_copy(&fl6->daddr, final_dst); +		fl6->daddr = *final_dst;  	if (can_sleep)  		fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; @@ -1095,7 +1100,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,  	if (err)  		return ERR_PTR(err);  	if (final_dst) -		ipv6_addr_copy(&fl6->daddr, final_dst); +		fl6->daddr = *final_dst;  	if (can_sleep)  		fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; @@ -1588,7 +1593,7 @@ int ip6_push_pending_frames(struct sock *sk)  	if (np->pmtudisc < IPV6_PMTUDISC_DO)  		skb->local_df = 1; -	ipv6_addr_copy(final_dst, &fl6->daddr); +	*final_dst = fl6->daddr;  	__skb_pull(skb, skb_network_header_len(skb));  	if (opt && opt->opt_flen)  		ipv6_push_frag_opts(skb, opt, &proto); @@ -1604,8 +1609,8 @@ int ip6_push_pending_frames(struct sock *sk)  	hdr->hop_limit = np->cork.hop_limit;  	hdr->nexthdr = proto; -	ipv6_addr_copy(&hdr->saddr, &fl6->saddr); -	ipv6_addr_copy(&hdr->daddr, final_dst); +	hdr->saddr = fl6->saddr; +	hdr->daddr = *final_dst;  	skb->priority = sk->sk_priority;  	skb->mark = sk->sk_mark;  |