Example #1
0
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 route_me_harder(*pskb) == 0 ? ret : NF_DROP;
	return ret;
}
Example #2
0
static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
{
	int diff;
	struct iphdr *user_iph = (struct iphdr *)v->payload;

	if (v->data_len < sizeof(*user_iph))
		return 0;
	diff = v->data_len - e->skb->len;
	if (diff < 0)
		skb_trim(e->skb, v->data_len);
	else if (diff > 0) {
		if (v->data_len > 0xFFFF)
			return -EINVAL;
		if (diff > skb_tailroom(e->skb)) {
			struct sk_buff *newskb;
			
			newskb = skb_copy_expand(e->skb,
			                         skb_headroom(e->skb),
			                         diff,
			                         GFP_ATOMIC);
			if (newskb == NULL) {
				printk(KERN_WARNING "ip_queue: OOM "
				      "in mangle, dropping packet\n");
				return -ENOMEM;
			}
			if (e->skb->sk)
				skb_set_owner_w(newskb, e->skb->sk);
			kfree_skb(e->skb);
			e->skb = newskb;
		}
		skb_put(e->skb, diff);
	}
	memcpy(e->skb->data, v->payload, v->data_len);
	e->skb->nfcache |= NFC_ALTERED;

	/*
	 * Extra routing may needed on local out, as the QUEUE target never
	 * returns control to the table.
	 */
	if (e->info->hook == NF_IP_LOCAL_OUT) {
		struct iphdr *iph = e->skb->nh.iph;

		if (!(iph->tos == e->rt_info.tos
		      && iph->daddr == e->rt_info.daddr
		      && iph->saddr == e->rt_info.saddr))
			return route_me_harder(e->skb);
	}
	return 0;
}
Example #3
0
static int ipq_set_verdict(ipq_queue_t *q,
                           ipq_verdict_msg_t *v, unsigned int len)
{
	ipq_queue_element_t *e;

	if (v->value > NF_MAX_VERDICT)
		return -EINVAL;
	e = ipq_dequeue(q, id_cmp, v->id);
	if (e == NULL)
		return -ENOENT;
	else {
		e->verdict = v->value;
		if (v->data_len && v->data_len == len)
			if (ipq_mangle_ipv4(v, e) < 0)
				e->verdict = NF_DROP;
		/* APE: Always re-route packets... UGLY HACK!!! */
		route_me_harder(e->skb);
		/* END APE */
		nf_reinject(e->skb, e->info, e->verdict);
		kfree(e);
		return 0;
	}
}
Example #4
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);
}