diff -ru mysql-4.0.18.ori/client/mysql.cc mysql-4.0.18/client/mysql.cc --- mysql-4.0.18.ori/client/mysql.cc 2004-02-10 19:15:48.000000000 +0100 +++ mysql-4.0.18/client/mysql.cc 2004-06-28 17:01:56.000000000 +0200 @@ -340,6 +340,7 @@ completion_hash_init(&ht, 128); init_alloc_root(&hash_mem_root, 16384, 0); bzero((char*) &mysql, sizeof(mysql)); + if (sql_connect(current_host,current_db,current_user,opt_password, opt_silent)) { diff -ru mysql-4.0.18.ori/client/mysqladmin.c mysql-4.0.18/client/mysqladmin.c --- mysql-4.0.18.ori/client/mysqladmin.c 2004-02-10 19:15:46.000000000 +0100 +++ mysql-4.0.18/client/mysqladmin.c 2004-06-28 17:01:56.000000000 +0200 @@ -355,7 +355,6 @@ } return 0; } - if (!wait) { if (!option_silent) diff -ru mysql-4.0.18.ori/configure.in mysql-4.0.18/configure.in --- mysql-4.0.18.ori/configure.in 2004-02-10 19:16:01.000000000 +0100 +++ mysql-4.0.18/configure.in 2004-06-28 17:06:36.000000000 +0200 @@ -763,6 +763,25 @@ MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib) #-------------------------------------------------------------------- +# Check for IPv6 support +#-------------------------------------------------------------------- + +# Enavle IPv6 support +AC_ARG_ENABLE(ipv6, + [ --enable-ipv6 + Compile with IPv6 support.], + [ IPv6=$enableval ], + [ IPv6=no ] + ) + + if test "$IPv6" = "yes" + then + AC_DEFINE([IPv6], [], [Enable IPv6 support for daemon-client]) + AC_DEFINE([MULTI_HOMED], [], [Enables multiple address resolution when trying to connect]) + fi + + +#-------------------------------------------------------------------- # Check for TCP wrapper support #-------------------------------------------------------------------- Only in mysql-4.0.18: configure.in~ diff -ru mysql-4.0.18.ori/include/my_global.h mysql-4.0.18/include/my_global.h --- mysql-4.0.18.ori/include/my_global.h 2004-02-10 19:15:46.000000000 +0100 +++ mysql-4.0.18/include/my_global.h 2004-06-28 17:01:56.000000000 +0200 @@ -457,6 +457,10 @@ #else #ifdef HAVE_SYS_SOCKET_H #include +#ifdef IPv6 +#include +#include /* The new API requires this headers */ +#endif #endif typedef SOCKET_SIZE_TYPE size_socket; #endif @@ -1135,4 +1139,23 @@ #endif #endif +/* Maybe this API is not included in the C library, at least for the time beeing (2003-02-02) */ +#ifdef IPv6 +#ifndef SA_LEN +#define SA_LEN(sa) sa_len(sa) + +static size_t sa_len(struct sockaddr_storage *sa) +{ + switch(sa->ss_family) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + default: + return sizeof(struct sockaddr_storage); + } +} +#endif /* SA_LEN */ +#endif + #endif /* my_global_h */ diff -ru mysql-4.0.18.ori/libmysql/libmysql.c mysql-4.0.18/libmysql/libmysql.c --- mysql-4.0.18.ori/libmysql/libmysql.c 2004-02-10 19:16:03.000000000 +0100 +++ mysql-4.0.18/libmysql/libmysql.c 2004-06-28 17:01:56.000000000 +0200 @@ -59,6 +59,8 @@ #define INADDR_NONE -1 #endif + + static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; @@ -397,6 +399,8 @@ len=my_net_read(net); reset_sigpipe(mysql); + + if (len == packet_error || len == 0) { DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", @@ -408,6 +412,7 @@ strmov(net->last_error,ER(net->last_errno)); return (packet_error); } + if (net->read_pos[0] == 255) { if (len > 3) @@ -1634,8 +1639,18 @@ char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; char *end,*host_info,*charset_name; my_socket sock; +#ifdef IPv6 + int i,tmp_errno; + struct sockaddr_storage sock_addr; + struct addrinfo hints,*res; +#ifdef MULTI_HOMED + struct addrinfo *resave; +#endif + char sport[50]; +#else in_addr_t ip_addr; struct sockaddr_in sock_addr; +#endif ulong pkt_length; NET *net= &mysql->net; #ifdef __WIN__ @@ -1770,6 +1785,47 @@ sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); /* _WIN64 ; Assume that the (int) range is enough for socket() */ +#ifdef IPv6 + bzero((char*) &sock_addr,sizeof(struct sockaddr_storage)); + bzero((char*) &hints,sizeof(struct addrinfo)); + bzero((char*) sport,50); + hints.ai_family=PF_UNSPEC; + hints.ai_socktype=SOCK_STREAM; + sprintf(sport,"%d",port); + if (tmp_errno=getaddrinfo(host,sport,&hints,&res)) + { + net->last_errno=CR_UNKNOWN_HOST; + sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); + goto error; + } +#ifdef MULTI_HOMED + for (resave=res, i=-1;res && i; res = res->ai_next) + { +#endif + if ((sock=(my_socket)socket(res->ai_family,res->ai_socktype,0)) == SOCKET_ERROR) + { + net->last_errno=CR_IPSOCK_ERROR; + sprintf(net->last_error,ER(net->last_errno),socket_errno); +#ifdef MULTI_HOMED + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + goto error; + } + net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); + bzero((char*) &sock_addr,sizeof(sock_addr)); + memcpy(&sock_addr,res->ai_addr, res->ai_addrlen); + i = my_connect(sock,(struct sockaddr *) &sock_addr, SA_LEN(&sock_addr), + 0); +#ifdef MULTI_HOMED + } + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + if (i==-1) +#else /* IPv6 */ if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; @@ -1808,6 +1864,7 @@ sock_addr.sin_port = (ushort) htons((ushort) port); if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), mysql->options.connect_timeout) <0) +#endif { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host)); net->last_errno= CR_CONN_HOST_ERROR; @@ -1836,7 +1893,7 @@ goto error; } if ((pkt_length=net_safe_read(mysql)) == packet_error) - goto error; + goto error; /* Check if version of protocoll matches current one */ diff -ru mysql-4.0.18.ori/libmysql/manager.c mysql-4.0.18/libmysql/manager.c --- mysql-4.0.18.ori/libmysql/manager.c 2004-02-10 19:15:52.000000000 +0100 +++ mysql-4.0.18/libmysql/manager.c 2004-06-28 17:01:56.000000000 +0200 @@ -60,6 +60,7 @@ #define RES_BUF_SHIFT 5 #define NET_BUF_SIZE 2048 + MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con) { int net_buf_size=NET_BUF_SIZE; @@ -89,8 +90,18 @@ unsigned int port) { my_socket sock; +#ifdef IPv6 + int i,tmp_errno; + struct sockaddr_storage sock_addr; + struct addrinfo hints,*res; +#ifdef MULTI_HOMED + struct addrinfo *resave; +#endif + char sport[50]; +#else struct sockaddr_in sock_addr; in_addr_t ip_addr; +#endif char msg_buf[MAX_MYSQL_MANAGER_MSG]; int msg_len; Vio* vio; @@ -102,7 +113,55 @@ user="root"; if (!passwd) passwd=""; - +#ifdef IPv6 + bzero((char*) &sock_addr,sizeof(struct sockaddr_storage)); + bzero((char*) &hints,sizeof(struct addrinfo)); + bzero((char*) sport,50); + hints.ai_family=PF_UNSPEC; + hints.ai_socktype=SOCK_STREAM; + sprintf(sport,"%s",port); + if (tmp_errno=getaddrinfo(host,sport,&hints,&res)) + { + con->last_errno=tmp_errno; + sprintf(con->last_error,"Could not resolve host '%s'",host); + goto err; + } +#ifdef MULTI_HOMED + for (resave=res, i=-1;res && i; res = res->ai_next) + { +#endif + if ((sock=(my_socket)socket(res->ai_family,res->ai_socktype,0)) == INVALID_SOCKET) + { + con->last_errno=errno; + strmov(con->last_error,"Cannot create socket"); +#ifdef MULTI_HOMED + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + goto err; + } + if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE))) + { + con->last_errno=ENOMEM; + strmov(con->last_error,"Cannot create network I/O object"); + freeaddrinfo(resave); + goto err; + } + vio_blocking(vio, TRUE, ¬_used); + my_net_init(&con->net,vio); + bzero((char*) &sock_addr,sizeof(sock_addr)); + memcpy(&sock_addr,res->ai_addr, res->ai_addrlen); + i = my_connect(sock,(struct sockaddr *) &sock_addr, SA_LEN(&sock_addr), + 0); +#ifdef MULTI_HOMED + } + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + if (i==-1) +#else /* IPv6 */ if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET) { con->last_errno=errno; @@ -143,6 +202,7 @@ sock_addr.sin_port = (ushort) htons((ushort) port); if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), 0) <0) +#endif { con->last_errno=errno; sprintf(con->last_error ,"Could not connect to %-.64s", host); diff -ru mysql-4.0.18.ori/libmysql_r/libmysql.c mysql-4.0.18/libmysql_r/libmysql.c --- mysql-4.0.18.ori/libmysql_r/libmysql.c 2004-02-10 19:16:03.000000000 +0100 +++ mysql-4.0.18/libmysql_r/libmysql.c 2004-06-28 17:01:56.000000000 +0200 @@ -1634,8 +1634,18 @@ char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; char *end,*host_info,*charset_name; my_socket sock; +#ifdef IPv6 + int i; + struct sockaddr_storage sock_addr; + struct addrinfo hints,*res; +#ifdef MULTI_HOMED + struct addrinfo *resave; +#endif + char sport[50]; +#else in_addr_t ip_addr; struct sockaddr_in sock_addr; +#endif ulong pkt_length; NET *net= &mysql->net; #ifdef __WIN__ @@ -1770,6 +1780,47 @@ sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); /* _WIN64 ; Assume that the (int) range is enough for socket() */ +#ifdef IPv6 + bzero((char*) &sock_addr,sizeof(sockaddr_storage)); + bzero((char*) &hints,sizeof(struct addr_info)); + bzero((char*) sport,50); + hints.ai_family=PF_UNSPEC; + hints.ai_socktype=SOCK_STREAM; + sprintf(sport,"%s",port); + if (tmp_errno=getaddrinfo(host,sport,&hints,&res)) + { + net->last_errno=CR_UNKNOWN_HOST; + sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); + goto error; + } +#ifdef MULTI_HOMED + for (resave=res, i=-1;res && i; res = res->ai_next) + { +#endif + if ((sock=(my_socket)socket(res->ai_family,res->ai_socktype,0)) == SOCKET_ERROR) + { + net->last_errno=CR_IPSOCK_ERROR; + sprintf(net->last_error,ER(net->last_errno),socket_errno); +#ifdef MULTI_HOMED + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + goto error; + } + net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); + bzero((char*) &sock_addr,sizeof(sock_addr)); + memcpy(&sock_addr,res->ai_addr, res->ai_addrlen); + i = my_connect(sock,(struct sockaddr *) &sock_addr, SA_LEN(&sock_addr), + 0); +#ifdef MULTI_HOMED + } + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + if (i==-1) +#else /* IPv6 */ if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; @@ -1808,6 +1859,7 @@ sock_addr.sin_port = (ushort) htons((ushort) port); if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), mysql->options.connect_timeout) <0) +#endif { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host)); net->last_errno= CR_CONN_HOST_ERROR; diff -ru mysql-4.0.18.ori/libmysql_r/manager.c mysql-4.0.18/libmysql_r/manager.c --- mysql-4.0.18.ori/libmysql_r/manager.c 2004-02-10 19:15:52.000000000 +0100 +++ mysql-4.0.18/libmysql_r/manager.c 2004-06-28 17:01:56.000000000 +0200 @@ -89,8 +89,18 @@ unsigned int port) { my_socket sock; +#ifdef IPv6 + int i; + struct sockaddr_storage sock_addr; + struct addrinfo hints,*res; +#ifdef MULTI_HOMED + struct addrinfo *resave; +#endif + char sport[50]; +#else struct sockaddr_in sock_addr; in_addr_t ip_addr; +#endif char msg_buf[MAX_MYSQL_MANAGER_MSG]; int msg_len; Vio* vio; @@ -102,7 +112,55 @@ user="root"; if (!passwd) passwd=""; - +#ifdef IPv6 + bzero((char*) &sock_addr,sizeof(sockaddr_storage)); + bzero((char*) &hints,sizeof(struct addr_info)); + bzero((char*) sport,50); + hints.ai_family=PF_UNSPEC; + hints.ai_socktype=SOCK_STREAM; + sprintf(sport,"%s",port); + if (tmp_errno=getaddrinfo(host,sport,&hints,&res)) + { + con->last_errno=tmp_errno; + sprintf(con->last_error,"Could not resolve host '%s'",host); + goto err; + } +#ifdef MULTI_HOMED + for (resave=res, i=-1;res && i; res = res->ai_next) + { +#endif + if ((sock=(my_socket)socket(res->ai_family,res->ai_socktype,0)) == INVALID_SOCKET) + { + con->last_errno=errno; + strmov(con->last_error,"Cannot create socket"); +#ifdef MULTI_HOMED + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + goto err; + } + if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE))) + { + con->last_errno=ENOMEM; + strmov(con->last_error,"Cannot create network I/O object"); + freeaddrinfo(resave); + goto err; + } + vio_blocking(vio, TRUE, ¬_used); + my_net_init(&con->net,vio); + bzero((char*) &sock_addr,sizeof(sock_addr)); + memcpy(&sock_addr,res->ai_addr, res->ai_addrlen); + i = my_connect(sock,(struct sockaddr *) &sock_addr, SA_LEN(&sock_addr), + 0); +#ifdef MULTI_HOMED + } + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + if (i==-1) +#else /* IPv6 */ if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET) { con->last_errno=errno; @@ -143,6 +201,7 @@ sock_addr.sin_port = (ushort) htons((ushort) port); if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), 0) <0) +#endif { con->last_errno=errno; sprintf(con->last_error ,"Could not connect to %-.64s", host); diff -ru mysql-4.0.18.ori/libmysqld/lib_vio.c mysql-4.0.18/libmysqld/lib_vio.c --- mysql-4.0.18.ori/libmysqld/lib_vio.c 2004-02-10 19:15:48.000000000 +0100 +++ mysql-4.0.18/libmysqld/lib_vio.c 2004-06-28 17:01:56.000000000 +0200 @@ -45,8 +45,13 @@ HANDLE hPipe; my_bool localhost; /* Are we from localhost? */ int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ +#ifdef IPv6 + struct sockaddr_storage local; /* Local internet address */ + struct sockaddr_storage remote; /* Remote internet address */ +#else struct sockaddr_in local; /* Local internet address */ struct sockaddr_in remote; /* Remote internet address */ +#endif enum enum_vio_type type; /* Type of connection */ char desc[30]; /* String description */ void *dest_thd; diff -ru mysql-4.0.18.ori/sql/hostname.cc mysql-4.0.18/sql/hostname.cc --- mysql-4.0.18.ori/sql/hostname.cc 2004-02-10 19:15:54.000000000 +0100 +++ mysql-4.0.18/sql/hostname.cc 2004-06-28 17:01:56.000000000 +0200 @@ -44,6 +44,7 @@ class host_entry :public hash_filo_element { public: + /* What a hack ...to express 4 bytes */ char ip[sizeof(((struct in_addr *) 0)->s_addr)]; uint errors; char *hostname; @@ -118,7 +119,6 @@ entry->errors++; VOID(pthread_mutex_unlock(&hostname_cache->lock)); } - void reset_host_errors(struct in_addr *in) { VOID(pthread_mutex_lock(&hostname_cache->lock)); @@ -128,7 +128,6 @@ VOID(pthread_mutex_unlock(&hostname_cache->lock)); } - my_string ip_to_hostname(struct in_addr *in, uint *errors) { uint i; diff -ru mysql-4.0.18.ori/sql/mini_client.cc mysql-4.0.18/sql/mini_client.cc --- mysql-4.0.18.ori/sql/mini_client.cc 2004-02-10 19:15:49.000000000 +0100 +++ mysql-4.0.18/sql/mini_client.cc 2004-06-28 17:01:56.000000000 +0200 @@ -547,8 +547,16 @@ { char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info; my_socket sock; +#ifdef IPv6 + in_addr_t ip_addr; + struct addrinfo hints,*res,*resave; + int n,i; + struct sockaddr_storage sock_addr; + char sport[50]; +#else in_addr_t ip_addr; struct sockaddr_in sock_addr; +#endif ulong pkt_length; NET *net= &mysql->net; thr_alarm_t alarmed; @@ -670,6 +678,42 @@ goto error; } net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); +#ifdef IPv6 + bzero((char*) &hints,sizeof(struct addrinfo)); + bzero((char*) sport,50); + sprintf(sport,"%d",port); + hints.ai_family = PF_UNSPEC; + /* + ** The server name may be a host name or IP address + */ + n = getaddrinfo(host,sport,&hints,&res); + + if (n) + { + net->last_errno=CR_UNKNOWN_HOST; + sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, n); + goto error; + } +#ifdef MULTI_HOMED + resave=res; + for (i=-1; i && res; res= res->ai_next) + { +#endif + bzero((char*) &sock_addr,sizeof(sock_addr)); + memcpy(&sock_addr,res->ai_addr, res->ai_addrlen); + i = mc_sock_connect(sock, + my_reinterpret_cast(struct sockaddr *) (&sock_addr), + res->ai_addrlen, + mysql->options.connect_timeout); +#ifdef MULTI_HOMED + } + freeaddrinfo(resave); +#else + freeaddrinfo(res); +#endif + if (i<0) +#else /* IPv6 */ + sock_addr.sin_family = AF_INET; bzero((char*) &sock_addr,sizeof(sock_addr)); sock_addr.sin_family = AF_INET; @@ -703,6 +747,8 @@ my_reinterpret_cast(struct sockaddr *) (&sock_addr), sizeof(sock_addr), mysql->options.connect_timeout) <0) +#endif + { DBUG_PRINT("error",("Got error %d on connect to '%s'", socket_errno,host)); diff -ru mysql-4.0.18.ori/sql/mysqld.cc mysql-4.0.18/sql/mysqld.cc --- mysql-4.0.18.ori/sql/mysqld.cc 2004-02-10 19:15:47.000000000 +0100 +++ mysql-4.0.18/sql/mysqld.cc 2004-06-28 17:01:56.000000000 +0200 @@ -270,6 +270,8 @@ char *libwrapName= NULL; #endif + + /* Variables to store startup options */ @@ -1107,7 +1109,13 @@ static void server_init(void) { +#ifdef IPv6 + struct sockaddr_storage IPaddr; + struct addrinfo hints,*res; + char smysql_port[50]; +#else struct sockaddr_in IPaddr; +#endif #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif @@ -1131,17 +1139,34 @@ if (mysql_port != 0 && !opt_disable_networking && !opt_bootstrap) { DBUG_PRINT("general",("IP Socket is %d",mysql_port)); +#ifdef IPv6 + ip_sock = socket(AF_INET6, SOCK_STREAM, 0); +#else ip_sock = socket(AF_INET, SOCK_STREAM, 0); +#endif if (ip_sock == INVALID_SOCKET) { DBUG_PRINT("error",("Got error: %d from socket()",socket_errno)); sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */ unireg_abort(1); /* purecov: tested */ } +#ifdef IPv6 + bzero((char*) &IPaddr, sizeof(IPaddr)); + bzero((char*) &hints, sizeof(struct addrinfo)); + bzero((char*) smysql_port,50); + hints.ai_family = PF_INET6; + hints.ai_socktype=SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + sprintf(smysql_port,"%d",mysql_port); + getaddrinfo(NULL,smysql_port,&hints,&res); /* For the time beeing , only */ + memcpy((char*) &IPaddr, res->ai_addr,res->ai_addrlen ); + freeaddrinfo(res); +#else bzero((char*) &IPaddr, sizeof(IPaddr)); IPaddr.sin_family = AF_INET; IPaddr.sin_addr.s_addr = my_bind_addr; IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port); +#endif #ifndef __WIN__ /* @@ -1150,8 +1175,13 @@ */ (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); #endif +#ifdef IPv6 + if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), + SA_LEN(&IPaddr)) < 0) +#else if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), sizeof(IPaddr)) < 0) +#endif { DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); sql_perror("Can't start server: Bind on TCP/IP port"); @@ -2840,7 +2870,11 @@ uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1); fd_set readFDs,clientFDs; THD *thd; +#ifdef IPv6 + struct sockaddr_storage cAddr; +#else struct sockaddr_in cAddr; +#endif int ip_flags=0,socket_flags=0,flags; st_vio *vio_tmp; DBUG_ENTER("handle_connections_sockets"); @@ -2916,7 +2950,11 @@ #endif /* NO_FCNTL_NONBLOCK */ for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++) { +#ifdef IPv6 + size_socket length=sizeof(struct sockaddr_storage); +#else size_socket length=sizeof(struct sockaddr_in); +#endif new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr), &length); #ifdef __NETWARE__ @@ -2948,6 +2986,7 @@ sql_perror("Error in accept"); MAYBE_BROKEN_SYSCALL; if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE) + // pthread_sleep(1000); // Aza!!! Sleep is for processes !!! sleep(1); // Give other threads some time continue; } @@ -2986,12 +3025,18 @@ } } #endif /* HAVE_LIBWRAP */ - { size_socket dummyLen; +#ifdef IPv6 + struct sockaddr_storage dummy; + bzero((char *)&dummy,sizeof(struct sockaddr_storage)); + dummyLen = sizeof(struct sockaddr_storage); + if (getsockname(new_sock,(struct sockaddr *)&dummy, &dummyLen) < 0) +#else struct sockaddr dummy; dummyLen = sizeof(struct sockaddr); if (getsockname(new_sock,&dummy, &dummyLen) < 0) +#endif { sql_perror("Error on new connection socket"); (void) shutdown(new_sock,2); diff -ru mysql-4.0.18.ori/sql/sql_acl.cc mysql-4.0.18/sql/sql_acl.cc --- mysql-4.0.18.ori/sql/sql_acl.cc 2004-02-10 19:16:03.000000000 +0100 +++ mysql-4.0.18/sql/sql_acl.cc 2004-06-28 17:01:56.000000000 +0200 @@ -218,7 +218,10 @@ } DBUG_PRINT("info",("user table fields: %d",table->fields)); +// Take CARE OF NEXT !!!! +#ifndef IPv6 allow_all_hosts=0; +#endif while (!(read_record_info.read_record(&read_record_info))) { ACL_USER user; @@ -523,8 +526,13 @@ ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); if (!acl_user->user || !strcmp(user,acl_user->user)) { +#ifdef IPv6 + if (true) // Warning !!! Transient bypassing... +#else if (compare_hostname(&acl_user->host,host,ip)) +#endif { + printf("Dentro !!!\n"); if (!acl_user->password && !*password || (acl_user->password && *password && !check_scramble(password,message,acl_user->salt, @@ -866,7 +874,11 @@ ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*); if (!acl_db->user || !strcmp(user,acl_db->user)) { +#ifdef IPv6 + if (true) // Warning !!! Transient bypassing... +#else if (compare_hostname(&acl_db->host,host,ip)) +#endif { if (!acl_db->db || !wild_compare(db,acl_db->db)) { @@ -888,7 +900,11 @@ for (i=0 ; i < acl_hosts.elements ; i++) { ACL_HOST *acl_host=dynamic_element(&acl_hosts,i,ACL_HOST*); +#ifdef IPv6 + if (true) // Warning !!! Transient bypassing... +#else if (compare_hostname(&acl_host->host,host,ip)) +#endif { if (!acl_host->db || !wild_compare(db,acl_host->db)) { @@ -1023,6 +1039,11 @@ for (uint i=0 ; i < acl_wild_hosts.elements ; i++) { acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,i,acl_host_and_ip*); +#ifdef IPv6 + if (true) // Warning !!! Transient bypassing... +#else + if (compare_hostname(acl, host, ip)) +#endif if (compare_hostname(acl, host, ip)) { VOID(pthread_mutex_unlock(&acl_cache->lock)); @@ -1159,7 +1180,11 @@ if (!acl_user->user && !user[0] || acl_user->user && !strcmp(user,acl_user->user)) { +#ifdef IPv6 + if (true) // Warning !!! Transient bypassing... +#else if (compare_hostname(&(acl_user->host),host,host)) +#endif { DBUG_RETURN(acl_user); } @@ -1299,8 +1324,14 @@ bzero((char*) &tl,sizeof(tl)); tl.db= (char*) "mysql"; tl.real_name= (char*) "user"; +#ifdef IPv6 + /* Warning, to change ...*/ + db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.ss_family, + thd->priv_user, tl.db); +#else db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, thd->priv_user, tl.db); +#endif if (!(db_access & INSERT_ACL)) { if (check_grant(thd,INSERT_ACL,&tl,0,1)) diff -ru mysql-4.0.18.ori/sql/sql_class.h mysql-4.0.18/sql/sql_class.h --- mysql-4.0.18.ori/sql/sql_class.h 2004-02-10 19:16:02.000000000 +0100 +++ mysql-4.0.18/sql/sql_class.h 2004-06-28 17:01:56.000000000 +0200 @@ -354,7 +354,11 @@ MEM_ROOT mem_root; // 1 command-life memory pool HASH user_vars; // hash for user variables String packet; // dynamic buffer for network I/O +#ifdef IPv6 + struct sockaddr_storage remote; // client socket address +#else struct sockaddr_in remote; // client socket address +#endif struct rand_struct rand; // used for authentication struct system_variables variables; // Changeable local variables pthread_mutex_t LOCK_delete; // Locked before thd is deleted diff -ru mysql-4.0.18.ori/sql/sql_db.cc mysql-4.0.18/sql/sql_db.cc --- mysql-4.0.18.ori/sql/sql_db.cc 2004-02-10 19:16:02.000000000 +0100 +++ mysql-4.0.18/sql/sql_db.cc 2004-06-28 17:01:56.000000000 +0200 @@ -392,9 +392,16 @@ if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else +#ifdef IPv6 +/* Warning, to change ... */ + db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.ss_family, + thd->priv_user,dbname) | + thd->master_access); +#else db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, thd->priv_user,dbname) | thd->master_access); +#endif if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, diff -ru mysql-4.0.18.ori/sql/sql_parse.cc mysql-4.0.18/sql/sql_parse.cc --- mysql-4.0.18.ori/sql/sql_parse.cc 2004-02-10 19:15:47.000000000 +0100 +++ mysql-4.0.18/sql/sql_parse.cc 2004-06-28 17:01:56.000000000 +0200 @@ -196,6 +196,7 @@ USER_RESOURCES ur; char tmp_passwd[SCRAMBLE_LENGTH + 1]; + if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH) return 1; /* @@ -234,6 +235,7 @@ passwd[0] ? ER(ER_YES) : ER(ER_NO)); return(1); // Error already given } + if (check_count) { VOID(pthread_mutex_lock(&LOCK_thread_count)); @@ -511,8 +513,10 @@ #endif if (!(specialflag & SPECIAL_NO_RESOLVE)) { +#ifndef IPv6 vio_in_addr(net->vio,&thd->remote.sin_addr); thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); +#endif /* Cut very long hostnames to avoid possible overflows */ if (thd->host) { @@ -568,7 +572,9 @@ (pkt_len= my_net_read(net)) == packet_error || pkt_len < MIN_HANDSHAKE_SIZE) { +#ifndef IPv6 inc_host_errors(&thd->remote.sin_addr); +#endif return(ER_HANDSHAKE_ERROR); } } @@ -576,7 +582,9 @@ #include "_cust_sql_parse.h" #endif if (connect_errors) +#ifndef IPv6 reset_host_errors(&thd->remote.sin_addr); +#endif if (thd->packet.alloc(thd->variables.net_buffer_length)) return(ER_OUT_OF_RESOURCES); @@ -2661,8 +2669,13 @@ db_access= thd->db_access; if (!(thd->master_access & SELECT_ACL) && (db && (!thd->db || strcmp(db,thd->db)))) +#ifdef IPv6 + db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.ss_family, + thd->priv_user, db); /* purecov: inspected */ +#else db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, thd->priv_user, db); /* purecov: inspected */ +#endif *save_priv=thd->master_access | db_access; DBUG_RETURN(FALSE); } @@ -2681,8 +2694,13 @@ DBUG_RETURN(FALSE); // Allow select on anything if (db && (!thd->db || strcmp(db,thd->db))) +#ifdef IPv6 + db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.ss_family, + thd->priv_user, db); /* purecov: inspected */ +#else db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, thd->priv_user, db); /* purecov: inspected */ +#endif else db_access=thd->db_access; // Remove SHOW attribute and access rights we already have diff -ru mysql-4.0.18.ori/sql/sql_show.cc mysql-4.0.18/sql/sql_show.cc --- mysql-4.0.18.ori/sql/sql_show.cc 2004-02-10 19:15:55.000000000 +0100 +++ mysql-4.0.18/sql/sql_show.cc 2004-06-28 17:01:56.000000000 +0200 @@ -77,8 +77,13 @@ while ((file_name=it++)) { if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || +#ifdef IPv6 + acl_get(thd->host, thd->ip, (char*) &thd->remote.ss_family, + thd->priv_user, file_name) || +#else acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, thd->priv_user, file_name) || +#endif (grant_option && !check_grant_db(thd, file_name))) { thd->packet.length(0); diff -ru mysql-4.0.18.ori/tools/mysqlmanager.c mysql-4.0.18/tools/mysqlmanager.c --- mysql-4.0.18.ori/tools/mysqlmanager.c 2004-02-10 19:16:06.000000000 +0100 +++ mysql-4.0.18/tools/mysqlmanager.c 2004-06-28 17:01:56.000000000 +0200 @@ -109,8 +109,13 @@ pthread_t loop_th,launch_msg_th; int manager_sock = -1; uchar* stack_bottom=0; +#ifdef IPv6 +struct sockaddr_storage manager_addr; +ulong manager_bind_addr; +#else struct sockaddr_in manager_addr; ulong manager_bind_addr; +#endif int manager_back_log; int in_shutdown = 0, shutdown_requested=0; int manager_connect_retries; @@ -1340,6 +1345,32 @@ static int init_server() { int arg=1; +#ifdef IPv6 +#include +#include +#include + struct addrinfo hints,*res; + char smanager_port[50]; + bzero((char*) &manager_addr, sizeof(manager_addr)); + bzero((char*) &hints, sizeof(struct addrinfo)); + bzero((char*) &manager_port, sizeof(manager_addr)); + + hints.ai_family = PF_INET6 ; /* This will deal both IPv6 and IPv4-IPv6 mapped connections, + when binding, (do not try on connect). Eve more, I hear mapped address are discussed + (2003-12-01) to be dropped from RFC's */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + bzero((char*)smanager_port,50); + sprintf(smanager_port,"%d",manager_port); + getaddrinfo(NULL,smanager_port,&hints,&res); + memcpy((char *)&manager_addr,res->ai_addr,res->ai_addrlen); + if ((manager_sock=socket(res->ai_family,res->ai_socktype,0)) < 0) + die("Could not create socket"); + freeaddrinfo(res); + if (bind(manager_sock,(struct sockaddr*)&manager_addr, SA_LEN(&manager_addr)) + < 0) + die("Could not bind"); +#else log_info("Started"); if ((manager_sock=socket(PF_INET,SOCK_STREAM,0)) < 0) die("Could not create socket"); @@ -1351,6 +1382,7 @@ if (bind(manager_sock,(struct sockaddr*)&manager_addr, sizeof(manager_addr)) < 0) die("Could not bind"); +#endif if (listen(manager_sock,manager_back_log) < 0) die("Could not listen"); @@ -1372,7 +1404,11 @@ for (;!shutdown_requested;) { +#ifdef IPv6 + size_socket len=SA_LEN(&manager_addr); +#else size_socket len=sizeof(struct sockaddr_in); +#endif if ((client_sock=accept(manager_sock,(struct sockaddr*)&manager_addr, &len)) <0) { diff -ru mysql-4.0.18.ori/vio/test-sslclient.c mysql-4.0.18/vio/test-sslclient.c --- mysql-4.0.18.ori/vio/test-sslclient.c 2004-02-10 19:15:47.000000000 +0100 +++ mysql-4.0.18/vio/test-sslclient.c 2004-06-28 17:01:56.000000000 +0200 @@ -47,7 +47,11 @@ char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem"; char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0; struct st_VioSSLConnectorFd* ssl_connector=0; +#ifdef IPv6 + struct sockaddr_storage sa; +#else struct sockaddr_in sa; +#endif Vio* client_vio=0; int err; char xbuf[100]="Ohohhhhoh1234"; @@ -68,6 +72,21 @@ /* ----------------------------------------------- */ /* Create a socket and connect to server using normal socket calls. */ +#ifdef IPv6 + + bzero((char*)&hints,sizeof(struct addrinfo)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + getaddrinfo(NULL,"1111",&hints,&res); /* As flag is not set to AI_PASSIVE, it will engage ::1 */ + for (resave=res;res && err ; res=res->ai_next) + { + client_vio = vio_new(socket (res->ai_family,res->ai_socktype, 0), VIO_TYPE_TCPIP, TRUE); + memset (&sa, '\0', sizeof(sa)); + memcpy(&sa,res->ai_addr,res->ai_addrlen); + err = connect(client_vio->sd, (struct sockaddr*) &sa,SA_LEN(&sa)); + } + freeaddrinfo(resave); +#else client_vio = vio_new(socket (AF_INET, SOCK_STREAM, 0), VIO_TYPE_TCPIP, TRUE); @@ -78,6 +97,7 @@ err = connect(client_vio->sd, (struct sockaddr*) &sa, sizeof(sa)); +#endif /* ----------------------------------------------- */ /* Now we have TCP conncetion. Start SSL negotiation. */ diff -ru mysql-4.0.18.ori/vio/test-sslserver.c mysql-4.0.18/vio/test-sslserver.c --- mysql-4.0.18.ori/vio/test-sslserver.c 2004-02-10 19:15:48.000000000 +0100 +++ mysql-4.0.18/vio/test-sslserver.c 2004-06-28 17:01:56.000000000 +0200 @@ -86,9 +86,15 @@ pthread_t th; TH_ARGS th_args; - +#ifdef IPv6 + struct sockaddr_storage sa_serv; + struct sockaddr_storage sa_cli; + char saddr[INET6_ADDRSTRLEN]; + char sport[50]; +#else struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; +#endif int listen_sd; int err; size_t client_len; @@ -110,6 +116,17 @@ /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ +#ifdef IPv6 + + hints.ai_flags = AI_PASSIVE; + getaddrinfo(NULL,"1111",&hints,&res); + listen_sd = socket (res->ai_family,res->ai_socktype, 0); + setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(&reuseaddr)); + + err = bind(listen_sd, (struct sockaddr*) &sa_serv, + sizeof (sa_serv)); +#else + listen_sd = socket (AF_INET, SOCK_STREAM, 0); setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(&reuseaddr)); @@ -120,17 +137,29 @@ err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); +#endif /* Receive a TCP connection. */ err = listen (listen_sd, 5); +#ifdef IPv6 + client_len = SA_LEN(&sa_cli); +#else client_len = sizeof(sa_cli); +#endif th_args.sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); close (listen_sd); +#ifdef IPv6 + bzero((char *)saddr,INET6_ADDRSTRLEN); + bzero((char *)sport,50); + getnameinfo((const struct sockaddr*)&sa_cli,SA_LEN(&sa_cli),saddr,INET6_ADDRSTRLEN,sport,50,NI_NUMERICHOST|NI_NUMERICSERD); + printf ("Connection from %s, port %s\n", + saddr, sport); +#else printf ("Connection from %lx, port %x\n", (long)sa_cli.sin_addr.s_addr, sa_cli.sin_port); - +#endif /* ----------------------------------------------- */ /* TCP connection is ready. Do server side SSL. */ diff -ru mysql-4.0.18.ori/vio/vio_priv.h mysql-4.0.18/vio/vio_priv.h --- mysql-4.0.18.ori/vio/vio_priv.h 2004-02-10 19:15:54.000000000 +0100 +++ mysql-4.0.18/vio/vio_priv.h 2004-06-28 17:01:56.000000000 +0200 @@ -42,7 +42,10 @@ /* Return last error number */ int vio_ssl_errno(Vio *vio); my_bool vio_ssl_peer_addr(Vio *vio, char *buf, uint16 *port); +/* Should be dropped, since is not protocol independent */ +#ifndef IPv6 void vio_ssl_in_addr(Vio *vio, struct in_addr *in); +#endif int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); /* Single copy for server */ diff -ru mysql-4.0.18.ori/vio/viosocket.c mysql-4.0.18/vio/viosocket.c --- mysql-4.0.18.ori/vio/viosocket.c 2004-02-10 19:15:47.000000000 +0100 +++ mysql-4.0.18/vio/viosocket.c 2004-06-28 17:01:56.000000000 +0200 @@ -23,6 +23,7 @@ #include "vio_priv.h" + void vio_delete(Vio* vio) { /* It must be safe to delete null pointers. */ @@ -267,6 +268,10 @@ my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port) { +#ifdef IPv6 + char sport[50]; + bzero(port,50); +#endif DBUG_ENTER("vio_peer_addr"); DBUG_PRINT("enter", ("sd: %d", vio->sd)); if (vio->localhost) @@ -276,21 +281,31 @@ } else { +#ifdef IPv6 + size_socket addrLen = sizeof(struct sockaddr_storage); +#else size_socket addrLen = sizeof(struct sockaddr); +#endif if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), &addrLen) != 0) { DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); DBUG_RETURN(1); } +#ifdef IPv6 + getnameinfo((const struct sockaddr *) (& (vio->remote)), SA_LEN((const struct sockaddr *)(& (vio->remote))), buf, INET6_ADDRSTRLEN,sport,50,NI_NUMERICSERV | NI_NUMERICHOST ); + *port=atoi(sport); +#else my_inet_ntoa(vio->remote.sin_addr,buf); *port= ntohs(vio->remote.sin_port); +#endif } DBUG_PRINT("exit", ("addr: %s", buf)); DBUG_RETURN(0); } - +// This is not protocol independent, so we have to drop it on IPv6-IPv4 networks +#ifndef IPv6 void vio_in_addr(Vio *vio, struct in_addr *in) { DBUG_ENTER("vio_in_addr"); @@ -300,7 +315,7 @@ *in=vio->remote.sin_addr; DBUG_VOID_RETURN; } - +#endif /* Return 0 if there is data to be read */ diff -ru mysql-4.0.18.ori/vio/viossl.c mysql-4.0.18/vio/viossl.c --- mysql-4.0.18.ori/vio/viossl.c 2004-02-10 19:16:07.000000000 +0100 +++ mysql-4.0.18/vio/viossl.c 2004-06-28 17:01:56.000000000 +0200 @@ -201,6 +201,7 @@ my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port) { + DBUG_ENTER("vio_ssl_peer_addr"); DBUG_PRINT("enter", ("sd=%d", vio->sd)); if (vio->localhost) @@ -210,13 +211,21 @@ } else { +#ifdef IPv6 + size_socket addrLen = sizeof(struct sockaddr_storage); +#else size_socket addrLen = sizeof(struct sockaddr); +#endif if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), &addrLen) != 0) { DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); DBUG_RETURN(1); } +#ifdef IPv6 + getnameinfo((const struct sockaddr *) (& (vio->remote)), SA_LEN((const struct sockaddr *)(& (vio->remote))), buf, INET6_ADDRSTRLEN,sport,50,NI_NUMERICSERV | NI_NUMERICHOST ); + *port=atoi(sport); +#else #ifdef TO_BE_FIXED my_inet_ntoa(vio->remote.sin_addr,buf); *port= 0; @@ -224,6 +233,7 @@ strmov(buf, "unknown"); *port= 0; #endif +#endif } DBUG_PRINT("exit", ("addr=%s", buf)); DBUG_RETURN(0);