iptables源码分析(4)

然match是以可扩展的形式表现出来,那么,当然就需要find_match这样的函数将它们一一找出来了。

 

前面说过,在输出规则的函数中:

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

用来遍历每一个match,找到了后,就调用print_match来输出。print_match是调用find_match来查找的:

 

struct iptables_match *

find_match(const char *name, enum ipt_tryload tryload)

{

struct iptables_match *ptr;

 

for (ptr = iptables_matches; ptr; ptr = ptr->next) {

if (strcmp(name, ptr->name) == 0)

break;

}

 

#ifndef NO_SHARED_LIBS

if (!ptr && tryload != DONT_LOAD) {

char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")

+ strlen(name)];

sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);

if (dlopen(path, RTLD_NOW)) {

/* Found library. If it didn't register itself,

maybe they specified target as match. */

ptr = find_match(name, DONT_LOAD);

 

if (!ptr)

exit_error(PARAMETER_PROBLEM,

"Couldn't load match `%s'/n",

name);

} else if (tryload == LOAD_MUST_SUCCEED)

exit_error(PARAMETER_PROBLEM,

"Couldn't load match `%s':%s/n",

name, dlerror());

}

#else

if (ptr && !ptr->loaded) {

if (tryload != DONT_LOAD)

ptr->loaded = 1;

else

ptr = NULL;

}

if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {

exit_error(PARAMETER_PROBLEM,

"Couldn't find match `%s'/n", name);

}

#endif

 

if (ptr)

ptr->used = 1;

 

return ptr;

}

 

分析这个函数,不从开头来看,先看这一段:

if (!ptr && tryload != DONT_LOAD) {

char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")

+ strlen(name)];

sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);

if (dlopen(path, RTLD_NOW)) {

/* Found library. If it didn't register itself,

maybe they specified target as match. */

ptr = find_match(name, DONT_LOAD);

 

if (!ptr)

exit_error(PARAMETER_PROBLEM,

"Couldn't load match `%s'/n",

name);

} else if (tryload == LOAD_MUST_SUCCEED)

exit_error(PARAMETER_PROBLEM,

"Couldn't load match `%s':%s/n",

name, dlerror());

}

函数根据传递过来的match名称,从指定位置,加载对应的共享库,呵呵,这些共享库的源码,全部在Extensions目录下边:

如果加载它们,那么其_init函数就会被调用。这个初始化函数用来向iptables_match全局结构注册当前match的相关处理函数。(这样,我们可以写我们自己的用户空间的扩展match处理工具了)。注册好后,函数再来调用自己:

ptr = find_match(name, DONT_LOAD);

递归回来后,呵呵,就是开头那一段了,我们需要从已经注册好的全局结构中查找与当前match名称相同的iptables_match成员,因为该成员中封装了print函数,这样就可以顺利地输出来了:

比如,加载了libptc_tcp.so,它用来处理tcp的扩展,我们来看Extensions/libiptc_tcp.c:

static

struct iptables_match tcp

= { NULL,

"tcp",

IPTABLES_VERSION,

IPT_ALIGN(sizeof(struct ipt_tcp)),

IPT_ALIGN(sizeof(struct ipt_tcp)),

&help,

&init,

&parse,

&final_check,

&print,

&save,

opts };

 

void

_init(void)

{

register_match(&tcp);

}

 

构建了一个

iptables_match结构,其间有其对应的所有用户空间工具函数,如分析命令行、输出、保存……

然后,就调用register_match函数将其插入至全局结构iptables_match当中:

void

register_match(struct iptables_match *me)

{

struct iptables_match **i;

 

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

}

 

if (find_match(me->name, DONT_LOAD)) {

fprintf(stderr, "%s: match `%s' already registered./n",

program_name, me->name);

exit(1);

}

 

if (me->size != IPT_ALIGN(me->size)) {

fprintf(stderr, "%s: match `%s' has invalid size %u./n",

program_name, me->name, me->size);

exit(1);

}

 

/* Append to list. */

for (i = &iptables_matches; *i; i = &(*i)->next);

me->next = NULL;

*i = me;

 

me->m = NULL;

me->mflags = 0;

}

 

函数就是一个建立链表的过程。不进一步分析了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值