int xtnu_ip_route_me_harder(struct sk_buff **pskb, unsigned int addr_type)
{
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
	/* Actually this one is valid up to 2.6.18.4, but changed in 2.6.18.5 */
	return ip_route_me_harder(pskb);
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
	return ip_route_me_harder(pskb, addr_type);
#else
	return ip_route_me_harder(*pskb, addr_type);
#endif
}
Exemple #2
0
static void
synproxy_send_tcp(struct net *net,
                  const struct sk_buff *skb, struct sk_buff *nskb,
                  struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
                  struct iphdr *niph, struct tcphdr *nth,
                  unsigned int tcp_hdr_size)
{
    nth->check = ~tcp_v4_check(tcp_hdr_size, niph->saddr, niph->daddr, 0);
    nskb->ip_summed   = CHECKSUM_PARTIAL;
    nskb->csum_start  = (unsigned char *)nth - nskb->head;
    nskb->csum_offset = offsetof(struct tcphdr, check);

    skb_dst_set_noref(nskb, skb_dst(skb));
    nskb->protocol = htons(ETH_P_IP);
    if (ip_route_me_harder(net, nskb, RTN_UNSPEC))
        goto free_nskb;

    if (nfct) {
        nskb->nfct = nfct;
        nskb->nfctinfo = ctinfo;
        nf_conntrack_get(nfct);
    }

    ip_local_out(net, nskb->sk, nskb);
    return;

free_nskb:
    kfree_skb(nskb);
}
static unsigned int nf_nat_output(const struct nf_hook_ops *ops,
				  struct sk_buff *skb,
				  const struct net_device *in,
				  const struct net_device *out,
				  int (*okfn)(struct sk_buff *))
{
	enum ip_conntrack_info ctinfo;
	const struct nf_conn *ct;
	unsigned int ret;

	ret = nf_nat_fn(ops, skb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN &&
	    (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.u3.ip !=
		    ct->tuplehash[!dir].tuple.src.u3.ip) {
			if (ip_route_me_harder(skb, RTN_UNSPEC))
				ret = NF_DROP;
		}
#ifdef CONFIG_XFRM
		else if (ct->tuplehash[dir].tuple.dst.u.all !=
			 ct->tuplehash[!dir].tuple.src.u.all)
			if (nf_xfrm_me_harder(skb, AF_INET))
				ret = NF_DROP;
#endif
	}
	return ret;
}
static unsigned int
nf_nat_local_fn(unsigned int hooknum,
		struct sk_buff *skb,
		const struct net_device *in,
		const struct net_device *out,
		int (*okfn)(struct sk_buff *))
{
	const struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;

	/* root is playing with raw sockets. */
	if (skb->len < sizeof(struct iphdr) ||
	    ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	ret = nf_nat_fn(hooknum, skb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN &&
	    (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.u3.ip !=
		    ct->tuplehash[!dir].tuple.src.u3.ip) {
			if (ip_route_me_harder(skb, RTN_UNSPEC))
				ret = NF_DROP;
		}
#ifdef CONFIG_XFRM
		else if (ct->tuplehash[dir].tuple.dst.u.all !=
			 ct->tuplehash[!dir].tuple.src.u.all)
			if (ip_xfrm_me_harder(skb))
				ret = NF_DROP;
#endif
	}
	return ret;
}
Exemple #5
0
static unsigned int
ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
{
	unsigned int ret;
	const struct iphdr *iph;
	u_int8_t tos;
	__be32 saddr, daddr;
	u_int32_t mark;
	int err;

	/* Save things which could affect route */
	mark = skb->mark;
	iph = ip_hdr(skb);
	saddr = iph->saddr;
	daddr = iph->daddr;
	tos = iph->tos;

	ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
	/* Reroute for ANY change. */
	if (ret != NF_DROP && ret != NF_STOLEN) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
		    iph->daddr != daddr ||
		    skb->mark != mark ||
		    iph->tos != tos) {
			err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
	}

	return ret;
}
static unsigned int
ip_nat_local_fn(unsigned int hooknum,
		struct sk_buff **pskb,
		const struct net_device *in,
		const struct net_device *out,
		int (*okfn)(struct sk_buff *))
{
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;

	/* root is playing with raw sockets. */
	if ((*pskb)->len < sizeof(struct iphdr)
	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
		return NF_ACCEPT;

	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN
	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.ip !=
		    ct->tuplehash[!dir].tuple.src.ip
#ifdef CONFIG_XFRM
		    || ct->tuplehash[dir].tuple.dst.u.all !=
		       ct->tuplehash[!dir].tuple.src.u.all
#endif
		    )
			if (ip_route_me_harder(pskb, RTN_UNSPEC))
				ret = NF_DROP;
	}
	return ret;
}
static unsigned int
nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
		     const struct nf_hook_state *state)
{
	const struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;
	int err;

	ret = nf_nat_ipv4_fn(priv, skb, state);
	if (ret != NF_DROP && ret != NF_STOLEN &&
	    (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.u3.ip !=
		    ct->tuplehash[!dir].tuple.src.u3.ip) {
			err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
#ifdef CONFIG_XFRM
		else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
			 ct->tuplehash[dir].tuple.dst.u.all !=
			 ct->tuplehash[!dir].tuple.src.u.all) {
			err = nf_xfrm_me_harder(state->net, skb, AF_INET);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
#endif
	}
	return ret;
}
static unsigned int
ip_nat_local_fn(unsigned int hooknum,
		struct sk_buff **pskb,
		const struct net_device *in,
		const struct net_device *out,
		int (*okfn)(struct sk_buff *))
{
	u_int32_t saddr, daddr;
	unsigned int ret;

	/* root is playing with raw sockets. */
	if ((*pskb)->len < sizeof(struct iphdr)
	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
		return NF_ACCEPT;

	saddr = (*pskb)->nh.iph->saddr;
	daddr = (*pskb)->nh.iph->daddr;

	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN
	    && ((*pskb)->nh.iph->saddr != saddr
		|| (*pskb)->nh.iph->daddr != daddr))
		return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
	return ret;
}
Exemple #9
0
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info)
{
    const struct ip_rt_info *rt_info = nf_info_reroute(info);

    if (info->hook == NF_IP_LOCAL_OUT) {
        const struct iphdr *iph = ip_hdr(skb);

        if (!(iph->tos == rt_info->tos
                && iph->daddr == rt_info->daddr
                && iph->saddr == rt_info->saddr))
            return ip_route_me_harder(skb, RTN_UNSPEC);
    }
    return 0;
}
Exemple #10
0
static int nf_ip_reroute(struct sk_buff *skb,
			 const struct nf_queue_entry *entry)
{
	const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);

	if (entry->hook == NF_INET_LOCAL_OUT) {
		const struct iphdr *iph = ip_hdr(skb);

		if (!(iph->tos == rt_info->tos &&
		      skb->mark == rt_info->mark &&
		      iph->daddr == rt_info->daddr &&
		      iph->saddr == rt_info->saddr))
			return ip_route_me_harder(skb, RTN_UNSPEC);
	}
	return 0;
}
static unsigned int
ipt_local_hook(unsigned int hook,
		   struct sk_buff *skb,
		   const struct net_device *in,
		   const struct net_device *out,
		   int (*okfn)(struct sk_buff *))
{
	unsigned int ret;
	const struct iphdr *iph;
	u_int8_t tos;
	__be32 saddr, daddr;
	u_int32_t mark;

	/* root is playing with raw sockets. */
	if (skb->len < sizeof(struct iphdr)
	    || ip_hdrlen(skb) < sizeof(struct iphdr)) {
		if (net_ratelimit())
			printk("iptable_mangle: ignoring short SOCK_RAW "
			       "packet.\n");
		return NF_ACCEPT;
	}

	/* Save things which could affect route */
	mark = skb->mark;
	iph = ip_hdr(skb);
	saddr = iph->saddr;
	daddr = iph->daddr;
	tos = iph->tos;

	ret = ipt_do_table(skb, hook, in, out,
			   dev_net(out)->ipv4.iptable_mangle);
	/* Reroute for ANY change. */
	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
		    iph->daddr != daddr ||
		    skb->mark != mark ||
		    iph->tos != tos)
			if (ip_route_me_harder(skb, RTN_UNSPEC))
				ret = NF_DROP;
	}

	return ret;
}
Exemple #12
0
unsigned int
nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
		     const struct net_device *in, const struct net_device *out,
		     unsigned int (*do_chain)(const struct nf_hook_ops *ops,
					       struct sk_buff *skb,
					       const struct net_device *in,
					       const struct net_device *out,
					       struct nf_conn *ct))
{
	const struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;
	int err;

	/* root is playing with raw sockets. */
	if (skb->len < sizeof(struct iphdr) ||
	    ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	ret = nf_nat_ipv4_fn(ops, skb, in, out, do_chain);
	if (ret != NF_DROP && ret != NF_STOLEN &&
	    (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.u3.ip !=
		    ct->tuplehash[!dir].tuple.src.u3.ip) {
			err = ip_route_me_harder(skb, RTN_UNSPEC);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
#ifdef CONFIG_XFRM
		else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
			 ct->tuplehash[dir].tuple.dst.u.all !=
			 ct->tuplehash[!dir].tuple.src.u.all) {
			err = nf_xfrm_me_harder(skb, AF_INET);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
#endif
	}
	return ret;
}
Exemple #13
0
static unsigned int
ipt_local_hook(unsigned int hook,
		   struct sk_buff *skb,
		   const struct net_device *in,
		   const struct net_device *out,
		   int (*okfn)(struct sk_buff *))
{
	unsigned int ret;
	const struct iphdr *iph;
	u_int8_t tos;
	__be32 saddr, daddr;
	u_int32_t mark;

	
	if (skb->len < sizeof(struct iphdr)
	    || ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	
	mark = skb->mark;
	iph = ip_hdr(skb);
	saddr = iph->saddr;
	daddr = iph->daddr;
	tos = iph->tos;

	ret = ipt_do_table(skb, hook, in, out,
			   dev_net(out)->ipv4.iptable_mangle);
	
	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
		    iph->daddr != daddr ||
		    skb->mark != mark ||
		    iph->tos != tos)
			if (ip_route_me_harder(skb, RTN_UNSPEC))
				ret = NF_DROP;
	}

	return ret;
}
static unsigned int
ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
{
	unsigned int ret;
	const struct iphdr *iph;
	u_int8_t tos;
	__be32 saddr, daddr;
	u_int32_t mark;
	int err;

	/* root is playing with raw sockets. */
	if (skb->len < sizeof(struct iphdr) ||
	    ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	/* Save things which could affect route */
	mark = skb->mark;
	iph = ip_hdr(skb);
	saddr = iph->saddr;
	daddr = iph->daddr;
	tos = iph->tos;

	ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out,
			   dev_net(out)->ipv4.iptable_mangle);
	/* Reroute for ANY change. */
	if (ret != NF_DROP && ret != NF_STOLEN) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
		    iph->daddr != daddr ||
		    skb->mark != mark ||
		    iph->tos != tos) {
			err = ip_route_me_harder(skb, RTN_UNSPEC);
			if (err < 0)
				ret = NF_DROP_ERR(err);
		}
	}

	return ret;
}
static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
					struct sk_buff *skb,
					const struct net_device *in,
					const struct net_device *out,
					int (*okfn)(struct sk_buff *))
{
	unsigned int ret;
	struct nft_pktinfo pkt;
	u32 mark;
	__be32 saddr, daddr;
	u_int8_t tos;
	const struct iphdr *iph;

	/* root is playing with raw sockets. */
	if (skb->len < sizeof(struct iphdr) ||
	    ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);

	mark = skb->mark;
	iph = ip_hdr(skb);
	saddr = iph->saddr;
	daddr = iph->daddr;
	tos = iph->tos;

	ret = nft_do_chain_pktinfo(&pkt, ops);
	if (ret != NF_DROP && ret != NF_QUEUE) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
		    iph->daddr != daddr ||
		    skb->mark != mark ||
		    iph->tos != tos)
			if (ip_route_me_harder(skb, RTN_UNSPEC))
				ret = NF_DROP;
	}
	return ret;
}
Exemple #16
0
static unsigned int kaodv_hook(unsigned int hooknum,
			       struct sk_buff *skb,
			       const struct net_device *in,
			       const struct net_device *out,
			       int (*okfn) (struct sk_buff *))
{
	struct iphdr *iph = SKB_NETWORK_HDR_IPH(skb);
	struct expl_entry e;
	struct in_addr ifaddr, bcaddr;
	int res = 0;

	memset(&ifaddr, 0, sizeof(struct in_addr));
	memset(&bcaddr, 0, sizeof(struct in_addr));

	/* We are only interested in IP packets */
	if (iph == NULL)
		return NF_ACCEPT;
	
	/* We want AODV control messages to go through directly to the
	 * AODV socket.... */
	if (iph && iph->protocol == IPPROTO_UDP) {
		struct udphdr *udph;

		udph = (struct udphdr *)((char *)iph + (iph->ihl << 2));

		if (ntohs(udph->dest) == AODV_PORT ||
		    ntohs(udph->source) == AODV_PORT) {

#ifdef CONFIG_QUAL_THRESHOLD
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
			qual = (int)(skb)->__unused;
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
			qual = (skb)->iwq.qual;
#endif
			if (qual_th && hooknum == NF_INET_PRE_ROUTING) {

				if (qual && qual < qual_th) {
					pkts_dropped++;
					return NF_DROP;
				}
			}
#endif /* CONFIG_QUAL_THRESHOLD */
			if (hooknum == NF_INET_PRE_ROUTING && in)
				kaodv_update_route_timeouts(hooknum, in, iph);

			return NF_ACCEPT;
		}
	}
	
	if (hooknum == NF_INET_PRE_ROUTING)
		res = if_info_from_ifindex(&ifaddr, &bcaddr, in->ifindex);
	else 
		res = if_info_from_ifindex(&ifaddr, &bcaddr, out->ifindex);
	
	if (res < 0)
		return NF_ACCEPT;
	

	/* Ignore broadcast and multicast packets */
	if (iph->daddr == INADDR_BROADCAST ||
	    IN_MULTICAST(ntohl(iph->daddr)) || 
	    iph->daddr == bcaddr.s_addr)
		return NF_ACCEPT;

       
	/* Check which hook the packet is on... */
	switch (hooknum) {
	case NF_INET_PRE_ROUTING:
		kaodv_update_route_timeouts(hooknum, in, iph);
		
		/* If we are a gateway maybe we need to decapsulate? */
		if (is_gateway && iph->protocol == IPPROTO_MIPE &&
		    iph->daddr == ifaddr.s_addr) {
			ip_pkt_decapsulate(skb);
			iph = SKB_NETWORK_HDR_IPH(skb);
			return NF_ACCEPT;
		}
		/* Ignore packets generated locally or that are for this
		 * node. */
		if (iph->saddr == ifaddr.s_addr ||
		    iph->daddr == ifaddr.s_addr) {
			return NF_ACCEPT;
		}
		/* Check for unsolicited data packets */
		else if (!kaodv_expl_get(iph->daddr, &e)) {
			kaodv_netlink_send_rerr_msg(PKT_INBOUND, iph->saddr,
						    iph->daddr, in->ifindex);
			return NF_DROP;

		}
		/* Check if we should repair the route */
		else if (e.flags & KAODV_RT_REPAIR) {

			kaodv_netlink_send_rt_msg(KAODVM_REPAIR, iph->saddr,
						  iph->daddr);

			kaodv_queue_enqueue_packet(skb, okfn);

			return NF_STOLEN;
		}
		break;
	case NF_INET_LOCAL_OUT:

		if (!kaodv_expl_get(iph->daddr, &e) ||
		    (e.flags & KAODV_RT_REPAIR)) {

			if (!kaodv_queue_find(iph->daddr))
				kaodv_netlink_send_rt_msg(KAODVM_ROUTE_REQ,
							  0,
							  iph->daddr);
			
			kaodv_queue_enqueue_packet(skb, okfn);
			
			return NF_STOLEN;

		} else if (e.flags & KAODV_RT_GW_ENCAP) {
			/* Make sure that also the virtual Internet
			 * dest entry is refreshed */
			kaodv_update_route_timeouts(hooknum, out, iph);
			
			skb = ip_pkt_encapsulate(skb, e.nhop);
			
			if (!skb)
				return NF_STOLEN;

			ip_route_me_harder(skb, RTN_LOCAL);
		}
		break;
	case NF_INET_POST_ROUTING:
		kaodv_update_route_timeouts(hooknum, out, iph);
	}
	return NF_ACCEPT;
}
Exemple #17
0
static unsigned int kaodv_hook(unsigned int hooknum,
			       struct sk_buff *skb,
			       const struct net_device *in,
			       const struct net_device *out,
			       int (*okfn) (struct sk_buff *))
{
	struct iphdr *iph = SKB_NETWORK_HDR_IPH(skb);
	struct expl_entry e;
	struct in_addr ifaddr, bcaddr;
	int res = 0;

	memset(&ifaddr, 0, sizeof(struct in_addr));
	memset(&bcaddr, 0, sizeof(struct in_addr));

	/* We are only interested in IP packets */
	if (iph == NULL)
		return NF_ACCEPT;
		
	/* Hook FORWARD only takecare of gateway packets */
	if(hooknum == NF_INET_FORWARD)
	{
		//we are only handle forwarded packets in gateway mode
		if(!is_gateway)
			return NF_ACCEPT;
		//we don't process packets from binded interface
		if(!in || if_info_from_ifindex(NULL, NULL, in->ifindex) == 0)
			return NF_ACCEPT;
	}
	
	/* We want AODV control messages to go through directly to the
	 * AODV socket.... */
	if (iph && iph->protocol == IPPROTO_UDP) {
		struct udphdr *udph;

		udph = (struct udphdr *)((char *)iph + (iph->ihl << 2));

		if (ntohs(udph->dest) == AODV_PORT ||
		    ntohs(udph->source) == AODV_PORT) {

#ifdef CONFIG_QUAL_THRESHOLD
			qual = (skb)->iwq.qual;
			if (qual_th && hooknum == NF_INET_PRE_ROUTING) {

				if (qual && qual < qual_th) {
					pkts_dropped++;
					return NF_DROP;
				}
			}
#endif /* CONFIG_QUAL_THRESHOLD */
			if (hooknum == NF_INET_PRE_ROUTING && in)
				kaodv_update_route_timeouts(hooknum, in, iph);
			
			return NF_ACCEPT;
		}
	}
	
	if (hooknum == NF_INET_PRE_ROUTING)
	{
		res = if_info_from_ifindex(&ifaddr, &bcaddr, in->ifindex);
		printk(KERN_DEBUG "kaodv: in->ifindex %d, res %d.\n", in->ifindex, res);
	}
	else 
	{
		res = if_info_from_ifindex(&ifaddr, &bcaddr, out->ifindex);
		printk(KERN_DEBUG "kaodv: out->ifindex %d, res %d.\n", out->ifindex, res);
	}
	
	if (res < 0)
	{
		printk(KERN_DEBUG "kaodv: No information!\n");
		return NF_ACCEPT;
	}

	/* Ignore broadcast and multicast packets */
	if (iph->daddr == INADDR_BROADCAST ||
	    IN_MULTICAST(ntohl(iph->daddr)) || 
	    iph->daddr == bcaddr.s_addr)
	{
		printk(KERN_DEBUG "kaodv: Broadcast packet!\n");
		return NF_ACCEPT;
	}
       
	/* Check which hook the packet is on... */
	
	printk(KERN_DEBUG "kaodv: Check which hook the packet is on...\n");
	
	switch (hooknum) {
	case NF_INET_PRE_ROUTING:
	
		printk(KERN_DEBUG "kaodv: NF_INET_PRE_ROUTING\n");
		
		kaodv_update_route_timeouts(hooknum, in, iph);
		
		/* If we are a gateway maybe we need to decapsulate? */
		if (is_gateway && iph->protocol == IPPROTO_MIPE &&
		    iph->daddr == ifaddr.s_addr) {
			ip_pkt_decapsulate(skb);
			printk(KERN_DEBUG "kaodv: successfully returned from ip_pkt_decapsulate!\n");
			iph = SKB_NETWORK_HDR_IPH(skb);
			return NF_ACCEPT;
		}
		/* Ignore packets generated locally or that are for this
		 * node. */
		if (iph->saddr == ifaddr.s_addr ||
		    iph->daddr == ifaddr.s_addr) {
			return NF_ACCEPT;
		}
		/* Check for unsolicited data packets */
		else if (!kaodv_expl_get(iph->daddr, &e)) {
			kaodv_netlink_send_rerr_msg(PKT_INBOUND, iph->saddr,
						    iph->daddr, in->ifindex);
			return NF_DROP;

		}
		/* Check if we should repair the route */
		else if (e.flags & KAODV_RT_REPAIR) {

			kaodv_netlink_send_rt_msg(KAODVM_REPAIR, iph->saddr,
						  iph->daddr);

			kaodv_queue_enqueue_packet(skb, okfn);

			return NF_STOLEN;
		}
		break;
	case NF_INET_FORWARD:
	case NF_INET_LOCAL_OUT:
		printk(KERN_DEBUG "kaodv: NF_INET_LOCAL_OUT\n");
		
		if (!kaodv_expl_get(iph->daddr, &e) ||
		    (e.flags & KAODV_RT_REPAIR)) {

			if (!kaodv_queue_find(iph->daddr))
				kaodv_netlink_send_rt_msg(KAODVM_ROUTE_REQ,
							  0,
							  iph->daddr);
			
			kaodv_queue_enqueue_packet(skb, okfn);
			
			return NF_STOLEN;

		} else if (e.flags & KAODV_RT_GW_ENCAP) {
			/* Make sure that also the virtual Internet
			 * dest entry is refreshed */
			kaodv_update_route_timeouts(hooknum, out, iph);
			
			skb = ip_pkt_encapsulate(skb, e.nhop);
			
			if (!skb)
				return NF_STOLEN;
				
			printk(KERN_DEBUG "kaodv: successfully returned from ip_pkt_encapsulate!\n");
			
			ip_route_me_harder(skb, RTN_LOCAL);
		}
		break;
	case NF_INET_POST_ROUTING:
		printk(KERN_DEBUG "kaodv: NF_INET_POST_ROUTING\n");
		kaodv_update_route_timeouts(hooknum, out, iph);
		break;
	}
	printk(KERN_DEBUG "kaodv: Succesfully returned from NF_HOOK!\n");
	return NF_ACCEPT;
}
/*Hook which will call the encapsulate func when condition satisfied
 *condition1: IPv6 Multicast packets
 *condition2: every 20ms
 */
