天天看點

Netlink執行個體----使用者态核心态全包含

#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif

#include <linux/types.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/netdevice.h>

#include <linux/skbuff.h>

#include <linux/mutex.h>

#include <linux/netfilter_ipv4.h>

#include <linux/ip.h>

#include <net/netlink.h>

#include <linux/netlink.h>

#include <linux/spinlock.h>

#include <net/sock.h>

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

#include <unistd.h>

#include <stdio.h>

#include <linux/types.h>

#include <string.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <asm/types.h>

#include <linux/netlink.h>

#include <signal.h>

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

}

繼續閱讀