#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h>
#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_arp.h> #include <linux/if_arp.h> #include <net/arp.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/netdevice.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <net/tcp.h> #include <net/udp.h> #include <net/icmp.h> #include <linux/spinlock.h>
#include <linux/timer.h> #include <linux/list.h> #include <linux/jiffies.h>
#include <linux/proc_fs.h> #include <linux/sched.h>
MODULE_LICENSE("GPL"); MODULE_AUTHOR("kenthy@163.com");
#define ARP_OUT 0 #define ARP_IN 1
#define ARP_EXIST 0 #define ARP_NOT_EXIST 1 typedef struct o_arp { struct list_head list; u32 dip; u32 sip; u16 arpop; int type; // in or out
}O_ARP;
static LIST_HEAD(arplist);
static spinlock_t wa_lock = SPIN_LOCK_UNLOCKED;
static void ip_add(O_ARP* node) { unsigned long flags; spin_lock_irqsave(&wa_lock, flags); list_add(&node->list,&arplist); spin_unlock_irqrestore(&wa_lock, flags); }
/*return 1--exist 0---not exist * if exist then update it */ static int ip_exist(u32 sip, u32 dip, int type) { struct list_head *p,*n; unsigned long flags; O_ARP* node; int exists= ARP_NOT_EXIST; spin_lock_irqsave(&wa_lock, flags); list_for_each_safe(p,n,&arplist) { node=list_entry(p, O_ARP, list); if(node->sip==sip && node->dip==dip && node->type==type) { exists=ARP_EXIST; break; } } spin_unlock_irqrestore(&wa_lock, flags); return (exists); }
void free_list(void) { struct list_head *p,*n; O_ARP *node; unsigned long flags; spin_lock_irqsave(&wa_lock, flags); list_for_each_safe(p,n,&arplist) { node=list_entry(p, O_ARP,list); list_del(&(node->list)); kfree(node); } spin_unlock_irqrestore(&wa_lock, flags);
} void skb_fun(struct sk_buff* skb, int flag) { struct arphdr *arp; struct net_device * dev; unsigned char * arp_ptr; u32 sip,dip; unsigned short arpop; O_ARP* node = NULL; dev= skb->dev; arp = skb->nh.arph; arp_ptr= (unsigned char *)(arp+1); arp_ptr += dev->addr_len; memcpy(&sip, arp_ptr, 4); arp_ptr += 4; arp_ptr += dev->addr_len; memcpy(&dip, arp_ptr, 4);
arpop=ntohs(arp->ar_op);
if(ip_exist(sip, dip, ARP_IN) == ARP_NOT_EXIST) { node = kmalloc(sizeof(O_ARP),GFP_ATOMIC); if(node == NULL) { printk("%s\n", "kmalloc node error"); return; } node->sip=sip; node->dip=dip; node->arpop = arpop; node->type=flag; ip_add(node); } } unsigned int arphook_rcv(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device * out, int (*okfn)(struct sk_buff*)) { skb_fun(*skb, ARP_IN); return NF_ACCEPT; }
unsigned int arphook_snd(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff*)) { skb_fun(*skb, ARP_OUT); return NF_ACCEPT; }
static int arp_read(char *page, char **start, off_t off,int count, int *eof, void *data) { int len = 0; struct list_head *p,*n; O_ARP *node; unsigned long flags; spin_lock_irqsave(&wa_lock, flags); list_for_each_safe(p,n,&arplist) { node=list_entry(p, O_ARP,list); len += sprintf(page+len,NIPQUAD_FMT" "NIPQUAD_FMT" %s %s\n", NIPQUAD(node->sip),NIPQUAD(node->dip), node->arpop==ARPOP_REQUEST?"ARPOP_REQUEST ":"ARPOP_REPLY", node->type==ARP_OUT?"OUT":"IN"); } spin_unlock_irqrestore(&wa_lock, flags); if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return len; }
static struct nf_hook_ops arp_ops[] = { { .hook = arphook_rcv, .owner = THIS_MODULE, .pf = NF_ARP, .hooknum = NF_ARP_IN, }, { .hook = arphook_snd, .owner = THIS_MODULE, .pf = NF_ARP, .hooknum = NF_ARP_OUT, }, };
static int __init init(void) { int ret; struct proc_dir_entry *entry;
ret = nf_register_hooks(arp_ops, ARRAY_SIZE(arp_ops)); if (ret < 0) { printk("http detect:can't register arp_ops hook!\n"); return ret; } entry = create_proc_entry("o_arp", 0444, &proc_root); if(entry == 0) { printk(KERN_ERR "create_proc_entry failed!\n"); return -1; } entry->mode = S_IFREG | 0444; entry->size = 0; entry->read_proc = arp_read;
printk("insmod arp_ops module\n"); return 0; }
static void __exit fini(void) { nf_unregister_hooks(arp_ops, ARRAY_SIZE(arp_ops)); free_list(); remove_proc_entry("o_arp", &proc_root); printk("remove arp_ops hook.\n"); }
module_init(init); module_exit(fini);
|