diff --git a/server/core/config.c b/server/core/config.c index 826fd9b58..316fa6ecf 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -340,11 +340,13 @@ int error_count = 0; else if (!strcmp(type, "listener")) { char *service; + char *address; char *port; char *protocol; service = config_get_value(obj->parameters, "service"); port = config_get_value(obj->parameters, "port"); + address = config_get_value(obj->parameters, "address"); protocol = config_get_value(obj->parameters, "protocol"); if (service && port && protocol) @@ -356,6 +358,7 @@ int error_count = 0; { serviceAddProtocol(ptr->element, protocol, + address, atoi(port)); } else @@ -758,8 +761,10 @@ SERVER *server; char *service; char *port; char *protocol; + char *address; service = config_get_value(obj->parameters, "service"); + address = config_get_value(obj->parameters, "address"); port = config_get_value(obj->parameters, "port"); protocol = config_get_value(obj->parameters, "protocol"); @@ -777,6 +782,7 @@ SERVER *server; { serviceAddProtocol(ptr->element, protocol, + address, atoi(port)); serviceStartProtocol(ptr->element, protocol, diff --git a/server/core/gw_utils.c b/server/core/gw_utils.c index ad81843a8..c3f230906 100644 --- a/server/core/gw_utils.c +++ b/server/core/gw_utils.c @@ -32,6 +32,7 @@ * 01-07-2013 Massimiliano Pinto Removed session->backends * from gw_read_gwbuff() * 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo + * 06-02-2014 Mark Riddoch Added parse_bindconfig * *@endverbatim */ @@ -40,9 +41,14 @@ #include #include +#include +#include + SPINLOCK tmplock = SPINLOCK_INIT; -/** +extern int lm_enabled_logfiles_bitmask; + +/* * Set IP address in socket structure in_addr * * @param a Pointer to a struct in_addr into which the address is written @@ -184,3 +190,64 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) { return 0; } +/** + * Parse the bind config data. This is passed in a string as address:port. + * + * The address may be either a . seperated IP address or a hostname to + * lookup. The address 0.0.0.0 is the wildcard address for SOCKADR_ANY. + * The ':' and port may be omitted, in which case the default port is + * used. + * + * @param config The bind address and port seperated by a ':' + * @param def_port The default port to use + * @param addr The sockaddr_in in which the data is written + * @return 0 on failure + */ +int +parse_bindconfig(char *config, unsigned short def_port, struct sockaddr_in *addr) +{ +char *port, buf[1024]; +short pnum; +struct hostent *hp; + + + strncpy(buf, config, 1024); + port = strrchr(buf, ':'); + if (port) + { + *port = 0; + port++; + pnum = atoi(port); + } + else + { + pnum = def_port; + } + + if (!strcmp(buf, "0.0.0.0")) + { + addr->sin_addr.s_addr = htonl(INADDR_ANY); + } + else + { + if (!inet_aton(buf, &addr->sin_addr)) + { + if ((hp = gethostbyname(buf)) != NULL) + { + bcopy(hp->h_addr, &(addr->sin_addr.s_addr), hp->h_length); + } + else + { + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error : Failed to lookup host '%s'. ", + buf))); + return 0; + } + } + } + + addr->sin_family = AF_INET; + addr->sin_port = htons(pnum); + return 1; +} diff --git a/server/core/service.c b/server/core/service.c index 2fb3f5e50..f3a065441 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -135,7 +135,10 @@ GWPROTOCOL *funcs; } memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL)); port->listener->session = NULL; - sprintf(config_bind, "0.0.0.0:%d", port->port); + if (port->address) + sprintf(config_bind, "%s:%d", port->address, port->port); + else + sprintf(config_bind, "0.0.0.0:%d", port->port); if (port->listener->func.listen(port->listener, config_bind)) { port->listener->session = session_alloc(service, port->listener); @@ -335,11 +338,12 @@ SERVICE *ptr; * * @param service The service * @param protocol The name of the protocol module + * @param address The address to listen with * @param port The port to listen on * @return TRUE if the protocol/port could be added */ int -serviceAddProtocol(SERVICE *service, char *protocol, unsigned short port) +serviceAddProtocol(SERVICE *service, char *protocol, char *address, unsigned short port) { SERV_PROTOCOL *proto; @@ -348,6 +352,10 @@ SERV_PROTOCOL *proto; return 0; } proto->protocol = strdup(protocol); + if (address) + proto->address = strdup(address); + else + proto->address = NULL; proto->port = port; spinlock_acquire(&service->spin); proto->next = service->ports; @@ -358,7 +366,7 @@ SERV_PROTOCOL *proto; } /** - * Check if a protocol/port pair si part of the service + * Check if a protocol/port pair is part of the service * * @param service The service * @param protocol The name of the protocol module diff --git a/server/include/gw.h b/server/include/gw.h index b03a924f7..98e48c60a 100644 --- a/server/include/gw.h +++ b/server/include/gw.h @@ -27,8 +27,6 @@ #define GW_BACKEND_SO_SNDBUF 1024 #define GW_NOINTR_CALL(A) do { errno = 0; A; } while (errno == EINTR) -#define GW_VERSION "0.1.0" -#define GW_MYSQL_VERSION "5.5.22-SKYSQL-" GW_VERSION #define GW_MYSQL_LOOP_TIMEOUT 300000000 #define GW_MYSQL_READ 0 #define GW_MYSQL_WRITE 1 @@ -51,7 +49,6 @@ void gw_daemonize(void); int do_read_dcb(DCB *dcb); void MySQLListener(int epfd, char *config_bind); int MySQLAccept(DCB *listener); -int gw_mysql_do_authentication(DCB *dcb, GWBUF *); char *gw_strend(register const char *s); int do_read_dcb(DCB *dcb); int do_read_10(DCB *dcb, uint8_t *buffer); @@ -61,3 +58,4 @@ int gw_read_backend_event(DCB *dcb); int setnonblocking(int fd); int gw_write(int fd, const void* buf, size_t nbytes); int gw_getsockerrno(int fd); +int parse_bindconfig(char *, unsigned short, struct sockaddr_in *); diff --git a/server/include/service.h b/server/include/service.h index ffa6a3dad..630bfdd8b 100644 --- a/server/include/service.h +++ b/server/include/service.h @@ -54,6 +54,7 @@ struct users; typedef struct servprotocol { char *protocol; /**< Protocol module to load */ unsigned short port; /**< Port to listen on */ + char *address; /**< Address to listen with */ DCB *listener; /**< The DCB for the listener */ struct servprotocol *next; /**< Next service protocol */ @@ -112,7 +113,7 @@ typedef struct service { extern SERVICE *service_alloc(char *, char *); extern int service_free(SERVICE *); extern SERVICE *service_find(char *); -extern int serviceAddProtocol(SERVICE *, char *, unsigned short); +extern int serviceAddProtocol(SERVICE *, char *, char *, unsigned short); extern int serviceHasProtocol(SERVICE *, char *, unsigned short); extern void serviceAddBackend(SERVICE *, SERVER *); extern int serviceHasBackend(SERVICE *, SERVER *); diff --git a/server/modules/protocol/httpd.c b/server/modules/protocol/httpd.c index cc4faf0a9..f92e49598 100644 --- a/server/modules/protocol/httpd.c +++ b/server/modules/protocol/httpd.c @@ -38,6 +38,7 @@ */ #include +#include #define ISspace(x) isspace((int)(x)) #define HTTP_SERVER_STRING "Gateway(c) v.1.0.0" @@ -364,23 +365,12 @@ static int httpd_listen(DCB *listener, char *config) { struct sockaddr_in addr; -char *port; int one = 1; -short pnum; int rc; memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL)); - - port = strrchr(config, ':'); - if (port) - port++; - else - port = "6442"; - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - pnum = atoi(port); - addr.sin_port = htons(pnum); + if (!parse_bindconfig(config, 6442, &addr)) + return 0; if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index 5d27f090f..a8cde7337 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -34,6 +34,7 @@ #include #include #include +#include extern int lm_enabled_logfiles_bitmask; @@ -793,42 +794,13 @@ int gw_MySQLListener( { int l_so; struct sockaddr_in serv_addr; - char *bind_address_and_port = NULL; - char *p; - char address[1024] = ""; - int port = 0; int one = 1; int rc; /* this gateway, as default, will bind on port 4404 for localhost only */ - if (config_bind != NULL) { - bind_address_and_port = config_bind; - } else { - bind_address_and_port = "127.0.0.1:4406"; - } + if (!parse_bindconfig(config_bind, 4406, &serv_addr)) + return 0; listen_dcb->fd = -1; - memset(&serv_addr, 0, sizeof serv_addr); - serv_addr.sin_family = AF_INET; - p = strchr(bind_address_and_port, ':'); - - if (p) { - strncpy(address, bind_address_and_port, sizeof(address)); - address[sizeof(address)-1] = '\0'; - p = strchr(address, ':'); - *p = '\0'; - port = atoi(p+1); - setipaddress(&serv_addr.sin_addr, address); - - snprintf(address, - (sizeof(address) - 1), - "%s", - inet_ntoa(serv_addr.sin_addr)); - } else { - port = atoi(bind_address_and_port); - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - sprintf(address, "0.0.0.0"); - } - serv_addr.sin_port = htons(port); // socket create if ((l_so = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -852,7 +824,7 @@ int gw_MySQLListener( errno, strerror(errno)); fprintf(stderr, "* Can't bind to %s\n\n", - bind_address_and_port); + config_bind); return 0; } /* @@ -868,7 +840,7 @@ int gw_MySQLListener( if (rc == 0) { fprintf(stderr, "Listening MySQL connections at %s\n", - bind_address_and_port); + config_bind); } else { int eno = errno; errno = 0; diff --git a/server/modules/protocol/telnetd.c b/server/modules/protocol/telnetd.c index f76f0f7fe..f7d6c1815 100644 --- a/server/modules/protocol/telnetd.c +++ b/server/modules/protocol/telnetd.c @@ -280,8 +280,6 @@ int n_connect = 0; socklen_t addrlen = sizeof(struct sockaddr); DCB *client_dcb; TELNETD* telnetd_pr = NULL; - dcb_state_t old_state = DCB_STATE_UNDEFINED; - bool succp = FALSE; so = accept(dcb->fd, (struct sockaddr *)&addr, &addrlen); @@ -354,23 +352,14 @@ static int telnetd_listen(DCB *listener, char *config) { struct sockaddr_in addr; -char *port; int one = 1; -short pnum; int rc; memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL)); - port = strrchr(config, ':'); - if (port) - port++; - else - port = "4442"; + if (!parse_bindconfig(config, 4442, &addr)) + return 0; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - pnum = atoi(port); - addr.sin_port = htons(pnum); if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {