参考资料:
https://blog.csdn.net/zqixiao_09/article/details/77131283
#include
#include
#include
#include
#include
#include
#include
#include
#define NETLINK_USER 22
#define USER_MSG (NETLINK_USER 1)
#define USER_PORT 50
MODULE_LICENSE("GPL");
MODULE_AUTHOR("arvik");
MODULE_DESCRIPTION("netlink_demo");
static void test_netlink_rcv(struct sk_buff *skb);
struct netlink_kernel_cfg cfg = {
.input = test_netlink_rcv,
/*...*/
};
static struct sock *test_netlink_sock = NULL;
int send_msg(int8_t *pbuf, uint16_t len)
{
struct sk_buff *nl_skb;
struct nlmsghdr *nlh;
int ret;
nl_skb = nlmsg_new(len, GFP_ATOMIC);
if (!nl_skb) {
printk("netlink_alloc_skb error\n");
return -1;
}
/*将header填充到skb中*/
nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);
if (nlh == NULL) {
printk("put error\n");
nlmsg_free(nl_skb);
return -1;
}
/*拷贝data*/
memcpy(nlmsg_data(nlh), pbuf, len);
/*发送*/
ret = netlink_unicast(test_netlink_sock, nl_skb, USER_PORT, MSG_DONTWAIT);
return ret;
}
static void test_netlink_rcv(struct sk_buff *skb)
{
struct nlmsghdr *nlh = NULL;
void *data = NULL;
printk("skb->len %u\n", skb->len);
if (skb->len >= nlmsg_total_size(0))
{
nlh = nlmsg_hdr(skb);
data = NLMSG_DATA(nlh);
if (data) {
printk("kernel receive date : %s\n", (int8_t *)data);
send_msg(data, nlmsg_len(nlh));
}
}
}
static int __init test_netlink_init(void)
{
printk("test netlink init\n");
test_netlink_sock = netlink_kernel_create(&init_net, USER_MSG, &cfg);
if (test_netlink_sock == NULL) {
printk("test netlink init error\n");
return -1;
}
printk("test netlink init ok\n");
return 0;
}
static void __exit test_netlink_exit(void)
{
netlink_kernel_release(test_netlink_sock);
test_netlink_sock = NULL;
printk("test netlink exit\n");
}
module_init(test_netlink_init);
module_exit(test_netlink_exit);
#include
#include
#include
#include
#include
#include
#include
#include
#define NETLINK_USER 22
#define USER_MSG (NETLINK_USER 1)
#define MSG_LEN 100
#define MAX_PLOAD 100
struct _my_msg {
struct nlmsghdr hdr;
int8_t data[MSG_LEN];
};
int main()
{
char *data = "hello kernel";
socklen_t addr_len;
struct sockaddr_nl local, dest_addr;
int skfd;
struct nlmsghdr *nlh = NULL;
struct _my_msg info;
int ret;
//创建socket
skfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);
if (skfd == (-1)) {
fprintf(stderr, "create socket error...%s\n", strerror(errno));
return (-1);
}
/*绑定*/
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = 50;
local.nl_groups = 0;
if (bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0) {
fprintf(stderr, "bind error\n");
close(skfd);
return (-1);
}
//初始化目的地址
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
/*填写data*/
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 = local.nl_pid;
memcpy(NLMSG_DATA(nlh), data, strlen(data));
ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl));
if (ret < 0) {
// fprintf(stderr, "sendto error\n");
perror("sendto error: ");
close(skfd);
return (-1);
}
printf("wait kernel msg!\n");
memset(&info, 0, sizeof(info));
/*接受信息*/
ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, &addr_len);
if (ret <= 0) {
// fprintf(stderr, "recv from kernel error\n");
perror("recv from kernel error: ");
close(skfd);
return (-1);
}
printf("msg receive from kernel : %s\n", info.data);
close(skfd);
free((void *)nlh);
close(skfd);
return 0;
}
来源:http://www.icode9.com/content-3-134001.html