#include <linux/init.h> #include <linux/module.h> #include <linux/version.h> #include <linux/skbuff.h> #include <linux/kernel.h> #include <linux/errno.h> #include <net/sock.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/netlink.h> #define MAX_PAYLOAD 1024 struct sock *nl_sk = NULL; u32 pid = 0; void nl_data_ready (struct sk_buff *skb) { struct sk_buff *skb2 = NULL; printk("input()called\n"); struct nlmsghdr *nlh = NULL; nlh = (struct nlmsghdr *)skb->data; printk("%s: received netlink message payload:%s\n", __FUNCTION__, NLMSG_DATA(nlh)); pid = nlh->nlmsg_pid; printk("pid = %d\n",pid); if(pid !=0){ skb2 = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL); printk("skb allocated\n"); nlh = (struct nlmsghdr *)skb2->data; nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = 0; nlh->nlmsg_flags = 0; strcpy(NLMSG_DATA(nlh),"Greeting From Kernel!"); NETLINK_CB(skb2).pid = 0; NETLINK_CB(skb2).dst_group = 0; printk("ready to unicast\n"); if(netlink_unicast(nl_sk, skb2, pid, MSG_DONTWAIT)<0) printk("error unicast\n"); else printk("unicasted to pid:%u \n",pid); }//endif } void netlink_test(){ //struct net net1; nl_sk = netlink_kernel_create(&init_net,25,0, nl_data_ready,NULL,THIS_MODULE); if(nl_sk<0) printk("error create sock\n"); else printk("successful create socket\n"); } static int my_module_init(void){ printk(KERN_INFO "initializing Netlink Socket!\n"); netlink_test(); return 0; } static void netlink_clear(void) { sock_release(nl_sk->sk_socket); printk(KERN_INFO"GOod Bye!\n"); } module_init(my_module_init); module_exit(netlink_clear); |
#include <sys/socket.h> #include <linux/netlink.h> #include <iostream> //#include <sys/socket.h> #include <linux/types.h> //#include <linux/netlink.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> using namespace std; #define MAX_PAYLOAD 1024 /* maximum payload size*/ struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; struct msghdr msg; int main(){ std::cout<<("error bind")<<std::endl; int sock_fd = socket(PF_NETLINK, SOCK_RAW,25); if (sock_fd <0) std::cout<<("error create socket!")<<std::endl; memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); /* self pid */ src_addr.nl_groups = 0; /* not in mcast groups */ if (bind(sock_fd, (struct sockaddr*)&src_addr,sizeof(src_addr))<0) std::cout<<("error bind")<<std::endl; else std::cout<<("binded")<<std::endl; memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; /* For Linux Kernel */ dest_addr.nl_groups = 0; /* unicast */ nlh=(struct nlmsghdr *)malloc( NLMSG_SPACE(MAX_PAYLOAD)); /* Fill the netlink message header */ nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); /* self pid */ nlh->nlmsg_flags = 0; /* Fill in the netlink message payload */ strcpy((char *)NLMSG_DATA(nlh), "Hello you!"); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; printf("%d\n",iov.iov_len); msg.msg_name = (void *)&dest_addr; msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; if(sendmsg(sock_fd, &msg, 0) == -1){ std::cout<<("error send")<<errno<<std::endl; } else std::cout<<("sent")<<std::endl; memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); printf("nlh set to be %s\n",NLMSG_DATA(nlh)); int ret = recvmsg(sock_fd, &msg, 0); if( ret < 0) std::cout<<("error recv")<<errno<<std::endl; else std::cout<<("received")<<ret<<std::endl; printf("Received message payload:%s\n from kernel, length is %d\n",(char *)(NLMSG_DATA(nlh)),nlh->nlmsg_len); /* Close Netlink Socket */ close(sock_fd); } |
原帖由 duanjigang 于 2009-2-22 22:40 发表
参考一个入门的例子修改下。
参考此文:
http://bbs3.chinaunix.net/viewthread.php?tid=1274437
原帖由 overcloud 于 2009-2-23 02:49 发表
新的内核 netlink_kernel_create变成了下面的定义,谁知道struct net这里怎么用?
extern struct sock *netlink_kernel_create(struct net *net,
int unit,unsigned int groups,
void (*input)( ...
但是从kernel unicast出去的msg用户态还是一直收不到,
static int
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
unsigned int queuenum, void *data)
{
int status = -EINVAL;
struct sk_buff *nskb;
struct ipq_queue_entry *entry;
if (copy_mode == IPQ_COPY_NONE)
return -EAGAIN;
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL) {
printk(KERN_ERR "ip_queue: OOM in ipq_enqueue_packet()\n");
return -ENOMEM;
}
entry->info = info;
entry->skb = skb;
nskb = ipq_build_packet_message(entry, &status);
if (nskb == NULL)
goto err_out_free;
write_lock_bh(&queue_lock);
if (!peer_pid)
goto err_out_free_nskb;
if (queue_total >= queue_maxlen) {
queue_dropped++;
status = -ENOSPC;
if (net_ratelimit())
printk (KERN_WARNING "ip_queue: full at %d entries, "
"dropping packets(s). Dropped: %d\n", queue_total,
queue_dropped);
goto err_out_free_nskb;
}
/* netlink_unicast will either free the nskb or attach it to a socket */
status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
if (status < 0) {
queue_user_dropped++;
goto err_out_unlock;
}
__ipq_enqueue_entry(entry);
write_unlock_bh(&queue_lock);
return status;
err_out_free_nskb:
kfree_skb(nskb);
err_out_unlock:
write_unlock_bh(&queue_lock);
err_out_free:
kfree(entry);
return status;
}
原帖由 overcloud 于 2009-2-27 18:07 发表
恩,
这个我在userspace用getpid()获得了然后通过第一个从userspace发到kernel的消息里传给了内核
在内核代码里
pid = nlh->nlmsg_pid;
然后再用netlink_unicast的阿
原帖由 Godbach 于 2009-2-27 19:08 发表
在调用netlink_unicast函数的前后打印一些信息出来,看看那些报文走到了这个流程,并且成功的被netlink_unicast处理了。
原帖由 Godbach 于 2009-2-27 17:50 发表
ip_queue中向用户空间发送信息的函数:
其中红色那行代码就是实际的发送函数,这个函数里面peer_pid参数为用户空间发送消息是记录下来的,你比较一下是否是在内核接受用户消息时记录下来的。
原帖由 overcloud 于 2009-3-7 05:03 发表
我看ip_queue.c里面并没有设置NETLINK_CB(skb),所以我把那两行去掉了,直接netlink_unicast,这次好像收到了,但是马上就机器崩溃,好像close(sock)那里出问题了,或者别的地方...依然一头雾水
NLMSG_PUT( skb_d, 0 , 0, 0, MAX_PAYLOAD ); NETLINK_CB( skb_d ).pid = 0; nlh = nlmsg_hdr( skb_d ); memcpy( NLMSG_DATA( nlh ) , ptMsg , MAX_PAYLOAD ); rc = netlink_unicast( nl_sk , skb_d, pid, MSG_DONTWAIT ); |
原帖由 overcloud 于 2009-3-7 05:03 发表
我看ip_queue.c里面并没有设置NETLINK_CB(skb),所以我把那两行去掉了,直接netlink_unicast,这次好像收到了,但是马上就机器崩溃,好像close(sock)那里出问题了,或者别的地方...依然一头雾水
#define NLMSG_NEW(skb, pid, seq, type, len, flags) \ ({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) \ goto nlmsg_failure; \ __nlmsg_put(skb, pid, seq, type, len, flags); }) #define NLMSG_PUT(skb, pid, seq, type, len) \ NLMSG_NEW(skb, pid, seq, type, len, 0) |
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |