netfilter提供了nf_register_sockopt()和nf_unregister_sockopt()来动态登记或取消sockopt命令字;打开一个网络socket后可以使用set/getsockopt(2)可实现用户空间与内核的通信,本质和ioctl差不多,区别在于set/getsockopt不用新建设备,直接利用系统已有的socket类型就可以进行,可用setsockopt函数向内核写数据,用getsockopt向内核读数据。module.c:#include
#include#include#include#include#include#include#defineSOCKET_OPS_BASE128#defineSOCKET_OPS_SET(SOCKET_OPS_BASE)#defineSOCKET_OPS_GET(SOCKET_OPS_BASE)#defineSOCKET_OPS_MAX(SOCKET_OPS_BASE+1)#defineKMSG"amessagefromkernel"#defineKMSG_LENsizeof("amessagefromkernel")MODULE_LICENSE("GPL");staticintrecv_msg(structsock*sk,intcmd,void__user*user,unsignedintlen){intret=0;printk(KERN_INFO"sockopt:recv_msg()\n");if(cmd==SOCKET_OPS_SET){charumsg[64];intlen=sizeof(char)*64;memset(umsg,0,len);ret=copy_from_user(umsg,user,len);printk("recv_msg:umsg=%s.ret=%d\n",umsg,ret);}return0;}staticintsend_msg(structsock*sk,intcmd,void__user*user,int*len){intret=0;printk(KERN_INFO"sockopt:send_msg()\n");if(cmd==SOCKET_OPS_GET){ret=copy_to_user(user,KMSG,KMSG_LEN);printk("send_msg:umsg=%s.ret=%d.success\n",KMSG,ret);}return0;}staticstructnf_sockopt_opstest_sockops={.pf=PF_INET,.set_optmin=SOCKET_OPS_SET,.set_optmax=SOCKET_OPS_MAX,.set=recv_msg,.get_optmin=SOCKET_OPS_GET,.get_optmax=SOCKET_OPS_MAX,.get=send_msg,.owner=THIS_MODULE,};staticint__initinit_sockopt(void){printk(KERN_INFO"sockopt:init_sockopt()\n");returnnf_register_sockopt(&test_sockops);}staticvoid__exitfini_sockopt(void){printk(KERN_INFO"sockopt:fini_sockopt()\n");nf_unregister_sockopt(&test_sockops);}module_init(init_sockopt);module_exit(fini_sockopt);user.c:#include#include#include#include#include#include#defineSOCKET_OPS_BASE128#defineSOCKET_OPS_SET(SOCKET_OPS_BASE)#defineSOCKET_OPS_GET(SOCKET_OPS_BASE)#defineSOCKET_OPS_MAX(SOCKET_OPS_BASE+1)#defineUMSG"amessagefromuserspace"#defineUMSG_LENsizeof("amessagefromuserspace")charkmsg[64];intmain(void){intsockfd;intlen;intret;sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_RAW);if(sockfd<0){printf("cannotcreateasocket\n");return-1;}/*callfunctionrecv_msg()*/ret=setsockopt(sockfd,IPPROTO_IP,SOCKET_OPS_SET,UMSG,UMSG_LEN);printf("setsockopt:ret=%d.msg=%s\n",ret,UMSG);len=sizeof(char)*64;/*callfunctionsend_msg()*/ret=getsockopt(sockfd,IPPROTO_IP,SOCKET_OPS_GET,kmsg,&len);printf("getsockopt:ret=%d.msg=%s\n",ret,kmsg);if(ret!=0){printf("getsockopterror:errno=%d,errstr=%s\n",errno,strerror(errno));}close(sockfd);return0;}Makefile:TARGET=testOBJS=test.oMDIR=drivers/miscEXTRA_CFLAGS=-DEXPORT_SYMTABCURRENT=$(shelluname-r)KDIR=/lib/modules/$(CURRENT)/buildPWD=$(shellpwd)DEST=/lib/modules/$(CURRENT)/kernel/$(MDIR)obj-m:=$(TARGET).o$(TARGET)-objs:=module.odefault:make-C$(KDIR)SUBDIRS=$(PWD)modulesgcc-ouseruser.c$(TARGET).o:$(OBJS)$(LD)$(LD_RFLAG)-r-o$@$(OBJS)ifneq(,$(findstring2.4.,$(CURRENT)))install:su-c"cp-v$(TARGET).o$(DEST)&&/sbin/depmod-a"elseinstall:su-c"cp-v$(TARGET).ko$(DEST)&&/sbin/depmod-a"endifclean:-rm-rf*.o*.ko.$(TARGET).ko.cmd.*.flags*.mod.cmodules.orderModule.symvers.tmp_versions-rm-rfprotocol/*.oprotocol/.*.o.cmd-rm-rfuser-include$(KDIR)/Rules.make