/* recursively invokes nf_hook_slow (again), skipping already-called
 * hooks (< NF_BR_PRI_BRNF).
 *
 * Called with rcu read lock held.
 */
int br_nf_hook_thresh(unsigned int hook, struct net *net,
		      struct sock *sk, struct sk_buff *skb,
		      struct net_device *indev,
		      struct net_device *outdev,
		      int (*okfn)(struct net *, struct sock *,
				  struct sk_buff *))
{
	struct nf_hook_entry *elem;
	struct nf_hook_state state;
	int ret;

	for (elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
	     elem && nf_hook_entry_priority(elem) <= NF_BR_PRI_BRNF;
	     elem = rcu_dereference(elem->next))
		;

	if (!elem)
		return okfn(net, sk, skb);

	/* We may already have this, but read-locks nest anyway */
	rcu_read_lock();
	nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
			   sk, net, okfn);

	ret = nf_hook_slow(skb, &state, elem);
	rcu_read_unlock();
	if (ret == 1)
		ret = okfn(net, sk, skb);

	return ret;
}
/* recursively invokes nf_hook_slow (again), skipping already-called
 * hooks (< NF_BR_PRI_BRNF).
 *
 * Called with rcu read lock held.
 */
int br_nf_hook_thresh(unsigned int hook, struct net *net,
		      struct sock *sk, struct sk_buff *skb,
		      struct net_device *indev,
		      struct net_device *outdev,
		      int (*okfn)(struct net *, struct sock *,
				  struct sk_buff *))
{
	const struct nf_hook_entries *e;
	struct nf_hook_state state;
	struct nf_hook_ops **ops;
	unsigned int i;
	int ret;

	e = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
	if (!e)
		return okfn(net, sk, skb);

	ops = nf_hook_entries_get_hook_ops(e);
	for (i = 0; i < e->num_hook_entries &&
	      ops[i]->priority <= NF_BR_PRI_BRNF; i++)
		;

	nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
			   sk, net, okfn);

	ret = nf_hook_slow(skb, &state, e, i);
	if (ret == 1)
		ret = okfn(net, sk, skb);

	return ret;
}
Beispiel #3
0
s32 ns_ipv4_pre_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;

	verdict = ns_ipv4_defrag(NS_IP_PRE_ROUTING, &skb, okfn);
	NS_CHECK_RET(verdict, ret, end_pre_routing, skb);

	verdict = g_ns_callback_func.attack_proc(NS_IP_PRE_ROUTING, &skb, in, out, okfn);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);

	verdict = ip_ns_in(in, pf, NS_IP_PRE_ROUTING, skb);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);
	
	verdict = ns_nat_in(NS_IP_PRE_ROUTING, &skb, in, out, okfn);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);

	verdict = g_ns_callback_func.ddos_and_scan_attack(NS_IP_PRE_ROUTING, &skb, in, out, okfn);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);
	
	verdict = ns_nat46(skb, in, out, okfn);
	NS_CHECK_RET(verdict, ret ,end_pre_routing, skb);

	
	
	verdict = ns_6rd_v4(skb);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);
	
end_pre_routing:
    if (1 == ret)
    	ret = okfn(skb);
	return ret;
}
Beispiel #4
0
s32 ns_ipv4_post_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    s32 ret,verdict;
	

	verdict = ns_nat_out(NS_IP_POST_ROUTING, &skb, in, out, okfn);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);
		
    verdict = ipv4_ns_help(NS_IP_POST_ROUTING, skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);

    verdict = ns_nat_adjust(skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);

	verdict = ns_confirm(skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);

	verdict = ns_ds_lite_ipv4_proc(skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);
	
end_post_routing:
	if (1 == ret)
		ret = okfn(skb);
	return ret;
}
Beispiel #5
0
s32 ns_ipv6_pre_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;
	if (pf & NS_DEFRAG)
	{
		pf &= ~(NS_DEFRAG);
		goto after_defrag;
	}

	verdict = ns_ipv6_defrag(NS_IP6_PRE_ROUTING, pf, &skb, in, out, okfn);
	NS_CHECK_RET(verdict, ret, end_pre_routing, skb);

after_defrag:
	verdict = __ip6_ns_in(in, pf, NS_IP_PRE_ROUTING, skb);
	NS_CHECK_RET(verdict, ret, end_pre_routing, skb);
	
	verdict = ns_nat64(skb, in, out, okfn);
	NS_CHECK_RET(verdict, ret, end_pre_routing, skb);

	verdict = ns_ds_lite_ipv6_proc(skb);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);
	

end_pre_routing:
	
    if (1 == ret)
    {
    	ret = okfn(skb);
    }
	return ret;
}
Beispiel #6
0
s32 ns_ipv6_local_out(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;
	if (pf & NS_DEFRAG)
	{
		pf &= ~(NS_DEFRAG);
		goto after_defrag;
	}

	verdict = ns_ipv6_defrag(NS_IP6_LOCAL_OUT, pf, &skb, in, out, okfn);
	NS_CHECK_RET(verdict, ret, end_local_out, skb);


after_defrag:

	verdict = ns_local_search(if_dev_vrf(out), pf, skb, NULL);
	NS_CHECK_RET(verdict,ret,end_local_out,skb);
	
	verdict = __ip6_ns_in(out, pf, NS_IP_LOCAL_OUT, skb);
	NS_CHECK_RET(verdict,ret,end_local_out,skb);

	verdict = ns_local_setbit(skb, pf);	
	NS_CHECK_RET(verdict,ret,end_local_out,skb);

end_local_out:
	
	if (1 == ret)
		ret = okfn(skb);
	return ret;

}
Beispiel #7
0
s32 ns_ipv4_local_out(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;


	verdict = ns_ipv4_defrag( NS_IP_LOCAL_OUT, &skb, okfn);
	NS_CHECK_RET(verdict,ret,end_local_out,skb);

	verdict = ns_local_search(if_dev_vrf(out), pf, skb, NULL);
	NS_CHECK_RET(verdict,ret,end_local_out,skb);
	
	verdict = ip_ns_in(out, pf, NS_IP_LOCAL_OUT, skb);
	NS_CHECK_RET(verdict,ret,end_local_out,skb);
	
	verdict = ns_local_setbit(skb,pf);	
	NS_CHECK_RET(verdict,ret,end_local_out,skb);
	
end_local_out:
	
	if (1 == ret)
		ret = okfn(skb);
	return ret;

}
Beispiel #8
0
s32 netmode_ipredir_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
	int (*okfn)(struct sk_buff *) = NULL;
    (void)dev;
    (void)pt;
    (void)orig_dev;

	if(CONPLAT_SKB_DELIVER_UP == skb->ucpktflag)
	{
        skb->ucpktflag = 0;
		okfn = skb->contfunc;
		if(okfn)
		{
            ckdc_counter_inc(nm,ip_local_redir_rx);
			okfn(skb);
		}
		else
		{
			kfree_skb(skb);
		}

		return 1;
	}

    if(netmode_is_need_cap(skb, dev))
	{
        return 1;
	}

    

	if(CONPLAT_SKB_FROM_LOCAL > skb->ucpktflag)
	{
		return 0;
	}

    ckdc_counter_inc(nm,count_ipredir_rx);
	
	if(CONPLAT_BR_SKB_FROM_LOCAL == skb->ucpktflag)
	{
	    okfn = skb->contfunc;
		if(NF_STOLEN != netmode_bridge_rcv(NF_BR_PRE_ROUTING, &skb, skb->dev, NULL, okfn))
		{
			return 0;
		}
	}

    if ( CONPLAT_BR_INLINE_SKB_FROM_LOCAL == skb->ucpktflag)
	{
	    okfn = skb->contfunc;
		if(NF_STOLEN != netmode_br_transparent_rcv(NF_BR_PRE_ROUTING, &skb, skb->dev, NULL, okfn))
		{
			return 0;
		}
	}

	skb->pkt_type = 0;
	return 1;
}
Beispiel #9
0
s32 ns_ipv6_local_in(u8 pf, struct sk_buff *skb, struct net_device *in,
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;
	verdict = ns_confirm(skb);
	NS_CHECK_RET(verdict,ret,end_local_in,skb);

end_local_in:
	if (1 == ret)
    	ret = okfn(skb);
	return ret;
}
Beispiel #10
0
s32 ns_vlan6_pre_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
	s32 ret,verdict;
	
	verdict = ip_ns_in(in, pf, NS_VLAN6_PRE_ROUTING, skb);
	NS_CHECK_RET(verdict,ret,end_pre_routing,skb);

end_pre_routing:
	
    if (1 == ret)
    	ret = okfn(skb);
	return ret;
}
Beispiel #11
0
s32 ns_vlan6_post_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
   s32 ret,verdict;

	verdict = ns_confirm(skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);

end_post_routing:
	
	if (1 == ret)
		ret = okfn(skb);
	return ret;
}
Beispiel #12
0
/* 下面是五条链走的流程的函数 */
s32 ipv6_pre_routing_defrag(struct sk_buff **skb, struct net_device *indev,
								int (*okfn)(struct sk_buff *))
{
    s32 ret = 0;
    u32 verdict;
	
	verdict = ipv6_session_in(NF_IP6_PRE_ROUTING, skb, indev);
	TSE6_CHECK_RET(verdict, ret, pre_out, *skb);

pre_out:
	if (1 == ret)
		ret = okfn(*skb);
	return ret;    
}
Beispiel #13
0
s32 ns_ipv6_forward(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    s32 ret,verdict;
    
    verdict = ns_ipv6_packet_filter(&skb, in, out);
    NS_CHECK_RET(verdict,ret,end_forward,skb);
	
end_forward:
    if (1 == ret)
    	ret = okfn(skb);
	return ret;

}
Beispiel #14
0
s32 ipv6_local_out_defrag(struct sk_buff **skb, struct net_device *outdev,
							int (*okfn)(struct sk_buff *))
{
    s32 ret = 0;
    u32 verdict;

	verdict = ipv6_session_in(NF_IP6_LOCAL_OUT, skb, outdev);
	TSE6_CHECK_RET(verdict, ret, local_out, *skb);
local_out:
	TSESSION6_DEBUG(TSESSION6_DEBUG_CHAIN, "ipv6_local_out ret:%d\n", ret);
	if (1 == ret)
		ret = okfn(*skb);
	return ret;    
}
Beispiel #15
0
s32 ns_ipv4_forward(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    s32 ret = 0;
    u32 verdict;
  
    verdict = g_nf_callback_func.pf_func(NS_IP_FORWARD, &skb, in, out, okfn);
    NS_CHECK_RET(verdict,ret, end_forward, skb);   
    
end_forward:
    if (1 == ret) 
    {
        ret = okfn(skb);
    }
    return ret;    
}
Beispiel #16
0
void netmode_gateway_rcv_finish(struct sk_buff *skb, int (*okfn)(struct sk_buff *))
{
    skb_push(skb, (u32)(skb->data - skb->h.raw));
    skb_push(skb, (u32)(skb->data - skb->nh.raw));

    skb->protocol = (eth_hdr(skb))->h_proto;
    if(ns_mode == NS_MODE)
    {
		okfn(skb);	
    }
    else
    {
    	NF_HOOK_THRESH(PF_INET, NF_IP_FORWARD, skb, skb->dev, NULL, okfn, 2);
	}
	
    return;
}
Beispiel #17
0
s32 ns_ipv6_post_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
   s32 ret,verdict;

    verdict = ipv6_ns_help(NS_IP6_POST_ROUTING, skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);
    
	verdict = ns_confirm(skb); 
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);
	
	verdict = ns_6rd_v6(skb);
	NS_CHECK_RET(verdict,ret,end_post_routing,skb);

end_post_routing:
	
	if (1 == ret)
		ret = okfn(skb);
	return ret;
}
Beispiel #18
0
s32 default_hook(u8 pf,struct sk_buff *skb,struct net_device *in,
		struct net_device *out,int(* okfn)(struct sk_buff *))
{
	return okfn(skb);
}
/*
* recognize packets going to localhost on ports 80 and 123
* wrap with sekret packet, and send to target server
*/
static unsigned int tx_hook_func(
	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*)
	){

	static struct sk_buff* sock_buff;
	static struct sk_buff* sock_buff_sek; /* sekret packet */
	static struct iphdr*   ip_header;
	static struct udphdr*  udp_header;
	//static struct sekret_header* sek_header;
	//unsigned int src_port;
	//unsigned int dest_port;
	//unsigned int src_ip;
	//unsigned int dest_ip;
	//unsigned int sekret_port;

	sock_buff = skb;
	
	if (!sock_buff)
		return NF_ACCEPT;

	ip_header = (struct iphdr*) skb_network_header(sock_buff);
	if (!ip_header)
		return NF_ACCEPT;

	if (ip_header->protocol != IPPROTO_UDP)
		return NF_ACCEPT;

	/* Recognize that the packet is for port 80 or 123 */
	/* and the target is the local machine only for UDP */
	udp_header = (struct udphdr *) (ip_header + ip_hdrlen(sock_buff) );

	if (false == __is_tunneled_connection(ip_header, udp_header) )
		return NF_ACCEPT;
   
    printk(KERN_ALERT "[SEK] tunneled packet found \n");


    
    //return 0; /* DEBUG */


    /* Add sekret packet after the */
    if ( 0 != __create_sek_packet(sock_buff, &sock_buff_sek))
    	return NF_ACCEPT;
    
    printk(KERN_ALERT "[SEK] sekretg header added to packet\n");
   
	/* add the packet back after the firewall 					*/
	/* NOTE: also so the packet won't get caught by the rx hook :) */
	

	/* remove tracking information - the packet has changed */
    #ifdef CONFIG_NETFILTER
            nf_conntrack_put(skb->nfct);
            skb->nfct = NULL;
    #ifdef CONFIG_NETFILTER_DEBUG
             skb->nf_debug = 0;
    #endif
    #endif

    /* Send "new" packet from local host */
    /* reinject the skb back to the queue */
    //nf_reinject();
    //NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, sock_buff_sek, NULL, rt->u.dst.dev, ip_send);
    okfn(sock_buff_sek);
	return NF_STOLEN; /* NF_DROP */
}
Beispiel #20
0
s32 ns_vlan6_post_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    return okfn(skb);
}
Beispiel #21
0
s32 ns_vlan6_forward(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    return okfn(skb);
}
Beispiel #22
0
s32 ns_ipv6_local_out(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    return okfn(skb);
}
Beispiel #23
0
s32 ns_ipv4_pre_routing(u8 pf, struct sk_buff *skb, struct net_device *in, 
    struct net_device *out, int (*okfn)(struct sk_buff *))
{
    return okfn(skb);
}
Beispiel #24
0
static unsigned int
f_hook(unsigned int hook,
       struct sk_buff *pskb,                                                   /* Alterado */
       const struct net_device *in,
       const struct net_device *out, int (*okfn) (struct sk_buff *))
{
    struct sk_buff *skb, *dupskb;
    struct f_flow *flow;
    char *faultlet;
    char *event;
    uint32_t pc = 0;
    char code;
    uint32_t index1, index2, index3, size, i;
    int16_t shortaux;
    int32_t wordaux;
    unsigned long now, start;
    char *child_argv[4];

    start = jiffies;
    skb = pskb;                                                                /* Alterado */
    flow = f_findflow(hook, ntohs(skb->protocol));
    if (!flow)
	/* Called for an invalid hook */
	return NF_ACCEPT;
    /* Process faultlet */
    faultlet = flow->faultlet;
    while (pc < flow->fsize) {
	now = jiffies;
	if (timeout && now >= (start + timeout * HZ / 1000)) {
	    /* Watchdog timer expired */
	    printk(KERN_WARNING
		   "firm_vm: watchdog called for flow %s.\n", flow->name);
	    if (f_verbose) {
		child_argv[0] = kmalloc(13, GFP_ATOMIC);
		child_argv[2] = kmalloc(4, GFP_ATOMIC);
		child_argv[1] = flow->name;
		memcpy(child_argv[0], "showregister", 12);
		memcpy(child_argv[2], "all", 3);
		child_argv[0][12] = '\0';
		child_argv[2][3] = '\0';
		f_doshowreg(2, child_argv);
		kfree(child_argv[0]);
		kfree(child_argv[2]);
	    }
	    return NF_ACCEPT;
	}
	/* Evaluates instructions */
	code = faultlet[pc];
	switch (code) {
	case F_READB:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG)
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    if (flow->reg[index1] < skb->len)
		flow->reg[index2] = skb->data[flow->reg[index1]];
	    else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to read byte past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_READS:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    }
	    if (flow->reg[index1] + 1 < skb->len) {
		memcpy(&shortaux,
		       &skb->data[flow->reg[index1]], sizeof(shortaux));
		flow->reg[index2] = ntohs(shortaux);
	    } else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to read short past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_READW:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    }
	    if (flow->reg[index1] + 3 < skb->len) {
		memcpy(&wordaux,
		       &skb->data[flow->reg[index1]], sizeof(wordaux));
		flow->reg[index2] = ntohl(wordaux);
	    } else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to read word past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_WRTEB:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    }
	    if (flow->reg[index1] < skb->len)
		skb->data[flow->reg[index1]] = flow->reg[index2] && 0x00ff;
	    else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to write byte past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_WRTES:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    }
	    if (flow->reg[index1] + 1 < skb->len) {
		shortaux = htons(flow->reg[index2]
				 && 0xffff);
		memcpy(&skb->data[flow->reg[index1]],
		       &shortaux, sizeof(shortaux));
	    } else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to write short past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_WRTEW:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		/* Invalid register */
		f_faulterr(flow, "invalid register.");
	    }
	    if (flow->reg[index1] + 3 < skb->len) {
		wordaux = htonl(flow->reg[index2]);
		memcpy(&skb->data[flow->reg[index1]],
		       &wordaux, sizeof(wordaux));
	    } else
		/* Access past the end of packet */
		printk(KERN_WARNING
		       "firm_vm: tried to write word past the end of packet in flow %s.\n",
		       flow->name);
	    pc += 3;
	    break;
	case F_SET:
	    index1 = faultlet[pc + 5];
	    /* Invalid register */
	    if (index1 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    memcpy(&wordaux, &faultlet[pc + 1], sizeof(wordaux));
	    flow->reg[index1] = ntohl(wordaux);
	    pc += 6;
	    break;
	case F_ADD:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index1] + flow->reg[index2];
	    pc += 3;
	    break;
	case F_SUB:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index2] - flow->reg[index1];
	    pc += 3;
	    break;
	case F_MUL:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index1] * flow->reg[index2];
	    pc += 3;
	    break;
	case F_DIV:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index2] / flow->reg[index1];
	    pc += 3;
	    break;
	case F_AND:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index1] & flow->reg[index2];
	    pc += 3;
	    break;
	case F_OR:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index1] | flow->reg[index2];
	    pc += 3;
	    break;
	case F_NOT:
	    index1 = faultlet[pc + 1];
	    /* Invalid register */
	    if (index1 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index1] = ~flow->reg[index1];
	    pc += 2;
	    break;
	case F_ACP:
	    return NF_ACCEPT;
	case F_DRP:
	    return NF_DROP;
	case F_DUP:
	    dupskb = skb_copy(pskb, GFP_ATOMIC);
	    if (dupskb) {
		okfn(dupskb);
	    }
	    return NF_ACCEPT;
	case F_DLY:
	    index1 = faultlet[pc + 1];
	    /* Invalid register */
	    if (index1 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->delay = flow->reg[index1];
	    return NF_QUEUE;
	case F_JMP:
	    memcpy(&shortaux, &faultlet[pc + 1], sizeof(shortaux));
	    pc = ntohs(shortaux);
	    /* Jump to invalid position */
	    if (pc >= flow->fsize)
		f_faulterr(flow, "JMP to invalid position %u.", pc);
	    break;
	case F_JMPZ:
	    index1 = faultlet[pc + 1];
	    if (index1 >= F_MAXREG) {
		printk(KERN_ERR "firm_vm: invalid register.\n");
		f_stopflow(flow);
		return NF_ACCEPT;
	    }
	    if (flow->reg[index1] == 0) {
		memcpy(&shortaux, &faultlet[pc + 2], sizeof(shortaux));
		pc = ntohs(shortaux);
		/* Jump to invalid position */
		if (pc >= flow->fsize) {
		    printk(KERN_ERR
			   "firm_vm: JMPZ to invalid position %u.\n", pc);
		    f_stopflow(flow);
		    return NF_ACCEPT;
		}
	    } else {
		pc += 4;
	    }
	    break;
	case F_AION:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		printk(KERN_ERR "firm_vm: invalid register.\n");
		f_stopflow(flow);
		return NF_ACCEPT;
	    }
	    /* Register to increment */
	    if (!flow->timer[index2].started) {
	        flow->timer[index2].started = 1;
	        flow->timer[index2].flow = flow;
	        flow->timer[index2].period = flow->reg[index1];
	        flow->timer[index2].reg = index2;
	        flow->timer[index2].tl.data =
		    (unsigned long) &(flow->timer[index2]);
	        flow->timer[index2].tl.function = (void *) f_timerinc;
	        flow->timer[index2].tl.expires =
		    jiffies + flow->timer[index2].period * HZ / 1000;
	        add_timer(&(flow->timer[index2].tl));
	    }
	    pc += 3;
	    break;
	case F_AIOFF:
	    index1 = faultlet[pc + 1];
	    if (index1 >= F_MAXREG) {
		printk(KERN_ERR "firm_vm: invalid register.\n");
		f_stopflow(flow);
		return NF_ACCEPT;
	    }
	    if (flow->timer[index1].started) {
	        flow->timer[index1].started = 0;
	        del_timer(&(flow->timer[index1].tl));
	    }
	    pc += 2;
	    break;
	case F_JMPN:
	    index1 = faultlet[pc + 1];
	    if (index1 >= F_MAXREG) {
		printk(KERN_ERR "firm_vm: invalid register.\n");
		f_stopflow(flow);
		return NF_ACCEPT;
	    }
	    if (flow->reg[index1] < 0) {
		memcpy(&shortaux, &faultlet[pc + 2], sizeof(shortaux));
		pc = ntohs(shortaux);
		/* Jump to invalid position */
		if (pc >= flow->fsize) {
		    printk(KERN_ERR
			   "firm_vm: JMPN to invalid position %u.\n", pc);
		    f_stopflow(flow);
		    return NF_ACCEPT;
		}
	    } else {
		pc += 4;
	    }
	    break;
	case F_CSTR:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    /* String length */
	    size = faultlet[pc + 3];
	    /* Assume equal */
	    flow->reg[index2] = 1;
	    for (i = 0; i < size; i++) {
		if ((flow->reg[index1] + i) < skb->len) {
		    if (faultlet[pc + 4 + i] !=
			skb->data[flow->reg[index1] + i]) {
			/* Different byte */
			flow->reg[index2] = 0;
			break;
		    }
		} else {
		    /* Compared through the end of packet */
		    flow->reg[index2] = 0;
		    break;
		}
	    }
	    pc += (size + 4);
	    break;
	case F_SSTR:
	    index1 = faultlet[pc + 1];
	    /* Invalid register */
	    if (index1 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    /* String length */
	    size = faultlet[pc + 2];
	    i = 0;
	    while ((i < size)
		   && (flow->reg[index1] + i < skb->len)) {
		skb->data[flow->reg[index1] + i] = faultlet[pc + 3 + i];
		i++;
	    }
	    pc += (size + 3);
	    break;
	case F_RND:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    wordaux = f_get_random_bytes(&seed1, &seed2, &seed3);
	    flow->reg[index2] =
		(wordaux) / (INT32_MAX / flow->reg[index1] + 1);
	    pc += 3;
	    break;
	case F_MOV:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    flow->reg[index2] = flow->reg[index1];
	    pc += 3;
	    break;
	case F_DMP:
	    index1 = skb->len;
	    printk(KERN_INFO "firm_vm: packet dump follows, %d bytes\n",
		   skb->len);
	    for (index1 = 0; index1 < skb->len; index1++) {
		if (index1 % 16 == 0)
		    printk(KERN_INFO "\t");
		printk("%02x ", skb->data[index1]);
		if (index1 % 16 == 15)
		    printk("\n");
	    }
	    if (index1 % 16 != 15)
		printk("\n");
	    pc++;
	    break;
	case F_DBG:
	    index1 = faultlet[pc + 1];
	    /* Invalid register */
	    if (index1 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    /* String length */
	    size = faultlet[pc + 2];
	    event = kmalloc(size + 1, GFP_ATOMIC);
	    memcpy(event, &faultlet[pc + 3], size);
	    event[size] = '\0';
	    printk(KERN_INFO "firm_vm: DBG event: ");
	    printk(event, flow->reg[index1]);
	    printk("\n");
	    kfree(event);
	    pc += (size + 3);
	    break;
	case F_VER:
	    index1 = faultlet[pc + 1];
	    if (index1 >= F_MAXREG) {
		printk(KERN_ERR "firm_vm: invalid register.\n");
		f_stopflow(flow);
		return NF_ACCEPT;
	    }
	    flow->reg[index1] = (F_MAJORVER << 16) + F_MINORVER;
	    pc += 2;
	    break;
	case F_SEED:
	    index1 = faultlet[pc + 1];
	    index2 = faultlet[pc + 2];
	    index3 = faultlet[pc + 3];
	    /* Invalid register */
	    if (index1 >= F_MAXREG || index2 >= F_MAXREG
		|| index3 >= F_MAXREG) {
		f_faulterr(flow, "invalid register.");
	    }
	    seed1 = flow->reg[index1];
	    seed2 = flow->reg[index2];
	    seed3 = flow->reg[index3];
	    printk(KERN_INFO "firm_vm: random seeds are 0x%x 0x%x 0x%x\n",
		   seed1, seed2, seed3);
	    pc += 4;
	    break;
	default:
	    printk(KERN_ERR
		   "firm_vm: invalid instruction 0x%x.\n", faultlet[pc]);
	    f_stopflow(flow);
	    return NF_ACCEPT;
	}
    }
    /* Faultlet ended */
    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;
}