- 论坛徽章:
- 0
|
原帖由 Godbach 于 2008-8-7 16:11 发表 ![]()
也就是说带-m state的规则在存到某个表里的时候,是不是存到表的最前面了。如果是,代码哪里实现的?
个人觉得这个应该是在iptables里实现的,因为每下一条规则,都相当于把某个表取出来,更新之后,又重新下 ...
不好意思,这两天看奥运了,回复的慢了:)
我看了一些东西,先写出来,不过还没有把所有的搞清楚,先写出来一起看看。
Iptables源码中有一个Libxt_state.c,它的第一行写的是:
/* Shared library add-on to iptables to add state tracking support. */ (支持状态追踪的共享库)
它的_init函数是在注册一个state_match结构:
- void _init(void)
- {
- xtables_register_match(&state_match);
- xtables_register_match(&state_match6);
- }
复制代码
这个注册动作是将state_match注册到一个全局的xtables_matches中。具体是调find_match看看是不是有旧的相同名字的match,如果有的话就删了,然后替换掉。
- void xtables_register_match(struct xtables_match *me)
- {
- struct xtables_match **i, *old;
- if (strcmp(me->version, program_version) != 0) {
- fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
- program_name, me->name, me->version, program_version);
- exit(1);
- }
- /* Revision field stole a char from name. */
- if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) {
- fprintf(stderr, "%s: target `%s' has invalid name\n",
- program_name, me->name);
- exit(1);
- }
- if (me->family >= NPROTO) {
- fprintf(stderr,
- "%s: BUG: match %s has invalid protocol family\n",
- program_name, me->name);
- exit(1);
- }
- /* ignore not interested match */
- if (me->family != afinfo.family && me->family != AF_UNSPEC)
- return;
- old = find_match(me->name, DURING_LOAD, NULL);
- if (old) {
- if (old->revision == me->revision &&
- old->family == me->family) {
- fprintf(stderr,
- "%s: match `%s' already registered.\n",
- program_name, me->name);
- exit(1);
- }
- /* Now we have two (or more) options, check compatibility. */
- if (compatible_match_revision(old->name, old->revision)
- && old->revision > me->revision)
- return;
- /* See if new match can be used. */
- if (!compatible_match_revision(me->name, me->revision))
- return;
- /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
- if (old->revision == me->revision && me->family == AF_UNSPEC)
- return;
- /* Delete old one. */
- for (i = &xtables_matches; *i!=old; i = &(*i)->next);
- *i = old->next;
- }
- if (me->size != XT_ALIGN(me->size)) {
- fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
- program_name, me->name, (unsigned int)me->size);
- exit(1);
- }
- /* Append to list. */
- for (i = &xtables_matches; *i; i = &(*i)->next);
- me->next = NULL;
- *i = me;
- me->m = NULL;
- me->mflags = 0;
- }
复制代码
其中 state_match是一个xtables_match结构体,具体如下里面的.parse注册一个state_parse函数指针,
- static struct xtables_match state_match = {
- .family = AF_INET,
- .name = "state",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_state_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
- .help = state_help,
- .parse = state_parse,
- .final_check = state_final_check,
- .print = state_print,
- .save = state_save,
- .extra_opts = state_opts,
- };
复制代码
而parse_state函数就是来根据判断state字符串来设置相应位的:
- static int
- parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
- {
- if (strncasecmp(state, "INVALID", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_INVALID;
- else if (strncasecmp(state, "NEW", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
- else if (strncasecmp(state, "ESTABLISHED", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
- else if (strncasecmp(state, "RELATED", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
- else if (strncasecmp(state, "UNTRACKED", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_UNTRACKED;
- else if (strncasecmp(state, "SNAT", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_SNAT;
- else if (strncasecmp(state, "DNAT", len) == 0)
- sinfo->statemask |= XT_CONNTRACK_STATE_DNAT;
- else
- return 0;
- return 1;
- }
复制代码
以上操作即实现了在添加这个共享库的时候全局的xtables_matches中已经有了可以实现解析state的match了。
现在重新回到那个do_command函数中,在解析到 -m 选项的时候,调用:
- case 'm': {
- size_t size;
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "unexpected ! flag before --match");
- m = find_match(optarg, LOAD_MUST_SUCCEED, &matches);
- size = IPT_ALIGN(sizeof(struct ipt_entry_match))
- + m->size;
- m->m = fw_calloc(1, size);
- m->m->u.match_size = size;
- strcpy(m->m->u.user.name, m->name);
- set_revision(m->m->u.user.name, m->revision);
- if (m->init != NULL)
- m->init(m->m);
- if (m != m->next) {
- /* Merge options for non-cloned matches */
- opts = merge_options(opts,
- m->extra_opts,
- &m->option_offset);
- if (opts == NULL)
- exit_error(OTHER_PROBLEM,
- "can't alloc memory!");
- }
- }
复制代码
它调用find_match函数根据optarg找相应名字的match(但是我的souceinsight始终找不到这个optarg在哪儿,到底是什么---郁闷!)
###################中间我也不知道怎么回事。。。####################这个{case "m"}函数段中的那个变量m(xtables_match类型的),一直没找到它是后来是用来干嘛的。。。。同志们也看看吧。
然后是do_command函数后面调用,e = generate_entry(&fw, matches, target->t);
然后就是append_entry往内核里添加了。。。
综上所述,实际上我只找到了parse state的函数,没找到它到底是加在一个chain的头部还是尾部了。。。。。我觉得就是由match的parse函数去设置要添加的entry追踪状态位。
还有就是,我有个想法,其实Iptables里的match,就是那个全局变量xtables_matches,跟netfilter里match根本不是一回事。前者是实现了对命令行解析的match,后者是对数据包的match。
我看了这些,还会继续看下去,如果哪里错了还望大家及时纠正
[ 本帖最后由 jaycu 于 2008-8-10 12:08 编辑 ] |
|