Add IPv6 support

pull/726/head
Donatas Abraitis 10 years ago committed by Donatas Abraitis
parent 799c7d411a
commit d4b3488046

@ -10,6 +10,8 @@
#define EXPMARIA
#define BUFLEN 256
extern const CHARSET_INFO * proxysql_find_charset_name(const char * const name);
extern MySQL_Authentication *GloMyAuth;
@ -1736,13 +1738,22 @@ __get_pkts_from_client:
default:
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Statuses: WAITING_CLIENT_DATA - STATE_UNKNOWN\n");
{
char buf[256];
if (client_myds->client_addr->sa_family==AF_INET) {
struct sockaddr_in * ipv4addr=(struct sockaddr_in *)client_myds->client_addr;
sprintf(buf,"%s:%d", inet_ntoa(ipv4addr->sin_addr), htons(ipv4addr->sin_port));
} else {
sprintf(buf,"localhost");
}
char buf[BUFLEN];
switch (client_myds->client_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)client_myds->client_addr;
inet_ntop(client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)client_myds->client_addr;
inet_ntop(client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN);
break;
}
default:
sprintf(buf, "localhost");
break;
}
proxy_error("Unexpected packet from client %s . Session_status: %d , client_status: %d Disconnecting it\n", buf, status, client_myds->status);
}
return -1;

