#include #include #include #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) #include #include #endif #define RING_SIZE 500 #define SYNC_RANGE 100 MODULE_LICENSE("GPL"); static wait_queue_head_t wq; static int thread_id; static DECLARE_COMPLETION(on_exit); static struct nf_hook_ops nfho_out,nfho_in; u16 tone[RING_SIZE]; int tone_counter; int tone_pos_counter; void update_tone_pos_counter(void) { if(tone_pos_counterSYNC_RANGE) { counter=tone_counter; while (((abs((counter - tone_counter+RING_SIZE) % RING_SIZE))<=SYNC_RANGE)) { tone[(counter%RING_SIZE)-1]=0; counter++; pr_debug(" %d ",(counter%RING_SIZE)-1); } pr_debug("SingingFirewall: Resyncing %d<---%d!\n",tone_counter,tone_pos_counter); tone_pos_counter=tone_counter; } } static int thread_code(void *data) { unsigned long timeout_1,timeout_2; u16 tone_; u8 Save; daemonize("KSingingFirewall"); allow_signal(SIGTERM); while(1) { if(tone[tone_counter]!=0) { tone_ = CLOCK_TICK_RATE/tone[tone_counter]; timeout_1=HZ/50; outb(0xb6, 0x43); outb_p(tone_ & 0xff, 0x42); outb((tone_>>8) & 0xff, 0x42); Save = inb(0x61); outb(Save|0x03, 0x61); timeout_1=wait_event_interruptible_timeout( wq, (timeout_1==0), timeout_1); if(timeout_1==-ERESTARTSYS) break; outb(inb_p(0x61) & 0xFC, 0x61); tone[tone_counter]=0; update_tone_counter(); pr_debug("Tone Counter: %d\n",tone_counter); } timeout_2=HZ/100; timeout_2=wait_event_interruptible_timeout( wq, (timeout_2==0), timeout_2); if(timeout_2==-ERESTARTSYS) break; } thread_id = 0; complete_and_exit(&on_exit, 0); } unsigned int hook_func( unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct tcphdr *thead; struct sk_buff *sk=*skb; u16 port; char check; check=0; if (sk->nh.iph->protocol == IPPROTO_TCP) {tone[tone_pos_counter]=100; check=1;} if (sk->nh.iph->protocol == IPPROTO_UDP) {tone[tone_pos_counter]=200; check=1;} if (sk->nh.iph->protocol == IPPROTO_ICMP) {tone[tone_pos_counter]=300; check=1;} if (!check) return NF_ACCEPT; update_tone_pos_counter(); check_syncing(); pr_debug("Tone Pos Counter: %d\n",tone_pos_counter); check=0; if (sk->nh.iph->protocol == IPPROTO_TCP) { thead=(struct tcphdr *) (sk->data + (sk->nh.iph->ihl * 4)); port=ntohs(thead->dest); switch( port ) { case 21 : {tone[tone_pos_counter]=1000;check=1;break;} case 22 : {tone[tone_pos_counter]=1500;check=1;break;} case 80 : {tone[tone_pos_counter]=2000;check=1;break;} case 443: {tone[tone_pos_counter]=2500;check=1;break;} } if (check) { update_tone_pos_counter(); check_syncing(); pr_debug("Tone Pos Counter: %d\n",tone_pos_counter); } } return NF_ACCEPT; } int init_module() { int counter; for (counter=0; counter<=RING_SIZE-1; counter++) tone[counter]=0; tone_counter=0; tone_pos_counter=0; init_waitqueue_head(&wq); thread_id=kernel_thread(thread_code, NULL, CLONE_KERNEL); if(thread_id==0) return -EIO; nfho_out.hook = hook_func; nfho_out.hooknum = NF_IP_LOCAL_OUT; nfho_out.pf = PF_INET; nfho_out.priority = NF_IP_PRI_FIRST; nfho_in.hook = hook_func; nfho_in.hooknum = NF_IP_LOCAL_IN; nfho_in.pf = PF_INET; nfho_in.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_out); nf_register_hook(&nfho_in); return 0; } void cleanup_module() { if(thread_id) kill_proc(thread_id, SIGTERM, 1); wait_for_completion(&on_exit); nf_unregister_hook(&nfho_in); nf_unregister_hook(&nfho_out); outb(inb_p(0x61) & 0xFC, 0x61); }