Hi, On Tue, Oct 11, 2022 at 04:20:52AM +0300, Maxim Dounin wrote: > Hello! > > On Tue, Sep 27, 2022 at 01:41:25PM +0400, Roman Arutyunyan wrote: > > [...] > > > # HG changeset patch > > # User Roman Arutyunyan <a...@nginx.com> > > # Date 1664263604 -14400 > > # Tue Sep 27 11:26:44 2022 +0400 > > # Node ID 38940ff7246574aa19a19c76b072073c34f191be > > # Parent ba5cf8f73a2d0a3615565bf9545f3d65216a0530 > > PROXY protocol v2 TLV variables. > > > > The variables have prefix $proxy_protocol_tlv_ and are accessible by name > > and by type. Examples are: $proxy_protocol_tlv_0x01, > > $proxy_protocol_tlv_alpn. > > > > diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c > > --- a/src/core/ngx_proxy_protocol.c > > +++ b/src/core/ngx_proxy_protocol.c > > @@ -15,6 +15,12 @@ > > > > #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1]) > > > > +#define ngx_proxy_protocol_parse_uint32(p) > > \ > > + ( ((uint32_t) (p)[0] << 24) > > \ > > + + ( (p)[1] << 16) > > \ > > + + ( (p)[2] << 8) > > \ > > + + ( (p)[3]) ) > > + > > > > typedef struct { > > u_char signature[12]; > > @@ -40,6 +46,24 @@ typedef struct { > > } ngx_proxy_protocol_inet6_addrs_t; > > > > > > +typedef struct { > > + u_char type; > > + u_char len[2]; > > +} ngx_proxy_protocol_tlv_t; > > + > > + > > +typedef struct { > > + u_char client; > > + u_char verify[4]; > > +} ngx_proxy_protocol_tlv_ssl_t; > > + > > + > > +typedef struct { > > + ngx_str_t name; > > + ngx_uint_t type; > > +} ngx_proxy_protocol_tlv_entry_t; > > + > > + > > static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, > > u_char *last, ngx_str_t *addr); > > static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last, > > @@ -48,6 +72,26 @@ static u_char *ngx_proxy_protocol_v2_rea > > u_char *last); > > > > > > +static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = { > > + { ngx_string("alpn"), 0x01 }, > > + { ngx_string("authority"), 0x02 }, > > + { ngx_string("unique_id"), 0x05 }, > > + { ngx_string("ssl"), 0x20 }, > > + { ngx_string("netns"), 0x30 }, > > + { ngx_null_string, 0x00 } > > +}; > > + > > + > > +static ngx_proxy_protocol_tlv_entry_t > > ngx_proxy_protocol_tlv_ssl_entries[] = { > > + { ngx_string("version"), 0x21 }, > > + { ngx_string("cn"), 0x22 }, > > + { ngx_string("cipher"), 0x23 }, > > + { ngx_string("sig_alg"), 0x24 }, > > + { ngx_string("key_alg"), 0x25 }, > > + { ngx_null_string, 0x00 } > > +}; > > + > > + > > u_char * > > ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) > > { > > @@ -412,11 +456,145 @@ ngx_proxy_protocol_v2_read(ngx_connectio > > &pp->src_addr, pp->src_port, &pp->dst_addr, > > pp->dst_port); > > > > if (buf < end) { > > - ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, > > - "PROXY protocol v2 %z bytes of tlv ignored", end - > > buf); > > + pp->tlvs.data = ngx_pnalloc(c->pool, end - buf); > > + if (pp->tlvs.data == NULL) { > > + return NULL; > > + } > > + > > + ngx_memcpy(pp->tlvs.data, buf, end - buf); > > + pp->tlvs.len = end - buf; > > } > > > > c->proxy_protocol = pp; > > > > return end; > > } > > + > > + > > +ngx_int_t > > +ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs, > > + ngx_uint_t type, ngx_str_t *value) > > This probably can be made static and moved after > ngx_proxy_protocol_get_tlv().
OK. In fact, I kept this function public for vendor-specific TLV variables which can be added by third-party modules. However, ngx_proxy_protocol_get_tlv() seems to be enough despite extra tlv type parsing. > > +{ > > + u_char *p; > > + size_t n, len; > > + ngx_proxy_protocol_tlv_t *tlv; > > + > > + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, > > + "PROXY protocol v2 lookup tlv:%02xi", type); > > + > > + p = tlvs->data; > > + n = tlvs->len; > > + > > + while (n) { > > + if (n < sizeof(ngx_proxy_protocol_tlv_t)) { > > + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol > > TLV"); > > + return NGX_ERROR; > > + } > > + > > + tlv = (ngx_proxy_protocol_tlv_t *) p; > > + len = ngx_proxy_protocol_parse_uint16(tlv->len); > > + > > + p += sizeof(ngx_proxy_protocol_tlv_t); > > + n -= sizeof(ngx_proxy_protocol_tlv_t); > > + > > + if (n < len) { > > + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol > > TLV"); > > + return NGX_ERROR; > > + } > > + > > + ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, > > + "PROXY protocol v2 tlv:0x%02xd len:%uz", tlv->type, > > len); > > I tend to think this is going to be too chatty on real load with > multiple TLVs, and probably should be removed or #if 0'ed. OK, removed. > > + > > + if (tlv->type == type) { > > + value->data = p; > > + value->len = len; > > + return NGX_OK; > > + } > > + > > + p += len; > > + n -= len; > > + } > > + > > + return NGX_DECLINED; > > +} > > + > > + > > +ngx_int_t > > +ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name, > > + ngx_str_t *value) > > +{ > > + u_char *p; > > + size_t n; > > + uint32_t verify; > > + ngx_str_t ssl, *tlvs; > > + ngx_int_t rc, type; > > + ngx_proxy_protocol_tlv_ssl_t *tlv_ssl; > > + ngx_proxy_protocol_tlv_entry_t *te; > > + > > + if (c->proxy_protocol == NULL) { > > + return NGX_DECLINED; > > + } > > + > > + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, > > + "PROXY protocol v2 get tlv \"%V\"", name); > > + > > + te = ngx_proxy_protocol_tlv_entries; > > + tlvs = &c->proxy_protocol->tlvs; > > + > > + p = name->data; > > + n = name->len; > > + > > + if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == > > '_') { > > + > > + rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl); > > + if (rc != NGX_OK) { > > + return rc; > > + } > > + > > + if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) { > > + return NGX_ERROR; > > + } > > + > > + p += 4; > > + n -= 4; > > + > > + if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) { > > + > > + tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data; > > + verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify); > > + > > + value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN); > > + if (value->data == NULL) { > > + return NGX_ERROR; > > + } > > + > > + value->len = ngx_sprintf(value->data, "%uD", verify) > > + - value->data; > > + return NGX_OK; > > + } > > + > > + ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t); > > + ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t); > > + > > + te = ngx_proxy_protocol_tlv_ssl_entries; > > + tlvs = &ssl; > > + } > > + > > + if (n >= 2 && p[0] == '0' && p[1] == 'x') { > > + > > + type = ngx_hextoi(p + 2, n - 2); > > + if (type == NGX_ERROR) { > > + return NGX_ERROR; > > This probably needs some error message. OK, added. > > + } > > + > > + return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value); > > + } > > + > > + for ( /* void */ ; te->type; te++) { > > + if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) { > > + return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value); > > + } > > + } > > + > > + return NGX_DECLINED; > > Invalid/unknown names will silently result in empty variables. I > tend to think this is going to be a problem, especially if we'll > introduce additional names at some point. Some error instead > might be a good idea. And here. > > +} > > diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h > > --- a/src/core/ngx_proxy_protocol.h > > +++ b/src/core/ngx_proxy_protocol.h > > @@ -21,6 +21,7 @@ struct ngx_proxy_protocol_s { > > ngx_str_t dst_addr; > > in_port_t src_port; > > in_port_t dst_port; > > + ngx_str_t tlvs; > > }; > > > > > > @@ -28,6 +29,10 @@ u_char *ngx_proxy_protocol_read(ngx_conn > > u_char *last); > > u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, > > u_char *last); > > +ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t > > *tlvs, > > + ngx_uint_t type, ngx_str_t *value); > > +ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name, > > + ngx_str_t *value); > > > > > > #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */ > > diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c > > --- a/src/http/ngx_http_variables.c > > +++ b/src/http/ngx_http_variables.c > > @@ -61,6 +61,8 @@ static ngx_int_t ngx_http_variable_proxy > > ngx_http_variable_value_t *v, uintptr_t data); > > static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t > > *r, > > ngx_http_variable_value_t *v, uintptr_t data); > > +static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t > > *r, > > + ngx_http_variable_value_t *v, uintptr_t data); > > static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, > > ngx_http_variable_value_t *v, uintptr_t data); > > static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, > > @@ -214,6 +216,10 @@ static ngx_http_variable_t ngx_http_cor > > ngx_http_variable_proxy_protocol_port, > > offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, > > > > + { ngx_string("proxy_protocol_tlv_"), NULL, > > + ngx_http_variable_proxy_protocol_tlv, > > + 0, NGX_HTTP_VAR_PREFIX, 0 }, > > + > > { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, > > 0, 0 }, > > > > { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, > > 0, 0 }, > > @@ -1387,6 +1393,39 @@ ngx_http_variable_proxy_protocol_port(ng > > > > > > static ngx_int_t > > +ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r, > > + ngx_http_variable_value_t *v, uintptr_t data) > > +{ > > + ngx_str_t *name = (ngx_str_t *) data; > > + > > + ngx_int_t rc; > > + ngx_str_t tlv, value; > > + > > + tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1); > > + tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1; > > + > > + rc = ngx_proxy_protocol_get_tlv(r->connection, &tlv, &value); > > + > > + if (rc == NGX_ERROR) { > > + return NGX_ERROR; > > + } > > + > > + if (rc == NGX_DECLINED) { > > + v->not_found = 1; > > + return NGX_OK; > > + } > > + > > + v->len = value.len; > > + v->valid = 1; > > + v->no_cacheable = 0; > > + v->not_found = 0; > > + v->data = value.data; > > + > > + return NGX_OK; > > +} > > + > > + > > +static ngx_int_t > > ngx_http_variable_server_addr(ngx_http_request_t *r, > > ngx_http_variable_value_t *v, uintptr_t data) > > { > > diff --git a/src/stream/ngx_stream_variables.c > > b/src/stream/ngx_stream_variables.c > > --- a/src/stream/ngx_stream_variables.c > > +++ b/src/stream/ngx_stream_variables.c > > @@ -23,6 +23,8 @@ static ngx_int_t ngx_stream_variable_pro > > ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t > > data); > > static ngx_int_t ngx_stream_variable_proxy_protocol_port( > > ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t > > data); > > +static ngx_int_t ngx_stream_variable_proxy_protocol_tlv( > > + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t > > data); > > static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, > > ngx_stream_variable_value_t *v, uintptr_t data); > > static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s, > > @@ -79,6 +81,10 @@ static ngx_stream_variable_t ngx_stream > > ngx_stream_variable_proxy_protocol_port, > > offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, > > > > + { ngx_string("proxy_protocol_tlv_"), NULL, > > + ngx_stream_variable_proxy_protocol_tlv, > > + 0, NGX_STREAM_VAR_PREFIX, 0 }, > > + > > { ngx_string("server_addr"), NULL, > > ngx_stream_variable_server_addr, 0, 0, 0 }, > > > > @@ -622,6 +628,39 @@ ngx_stream_variable_proxy_protocol_port( > > > > > > static ngx_int_t > > +ngx_stream_variable_proxy_protocol_tlv(ngx_stream_session_t *s, > > + ngx_stream_variable_value_t *v, uintptr_t data) > > +{ > > + ngx_str_t *name = (ngx_str_t *) data; > > + > > + ngx_int_t rc; > > + ngx_str_t tlv, value; > > + > > + tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1); > > + tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1; > > + > > + rc = ngx_proxy_protocol_get_tlv(s->connection, &tlv, &value); > > + > > + if (rc == NGX_ERROR) { > > + return NGX_ERROR; > > + } > > + > > + if (rc == NGX_DECLINED) { > > + v->not_found = 1; > > + return NGX_OK; > > + } > > + > > + v->len = value.len; > > + v->valid = 1; > > + v->no_cacheable = 0; > > + v->not_found = 0; > > + v->data = value.data; > > + > > + return NGX_OK; > > +} > > + > > + > > +static ngx_int_t > > ngx_stream_variable_server_addr(ngx_stream_session_t *s, > > ngx_stream_variable_value_t *v, uintptr_t data) > > { > > Otherwise looks good. [..] -- Roman
# HG changeset patch # User Roman Arutyunyan <a...@nginx.com> # Date 1664263604 -14400 # Tue Sep 27 11:26:44 2022 +0400 # Node ID 2774f8d59b108635752f9f2dbe3a5394a3650b85 # Parent ba5cf8f73a2d0a3615565bf9545f3d65216a0530 PROXY protocol v2 TLV variables. The variables have prefix $proxy_protocol_tlv_ and are accessible by name and by type. Examples are: $proxy_protocol_tlv_0x01, $proxy_protocol_tlv_alpn. diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -15,6 +15,12 @@ #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1]) +#define ngx_proxy_protocol_parse_uint32(p) \ + ( ((uint32_t) (p)[0] << 24) \ + + ( (p)[1] << 16) \ + + ( (p)[2] << 8) \ + + ( (p)[3]) ) + typedef struct { u_char signature[12]; @@ -40,12 +46,52 @@ typedef struct { } ngx_proxy_protocol_inet6_addrs_t; +typedef struct { + u_char type; + u_char len[2]; +} ngx_proxy_protocol_tlv_t; + + +typedef struct { + u_char client; + u_char verify[4]; +} ngx_proxy_protocol_tlv_ssl_t; + + +typedef struct { + ngx_str_t name; + ngx_uint_t type; +} ngx_proxy_protocol_tlv_entry_t; + + static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last, ngx_str_t *addr); static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port, u_char sep); static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last); +static ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, + ngx_str_t *tlvs, ngx_uint_t type, ngx_str_t *value); + + +static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = { + { ngx_string("alpn"), 0x01 }, + { ngx_string("authority"), 0x02 }, + { ngx_string("unique_id"), 0x05 }, + { ngx_string("ssl"), 0x20 }, + { ngx_string("netns"), 0x30 }, + { ngx_null_string, 0x00 } +}; + + +static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_ssl_entries[] = { + { ngx_string("version"), 0x21 }, + { ngx_string("cn"), 0x22 }, + { ngx_string("cipher"), 0x23 }, + { ngx_string("sig_alg"), 0x24 }, + { ngx_string("key_alg"), 0x25 }, + { ngx_null_string, 0x00 } +}; u_char * @@ -412,11 +458,147 @@ ngx_proxy_protocol_v2_read(ngx_connectio &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port); if (buf < end) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol v2 %z bytes of tlv ignored", end - buf); + pp->tlvs.data = ngx_pnalloc(c->pool, end - buf); + if (pp->tlvs.data == NULL) { + return NULL; + } + + ngx_memcpy(pp->tlvs.data, buf, end - buf); + pp->tlvs.len = end - buf; } c->proxy_protocol = pp; return end; } + + +ngx_int_t +ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name, + ngx_str_t *value) +{ + u_char *p; + size_t n; + uint32_t verify; + ngx_str_t ssl, *tlvs; + ngx_int_t rc, type; + ngx_proxy_protocol_tlv_ssl_t *tlv_ssl; + ngx_proxy_protocol_tlv_entry_t *te; + + if (c->proxy_protocol == NULL) { + return NGX_DECLINED; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol v2 get tlv \"%V\"", name); + + te = ngx_proxy_protocol_tlv_entries; + tlvs = &c->proxy_protocol->tlvs; + + p = name->data; + n = name->len; + + if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == '_') { + + rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl); + if (rc != NGX_OK) { + return rc; + } + + if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) { + return NGX_ERROR; + } + + p += 4; + n -= 4; + + if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) { + + tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data; + verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify); + + value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN); + if (value->data == NULL) { + return NGX_ERROR; + } + + value->len = ngx_sprintf(value->data, "%uD", verify) + - value->data; + return NGX_OK; + } + + ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t); + ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t); + + te = ngx_proxy_protocol_tlv_ssl_entries; + tlvs = &ssl; + } + + if (n >= 2 && p[0] == '0' && p[1] == 'x') { + + type = ngx_hextoi(p + 2, n - 2); + if (type == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "invalid PROXY protocol TLV \"%V\"", name); + return NGX_ERROR; + } + + return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value); + } + + for ( /* void */ ; te->type; te++) { + if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) { + return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value); + } + } + + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "PROXY protocol TLV \"%V\" not found", name); + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs, + ngx_uint_t type, ngx_str_t *value) +{ + u_char *p; + size_t n, len; + ngx_proxy_protocol_tlv_t *tlv; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol v2 lookup tlv:%02xi", type); + + p = tlvs->data; + n = tlvs->len; + + while (n) { + if (n < sizeof(ngx_proxy_protocol_tlv_t)) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV"); + return NGX_ERROR; + } + + tlv = (ngx_proxy_protocol_tlv_t *) p; + len = ngx_proxy_protocol_parse_uint16(tlv->len); + + p += sizeof(ngx_proxy_protocol_tlv_t); + n -= sizeof(ngx_proxy_protocol_tlv_t); + + if (n < len) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV"); + return NGX_ERROR; + } + + if (tlv->type == type) { + value->data = p; + value->len = len; + return NGX_OK; + } + + p += len; + n -= len; + } + + return NGX_DECLINED; +} diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h --- a/src/core/ngx_proxy_protocol.h +++ b/src/core/ngx_proxy_protocol.h @@ -21,6 +21,7 @@ struct ngx_proxy_protocol_s { ngx_str_t dst_addr; in_port_t src_port; in_port_t dst_port; + ngx_str_t tlvs; }; @@ -28,6 +29,8 @@ u_char *ngx_proxy_protocol_read(ngx_conn u_char *last); u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last); +ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name, + ngx_str_t *value); #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */ diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -61,6 +61,8 @@ static ngx_int_t ngx_http_variable_proxy ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, @@ -214,6 +216,10 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_proxy_protocol_port, offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, + { ngx_string("proxy_protocol_tlv_"), NULL, + ngx_http_variable_proxy_protocol_tlv, + 0, NGX_HTTP_VAR_PREFIX, 0 }, + { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, @@ -1387,6 +1393,39 @@ ngx_http_variable_proxy_protocol_port(ng static ngx_int_t +ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_int_t rc; + ngx_str_t tlv, value; + + tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1); + tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1; + + rc = ngx_proxy_protocol_get_tlv(r->connection, &tlv, &value); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = value.data; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -23,6 +23,8 @@ static ngx_int_t ngx_stream_variable_pro ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_proxy_protocol_port( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_proxy_protocol_tlv( + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s, @@ -79,6 +81,10 @@ static ngx_stream_variable_t ngx_stream ngx_stream_variable_proxy_protocol_port, offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, + { ngx_string("proxy_protocol_tlv_"), NULL, + ngx_stream_variable_proxy_protocol_tlv, + 0, NGX_STREAM_VAR_PREFIX, 0 }, + { ngx_string("server_addr"), NULL, ngx_stream_variable_server_addr, 0, 0, 0 }, @@ -622,6 +628,39 @@ ngx_stream_variable_proxy_protocol_port( static ngx_int_t +ngx_stream_variable_proxy_protocol_tlv(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_int_t rc; + ngx_str_t tlv, value; + + tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1); + tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1; + + rc = ngx_proxy_protocol_get_tlv(s->connection, &tlv, &value); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = value.data; + + return NGX_OK; +} + + +static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) {
_______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org