iptables insert_entry

 iptables v1.8.3

【预备知识】
使用getopt_long函数存在两个全局变量
全局变量:
(1)optarg:表示当前选项对应的参数值。
(2)optind:表示的是下一个将被处理到的参数在argv中的下标值。

【插入过程】
(1)
///< 命令行I选项:代表要在指定位置插入一条entry
1280         case 'I':
1281             add_command(&command, CMD_INSERT, CMD_NONE,
1282                     cs.invert);
1283             chain = optarg;  //指定了链表
1284             if (xs_has_arg(argc, argv))
1285                 rulenum = parse_rulenumber(argv[optind++]); // 指定了插入位置
1286             else rulenum = 1;
1287             break;

(2)
///< ipt_entry生成(此处生成的ipt_entry, 主要是为了ipt_entry + ipt_match + ipt_target组合在一起,让其内存连续)
1723             e = generate_entry(&cs.fw, cs.matches, cs.target->t);
(2-1)
static struct ipt_entry *
generate_entry(const struct ipt_entry *fw, 
           struct xtables_rule_match *matches,
           struct xt_entry_target *target)
{
    unsigned int size;
    struct xtables_rule_match *matchp;
    struct ipt_entry *e;

    size = sizeof(struct ipt_entry);
    for (matchp = matches; matchp; matchp = matchp->next)
        size += matchp->match->m->u.match_size;

    e = xtables_malloc(size + target->u.target_size);
    *e = *fw; 
    e->target_offset = size;
    e->next_offset = size + target->u.target_size;

    size = 0; 
    for (matchp = matches; matchp; matchp = matchp->next) {
        memcpy(e->elems + size, matchp->match->m, matchp->match->m->u.match_size);
        size += matchp->match->m->u.match_size;
    }    
    memcpy(e->elems + size, target, target->u.target_size);

    return e;
}
(2-2)
// cs.fw, cs.matches, cs.target->t这三个变量如何构建
首先看一下cs的结构
struct iptables_command_state cs = {
	...
};

struct iptables_command_state {
	union {
		struct ebt_entry eb;
		struct ipt_entry fw;
		struct ip6t_entry fw6;
		struct arpt_entry arp;
	};
	int invert;
	int c;
	unsigned int options;
	struct xtables_rule_match *matches;
	struct ebt_match *match_list;
	struct xtables_target *target;
	struct xt_counter counters;
	char *protocol;
	int proto_used;
	const char *jumpto;
	char **argv;
	bool restore;
};

struct xtables_rule_match {
	struct xtables_rule_match *next;
	struct xtables_match *match;
	/* Multiple matches of the same type: the ones before
	   the current one are completed from parsing point of view */
	bool completed;
};
(2-2-1)
// cs.fw构建
数据结构
 99 /* This structure defines each of the firewall rules.  Consists of 3
100    parts which are 1) general IP header stuff 2) match specific
101    stuff 3) the target to perform if the rule matches */
102 struct ipt_entry {
103     struct ipt_ip ip;
104 
105     /* Mark with fields that we care about. */
106     unsigned int nfcache;
107 
108     /* Size of ipt_entry + matches */
109     __u16 target_offset;
110     /* Size of ipt_entry + matches + target */
111     __u16 next_offset;
112 
113     /* Back pointer */
114     unsigned int comefrom;
115 
116     /* Packet and byte counters. */
117     struct xt_counters counters;
118 
119     /* The matches (if any), then the target. */
120     unsigned char elems[0];
121 };


 67 struct ipt_ip {
 68     /* Source and destination IP addr */
 69     struct in_addr src, dst;
// 分析入设备和出设备
//1435             xtables_parse_interface(optarg,
//1436                     cs.fw.ip.iniface,
//1437                     cs.fw.ip.iniface_mask);
 70     /* Mask for src and dest IP addr */
 71     struct in_addr smsk, dmsk;
 72     char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
 73     unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
 74 
 // 1392             cs.fw.ip.proto = xtables_parse_protocol(cs.protocol);
 75     /* Protocol, 0 = ANY */
 76     __u16 proto;
 77 
 78     /* Flags word */
 79     __u8 flags;
 80     /* Inverse flags */
 81     __u8 invflags;
 82 };


(2-2-2)
// cs.matches构建
以"-m tcp --dport 1234"为例

// (a)以下为用户空间注册match
数据结构
/* Include file for additions: new matches and targets. */
struct xtables_match {
    /*
     * ABI/API version this module requires. Must be first member,
     * as the rest of this struct may be subject to ABI changes.
     */
    const char *version;

    struct xtables_match *next;

    const char *name;
    const char *real_name;

    /* Revision of match (0 by default). */
    uint8_t revision;

    /* Extension flags */
    uint8_t ext_flags;

    uint16_t family;

    /* Size of match data. */
    size_t size;  // 

    /* Size of match data relevant for userspace comparison purposes */
    size_t userspacesize;

    /* Function which prints out usage message. */
    void (*help)(void);

    /* Initialize the match. */
    void (*init)(struct xt_entry_match *m);

    /* Function which parses command options; returns true if it
           ate an option */
    /* entry is struct ipt_entry for example */
    int (*parse)(int c, char **argv, int invert, unsigned int *flags,
             const void *entry,
             struct xt_entry_match **match);

    /* Final check; exit if not ok. */
    void (*final_check)(unsigned int flags);

    /* Prints out the match iff non-NULL: put space at end */
    /* ip is struct ipt_ip * for example */
    void (*print)(const void *ip,
              const struct xt_entry_match *match, int numeric);

