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

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: LINUX

2010-01-22 16:58:06

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

1.         命令行参数解析;

2.         kernel取得初始规则集;

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

4.         发送到kernel

 

int

TC_COMMIT(TC_HANDLE_T *handle)

{

              /* Replace, then map back the counters. */

              STRUCT_REPLACE *repl;

              STRUCT_COUNTERS_INFO *newcounters;

              struct chain_head *c;

              int ret;

              size_t counterlen;

              int new_number;

              unsigned int new_size;

 

              iptc_fn = TC_COMMIT;

              CHECK(*handle);

 

              /* Don't commit if nothing changed. */

              if (!(*handle)->changed)                                                             // 有变化才需要提交kernel

                            goto finished;

 

              new_number = iptcc_compile_table_prep(*handle, &new_size);

              if (new_number < 0) {

                            errno = ENOMEM;

                            goto out_zero;

              }

 

              repl = malloc(sizeof(*repl) + new_size);                        // 申请repl

              if (!repl) {                                                                                                               // #define STRUCT_REPLACE              struct ipt_replace

                            errno = ENOMEM;

                            goto out_zero;

              }

              memset(repl, 0, sizeof(*repl) + new_size);

 

#if 0

              TC_DUMP_ENTRIES(*handle);

#endif

 

              counterlen = sizeof(STRUCT_COUNTERS_INFO)

                                          + sizeof(STRUCT_COUNTERS) * new_number;

 

              /* These are the old counters we will get from kernel */

              repl->counters = malloc(sizeof(STRUCT_COUNTERS)

                                                        * (*handle)->info.num_entries);

              if (!repl->counters) {

                            errno = ENOMEM;

                            goto out_free_repl;

              }

              /* These are the counters we're going to put back, later. */

              newcounters = malloc(counterlen);

              if (!newcounters) {

                            errno = ENOMEM;

                            goto out_free_repl_counters;

              }

              memset(newcounters, 0, counterlen);

 

              strcpy(repl->name, (*handle)->info.name);                                                   // repl的设置

              repl->num_entries = new_number;

              repl->size = new_size;

 

              repl->num_counters = (*handle)->info.num_entries;

              repl->valid_hooks = (*handle)->info.valid_hooks;

 

              DEBUGP("num_entries=%u, size=%u, num_counters=%u\n",

                            repl->num_entries, repl->size, repl->num_counters);

 

              ret = iptcc_compile_table(*handle, repl);                                                  // 根据*handle来构成repl的规则部分

              if (ret < 0) {

                            errno = ret;

                            goto out_free_newcounters;

              }

 

 

#ifdef IPTC_DEBUG2

              {

                            int fd = open("/tmp/libiptc-so_set_replace.blob",

                                                        O_CREAT|O_WRONLY);

                            if (fd >= 0) {

                                          write(fd, repl, sizeof(*repl) + repl->size);

                                          close(fd);

                            }

              }

#endif

 

              ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,           // 向内核发出请求

                                           sizeof(*repl) + repl->size);                                                                                                                // 重要的就成了看repl的组织

              if (ret < 0) {                                                                                                                                                                    // 注意规则要贴在ipt_replace的后面

                            errno = ret;

                            goto out_free_newcounters;

              }

 

              /* Put counters back. */

              strcpy(newcounters->name, (*handle)->info.name);

              newcounters->num_counters = new_number;

 

              list_for_each_entry(c, &(*handle)->chains, list) {

                            struct rule_head *r;

 

                            /* Builtin chains have their own counters */

                            if (iptcc_is_builtin(c)) {

                                          DEBUGP("counter for chain-index %u: ", c->foot_index);

                                          switch(c->counter_map.maptype) {

                                          case COUNTER_MAP_NOMAP:

                                                        counters_nomap(newcounters, c->foot_index);

                                                        break;

                                          case COUNTER_MAP_NORMAL_MAP:

                                                        counters_normal_map(newcounters, repl,

                                                                                        c->foot_index,

                                                                                        c->counter_map.mappos);

                                                        break;

                                          case COUNTER_MAP_ZEROED:

                                                        counters_map_zeroed(newcounters, repl,

                                                                                        c->foot_index,

                                                                                        c->counter_map.mappos,

                                                                                        &c->counters);

                                                        break;

                                          case COUNTER_MAP_SET:

                                                        counters_map_set(newcounters, c->foot_index,

                                                                                     &c->counters);

                                                        break;

                                          }

                            }

 

                            list_for_each_entry(r, &c->rules, list) {

                                          DEBUGP("counter for index %u: ", r->index);

                                          switch (r->counter_map.maptype) {

                                          case COUNTER_MAP_NOMAP:

                                                        counters_nomap(newcounters, r->index);

                                                        break;

 

                                          case COUNTER_MAP_NORMAL_MAP:

                                                        counters_normal_map(newcounters, repl,

                                                                                        r->index,

                                                                                        r->counter_map.mappos);

                                                        break;

 

                                          case COUNTER_MAP_ZEROED:

                                                        counters_map_zeroed(newcounters, repl,

                                                                                        r->index,

                                                                                        r->counter_map.mappos,

                                                                                        &r->entry->counters);

                                                        break;

 

                                          case COUNTER_MAP_SET:

                                                        counters_map_set(newcounters, r->index,

                                                                                     &r->entry->counters);

                                                        break;

                                          }

                            }

              }

 

 

