#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 %lu\n",
NIPQUAD(node->sip),NIPQUAD(node->dip),
node->arpop==ARPOP_REQUEST?"ARPOP_REQUEST ":"ARPOP_REPLY",
node->type==ARP_OUT?"OUT":"IN",
node->time_stamp);
}
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);
#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 %lu\n",
NIPQUAD(node->sip),NIPQUAD(node->dip),
node->arpop==ARPOP_REQUEST?"ARPOP_REQUEST ":"ARPOP_REPLY",
node->type==ARP_OUT?"OUT":"IN",
node->time_stamp);
}
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);