1、库libiptc
什么是libiptc
如何获取这些知识
文档参考地址:
http://tldp.org/HOWTO/Querying-libiptc-HOWTO/index.html
iptables源代码:
在程序iptables-save.c中,使用libiptc从防火墙内核代码转储信息
安装iptables + libiptc
要安装libiptc,请按照下列步骤操作:
- 从 http://netfilter.samba.org/ 下载iptables-1.2.6.tar.bz2。
- sudo apt-get install iptables-dev和iptables
- 在iptables源码中的libiptc目录中make,获取库文件.lib
- 将./.lib 拷贝到/usr/lib即可
编译时链接该库即可
gcc test.c -l ip4tc
注意:libiptc库需要root权限,才能使用
问题:
编译后的程序,使用root权限执行:
报错iptc_init函数问题:iptables who? (do you need to insmod?)
但是代码没有进行修改,在终端下发一条iptables规则
sudo iptables -D INPUT -p tcp --dport 80 -j REJECT
重新执行,程序正常。
问题原因未找到,怀疑是由于底层iptables模块未启动。导致执行失败。
如何创建程序
编写程序,可以使用以下的库,避免出现找不到函数的情况:
/ *我的节目* /
#include <getopt.h>
#include <sys / errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <time.h>
#include“libiptc / libiptc.h”
#include“iptables.h”
int main(void)
{
/ *总是将此部分用于您的程序....从这里...... **** * /
iptc_handle_t h;
const char * chain = NULL;
const char * tablename = NULL;
program_name =“my_program”;
program_version = NETFILTER_VERSION;
/* .... 到这里 .... ************************************** ****** * /
/ *从这里你编写自己的代码* /
....你的代码......
....
....
}
libiptc的函数介绍
iptc和ip6tc的函数,均由宏定义替代函数名进行的声明。
例如iptc_init
libiptc/libip4tc.c:87:#define TC_INIT iptc_init
然后iptc_init的具体实现为
libiptc/libiptc.c:1302:TC_INIT(const char *tablename)
查询类函数
iptc_init和iptc_free
函数原型:
struct xtc_handle *iptc_init(const char *tablename);
void iptc_free(struct xtc_handle *h);
其中:#define iptc_handle xtc_handle
函数功能:
iptc_init函数获取rules的快照。如果出现错误,return NULL。该函数必须在调用任何其他函数之前调用
参数:
tablename是我们需要查询或修改的表的名称; 这可能是filter, mangle,nat以及raw。
返回值:
指向iptc_handle_t类型结构的指针,该结构必须用作我们将从libiptc调用的其余函数的主要参数。iptc_init返回指向结构的指针,如果失败则返回NULL。如果发生这种情况,您可以调用 iptc_strerror来获取有关错误的信息。
例如:
iptc_free:
iptc_init()函数的清除函数,与iptc_free()对应使用
函数原型:
const char *iptc_strerror(int err);
函数功能:
将错误码转化为易读形式
描述:
该函数返回iptc库中失败代码的更有意义的解释。如果函数失败,它将始终设置 errno。可以将此值传递给 iptc_strerror()以生成错误消息。
参数:
err是一个表示错误号的整数。
返回:
包含错误描述的Char指针。
函数原型:
const char *iptc_first_chain(struct xtc_handle *handle);
函数功能:
函数返回表中的第一个链名称。
参数:
指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
指向链名称的Char指针。
函数原型:
const char *iptc_next_chain(struct xtc_handle *handle);
函数功能:
获取下一个链
参数:
指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
指向链名称的Char指针。
函数原型:
int iptc_is_chain(const char *chain, struct xtc_handle *const handle);
函数功能:
检查chain是否存在
参数:
chain:需要检查的是否存在的链
handle:iptc_init函数提供的指向表的指针
返回值:
存在 return 1;不存在 return 0
函数原型:
int iptc_builtin(const char *chain, struct xtc_handle *const handle);
函数功能:
检测chain是否为内置链。
参数:
chain:链
handle:iptc_init函数提供的指向表的指针
返回值:
如果给定的链名是内置链,则返回整数值1(true); 不是, 返回整数值0(false)
函数原型:
const struct ipt_entry *iptc_first_rule(const char *chain,
struct xtc_handle *handle);
函数功能:
获取指定链中的第一条规则。如果是空链,则返回NULL
函数原型:
const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev,
struct xtc_handle *handle);
函数功能:
获取指定链的下一条规则。
返回值:
返回指定链中的下一条规则的指针;返回NULL表示链的末尾
函数原型:
const char *iptc_get_target(const struct ipt_entry *e,
struct xtc_handle *handle);
函数功能:
由于内置链的存在,我们不知道是返回一个动作还是一个内置链
该函数获取给定规则的目标。如果它是扩展目标,则返回该目标的名称。如果是跳转到另一个链,则返回该链的名称。如果是判决(例如DROP),则返回该名称。如果它没有目标(会计样式规则),则返回空字符串。请注意,应该使用此函数而不是直接使用ipt_entry结构的verdict字段 的值,因为它提供了对标准判定的上述进一步解释。
参数:
e是指向ipt_entry类型结构的指针,该结构 必须首先通过先前调用函数iptc_first_rule或函数 iptc_next_rule获得。
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
返回指向目标名称的char指针。
iptc_get_policy
函数原型:
const char *iptc_get_policy(const char *chain,
struct xt_counters *counter,
struct xtc_handle *handle);
函数功能:
此函数获取内置链的策略,并使用该策略的命中统计信息填充 counters参数。
参数:
您必须将要获取策略的内置链的名称作为参数传递,指向要 由函数填充的ipt_counters结构的指针以及标识我们正在处理的表的 iptc_handle_t结构。
该ipt_counters结构在前面的部分进行了说明; 不要忘记iptc_handle_t 必须通过先前调用函数iptc_init获得。
返回:
返回指向策略名称的char指针。
函数原型:
struct xt_counters *iptc_read_counter(const xt_chainlabel chain,
unsigned int rulenum,
struct xtc_handle *handle);
函数功能:
此函数读取并返回位于 rulenum的链链中的条目规则的数据包和字节计数器。计数器返回指向类型结构ipt_counters的指针。第一条规则的规则编号从1开始。
参数:
chain是一个指向要被加入的链名称的char指针;
rulenum是一个整数值,定义了规则链中的位置,该计数器将被读取。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:返回指向ipt_counters结构的指针,该结构包含已加入的字节和数据包计数器。
修改防火墙规则和统计信息的函数
函数原型:
int iptc_commit(struct xtc_handle *handle);
函数功能:
提交修改。在调用iptc_commit()函数之前,不会写回您更改的表 。这意味着在同一链上运行的两个库用户可以相互竞争; 需要锁定以防止这种情况,目前尚未完成。然而,没有与柜台比赛; 计数器以这样的方式重新添加到内核中,即表的读取和写入之间的计数器增量仍然显示在新表中。要保护系统状态,您必须提交更改。(功能类似git commit)
参数:
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_insert_entry(const xt_chainlabel chain,
const struct ipt_entry *e,
unsigned int rulenum,
struct xtc_handle *handle);
函数功能:
在链中插入新规则。插入ipt_entry到序号为rulenum的位置
参数:
chain是一个指向要修改的链名称的char指针;
e是指向ipt_entry类型结构的指针,该结构 包含有关要插入的规则的信息。程序员必须在将指针作为参数传递给函数之前,使用定义其规则所需的值填充此结构的字段。
rulenum是一个整数值,定义了将插入新规则的规则链中的位置。第一条规则的规则编号从1开始。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
iptc_check_entry
/* Check whether a mathching rule exists */
函数原型
int iptc_check_entry(const xt_chainlabel chain,
const struct ipt_entry *origfw,
unsigned char *matchmask,
struct xtc_handle *handle);
函数功能:
检查规则是否已经存在
函数原型:
int iptc_replace_entry(const xt_chainlabel chain,
const struct ipt_entry *e,
unsigned int rulenum,
struct xtc_handle *handle);
函数功能:
使用新规则替换序号为rulenum旧规则。第一条规则序号为1
参数:
chain是一个指向要修改的链名称的char指针;
e是指向ipt_entry类型结构的指针,该结构 包含有关要插入的规则的信息。程序员必须在将指针作为参数传递给函数之前,使用定义其规则所需的值填充此结构的字段。
rulenum是一个整数值,定义了规则链中的位置,旧规则将被新规则替换。第一条规则的规则编号从1开始。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_append_entry(const xt_chainlabel chain,
const struct ipt_entry *e,
struct xtc_handle *handle);
函数功能:
此函数在链链中附加在结构类型ipt_entry中定义的规则 (相当于使用rulenum = chain of length的insert)。
参数:
chain是一个指向要修改的链名称的char指针;
e是指向ipt_entry类型结构的指针,该结构 包含有关要追加的规则的信息。程序员必须在将指针作为参数传递给函数之前,使用定义其规则所需的值填充此结构的字段。
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)
iptc_delete_entry
/* Delete the first rule in `chain' which matches `e', subject to
matchmask (array of length == origfw) */
函数原型
int iptc_delete_entry(const xt_chainlabel chain,
const struct ipt_entry *origfw,
unsigned char *matchmask,
struct xtc_handle *handle);
函数功能:
删除与指定ipt_entry的匹配掩码(matchmask)部分相同的rules
函数原型:
int iptc_delete_num_entry(const xt_chainlabel chain,
unsigned int rulenum,
struct xtc_handle *handle);
函数功能:
此函数删除位于rulenum的链链中的输入规则。第一条规则的规则编号从1开始。
参数:
. chain是一个指向要修改的链名称的char指针;
rulenum是一个整数值,用于定义规则链中将删除规则的位置。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_flush_entries(const xt_chainlabel chain,
struct xtc_handle *handle);
函数功能:
清空指定链
参数:
chain是指向要刷新的链的名称的char指针;
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_zero_entries(const xt_chainlabel chain,
struct xtc_handle *handle);
函数功能:
将给定链的计数器归零
参数:
chain是指向链名称的char指针,计数器将为零;
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_create_chain(const xt_chainlabel chain,
struct xtc_handle *handle);
函数功能:
在给定的表中创建一条新链
参数:
chain是一个指向要创建的链名称的char指针;
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_delete_chain(const xt_chainlabel chain,
struct xtc_handle *handle);
函数功能:
删除指定表中的指定链
参数:
chain是指向要删除的链名称的char指针;
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_rename_chain(const xt_chainlabel oldname,
const xt_chainlabel newname,
struct xtc_handle *handle);
函数功能:
将指定的表中的指定链重新命名为newname
参数:
oldname是一个char指针,指向要重命名的链的名称,
newname是新名称;
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_set_policy(const xt_chainlabel chain,
const xt_chainlabel policy,
struct xt_counters *counters,
struct xtc_handle *handle);
函数功能:
在内置链中设置策略。这个函数在链中的策略由字符指针所代表的policy。如果要同时设置链的计数器,请在ipt_counters类型的结构中填充这些值,并将指针作为参数计数器传递给它。注意:链条 必须是内置链条。
参数:
chain是一个指向要修改的链名称的char指针;
policy是指向要设置的策略名称的char指针。
计数器是一个指向 ipt_counters结构要被用于设置链的计数器。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_zero_counter(const xt_chainlabel chain,
unsigned int rulenum,
struct xtc_handle *handle);
函数功能:
将指定表中的指定链的指定规则的计数器清零
参数:
chain是一个指向要修改的链名称的char指针;
rulenum是一个整数值,定义了规则链中的位置,计数器将为零。
handle是指向iptc_handle_t类型结构的指针,该结构 是通过先前调用 iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
函数原型:
int iptc_set_counter(const xt_chainlabel chain,
unsigned int rulenum,
struct xt_counters *counters,
struct xtc_handle *handle);
函数功能:
设置指定的表中的指定链的指定规则的包和字节的计数器
参数:
chain是一个指向要修改的链名称的char指针;
rulenum是一个整数值,定义了规则链中的位置,计数器将被设置。
计数器是一个指向一个 ipt_counters要使用结构来设置规则中的计数器; 程序员必须用要设置的值填充此结构的字段。
handle是指向iptc_handle_t类型结构的指针,该结构是通过先前调用iptc_init获得的。
返回:
如果成功则返回整数值1(true); 如果失败,则返回整数值0(false)。在这种情况下,errno设置为生成的错误号。使用iptc_strerror获取有关该问题的有用信息。如果errno == 0,则表示存在版本错误(即升级libiptc)。
iptc_get_references
/* Get the number of references to this chain */
函数原型:
int iptc_get_references(unsigned int *ref,
const xt_chainlabel chain,
struct xtc_handle *handle);
函数功能:
获取对应链的引用次数
iptc_get_raw_socket
/* Get raw socket. */
函数原型
int iptc_get_raw_socket(void);
函数功能:
获取原始套接字
libiptc的重要结构体
几个重要的结构体的定义在iptables/libiptc/libiptc.c和libiptc.h文件中。
struct xtc_handle
#define iptc_handle xtc_handle
struct xtc_handle {
int sockfd;
int changed; /* Have changes been made? */
struct list_head chains;
struct chain_head *chain_iterator_cur;
struct rule_head *rule_iterator_cur;
unsigned int num_chains; /* number of user defined chains */
struct chain_head **chain_index; /* array for fast chain list access*/
unsigned int chain_index_sz;/* size of chain index array */
int sorted_offsets; /* if chains are received sorted from kernel,
* then the offsets are also sorted. Says if its
* possible to bsearch offsets using chain_index.
*/
STRUCT_GETINFO info;
STRUCT_GET_ENTRIES *entries;
};
struct ipt_entry
struct ipt_entry {
struct ipt_ip ip;
/* Mark with fields that we care about. */
unsigned int nfcache;
/* Size of ipt_entry + matches */
__u16 target_offset;
/* Size of ipt_entry + matches + target */
__u16 next_offset;
/* Back pointer */
unsigned int comefrom;
/* Packet and byte counters. */
struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
};
struct ipt_ip
struct ipt_ip {
/* Source and destination IP addr */
struct in_addr src, dst;
/* Mask for src and dest IP addr */
struct in_addr smsk, dmsk;
char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
/* Protocol, 0 = ANY */
__u16 proto;
/* Flags word */
__u8 flags;
/* Inverse flags */
__u8 invflags;
};
struct xt_counters
struct xt_counters {
__u64 pcnt, bcnt; /* Packet and byte counters */
};
rule下发
规则下发可以参考:http://lib.csdn.net/article/linux/56211
Linux c/c++编程使用 libiptc库下发规则可以代替system调用 iptables 命令方法,可以满足程序中批量地创建连接所需的批量增加、删除iptables规则;
但是使用步骤确实比较繁琐,得注意iptables版本的问题,编译相关库需要“-lip4tc” “-lxtables”,头文件需要“libiptc/libiptc.h” “net/netfilter/nf_nat.h” “iptables.h”;需要填写多个结构体,操作复杂。
而且实验结果表明,当多进程高频率得操作iptables时,system 和 libiptc 均会出现 “Resource temporarily unavailable” 错误,建议进行返回值判定和多进程的加锁保护;
操作较少时,建议采用popen或者system进行操作。
system和popen的不同:
system和popen都是执行了类似的运行流程,大致是fork->execl->return。
system在执行期间调用进程会一直等待shell命令执行完成(waitpid等待子进程结束)才返回。
popen无须等待shell命令执行完成就返回了。
我们可以理解system为串行执行,在执行期间调用进程放弃了”控制权”,popen为并行执行。
popen中的子进程没人给它”收尸”了啊?是的,如果你没有在调用popen后调用pclose那么这个子进程就可能变成”僵尸”
3、下发entry(IPv4)
entry主要的难点在于ipt_entry的封装。
match可以是多个
封装结构如图所示。对于自定义的结构体,应该使用iptables/include/linux/netfilter下的文件定义的结构体。
例如,
使用mac匹配规则:xt_mac.h
使用udp或者tcp匹配:xt_tcpudp.h
使用物理接口匹配:xt_physdev.h
首先匹配的应该是ipt_entry中的ipt_ip字段。如果ipt_ip中的protocol字段为0,表示任何协议都可以通过,(协议定义在linux的in.h文件中);进一步与自定义的match进行匹配,例如mac匹配。
struct ipt_entry
struct ipt_entry {
struct ipt_ip ip;
unsigned int nfcache;
__u16 target_offset; /* Size of ipt_entry + matches */
__u16 next_offset; /* Size of ipt_entry + matches + target */
unsigned int comefrom;/* 后退指针 */
struct xt_counters counters;/* 报文和字节计数 */
unsigned char elems[0];/* match和target ,可以是多个match */
};
该结构体用于每个防火墙规则的定义。包含三部分
- 通用的ip头
- match,匹配
- target,处理
其中的ipt_ip结构体如下:
struct ipt_ip {
/* Source and destination IP addr */
struct in_addr src, dst;
/* Mask for src and dest IP addr */
struct in_addr smsk, dmsk;
char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
/* Protocol, 0 = ANY */
__u16 proto;
/* Flags word */
__u8 flags;
/* Inverse flags */
__u8 invflags;
};
其中的protocol字段的所有定义在in.h中有定义。
/* Standard well-defined IP protocols. */
enum {
IPPROTO_IP = 0, /* Dummy protocol for TCP */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
#define IPPROTO_IGMP IPPROTO_IGMP
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
#define IPPROTO_IPIP IPPROTO_IPIP
IPPROTO_TCP = 6, /* Transmission Control Protocol */
#define IPPROTO_TCP IPPROTO_TCP
IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
#define IPPROTO_EGP IPPROTO_EGP
IPPROTO_PUP = 12, /* PUP protocol */
#define IPPROTO_PUP IPPROTO_PUP
IPPROTO_UDP = 17, /* User Datagram Protocol */
#define IPPROTO_UDP IPPROTO_UDP
IPPROTO_IDP = 22, /* XNS IDP protocol */
#define IPPROTO_IDP IPPROTO_IDP
IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */
#define IPPROTO_TP IPPROTO_TP
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
#define IPPROTO_DCCP IPPROTO_DCCP
IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
#define IPPROTO_IPV6 IPPROTO_IPV6
IPPROTO_RSVP = 46, /* RSVP Protocol */
#define IPPROTO_RSVP IPPROTO_RSVP
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
#define IPPROTO_GRE IPPROTO_GRE
IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
#define IPPROTO_ESP IPPROTO_ESP
IPPROTO_AH = 51, /* Authentication Header protocol */
#define IPPROTO_AH IPPROTO_AH
IPPROTO_MTP = 92, /* Multicast Transport Protocol */
#define IPPROTO_MTP IPPROTO_MTP
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */
#define IPPROTO_BEETPH IPPROTO_BEETPH
IPPROTO_ENCAP = 98, /* Encapsulation Header */
#define IPPROTO_ENCAP IPPROTO_ENCAP
IPPROTO_PIM = 103, /* Protocol Independent Multicast */
#define IPPROTO_PIM IPPROTO_PIM
IPPROTO_COMP = 108, /* Compression Header Protocol */
#define IPPROTO_COMP IPPROTO_COMP
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
#define IPPROTO_SCTP IPPROTO_SCTP
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
#define IPPROTO_UDPLITE IPPROTO_UDPLITE
IPPROTO_RAW = 255, /* Raw IP packets */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MAX
};
struct ipt_entry_target
#define ipt_entry_target xt_entry_target
struct xt_entry_target {
union {
struct {
__u16 target_size;/* target的长度 */
char name[XT_EXTENSION_MAXNAMELEN];/* chainname */
__u8 revision;
} user;
struct {
__u16 target_size; /* target的长度 */
struct xt_target *target;
} kernel;
__u16 target_size;
} u;
unsigned char data[0];/* 指向自定义的target */
};
struct ipt_entry_match
#define ipt_entry_match xt_entry_match
struct xt_entry_match {
union {
struct {
__u16 match_size;
char name[XT_EXTENSION_MAXNAMELEN];
__u8 revision;
} user;
struct {
__u16 match_size;
struct xt_match *match;
} kernel;
__u16 match_size;
} u;
unsigned char data[0];/* 指向自定义的match */
};
初学libiptc
如果不清楚如何使用libiptc下发想要的规则。可以在iptables中的generate_entry函数中加入log。打印entry信息。
然后使用iptables下发想要的规则。获取entry信息。
然后根据entry信息,自定义封装规则。
代码例程
http://github.com/hanfs390/iptables_hfs