免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2350 | 回复: 4
打印 上一主题 下一主题

[内核模块] netfilter回调函数中进行日志文件读写出错 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-16 21:12 |只看该作者 |倒序浏览
最近在研究Linux下的防火墙,看了下《Linux网络编程》,书后面有一个静态包过滤防火墙的例子。我也照着源代码写了下,我的内核是2.6.32。在书中,netfilter的回调函数中调用了一个写日志的文件,基本结构向下面这个样子:
  1. /*进入本地数据的钩子处理函数*/
  2. static unsigned int
  3. SIPFW_HookLocalIn(unsigned int hook,
  4.         struct sk_buff *pskb,
  5.         const struct net_device *in,
  6.         const struct net_device *out,
  7.         int (*okfn)(struct sk_buff *))
  8. {
  9.         .........
  10.         if(found)/*有匹配规则*/
  11.                 SIPFW_LogAppend(skb, found);/*日志记录*/
  12.         ........
  13. }
复制代码
日志记录函数的读写文件的关键函数如下:
  1. f = filp_open(filename, flags, 0);        /*filp_open打开文件*/
  2. ........
  3. /*是否有文件操作函数*/
  4.         if (f->f_op && f->f_op->read && f->f_op->write)
  5.         {
  6.                 oldfs = get_fs();                        /*获得地址设置*/
  7.                 set_fs(KERNEL_DS);                /*设置为内核模式*/
  8.                 count = 0;
  9.                 count = f->f_op->write(f, buf, len, &f->f_pos) ;
  10.                 if (count == -1)                        /*写入数据失败*/
  11.                         goto out;
  12.         }
  13.         else                                                        /*没有操作函数*/
  14.                 goto out_error;

  15. out:
  16.         set_fs(oldfs);                                        /*回复原来的地址设置方式*/
  17. ...........
  18. 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的回调函数中写文件呢?而且,我希望防火墙的日志写文件应该是即时的。各位高手有什么好的方案么,跪求指教啊!!!!!!

论坛徽章:
0
2 [报告]
发表于 2013-05-17 09:56 |只看该作者
本帖最后由 飞机塞进菊花 于 2013-05-17 10:14 编辑

跟我遇到的问题一样  猜测:
回调函数是中断  文件io会产生休眠  可是中断中不能休眠

如果使用非阻塞io  的确不会死机  不过软中断很快会被吃满。。。

还有  你没有加锁

正头疼呢

论坛徽章:
0
3 [报告]
发表于 2013-05-17 10:02 |只看该作者
LZ是做网络服务器的吗

论坛徽章:
0
4 [报告]
发表于 2013-05-17 21:42 |只看该作者
回复 2# 飞机塞进菊花
不是,我只是研究防火墙的时候碰到这个问题了。您说我没有加锁,是写日志文件的时候吗?


   

论坛徽章:
0
5 [报告]
发表于 2013-05-18 10:16 |只看该作者
回复 4# tzyhpcom


    数据两不大的话用printk吧  或者写进proc吧 在乎在哦个debugfs也行  直接访问文件系统  又是io 又是中断很头痛的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP