Linux之netlink学习

来源:互联网 发布:冒险岛2韩服pk数据榜 编辑:程序博客网 时间:2024/05/16 05:37


//imp2.h#ifndef __IMP2_H__#define __IMP2_H__#define IMP2_U_PID   0#define IMP2_K_MSG   1#define IMP2_CLOSE   2#define NL_IMP2      31struct packet_info{  __u32 src;  __u32 dest;};#endif//内核态程序imp2_k_my.c#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include <linux/netfilter.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/types.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/netfilter_ipv4.h>#include <linux/inet.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/netlink.h>#include <linux/spinlock.h>#include <net/sock.h>#include "imp2.h"MODULE_LICENSE("Dual BSD/GPL");#define IMP2_K_MY "imp2_k_my:"//#define printk(arg) //printkk(KERN_ALERT IMP2_K_MY arg)DECLARE_MUTEX(receive_sem);static struct sock *mysock;struct{    __u32 pid;    rwlock_t lock;} user_proc;static int send_to_user(struct packet_info *info){    int ret = 0;    int size;    //unsigned char *old_tail;    sk_buff_data_t old_tail;    struct sk_buff *skb;    struct nlmsghdr *nlh;    struct packet_info *packet;    printk("%s, begin !!! \n", __func__);    size = NLMSG_SPACE(sizeof(*info));        skb = alloc_skb(size, GFP_ATOMIC);    old_tail = skb->tail;    nlh = NLMSG_PUT(skb, 0, 0, IMP2_K_MSG, size - sizeof(*nlh));    packet = NLMSG_DATA(nlh);    memset(packet, 0, sizeof(struct packet_info));    packet->src = info->src;    packet->dest = info->dest;    nlh->nlmsg_len = (__u32)(skb->tail - old_tail);        NETLINK_CB(skb).dst_group = 0;    read_lock_bh(&user_proc.lock);    ret = netlink_unicast(mysock, skb, user_proc.pid, MSG_DONTWAIT);    read_unlock_bh(&user_proc.lock);        printk("%s, end !!! \n", __func__);    return ret;    nlmsg_failure:     if(skb)        kfree_skb(skb);    return -1;}static unsigned int icmp_hook_func(unsigned int hooknum,             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;    //printk("%s, begin !!! \n", __func__);    if (iph->protocol == IPPROTO_ICMP) {        read_lock_bh(&user_proc.lock);                if (user_proc.pid != 0) {            info.src = iph->saddr;            info.dest = iph->daddr;            printk("%s, src=%u.%u.%u.%u, dst=%u.%u.%u.%u\n", __func__,                NIPQUAD(info.src), NIPQUAD(info.dest));            send_to_user(&info);        } else {            printk("%s, no user process running..!\n", __func__);        }                read_unlock_bh(&user_proc.lock);    }     //printk("%s, end !!! \n", __func__);        return NF_ACCEPT;}#define NF_IP_PRE_ROUTING    0static struct nf_hook_ops my_icmp_hook = {    .hook = icmp_hook_func,    .pf = PF_INET,    .hooknum = NF_IP_PRE_ROUTING,    .owner = THIS_MODULE,    .priority = NF_IP_PRI_FILTER - 1,};static void my_receive(struct sk_buff *skb){    struct nlmsghdr *nlh;    int len;        printk("%s, begin !!!!!\n", __func__);    nlh = nlmsg_hdr(skb);    len = skb->len;    while (NLMSG_OK(nlh, len)) {        printk("%s, skb_len = %d!!!!!\n", __func__, len);        if (nlh->nlmsg_type == IMP2_U_PID) {        write_lock_bh(&user_proc.lock);            user_proc.pid = nlh->nlmsg_pid;        write_unlock_bh(&user_proc.lock);        } else if (nlh->nlmsg_type == IMP2_CLOSE)        {        write_lock_bh(&user_proc.lock);    if(nlh->nlmsg_pid == user_proc.pid)            user_proc.pid = 0;        write_unlock_bh(&user_proc.lock);        }                 netlink_ack(skb, nlh, 0);        nlh = NLMSG_NEXT(nlh, len);    }       printk("%s, end !!!!!\n", __func__);}static int __init imp2_k_my_init(void){    printk("%s, begin !!!!!\n", __func__);        rwlock_init(&user_proc.lock);        mysock = netlink_kernel_create(&init_net, NL_IMP2, 0, my_receive,        NULL, THIS_MODULE);    if (!mysock) {        printk("%s, netlink_kernel_create fail.. !!!!!\n", __func__);        return -1;    }         printk("%s, end !!!!!\n", __func__);    return nf_register_hook(&my_icmp_hook);}static void __exit imp2_k_my_exit(void){    printk("%s, begin !!!!!\n", __func__);    netlink_kernel_release(mysock);    nf_unregister_hook(&my_icmp_hook);    printk("%s, end !!!!!\n", __func__);}module_init(imp2_k_my_init);module_exit(imp2_k_my_exit); //用户态程序imp2_u_my.c#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <error.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 "imp2.h"struct msg_to_kernel{    struct nlmsghdr hdr;};struct u_packet_info{  struct nlmsghdr hdr;  struct packet_info icmp_info;};static int skfd;static void sig_int(int signo){    struct sockaddr_nl kpeer;    struct msg_to_kernel message;    memset(&kpeer, 0, sizeof(kpeer));    kpeer.nl_family = AF_NETLINK;    kpeer.nl_pid = 0;    kpeer.nl_groups = 0;    memset(&message, 0, sizeof(message));    message.hdr.nlmsg_len = NLMSG_LENGTH(0);    message.hdr.nlmsg_flags = 0;    message.hdr.nlmsg_type = IMP2_CLOSE;    message.hdr.nlmsg_pid = getpid();    sendto(skfd, &message, message.hdr.nlmsg_len, 0, (struct sockaddr *)(&kpeer),         sizeof(kpeer));    close(skfd);    exit(0);}int main(void){    struct sockaddr_nl local;    struct sockaddr_nl kpeer;    int kpeerlen;    struct msg_to_kernel message;    struct u_packet_info info;    int sendlen = 0;    int rcvlen = 0;    struct in_addr addr;    skfd = socket(PF_NETLINK, SOCK_RAW, NL_IMP2);    if(skfd < 0) {        printf("can not create a netlink socket\n");        exit(0);    }    memset(&local, 0, sizeof(local));    local.nl_family = AF_NETLINK;    local.nl_pid = getpid();    local.nl_groups = 0;    if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0) {        printf("bind() error\n");        return -1;    }    signal(SIGINT, sig_int);    memset(&kpeer, 0, sizeof(kpeer));    kpeer.nl_family = AF_NETLINK;    kpeer.nl_pid = 0;    kpeer.nl_groups = 0;    memset(&message, 0, sizeof(message));    message.hdr.nlmsg_len = NLMSG_LENGTH(0);    message.hdr.nlmsg_flags = 0;    message.hdr.nlmsg_type = IMP2_U_PID;    message.hdr.nlmsg_pid = local.nl_pid;    sendto(skfd, &message, message.hdr.nlmsg_len, 0,        (struct sockaddr*)&kpeer, sizeof(kpeer));    while(1) {        kpeerlen = sizeof(struct sockaddr_nl);        rcvlen = recvfrom(skfd, &info, sizeof(struct u_packet_info),        0, (struct sockaddr*)&kpeer, &kpeerlen);        addr.s_addr = info.icmp_info.src;        printf("src: %s, ", inet_ntoa(addr));        addr.s_addr = info.icmp_info.dest;        printf("dest: %s\n", inet_ntoa(addr));    }    return 0;}




0 0
原创粉丝点击