mirror of
https://github.com/nginx/nginx.git
synced 2025-06-11 12:22:41 +08:00
Support bind to device.
Using SO_BINDTODEVICE option for the socket. A similar patch was proposed long ago[1], but was rejected. This feature is requested once in a while by several users[2][3]. [1] https://mailman.nginx.org/pipermail/nginx-devel/2013-January/003234.html [2] https://mailman.nginx.org/pipermail/nginx/2016-May/050713.html [3] https://stackoverflow.com/q/39536714/764870
This commit is contained in:
parent
3327353ec0
commit
81f31d1241
10
auto/unix
10
auto/unix
@ -354,6 +354,16 @@ ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_BINDANY, NULL, 0)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
ngx_feature="SO_BINDTODEVICE"
|
||||
ngx_feature_name="NGX_HAVE_BINDTODEVICE"
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#include <sys/socket.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs=
|
||||
ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
# Linux transparent proxying
|
||||
|
||||
ngx_feature="IP_TRANSPARENT"
|
||||
|
@ -67,7 +67,7 @@ syn match ngxListenComment '#.*$'
|
||||
syn keyword ngxListenOptions contained
|
||||
\ default_server ssl quic proxy_protocol
|
||||
\ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind
|
||||
\ ipv6only reuseport so_keepalive
|
||||
\ ipv6only reuseport so_keepalive bind_device
|
||||
\ nextgroup=@ngxListenParams skipwhite skipempty
|
||||
syn keyword ngxListenOptionsDeprecated contained
|
||||
\ http2
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
|
||||
ngx_os_io_t ngx_io;
|
||||
@ -150,6 +153,9 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
int reuseport;
|
||||
#endif
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
char bind_device[IFNAMSIZ];
|
||||
#endif
|
||||
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
@ -397,6 +403,39 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
|
||||
|
||||
ls[i].deferred_accept = 1;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
|
||||
ngx_memzero(&bind_device, sizeof(bind_device));
|
||||
olen = sizeof(bind_device);
|
||||
|
||||
if (getsockopt(ls[i].fd, SOL_SOCKET, SO_BINDTODEVICE, bind_device, &olen)
|
||||
== -1)
|
||||
{
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == NGX_EINVAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
|
||||
"getsockopt(SO_BINDTODEVICE) for %V failed, ignored",
|
||||
&ls[i].addr_text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bind_device[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
ls[i].bind_device = ngx_palloc(cycle->pool, IFNAMSIZ);
|
||||
if (ls[i].bind_device == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
(void) ngx_cpystrn((u_char *) ls[i].bind_device,
|
||||
(u_char *) bind_device, IFNAMSIZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
@ -495,6 +534,17 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
if (ls[i].bind_device) {
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
ls[i].bind_device, ngx_strlen(ls[i].bind_device)) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
|
||||
"setsockopt(SO_BINDTODEVICE, %s) %V failed, ignored",
|
||||
ls[i].bind_device, &ls[i].addr_text);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ls[i].type != SOCK_DGRAM || !ngx_test_config) {
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
|
@ -81,6 +81,9 @@ struct ngx_listening_s {
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
char *accept_filter;
|
||||
#endif
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
const char *bind_device;
|
||||
#endif
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
int setfib;
|
||||
#endif
|
||||
|
@ -202,6 +202,12 @@
|
||||
#define NGX_MODULE_SIGNATURE_34 "0"
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
#define NGX_MODULE_SIGNATURE_35 "1"
|
||||
#else
|
||||
#define NGX_MODULE_SIGNATURE_35 "0"
|
||||
#endif
|
||||
|
||||
#define NGX_MODULE_SIGNATURE \
|
||||
NGX_MODULE_SIGNATURE_0 NGX_MODULE_SIGNATURE_1 NGX_MODULE_SIGNATURE_2 \
|
||||
NGX_MODULE_SIGNATURE_3 NGX_MODULE_SIGNATURE_4 NGX_MODULE_SIGNATURE_5 \
|
||||
@ -214,7 +220,7 @@
|
||||
NGX_MODULE_SIGNATURE_24 NGX_MODULE_SIGNATURE_25 NGX_MODULE_SIGNATURE_26 \
|
||||
NGX_MODULE_SIGNATURE_27 NGX_MODULE_SIGNATURE_28 NGX_MODULE_SIGNATURE_29 \
|
||||
NGX_MODULE_SIGNATURE_30 NGX_MODULE_SIGNATURE_31 NGX_MODULE_SIGNATURE_32 \
|
||||
NGX_MODULE_SIGNATURE_33 NGX_MODULE_SIGNATURE_34
|
||||
NGX_MODULE_SIGNATURE_33 NGX_MODULE_SIGNATURE_34 NGX_MODULE_SIGNATURE_35
|
||||
|
||||
|
||||
#define NGX_MODULE_V1 \
|
||||
|
@ -1886,6 +1886,10 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
|
||||
ls->quic = addr->opt.quic;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
ls->bind_device = addr->opt.bind_device;
|
||||
#endif
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
|
@ -4027,6 +4027,20 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(value[n].data, "bind_device=", 12) == 0) {
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
lsopt.bind_device = (const char *) &value[n].data[12];
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"bind to device \"%V\" is not supported "
|
||||
"on this platform, ignored",
|
||||
&value[n]);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
|
||||
lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
|
||||
|
@ -103,6 +103,9 @@ typedef struct {
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
char *accept_filter;
|
||||
#endif
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
const char *bind_device;
|
||||
#endif
|
||||
} ngx_http_listen_opt_t;
|
||||
|
||||
|
||||
|
@ -1047,6 +1047,10 @@ ngx_stream_add_listening(ngx_conf_t *cf, ngx_stream_conf_addr_t *addr)
|
||||
|
||||
ls->wildcard = addr->opt.wildcard;
|
||||
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
ls->bind_device = addr->opt.bind_device;
|
||||
#endif
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
|
@ -952,6 +952,20 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(value[n].data, "bind_device=", 12) == 0) {
|
||||
#if (NGX_HAVE_BINDTODEVICE)
|
||||
lsopt.bind_device = (const char *) &value[n].data[12];
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"bind to device \"%V\" is not supported "
|
||||
"on this platform, ignored",
|
||||
&value[n]);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
if (ngx_strncmp(value[i].data, "setfib=", 7) == 0) {
|
||||
lsopt.setfib = ngx_atoi(value[i].data + 7, value[i].len - 7);
|
||||
|
Loading…
Reference in New Issue
Block a user