用户态程序
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <sys/socket.h>
-
#include <string.h>
-
#include <linux/netlink.h>
-
#include <stdint.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
-
-
#define NETLINK_TEST 30
-
#define MSG_LEN 100
-
#define MAX_PLOAD 100
-
#define USER_PORT 66
-
typedef struct _user_msg_info
-
{
-
struct nlmsghdr hdr;
-
char msg[MSG_LEN];
-
} user_msg_info;
-
-
int main(int argc,char **argv)
-
{
-
int sockfd;
-
struct sockaddr_nl saddr, daddr;
-
struct nlmsghdr *nlh;
-
user_msg_info u_info;
-
char *msg = "hello kernel, I am user process!";
-
socklen_t len;
-
-
//创建socket SOCK_RAW|SOCK_NONBLOCK
-
sockfd = socket(AF_NETLINK,SOCK_RAW, NETLINK_TEST);
-
-
//初始化目的地址
-
memset(&daddr, 0, sizeof(daddr));
-
daddr.nl_family = AF_NETLINK;
-
daddr.nl_pid = 0; // to kernel
-
daddr.nl_groups = 0;
-
-
//初始化消息头
-
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));
-
memset(nlh, 0, sizeof(struct nlmsghdr));
-
nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);
-
nlh->nlmsg_flags = 0;
-
nlh->nlmsg_type = 0;
-
nlh->nlmsg_seq = 0;
-
//nlh->nlmsg_pid = USER_PORT; //self port
-
nlh->nlmsg_pid = getpid();//我们希望得到内核回应,所以得告诉内核我们ID号
-
-
//设置消息内容
-
memcpy(NLMSG_DATA(nlh),msg,strlen(msg));
-
-
do
-
{
-
//发送消息
-
int ret = sendto(sockfd,nlh,nlh->nlmsg_len,0,(struct sockaddr *)&daddr,sizeof(struct sockaddr_nl));
-
if(ret < 0){
-
printf("sendto error, errno:%d \n", errno);
-
break;
-
}
-
printf("send to kernel :%s ret:%d nlmsg_len:%d \n",msg,ret, nlh->nlmsg_len);
-
-
memset(&u_info, 0, sizeof(u_info));
-
len = sizeof(struct sockaddr_nl);
-
//接收消息
-
ret = recvfrom(sockfd,&u_info,sizeof(user_msg_info),0,(struct sockaddr *)&daddr,&len);
-
if(ret < 0){
-
printf("recvfrom error, errno:%d \n",errno);
-
break;
-
}
-
-
printf("recv from kernel:%s ret:%d\n",u_info.msg,ret);
-
}while(0);
-
-
free(nlh);
-
close(sockfd);
-
return 0;
-
}
编译命令:
Gcc -o netlink_user netlink_user.c
内核态程序
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/types.h>
-
#include <net/sock.h>
-
#include <linux/netlink.h>
-
-
#define NETLINK_TEST 30
-
#define MSG_LEN 100
-
#define USER_PORT 66
-
-
struct sock *nlsk;
-
-
extern struct net init_net;
-
-
int send_usrmsg(char *pbuf, uint16_t len, int pid)
-
{
-
struct sk_buff *nl_skb;
-
struct nlmsghdr *nlh; //消息头部
-
-
int ret;
-
//创建sk_buff
-
nl_skb = nlmsg_new(len, GFP_ATOMIC);
-
if(!nl_skb)
-
{
-
printk("netlink alloc failure\n");
-
return -1;
-
}
-
-
/* 设置netlink消息头部 */
-
nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0);
-
if(nlh == NULL)
-
{
-
printk("nlmsg_put failaure \n");
-
nlmsg_free(nl_skb);
-
return -1;
-
}
-
-
/* 拷贝数据发送 */
-
memcpy(nlmsg_data(nlh), pbuf, len);
-
ret = netlink_unicast(nlsk, nl_skb, pid, 0); //阻塞模式
-
//ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT);
-
return ret;
-
}
-
-
static void netlink_rcv_msg(struct sk_buff *skb)
-
{
-
struct nlmsghdr *nlh;
-
char *umsg = NULL;
-
char *kmsg = "hello users";
-
//从skb中获取data字段,并转换成nlh进行读取
-
nlh = nlmsg_hdr(skb);
-
//读取nlh后面的数据部分
-
umsg = NLMSG_DATA(nlh);
-
if(umsg){
-
printk("kernel recv from user: %s\n", umsg);
-
printk("port id :%d\n",NETLINK_CB(skb).portid);
-
send_usrmsg(kmsg, strlen(kmsg), nlh->nlmsg_pid); //给用户态发消息
-
}
-
-
}
-
struct netlink_kernel_cfg cfg = {
-
.input = netlink_rcv_msg,
-
};
-
-
static int __init test_netlink_init(void)
-
{
-
nlsk = (struct sock *)netlink_kernel_create(&init_net,NETLINK_TEST,&cfg);
-
return 0;
-
}
-
-
static void __exit test_netlink_exit(void)
-
{
-
// 注销netlink协议
-
if(nlsk)
-
{
-
netlink_kernel_release(nlsk);
-
nlsk = NULL;
-
}
-
printk("exit......\n");
-
}
-
MODULE_LICENSE("GPL");
-
module_init(test_netlink_init);
-
module_exit(test_netlink_exit);
makefile 文件:
obj-m:=netlink_kernel.o
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/kernels/$(LINUX_KERNEL)
#linux-headers-
all:
make
-C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make
-C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
阅读(268) | 评论(0) | 转发(0) |