    /* Saves the match info in parsable form to stdout. */
    /* ip is struct ipt_ip * for example */
    void (*save)(const void *ip, const struct xt_entry_match *match);

    /* Print match name or alias */
    const char *(*alias)(const struct xt_entry_match *match);

    /* Pointer to list of extra command-line options */
    const struct option *extra_opts;

    /* New parser */
    void (*x6_parse)(struct xt_option_call *);
    void (*x6_fcheck)(struct xt_fcheck_call *);
    const struct xt_option_entry *x6_options;

    /* Translate iptables to nft */
    int (*xlate)(struct xt_xlate *xl,
             const struct xt_xlate_mt_params *params);

    /* Size of per-extension instance extra "global" scratch space */
    size_t udata_size;

    /* Ignore these men behind the curtain: */
    void *udata;
    unsigned int option_offset;
    struct xt_entry_match *m;
    unsigned int mflags;
    unsigned int loaded; /* simulate loading so options are merged properly */
};

// libxt_tcp.c注册内容
static struct xtables_match tcp_match = { 
    .family     = NFPROTO_UNSPEC,
    .name       = "tcp",
    .version    = XTABLES_VERSION,
    .size       = XT_ALIGN(sizeof(struct xt_tcp)),
    .userspacesize  = XT_ALIGN(sizeof(struct xt_tcp)),
    .help       = tcp_help,
    .init       = tcp_init,
    .parse      = tcp_parse,
    .print      = tcp_print,
    .save       = tcp_save,
    .extra_opts = tcp_opts,
    .xlate      = tcp_xlate,
};


// 注册函数
void xtables_register_match(struct xtables_match *me) 
{
    if (me->next) {
        fprintf(stderr, "%s: match \"%s\" already registered\n",
            xt_params->program_name, me->name);
        exit(1);
    }    

    if (me->version == NULL) {
        fprintf(stderr, "%s: match %s<%u> is missing a version\n",
                xt_params->program_name, me->name, me->revision);
        exit(1);
    }    

    if (me->size != XT_ALIGN(me->size)) {
        fprintf(stderr, "%s: match \"%s\" has invalid size %u.\n",
                xt_params->program_name, me->name,
                (unsigned int)me->size);
        exit(1);
    }    

    if (strcmp(me->version, XTABLES_VERSION) != 0) { 
        fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
                "but \"%s\" is required.\n",
            xt_params->program_name, me->name,
            me->version, XTABLES_VERSION);
        exit(1);
    }    

    if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
        fprintf(stderr, "%s: match `%s' has invalid name\n",
            xt_params->program_name, me->name);
        exit(1);
    }    

    if (me->real_name && strlen(me->real_name) >= XT_EXTENSION_MAXNAMELEN) {
        fprintf(stderr, "%s: match `%s' has invalid real name\n",
            xt_params->program_name, me->real_name);
        exit(1);
    }    

    if (me->family >= NPROTO) {
        fprintf(stderr,
            "%s: BUG: match %s has invalid protocol family\n",
            xt_params->program_name, me->name);
        exit(1);
    }

    if (me->x6_options != NULL)
        xtables_option_metavalidate(me->name, me->x6_options);
    if (me->extra_opts != NULL)
        xtables_check_options(me->name, me->extra_opts);

/* 将xtables_match放置到xtables_pending_matches的头部
   (在xtables_find_match中通过xtables_pending_match链表进行查找,并进行注册)*/
    /* place on linked list of matches pending full registration */
    me->next = xtables_pending_matches;
    xtables_pending_matches = me;
}
// (b)以下为iptables接收到command进行match相关的解析
// 对于match的data数据格式在成员声明时指定了大小 {.size = XT_ALIGN(sizeof(struct xt_tcp)),}
// 在do_command4的default中进行command_defult会进行解析match,将dport放入match(struct xt_tcp)中。

(2-2-3)
// cs.target构建



1758     case CMD_INSERT:
1759         ret = insert_entry(chain, e, rulenum - 1, // chain 通过参数I后的值(optarg)
1760                    nsaddrs, saddrs, smasks,
1761                    ndaddrs, daddrs, dmasks,
1762                    cs.options&OPT_VERBOSE,
1763                    *handle); // 此处的handle可以通过iptc_init(表名)获取

 646 static int
 647 insert_entry(const xt_chainlabel chain,
 648          struct ipt_entry *fw,
 649          unsigned int rulenum,
 650          unsigned int nsaddrs,
 651          const struct in_addr saddrs[],
 652          const struct in_addr smasks[],
 653          unsigned int ndaddrs,
 654          const struct in_addr daddrs[],
 655          const struct in_addr dmasks[],
 656          int verbose,
 657          struct xtc_handle *handle)
 658 {
 659     unsigned int i, j;
 660     int ret = 1;
 661 
 662     for (i = 0; i < nsaddrs; i++) {
 663         fw->ip.src.s_addr = saddrs[i].s_addr;
 664         fw->ip.smsk.s_addr = smasks[i].s_addr;
 665         for (j = 0; j < ndaddrs; j++) {
 666             fw->ip.dst.s_addr = daddrs[j].s_addr;
 667             fw->ip.dmsk.s_addr = dmasks[j].s_addr;
 668             if (verbose)
 669                 print_firewall_line(fw, handle); // 打印log:ACCEPT  tcp opt -- in * out *  192.168.0.124  -> 0.0.0.0/0   tcp dpt:3339
 670             ret &= iptc_insert_entry(chain, fw, rulenum, handle);
 671         }
 672     }
 673 
 674     return ret;
 675 }

有待于后续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值