Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5976
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-08 19:48
文章分类
文章存档

2013年(1)

我的朋友

分类: LINUX

2013-07-08 19:57:19

原文地址:netlink实例 作者:peking_A_Liang

内核版本 2.6.30
 
用户空间源程序
/*
 *      netlink_user.c
 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "netlink.h"
struct msg_to_kernel
{
    struct nlmsghdr hdr;
};
struct u_packet_info
{
    struct nlmsghdr hdr;
    struct packet_info icmp_info;
};
static int sock_fd = -1;
 
int main()
{
    struct sockaddr_nl local; //local {user space}
    struct sockaddr_nl kpeer; //peer {kernel space}
    struct msg_to_kernel message;
    struct u_packet_info info;
    int k_peer_len,rcv_len;
    struct in_addr addr;

    //create netlink socket
    sock_fd = socket(AF_NETLINK,SOCK_RAW,NETLINK_TEST);
    if(!sock_fd)
    {
        perror("create netlink socket error\n");
        return -1;
    }
    memset(&local,0,sizeof(local));
    local.nl_family = AF_NETLINK;
    local.nl_pid = getpid();
    local.nl_groups = 0;
    if(bind(sock_fd,(struct sockaddr *)&local,sizeof(local)) != 0)
    {
        perror("bind error\n");
        return -1;
    }
 
    memset(&kpeer,0,sizeof(kpeer));
    kpeer.nl_family = AF_NETLINK;
    kpeer.nl_pid = 0;
    kpeer.nl_groups = 0; //not in multicast
 
    memset(&message,0,sizeof(message));
    message.hdr.nlmsg_len = NLMSG_LENGTH(0);
    message.hdr.nlmsg_flags = 0;
    message.hdr.nlmsg_type = NETLINK_TEST_U_PID;
    message.hdr.nlmsg_pid = local.nl_pid;
 
    //send to kernel
    sendto(sock_fd,&message,message.hdr.nlmsg_len,0,(struct sockaddr *)  &kpeer,sizeof(kpeer));
    while(1)
    {
        k_peer_len = sizeof(struct sockaddr_nl);
        rcv_len = recvfrom(sock_fd,&info,sizeof(struct u_packet_info),0,(struct sockaddr *)&kpeer,(socklen_t *)&k_peer_len);
        addr.s_addr = info.icmp_info.src;
        printf("src: %s,",inet_ntoa(addr));
        addr.s_addr = info.icmp_info.dest;
        printf("dst: %s\n",inet_ntoa(addr));
    }
    return 0;
 
内核空间源程序
/*
 * netlink_kernel.c
 */

#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "netlink.h"

static struct sock  *nl_sock = NULL;
static struct
{
    __u32 pid;
    rwlock_t lock;
}user_proc;
static DEFINE_MUTEX(nl_mutex);
static void netlink_kernel_rcv(struct sk_buff *skb)
{
    struct nlmsghdr *nlh = NULL;
    if(skb->len >= nlmsg_total_size(0)){ //sizeof(struct nlmsghdr)
        nlh = nlmsg_hdr(skb);
        if( (nlh->nlmsg_len >= sizeof(struct nlmsghdr))
            && (skb->len >= nlh->nlmsg_len)){
            if(nlh->nlmsg_type == NETLINK_TEST_U_PID){
                write_lock_bh(&user_proc.lock);
                user_proc.pid = nlh->nlmsg_pid; //record pid
                printk("NETLINK_TEST_U_PID: user_proc.pid = %d\n",user_proc.pid);
                write_unlock_bh(&user_proc.lock);
            }
         }
    }
 }