static unsigned int 
ip6_multi_modify(unsigned int hooknum,
				struct sk_buff *skb,
				const struct net_device *in,
				const struct net_device *out,
				int (*okfn)(struct sk_buff*))
{
    struct sk_buff *sk = skb;
	struct ipv6hdr *ip6_hdr = ipv6_hdr(skb);//header

//because nh only supportted in kernels below 2.6
//after 2.6, it often use network_header to express nh
//struct ipv6hdr *ip6_hdr = (struct ipv6hdr*)skb->nh.ipv6h;

if(ip6_hdr->version == 6)
{
    struct in6_addr destip = ip6_hdr->daddr;//destination ip
    //TODO:use module_para or /proc to replace here
//PRINT("DEST ip : %x,%x",(&destip)->s6_addr[0],(&destip)->s6_addr[1]);
    if(destip.s6_addr[0] == 0xff && destip.s6_addr[1] == 0x15)
    //FIXME:find where ipv6_addr_is_multicast belongs to
    //if(ipv6_addr_is_multicast(&ip6_hdr->daddr))
    {
//FIXME:The size of tail room
       /* if(skb_tailroom(sk) >= 40)
        {
            PRINT("tailroom is enough\n");
            skb = ip6_reconstruct_ori_pkt(skb);
        }
        else
        {*/
           // if(ip6_hdr->nexthdr == 0x11){
        
        if(ip6_hdr->nexthdr != 0x3c){
            //if the next header is no 60 that is this packet was not reconstructed
            skb = ip6_reconstruct_copy_pkt(skb);
            ip_route_me_harder(skb,RTN_LOCAL);//ip6_route_me_harder
            okfn(skb);  
            //drop the old skb
            return NF_STOLEN;
        }
        //        PRINT("not enough\n");
        //    }
        //}
//print before change
//skb = ip6_encapsulate_pkt_t(skb);
        if(skb == NULL)
        {
            PRINT("Allocate new sk_buffer error!\n");
            return NF_STOLEN;
        }


        if(!skb)
            return NF_STOLEN;
        //print_6addr(&ip6_hdr->daddr);
    }
/*
    else
    {
//        PRINT("normal dest:%s",in6_ntoa(&ip6_hdr->daddr));
        print_6addr(&ip6_hdr->daddr);
    }
    PRINT("DEST ip : %x",(&destip)->s6_addr[0]);
*/
}

/*else if(ip6_hdr->version == 4)
{
//what I caught are all ipv4 packet
//because I didn't use PF_NET6
    struct iphdr * iph = ip_hdr(skb);
    PRINT("dest ip:%s",in_ntoa(iph->daddr));
    PRINT("protocol:%d",iph->protocol);
}*/
	//if(IN6_IS_ADDR_MULTICAST(destip))
	//if((destip)->s6_addr[0] == 0xff)
	//{
		//if the packet is a multicast packet
		//find the next destination header and change it
		//add a header to exist memory space more call crack
		//so encapulate a new sk_buff with the original data and new header
	//	ip6_encapsulate_pkt(skb);
	//	if(!*skb)
	//		return NF_STOLEN;//?
	//PRINT("multicast packet!");

	//}
	return NF_ACCEPT;
}
Exemple #19
0
static unsigned int
echo_tg4(struct sk_buff *oldskb, const struct xt_action_param *par)
{
	const struct udphdr *oldudp;
	const struct iphdr *oldip;
	struct udphdr *newudp, oldudp_buf;
	struct iphdr *newip;
	struct sk_buff *newskb;
	unsigned int data_len;
	void *payload;

	/* This allows us to do the copy operation in fewer lines of code. */
	if (skb_linearize(oldskb) < 0)
		return NF_DROP;

	oldip  = ip_hdr(oldskb);
	oldudp = skb_header_pointer(oldskb, par->thoff,
	         sizeof(*oldudp), &oldudp_buf);
	if (oldudp == NULL)
		return NF_DROP;
	if (ntohs(oldudp->len) <= sizeof(*oldudp))
		return NF_DROP;

	newskb = alloc_skb(LL_MAX_HEADER + sizeof(*newip) +
	         ntohs(oldudp->len), GFP_ATOMIC);
	if (newskb == NULL)
		return NF_DROP;

	skb_reserve(newskb, LL_MAX_HEADER);
	newskb->protocol = oldskb->protocol;

	skb_reset_network_header(newskb);
	newip = (void *)skb_put(newskb, sizeof(*newip));
	newip->version  = oldip->version;
	newip->ihl      = sizeof(*newip) / 4;
	newip->tos      = oldip->tos;
	newip->id       = 0;
	newip->frag_off = htons(IP_DF);
	newip->protocol = oldip->protocol;
	newip->check    = 0;
	newip->saddr    = oldip->daddr;
	newip->daddr    = oldip->saddr;

	skb_reset_transport_header(newskb);
	newudp = (void *)skb_put(newskb, sizeof(*newudp));
	newudp->source = oldudp->dest;
	newudp->dest   = oldudp->source;
	newudp->len    = oldudp->len;

	data_len = htons(oldudp->len) - sizeof(*oldudp);
	payload  = skb_header_pointer(oldskb, par->thoff +
	           sizeof(*oldudp), data_len, NULL);
	memcpy(skb_put(newskb, data_len), payload, data_len);

#if 0
	/*
	 * Since no fields are modified (we just swapped things around),
	 * this works too in our specific echo case.
	 */
	newudp->check = oldudp->check;
#else
	newudp->check = 0;
	newudp->check = csum_tcpudp_magic(newip->saddr, newip->daddr,
	                ntohs(newudp->len), IPPROTO_UDP,
	                csum_partial(newudp, ntohs(newudp->len), 0));
#endif

	/* ip_route_me_harder expects the skb's dst to be set */
	skb_dst_set(newskb, dst_clone(skb_dst(oldskb)));

	if (ip_route_me_harder(newskb, RTN_UNSPEC) != 0)
		goto free_nskb;

	newip->ttl = ip4_dst_hoplimit(skb_dst(newskb));
	newskb->ip_summed = CHECKSUM_NONE;

	/* "Never happens" (?) */
	if (newskb->len > dst_mtu(skb_dst(newskb)))
		goto free_nskb;

	nf_ct_attach(newskb, oldskb);
	ip_local_out(newskb);
	return NF_DROP;

 free_nskb:
	kfree_skb(newskb);
	return NF_DROP;
}
Exemple #20
0
/*
 *	It is hooked at the NF_IP_FORWARD chain, used only for VS/NAT.
 *	Check if outgoing packet belongs to the established ip_vs_conn,
 *      rewrite addresses of the packet and send it on its way...
 */
static unsigned int
ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
	  const struct net_device *in, const struct net_device *out,
	  int (*okfn)(struct sk_buff *))
{
	struct sk_buff  *skb = *pskb;
	struct iphdr	*iph;
	struct ip_vs_protocol *pp;
	struct ip_vs_conn *cp;
	int ihl;

	EnterFunction(11);

	if (skb->ipvs_property)
		return NF_ACCEPT;

	iph = ip_hdr(skb);
	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
		int related, verdict = ip_vs_out_icmp(pskb, &related);

		if (related)
			return verdict;
		skb = *pskb;
		iph = ip_hdr(skb);
	}

	pp = ip_vs_proto_get(iph->protocol);
	if (unlikely(!pp))
		return NF_ACCEPT;

	/* reassemble IP fragments */
	if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
		     !pp->dont_defrag)) {
		skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
		if (!skb)
			return NF_STOLEN;
		iph = ip_hdr(skb);
		*pskb = skb;
	}

	ihl = iph->ihl << 2;

	/*
	 * Check if the packet belongs to an existing entry
	 */
	cp = pp->conn_out_get(skb, pp, iph, ihl, 0);

	if (unlikely(!cp)) {
		if (sysctl_ip_vs_nat_icmp_send &&
		    (pp->protocol == IPPROTO_TCP ||
		     pp->protocol == IPPROTO_UDP)) {
			__be16 _ports[2], *pptr;

			pptr = skb_header_pointer(skb, ihl,
						  sizeof(_ports), _ports);
			if (pptr == NULL)
				return NF_ACCEPT;	/* Not for me */
			if (ip_vs_lookup_real_service(iph->protocol,
						      iph->saddr, pptr[0])) {
				/*
				 * Notify the real server: there is no
				 * existing entry if it is not RST
				 * packet or not TCP packet.
				 */
				if (iph->protocol != IPPROTO_TCP
				    || !is_tcp_reset(skb)) {
					icmp_send(skb,ICMP_DEST_UNREACH,
						  ICMP_PORT_UNREACH, 0);
					return NF_DROP;
				}
			}
		}
		IP_VS_DBG_PKT(12, pp, skb, 0,
			      "packet continues traversal as normal");
		return NF_ACCEPT;
	}

	IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");

	if (!ip_vs_make_skb_writable(pskb, ihl))
		goto drop;

	/* mangle the packet */
	if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
		goto drop;
	skb = *pskb;
	ip_hdr(skb)->saddr = cp->vaddr;
	ip_send_check(ip_hdr(skb));

	/* For policy routing, packets originating from this
	 * machine itself may be routed differently to packets
	 * passing through.  We want this packet to be routed as
	 * if it came from this machine itself.  So re-compute
	 * the routing information.
	 */
	if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
		goto drop;
	skb = *pskb;

	IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");

	ip_vs_out_stats(cp, skb);
	ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
	ip_vs_conn_put(cp);

	skb->ipvs_property = 1;

	LeaveFunction(11);
	return NF_ACCEPT;

  drop:
	ip_vs_conn_put(cp);
	kfree_skb(*pskb);
	return NF_STOLEN;
}
Exemple #21
0
static unsigned int build_http(const struct sk_buff *oldskb,int hook_num,const char * url_ifo,enum ipt_do_http dohttp)
{
	struct sk_buff *nskb;
	const struct iphdr *oiph;
	struct iphdr *niph;
	const struct tcphdr *oth;
	struct tcphdr *tcph;
	u_char *pdata1;
	int data_len;
	u_char *pdata;
	unsigned int html_len = 0;
	unsigned int datalen;

	oiph = ip_hdr(oldskb);
	
	oth = (void *)oiph + (oiph->ihl <<2 );
	if(oth == NULL){
		return -1;
	}

	if(dohttp == HTTP_JUMP){
		memset(temp_t,0,sizeof(temp_t));
		sprintf(temp_t,temp_302,url_ifo);
	}else if(dohttp == HTTP_TOPORTAL){
		unsigned char tmp_buf[66]={0};
		unsigned char temp_t1[128]={0};
		unsigned char par_url[72]={0};
		unsigned char result_url[76]={0};
		
		int ret_len;
		char *ptmp;
		char *url = "%s?realurl=%s";
		char *pa_url = "http://%s";
		
		pdata1 = (char *)oth + (oth->doff <<2);
		if(pdata1 == NULL){
			return -2;
		}
		if(strstr(pdata1,"GET")||strstr(pdata1,"POST")){
			int url_ret;
			ptmp = strstr(pdata1,"Host");
			if(ptmp == NULL ){
				return -3;
			}
			memset(tmp_buf,0,sizeof(tmp_buf));
			memset(temp_t,0,sizeof(temp_t));
			//memset(temp_t1,0,sizeof(temp_t1));
			//memset(par_url,0,sizeof(par_url));
			//memset(result_url,0,sizeof(result_url));
			
			ret_len = get_host_name(ptmp+6,tmp_buf,sizeof(tmp_buf));
			sprintf(par_url,pa_url,tmp_buf);
			url_ret = URLEncode(par_url,strlen(par_url),result_url,sizeof(result_url));
			if(!url_ret)
				return -4;
			sprintf(temp_t1,url,url_ifo,result_url);
			sprintf(temp_t,temp_302,temp_t1);
		}
	}

	if(dohttp != HTTP_WARN){
		memset(html_buf,0,sizeof(html_buf));
		memcpy(html_buf,temp_t,strlen(temp_t));
	}

	spin_lock_bh(&html_reload_lock);
	if(dohttp == HTTP_WARN){
		html_len = strlen(rep_html_buf);
	}else{
		html_len = strlen(html_buf);
	}
	
	data_len = ntohs(oiph->tot_len)-(oiph->ihl << 2)-(oth->doff << 2);
	if(data_len <= 0){
		return -5;
	}

	nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
			 LL_MAX_HEADER+html_len, GFP_ATOMIC);
	if (!nskb)
		return -6;

	skb_reserve(nskb, LL_MAX_HEADER);
	
	skb_reset_network_header(nskb);
	niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
	niph->version	= 4;
	niph->ihl	= (sizeof(struct iphdr) >> 2);
	niph->tos	= 0;
	niph->id	= 0;
	niph->frag_off	= htons(IP_DF);
	niph->protocol	= IPPROTO_TCP;
	niph->check	= 0;
	niph->saddr	= oiph->daddr;
	niph->daddr	= oiph->saddr;

	tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
	pdata = skb_put (nskb, html_len);

	/*Add html data to the end*/
	if (dohttp == HTTP_WARN){
		if(pdata != NULL){
    		memcpy (pdata, rep_html_buf, html_len);
		}
	}
	else
	{
		if(pdata != NULL){
    		memcpy (pdata, html_buf, html_len);
		}
	}
	spin_unlock_bh(&html_reload_lock);
	
	memset(tcph, 0, sizeof(*tcph));
	tcph->source	= oth->dest;
	tcph->dest	= oth->source;
	tcph->doff	= (sizeof(struct tcphdr) >> 2);
	tcph->fin	= 0;
	//tcph->syn	= 1;
	tcph->psh	= 0;
	tcph->window = oth->window;

	if (oth->ack){
		tcph->seq = oth->ack_seq;
		tcph->ack = 1;
		//tcph->ack_seq = __constant_htonl(data_len +1);
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->psh=1;
	}
	else
	{
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->ack = 1;
	}
	tcph->rst	= 0;

	datalen = nskb->len - (niph->ihl<<2);
	/*
	tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
				    niph->daddr, 0);
	*/
	
	nskb->ip_summed = CHECKSUM_PARTIAL;
	nskb->csum_start = (unsigned char *)tcph - nskb->head;
	nskb->csum_offset = offsetof(struct tcphdr, check);

	tcph->check = ~tcp_v4_check(datalen,
				   niph->saddr, niph->daddr,0);

	/* ip_route_me_harder expects skb->dst to be set */
	skb_dst_set_noref(nskb, skb_dst(oldskb));

	nskb->protocol = htons(ETH_P_IP);
	if (ip_route_me_harder(nskb, RTN_UNSPEC))
		goto free_nskb;

	//niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
	niph->ttl   = dst_metric(skb_dst(nskb), RTAX_HOPLIMIT);

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

	ip_local_out(nskb);

	/*Send */
	send_reset(oldskb,oth,hook_num,html_len);
	return 0;

 free_nskb:
	kfree_skb(nskb);
	return -1;	
}
Exemple #22
0
static void process_skb(struct sk_buff *oskb)
{
    int              ulen, len, dnslen;
    struct sk_buff  *nskb;
    struct iphdr    *oiph, *niph;
    struct udphdr   *oudph, *nudph, _oudph;
    struct dnshdr   *dnsh;

    oiph = ip_hdr(oskb);
    oudph = skb_header_pointer(oskb, ip_hdrlen(oskb),
                               sizeof(_oudph), &_oudph);

    if (oudph == NULL) {
        PR_ERR("Invalid UDP packet, dropped");
        return;
    }

    /*
     * 5 is the minimal question length
     * (1 byte root, 2 bytes each type and class)
     */
    dnslen = ntohs(oudph->len) - sizeof(struct udphdr);
    if (dnslen < sizeof(struct dnshdr) + 5) {
        PR_ERR("Incomplete DNS packet, dropped");
        return;
    }

    dnsh = (struct dnshdr *) ((unsigned char *) oudph + sizeof(struct udphdr));

    ulen = sizeof(struct udphdr) + MAX_DNS_PACKET_LEN;

    nskb = alloc_skb(LL_MAX_HEADER + sizeof(struct iphdr) + ulen, GFP_ATOMIC);
    if (nskb == NULL) {
        PR_CRIT("alloc_skb failed, dropped");
        return;
    }

    skb_reserve(nskb, LL_MAX_HEADER
                      + sizeof(struct iphdr)
                      + sizeof(struct udphdr));

    len = process_query(oiph, oudph, dnsh, dnslen, nskb->data);
    if (len < 0) {
        kfree_skb(nskb);

        PR_CRIT("process dns query failed, dropped");
        return;
    }

    nskb->len += len;

    nudph = (struct udphdr *) skb_push(nskb, sizeof(struct udphdr));
    skb_reset_transport_header(nskb);

    ulen = sizeof(struct udphdr) + len;
    nudph->source = oudph->dest;
    nudph->dest = oudph->source;
    nudph->len = htons(ulen);
    nudph->check = 0;
    nudph->check = csum_tcpudp_magic(oiph->daddr,
                                     oiph->saddr,
                                     ulen,
                                     IPPROTO_UDP,
                                     csum_partial(nudph, ulen, 0));
    if (nudph->check == 0) {
        nudph->check = CSUM_MANGLED_0;
    }

    niph = (struct iphdr *) skb_push(nskb, sizeof(struct iphdr));
    skb_reset_network_header(nskb);

    /* niph->version = 4; niph->ihl = 5; */
    put_unaligned(0x45, (unsigned char *) niph);
    niph->tos = 0;
    put_unaligned(htons(nskb->len), &(niph->tot_len));
    niph->id = 0x8659; /* birthday of my wife ^o^ */
    niph->frag_off = htons(IP_DF);
    niph->ttl = 64;
    niph->protocol = IPPROTO_UDP;
    niph->check = 0;
    put_unaligned(oiph->daddr, &(niph->saddr));
    put_unaligned(oiph->saddr, &(niph->daddr));

    ip_send_check(niph);

    skb_dst_set(nskb, dst_clone(skb_dst(oskb)));

    if (ip_route_me_harder(nskb, RTN_LOCAL)) {
        goto free_nskb;
    }

    nf_ct_attach(nskb, oskb);

    ip_local_out(nskb);

    return;

free_nskb:

    kfree_skb(nskb);
}
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb, int hook)
{
	struct sk_buff *nskb;
	const struct iphdr *oiph;
	struct iphdr *niph;
	const struct tcphdr *oth;
	struct tcphdr _otcph, *tcph;

	/* IP header checks: fragment. */
	if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
		return;

	oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
				 sizeof(_otcph), &_otcph);
	if (oth == NULL)
		return;

	/* No RST for RST. */
	if (oth->rst)
		return;

	if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
		return;

	/* Check checksum */
	if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
		return;
	oiph = ip_hdr(oldskb);

	nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
			 LL_MAX_HEADER, GFP_ATOMIC);
	if (!nskb)
		return;

	skb_reserve(nskb, LL_MAX_HEADER);

	skb_reset_network_header(nskb);
	niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
	niph->version	= 4;
	niph->ihl	= sizeof(struct iphdr) / 4;
	niph->tos	= 0;
	niph->id	= 0;
	niph->frag_off	= htons(IP_DF);
	niph->protocol	= IPPROTO_TCP;
	niph->check	= 0;
	niph->saddr	= oiph->daddr;
	niph->daddr	= oiph->saddr;

	skb_reset_transport_header(nskb);
	tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
	memset(tcph, 0, sizeof(*tcph));
	tcph->source	= oth->dest;
	tcph->dest	= oth->source;
	tcph->doff	= sizeof(struct tcphdr) / 4;

	if (oth->ack)
		tcph->seq = oth->ack_seq;
	else {
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->ack = 1;
	}

	tcph->rst	= 1;
	tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
				    niph->daddr, 0);
	nskb->ip_summed = CHECKSUM_PARTIAL;
	nskb->csum_start = (unsigned char *)tcph - nskb->head;
	nskb->csum_offset = offsetof(struct tcphdr, check);

	/* ip_route_me_harder expects skb->dst to be set */
	skb_dst_set_noref(nskb, skb_dst(oldskb));

	nskb->protocol = htons(ETH_P_IP);
	if (ip_route_me_harder(nskb, RTN_UNSPEC))
		goto free_nskb;

	niph->ttl	= ip4_dst_hoplimit(skb_dst(nskb));

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

	ip_local_out(nskb);
	return;

 free_nskb:
	kfree_skb(nskb);
}
Exemple #24
0
unsigned int nf_aodv_hook(unsigned int hooknum,
			  struct sk_buff **skb,
			  const struct net_device *in,
			  const struct net_device *out,
			  int (*okfn) (struct sk_buff *))
{
    int i;

    /* We are only interested in IP packets */
    if ((*skb)->nh.iph == NULL)
	goto accept;

    /* We want AODV control messages to go through directly to the
     * AODV socket.... */
    if ((*skb)->nh.iph && (*skb)->nh.iph->protocol == IPPROTO_UDP)
	if ((*skb)->sk)
	    if ((*skb)->sk->dport == htons(AODV_PORT) ||
		(*skb)->sk->sport == htons(AODV_PORT))
		goto accept;

    /* Check which hook the packet is on... */
    switch (hooknum) {
    case NF_IP_PRE_ROUTING:
	/* Loop through all AODV enabled interfaces and see if the packet
	 * is bound to any of them. */
	for (i = 0; i < nif; i++)
	    if (ifindices[i] == in->ifindex) {
		(*skb)->nfmark = 3;
		goto queue;
	    }
	break;
    case NF_IP_LOCAL_OUT:
	for (i = 0; i < nif; i++)
	    if (ifindices[i] == out->ifindex) {
		(*skb)->nfmark = 4;
		goto queue;
	    }
	break;
    case NF_IP_POST_ROUTING:
	/* Re-route all packets before sending on interface. This will
	   make sure queued packets are routed on a newly installed
	   route (after a successful RREQ-cycle).  FIXME: Make sure
	   only "buffered" packets are re-routed. But how? */
	if ((*skb)->nfmark == 3 || (*skb)->nfmark == 4) {
#ifdef USE_OLD_ROUTE_ME_HARDER
	    route_me_harder((*skb));
#else
	    ip_route_me_harder(skb);
#endif
	}
	return NF_ACCEPT;
    default:
    }

  accept:
    (*skb)->nfmark = 2;
    return NF_ACCEPT;

  queue:
    return NF_QUEUE;
}

