UNIX socket support
UNIX socket support
This commit is contained in:
@ -28,6 +28,7 @@
|
|||||||
* 23/07/13 Mark Riddoch Addition on default monitor password
|
* 23/07/13 Mark Riddoch Addition on default monitor password
|
||||||
* 06/02/14 Massimiliano Pinto Added support for enable/disable root user in services
|
* 06/02/14 Massimiliano Pinto Added support for enable/disable root user in services
|
||||||
* 14/02/14 Massimiliano Pinto Added enable_root_user in the service_params list
|
* 14/02/14 Massimiliano Pinto Added enable_root_user in the service_params list
|
||||||
|
* 11/03/14 Massimiliano Pinto Added socket support
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -344,14 +345,36 @@ int error_count = 0;
|
|||||||
char *address;
|
char *address;
|
||||||
char *port;
|
char *port;
|
||||||
char *protocol;
|
char *protocol;
|
||||||
|
char *socket;
|
||||||
|
|
||||||
service = config_get_value(obj->parameters, "service");
|
service = config_get_value(obj->parameters, "service");
|
||||||
port = config_get_value(obj->parameters, "port");
|
port = config_get_value(obj->parameters, "port");
|
||||||
address = config_get_value(obj->parameters, "address");
|
address = config_get_value(obj->parameters, "address");
|
||||||
protocol = config_get_value(obj->parameters, "protocol");
|
protocol = config_get_value(obj->parameters, "protocol");
|
||||||
|
socket = config_get_value(obj->parameters, "socket");
|
||||||
if (service && port && protocol)
|
|
||||||
{
|
if (service && socket && protocol) {
|
||||||
|
CONFIG_CONTEXT *ptr = context;
|
||||||
|
while (ptr && strcmp(ptr->object, service) != 0)
|
||||||
|
ptr = ptr->next;
|
||||||
|
if (ptr && ptr->element)
|
||||||
|
{
|
||||||
|
serviceAddProtocol(ptr->element,
|
||||||
|
protocol,
|
||||||
|
socket,
|
||||||
|
0);
|
||||||
|
} else {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Listener '%s', "
|
||||||
|
"service '%s' not found. "
|
||||||
|
"Listener will not execute for socket %s.",
|
||||||
|
obj->object, service, socket)));
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service && port && protocol) {
|
||||||
CONFIG_CONTEXT *ptr = context;
|
CONFIG_CONTEXT *ptr = context;
|
||||||
while (ptr && strcmp(ptr->object, service) != 0)
|
while (ptr && strcmp(ptr->object, service) != 0)
|
||||||
ptr = ptr->next;
|
ptr = ptr->next;
|
||||||
@ -763,11 +786,35 @@ SERVER *server;
|
|||||||
char *port;
|
char *port;
|
||||||
char *protocol;
|
char *protocol;
|
||||||
char *address;
|
char *address;
|
||||||
|
char *socket;
|
||||||
|
|
||||||
service = config_get_value(obj->parameters, "service");
|
service = config_get_value(obj->parameters, "service");
|
||||||
address = config_get_value(obj->parameters, "address");
|
address = config_get_value(obj->parameters, "address");
|
||||||
port = config_get_value(obj->parameters, "port");
|
port = config_get_value(obj->parameters, "port");
|
||||||
protocol = config_get_value(obj->parameters, "protocol");
|
protocol = config_get_value(obj->parameters, "protocol");
|
||||||
|
socket = config_get_value(obj->parameters, "socket");
|
||||||
|
|
||||||
|
if (service && socket && protocol)
|
||||||
|
{
|
||||||
|
CONFIG_CONTEXT *ptr = context;
|
||||||
|
while (ptr && strcmp(ptr->object, service) != 0)
|
||||||
|
ptr = ptr->next;
|
||||||
|
|
||||||
|
if (ptr &&
|
||||||
|
ptr->element &&
|
||||||
|
serviceHasProtocol(ptr->element,
|
||||||
|
protocol,
|
||||||
|
0) == 0)
|
||||||
|
{
|
||||||
|
serviceAddProtocol(ptr->element,
|
||||||
|
protocol,
|
||||||
|
socket,
|
||||||
|
0);
|
||||||
|
serviceStartProtocol(ptr->element,
|
||||||
|
protocol,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (service && port && protocol)
|
if (service && port && protocol)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
* 24/02/2014 Massimiliano Pinto Added: on failed authentication a new users' table is loaded with time and frequency limitations
|
* 24/02/2014 Massimiliano Pinto Added: on failed authentication a new users' table is loaded with time and frequency limitations
|
||||||
* If current user is authenticated the new users' table will replace the old one
|
* If current user is authenticated the new users' table will replace the old one
|
||||||
* 28/02/2014 Massimiliano Pinto Added: client IPv4 in dcb->ipv4 and inet_ntop for string representation
|
* 28/02/2014 Massimiliano Pinto Added: client IPv4 in dcb->ipv4 and inet_ntop for string representation
|
||||||
|
* 11/03/2014 Massimiliano Pinto Added: Unix socket support
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -807,47 +808,94 @@ int gw_MySQLListener(
|
|||||||
{
|
{
|
||||||
int l_so;
|
int l_so;
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_in serv_addr;
|
||||||
|
struct sockaddr_un local_addr;
|
||||||
|
struct sockaddr *current_addr;
|
||||||
int one = 1;
|
int one = 1;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* this gateway, as default, will bind on port 4404 for localhost only */
|
if (strchr(config_bind, '/')) {
|
||||||
if (!parse_bindconfig(config_bind, 4406, &serv_addr))
|
char *tmp = strrchr(config_bind, ':');
|
||||||
return 0;
|
if (tmp)
|
||||||
listen_dcb->fd = -1;
|
*tmp = '\0';
|
||||||
|
|
||||||
// socket create
|
// UNIX socket create
|
||||||
if ((l_so = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
if ((l_so = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\n* Error: can't open listening socket due "
|
"\n* Error: can't create UNIX socket due "
|
||||||
"error %i, %s.\n\n\t",
|
"error %i, %s.\n\n\t",
|
||||||
errno,
|
errno,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
memset(&local_addr, 0, sizeof(local_addr));
|
||||||
|
local_addr.sun_family = AF_UNIX;
|
||||||
|
strncpy(local_addr.sun_path, config_bind, sizeof(local_addr.sun_path) - 1);
|
||||||
|
|
||||||
|
current_addr = (struct sockaddr *) &local_addr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* MaxScale, as default, will bind on port 4406 */
|
||||||
|
if (!parse_bindconfig(config_bind, 4406, &serv_addr)) {
|
||||||
|
fprintf(stderr, "Error in parse_bindconfig for [%s]\n", config_bind);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// TCP socket create
|
||||||
|
if ((l_so = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n* Error: can't create socket due "
|
||||||
|
"error %i, %s.\n\n\t",
|
||||||
|
errno,
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_addr = (struct sockaddr *) &serv_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listen_dcb->fd = -1;
|
||||||
|
|
||||||
// socket options
|
// socket options
|
||||||
setsockopt(l_so, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
|
setsockopt(l_so, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
|
||||||
|
|
||||||
// set NONBLOCKING mode
|
// set NONBLOCKING mode
|
||||||
setnonblocking(l_so);
|
setnonblocking(l_so);
|
||||||
|
|
||||||
|
/* get the right socket family for bind */
|
||||||
|
switch (current_addr->sa_family) {
|
||||||
|
case AF_UNIX:
|
||||||
|
rc = unlink(config_bind);
|
||||||
|
if ( (rc == -1) && (errno!=ENOENT) ) {
|
||||||
|
fprintf(stderr, "Error unlink Unix Socket %s\n", config_bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(l_so, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n* Bind failed due error %i, %s.\n",
|
||||||
|
errno,
|
||||||
|
strerror(errno));
|
||||||
|
fprintf(stderr, "* Can't bind to %s\n\n", config_bind);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET:
|
||||||
|
if (bind(l_so, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n* Bind failed due error %i, %s.\n",
|
||||||
|
errno,
|
||||||
|
strerror(errno));
|
||||||
|
fprintf(stderr, "* Can't bind to %s\n\n", config_bind);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "* Socket Family %i not supported\n", current_addr->sa_family);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// bind address and port
|
|
||||||
if (bind(l_so, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"\n* Bind failed due error %i, %s.\n",
|
|
||||||
errno,
|
|
||||||
strerror(errno));
|
|
||||||
fprintf(stderr, "* Can't bind to %s\n\n",
|
|
||||||
config_bind);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
fprintf(stderr,
|
|
||||||
">> GATEWAY bind is: %s:%i. FD is %i\n",
|
|
||||||
address,
|
|
||||||
port,
|
|
||||||
l_so);
|
|
||||||
*/
|
|
||||||
|
|
||||||
rc = listen(l_so, 10 * SOMAXCONN);
|
rc = listen(l_so, 10 * SOMAXCONN);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
@ -863,11 +911,6 @@ int gw_MySQLListener(
|
|||||||
strerror(eno));
|
strerror(eno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
fprintf(stderr,
|
|
||||||
">> GATEWAY listen backlog queue is %i\n",
|
|
||||||
10 * SOMAXCONN);
|
|
||||||
*/
|
|
||||||
// assign l_so to dcb
|
// assign l_so to dcb
|
||||||
listen_dcb->fd = l_so;
|
listen_dcb->fd = l_so;
|
||||||
|
|
||||||
@ -908,8 +951,8 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
DCB *client_dcb;
|
DCB *client_dcb;
|
||||||
MySQLProtocol *protocol;
|
MySQLProtocol *protocol;
|
||||||
int c_sock;
|
int c_sock;
|
||||||
struct sockaddr_in local;
|
struct sockaddr client_conn;
|
||||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
socklen_t client_len = sizeof(struct sockaddr_storage);
|
||||||
int sendbuf = GW_BACKEND_SO_SNDBUF;
|
int sendbuf = GW_BACKEND_SO_SNDBUF;
|
||||||
socklen_t optlen = sizeof(sendbuf);
|
socklen_t optlen = sizeof(sendbuf);
|
||||||
int eno = 0;
|
int eno = 0;
|
||||||
@ -932,8 +975,8 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
#endif /* SS_DEBUG */
|
#endif /* SS_DEBUG */
|
||||||
// new connection from client
|
// new connection from client
|
||||||
c_sock = accept(listener->fd,
|
c_sock = accept(listener->fd,
|
||||||
(struct sockaddr *) &local,
|
(struct sockaddr *) &client_conn,
|
||||||
&addrlen);
|
&client_len);
|
||||||
eno = errno;
|
eno = errno;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
@ -1020,19 +1063,38 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
setnonblocking(c_sock);
|
setnonblocking(c_sock);
|
||||||
|
|
||||||
client_dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
|
client_dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
|
||||||
|
|
||||||
|
if (client_dcb == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [gw_MySQLAccept] Failed to create "
|
||||||
|
"dcb object for client connection.",
|
||||||
|
pthread_self())));
|
||||||
|
rc = 1;
|
||||||
|
goto return_rc;
|
||||||
|
}
|
||||||
|
|
||||||
client_dcb->service = listener->session->service;
|
client_dcb->service = listener->session->service;
|
||||||
client_dcb->fd = c_sock;
|
client_dcb->fd = c_sock;
|
||||||
|
|
||||||
/* client IPv4 in raw data*/
|
// get client address
|
||||||
memcpy(&client_dcb->ipv4, &local, sizeof(struct sockaddr_in));
|
if ( client_conn.sa_family == AF_UNIX) {
|
||||||
|
// client address
|
||||||
/* client IPv4 in string representation */
|
client_dcb->remote = strdup("localhost_from_socket");
|
||||||
client_dcb->remote = (char *)calloc(INET_ADDRSTRLEN+1, sizeof(char));
|
// set localhost IP for user authentication
|
||||||
if (client_dcb->remote != NULL) {
|
(client_dcb->ipv4).sin_addr.s_addr = 0x0100007F;
|
||||||
inet_ntop(AF_INET, &(client_dcb->ipv4).sin_addr, client_dcb->remote, INET_ADDRSTRLEN);
|
} else {
|
||||||
|
/* client IPv4 in raw data*/
|
||||||
|
memcpy(&client_dcb->ipv4, (struct sockaddr_in *)&client_conn, sizeof(struct sockaddr_in));
|
||||||
|
/* client IPv4 in string representation */
|
||||||
|
client_dcb->remote = (char *)calloc(INET_ADDRSTRLEN+1, sizeof(char));
|
||||||
|
if (client_dcb->remote != NULL) {
|
||||||
|
inet_ntop(AF_INET, &(client_dcb->ipv4).sin_addr, client_dcb->remote, INET_ADDRSTRLEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol = mysql_protocol_init(client_dcb, c_sock);
|
protocol = mysql_protocol_init(client_dcb, c_sock);
|
||||||
|
|
||||||
ss_dassert(protocol != NULL);
|
ss_dassert(protocol != NULL);
|
||||||
|
|
||||||
if (protocol == NULL) {
|
if (protocol == NULL) {
|
||||||
|
Reference in New Issue
Block a user