@ -10,18 +10,7 @@ MySQL_Session *sess_stopat;
#define PROXYSQL_LISTEN_LEN 1024
#define MIN_THREADS_FOR_MAINTENANCE 8
/*
// qsort int comparison function
static int int_cmp(const void *a, const void *b) {
const int *ia = (const int *)a; // casting pointer types
const int *ib = (const int *)b;
return *ia - *ib;
// integer comparison: returns negative if b > a
// and positive if a > b
}
*/
#define BUFLEN 256
extern Query_Processor *GloQPro;
extern MySQL_Authentication *GloMyAuth;
@ -107,8 +96,24 @@ int MySQL_Listeners_Manager::add(const char *iface, unsigned int num_threads, in
}
}
char *address=NULL; char *port=NULL;
c_split_2(iface, ":" , &address, &port);
int s=-1;
int s = -1;
char *h = NULL;
if (*(char *)iface == '[') {
char *p = strchr((char *)iface, ']');
if (p == NULL) {
proxy_error("Invalid IPv6 address: %s\n", iface);
return -1;
}
h = (char *)++iface; // remove first '['
*p = '\0';
iface = p++; // remove last ']'
address = h;
port = ++p; // remove ':'
} else {
c_split_2(iface, ":" , &address, &port);
}
#ifdef SO_REUSEPORT
if (GloVars.global.reuseport==false) {
s = ( atoi(port) ? listen_on_port(address, atoi(port), PROXYSQL_LISTEN_LEN) : listen_on_unix(address, PROXYSQL_LISTEN_LEN));
@ -2846,13 +2851,29 @@ void MySQL_Thread::listener_handle_new_connection(MySQL_Data_Stream *myds, unsig
}
sess->client_myds->client_addrlen=addrlen;
sess->client_myds->client_addr=addr;
if (sess->client_myds->client_addr->sa_family==AF_INET) {
struct sockaddr_in * ipv4addr=(struct sockaddr_in *)sess->client_myds->client_addr;
sess->client_myds->addr.addr=strdup(inet_ntoa(ipv4addr->sin_addr));
sess->client_myds->addr.port=htons(ipv4addr->sin_port);
} else {
sess->client_myds->addr.addr=strdup("localhost");
}
switch (sess->client_myds->client_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr;
char buf[BUFLEN];
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN);
sess->client_myds->addr.addr = strdup(buf);
sess->client_myds->addr.port = htons(ipv4->sin_port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr;
char buf[BUFLEN];
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN);
sess->client_myds->addr.addr = strdup(buf);
sess->client_myds->addr.port = htons(ipv6->sin6_port);
break;
}
default:
sess->client_myds->addr.addr = strdup("localhost");
break;
}
iface_info *ifi=NULL;
ifi=GloMTH->MLM_find_iface_from_fd(myds->fd); // here we try to get the info about the proxy bind address
if (ifi) {
@ -3114,6 +3135,7 @@ void MySQL_Threads_Handler::Get_Memory_Stats() {
SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() {
const int colnum=14;
char port[NI_MAXSERV];
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 4, "Dumping MySQL Processlist\n");
SQLite3_result *result=new SQLite3_result(colnum);
result->add_column_definition(SQLITE_TEXT,"ThreadID");
@ -3173,15 +3195,31 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() {
pta[3]=strdup(ui->schemaname);
}
}
if (sess->mirror==false && sess->client_myds->client_addr->sa_family==AF_INET) {
struct sockaddr_in * ipv4addr=(struct sockaddr_in *)sess->client_myds->client_addr;
pta[4]=strdup(inet_ntoa(ipv4addr->sin_addr));
sprintf(buf,"%d", htons(ipv4addr->sin_port));
pta[5]=strdup(buf);
} else {
pta[4]=strdup("localhost");
pta[5]=NULL;
}
if (sess->mirror==false) {
switch (sess->client_myds->client_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[5] = strdup(port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[5] = strdup(port);
break;
}
default:
pta[4] = strdup("localhost");
pta[5] = NULL;
break;
}
}
sprintf(buf,"%d", sess->current_hostgroup);
pta[6]=strdup(buf);
if (sess->mybe && sess->mybe->server_myds && sess->mybe->server_myds->myconn) {
@ -3194,15 +3232,28 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() {
int rc;
rc=getsockname(mc->fd, &addr, &addr_len);
if (rc==0) {
if (addr.sa_family==AF_INET) {
struct sockaddr_in * ipv4addr=(struct sockaddr_in *)&addr;
pta[7]=strdup(inet_ntoa(ipv4addr->sin_addr));
sprintf(buf,"%d", htons(ipv4addr->sin_port));
pta[8]=strdup(buf);
} else {
pta[7]=strdup("localhost");
pta[8]=NULL;
}
switch (addr.sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)&addr;
inet_ntop(addr.sa_family, &ipv4->sin_addr, buf, BUFLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[8] = strdup(port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&addr;
inet_ntop(addr.sa_family, &ipv6->sin6_addr, buf, BUFLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[8] = strdup(port);
break;
}
default:
pta[7] = strdup("localhost");
pta[8] = NULL;
break;
}
} else {
pta[7]=NULL;
pta[8]=NULL;

@ -2353,7 +2353,22 @@ __end_while_pool:
i=0; j=0;
for (j=0; j<S_amll.ifaces_mysql->ifaces->len; j++) {
char *add=NULL; char *port=NULL; char *sn=(char *)S_amll.ifaces_mysql->ifaces->index(j);
c_split_2(sn, ":" , &add, &port);
char *h = NULL;
if (*sn == '[') {
char *p = strchr(sn, ']');
if (p == NULL)
proxy_error("Invalid IPv6 address: %s\n", sn);
h = ++sn; // remove first '['
*p = '\0';
sn = p++; // remove last ']'
add = h;
port = ++p; // remove ':'
} else {
c_split_2(sn, ":" , &add, &port);
}
int s = ( atoi(port) ? listen_on_port(add, atoi(port), 128) : listen_on_unix(add, 128));
if (s>0) { fds[nfds].fd=s; fds[nfds].events=POLLIN; fds[nfds].revents=0; callback_func[nfds]=0; socket_names[nfds]=strdup(sn); nfds++; }
}

@ -5,51 +5,63 @@
* returns the socket
*/
int listen_on_port(char *ip, uint16_t port, int backlog, bool reuseport) {
int rc, arg_on=1;
struct sockaddr_in addr;
int sd;
// create a socket
if ( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) {
proxy_error("Error on creating socket\n");
close(sd);
return -1;
}
// set SO_REUSEADDR
rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg_on, sizeof(arg_on));
if (rc < 0) {
proxy_error("setsockopt() failed\n");
}
int arg_on = 1;
struct addrinfo hints = {
.ai_flags = AI_PASSIVE,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM
};
struct addrinfo *next, *ai;
char port_string[NI_MAXSERV];
int sd = -1;
snprintf(port_string, sizeof(port_string), "%d", port);
if (getaddrinfo(ip, port_string, &hints, &ai) != 0) {
proxy_error("getaddrinfo(): %s\n", gai_strerror(errno));
return -1;
}
for (next = ai; next != NULL; next = next->ai_next) {
if ((sd = socket(next->ai_family, next->ai_socktype, next->ai_protocol)) == -1)
continue;
#ifdef IPV6_V6ONLY
if (next->ai_family == AF_INET6) {
if(setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&arg_on, sizeof(arg_on)) == -1)
proxy_error("setsockopt() IPV6_V6ONLY: %d\n", gai_strerror(errno));
}
#endif
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg_on, sizeof(arg_on)) == -1) {
proxy_error("setsockopt() SO_REUSEADDR: %s\n", gai_strerror(errno));
close(sd);
freeaddrinfo(ai);
return -1;
}
#ifdef SO_REUSEPORT
// set SO_REUSEPORT
if (reuseport) {
rc = setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&arg_on, sizeof(arg_on));
if (rc < 0) {
proxy_error("setsockopt() failed\n");
if (reuseport) {
if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&arg_on, sizeof(arg_on)) == -1) {
proxy_error("setsockopt() SO_REUSEPORT: %d\n", gai_strerror(errno));
}
}
}
#endif /* SO_REUSEPORT */
// define addr with the specified IP and port
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
// call bind() to bind the socket on the specified address
if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) {
proxy_error("Error on Bind , address %s:%d\n", ip, port);
close(sd);
return -1;
}
// define the backlog
if ( listen(sd, backlog) != 0 ) {
proxy_error("Error on Listen , address %s:%d\n", ip, port);
close(sd);
return -1;
}
if (bind(sd, next->ai_addr, next->ai_addrlen) == -1) {
if (errno != EADDRINUSE) {
proxy_error("bind(): %s\n", gai_strerror(errno));
close(sd);
freeaddrinfo(ai);
return -1;
}
} else {
if (listen(sd, backlog) == -1) {
proxy_error("listen(): %s\n", gai_strerror(errno));
close(sd);
freeaddrinfo(ai);
return -1;
}
}
}
// return the socket
return sd;

Loading…
Cancel
Save