skb->nfcache |= NFC_IPVS_PROPERTY; 
skb->ipvs_property = 1; 
static int ip_vs_out_icmp(struct sk_buff **pskb, int *related){	struct sk_buff *skb = *pskb;	struct iphdr *iph;	struct icmphdr	_icmph, *ic;	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */	struct ip_vs_conn *cp;	struct ip_vs_protocol *pp;	unsigned int offset, ihl, verdict;	*related = 1;	/* reassemble IP fragments */	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {		skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);		if (!skb)			return NF_STOLEN;		*pskb = skb;	}	iph = skb->nh.iph;	offset = ihl = iph->ihl * 4;	ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);	if (ic == NULL)		return NF_DROP;	IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",		  ic->type, ntohs(icmp_id(ic)),		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));	/*	 * Work through seeing if this is for us.	 * These checks are supposed to be in an order that means easy	 * things are checked first to speed up processing.... however	 * this means that some packets will manage to get a long way	 * down this stack and then be rejected, but that's life.	 */	if ((ic->type != ICMP_DEST_UNREACH) &&	    (ic->type != ICMP_SOURCE_QUENCH) &&	    (ic->type != ICMP_TIME_EXCEEDED)) {		*related = 0;		return NF_ACCEPT;	}	/* Now find the contained IP header */	offset += sizeof(_icmph);	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);	if (cih == NULL)		return NF_ACCEPT; /* The packet looks wrong, ignore */	pp = ip_vs_proto_get(cih->protocol);	if (!pp)		return NF_ACCEPT;	/* Is the embedded protocol header present? */	if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&		     pp->dont_defrag))		return NF_ACCEPT;	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");	offset += cih->ihl * 4;	/* The embedded headers contain source and dest in reverse order */	cp = pp->conn_out_get(skb, pp, cih, offset, 1);	if (!cp)		return NF_ACCEPT;	verdict = NF_DROP;	if (IP_VS_FWD_METHOD(cp) != 0) {		IP_VS_ERR("shouldn't reach here, because the box is on the"			  "half connection in the tun/dr module.\n");	}	/* Ensure the checksum is correct */	if (skb->ip_summed != CHECKSUM_UNNECESSARY &&	    ip_vs_checksum_complete(skb, ihl)) {		/* Failed checksum! */		IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n",			  NIPQUAD(iph->saddr));		goto out;	}	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)		offset += 2 * sizeof(__u16);	if (!ip_vs_make_skb_writable(pskb, offset))		goto out;	skb = *pskb;	ip_vs_nat_icmp(skb, pp, cp, 1);	/* do the statistics and put it back */	ip_vs_out_stats(cp, skb);	skb->nfcache |= NFC_IPVS_PROPERTY;	verdict = NF_ACCEPT;  out:	__ip_vs_conn_put(cp);	return verdict;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/6869c4d8e066e21623c812c448a05f1ed931c9c6/ip_vs_core.c/clean/net/ipv4/ipvs/ip_vs_core.c