カーネルからユーザ空間にnetlinkブロードキャスト
iptablesのULOGを調べててカーネル空間にnetlinkにブロードキャストを送る方法が気になったので書いてみた
カーネル空間のプログラム
#include <linux/socket.h> #include <net/sock.h> static struct timer_list my_timer; static struct sock *sock; static int seq; MODULE_LICENSE("GPL"); void my_timer_callback( unsigned long data ) { char word[] = "hello world!"; struct sk_buff *skb; int type = 0; struct nlmsghdr *nlh; char *d; int ret; printk("timeout\n"); mod_timer(&my_timer, jiffies + msecs_to_jiffies(200)); skb = alloc_skb(1024, GFP_ATOMIC); if ( !skb ) { printk("error: skb alloc\n"); return; } nlh = NLMSG_PUT(skb, 0, ++seq, type, strlen(word)); d = NLMSG_DATA(nlh); memcpy(d, word, strlen(word)); ret = netlink_broadcast(sock, skb, 0, 5, GFP_ATOMIC); return; nlmsg_failure: printk("error:NLMSG_PUT\n"); return; } int myrtnl_init(void) { sock = netlink_kernel_create(&init_net, 20, 32, NULL, NULL, THIS_MODULE); if ( !sock ) { printk("error: netlink kernel create\n"); return 1; } setup_timer(&my_timer, my_timer_callback, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(200)); return 0; } void myrtnl_exit(void) { del_timer(&my_timer); netlink_kernel_release(sock); } module_init(myrtnl_init); module_exit(myrtnl_exit);
200ミリ秒ごとにNETLINKにブロードキャストを送るプログラム
cat /proc/net/netlink で空いてるをとりあえず使ってみた。(ルールは今度ちゃんと調べる)
netlink_broadcastにsk_buffを渡せば作れる。
NLMSG_PUTというショートカットメソッドも用意されている。
ユーザ空間のプログラム
#include <stdio.h> #include <libnetlink.h> #include <stdlib.h> #include <string.h> int listen_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg) { char buf[256] = {0}; memcpy(buf, NLMSG_DATA(n), 12); printf("data: %s\n", buf); return 0; } void main() { struct rtnl_handle rh; int n = 5; if ( rtnl_open_byproto(&rh, 1 << (n - 1), 20) != 0 ) { perror("open error\n"); exit(1); } printf("listen start\n"); rtnl_listen(&rh, listen_handler, NULL); }
libnetlinkを使った受信
ユーザ空間のグループ指定はビットシフトになるので注意
出力結果
[root@localhost rtnetlink]# ./a.out listen start data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world! data: hello world!