Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107885
  • 博文数量: 41
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 16:25
文章分类

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: LINUX

2010-01-22 17:00:19

本章分析target

 

所有表最后会有一个错误目标的规则;

自定义链会有一个错误目标的链头(规则);

所有链都有一个标准目标的链尾(规则),自定义链的verdictRETURN,内建链的verdictACCEPTDROP

 

关于链的排列方式:

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 < 0)

                                          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 < 0)

                                          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 < 0)

                                          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

};

阅读(1009) | 评论(0) | 转发(0) |
0

上一篇:iptables match

下一篇:Xen Event Channel (1)

给主人留下些什么吧!~~