From: Jim Jagielski Date: Mon, 12 Jan 2015 13:39:07 +0000 (+0000) Subject: Merge r1512819, r1513461 (part of it), r1565777, r1643538 from trunk: X-Git-Tag: 2.4.11~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb4a5a5a7b097a8d0f07c829122ec22efc5b8b98;p=thirdparty%2Fapache%2Fhttpd.git Merge r1512819, r1513461 (part of it), r1565777, r1643538 from trunk: * core: Add ap_log_data(), ap_log_rdata(), etc. for logging buffers. Submitted by: Jeff Trawick Reviewed/backported by: jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1651084 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 2e5e08ab5d2..bc1cca8d0ea 100644 --- a/CHANGES +++ b/CHANGES @@ -46,6 +46,9 @@ Changes with Apache 2.4.11 *) mod_ssl: Fix recognition of OCSP stapling responses that are encoded improperly or too large. [Jeff Trawick] + *) core: Add ap_log_data(), ap_log_rdata(), etc. for logging buffers. + [Jeff Trawick] + *) mod_proxy_fcgi, mod_authnz_fcgi: stop reading the response and issue an error when parsing or forwarding the response fails. [Yann Ylavic] diff --git a/STATUS b/STATUS index fcacd3be08f..3f000a9e256 100644 --- a/STATUS +++ b/STATUS @@ -110,16 +110,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK: 2.4.x patch: trunk works +1 jkaluza, ylavic, covener - * core: Add ap_log_data(), ap_log_rdata(), etc. for logging buffers. - trunk patch: http://svn.apache.org/r1512819 - http://svn.apache.org/r1513461 ONLY the change to http_log.h - http://svn.apache.org/r1565777 - http://svn.apache.org/r1643538 - 2.4.x patch: http://people.apache.org/~trawick/ap_log_data-to-2.4.x.txt - (trunk works with the expected minor conflicts in CHANGES - and ap_mmn.h) - +1: trawick, covener, rjung - * mod_autoindex: Fix (add) css attribute for description column when column contains no data. PR 57227. [Bruno Raoult] trunk patch: http://svn.apache.org/r1648201 diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 633e0520518..b8f0bb5343b 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -433,8 +433,9 @@ to util_ldap_connection_t * 20120211.36 (2.4.10-dev) Add ap_copy_scoreboard_worker() * 20120211.37 (2.4.11-dev) Add r->trailers_{in,out} - * 20120211.38 (2.4.10-dev) Added ap_shutdown_conn(). - * 20120211.39 (2.4.10-dev) Add ap_proxy_connect_uds(). + * 20120211.38 (2.4.11-dev) Added ap_shutdown_conn(). + * 20120211.39 (2.4.11-dev) Add ap_proxy_connect_uds(). + * 20120211.40 (2.4.11-dev) Add ap_log_data(), ap_log_rdata(), etc. */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -442,7 +443,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 39 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 40 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_log.h b/include/http_log.h index c5da45136b4..bd0faf7f681 100644 --- a/include/http_log.h +++ b/include/http_log.h @@ -552,6 +552,180 @@ AP_DECLARE(void) ap_log_cserror_(const char *file, int line, int module_index, __attribute__((format(printf,8,9))); #endif +/* + * The buffer logging functions, ap_log_data, ap_log_rdata, ap_log_cdata, + * and ap_log_csdata log a buffer in printable and hex format. The exact + * format is controlled by processing flags, described next. + */ + +/** + * Processing flags for ap_log_data() et al + * + * AP_LOG_DATA_DEFAULT - default formatting, with printable chars and hex + * AP_LOG_DATA_SHOW_OFFSET - prefix each line with hex offset from the start + * of the buffer + */ +#define AP_LOG_DATA_DEFAULT 0 +#define AP_LOG_DATA_SHOW_OFFSET 1 + +/** + * ap_log_data() - log buffers which are not related to a particular request + * or connection. + * @param file The file in which this function is called + * @param line The line number on which this function is called + * @param module_index The module_index of the module logging this buffer + * @param level The log level + * @param s The server on which we are logging + * @param label A label for the buffer, to be logged preceding the buffer + * @param data The buffer to be logged + * @param len The length of the buffer + * @param flags Special processing flags like AP_LOG_DATA_SHOW_OFFSET + * @note ap_log_data is implemented as a macro. + * @note Use APLOG_MARK to fill out file, line, and module_index + * @note If a request_rec is available, use that with ap_log_rdata() + * in preference to calling this function. Otherwise, if a conn_rec is + * available, use that with ap_log_cdata() in preference to calling + * this function. + */ +#ifdef DOXYGEN +AP_DECLARE(void) ap_log_data(const char *file, int line, int module_index, + int level, const server_rec *s, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#else +#ifdef AP_HAVE_C99 +/* need additional step to expand APLOG_MARK first */ +#define ap_log_data(...) ap_log_data__(__VA_ARGS__) +/* need server_rec *sr = ... for the case if s is verbatim NULL */ +#define ap_log_data__(file, line, mi, level, s, ...) \ + do { const server_rec *sr__ = s; if (APLOG_MODULE_IS_LEVEL(sr__, mi, level)) \ + ap_log_data_(file, line, mi, level, sr__, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_data ap_log_data_ +#endif +AP_DECLARE(void) ap_log_data_(const char *file, int line, int module_index, + int level, const server_rec *s, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#endif + +/** + * ap_log_rdata() - log buffers which are related to a particular request. + * @param file The file in which this function is called + * @param line The line number on which this function is called + * @param module_index The module_index of the module logging this buffer + * @param level The log level + * @param r The request which we are logging for + * @param label A label for the buffer, to be logged preceding the buffer + * @param data The buffer to be logged + * @param len The length of the buffer + * @param flags Special processing flags like AP_LOG_DATA_SHOW_OFFSET + * @note ap_log_rdata is implemented as a macro. + * @note Use APLOG_MARK to fill out file, line, and module_index + * @note If a request_rec is available, use that with ap_log_rerror() + * in preference to calling this function. Otherwise, if a conn_rec is + * available, use that with ap_log_cerror() in preference to calling + * this function. + */ +#ifdef DOXYGEN +AP_DECLARE(void) ap_log_rdata(const char *file, int line, int module_index, + int level, const request_rec *r, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#else +#ifdef AP_HAVE_C99 +/* need additional step to expand APLOG_MARK first */ +#define ap_log_rdata(...) ap_log_rdata__(__VA_ARGS__) +#define ap_log_rdata__(file, line, mi, level, s, ...) \ + do { if (APLOG_R_MODULE_IS_LEVEL(r, mi, level)) \ + ap_log_rdata_(file, line, mi, level, r, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_rdata ap_log_rdata_ +#endif +AP_DECLARE(void) ap_log_rdata_(const char *file, int line, int module_index, + int level, const request_rec *r, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#endif + +/** + * ap_log_cdata() - log buffers which are related to a particular connection. + * @param file The file in which this function is called + * @param line The line number on which this function is called + * @param module_index The module_index of the module logging this buffer + * @param level The log level + * @param c The connection which we are logging for + * @param label A label for the buffer, to be logged preceding the buffer + * @param data The buffer to be logged + * @param len The length of the buffer + * @param flags Special processing flags like AP_LOG_DATA_SHOW_OFFSET + * @note ap_log_cdata is implemented as a macro + * @note Use APLOG_MARK to fill out file, line, and module_index + * @note If a request_rec is available, use that with ap_log_rerror() + * in preference to calling this function. Otherwise, if a conn_rec is + * available, use that with ap_log_cerror() in preference to calling + * this function. + */ +#ifdef DOXYGEN +AP_DECLARE(void) ap_log_cdata(const char *file, int line, int module_index, + int level, const conn_rec *c, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#else +#ifdef AP_HAVE_C99 +/* need additional step to expand APLOG_MARK first */ +#define ap_log_cdata(...) ap_log_cdata__(__VA_ARGS__) +#define ap_log_cdata__(file, line, mi, level, c, ...) \ + do { if (APLOG_C_MODULE_IS_LEVEL(c, mi, level)) \ + ap_log_cdata_(file, line, mi, level, c, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_cdata ap_log_cdata_ +#endif +AP_DECLARE(void) ap_log_cdata_(const char *file, int line, int module_index, + int level, const conn_rec *c, const char *label, + const void *data, apr_size_t len, unsigned int flags); +#endif + +/** + * ap_log_csdata() - log buffers which are related to a particular connection + * and to a vhost other than c->base_server. + * @param file The file in which this function is called + * @param line The line number on which this function is called + * @param module_index The module_index of the module logging this buffer + * @param level The log level + * @param c The connection which we are logging for + * @param s The server which we are logging for + * @param label A label for the buffer, to be logged preceding the buffer + * @param data The buffer to be logged + * @param len The length of the buffer + * @param flags Special processing flags like AP_LOG_DATA_SHOW_OFFSET + * @note ap_log_csdata is implemented as a macro + * @note Use APLOG_MARK to fill out file, line, and module_index + * @note If a request_rec is available, use that with ap_log_rerror() + * in preference to calling this function. Otherwise, if a conn_rec is + * available, use that with ap_log_cerror() in preference to calling + * this function. + */ +#ifdef DOXYGEN +AP_DECLARE(void) ap_log_csdata(const char *file, int line, int module_index, + int level, const conn_rec *c, const server_rec *s, + const char *label, const void *data, + apr_size_t len, unsigned int flags); +#else +#ifdef AP_HAVE_C99 +/* need additional step to expand APLOG_MARK first */ +#define ap_log_csdata(...) ap_log_csdata__(__VA_ARGS__) +#define ap_log_csdata__(file, line, mi, level, c, s, ...) \ + do { if (APLOG_CS_MODULE_IS_LEVEL(c, s, mi, level)) \ + ap_log_csdata_(file, line, mi, level, c, s, __VA_ARGS__); \ + } while(0) +#else +#define ap_log_cdata ap_log_cdata_ +#endif +AP_DECLARE(void) ap_log_csdata_(const char *file, int line, int module_index, + int level, const conn_rec *c, const server_rec *s, + const char *label, const void *data, + apr_size_t len, unsigned int flags); +#endif + /** * Convert stderr to the error log * @param s The current server diff --git a/server/log.c b/server/log.c index 9a15d24dbbc..35f4f2ba305 100644 --- a/server/log.c +++ b/server/log.c @@ -1293,6 +1293,21 @@ static void log_error_core(const char *file, int line, int module_index, } } +/* For internal calls to log_error_core with self-composed arg lists */ +static void log_error_va_glue(const char *file, int line, int module_index, + int level, apr_status_t status, + const server_rec *s, const conn_rec *c, + const request_rec *r, apr_pool_t *pool, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + log_error_core(file, line, module_index, level, status, s, c, r, pool, + fmt, args); + va_end(args); +} + AP_DECLARE(void) ap_log_error_(const char *file, int line, int module_index, int level, apr_status_t status, const server_rec *s, const char *fmt, ...) @@ -1371,6 +1386,129 @@ AP_DECLARE(void) ap_log_cerror_(const char *file, int line, int module_index, va_end(args); } +#define BYTES_LOGGED_PER_LINE 16 +#define LOG_BYTES_BUFFER_SIZE (BYTES_LOGGED_PER_LINE * 3 + 2) + +static void fmt_data(unsigned char *buf, const void *vdata, apr_size_t len, apr_size_t *off) +{ + const unsigned char *data = (const unsigned char *)vdata; + unsigned char *chars; + unsigned char *hex; + apr_size_t this_time = 0; + + memset(buf, ' ', LOG_BYTES_BUFFER_SIZE - 1); + buf[LOG_BYTES_BUFFER_SIZE - 1] = '\0'; + + chars = buf; /* start character dump here */ + hex = buf + BYTES_LOGGED_PER_LINE + 1; /* start hex dump here */ + while (*off < len && this_time < BYTES_LOGGED_PER_LINE) { + unsigned char c = data[*off]; + + if (apr_isprint(c) + && c != '\\') { /* backslash will be escaped later, which throws + * off the formatting + */ + *chars = c; + } + else { + *chars = '.'; + } + + if ((c >> 4) >= 10) { + *hex = 'a' + ((c >> 4) - 10); + } + else { + *hex = '0' + (c >> 4); + } + + if ((c & 0x0F) >= 10) { + *(hex + 1) = 'a' + ((c & 0x0F) - 10); + } + else { + *(hex + 1) = '0' + (c & 0x0F); + } + + chars += 1; + hex += 2; + *off += 1; + ++this_time; + } +} + +static void log_data_core(const char *file, int line, int module_index, + int level, const server_rec *s, + const conn_rec *c, const request_rec *r, + const char *label, const void *data, apr_size_t len, + unsigned int flags) +{ + unsigned char buf[LOG_BYTES_BUFFER_SIZE]; + apr_size_t off; + char prefix[20]; + + if (!(flags & AP_LOG_DATA_SHOW_OFFSET)) { + prefix[0] = '\0'; + } + + if (len > 0xffff) { /* bug in caller? */ + len = 0xffff; + } + + if (label) { + log_error_va_glue(file, line, module_index, level, APR_SUCCESS, s, + c, r, NULL, "%s (%" APR_SIZE_T_FMT " bytes)", + label, len); + } + + off = 0; + while (off < len) { + if (flags & AP_LOG_DATA_SHOW_OFFSET) { + apr_snprintf(prefix, sizeof prefix, "%04x: ", (unsigned int)off); + } + fmt_data(buf, data, len, &off); + log_error_va_glue(file, line, module_index, level, APR_SUCCESS, s, + c, r, NULL, "%s%s", prefix, buf); + } +} + +AP_DECLARE(void) ap_log_data_(const char *file, int line, + int module_index, int level, + const server_rec *s, const char *label, + const void *data, apr_size_t len, + unsigned int flags) +{ + log_data_core(file, line, module_index, level, s, NULL, NULL, label, + data, len, flags); +} + +AP_DECLARE(void) ap_log_rdata_(const char *file, int line, + int module_index, int level, + const request_rec *r, const char *label, + const void *data, apr_size_t len, + unsigned int flags) +{ + log_data_core(file, line, module_index, level, r->server, NULL, r, label, + data, len, flags); +} + +AP_DECLARE(void) ap_log_cdata_(const char *file, int line, + int module_index, int level, + const conn_rec *c, const char *label, + const void *data, apr_size_t len, + unsigned int flags) +{ + log_data_core(file, line, module_index, level, c->base_server, c, NULL, + label, data, len, flags); +} + +AP_DECLARE(void) ap_log_csdata_(const char *file, int line, int module_index, + int level, const conn_rec *c, const server_rec *s, + const char *label, const void *data, + apr_size_t len, unsigned int flags) +{ + log_data_core(file, line, module_index, level, s, c, NULL, label, data, + len, flags); +} + AP_DECLARE(void) ap_log_command_line(apr_pool_t *plog, server_rec *s) { int i;