iptables源码分析(1)
来源:互联网 发布:图书馆数据库设计 编辑:程序博客网 时间:2024/06/08 06:36
一、规则的显示 选择先来说明规则的显示,因为他涉及到的东东简单,而且又全面,了解了规则的显示,对于其它操作的了解就显得容易了。 iptables version 1.2.7 iptables有两条线:ipv4 和ipv6,这里只分析v4的,因为v6偶暂时还用不着,没有去看。 iptables_standardone.c 主函数: int main(int argc, char *argv[]) { int ret; char *table = "filter"; /*默认的表是filter*/ iptc_handle_t handle = NULL; program_name = "iptables"; program_version = IPTABLES_VERSION; #ifdef NO_SHARED_LIBS init_extensions(); #endif /*进入命令行处理函数*/ ret = do_command(argc, argv, &table, &handle); if (ret) ret = iptc_commit(&handle); if (!ret) fprintf(stderr, "iptables: %s/n", iptc_strerror(errno)); exit(!ret); } table表示表的名称,就是iptables -t 后面跟的那个,默认是"filter" iptc_handle_t handle = NULL; 这个东东很重要,现在初始化NULL,后面他被用来存储一个表的所有规则的快照。 program_name = "iptables"; program_version = IPTABLES_VERSION; 设置名称和版本。 #ifdef NO_SHARED_LIBS init_extensions(); #endif iptables很多东东,是用共享库*.so的形式(我们安装会,可以在诸如/lib/iptables下边看到),如果不采用共享库,则进行一个初始化操作。我们假设是采用共享库的,忽略它。 然后就进入核心处理模块: do_command(argc, argv, &table, &handle); do_command 函数是整个系统的核心,负责处理整个用户的输入命令。函数首先对一些结构、变量进行初始化,初始化完毕后,进入while循环,分析用户输入的命令,设置相关的标志变量,然后根据相应标志,调用对应的处理函数。 struct ipt_entry fw, *e = NULL; int invert = 0; unsigned int nsaddrs = 0, ndaddrs = 0; struct in_addr *saddrs = NULL, *daddrs = NULL; int c, verbose = 0; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; unsigned int rulenum = 0, options = 0, command = 0; const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct iptables_match *m; struct iptables_target *target = NULL; struct iptables_target *t; const char *jumpto = ""; char *protocol = NULL; const char *modprobe = NULL; /*初始化变量*/ memset(&fw, 0, sizeof(fw)); opts = original_opts; global_option_offset = 0; /* re-set optind to 0 in case do_command gets called * a second time */ optind = 0; /*初始化两个全局变量*/ /* clear mflags in case do_command gets called a second time * (we clear the global list of all matches for security)*/ for (m = iptables_matches; m; m = m->next) { m->mflags = 0; m->used = 0; } for (t = iptables_targets; t; t = t->next) { t->tflags = 0; t->used = 0; } ps:开头一大堆的变量定义和初始化,可以在程序分析的时候看它们的作用,有两个全局结构变量很重要:iptables_matches和iptables_targets。现在来分析他们的作用会有一点困难,因为它们涉及到了太多方面的东东,这里,可以先把它们“想像成”用户空间用来读取内核规则的结构(当然,这有点错误)。 /*开始化析命令行*/ while ((c = getopt_long(argc, argv, "-A:C:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:", opts, NULL)) != -1) { } 这个while循环处理所有的用户输入,对应规则输出-L,有: case 'L': add_command(&command, CMD_LIST, CMD_ZERO, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; add_command函数负责将命令标志变量command与令标志 CMD_LIST求&运算, CMD_ZERO只是一个附加的判断标志而已,invert);然后,从命令行中取得要显示的链名(如果有的话)。 与此相关的还有用t参数指定了表名: case 't': if (invert) exit_error(PARAMETER_PROBLEM, "unexpected ! flag before --table"); *table = argv[optind-1]; break; 即,如果有’t’参数,则取’t’后跟的表名:*table = argv[optind-1],否则,它应该是主函数中默认的filter表。 命令处理完毕后,即进入执行模块: /*因为程序定义了共享库的话,iptables_matches/iptables_target这两个结构运行至此是NULL,并且target也是NULL,对于规则显示而言,这一部份的处理目前没有实际意义,回过头再来看这一段更易理解。final_check成员函数的作用是作最终的标志检查,如果检测失则,则退出*/ for (m = iptables_matches; m; m = m->next) { if (!m->used) continue; m->final_check(m->mflags); } if (target) target->final_check(target->tflags); 接着对参数作一些必要的合法性检查: /* Fix me: must put inverse options checking here --MN */ if (optind < argc) exit_error(PARAMETER_PROBLEM, "unknown arguments found on commandline"); if (!command) exit_error(PARAMETER_PROBLEM, "no command specified"); if (invert) exit_error(PARAMETER_PROBLEM, "nothing appropriate following !"); /*对于如果要进行(CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)处理来说,如果没有设置来源/目的地址及掩码,则给予它们一个默认值*/ if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { if (!(options & OPT_DESTINATION)) dhostnetworkmask = "0.0.0.0/0"; if (!(options & OPT_SOURCE)) shostnetworkmask = "0.0.0.0/0"; } /*对来源/目的地址及掩码进行拆分,它们总是以 addr/mask的形式来出现的,根据’/’前面的字符串取得地址值,根据’/’后面的掩码位数,求得正确的掩码值,值得注意的是,同时要处理主机地址和网络地址的情况*/ if (shostnetworkmask) parse_hostnetworkmask(shostnetworkmask, &saddrs, &(fw.ip.smsk), &nsaddrs); if (dhostnetworkmask) parse_hostnetworkmask(dhostnetworkmask, &daddrs, &(fw.ip.dmsk), &ndaddrs); /*然后检查来源/目的网络地址的合法性*/ if ((nsaddrs > 1 || ndaddrs > 1) && (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP))) exit_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); /*对命令行格式进行合法性检查*/ generic_opt_check(command, options); 如果前面只是热身的话,那么从现在开始,就进入实质性阶段了: do_command函数最后一个参数handle,是一个指向了具体表,如filter、nat表的句柄,这里判断,如果handle为空,则调用iptc_init,根据table的名称,让handle指针指向相应的表的地址空间,也就是把对应表的所有信息从内核中取出来: /* only allocate handle if we weren't called with a handle */ if (!*handle) *handle = iptc_init(*table); /*如果获取换败,将试着插入模块,再次获取*/ if (!*handle) { /* try to insmod the module if iptc_init failed */ iptables_insmod("ip_tables", modprobe); *handle = iptc_init(*table); /*仍然失败,则退出*/ if (!*handle) exit_error(VERSION_PROBLEM, "can't initialize iptables table `%s': %s", *table, iptc_strerror(errno)); /*继续进行一些简单的判断*/ if (command == CMD_APPEND || command == CMD_DELETE || command == CMD_INSERT || command == CMD_REPLACE) { /*List命令不在判断之列,暂时不分析*/ } /*判断命令标志,调用相关函数进行处理*/ switch (command) { case CMD_LIST: ret = list_entries(chain, options&OPT_VERBOSE, options&OPT_NUMERIC, options&OPT_EXPANDED, options&OPT_LINENUMBERS, handle); } list_entries是规则显示的主要处理函数。 Options是显示的标志变量: OPT_VERBOSE:对应-v OPT_NUMERIC:对应-n OPT_EXPANDED:对应-x OPT_LINENUMBERS: -l 看来很简单,说了这么大一圈子,就是调用 iptc_init获取表的规则信息,调用list_entries函数显示规则。
- iptables源码分析(1)
- iptables源码分析(2)
- iptables源码分析(3)
- iptables源码分析(4)
- iptables 源码分析
- iptables 源码分析
- iptables 分析
- 实用防火墙(Iptables)脚本分析
- 实用防火墙(Iptables)脚本分析
- Okhttp 源码分析(1)----流程分析
- Android5.1源码分析系列(一)Settings源码分析
- jBPM源码分析(1)
- __mt_alloc源码分析(1)
- LIRC源码分析(1)
- uboot源码分析(1)
- uboot源码分析(1)
- libevent源码分析(1)
- uboot源码分析(1)
- arcEngine部分刷新问题
- Request.ServerVariables (server environment variable)
- 【PHP系列教程】(3)——PHP的类型
- SWT异常: Invalid thread access
- 游标的使用
- iptables源码分析(1)
- linux下安装java jdk及环境变量配置
- WinCE BSP中的Dirs文件和Sources文件(转自微软MVP作者:ARM—WinCE) 收藏
- ODI笔记一 – 创建存储库
- sql 格式化 日期函数
- 《调试高手和编程高手》
- VS2005 ATL项目错误
- 做需求调研必须回答的三个问题
- 2009项目总结