I want to implements kernel communicate with user space,Here is my code:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stddef.h>
#define NETLINK_USER 16
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
void main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
printf("%d\n",sock_fd);
if (sock_fd < 0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
printf("%d\n",getpid());
.....
When I set NETLINK_USER = 17,18 or something else, then I exec this code :
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
it show sock_fd return -1, so it must set NETLINK_USER = 16, I want know why? And I have another question: Here is my kernel code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/string.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <stddef.h>
#define NETLINK_USER 16
struct sock *nl_sk = NULL;
void **sys_call_table;
asmlinkage int (*original_call_open) (const char*, int, int);
asmlinkage int (*original_call_read) (unsigned int, char*, int);
asmlinkage long (*sys_openat) (int, const char*, int, int);
asmlinkage long our_openat(int dfd, const char *filename, int flags, int mode){
printk("%s\n",filename);
return sys_openat(dfd,filename,flags,mode);
}
void hello_nl_recv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr *)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n", (char *)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0)
printk(KERN_INFO "Error while sending bak to user\n");
}
int init_module()
{
printk("Entering: %s\n", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
// printk("%s",nl_sk);
// nl_sk = netlink_kernel_create(NETLINK_USER, input);
if (!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[__NR_open] = original_call_open;
sys_call_table[__NR_read] = original_call_read;
sys_call_table[__NR_openat] = sys_openat;
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
//MODULE_LICENSE("GPL");
//module_init(init_module);
//module_exit(cleanup_module);
I found if I set NETLINK_USER = 16, when I insert kernel, the avd will stop running, but if I set NETLINK_USER = 31,28 or something else the avd will run normally,I want to know why it will like this? At last, I think the function hello_nl_recv_msg haven't exec, I don't know why.