Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4823546
  • 博文数量: 930
  • 博客积分: 12070
  • 博客等级: 上将
  • 技术积分: 11448
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-15 16:57
文章分类

全部博文(930)

文章存档

2011年(60)

2010年(220)

2009年(371)

2008年(279)

分类: LINUX

2010-01-23 15:03:37

   今天无事,写了个内核态的ARP记录,通过/proc/读就可以了cat /proc/o_arp
 

#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);


阅读(3316) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~