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

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: LINUX

2010-01-22 16:58:45

本章主要是讲iptables命令的整个处理过程,包括:

1.         命令行参数解析;

2.         kernel取得初始规则集;

3.         显示规则;或如果要设置,那么组装要发送到kernel的数据结构;

4.         发送到kernel

 

 

/* Append entry `fw' to chain `chain'.  Equivalent to insert with

   rulenum = length of chain. */

int

TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,

                            const STRUCT_ENTRY *e,

                            TC_HANDLE_T *handle)

{

              struct chain_head *c;

              struct rule_head *r;

 

              iptc_fn = TC_APPEND_ENTRY;

              if (!(c = iptcc_find_label(chain, *handle))) {                                                 // 确认chain是否存在

                            DEBUGP("unable to find chain `%s'\n", chain);

                            errno = ENOENT;

                            return 0;

              }

 

              if (!(r = iptcc_alloc_rule(c, e->next_offset))) {

                            DEBUGP("unable to allocate rule for chain `%s'\n", chain);

                            errno = ENOMEM;

                            return 0;

              }

 

              memcpy(r->entry, e, e->next_offset);

              r->counter_map.maptype = COUNTER_MAP_SET;

 

              if (!iptcc_map_target(*handle, r)) {                                  // 这个函数很重要。似乎是修改r中的target

                            DEBUGP("unable to map target of rule for chain `%s'\n", chain);

                            free(r);

                            return 0;

              }

 

              list_add_tail(&r->list, &c->rules);                                                  // 添加到chainrules链的尾部

              c->num_rules++;

 

              set_changed(*handle);

 

              return 1;

}


static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)

{

              struct chain_head *c;

              struct iptcb_chain_error *error;

struct iptcb_chain_error {

              STRUCT_ENTRY entry;

              struct ipt_error_target target;

};

              /* 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;

这个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);// ERROR_TARGET = “ERROR”

              strcpy((char *)&error->target.error, "ERROR");                                            // error->target.error也设置为"ERROR"

 

              return 1;

}

 

/* compile chain from cache into blob */

static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c)

在这里会构筑blob的链;

找了半天的链头的ERROR_TARGET的规则就是在这里被加入的。

{

              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)) {                                                               // 如果不是内建链的话(return (c->hooknum ? 1 : 0);

                            /* put chain header in place */                            // c->head_offset处,设置一个iptcb_chain_start *head;

                            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);      // ERROR_TARGET = “ERROR”

                            head->name.t.u.target_size =

                                                        ALIGN(sizeof(struct ipt_error_target));

                            strcpy(head->name.error, c->name);                                                            // 这个地方的name是链名

/* Convenience structures */

struct iptcb_chain_start{

              STRUCT_ENTRY e;

              struct ipt_error_target name;

};

/* Convenience structures */

struct ipt_error_target

{

              STRUCT_ENTRY_TARGET t;

              char error[TABLE_MAXNAMELEN];

};

 

c->name是自定义链的名字,例如iptables –N abc

iptcc_alloc_chain_head()中设置的

              } else {

                            repl->hook_entry[c->hooknum-1] = c->head_offset;                                     // 如果不是自定义链,那么记录

                            repl->underflow[c->hooknum-1] = c->foot_offset;                                        // hook_entryunderflow

              }

 

              /* 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 */                                                                      // 每个链都会有这个处理,加个链的footer

              foot = (void *)repl->entries + c->foot_offset;

              foot->e.target_offset = sizeof(STRUCT_ENTRY);

              foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;          // STRUCT_STANDARD_TARGET

              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;                    // 内建链设置target.verdict = c->verdict

              else

                            foot->target.verdict = RETURN;                                   // 自定义链设置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) {

                            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;

如果是一条类型为IPTCC_R_JUMP的规则,那么设置对应的blob内的规则的verdict为所跳转的链的第二条规则(的偏移)。非内建链的第一条规则必须是一条iptcb_chain_start规则,参考iptcc_compile_chain()

 

STRUCT_STANDARD_TARGET是内核定义的结构体:

struct xt_standard_target

{

              struct xt_entry_target target;

              int 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;

}

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

上一篇:iptables (4)

下一篇:iptables match

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