QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1084|回复: 3

kernel 2.6.11.x + ipt_time 的问题

[复制链接]
发表于 2005-5-20 22:08:50 | 显示全部楼层 |阅读模式
正在学习netfilter,打算给机器加个ipt_time patch,我的操作步骤如下:

Kernel 2.6.11.10,patch-o-matic-20050519,iptables 1.3.1

Kernel source 放在 /usr/src/linux
Iptables source 放在 /usr/src/iptables

# cd /usr/src/linux
# make menuconfig  (生成了.config)
# tar -jxvf patch-o-matic-20050519.tar.bz2
# cd patch-o-matic-20050519
# export KERNEL_DIR=/usr/src/linux
# export IPTABLES_DIR=/usr/src/iptables
# ./runme time
# cd /usr/src/linux
# make menuconfig (加上TIME MATCH)
# make
# make modules_install
# cp arch/i386/boot/bzImage /boot/kernel-2.6.11.10-time
# cd /usr/src/iptables
# make KERNEL_DIR=/usr/src/linux
# make install

重新启动系统后可以看到:

ip_tables: (C) 2000-2002 Netfilter core team
ipt_time loading

登录进入系统清空所有iptables规则,然后执行:

iptables -A INPUT -p icmp -m time --timestart 14:20 --timestop 14:21 -j REJECT

测试1:这时在另外一台机器 ping 该机(ip为 192.168.0.123),当机器时间到达 14:20的时候依然可以ping通,一直到了14:23分还是一样。

似乎ipt_time没有起作用?

测试2:后来重新删除所有的linux kernel和iptables的源代码,重新下载解压,重新打上ipt_time的patch,同样的内核配置,再make,再用相同的测试,结果这次在 14:20分是ping不通了,一直到 14:22分才ping通,这时感觉ipt_time应该工作了。

测试3:正在为ipt_time工作了而高兴,重新启动了一下机器,这下奇怪的事情发生了,加上与上面一样的规则,再ping 192.168.0.123,这时的结果和“测试1”一样,ipt_time又不起作用了。

到底是怎么一回事呢?难道这么不稳定??而且后来测试了很多次(包括删除源代码重新编译),ipt_time在大部分测试中都没有起作用,只是偶尔一两次才起作用,真是郁闷,编译又没有报任何错,难道time不支持kernel-2.6.11 ??请大家赐教。
 楼主| 发表于 2005-5-20 23:59:47 | 显示全部楼层
终于找到原因了:
/usr/src/linux/net/ipv4/netfilter/ipt_time.c 中
[code:1]
long int tm_gmtoff;                  /* we don't care, we count from GMT */
const char *tm_zone;             /* we don't care, we count from GMT */
[/code:1]

原来是与timezone有关,看来这个patch还没有实现timezone的功能,它的所有计时都是从GMT开始的,而我的timezone是Asia/Chongqing 即 GMT+8

后来把timezone改成了GMT就可以了。

当然也可以把原来的规则改成GMT时间,即-8:

iptables -A INPUT -p icmp -m time --timestart 6:20 --timestop 6:21 -j REJECT

现在就一切正常了,非常实用的功能 ^_^
回复

使用道具 举报

 楼主| 发表于 2005-5-22 01:07:22 | 显示全部楼层
今天再测试的时候发现对 INPUT chain 还是有问题,时间还是不准,但 OUTPUT chain 和 FORWARD chain 却十分准确。

后来再次仔细的看了一次/usr/src/linux/net/ipv4/netfilter/ipt_time.c,发现ipt_time只在FORWARD和OUTPUT的时候使用kerneltime(内核时间),如果是INPUT使用的则是skb->stamp ,相关代码如下:

[code:1]
        /* we use the kerneltime if we are in forward or output */
        info->kerneltime = 1;
        if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
                /* we use the skb time */
                info->kerneltime = 0;
[/code:1]

在规则匹配函数match()中:
[code:1]
        /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
        if (info->kerneltime)
        {
                do_gettimeofday(&kerneltimeval);
                packet_local_time = kerneltimeval.tv_sec;
        }
        else
                packet_local_time = skb->stamp.tv_sec;
[/code:1]

而skb->stamp是在什么时候生成的呢?找了很久,终于在/usr/src/linux/net/core/dev.c中找到答案:
[code:1]
/**
*      netif_rx        -       post buffer to the network code
*      @skb: buffer to post
*
*      This function receives a packet from a device driver and queues it for
*      the upper (protocol) levels to process.  It always succeeds. The buffer
*      may be dropped during processing for congestion control or by the
*      protocol layers.
*
*      return values:
*      NET_RX_SUCCESS  (no congestion)
*      NET_RX_CN_LOW   (low congestion)
*      NET_RX_CN_MOD   (moderate congestion)
*      NET_RX_CN_HIGH  (high congestion)
*      NET_RX_DROP     (packet was dropped)
*
*/

int netif_rx(struct sk_buff *skb)
{
        int this_cpu;
        struct softnet_data *queue;
        unsigned long flags;

#ifdef CONFIG_NETPOLL
        if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
                kfree_skb(skb);
                return NET_RX_DROP;
        }
#endif

        if (!skb->stamp.tv_sec)
                net_timestamp(&skb->stamp);
[/code:1]

而net_timestamp()的代码为:
[code:1]
/* When > 0 there are consumers of rx skb time stamps */
static atomic_t netstamp_needed = ATOMIC_INIT(0);

static inline void net_timestamp(struct timeval *stamp)
{
        if (atomic_read(&netstamp_needed))
                do_gettimeofday(stamp);
        else {
                stamp->tv_sec = 0;
                stamp->tv_usec = 0;
        }
}
[/code:1]

看来netstamp_needed默认为0,那么skb->stamp.tv_sec就等于0,所以在ipt_time用于的INPUT chain时时间老是不对,看来在ipt_time.c上动手改造最方便了,将/usr/src/linux/net/ipv4/netfilter/ipt_time.c中的:
[code:1]
        /* we use the kerneltime if we are in forward or output */
        info->kerneltime = 1;
        if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
                /* we use the skb time */
                info->kerneltime = 0;
[/code:1]
改成:
[code:1]
        /* we use the kerneltime if we are in forward or output */
        info->kerneltime = 1;
[/code:1]
现在ipt_time将对所有的chain使用kerneltime,重新编译内核,如果现在再测试用于INPUT链的time匹配就可以正常工作了。

但还是存在一点问题,就是如果网络流量特别大的时候(包特别多),则规则匹配的将是ipt_time处理该包时的时间,而不是收到该包的时间,所以存在一定差距。如果将/usr/src/net/core/dev.c中的netstamp_needed 默认设置为1可能将是最终解决方法(这时就不要更改ipt_time.c )。但这种设置可能会对网络的性能有一点影响,因为即使你不使用ipt_time模块时,系统也会对每个收到的包加上timestamp值
回复

使用道具 举报

 楼主| 发表于 2005-5-22 01:29:31 | 显示全部楼层
终于找到最终解决方案了 ^_^

/usr/src/linux/net/core/dev.c中有个函数net_enable_timestamp()用来开启在每个包中记录timestamp的功能,而且这个函数是EXPORT_SYMBOL的,也就是说我们可以在module中调用它。

接下来的工作就简单了,只要将改/usr/src/linux/net/ipv4/netfilter/ipt_time.c中的:
[code:1]
static int __init init(void)
{
        printk("ipt_time loading\n");
        return ipt_register_match(&time_match);
}

static void __exit fini(void)
{
        ipt_unregister_match(&time_match);
        printk("ipt_time unloaded\n");
}

module_init(init);
module_exit(fini);
[/code:1]

修改为:

[code:1]
static int __init init(void)
{
        printk("ipt_time loading\n");
        net_enable_timestamp();
        return ipt_register_match(&time_match);
}

static void __exit fini(void)
{
        ipt_unregister_match(&time_match);
        printk("ipt_time unloaded\n");
        net_disable_timestamp();
}

module_init(init);
module_exit(fini);
[/code:1]

现在所有的问题都解决了,只有当你加载ipt_time模块时才会开启记录数据包timestamp 的功能,当卸载ipt_time时又会自动关闭timestamp 记录功能,现在总算完美了,最终还是在ipt_time.c上动手脚  ^_^

BTW:我这儿的linux kernel源代码版本为 2.6.11.10,patch-o-matic-ng为 20050519
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 22:48 , Processed in 0.069418 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表