netfilter内核态与用户态通信之sockopt
用户态与内核态交互通信的方法不止一种,sockopt是比较方便的一个,写法也简单.
缺点就是使用 copy_from_user()/copy_to_user()完成内核和用户的通信, 效率其实不高, 多用在传递控制 选项 信息,不适合做大量的数据传输。
用户态函数:
- 发送:int setsockopt ( int sockfd, int proto, int cmd, void *data, int datelen);
- 接收:int getsockopt(int sockfd, int proto, int cmd, void *data, int datalen)
- 第一个参数是socket描述符;
- 第二个参数proto是sock协议,IP RAW的就用SOL_SOCKET/SOL_IP等,TCP/UDP socket的可用SOL_SOCKET/SOL_IP/SOL_TCP/SOL_UDP等,即高层的socket是都可以使用低层socket的命令字 的,IPPROTO_IP;
- 第三个参数cmd是操作命令字,由自己定义;
- 第四个参数是数据缓冲区起始位置指针,set操作时是将缓冲区数据写入内核,get的时候是将内核中的数 据读入该缓冲区;
- 第五个参数数据长度
内核态函数:
- 注册:nf_register_sockopt(struct nf_sockopt_ops *sockops)
- 解除:nf_unregister_sockopt(struct nf_sockopt_ops *sockops)
结构体 nf_sockopt_ops test_sockops
1 | struct nf_sockopt_ops { |
其中命令字不能和内核已有的重复,宜大不宜小。命令字很重要,是用来做标识符的。而且用户态和内核态要定义的相同,
系统调用如下:sockt==》sock_common_setsockopt==》sk->sk_prot->setsockopt==》ip_setsockopt(tcp为例)
==>do_ip_setsockopt
==> nf_setsockopt==>nf_sockopt
1 | int ip_setsockopt(struct sock *sk, int level, |
内核态的module.c
1 |
|
用户态的user.c
1 |
|
Makefile—-系统不同命令可能不同,fedora 12
1 | TARGET = socketopt |
运行的结果
1 | [root@root socket]# make //编译 |