最近使用openwrt 的 apache ,移植到全志H3 平台。
编译一切正常,实际运行时打开网页总是报错 500 Internal Server Error:
查看 /var/log/error_log 如下:(需要将 http.conf 的 LogLevel 设为 debug )
root@172:/# cat /var/log/error_log
[Tue Jul 23 07:01:50.739491 2019] [core:debug] [pid 2542] protocol.c(917): [client 172.16.0.158:25524] AH02418: HTTP Request Line; Unrecognized protocol ‘HTTP/0.9’ (perhaps whitespace was injected?)
[Tue Jul 23 07:01:50.740507 2019] [http:error] [pid 2542] [client 172.16.0.158:25524] AH02429: Response header name ‘Content-Length’ contains invalid characters, aborting request
[Tue Jul 23 07:01:50.992364 2019] [core:debug] [pid 2542] protocol.c(917): [client 172.16.0.158:25525] AH02418: HTTP Request Line; Unrecognized protocol ‘HTTP/0.9’ (perhaps whitespace was injected?)
[Tue Jul 23 07:01:50.992502 2019] [http:error] [pid 2542] [client 172.16.0.158:25525] AH02429: Response header name ‘Content-Length’ contains invalid characters, aborting request
AH02418: HTTP Request Line; Unrecognized protocol ‘HTTP/0.9’ (perhaps whitespace was injected?)
我用的apache 版本是 2.4.37 。
使用 gdb 调试跟踪代码:
分析代码含义,按正常流程的话到运行到 793 行,之后应该进入794行,但是从gdb 调试结果来看,并没有,问题就出在这。
重点分析 793 行的 ap_scan_vchar_obstext 函数。
//位于 httpd-2.4.37\server\util.c
/* Scan a string for visible ASCII (0x21-0x7E) or obstext (0x80+)
* and return a pointer to the first ctrl/space character encountered.
*/
AP_DECLARE(const char *) ap_scan_vchar_obstext(const char *ptr)
{
for ( ; TEST_CHAR(*ptr, T_VCHAR_OBSTEXT); ++ptr) ;
return ptr;
}
TEST_CHAR 是个宏定义
#include "test_char.h"
/* we assume the folks using this ensure 0 <= c < 256... which means
* you need a cast to (unsigned char) first, you can't just plug a
* char in here and get it to work, because if char is signed then it
* will first be sign extended.
*/
#define TEST_CHAR(c, f) (test_char_table[(unsigned char)(c)] & (f))
test_char_table 的定义位于 test_char.h 中
正常在x86 linux 中 test_char.h 是在编译过程中执行 gen_test_char > test_char.h 自动生成的。
而在opwert 中使用交叉编译 ,编出来的gen_test_char 是不能在 x86 linux 上运行的,所以openwrt 中使用了 打补丁的方式。它的补丁位于 openwrt\feeds\packages\net\apache\patches\002-test_char_h.patch
Index: httpd-2.4.25/server/test_char.h
===================================================================
--- /dev/null
+++ httpd-2.4.25/server/test_char.h
@@ -0,0 +1,23 @@
+/* this file is automatically generated by gen_test_char, do not edit */
+#define T_ESCAPE_SHELL_CMD (1)
+#define T_ESCAPE_PATH_SEGMENT (2)
+#define T_OS_ESCAPE_PATH (4)
+#define T_HTTP_TOKEN_STOP (8)
+#define T_ESCAPE_LOGITEM (16)
+#define T_ESCAPE_FORENSIC (32)
+
+static const unsigned char test_char_table[256] = {
+ 32,62,62,62,62,62,62,62,62,62,63,62,62,62,62,62,62,62,62,62,
+ 62,62,62,62,62,62,62,62,62,62,62,62,14,0,23,6,1,38,1,1,
+ 9,9,1,0,8,0,0,10,0,0,0,0,0,0,0,0,0,0,40,15,
+ 15,8,15,15,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,15,31,15,7,0,7,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,15,39,15,1,62,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
+ 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54
+};
这跟使用 gen_test_char 生成的是否一致呢?
把 gen_test_char 拷贝到 H3 的板子的 /usr/sbin,运行看一下:
root@172:/# gen_test_char
/* this file is automatically generated by gen_test_char, do not edit */
#define T_ESCAPE_SHELL_CMD (1)
#define T_ESCAPE_PATH_SEGMENT (2)
#define T_OS_ESCAPE_PATH (4)
#define T_HTTP_TOKEN_STOP (8)
#define T_ESCAPE_LOGITEM (16)
#define T_ESCAPE_FORENSIC (32)
#define T_ESCAPE_URLENCODED (64)
#define T_HTTP_CTRLS (128)
#define T_VCHAR_OBSTEXT (256)
static const unsigned short test_char_table[256] = {
0x0a8,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
0x0fe,0x07e,0x0ff,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
0x00e,0x140,0x15f,0x146,0x141,0x166,0x141,0x141,
0x149,0x149,0x101,0x140,0x148,0x100,0x100,0x14a,
0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x168,0x14b,0x14f,0x148,0x14f,0x14f,
0x148,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x14f,0x15f,0x14f,0x147,0x100,
0x147,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
0x100,0x100,0x100,0x14f,0x167,0x14f,0x141,0x0fe,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e
};
结果果然不一样!!!!问题就出在这!!!!
所以需要修改openwrt\feeds\packages\net\apache\patches\002-test_char_h.patch 文件,openwrt 可以使用quilt 进行补丁修改,这里不具体介绍修改补丁的方法,直接附上我改好的 002-test_char_h.patch
--- /dev/null
+++ b/server/test_char.h
@@ -0,0 +1,45 @@
+/* this file is automatically generated by gen_test_char, do not edit */
+#define T_ESCAPE_SHELL_CMD (1)
+#define T_ESCAPE_PATH_SEGMENT (2)
+#define T_OS_ESCAPE_PATH (4)
+#define T_HTTP_TOKEN_STOP (8)
+#define T_ESCAPE_LOGITEM (16)
+#define T_ESCAPE_FORENSIC (32)
+#define T_ESCAPE_URLENCODED (64)
+#define T_HTTP_CTRLS (128)
+#define T_VCHAR_OBSTEXT (256)
+
+static const unsigned short test_char_table[256] = {
+ 0x0a8,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
+ 0x0fe,0x07e,0x0ff,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
+ 0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
+ 0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,0x0fe,
+ 0x00e,0x140,0x15f,0x146,0x141,0x166,0x141,0x141,
+ 0x149,0x149,0x101,0x140,0x148,0x100,0x100,0x14a,
+ 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x168,0x14b,0x14f,0x148,0x14f,0x14f,
+ 0x148,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x14f,0x15f,0x14f,0x147,0x100,
+ 0x147,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,
+ 0x100,0x100,0x100,0x14f,0x167,0x14f,0x141,0x0fe,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,
+ 0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e,0x17e
+};
--- a/server/util.c
+++ b/server/util.c
@@ -96,6 +96,16 @@
#undef APLOG_MODULE_INDEX
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
+#define T_ESCAPE_SHELL_CMD (0x01)
+#define T_ESCAPE_PATH_SEGMENT (0x02)
+#define T_OS_ESCAPE_PATH (0x04)
+#define T_HTTP_TOKEN_STOP (0x08)
+#define T_ESCAPE_LOGITEM (0x10)
+#define T_ESCAPE_FORENSIC (0x20)
+#define T_ESCAPE_URLENCODED (0x40)
+#define T_HTTP_CTRLS (0x80)
+#define T_VCHAR_OBSTEXT (0x100)
+
/*
* Examine a field value (such as a media-/content-type) string and return
* it sans any parameters; e.g., strip off any ';charset=foo' and the like.
替换补丁文件后,从新编译,测试结果:
耶!终于OK了!
总结:
AH02418: HTTP Request Line; Unrecognized protocol ‘HTTP/0.9’ (perhaps whitespace was injected?)
问题原因:server/test_char.h 内容不对
解决办法:生成正确的 test_char.h 文件,从新编译
生成正确的 test_char.h 文件方法,拷贝编译目录 httpd-2.x.x/server/gen_test_char 到板子上运行,
其输出结果就是正确的 test_char.h 。