int hlimit; 
int hlimit, tclass; 
void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 		 struct net_device *dev){	struct inet6_dev *idev = NULL;	struct ipv6hdr *hdr = skb->nh.ipv6h;	struct sock *sk;	struct ipv6_pinfo *np;	struct in6_addr *saddr = NULL;	struct dst_entry *dst;	struct icmp6hdr tmp_hdr;	struct flowi fl;	struct icmpv6_msg msg;	int iif = 0;	int addr_type = 0;	int len;	int hlimit;	int err = 0;	if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)		return;	/*	 *	Make sure we respect the rules 	 *	i.e. RFC 1885 2.4(e)	 *	Rule (e.1) is enforced by not using icmpv6_send	 *	in any code that processes icmp errors.	 */	addr_type = ipv6_addr_type(&hdr->daddr);	if (ipv6_chk_addr(&hdr->daddr, skb->dev, 0))		saddr = &hdr->daddr;	/*	 *	Dest addr check	 */	if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {		if (type != ICMPV6_PKT_TOOBIG &&		    !(type == ICMPV6_PARAMPROB && 		      code == ICMPV6_UNK_OPTION && 		      (opt_unrec(skb, info))))			return;		saddr = NULL;	}	addr_type = ipv6_addr_type(&hdr->saddr);	/*	 *	Source addr check	 */	if (addr_type & IPV6_ADDR_LINKLOCAL)		iif = skb->dev->ifindex;	/*	 *	Must not send if we know that source is Anycast also.	 *	for now we don't know that.	 */	if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");		return;	}	/* 	 *	Never answer to a ICMP packet.	 */	if (is_ineligible(skb)) {		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n");		return;	}	memset(&fl, 0, sizeof(fl));	fl.proto = IPPROTO_ICMPV6;	ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);	if (saddr)		ipv6_addr_copy(&fl.fl6_src, saddr);	fl.oif = iif;	fl.fl_icmp_type = type;	fl.fl_icmp_code = code;	if (icmpv6_xmit_lock())		return;	sk = icmpv6_socket->sk;	np = inet6_sk(sk);	if (!icmpv6_xrlim_allow(sk, type, &fl))		goto out;	tmp_hdr.icmp6_type = type;	tmp_hdr.icmp6_code = code;	tmp_hdr.icmp6_cksum = 0;	tmp_hdr.icmp6_pointer = htonl(info);	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))		fl.oif = np->mcast_oif;	err = ip6_dst_lookup(sk, &dst, &fl);	if (err)		goto out;	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)		goto out_dst_release;	if (ipv6_addr_is_multicast(&fl.fl6_dst))		hlimit = np->mcast_hops;	else		hlimit = np->hop_limit;	if (hlimit < 0)		hlimit = dst_metric(dst, RTAX_HOPLIMIT);	if (hlimit < 0)		hlimit = ipv6_get_hoplimit(dst->dev);	msg.skb = skb;	msg.offset = skb->nh.raw - skb->data;	len = skb->len - msg.offset;	len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr));	if (len < 0) {		LIMIT_NETDEBUG(KERN_DEBUG "icmp: len problem\n");		goto out_dst_release;	}	idev = in6_dev_get(skb->dev);	err = ip6_append_data(sk, icmpv6_getfrag, &msg,			      len + sizeof(struct icmp6hdr),			      sizeof(struct icmp6hdr),			      hlimit, NULL, &fl, (struct rt6_info*)dst,			      MSG_DONTWAIT);	if (err) {		ip6_flush_pending_frames(sk);		goto out_put;	}	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)		ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH);	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);out_put:	if (likely(idev != NULL))		in6_dev_put(idev);out_dst_release:	dst_release(dst);out:	icmpv6_xmit_unlock();}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/41a1f8ea4fbfcdc4232f023732584aae2220de31/icmp.c/clean/net/ipv6/icmp.c