#ifdef KERNEL_64_USERSPACE_32

              {

                            /* Kernel will think that pointer should be 64-bits, and get

                               padding.  So we accomodate here (assumption: alignment of

                               `counters' is on 64-bit boundary). */

                            u_int64_t *kernptr = (u_int64_t *)&newcounters->counters;

                            if ((unsigned long)&newcounters->counters % 8 != 0) {

                                          fprintf(stderr,

                                                        "counters alignment incorrect! Mail rusty!\n");

                                          abort();

                            }

                            *kernptr = newcounters->counters;

              }

#endif /* KERNEL_64_USERSPACE_32 */

 

#ifdef IPTC_DEBUG2

              {

                            int fd = open("/tmp/libiptc-so_set_add_counters.blob",

                                                        O_CREAT|O_WRONLY);

                            if (fd >= 0) {

                                          write(fd, newcounters, counterlen);

                                          close(fd);

                            }

              }

#endif

 

              ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,

                                           newcounters, counterlen);

              if (ret < 0) {

                            errno = ret;

                            goto out_free_newcounters;

              }

 

              free(repl->counters);

              free(repl);

              free(newcounters);

 

finished:

              TC_FREE(handle);

              return 1;

 

out_free_newcounters:

              free(newcounters);

out_free_repl_counters:

              free(repl->counters);

out_free_repl:

              free(repl);

out_zero:

              return 0;

}


 

/* parse an iptables blob into it's pieces */

static int parse_table(TC_HANDLE_T h)

TC_HANDLE_Tentries的规则解析到各个chain

{

              STRUCT_ENTRY *prev;

              unsigned int num = 0;

              struct chain_head *c;

 

              /* First pass: over ruleset blob */

              ENTRY_ITERATE(h->entries->entrytable, h->entries->size,

                                          cache_add_entry, h, &prev, &num);

 

              /* Second pass: fixup parsed data from first pass */

              list_for_each_entry(c, &h->chains, list) {

                            struct rule_head *r;

                            list_for_each_entry(r, &c->rules, list) {

                                          struct chain_head *c;

                                          STRUCT_STANDARD_TARGET *t;

 

                                          if (r->type != IPTCC_R_JUMP)

                                                        continue;

 

                                          t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);

                                          c = iptcc_find_chain_by_offset(h, t->verdict);

                                          if (!c)

                                                        return -1;

                                          r->jump = c;

                                          c->references++;

                            }

              }

 

              /* FIXME: sort chains */

 

              return 1;

}


 

/* e is called `fw' here for hysterical raisins */

static void

print_firewall(const struct ipt_entry *fw,

                     const char *targname,

                     unsigned int num,

                     unsigned int format,

                     const iptc_handle_t handle)

{

              struct iptables_target *target = NULL;

              const struct ipt_entry_target *t;

              u_int8_t flags;

              char buf[BUFSIZ];

 

              if (!iptc_is_chain(targname, handle))

                            target = find_target(targname, TRY_LOAD);                     // 根据名字找到target

              else

                            target = find_target(IPT_STANDARD_TARGET, LOAD_MUST_SUCCEED);

 

              t = ipt_get_target((struct ipt_entry *)fw);

              flags = fw->ip.flags;

 

              if (format & FMT_LINENUMBERS)

                            printf(FMT("%-4u ", "%u "), num+1);

 

              if (!(format & FMT_NOCOUNTS)) {

                            print_num(fw->counters.pcnt, format);

                            print_num(fw->counters.bcnt, format);

              }

 

              if (!(format & FMT_NOTARGET))

                            printf(FMT("%-9s ", "%s "), targname);

 

              fputc(fw->ip.invflags & IPT_INV_PROTO ? '!' : ' ', stdout);

              {

                            char *pname = proto_to_name(fw->ip.proto, format&FMT_NUMERIC);

                            if (pname)

                                          printf(FMT("%-5s", "%s "), pname);

                            else

                                          printf(FMT("%-5hu", "%hu "), fw->ip.proto);

              }

 

              if (format & FMT_OPTIONS) {

                            if (format & FMT_NOTABLE)

                                          fputs("opt ", stdout);

                            fputc(fw->ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);

                            fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);

                            fputc(' ', stdout);

              }

 

              if (format & FMT_VIA) {

                            char iface[IFNAMSIZ+2];

 

                            if (fw->ip.invflags & IPT_INV_VIA_IN) {

                                          iface[0] = '!';

                                          iface[1] = '\0';

                            }

                            else iface[0] = '\0';

 

                            if (fw->ip.iniface[0] != '\0') {

                                          strcat(iface, fw->ip.iniface);

                            }

                            else if (format & FMT_NUMERIC) strcat(iface, "*");

                            else strcat(iface, "any");

                            printf(FMT(" %-6s ","in %s "), iface);

 

                            if (fw->ip.invflags & IPT_INV_VIA_OUT) {

                                          iface[0] = '!';

                                          iface[1] = '\0';

                            }

                            else iface[0] = '\0';

 

                            if (fw->ip.outiface[0] != '\0') {

                                          strcat(iface, fw->ip.outiface);

                            }

                            else if (format & FMT_NUMERIC) strcat(iface, "*");

                            else strcat(iface, "any");

                            printf(FMT("%-6s ","out %s "), iface);

              }

 

              fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);

              if (fw->ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))

                            printf(FMT("%-19s ","%s "), "anywhere");

              else {

                            if (format & FMT_NUMERIC)

                                          sprintf(buf, "%s", addr_to_dotted(&(fw->ip.src)));

                            else

                                          sprintf(buf, "%s", addr_to_anyname(&(fw->ip.src)));

                            strcat(buf, mask_to_dotted(&(fw->ip.smsk)));

                            printf(FMT("%-19s ","%s "), buf);

              }

 

              fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);

              if (fw->ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))

                            printf(FMT("%-19s ","-> %s"), "anywhere");

              else {

                            if (format & FMT_NUMERIC)

                                          sprintf(buf, "%s", addr_to_dotted(&(fw->ip.dst)));

                            else

                                          sprintf(buf, "%s", addr_to_anyname(&(fw->ip.dst)));

                            strcat(buf, mask_to_dotted(&(fw->ip.dmsk)));

                            printf(FMT("%-19s ","-> %s"), buf);

              }

 

              if (format & FMT_NOTABLE)

                            fputs("  ", stdout);

 

#ifdef IPT_F_GOTO

              if(fw->ip.flags & IPT_F_GOTO)

                            printf("[goto] ");

#endif

 

              IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC);         // matchprint

 

              if (target) {

                            if (target->print)

                                          /* Print the target information. */

                                          target->print(&fw->ip, t, format & FMT_NUMERIC);                                   // 调用target的用户定义的print()

              } else if (t->u.target_size != sizeof(*t))

                            printf("[%u bytes of unknown target data] ",

                                   (unsigned int)(t->u.target_size - sizeof(*t)));

 

              if (!(format & FMT_NONEWLINE))

                            fputc('\n', stdout);

}


 

/* Returns NULL when rules run out. */

const STRUCT_ENTRY *

TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)

{

              struct rule_head *r;

 

              iptc_fn = TC_NEXT_RULE;

              DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur);

 

              if (!(*handle)->rule_iterator_cur) {

                            DEBUGP_C("returning NULL\n");

                            return NULL;

              }

             

              r = list_entry((*handle)->rule_iterator_cur->list.next,

                                          struct rule_head, list);

 

              iptc_fn = TC_NEXT_RULE;

 

              DEBUGP_C("next=%p, head=%p...", &r->list,

                            &(*handle)->rule_iterator_cur->chain->rules);

 

              if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) {

                            (*handle)->rule_iterator_cur = NULL;

                            DEBUGP_C("finished, returning NULL\n");

                            return NULL;

              }

 

              (*handle)->rule_iterator_cur = r;

 

              /* NOTE: prev is without any influence ! */

              DEBUGP_C("returning rule %p\n", r);

              return r->entry;

}

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

上一篇:iptables (3)

下一篇:iptables (5)

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