免费注册 查看新帖 |

Chinaunix

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

iptables target [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-22 17:00 |只看该作者 |倒序浏览

本章分析target。

所有表最后会有一个错误目标的规则;
自定义链会有一个错误目标的链头(规则);
所有链都有一个标准目标的链尾(规则),自定义链的verdict是RETURN,内建链的verdict是ACCEPT和DROP。

关于链的排列方式:
1)  在用户空间的链表形态:
TC_CREATE_CHAIN()可以看出,新链总是加在最后。
list_add_tail(&c->list, &(*handle)->chains);
              但是如果新内建链来了呢?
2)  在内核空间的连续内存形态:
内建链在前面;自定义链在后面;
另外的说明参考上面。

/* Convenience structures */
struct ipt_error_target
{
              STRUCT_ENTRY_TARGET t;
              char error[TABLE_MAXNAMELEN];
};

#define STRUCT_STANDARD_TARGET           struct ipt_standard_target
#define ipt_standard_target xt_standard_target                   // 内核里面定义的ipt_standard_target
struct xt_standard_target
{
              struct xt_entry_target target;
              int verdict;
};


/* Convenience structures */
struct iptcb_chain_start{
              STRUCT_ENTRY e;
              struct ipt_error_target name;
};
#define IPTCB_CHAIN_START_SIZE  (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(struct ipt_error_target)))
链头,这个是只有自定义链太会有的。target是个错误目标。此rule不应该被用到。因为所有跳转到此链的规则,都会直接跳到此链的第二条规则。而不是这条错误的规则,参考
iptcc_compile_rule
()。



struct
iptcb_chain_foot
{
              STRUCT_ENTRY e;
              STRUCT_STANDARD_TARGET target;
};
#define IPTCB_CHAIN_FOOT_SIZE   (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(STRUCT_STANDARD_TARGET)))
链尾,标准链和自定义链都会有的。它包含一个标准目标。标准目标在内核定义,包含一个xt_entry_target和一个verdict。
verdict对标准链来说是ACCEPT, DROP等;对自定义链来说是RETURN。



struct
iptcb_chain_error
{
              STRUCT_ENTRY entry;
              struct ipt_error_target target;
};
#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(struct ipt_error_target)))
只在iptcc_compile_table()里面用到了,在表的末尾加一个struct iptcb_chain_error。
/* Convenience structures */
struct iptcb_chain_start{
              STRUCT_ENTRY e;
              struct ipt_error_target name;
};
#define IPTCB_CHAIN_START_SIZE  (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(struct ipt_error_target)))
链头,这个是只有自定义链太会有的。target是个错误目标。此rule不应该被用到。因为所有跳转到此链的规则,都会直接跳到此链的第二条规则。而不是这条错误的规则。

/* compile chain from cache into blob */
static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c)
{
              int ret;
              struct rule_head *r;
              struct iptcb_chain_start *head;
              struct iptcb_chain_foot *foot;

              /* only user-defined chains have heaer */
              if (!iptcc_is_builtin(c)) {                                                                                                                       // 只有自定义链才有此链头
                            /* put chain header in place */
                            head = (void *)repl->entries + c->head_offset;
                            head->e.target_offset = sizeof(STRUCT_ENTRY);
                            head->e.next_offset = IPTCB_CHAIN_START_SIZE;
                            strcpy(head->name.t.u.user.name, ERROR_TARGET);      // 错误目标
                            head->name.t.u.target_size =
                                                        ALIGN(sizeof(struct ipt_error_target));
                            strcpy(head->name.error, c->name);
              } else {
                            repl->hook_entry[c->hooknum-1] = c->head_offset;         
                            repl->underflow[c->hooknum-1] = c->foot_offset;
              }

              /* iterate over rules */
              list_for_each_entry(r, &c->rules, list) {
                            ret = iptcc_compile_rule(h, repl, r);
                            if (ret
                                          return ret;
              }

              /* put chain footer in place */
              foot = (void *)repl->entries + c->foot_offset;
              foot->e.target_offset = sizeof(STRUCT_ENTRY);
              foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;
              strcpy(foot->target.target.u.user.name, STANDARD_TARGET);
              foot->target.target.u.target_size =
                                                        ALIGN(sizeof(STRUCT_STANDARD_TARGET));
              /* builtin targets have verdict, others return */
              if (iptcc_is_builtin(c))
                            foot->target.verdict = c->verdict;
              else
                            foot->target.verdict = RETURN;
              /* set policy-counters */
              memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));

              return 0;
}


/* compile rule from cache into blob */
static inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r)
{
              /* handle jumps */
              if (r->type == IPTCC_R_JUMP) {                                                               // 是JUMP。也就是说目标自定义的链
                            STRUCT_STANDARD_TARGET *t;
                            t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
                            /* memset for memcmp convenience on delete/replace */
                            memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
                            strcpy(t->target.u.user.name, STANDARD_TARGET);
                            /* Jumps can only happen to builtin chains, so we
                             * can safely assume that they always have a header */
                            t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; // 设置verdict为第二条规则
              } else if (r->type == IPTCC_R_FALLTHROUGH) {
                            STRUCT_STANDARD_TARGET *t;
                            t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
                            t->verdict = r->offset + r->size;
              }
              
              /* copy entry from cache to blob */
              memcpy((char *)repl->entries+r->offset, r->entry, r->size);

              return 1;
}
struct iptcb_chain_foot {
              STRUCT_ENTRY e;
              STRUCT_STANDARD_TARGET target;
};
#define IPTCB_CHAIN_FOOT_SIZE   (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(STRUCT_STANDARD_TARGET)))
链尾,标准链和自定义链都会有的。它包含一个标准目标。标准目标在内核定义,包含一个xt_entry_target和一个verdict。
verdict对标准链来说是ACCEPT, DROP等;对自定义链来说是RETURN。

