标签:
上周,一名医生在儿童医院等待一段差距叫做数量。接受NetfilterPush信息的邮件列表,列表ipset最新6.23版本号的新功能,非常喜欢我现在需要的是,特别是timeout和skbinfo支持参数,欲了解更多详情,请参阅自己manual,假设不想看那么多,我这里简单的贴一下:
timeout总之,相比較老版本号的4.5。确实添加了不少新的东西,于是就迫不及待地下载。编译。试用,一般而言,这些步骤都是例行的。都不会遇到什么特别大的困难,特别是看了其README之后:
0. You need the source tree of your kernel (version >= 2.6.32)#ifdef HAVE_CHECKENTRY_BOOL #define CHECK_OK 1 #define CHECK_FAIL(err) 0 #define CONST const #define FTYPE bool #define XT_PAR_NET(par) NULL #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */ #define CHECK_OK 0 #define CHECK_FAIL(err) (err) #define CONST #define FTYPE int #define XT_PAR_NET(par) (par)->net #endif非常显然,依据凝视,我应该定义HAVE_CHECKENTRY_BOOL,可是这个宏的定义应该自己主动化才合理,全然不应该去手工干预。在configure文件里,发现了以下的定义语句:
if test -f $ksourcedir/net/netfilter/xt_state.c && $GREP -q ‘bool state_mt_check‘ $ksourcedir/net/netfilter/xt_state.c; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } HAVE_CHECKENTRY_BOOL=define else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } HAVE_CHECKENTRY_BOOL=undef fi注意$ksourcedir/net/netfilter/xt_state.c这个万恶的语句,我顿时火冒三丈,指定源代码文件就是为了在这个文件里寻找match check回调函数的返回值类型,作者难道不能通过内核的版本号号还区分吗?难道对于一个固定的内核版本号,match check的返回值规范不是固定的吗?对于2.6.32内核,以下的调用难道能够改变吗?:
if (par->target->checkentry != NULL && !par->target->checkentry(par)) return -EINVAL;我非常生气。但我不能强求开源软件一定怎么怎么样,就像比尔.盖茨以前说的那样。得不到酬劳的程序猿是写不出一流的软件的,这一点我略微有点信了。
好吧。我指定一定源代码文件,让configure的过程去定义那个万恶的HAVE_CHECKENTRY_BOOL宏。值得注意的是,除了那个宏之外,起到同样的旨在不同内核版本号间适配作用的另一个宏:HAVE_XT_TARGET_PARAM。它的作用是在未定义xt_action_param结构体的低版本号内核中将其定义为xt_target_param。在必要的时候强转成xt_match_param。定义了这两个宏之后,xt_set编译通过,可是ipset内核模块本身却报错了。而这个ipset内核模块本身是要比xt_set更重要的,要知道xt_set仅仅是一个和iptables联动时所用的模块,即便真的无法适配。自己写一个应该也不难,然而对于ipset本身的内核模块。假设要自己写,那就相当于自己实现ipset-6.23本身了...还好。这次的新错误不多:
CC [M] /usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.o
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c: In function ‘call_ad‘:
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c:1444: error: ‘SIZE_MAX‘ undeclared (first use in this function)
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c:1444: error: (Each undeclared identifier is reported only once
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c:1444: error: for each function it appears in.)
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c:1444: warning: type defaults to ‘int‘ in declaration of ‘_min1‘
/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.c:1444: warning: comparison of distinct pointer types lacks a cast
make[4]: *** [/usr/src/ipset-6.23/kernel/net/netfilter/ipset/ip_set_core.o] 错误 1
说的是SIZE_MAX未定义。这个常量在3.5以上的高版本号内核上才有,2.6.32假设不手工定义的话依据不能编译通过,尽管手工定义一下并不难,可是越发认为ipset-6.23的编译文档和支持版本号的说明文档就是在不负责任地胡说八道。简直就是在扯淡!。我找到了另外一篇文档。上面明白了一个多少还能说得过去的事实:
2 Supported Configurations
* iptables >= 1.4.3
* kernel-source >= 2.6.29
For ipset-6 you need:
* libmnl
* Linux kernel >= 2.6.35
起码和ipset-6.23源代码中的凝视能对得上。除此之外也是在胡扯。
这个事实太恶心人了啊!我定义了SIZE_MAX之后,编译就能够顺利通过了,尽管有一些类型转换的警告,可是忽略它们并不会有什么大不了的后果。于是我认为为了让ipset-6.23自带的文档更好地服务大众,有必要做一个真正的patch,其实我确实这么做了,我想做的事情有以下的目标:
1.编译ipset-6.23仅仅依赖内核头文件而不再依赖源代码。
2.依赖内核版本号而适配数据结构和宏定义而不是在内核源代码中找特征值。
因为我的目标仅仅是在2.6.32内核上编译成功,因为我并没有測试2.6.33/34/35/36以及3.0/1/2/3/4/5/6/7/8...但我相信,3.5以上的内核版本号上是一定能够成功编译的。
ipset-6.23的打包者可能根本就没有在低版本号比方2.6.32内核上进行測试。这个工作以及紧随其后的修正工作或许本来就是留给我这种人的,再者说。2.6.32这个版本号或许使用的人本来就不多,不提供全訪问的支持也是理所当然。我并没有怪作者和打包者的意思,或许在修正过程中确实有些冲动。所以在此澄清。
这让人想起了时尚这个名词,这是在19世纪末粗放的工业化达到顶峰时诞生的一个词。人们普遍认为,进步是必定的,最新的就是最好的,变化的向前的,速度是加快的,保持时尚的方式就是站在潮流最前端。这个理念被普遍信奉和传承,一直到Linux 3.X内核时代...假设你还在用2.6.9内核,并且发现了它的一个大bug,没人会理你的。站在潮流最前端的冲浪者会说:世界在进步,为何不试试3.17版本号的内核呢?。
直接进入ipset-6.23文件夹,运行patch -p1 < ../ipset-6.23.patch就可以,而ipset-6.23.patch的内容例如以下:
diff -Nur ipset-6.23/kernel/include/linux/netfilter/ipset/ip_set.h ipset-6.23.new/kernel/include/linux/netfilter/ipset/ip_set.h --- ipset-6.23/kernel/include/linux/netfilter/ipset/ip_set.h 2014-09-23 19:18:34.000000000 +0800 +++ ipset-6.23.new/kernel/include/linux/netfilter/ipset/ip_set.h 2014-11-13 16:27:15.000000000 +0800 @@ -26,6 +26,9 @@ #define IP_SET_MODULE_DESC(a, b, c) _IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c)) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) +#define SIZE_MAX (~(size_t)0) +#endif /* Set features */ enum ip_set_feature { IPSET_TYPE_IP_FLAG = 0, diff -Nur ipset-6.23/kernel/net/netfilter/xt_set.c ipset-6.23.new/kernel/net/netfilter/xt_set.c --- ipset-6.23/kernel/net/netfilter/xt_set.c 2014-09-23 19:18:34.000000000 +0800 +++ ipset-6.23.new/kernel/net/netfilter/xt_set.c 2014-11-13 16:26:50.000000000 +0800 @@ -28,12 +28,18 @@ MODULE_ALIAS("ipt_SET"); MODULE_ALIAS("ip6t_SET"); -#ifdef HAVE_CHECKENTRY_BOOL +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) #define CHECK_OK 1 #define CHECK_FAIL(err) 0 #define CONST const #define FTYPE bool +/* Only confirm version 2.6.32 :) */ +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,32) +/* netns is not supported completly */ +#define XT_PAR_NET(par) (&init_net) +#else #define XT_PAR_NET(par) NULL +#endif #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */ #define CHECK_OK 0 #define CHECK_FAIL(err) (err) @@ -217,7 +223,7 @@ /* Revision 0 interface: backward compatible with netfilter/iptables */ -#ifdef HAVE_XT_TARGET_PARAM +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) #undef xt_action_param #define xt_action_param xt_target_param #define CAST_TO_MATCH (const struct xt_match_param *)
struct net { ... struct net_generic *gen; }值得注意的是gen字段:
struct net_generic { unsigned int len; struct rcu_head rcu; void *ptr[0]; };我们看一下它的凝视:
/* * Generic net pointers are to be used by modules to put some private * stuff on the struct net without explicit struct net modification * * The rules are simple: * 1. register the ops with register_pernet_gen_device to get the id * of your private pointer; * 2. call net_assign_generic() to put the private data on the struct * net (most preferably this should be done in the ->init callback * of the ops registered); * 3. do not change this pointer while the net is alive; * 4. do not try to have any private reference on the net_generic object. * * After accomplishing all of the above, the private pointer can be * accessed with the net_generic() call. */
static inline struct ip_set_net *ip_set_pernet(struct net *net) { return net_generic(net, ip_set_net_id); }这样就会导致panic崩溃。因此这个原始的代码根本就不可能在HAVE_CHECKENTRY_BOOL宏被定义了的时候使用。因为net为空,假设推断了,内核不会崩溃,可是却取不到不论什么数据,假设没有推断,内核就会崩溃。因此这个代码本身能够说是错误的!
仅仅会编程的人是惹不起的。
别的不说。反正我是看着README操作的。上面写了>=2.6.32的都能够,然而我就是没法编译,confiure里面的办法真的非常恶心。
反正不正确写入!。。跟风TMD不行。!
!
版权声明:本文博主原创文章,博客,未经同意不得转载。
至Linux-2.6.32编译内核ipset-6.23坎坷的经历
标签:
原文地址:http://www.cnblogs.com/gcczhongduan/p/4844601.html