MXS-1220: Allow binding to a specific address
The admin interface can now bind to a specific network interface.
This commit is contained in:
parent
af2a4e792f
commit
4ed4773d91
@ -172,6 +172,12 @@ write or modify the data in the backend server. The default is 2 seconds.
|
||||
auth_write_timeout=10
|
||||
```
|
||||
|
||||
#### `admin_host`
|
||||
|
||||
The network interface where the HTTP admin interface listens on. The default
|
||||
value is the IPv6 address `::` which listens on all available network
|
||||
interfaces.
|
||||
|
||||
#### `admin_port`
|
||||
|
||||
The port where the HTTP admin interface listens on. The default value is port
|
||||
|
@ -28,10 +28,12 @@ MXS_BEGIN_DECLS
|
||||
|
||||
/** Default port where the REST API listens */
|
||||
#define DEFAULT_ADMIN_HTTP_PORT 8989
|
||||
#define DEFAULT_ADMIN_HOST "::"
|
||||
|
||||
#define _RELEASE_STR_LENGTH 256 /**< release len */
|
||||
#define MAX_ADMIN_USER_LEN 1024
|
||||
#define MAX_ADMIN_PW_LEN 1024
|
||||
#define MAX_ADMIN_HOST_LEN 1024
|
||||
|
||||
/**
|
||||
* Common configuration parameters names
|
||||
@ -42,6 +44,7 @@ MXS_BEGIN_DECLS
|
||||
*/
|
||||
extern const char CN_ADDRESS[];
|
||||
extern const char CN_ADMIN_AUTH[];
|
||||
extern const char CN_ADMIN_HOST[];
|
||||
extern const char CN_ADMIN_PASSWORD[];
|
||||
extern const char CN_ADMIN_PORT[];
|
||||
extern const char CN_ADMIN_USER[];
|
||||
@ -156,6 +159,7 @@ typedef struct
|
||||
char* qc_args; /**< Arguments for the query classifier */
|
||||
char admin_user[MAX_ADMIN_USER_LEN]; /**< Admin interface user */
|
||||
char admin_password[MAX_ADMIN_PW_LEN]; /**< Admin interface password */
|
||||
char admin_host[MAX_ADMIN_HOST_LEN]; /**< Admin interface host */
|
||||
uint16_t admin_port; /**< Admin interface port */
|
||||
bool admin_auth; /**< Admin interface authentication */
|
||||
} MXS_CONFIG;
|
||||
|
@ -11,11 +11,17 @@
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file The embedded HTTP protocol administrative interface
|
||||
*/
|
||||
#include "maxscale/admin.hh"
|
||||
|
||||
#include <climits>
|
||||
#include <new>
|
||||
#include <microhttpd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <maxscale/atomic.h>
|
||||
#include <maxscale/debug.h>
|
||||
@ -180,16 +186,64 @@ int handle_client(void *cls,
|
||||
return client->process(url, method, upload_data, upload_data_size);
|
||||
}
|
||||
|
||||
static bool host_to_sockaddr(const char* host, uint16_t port, struct sockaddr_storage* addr)
|
||||
{
|
||||
struct addrinfo *ai = NULL, hint = {};
|
||||
int rc;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_flags = AI_ALL;
|
||||
|
||||
if ((rc = getaddrinfo(host, NULL, &hint, &ai)) != 0)
|
||||
{
|
||||
MXS_ERROR("Failed to obtain address for host %s: %s", host, gai_strerror(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Take the first one */
|
||||
if (ai)
|
||||
{
|
||||
memcpy(addr, ai->ai_addr, ai->ai_addrlen);
|
||||
|
||||
if (addr->ss_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *ip = (struct sockaddr_in*)addr;
|
||||
ip->sin_port = htons(port);
|
||||
}
|
||||
else if (addr->ss_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *ip = (struct sockaddr_in6*)addr;
|
||||
ip->sin6_port = htons(port);
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mxs_admin_init()
|
||||
{
|
||||
http_daemon = MHD_start_daemon(MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY | MHD_USE_DUAL_STACK,
|
||||
config_get_global_options()->admin_port,
|
||||
NULL, NULL,
|
||||
handle_client, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, close_client, NULL,
|
||||
MHD_OPTION_END);
|
||||
return http_daemon != NULL;
|
||||
struct sockaddr_storage addr;
|
||||
|
||||
if (host_to_sockaddr(config_get_global_options()->admin_host,
|
||||
config_get_global_options()->admin_port,
|
||||
&addr))
|
||||
{
|
||||
int options = MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY;
|
||||
|
||||
if (addr.ss_family == AF_INET6)
|
||||
{
|
||||
options |= MHD_USE_DUAL_STACK;
|
||||
}
|
||||
|
||||
// The port argument is ignored and the port in the struct sockaddr is used instead
|
||||
http_daemon = MHD_start_daemon(options, 0, NULL, NULL, handle_client, NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED, close_client, NULL,
|
||||
MHD_OPTION_SOCK_ADDR, &addr,
|
||||
MHD_OPTION_END);
|
||||
}
|
||||
|
||||
return http_daemon != NULL;
|
||||
}
|
||||
|
||||
void mxs_admin_shutdown()
|
||||
|
@ -53,6 +53,7 @@ using std::string;
|
||||
|
||||
const char CN_ADDRESS[] = "address";
|
||||
const char CN_ADMIN_AUTH[] = "admin_auth";
|
||||
const char CN_ADMIN_HOST[] = "admin_host";
|
||||
const char CN_ADMIN_PASSWORD[] = "admin_password";
|
||||
const char CN_ADMIN_PORT[] = "admin_port";
|
||||
const char CN_ADMIN_USER[] = "admin_user";
|
||||
@ -1520,6 +1521,10 @@ handle_global_item(const char *name, const char *value)
|
||||
{
|
||||
gateway.admin_port = atoi(value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_HOST) == 0)
|
||||
{
|
||||
strcpy(gateway.admin_host, value);
|
||||
}
|
||||
else if (strcmp(name, CN_ADMIN_AUTH) == 0)
|
||||
{
|
||||
gateway.admin_auth = config_truth_value(value);
|
||||
@ -1746,6 +1751,7 @@ global_defaults()
|
||||
gateway.skip_permission_checks = false;
|
||||
gateway.admin_port = DEFAULT_ADMIN_HTTP_PORT;
|
||||
gateway.admin_auth = false;
|
||||
strcpy(gateway.admin_host, DEFAULT_ADMIN_HOST);
|
||||
strcpy(gateway.admin_user, INET_DEFAULT_USERNAME);
|
||||
strcpy(gateway.admin_password, INET_DEFAULT_PASSWORD);
|
||||
|
||||
|
@ -1982,6 +1982,18 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (mxs_admin_init())
|
||||
{
|
||||
MXS_NOTICE("Started REST API on [%s]:%u", cnf->admin_host, cnf->admin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* logerr = "Failed to initialize admin interface";
|
||||
print_log_n_stderr(true, true, logerr, logerr, 0);
|
||||
rc = MAXSCALE_INTERNALERROR;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
MXS_NOTICE("MaxScale started with %d server threads.", config_threadcount());
|
||||
/**
|
||||
* Successful start, notify the parent process that it can exit.
|
||||
@ -1992,14 +2004,6 @@ int main(int argc, char **argv)
|
||||
write_child_exit_code(daemon_pipe[1], rc);
|
||||
}
|
||||
|
||||
if (!mxs_admin_init())
|
||||
{
|
||||
const char* logerr = "Failed to initialize admin interface";
|
||||
print_log_n_stderr(true, true, logerr, logerr, 0);
|
||||
rc = MAXSCALE_INTERNALERROR;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
/*<
|
||||
* Run worker 0 in the main thread.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user