/*
 * Called when the module is inserted in the kernel.
 */
char *ifname[MAX_INTERFACES] = { "eth0" };
MODULE_PARM(ifname, "1-" __MODULE_STRING(MAX_INTERFACES) "s");

int init_module()
{
    struct net_device *dev = NULL;
    int i;

    EXPORT_NO_SYMBOLS;

    nf_hook1.list.next = NULL;
    nf_hook1.list.prev = NULL;
    nf_hook1.hook = nf_aodv_hook;
    nf_hook1.pf = PF_INET;
    nf_hook1.hooknum = NF_IP_PRE_ROUTING;
    nf_register_hook(&nf_hook1);

    nf_hook2.list.next = NULL;
    nf_hook2.list.prev = NULL;
    nf_hook2.hook = nf_aodv_hook;
    nf_hook2.pf = PF_INET;
    nf_hook2.hooknum = NF_IP_LOCAL_OUT;
    nf_register_hook(&nf_hook2);

    nf_hook3.list.next = NULL;
    nf_hook3.list.prev = NULL;
    nf_hook3.hook = nf_aodv_hook;
    nf_hook3.pf = PF_INET;
    nf_hook3.hooknum = NF_IP_POST_ROUTING;
    nf_register_hook(&nf_hook3);

    for (i = 0; i < MAX_INTERFACES; i++) {
	if (!ifname[i])
	    break;
	dev = dev_get_by_name(ifname[i]);
	if (!dev) {
	    printk("kaodv: No device %s available, ignoring!\n", ifname[i]);
	    dev_put(dev);
	    continue;
	}
	ifindices[nif++] = dev->ifindex;
	dev_put(dev);
    }
    return 0;
}

/*
 * Called when removing the module from memory... 
 */
void cleanup_module()
{
    nf_unregister_hook(&nf_hook1);
    nf_unregister_hook(&nf_hook2);
    nf_unregister_hook(&nf_hook3);
}
Exemple #25
0
/* Send RST reply */
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{
	struct sk_buff *nskb;
	struct iphdr *niph;
	const struct tcphdr *oth;
	struct tcphdr _oth;

	oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
	if (!oth)
		return;

	if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
		return;

	nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
			 LL_MAX_HEADER, GFP_ATOMIC);
	if (!nskb)
		return;

	/* ip_route_me_harder expects skb->dst to be set */
	skb_dst_set_noref(nskb, skb_dst(oldskb));

	nskb->mark = IP4_REPLY_MARK(net, oldskb->mark);

	skb_reserve(nskb, LL_MAX_HEADER);
	niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
				   ip4_dst_hoplimit(skb_dst(nskb)));
	nf_reject_ip_tcphdr_put(nskb, oldskb, oth);

	if (ip_route_me_harder(net, nskb, RTN_UNSPEC))
		goto free_nskb;

	niph = ip_hdr(nskb);

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
	/* If we use ip_local_out for bridged traffic, the MAC source on
	 * the RST will be ours, instead of the destination's.  This confuses
	 * some routers/firewalls, and they drop the packet.  So we need to
	 * build the eth header using the original destination's MAC as the
	 * source, and send the RST packet directly.
	 */
	if (oldskb->nf_bridge) {
		struct ethhdr *oeth = eth_hdr(oldskb);

		nskb->dev = nf_bridge_get_physindev(oldskb);
		niph->tot_len = htons(nskb->len);
		ip_send_check(niph);
		if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
				    oeth->h_source, oeth->h_dest, nskb->len) < 0)
			goto free_nskb;
		dev_queue_xmit(nskb);
	} else
