Use netlink to achieve user mode and kernel interaction
于运超
wuyaalan at gmail.com
Wed Jul 10 09:23:34 EDT 2013
Hi,
nowadays i am learning how to use netlink achieve user mode and kernel
interaction. and when i finsh it ,i found kernel can not get the data from
user mode.
next is my code. can you tell me why? thank u
user mode code:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
void myerr(const char * err_string,int line)
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}
#define MAX_PAYLOAD 2046
#define NETLINK_TEST 26
/*struct req {
struct nlmsghdr nlh;
char buf[MAX_PAYLOAD];
}*/
int main (int argc,char * argv[])
{
int fd;
struct sockaddr_nl saddr,daddr;
int sock_fd;
struct nlmsghdr *nlhdr = NULL;
struct iovec iov;
struct msghdr msg;
char text[MAX_PAYLOAD];
int ret;
if(argc < 2){
printf("Usage:%s textfile\n",argv[0]);
exit(1);
}
if(fd = (open(argv[1],O_RDWR|O_CREAT,S_IRWXU)) == -1){
myerr("open",__LINE__);
}else{
printf("file open success!\n");
}
sock_fd = socket( AF_NETLINK,SOCK_RAW,NETLINK_TEST);
if( sock_fd < 0 ){
myerr("sock_fd",__LINE__);
}
memset(&saddr,0,sizeof(saddr));
memset(&daddr,0,sizeof(daddr));
saddr.nl_family = AF_NETLINK;
saddr.nl_pid = getpid();
saddr.nl_groups = 0;
if(bind(sock_fd,(struct sockaddr * )&saddr,sizeof( saddr)))
{
myerr("bind",__LINE__);
}
daddr.nl_family = AF_NETLINK;
daddr.nl_pid = 0;
daddr.nl_groups = 0;
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
while(1){
if(read(fd,text,MAX_PAYLOAD) == -1){
myerr("read",__LINE__);
}
// while(read(fd,text,MAX_PAYLOAD)){
memcpy(NLMSG_DATA(nlhdr),text,strlen(text));
memset(&msg,0,sizeof(struct msghdr));
nlhdr->nlmsg_len = NLMSG_LENGTH(strlen(text));
nlhdr->nlmsg_pid = getpid();
nlhdr->nlmsg_flags = 0;
iov.iov_base = (void *)nlhdr;
iov.iov_len = nlhdr->nlmsg_len;
msg.msg_name = (void * )&daddr;
msg.msg_namelen = sizeof(daddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
ret = sendmsg(sock_fd,&msg,0);
if(ret == -1){
myerr("sendmsg",__LINE__);
}else{
printf("usr send message to kernel\n");
}
}
close(sock_fd);
}
kernel module:
#include <linux/module.h>
//#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <net/sock.h>
struct sock *nl_sk = NULL;
#define MAX_PAYLOAD 2046
#define NETLINK_TEST 26
void nl_data_handler(struct sk_buff *__skb)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
pid_t pid;
char str[2046];
// int len = NLMSG_SPACE(MAX_PAYLOAD);
int rc;
printk("start reading...\n");
skb = skb_get(__skb);
if(skb->len >= NLMSG_SPACE(0)) {
nlh = nlmsg_hdr(skb);
printk("recv:%s\n",(char *)NLMSG_DATA(nlh));
memcpy(str,NLMSG_DATA(nlh),sizeof(str));
pid = nlh->nlmsg_pid;
printk("pid is %d\n",pid);
kfree_skb(skb);
skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_ATOMIC);
if(!skb){
printk(KERN_ERR "allocate failed!\n");
return ;
}
nlh = nlmsg_put(skb,0,0,0,MAX_PAYLOAD,0);
NETLINK_CB(skb).pid = 0;
memcpy(NLMSG_DATA(nlh),str,sizeof(str));
printk("net_link: ready send message\n");
rc = netlink_unicast(nl_sk,skb,pid,MSG_DONTWAIT);
if(rc < 0){
printk("can`t unicast skb\n");
}
printk("send ok!\n");
}
}
static int __init net_init(void)
{
struct net init_net;
// struct sock *nl_sk = NULL;
printk("net creat start.....\n");
nl_sk =
netlink_kernel_create(&init_net,NETLINK_TEST,0,nl_data_handler,NULL,THIS_MODULE);
if(nl_sk == 0)
{
printk("create netlink faile!\n");
return -1;
}else{
printk("netlink create success!\n");
}
return 0;
}
static void __exit net_exit(void)
{
printk("lal\n");
sock_release(nl_sk->sk_socket);
printk("netlink over!\n");
}
module_init(net_init);
module_exit(net_exit);
MODULE_LICENSE("GPL");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20130710/491c303f/attachment.html
More information about the Kernelnewbies
mailing list