netlink实例

荒凉一梦 提交于 2020-02-17 01:38:49

#include <linux/module.h>  
#include <linux/netlink.h>  
#include <net/netlink.h>  
#include <net/net_namespace.h>  
#define NETLINK_TEST 31  
  
#define NLMSG_SETECHO 0x11  
#define NLMSG_GETECHO 0x12  
  
static struct sock *sk; //内核端socket  
static void nl_custom_data_ready(struct sk_buff *skb); //接收消息回调函数  
  
int __init nl_custom_init(void)  
{  
    struct netlink_kernel_cfg nlcfg = {  
        .input = nl_custom_data_ready,  
    };  
    sk = netlink_kernel_create(&init_net, NETLINK_TEST, &nlcfg);  
    printk(KERN_INFO "initialed ok!\n");  
    if (!sk) {  
        printk(KERN_INFO "netlink create error!\n");  
    }  
    return 0;  
}  
void __exit nl_custom_exit(void)  
{  
    printk(KERN_INFO "existing...\n");  
    netlink_kernel_release(sk);  
}  
  
static void nl_custom_data_ready(struct sk_buff *skb)  
{  
    struct nlmsghdr *nlh;  
    void *payload;  
    struct sk_buff *out_skb;  
    void *out_payload;  
    struct nlmsghdr *out_nlh;  
    int payload_len; // with padding, but ok for echo   
    nlh = nlmsg_hdr(skb);  
    switch(nlh->nlmsg_type)  
    {  
        case NLMSG_SETECHO:  
            break;  
        case NLMSG_GETECHO:  
            payload = nlmsg_data(nlh);  
            payload_len = nlmsg_len(nlh);  
            printk(KERN_INFO "payload_len = %d\n", payload_len);  
            printk(KERN_INFO "Recievid: %s, From: %d\n", (char *)payload, nlh->nlmsg_pid);  
            out_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); //分配足以存放默认大小的sk_buff  
            if (!out_skb) goto failure;  
            out_nlh = nlmsg_put(out_skb, 0, 0, NLMSG_SETECHO, payload_len, 0); //填充协议头数据  
            if (!out_nlh) goto failure;  
            out_payload = nlmsg_data(out_nlh);  
            strcpy(out_payload, "[from kernel]:"); // 在响应中加入字符串,以示区别  
            strcat(out_payload, payload);  
            nlmsg_unicast(sk, out_skb, nlh->nlmsg_pid);  
            break;  
        default:  
            printk(KERN_INFO "Unknow msgtype recieved!\n");  
    }  
    return;  
failure:  
    printk(KERN_INFO " failed in fun dataready!\n");  
}  
module_init(nl_custom_init);  
module_exit(nl_custom_exit);  
  
MODULE_LICENSE("GPL");  
MODULE_DESCRIPTION("a simple example for custom netlink protocal family");  
MODULE_AUTHOR("RSLjdkt"); 

 

 

用户

#include <stdlib.h>  
#include <stdio.h>  
#include <unistd.h>  
#include <linux/netlink.h>  
#include <sys/socket.h>  
#include <strings.h>  
#include <string.h>  
#define NETLINK_TEST 31 // 自定义的协议号  
/** 消息类型 **/  
#define NLMSG_SETECHO 0x11  
#define NLMSG_GETECHO 0x12  
/** 最大协议负荷(固定) **/  
#define MAX_PAYLOAD 101  
  
struct sockaddr_nl src_addr, dst_addr;  
struct iovec iov;  
int sockfd;  
struct nlmsghdr *nlh = NULL;  
struct msghdr msg;  
  
int main( int argc, char **argv)  
{  
    if (argc != 2) {  
        printf("usage: ./a.out <str>\n");  
        exit(-1);  
    }  
  
    sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_TEST); // 创建NETLINK_TEST协议的socket  
    /* 设置本地端点并绑定,用于侦听 */  
    bzero(&src_addr, sizeof(src_addr));  
    src_addr.nl_family = AF_NETLINK;  
    src_addr.nl_pid = getpid();  
    src_addr.nl_groups = 0; //未加入多播组  
    bind(sockfd, (struct sockaddr*)&src_addr, sizeof(src_addr));  
    /* 构造目的端点,用于发送 */  
    bzero(&dst_addr, sizeof(dst_addr));  
    dst_addr.nl_family = AF_NETLINK;  
    dst_addr.nl_pid = 0; // 表示内核  
    dst_addr.nl_groups = 0; //未指定接收多播组   
    /* 构造发送消息 */  
    nlh = (struct nlmsghdr *) malloc(NLMSG_SPACE(MAX_PAYLOAD));  
    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); //保证对齐  
    nlh->nlmsg_pid = getpid();  /* self pid */  
    nlh->nlmsg_flags = 0;  
    nlh->nlmsg_type = NLMSG_GETECHO;  
    strcpy((char *)NLMSG_DATA(nlh), argv[1]);  
    iov.iov_base = (void *)nlh;  
    iov.iov_len = nlh->nlmsg_len;  
    msg.msg_name = (void *)&dst_addr;  
    msg.msg_namelen = sizeof(dst_addr);  
    msg.msg_iov = &iov;  
    msg.msg_iovlen = 1;  
  
    sendmsg(sockfd, &msg, 0); // 发送  
    /* 接收消息并打印 */  
    memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));  
    recvmsg(sockfd, &msg, 0);  
    printf(" Received message payload: %s\n",  
           (char *) NLMSG_DATA(nlh));  
      printf(" Received message payload: %s %lx %lx\n",  
          (char *) NLMSG_DATA(nlh) ,msg.msg_iov->iov_len
          ,(unsigned long)((struct nlmsghdr *)msg.msg_iov->iov_base)->nlmsg_len); 
}
 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!