/* compile chain from cache into blob */
static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c)
{
              int ret;
              struct rule_head *r;
              struct iptcb_chain_start *head;
              struct iptcb_chain_foot *foot;

              /* only user-defined chains have heaer */
              if (!iptcc_is_builtin(c)) {
                            /* put chain header in place */
                            head = (void *)repl->entries + c->head_offset;
                            head->e.target_offset = sizeof(STRUCT_ENTRY);
                            head->e.next_offset = IPTCB_CHAIN_START_SIZE;
                            strcpy(head->name.t.u.user.name, ERROR_TARGET);
                            head->name.t.u.target_size =
                                                        ALIGN(sizeof(struct ipt_error_target));
                            strcpy(head->name.error, c->name);
              } else {
                            repl->hook_entry[c->hooknum-1] = c->head_offset;         
                            repl->underflow[c->hooknum-1] = c->foot_offset;
              }

              /* iterate over rules */
              list_for_each_entry(r, &c->rules, list) {
                            ret = iptcc_compile_rule(h, repl, r);
                            if (ret
                                          return ret;
              }

              /* put chain footer in place */
              foot = (void *)repl->entries + c->foot_offset;
              foot->e.target_offset = sizeof(STRUCT_ENTRY);
              foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;
              strcpy(foot->target.target.u.user.name, STANDARD_TARGET);
              foot->target.target.u.target_size =
                                                        ALIGN(sizeof(STRUCT_STANDARD_TARGET));
              /* builtin targets have verdict, others return */
              if (iptcc_is_builtin(c))
                            foot->target.verdict = c->verdict;                       // 标准链,这个值是在那里设置的?
如果链是表的默认链,那么表模板里面会给出这个值。比如packet_filter表;
                  /* LOCAL_IN */
                  { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
                            0,
                            sizeof(struct ipt_entry),
                            sizeof(struct ipt_standard),
                            0, { 0, 0 }, { } },
                    { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
                            -NF_ACCEPT - 1 } },
如果不是表的默认链呢?
              首先是可以通过case 'P':来调用TC_SET_POLICY()来设置链的默认处理结果的。
              if (strcmp(policy, LABEL_ACCEPT) == 0)
                            c->verdict = -NF_ACCEPT - 1;
              else if (strcmp(policy, LABEL_DROP) == 0)
                            c->verdict = -NF_DROP - 1;
              else {
                            errno = EINVAL;
                            return 0;
              }

              规则插入的时候似乎会有设置:
              TC_INSERT_ENTRY()
               -> iptcc_map_target()
                -> iptcc_standard_map()
                 -> t->verdict = verdict;

              else
                            foot->target.verdict = RETURN;                        // 自定义链
              /* set policy-counters */
              memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));

              return 0;
} struct iptcb_chain_error {
              STRUCT_ENTRY entry;
              struct ipt_error_target target;
};
#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) +                             \
                                                         ALIGN(sizeof(struct ipt_error_target)))
只在iptcc_compile_table()里面用到了,在表的末尾加一个struct iptcb_chain_error。
static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)
{
              struct chain_head *c;
              struct iptcb_chain_error *error;

              /* Second pass: copy from cache to offsets, fill in jumps */
              list_for_each_entry(c, &h->chains, list) {
                            int ret = iptcc_compile_chain(h, repl, c);
                            if (ret
                                          return ret;
              }

              /* Append error rule at end of chain */
              error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
              error->entry.target_offset = sizeof(STRUCT_ENTRY);
              error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
              error->target.t.u.user.target_size =
                            ALIGN(sizeof(struct ipt_error_target));
              strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET);
              strcpy((char *)&error->target.error, "ERROR");

              return 1;
}




ipt_standard_target:

do_command():
                            case 'j':
                                          set_option(&options, OPT_JUMP, &fw.ip.invflags,
                                                           invert);
                                          jumpto = parse_target(optarg);
                                          /* TRY_LOAD (may be chain name) */
                                          target = find_target(jumpto, TRY_LOAD);


struct iptables_target *
find_target(const char *name, enum ipt_tryload tryload)
{
              struct iptables_target *ptr;

              /* Standard target? */
              if (strcmp(name, "") == 0
                  || strcmp(name, IPTC_LABEL_ACCEPT) == 0
                  || strcmp(name, IPTC_LABEL_DROP) == 0
                  || strcmp(name, IPTC_LABEL_QUEUE) == 0
                  || strcmp(name, IPTC_LABEL_RETURN) == 0)
                            name = "standard";                                           // 内建规则

libipt_standard.c:
static
struct iptables_target standard = {
              .next                     = NULL,
              .name                    = "standard",
              .version   = IPTABLES_VERSION,
              .size                      = IPT_ALIGN(sizeof(int)),
              .userspacesize        = IPT_ALIGN(sizeof(int)),
              .help                     = &help,
              .init                       = &init,
              .parse                    = &parse,
              .final_check           = &final_check,
              .print                     = NULL,
              .save                     = &save,
              .extra_opts            = opts
};


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/110937/showart_2157927.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP