- 论坛徽章:
- 0
|
最近在研究Linux下的防火墙,看了下《Linux网络编程》,书后面有一个静态包过滤防火墙的例子。我也照着源代码写了下,我的内核是2.6.32。在书中,netfilter的回调函数中调用了一个写日志的文件,基本结构向下面这个样子:- /*进入本地数据的钩子处理函数*/
- static unsigned int
- SIPFW_HookLocalIn(unsigned int hook,
- struct sk_buff *pskb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
- {
- .........
- if(found)/*有匹配规则*/
- SIPFW_LogAppend(skb, found);/*日志记录*/
- ........
- }
复制代码 日志记录函数的读写文件的关键函数如下:- f = filp_open(filename, flags, 0); /*filp_open打开文件*/
- ........
- /*是否有文件操作函数*/
- if (f->f_op && f->f_op->read && f->f_op->write)
- {
- oldfs = get_fs(); /*获得地址设置*/
- set_fs(KERNEL_DS); /*设置为内核模式*/
- count = 0;
- count = f->f_op->write(f, buf, len, &f->f_pos) ;
- if (count == -1) /*写入数据失败*/
- goto out;
- }
- else /*没有操作函数*/
- goto out_error;
- out:
- set_fs(oldfs); /*回复原来的地址设置方式*/
- ...........
- filp_close(f, current->files); /*关闭文件*/
复制代码 上面只是关于读写的比较关键的函数。当进入数据包和过滤规则符合时,关于这个数据包的源IP端口、目的IP端口等关键信息就被格式化成一条信息添加到日志文件。这个日志读写函数是在数据包流动比较少时是可以运行的,比如我禁止192.168.0.1的所有类型的数据包,当我从0.1来ping防火墙所在的主机,来3、4个包还可以,日志文件也可以写入,但是我连续ping,防火墙所在的linux主机就会内核崩溃。后来,我把打开日志文件的函数放在防火墙启动时,在卸载防火墙内核模块时关闭日志文件,日志读写函数中只进行写,这样内核貌似“性能”增强了,连续ping时内核不会崩溃,但是会出现如下错误:
javascript:;
而且时间一长或数据量一增大,内核还是要崩的。我在网上查了下,"Scheduling while atomic" indicates that you've tried to sleep somewhere that you shouldn't - like within a spinlock-protected critical section or an interrupt handler.是说我尝试在不该睡眠的位置睡眠,比如在自旋锁保护的位置或一个中断函数中。这就是说netfilter的回调函数是一个中断函数,而内核中写文件的函数是可以造成睡眠的吧?如果是这样的话,我如何在一个netfilter的回调函数中写文件呢?而且,我希望防火墙的日志写文件应该是即时的。各位高手有什么好的方案么,跪求指教啊!!!!!! |
|