super皮波 发表于 2015-05-03 22:37

关于netfilter中的ipt_do_table的一点疑问

直接贴代码了
ipt_do_table(struct sk_buff **pskb,
             unsigned int hook,
             const struct net_device *in,
             const struct net_device *out,
             struct ipt_table *table)
{
      .....
   do {
                IP_NF_ASSERT(e);
                IP_NF_ASSERT(back);
                if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
                        struct ipt_entry_target *t;

                        if (IPT_MATCH_ITERATE(e, do_match,
                                              *pskb, in, out,
                                              offset, &hotdrop) != 0)
                                goto no_match;

                        ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);

                        t = ipt_get_target(e);
                        IP_NF_ASSERT(t->u.kernel.target);
                        /* Standard target? */
                        if (!t->u.kernel.target->target) {
                                int v;

                                v = ((struct ipt_standard_target *)t)->verdict;
                                if (v < 0) {
                                        /* Pop from stack? */
                                        if (v != IPT_RETURN) {
                                                verdict = (unsigned)(-v) - 1;
                                                break;
                                        }
                                        e = back;
                                        back = get_entry(table_base,
                                                       back->comefrom);
                                        continue;
                                }
                                if (table_base + v != (void *)e + e->next_offset
                                  && !(e->ip.flags & IPT_F_GOTO)) {
                                        /* Save old back ptr in next entry */
                                        struct ipt_entry *next
                                                = (void *)e + e->next_offset;
                                        next->comefrom
                                                = (void *)back - table_base;
                                        /* set back pointer to next entry */
                                        back = next;
                                }

                                e = get_entry(table_base, v);
                        } else {
                                /* Targets which reenter must return
                                 abs. verdicts */
#ifdef CONFIG_NETFILTER_DEBUG
                                ((struct ipt_entry *)table_base)->comefrom
                                        = 0xeeeeeeec;
#endif
                                verdict = t->u.kernel.target->target(pskb,
                                                                     in, out,
                                                                     hook,
                                                                     t->u.kernel.target,
                                                                     t->data);

#ifdef CONFIG_NETFILTER_DEBUG
                                if (((struct ipt_entry *)table_base)->comefrom
                                  != 0xeeeeeeec
                                  && verdict == IPT_CONTINUE) {
                                        printk("Target %s reentered!\n",
                                             t->u.kernel.target->name);
                                        verdict = NF_DROP;
                                }
                                ((struct ipt_entry *)table_base)->comefrom
                                        = 0x57acc001;
#endif
                                /* Target might have changed stuff. */
                                ip = (*pskb)->nh.iph;
                                datalen = (*pskb)->len - ip->ihl * 4;

                                if (verdict == IPT_CONTINUE)
                                        e = (void *)e + e->next_offset;
                                else
                                        /* Verdict */
                                        break;
                        }
                } else {

                no_match:
                        e = (void *)e + e->next_offset;
                }
        } while (!hotdrop);/*这是循环退出的条件,假如我这里的rule只有一条标准匹配的话,并且没有第二条rule*/
}

多谢各位少侠

philarlala 发表于 2015-05-04 08:33

没看懂你的疑问在哪里

nswcfd 发表于 2015-05-04 14:20

本帖最后由 nswcfd 于 2015-05-04 14:22 编辑

你是想问loop的退出条件吧?

iptables用户态会给每个chain的最后加上一条不可见的end rule的,保证遍历可以结束(通过standard target分支)。

super皮波 发表于 2015-05-04 14:27

回复 3# nswcfd
嗯,昨天在网上也找到了这块资料,多谢了兄弟


   
页: [1]
查看完整版本: 关于netfilter中的ipt_do_table的一点疑问