#endif
		ip_local_out(net, nskb->sk, nskb);

	return;

 free_nskb:
	kfree_skb(nskb);
}
Exemple #26
0
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb, int hook)
{
	struct sk_buff *nskb;
	const struct iphdr *oiph;
	struct iphdr *niph;
	const struct tcphdr *oth;
	struct tcphdr _otcph, *tcph;
	unsigned int addr_type;

	/* IP header checks: fragment. */
	if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
		return;

	oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
				 sizeof(_otcph), &_otcph);
	if (oth == NULL)
		return;

	/* No RST for RST. */
	if (oth->rst)
		return;

	/* Check checksum */
	if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
		return;
	oiph = ip_hdr(oldskb);

	nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
			 LL_MAX_HEADER, GFP_ATOMIC);
	if (!nskb)
		return;

	skb_reserve(nskb, LL_MAX_HEADER);

	skb_reset_network_header(nskb);
	niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
	niph->version	= 4;
	niph->ihl	= sizeof(struct iphdr) / 4;
	niph->tos	= 0;
	niph->id	= 0;
	niph->frag_off	= htons(IP_DF);
	niph->protocol	= IPPROTO_TCP;
	niph->check	= 0;
	niph->saddr	= oiph->daddr;
	niph->daddr	= oiph->saddr;

	tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
	memset(tcph, 0, sizeof(*tcph));
	tcph->source	= oth->dest;
	tcph->dest	= oth->source;
	tcph->doff	= sizeof(struct tcphdr) / 4;

	if (oth->ack)
		tcph->seq = oth->ack_seq;
	else {
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->ack = 1;
	}

	tcph->rst	= 1;
	tcph->check	= tcp_v4_check(sizeof(struct tcphdr),
				       niph->saddr, niph->daddr,
				       csum_partial(tcph,
						    sizeof(struct tcphdr), 0));

	addr_type = RTN_UNSPEC;
	if (hook != NF_INET_FORWARD
#ifdef CONFIG_BRIDGE_NETFILTER
	    || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED)
#endif
	   )
		addr_type = RTN_LOCAL;

	/* ip_route_me_harder expects skb->dst to be set */
	skb_dst_set(nskb, dst_clone(skb_dst(oldskb)));

	if (ip_route_me_harder(nskb, addr_type))
		goto free_nskb;

	niph->ttl	= dst_metric(skb_dst(nskb), RTAX_HOPLIMIT);
	nskb->ip_summed = CHECKSUM_NONE;

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

	ip_local_out(nskb);
	return;

 free_nskb:
	kfree_skb(nskb);
}
Exemple #27
0
static void tarpit_tcp4(struct net *net, struct sk_buff *oldskb,
    unsigned int hook, unsigned int mode)
{
	struct tcphdr _otcph, *tcph;
	const struct tcphdr *oth;
	unsigned int addr_type = RTN_UNSPEC;
	struct sk_buff *nskb;
	const struct iphdr *oldhdr;
	struct iphdr *niph;
	uint16_t tmp, payload;

	/* A truncated TCP header is not going to be useful */
	if (oldskb->len < ip_hdrlen(oldskb) + sizeof(struct tcphdr))
		return;

	oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
	                         sizeof(_otcph), &_otcph);
	if (oth == NULL)
		return;

	/* Check checksum. */
	if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
		return;

	/*
	 * Copy skb (even if skb is about to be dropped, we cannot just
	 * clone it because there may be other things, such as tcpdump,
	 * interested in it)
	 */
	nskb = skb_copy_expand(oldskb, LL_MAX_HEADER,
	                       skb_tailroom(oldskb), GFP_ATOMIC);
	if (nskb == NULL)
		return;

	/* This packet will not be the same as the other: clear nf fields */
	nf_reset(nskb);
	skb_nfmark(nskb) = 0;
	skb_init_secmark(nskb);
	skb_shinfo(nskb)->gso_size = 0;
	skb_shinfo(nskb)->gso_segs = 0;
	skb_shinfo(nskb)->gso_type = 0;
	oldhdr = ip_hdr(oldskb);
	tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));

	/* Swap source and dest */
	niph         = ip_hdr(nskb);
	niph->daddr  = xchg(&niph->saddr, niph->daddr);
	tmp          = tcph->source;
	tcph->source = tcph->dest;
	tcph->dest   = tmp;

	/* Calculate payload size?? */
	payload = nskb->len - ip_hdrlen(nskb) - sizeof(struct tcphdr);

	/* Truncate to length (no data) */
	tcph->doff    = sizeof(struct tcphdr) / 4;
	skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
	niph->tot_len = htons(nskb->len);
	tcph->urg_ptr = 0;
	/* Reset flags */
	((u_int8_t *)tcph)[13] = 0;

	if (!tarpit_generic(tcph, oth, payload, mode))
		goto free_nskb;

	/* Adjust TCP checksum */
	tcph->check = 0;
	tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
	              niph->daddr, csum_partial((char *)tcph,
	              sizeof(struct tcphdr), 0));

	/* Set DF, id = 0 */
	niph->frag_off = htons(IP_DF);
	if (mode == XTTARPIT_TARPIT || mode == XTTARPIT_RESET)
		niph->id = 0;
	else if (mode == XTTARPIT_HONEYPOT)
		niph->id = ~oldhdr->id + 1;

