NetLink Demo
Kernel
#include <linux/kernel.h>
#include <linux/module.h>
#include <net/net_namespace.h>
#include <linux/netlink.h>
#include <net/sock.h>
#define NETLINK_TEST 20
static struct sock *netlink_test_sk;
static void netlink_test_rcv(struct sk_buff *skb)
{
struct sk_buff *skb_in, *skb_out;
struct nlmsghdr *nlh;
char message[32] = {0};
int seq, pid;
unsigned int datalength;
skb_in = skb_get(skb);
if (skb_in->len >= nlmsg_total_size(0)) {
nlh = nlmsg_hdr(skb_in);
pid = nlh->nlmsg_pid;
seq = nlh->nlmsg_seq;
printk("message received from process %d: %s\n", pid, (char*)NLMSG_DATA(nlh));
sprintf(message, "哎~乖孙儿~ %d", pid);
datalength = strlen(message) + 1;
skb_out = nlmsg_new(NLMSG_LENGTH(datalength), GFP_KERNEL);
nlh = nlmsg_put(skb_out, pid, seq, 0, NLMSG_ALIGN(datalength), 0);
memcpy(nlmsg_data(nlh), message, datalength);
netlink_unicast(netlink_test_sk, skb_out, pid, MSG_DONTWAIT);
}
kfree_skb(skb_in);
}
int __init netlink_test_init(void)
{
struct netlink_kernel_cfg cfg = {
.groups = 0,
.input = netlink_test_rcv,
};
netlink_test_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);
if (!netlink_test_sk)
return -ENOMEM;
return 0;
}
void __exit netlink_test_exit(void)
{
netlink_kernel_release(netlink_test_sk);
}
module_init(netlink_test_init);
module_exit(netlink_test_exit);
MODULE_LICENSE("GPL");
User
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/netlink.h>
#include <unistd.h>
#define NETLINK_TEST 20
#define MSG_LEN 100
int main(int argc, char* argv[])
{
char *data = "爷爷,您孙子给你来消息啦";
struct sockaddr_nl local, dest;
int skfd, ret;
unsigned int datalength, addrlength;
struct nlmsghdr *msg_out, *msg_in;
skfd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
if(skfd < 0){
perror("create socket failed");
return 0;
}
memset(&local, 0, sizeof(struct sockaddr_nl));
local.nl_family = AF_NETLINK;
local.nl_pid = getpid();
local.nl_groups = 0;
if(bind(skfd, (struct sockaddr *)&local, sizeof(struct sockaddr_nl)) != 0){
perror("bind failed");
close(skfd);
return 0;
}
memset(&dest, 0, sizeof(struct sockaddr_nl));
dest.nl_family = AF_NETLINK;
dest.nl_pid = 0;
dest.nl_groups = 0;
datalength = strlen(data) + 1;
msg_out = (struct nlmsghdr*)malloc(NLMSG_SPACE(datalength));
memset(msg_out, 0, NLMSG_SPACE(datalength));
msg_out->nlmsg_len = NLMSG_SPACE(datalength);
msg_out->nlmsg_flags = 0;
msg_out->nlmsg_type = 0;
msg_out->nlmsg_seq = 0;
msg_out->nlmsg_pid = local.nl_pid;
memcpy(NLMSG_DATA(msg_out), data, strlen(data));
ret = sendto(skfd, msg_out, msg_out->nlmsg_len, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr_nl));
if(!ret){
perror("send failed");
free(msg_out);
close(skfd);
return 0;
}
free(msg_out);
msg_in = (struct nlmsghdr*)malloc(NLMSG_SPACE(MSG_LEN));
memset(msg_in, 0, NLMSG_SPACE(MSG_LEN));
addrlength = sizeof(struct sockaddr_nl);
ret = recvfrom(skfd, msg_in, NLMSG_SPACE(MSG_LEN), 0, (struct sockaddr*)&dest, &addrlength);
if(!ret){
perror("recv failed");
free(msg_in);
close(skfd);
return 0;
}
printf("message received from kernel: %s\n", (char*)NLMSG_DATA(msg_in));
free(msg_in);
close(skfd);
return 0;
}