Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Roman Arutyunyan
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 
0012 u_char *
0013 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
0014 {
0015     size_t     len;
0016     u_char     ch, *p, *addr, *port;
0017     ngx_int_t  n;
0018 
0019     p = buf;
0020     len = last - buf;
0021 
0022     if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
0023         goto invalid;
0024     }
0025 
0026     p += 6;
0027     len -= 6;
0028 
0029     if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
0030         ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
0031                        "PROXY protocol unknown protocol");
0032         p += 7;
0033         goto skip;
0034     }
0035 
0036     if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
0037         || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
0038     {
0039         goto invalid;
0040     }
0041 
0042     p += 5;
0043     addr = p;
0044 
0045     for ( ;; ) {
0046         if (p == last) {
0047             goto invalid;
0048         }
0049 
0050         ch = *p++;
0051 
0052         if (ch == ' ') {
0053             break;
0054         }
0055 
0056         if (ch != ':' && ch != '.'
0057             && (ch < 'a' || ch > 'f')
0058             && (ch < 'A' || ch > 'F')
0059             && (ch < '0' || ch > '9'))
0060         {
0061             goto invalid;
0062         }
0063     }
0064 
0065     len = p - addr - 1;
0066     c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
0067 
0068     if (c->proxy_protocol_addr.data == NULL) {
0069         return NULL;
0070     }
0071 
0072     ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
0073     c->proxy_protocol_addr.len = len;
0074 
0075     for ( ;; ) {
0076         if (p == last) {
0077             goto invalid;
0078         }
0079 
0080         if (*p++ == ' ') {
0081             break;
0082         }
0083     }
0084 
0085     port = p;
0086 
0087     for ( ;; ) {
0088         if (p == last) {
0089             goto invalid;
0090         }
0091 
0092         if (*p++ == ' ') {
0093             break;
0094         }
0095     }
0096 
0097     len = p - port - 1;
0098 
0099     n = ngx_atoi(port, len);
0100 
0101     if (n < 0 || n > 65535) {
0102         goto invalid;
0103     }
0104 
0105     c->proxy_protocol_port = (in_port_t) n;
0106 
0107     ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
0108                    "PROXY protocol address: %V %i", &c->proxy_protocol_addr, n);
0109 
0110 skip:
0111 
0112     for ( /* void */ ; p < last - 1; p++) {
0113         if (p[0] == CR && p[1] == LF) {
0114             return p + 2;
0115         }
0116     }
0117 
0118 invalid:
0119 
0120     ngx_log_error(NGX_LOG_ERR, c->log, 0,
0121                   "broken header: \"%*s\"", (size_t) (last - buf), buf);
0122 
0123     return NULL;
0124 }
0125 
0126 
0127 u_char *
0128 ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
0129 {
0130     ngx_uint_t  port, lport;
0131 
0132     if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
0133         return NULL;
0134     }
0135 
0136     if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
0137         return NULL;
0138     }
0139 
0140     switch (c->sockaddr->sa_family) {
0141 
0142     case AF_INET:
0143         buf = ngx_cpymem(buf, "PROXY TCP4 ", sizeof("PROXY TCP4 ") - 1);
0144         break;
0145 
0146 #if (NGX_HAVE_INET6)
0147     case AF_INET6:
0148         buf = ngx_cpymem(buf, "PROXY TCP6 ", sizeof("PROXY TCP6 ") - 1);
0149         break;
0150 #endif
0151 
0152     default:
0153         return ngx_cpymem(buf, "PROXY UNKNOWN" CRLF,
0154                           sizeof("PROXY UNKNOWN" CRLF) - 1);
0155     }
0156 
0157     buf += ngx_sock_ntop(c->sockaddr, c->socklen, buf, last - buf, 0);
0158 
0159     *buf++ = ' ';
0160 
0161     buf += ngx_sock_ntop(c->local_sockaddr, c->local_socklen, buf, last - buf,
0162                          0);
0163 
0164     port = ngx_inet_get_port(c->sockaddr);
0165     lport = ngx_inet_get_port(c->local_sockaddr);
0166 
0167     return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
0168 }