static unsigned int ipt_mirror_target(struct sk_buff **pskb,
				      unsigned int hooknum,
				      const struct net_device *in,
				      const struct net_device *out,
				      const void *targinfo,
				      void *userinfo)
{
	if (((*pskb)->dst != NULL) &&
	    route_mirror(*pskb)) {

		ip_rewrite(*pskb);

		/* If we are not at FORWARD hook (INPUT/PREROUTING),
		 * the TTL isn't decreased by the IP stack */
		if (hooknum != NF_IP_FORWARD) {
			struct iphdr *iph = (*pskb)->nh.iph;
			if (iph->ttl <= 1) {
				/* this will traverse normal stack, and 
				 * thus call conntrack on the icmp packet */
				icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
					  ICMP_EXC_TTL, 0);
				return NF_DROP;
			}
			ip_decrease_ttl(iph);
		}

		/* Don't let conntrack code see this packet:
                   it will think we are starting a new
                   connection! --RR */
		ip_direct_send(*pskb);

		return NF_STOLEN;
	}
	return NF_DROP;
}
Esempio n. 2
0
static unsigned int ipt_mirror_target(struct sk_buff **pskb,
				      unsigned int hooknum,
				      const struct net_device *in,
				      const struct net_device *out,
				      const void *targinfo,
				      void *userinfo)
{
	struct rtable *rt;
	struct sk_buff *nskb;
	unsigned int hh_len;

	/* If we are not at FORWARD hook (INPUT/PREROUTING),
	 * the TTL isn't decreased by the IP stack */
	if (hooknum != NF_IP_FORWARD) {
		struct iphdr *iph = (*pskb)->nh.iph;
		if (iph->ttl <= 1) {
			/* this will traverse normal stack, and 
			 * thus call conntrack on the icmp packet */
			icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
				  ICMP_EXC_TTL, 0);
			return NF_DROP;
		}
		ip_decrease_ttl(iph);
	}

	if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
		return NF_DROP;

	hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;

	/* Copy skb (even if skb is about to be dropped, we can't just
	 * clone it because there may be other things, such as tcpdump,
	 * interested in it). We also need to expand headroom in case
	 * hh_len of incoming interface < hh_len of outgoing interface */
	nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
	if (nskb == NULL) {
		dst_release(&rt->u.dst);
		return NF_DROP;
	}

	dst_release(nskb->dst);
	nskb->dst = &rt->u.dst;

	ip_rewrite(nskb);
	/* Don't let conntrack code see this packet:
           it will think we are starting a new
           connection! --RR */
	ip_direct_send(nskb);

	return NF_DROP;
}