static int send_to_user(struct packet_info *info)
{
    int size,ret;
    unsigned char *old_tail;
    struct sk_buff *skb;
    struct nlmsghdr *nlh;
    struct packet_info *pk_info;
    size = NLMSG_SPACE(sizeof(*info));
    skb = alloc_skb(size,GFP_ATOMIC);
    if(!skb){
        printk("alloc skb failed\n");
        return -1;
    }
    old_tail = skb->tail;
    nlh = NLMSG_PUT(skb,0,0,NETLINK_TEST_K_MSG,size - sizeof(*nlh));
    pk_info = NLMSG_DATA(nlh);
    memset(pk_info,0,sizeof(struct packet_info));
    pk_info->src = info->src;
    pk_info->dest = info->dest;
    nlh->nlmsg_len = skb->tail - old_tail;
    NETLINK_CB(skb).pid = 0;
    NETLINK_CB(skb).dst_group = 0;
    read_lock_bh(&user_proc.lock);
    ret = netlink_unicast(nl_sock,skb,user_proc.pid,MSG_DONTWAIT);
    read_unlock_bh(&user_proc.lock);
nlmsg_failure:
    return ret;
}
static unsigned int get_icmp_info(unsigned int hook,
                                  struct sk_buff *skb,
                                  const struct net_device *in,
                                  const struct net_device *out,
                                  int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph = ip_hdr(skb);
    struct packet_info info;
    if(iph->protocol == IPPROTO_ICMP)
    {
        read_lock_bh(&user_proc.lock);
        if(user_proc.pid != 0)
        {
            read_unlock_bh(&user_proc.lock);
            info.src = iph->saddr;
            info.dest = iph->daddr;
            send_to_user(&info);
        }
        else
        {
            read_unlock_bh(&user_proc.lock);
        }
    }
    return NF_ACCEPT;
}
static struct nf_hook_ops netlink_test_ops =
{
    .hook = get_icmp_info,
    .owner = THIS_MODULE,
    .pf = PF_INET,
    .hooknum = NF_INET_PRE_ROUTING,
    .priority = NF_IP_PRI_FILTER - 1,
};
static int netlink_kernel_init(void)
{
    rwlock_init(&user_proc.lock);
    nl_sock = netlink_kernel_create(&init_net,NETLINK_TEST,0,netlink_kernel_rcv,&nl_mutex,THIS_MODULE);
    if(!nl_sock){
        printk("create netlink kernel sock error\n");
        return -1;
    }
    printk("netlink_kernel_init()\n");
    return nf_register_hook(&netlink_test_ops);
}
static void netlink_kernel_exit(void)
{
    if(nl_sock){
        sock_release(nl_sock->sk_socket);
    }
    nf_unregister_hook(&netlink_test_ops);
    printk("netlink_kernel_exit()\n");
}
module_init(netlink_kernel_init);
module_exit(netlink_kernel_exit);
MODULE_LICENSE("GPL");
 
自定义头文件
/*
 * netlink.h
 */
#ifndef __NETLINK_H__
#define __NETLINK_H__
#define NETLINK_TEST_U_PID 0
#define NETLINK_TEST_K_MSG 1
#define NETLINK_TEST_CLOSE 2
#define NETLINK_TEST 31
struct packet_info
{
    __u32 src;
    __u32 dest;
};
#endif
 
Makefile
 
#!/usr/bin/make
CC=gcc
COMMON_FLAGS= -Wall -g -I/usr/include/ -I/usr/src/linux/include
 
#kernel module
MODULE_NAME=netlink_kernel
obj-m:= $(MODULE_NAME).o
KERNEL_DIR ?=/lib/modules/$(shell uname -r)/build/
PWD :=$(shell pwd)

#user-space app
SRC=netlink_user.c
NETLINK_USR=netlink_usr

all:
    $(CC) $(COMMON_FLAGS) -o $(NETLINK_USR) $(SRC)
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
.PHONY:clean
clean:
    rm -fr $(NETLINK_USR) *.o *.ko Module.* modules.* $(MODULE_NAME).mod.c
 
功能
内核在netfilter的prerouting点截获别的主机发来的icmp包,并记录下来,然后通过netlink socket反馈给用户程序,用户程序终端予以显示。
 
 
阅读(711) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~