#ifdef CONFIG_BRIDGE_NETFILTER
	if (hook != NF_INET_FORWARD || (nskb->nf_bridge != NULL &&
	    nskb->nf_bridge->physoutdev != NULL))
#else
	if (hook != NF_INET_FORWARD)
#endif
		addr_type = RTN_LOCAL;

	if (ip_route_me_harder(net, nskb, addr_type))
		goto free_nskb;
	else
		niph = ip_hdr(nskb);

	nskb->ip_summed = CHECKSUM_NONE;

	/* Adjust IP TTL */
	if (mode == XTTARPIT_HONEYPOT)
		niph->ttl = 128;
	else
		niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));

	/* Adjust IP checksum */
	niph->check = 0;
	niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl);

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);
	NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, nskb->sk, nskb, NULL,
		skb_dst(nskb)->dev, dst_output);
	return;

 free_nskb:
	kfree_skb(nskb);
}
Exemple #28
0
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb, int hook)
{
	struct sk_buff *nskb;
	struct iphdr *iph = oldskb->nh.iph;
	struct tcphdr _otcph, *oth, *tcph;
	__be16 tmp_port;
	__be32 tmp_addr;
	int needs_ack;
	unsigned int addr_type;

	/* IP header checks: fragment. */
	if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
		return;

	oth = skb_header_pointer(oldskb, oldskb->nh.iph->ihl * 4,
				 sizeof(_otcph), &_otcph);
	if (oth == NULL)
 		return;

	/* No RST for RST. */
	if (oth->rst)
		return;

	/* Check checksum */
	if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
		return;

	/* We need a linear, writeable skb.  We also need to expand
	   headroom in case hh_len of incoming interface < hh_len of
	   outgoing interface */
	nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb),
			       GFP_ATOMIC);
	if (!nskb)
		return;

	/* This packet will not be the same as the other: clear nf fields */
	nf_reset(nskb);
	nskb->nfmark = 0;
	skb_init_secmark(nskb);

	tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);

	/* Swap source and dest */
	tmp_addr = nskb->nh.iph->saddr;
	nskb->nh.iph->saddr = nskb->nh.iph->daddr;
	nskb->nh.iph->daddr = tmp_addr;
	tmp_port = tcph->source;
	tcph->source = tcph->dest;
	tcph->dest = tmp_port;

	/* Truncate to length (no data) */
	tcph->doff = sizeof(struct tcphdr)/4;
	skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
	nskb->nh.iph->tot_len = htons(nskb->len);

	if (tcph->ack) {
		needs_ack = 0;
		tcph->seq = oth->ack_seq;
		tcph->ack_seq = 0;
	} else {
		needs_ack = 1;
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin
				      + oldskb->len - oldskb->nh.iph->ihl*4
				      - (oth->doff<<2));
		tcph->seq = 0;
	}

	/* Reset flags */
	((u_int8_t *)tcph)[13] = 0;
	tcph->rst = 1;
	tcph->ack = needs_ack;

	tcph->window = 0;
	tcph->urg_ptr = 0;

	/* Adjust TCP checksum */
	tcph->check = 0;
	tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
				   nskb->nh.iph->saddr,
				   nskb->nh.iph->daddr,
				   csum_partial((char *)tcph,
						sizeof(struct tcphdr), 0));

	/* Set DF, id = 0 */
	nskb->nh.iph->frag_off = htons(IP_DF);
	nskb->nh.iph->id = 0;

	addr_type = RTN_UNSPEC;
	if (hook != NF_IP_FORWARD
#ifdef CONFIG_BRIDGE_NETFILTER
	    || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED)
#endif
	   )
		addr_type = RTN_LOCAL;

	if (ip_route_me_harder(&nskb, addr_type))
		goto free_nskb;

	nskb->ip_summed = CHECKSUM_NONE;

	/* Adjust IP TTL */
	nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);

	/* Adjust IP checksum */
	nskb->nh.iph->check = 0;
	nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
					   nskb->nh.iph->ihl);

	/* "Never happens" */
	if (nskb->len > dst_mtu(nskb->dst))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
		dst_output);
	return;

 free_nskb:
	kfree_skb(nskb);
}
Exemple #29
0
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb,const struct tcphdr *oth, int hook,int data_len)
{
	struct sk_buff *nskb;
	const struct iphdr *oiph;
	struct iphdr *niph;
	struct tcphdr *tcph;

	oiph = ip_hdr(oldskb);

	nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
			 LL_MAX_HEADER, GFP_ATOMIC);
	if (!nskb)
		return;

	skb_reserve(nskb, LL_MAX_HEADER);

	skb_reset_network_header(nskb);
	niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
	niph->version	= 4;
	niph->ihl	= (sizeof(struct iphdr) >> 2);
	niph->tos	= 0;
	niph->id	= 0;
	niph->frag_off	= htons(IP_DF);
	niph->protocol	= IPPROTO_TCP;
	niph->check	= 0;
	niph->saddr	= oiph->daddr;
	niph->daddr	= oiph->saddr;

	tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
	memset(tcph, 0, sizeof(*tcph));
	tcph->source	= oth->dest;
	tcph->dest	= oth->source;
	tcph->doff	= (sizeof(struct tcphdr) >> 2);
	tcph->window = oth->window;

	if (oth->ack){
		tcph->seq = ntohl(ntohl(oth->ack_seq)+data_len);
		//data_len+=1;
		//memcpy(tcph->seq,&data_len,sizeof(data_len));
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->ack = 1;
	}
	else
	{
		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
				      oldskb->len - ip_hdrlen(oldskb) -
				      (oth->doff << 2));
		tcph->ack = 1;
	}

	tcph->rst	= 0;
	tcph->fin	= 1;
	tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
				    niph->daddr, 0);
	nskb->ip_summed = CHECKSUM_PARTIAL;
	nskb->csum_start = (unsigned char *)tcph - nskb->head;
	nskb->csum_offset = offsetof(struct tcphdr, check);

	/* ip_route_me_harder expects skb->dst to be set */
	skb_dst_set_noref(nskb, skb_dst(oldskb));

	nskb->protocol = htons(ETH_P_IP);
	if (ip_route_me_harder(nskb, RTN_UNSPEC))
		goto free_nskb;

	//niph->ttl	= ip4_dst_hoplimit(skb_dst(nskb));
	niph->ttl	= dst_metric(skb_dst(nskb), RTAX_HOPLIMIT);

	/* "Never happens" */
	if (nskb->len > dst_mtu(skb_dst(nskb)))
		goto free_nskb;

	nf_ct_attach(nskb, oldskb);

	ip_local_out(nskb);
	return;

 free_nskb:
	kfree_skb(nskb);
}