aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ngx_connection.h2
-rw-r--r--src/core/ngx_core.h1
-rw-r--r--src/core/ngx_proxy_protocol.c91
-rw-r--r--src/core/ngx_proxy_protocol.h23
4 files changed, 117 insertions, 0 deletions
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index d9bc60a77..ed14e6023 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -139,6 +139,8 @@ struct ngx_connection_s {
socklen_t socklen;
ngx_str_t addr_text;
+ ngx_str_t proxy_protocol_addr;
+
#if (NGX_SSL)
ngx_ssl_connection_t *ssl;
#endif
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index dfcf2d56c..a2d417e8d 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -77,6 +77,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_open_file_cache.h>
#include <ngx_os.h>
#include <ngx_connection.h>
+#include <ngx_proxy_protocol.h>
#define LF (u_char) 10
diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c
new file mode 100644
index 000000000..59ef010fc
--- /dev/null
+++ b/src/core/ngx_proxy_protocol.c
@@ -0,0 +1,91 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+u_char *
+ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
+{
+ size_t len;
+ u_char ch, *p, *addr;
+
+ p = buf;
+ len = last - buf;
+
+ if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
+ goto invalid;
+ }
+
+ p += 6;
+ len -= 6;
+
+ if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "PROXY protocol unknown protocol");
+ p += 7;
+ goto skip;
+ }
+
+ if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
+ || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
+ {
+ goto invalid;
+ }
+
+ p += 5;
+ addr = p;
+
+ for ( ;; ) {
+ if (p == last) {
+ goto invalid;
+ }
+
+ ch = *p++;
+
+ if (ch == ' ') {
+ break;
+ }
+
+ if (ch != ':' && ch != '.'
+ && (ch < 'a' || ch > 'f')
+ && (ch < 'A' || ch > 'F')
+ && (ch < '0' || ch > '9'))
+ {
+ goto invalid;
+ }
+ }
+
+ len = p - addr - 1;
+ c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
+
+ if (c->proxy_protocol_addr.data == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
+ c->proxy_protocol_addr.len = len;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
+
+skip:
+
+ for ( /* void */ ; p < last - 1; p++) {
+ if (p[0] == CR && p[1] == LF) {
+ return p + 2;
+ }
+ }
+
+invalid:
+
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "broken header: \"%*s\"", (size_t) (last - buf), buf);
+
+ return NULL;
+}
diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h
new file mode 100644
index 000000000..4f3912512
--- /dev/null
+++ b/src/core/ngx_proxy_protocol.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
+#define _NGX_PROXY_PROTOCOL_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
+
+
+u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
+ u_char *last);
+
+
+#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */