On 12/30/2016 03:20 PM, drugg...@apache.org wrote:
> Author: druggeri
> Date: Fri Dec 30 14:20:48 2016
> New Revision: 1776575
>
> URL: http://svn.apache.org/viewvc?rev=1776575=rev
> Log:
> Merge new PROXY protocol code into mod_remoteip
>
> Modified:
> httpd/httpd/trunk/docs/log-message-tags/next-number
> httpd/httpd/trunk/docs/manual/mod/mod_remoteip.xml
> httpd/httpd/trunk/modules/metadata/mod_remoteip.c
>
> ==
> --- httpd/httpd/trunk/modules/metadata/mod_remoteip.c (original)
> +++ httpd/httpd/trunk/modules/metadata/mod_remoteip.c Fri Dec 30 14:20:48 2016
> @@ -427,6 +730,464 @@ static int remoteip_modify_request(reque
> return OK;
> }
>
> +static int remoteip_is_server_port(apr_port_t port)
> +{
> +ap_listen_rec *lr;
> +
> +for (lr = ap_listeners; lr; lr = lr->next) {
> +if (lr->bind_addr && lr->bind_addr->port == port) {
> +return 1;
> +}
> +}
> +
> +return 0;
> +}
> +
> +/*
> + * Human readable format:
> + * PROXY {TCP4|TCP6|UNKNOWN}
>
> + */
> +static remoteip_parse_status_t remoteip_process_v1_header(conn_rec *c,
> +
> remoteip_conn_config_t *conn_conf,
> + proxy_header *hdr,
> apr_size_t len,
> + apr_size_t
> *hdr_len)
> +{
> +char *end, *word, *host, *valid_addr_chars, *saveptr;
> +char buf[sizeof(hdr->v1.line)];
> +apr_port_t port;
> +apr_status_t ret;
> +apr_int32_t family;
> +
> +#define GET_NEXT_WORD(field) \
> +word = apr_strtok(NULL, " ", ); \
> +if (!word) { \
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03497) \
> + "RemoteIPProxyProtocol: no " field " found in header
> '%s'", \
> + hdr->v1.line); \
> +return HDR_ERROR; \
> +}
> +
> +end = memchr(hdr->v1.line, '\r', len - 1);
> +if (!end || end[1] != '\n') {
> +return HDR_NEED_MORE; /* partial or invalid header */
> +}
> +
> +*end = '\0';
> +*hdr_len = end + 2 - hdr->v1.line; /* skip header + CRLF */
> +
> +/* parse in separate buffer so have the original for error messages */
> +strcpy(buf, hdr->v1.line);
> +
> +apr_strtok(buf, " ", );
> +
> +/* parse family */
> +GET_NEXT_WORD("family")
> +if (strcmp(word, "UNKNOWN") == 0) {
> +conn_conf->client_addr = c->client_addr;
> +conn_conf->client_ip = c->client_ip;
> +return HDR_DONE;
> +}
> +else if (strcmp(word, "TCP4") == 0) {
> +family = APR_INET;
> +valid_addr_chars = "0123456789.";
> +}
> +else if (strcmp(word, "TCP6") == 0) {
> +#if APR_HAVE_IPV6
> +family = APR_INET6;
> +valid_addr_chars = "0123456789abcdefABCDEF:";
> +#else
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03498)
> + "RemoteIPProxyProtocol: Unable to parse v6 address -
> APR is not compiled with IPv6 support",
> + word, hdr->v1.line);
> +return HDR_ERROR;
> +#endif
> +}
> +else {
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03499)
> + "RemoteIPProxyProtocol: unknown family '%s' in header
> '%s'",
> + word, hdr->v1.line);
> +return HDR_ERROR;
> +}
> +
> +/* parse client-addr */
> +GET_NEXT_WORD("client-address")
> +
> +if (strspn(word, valid_addr_chars) != strlen(word)) {
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03500)
> + "RemoteIPProxyProtocol: invalid client-address '%s'
> found in "
> + "header '%s'", word, hdr->v1.line);
> +return HDR_ERROR;
> +}
> +
> +host = word;
> +
> +/* parse dest-addr */
> +GET_NEXT_WORD("destination-address")
> +
> +/* parse client-port */
> +GET_NEXT_WORD("client-port")
> +if (sscanf(word, "%hu", ) != 1) {
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03501)
> + "RemoteIPProxyProtocol: error parsing port '%s' in
> header '%s'",
> + word, hdr->v1.line);
> +return HDR_ERROR;
> +}
> +
> +/* parse dest-port */
> +/* GET_NEXT_WORD("destination-port") - no-op since we don't care about
> it */
> +
> +/* create a socketaddr from the info */
> +ret = apr_sockaddr_info_get(_conf->client_addr, host, family, port,
> 0,
> +c->pool);
> +if (ret != APR_SUCCESS) {
> +conn_conf->client_addr = NULL;
> +ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03502)
> + "RemoteIPProxyProtocol: error converting family '%d',
> host '%s',"
> + " and port '%hu' to sockaddr; header was '%s'",
> + family, host, port,