Example #1
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;
}
Example #2
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;
}