NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n")); 
NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); 
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)){	struct net_device *dev;	struct sk_buff *frag;	struct rt6_info *rt = (struct rt6_info*)skb->dst;	struct ipv6hdr *tmp_hdr;	struct frag_hdr *fh;	unsigned int mtu, hlen, left, len;	u32 frag_id = 0;	int ptr, offset = 0, err=0;	u8 *prevhdr, nexthdr = 0;	dev = rt->u.dst.dev;	hlen = ip6_find_1stfragopt(skb, &prevhdr);	nexthdr = *prevhdr;	mtu = dst_mtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);	if (skb_shinfo(skb)->frag_list) {		int first_len = skb_pagelen(skb);		if (first_len - hlen > mtu ||		    ((first_len - hlen) & 7) ||		    skb_cloned(skb))			goto slow_path;		for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {			/* Correct geometry. */			if (frag->len > mtu ||			    ((frag->len & 7) && frag->next) ||			    skb_headroom(frag) < hlen)			    goto slow_path;			/* Partially cloned skb? */			if (skb_shared(frag))				goto slow_path;			BUG_ON(frag->sk);			if (skb->sk) {				sock_hold(skb->sk);				frag->sk = skb->sk;				frag->destructor = sock_wfree;				skb->truesize -= frag->truesize;			}		}		err = 0;		offset = 0;		frag = skb_shinfo(skb)->frag_list;		skb_shinfo(skb)->frag_list = NULL;		/* BUILD HEADER */		tmp_hdr = kmalloc(hlen, GFP_ATOMIC);		if (!tmp_hdr) {			IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);			return -ENOMEM;		}		*prevhdr = NEXTHDR_FRAGMENT;		memcpy(tmp_hdr, skb->nh.raw, hlen);		__skb_pull(skb, hlen);		fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));		skb->nh.raw = __skb_push(skb, hlen);		memcpy(skb->nh.raw, tmp_hdr, hlen);		ipv6_select_ident(skb, fh);		fh->nexthdr = nexthdr;		fh->reserved = 0;		fh->frag_off = htons(IP6_MF);		frag_id = fh->identification;		first_len = skb_pagelen(skb);		skb->data_len = first_len - skb_headlen(skb);		skb->len = first_len;		skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); 		for (;;) {			/* Prepare header of the next frame,			 * before previous one went down. */			if (frag) {				frag->ip_summed = CHECKSUM_NONE;				frag->h.raw = frag->data;				fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr));				frag->nh.raw = __skb_push(frag, hlen);				memcpy(frag->nh.raw, tmp_hdr, hlen);				offset += skb->len - hlen - sizeof(struct frag_hdr);				fh->nexthdr = nexthdr;				fh->reserved = 0;				fh->frag_off = htons(offset);				if (frag->next != NULL)					fh->frag_off |= htons(IP6_MF);				fh->identification = frag_id;				frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));				ip6_copy_metadata(frag, skb);			}						err = output(skb);			if (err || !frag)				break;			skb = frag;			frag = skb->next;			skb->next = NULL;		}		if (tmp_hdr)			kfree(tmp_hdr);		if (err == 0) {			IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);			return 0;		}		while (frag) {			skb = frag->next;			kfree_skb(frag);			frag = skb;		}		IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);		return err;	}slow_path:	left = skb->len - hlen;		/* Space per frame */	ptr = hlen;			/* Where to start from */	/*	 *	Fragment the datagram.	 */	*prevhdr = NEXTHDR_FRAGMENT;	/*	 *	Keep copying data until we run out.	 */	while(left > 0)	{		len = left;		/* IF: it doesn't fit, use 'mtu' - the data space left */		if (len > mtu)			len = mtu;		/* IF: we are not sending upto and including the packet end		   then align the next start on an eight byte boundary */		if (len < left)	{			len &= ~7;		}		/*		 *	Allocate buffer.		 */		if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {			NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n"));			IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);			err = -ENOMEM;			goto fail;		}		/*		 *	Set up data on packet		 */		ip6_copy_metadata(frag, skb);		skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev));		skb_put(frag, len + hlen + sizeof(struct frag_hdr));		frag->nh.raw = frag->data;		fh = (struct frag_hdr*)(frag->data + hlen);		frag->h.raw = frag->data + hlen + sizeof(struct frag_hdr);		/*		 *	Charge the memory for the fragment to any owner		 *	it might possess		 */		if (skb->sk)			skb_set_owner_w(frag, skb->sk);		/*		 *	Copy the packet header into the new buffer.		 */		memcpy(frag->nh.raw, skb->data, hlen);		/*		 *	Build fragment header.		 */		fh->nexthdr = nexthdr;		fh->reserved = 0;		if (frag_id) {			ipv6_select_ident(skb, fh);			frag_id = fh->identification;		} else			fh->identification = frag_id;		/*		 *	Copy a block of the IP datagram.		 */		if (skb_copy_bits(skb, ptr, frag->h.raw, len))			BUG();		left -= len;		fh->frag_off = htons(offset);		if (left > 0)			fh->frag_off |= htons(IP6_MF);		frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));		ptr += len;		offset += len;		/*		 *	Put this fragment into the sending queue.		 */		IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);		err = output(frag);		if (err)			goto fail;	}	kfree_skb(skb);	IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);	return err;fail:	kfree_skb(skb); 	IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);	return err;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/64ce207306debd7157f47282be94770407bec01c/ip6_output.c/clean/net/ipv6/ip6_output.c