{"thread":{"id":"21731","subject":"[PATCH 0/2] Add support for IPv6 on MinGW","startedAt":"2009-11-23T22:54:13Z","lastAt":"2009-11-24T11:41:17Z","messageCount":7,"participants":["Martin Storsjö","Junio C Hamano","Johannes Sixt"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"128207","messageId":"alpine.DEB.2.00.0911240052440.14228@cone.home.martin.st","threadId":"21731","inReplyTo":null,"subject":"[PATCH 0/2] Add support for IPv6 on MinGW","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2009-11-23T22:54:13Z","receivedAt":"2009-11-23T22:54:13Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"Hi,\n\nThis is a short patch series that adds support for IPv6 on MinGW. These \npatches have been in use in msysgit for a few months (but the code was \naccidentally removed recently in a merge). For consistency, it would be \ngood to add them upstream, too.\n\nMartin Storsjö (2):\n  Refactor winsock initialization into a separate function\n  Enable support for IPv6 on MinGW\n\n Makefile       |    1 -\n compat/mingw.c |  184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   13 ++++\n 3 files changed, 193 insertions(+), 5 deletions(-)\n"},{"id":"128208","messageId":"alpine.DEB.2.00.0911240054420.14228@cone.home.martin.st","threadId":"21731","inReplyTo":"alpine.DEB.2.00.0911240052440.14228@cone.home.martin.st","subject":"[PATCH 1/2] Refactor winsock initialization into a separate function","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2009-11-23T22:55:12Z","receivedAt":"2009-11-23T22:55:12Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"Signed-off-by: Martin Storsjo <martin@martin.st>\n---\n compat/mingw.c |   15 ++++++++++++---\n 1 files changed, 12 insertions(+), 3 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 15fe33e..f9d82ff 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -903,16 +903,25 @@ char **make_augmented_environ(const char *const *vars)\n \treturn env;\n }\n \n-/* this is the first function to call into WS_32; initialize it */\n-#undef gethostbyname\n-struct hostent *mingw_gethostbyname(const char *host)\n+static void ensure_socket_initialization(void)\n {\n \tWSADATA wsa;\n+\tstatic int initialized = 0;\n+\n+\tif (initialized)\n+\t\treturn;\n \n \tif (WSAStartup(MAKEWORD(2,2), &wsa))\n \t\tdie(\"unable to initialize winsock subsystem, error %d\",\n \t\t\tWSAGetLastError());\n \tatexit((void(*)(void)) WSACleanup);\n+\tinitialized = 1;\n+}\n+\n+#undef gethostbyname\n+struct hostent *mingw_gethostbyname(const char *host)\n+{\n+\tensure_socket_initialization();\n \treturn gethostbyname(host);\n }\n \n-- \n1.6.4.4\n"},{"id":"128209","messageId":"alpine.DEB.2.00.0911240055170.14228@cone.home.martin.st","threadId":"21731","inReplyTo":"alpine.DEB.2.00.0911240052440.14228@cone.home.martin.st","subject":"[PATCH 2/2] Enable support for IPv6 on MinGW","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2009-11-23T22:55:50Z","receivedAt":"2009-11-23T22:55:50Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"The IPv6 support functions are loaded dynamically, to maintain backwards\ncompatibility with versions of Windows prior to XP, and fallback wrappers\nare provided, implemented in terms of gethostbyname and gethostbyaddr.\n\nSigned-off-by: Martin Storsjo <martin@martin.st>\n---\n Makefile       |    1 -\n compat/mingw.c |  169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   13 ++++\n 3 files changed, 181 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 25a9771..31db29d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -982,7 +982,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNEEDS_CRYPTO_WITH_SSL = YesPlease\n \tNO_LIBGEN_H = YesPlease\n \tNO_SYMLINK_HEAD = YesPlease\n-\tNO_IPV6 = YesPlease\n \tNO_SETENV = YesPlease\n \tNO_UNSETENV = YesPlease\n \tNO_STRCASESTR = YesPlease\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex f9d82ff..0d73f15 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -903,10 +903,129 @@ char **make_augmented_environ(const char *const *vars)\n \treturn env;\n }\n \n+/*\n+ * Note, this isn't a complete replacement for getaddrinfo. It assumes\n+ * that service contains a numerical port, or that it it is null. It\n+ * does a simple search using gethostbyname, and returns one IPv4 host\n+ * if one was found.\n+ */\n+static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n+\t\t\t\t   const struct addrinfo *hints,\n+\t\t\t\t   struct addrinfo **res)\n+{\n+\tstruct hostent *h = gethostbyname(node);\n+\tstruct addrinfo *ai;\n+\tstruct sockaddr_in *sin;\n+\n+\tif (!h)\n+\t\treturn WSAGetLastError();\n+\n+\tai = xmalloc(sizeof(struct addrinfo));\n+\t*res = ai;\n+\tai->ai_flags = 0;\n+\tai->ai_family = AF_INET;\n+\tai->ai_socktype = hints->ai_socktype;\n+\tswitch (hints->ai_socktype) {\n+\tcase SOCK_STREAM:\n+\t\tai->ai_protocol = IPPROTO_TCP;\n+\t\tbreak;\n+\tcase SOCK_DGRAM:\n+\t\tai->ai_protocol = IPPROTO_UDP;\n+\t\tbreak;\n+\tdefault:\n+\t\tai->ai_protocol = 0;\n+\t\tbreak;\n+\t}\n+\tai->ai_addrlen = sizeof(struct sockaddr_in);\n+\tai->ai_canonname = strdup(h->h_name);\n+\n+\tsin = xmalloc(ai->ai_addrlen);\n+\tmemset(sin, 0, ai->ai_addrlen);\n+\tsin->sin_family = AF_INET;\n+\tif (service)\n+\t\tsin->sin_port = htons(atoi(service));\n+\tsin->sin_addr = *(struct in_addr *)h->h_addr;\n+\tai->ai_addr = (struct sockaddr *)sin;\n+\tai->ai_next = 0;\n+\treturn 0;\n+}\n+\n+static void WSAAPI freeaddrinfo_stub(struct addrinfo *res)\n+{\n+\tfree(res->ai_canonname);\n+\tfree(res->ai_addr);\n+\tfree(res);\n+}\n+\n+static int WSAAPI getnameinfo_stub(const struct sockaddr *sa, socklen_t salen,\n+\t\t\t\t   char *host, DWORD hostlen,\n+\t\t\t\t   char *serv, DWORD servlen, int flags)\n+{\n+\tconst struct sockaddr_in *sin = (const struct sockaddr_in *)sa;\n+\tif (sa->sa_family != AF_INET)\n+\t\treturn EAI_FAMILY;\n+\tif (!host && !serv)\n+\t\treturn EAI_NONAME;\n+\n+\tif (host && hostlen > 0) {\n+\t\tstruct hostent *ent = NULL;\n+\t\tif (!(flags & NI_NUMERICHOST))\n+\t\t\tent = gethostbyaddr((const char *)&sin->sin_addr,\n+\t\t\t\t\t    sizeof(sin->sin_addr), AF_INET);\n+\n+\t\tif (ent)\n+\t\t\tsnprintf(host, hostlen, \"%s\", ent->h_name);\n+\t\telse if (flags & NI_NAMEREQD)\n+\t\t\treturn EAI_NONAME;\n+\t\telse\n+\t\t\tsnprintf(host, hostlen, \"%s\", inet_ntoa(sin->sin_addr));\n+\t}\n+\n+\tif (serv && servlen > 0) {\n+\t\tstruct servent *ent = NULL;\n+\t\tif (!(flags & NI_NUMERICSERV))\n+\t\t\tent = getservbyport(sin->sin_port,\n+\t\t\t\t\t    flags & NI_DGRAM ? \"udp\" : \"tcp\");\n+\n+\t\tif (ent)\n+\t\t\tsnprintf(serv, servlen, \"%s\", ent->s_name);\n+\t\telse\n+\t\t\tsnprintf(serv, servlen, \"%d\", ntohs(sin->sin_port));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static HMODULE ipv6_dll = NULL;\n+static void (WSAAPI *ipv6_freeaddrinfo)(struct addrinfo *res);\n+static int (WSAAPI *ipv6_getaddrinfo)(const char *node, const char *service,\n+\t\t\t\t      const struct addrinfo *hints,\n+\t\t\t\t      struct addrinfo **res);\n+static int (WSAAPI *ipv6_getnameinfo)(const struct sockaddr *sa, socklen_t salen,\n+\t\t\t\t      char *host, DWORD hostlen,\n+\t\t\t\t      char *serv, DWORD servlen, int flags);\n+/*\n+ * gai_strerror is an inline function in the ws2tcpip.h header, so we\n+ * don't need to try to load that one dynamically.\n+ */\n+\n+static void socket_cleanup(void)\n+{\n+\tWSACleanup();\n+\tif (ipv6_dll)\n+\t\tFreeLibrary(ipv6_dll);\n+\tipv6_dll = NULL;\n+\tipv6_freeaddrinfo = freeaddrinfo_stub;\n+\tipv6_getaddrinfo = getaddrinfo_stub;\n+\tipv6_getnameinfo = getnameinfo_stub;\n+}\n+\n static void ensure_socket_initialization(void)\n {\n \tWSADATA wsa;\n \tstatic int initialized = 0;\n+\tconst char *libraries[] = { \"ws2_32.dll\", \"wship6.dll\", NULL };\n+\tconst char **name;\n \n \tif (initialized)\n \t\treturn;\n@@ -914,7 +1033,35 @@ static void ensure_socket_initialization(void)\n \tif (WSAStartup(MAKEWORD(2,2), &wsa))\n \t\tdie(\"unable to initialize winsock subsystem, error %d\",\n \t\t\tWSAGetLastError());\n-\tatexit((void(*)(void)) WSACleanup);\n+\n+\tfor (name = libraries; *name; name++) {\n+\t\tipv6_dll = LoadLibrary(*name);\n+\t\tif (!ipv6_dll)\n+\t\t\tcontinue;\n+\n+\t\tipv6_freeaddrinfo = (void (WSAAPI *)(struct addrinfo *))\n+\t\t\tGetProcAddress(ipv6_dll, \"freeaddrinfo\");\n+\t\tipv6_getaddrinfo = (int (WSAAPI *)(const char *, const char *,\n+\t\t\t\t\t\t   const struct addrinfo *,\n+\t\t\t\t\t\t   struct addrinfo **))\n+\t\t\tGetProcAddress(ipv6_dll, \"getaddrinfo\");\n+\t\tipv6_getnameinfo = (int (WSAAPI *)(const struct sockaddr *,\n+\t\t\t\t\t\t   socklen_t, char *, DWORD,\n+\t\t\t\t\t\t   char *, DWORD, int))\n+\t\t\tGetProcAddress(ipv6_dll, \"getnameinfo\");\n+\t\tif (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo) {\n+\t\t\tFreeLibrary(ipv6_dll);\n+\t\t\tipv6_dll = NULL;\n+\t\t} else\n+\t\t\tbreak;\n+\t}\n+\tif (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo) {\n+\t\tipv6_freeaddrinfo = freeaddrinfo_stub;\n+\t\tipv6_getaddrinfo = getaddrinfo_stub;\n+\t\tipv6_getnameinfo = getnameinfo_stub;\n+\t}\n+\n+\tatexit(socket_cleanup);\n \tinitialized = 1;\n }\n \n@@ -925,6 +1072,26 @@ struct hostent *mingw_gethostbyname(const char *host)\n \treturn gethostbyname(host);\n }\n \n+void mingw_freeaddrinfo(struct addrinfo *res)\n+{\n+\tipv6_freeaddrinfo(res);\n+}\n+\n+int mingw_getaddrinfo(const char *node, const char *service,\n+\t\t      const struct addrinfo *hints, struct addrinfo **res)\n+{\n+\tensure_socket_initialization();\n+\treturn ipv6_getaddrinfo(node, service, hints, res);\n+}\n+\n+int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,\n+\t\t      char *host, DWORD hostlen, char *serv, DWORD servlen,\n+\t\t      int flags)\n+{\n+\tensure_socket_initialization();\n+\treturn ipv6_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);\n+}\n+\n int mingw_socket(int domain, int type, int protocol)\n {\n \tint sockfd;\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 51993ef..b3d299f 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -1,4 +1,5 @@\n #include <winsock2.h>\n+#include <ws2tcpip.h>\n \n /*\n  * things that are not available in header files\n@@ -178,6 +179,18 @@ char *mingw_getenv(const char *name);\n struct hostent *mingw_gethostbyname(const char *host);\n #define gethostbyname mingw_gethostbyname\n \n+void mingw_freeaddrinfo(struct addrinfo *res);\n+#define freeaddrinfo mingw_freeaddrinfo\n+\n+int mingw_getaddrinfo(const char *node, const char *service,\n+\t\t      const struct addrinfo *hints, struct addrinfo **res);\n+#define getaddrinfo mingw_getaddrinfo\n+\n+int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,\n+\t\t      char *host, DWORD hostlen, char *serv, DWORD servlen,\n+\t\t      int flags);\n+#define getnameinfo mingw_getnameinfo\n+\n int mingw_socket(int domain, int type, int protocol);\n #define socket mingw_socket\n \n-- \n1.6.4.4\n"},{"id":"128218","messageId":"7vy6lwrb5p.fsf@alter.siamese.dyndns.org","threadId":"21731","inReplyTo":"alpine.DEB.2.00.0911240052440.14228@cone.home.martin.st","subject":"Re: [PATCH 0/2] Add support for IPv6 on MinGW","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-11-24T00:58:42Z","receivedAt":"2009-11-24T00:58:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Storsjö <martin@martin.st> writes:\n\n> This is a short patch series that adds support for IPv6 on MinGW. These \n> patches have been in use in msysgit for a few months (but the code was \n> accidentally removed recently in a merge). For consistency, it would be \n> good to add them upstream, too.\n\nI am aware of the exchange between you and J6t on msysgit@googlegroups\nwhere he suggested you to send them here.  Giving better visibility to\nthese patches for public review is good.\n\nBut you didn't have to Cc: me; in Windows API issues I have no clue so I\nwon't be a good reviewer.  I do not even compile git on Windows myself,\nlet alone testing nor using.\n\nAs hinted by J6t, he will be saying Ack or something else, so I'll act on\nthese patches when it happens.\n\nPreferrably, I'd like somebody reasonably high in msysgit foodchain to\nvolunteer to be a coordinator and send me a pull-request whenever a set of\nchanges that has been:\n\n (1) cooking in msysgit tree without issues; and\n\n (2) reviewed favorably here on this list\n\nis ready for git.git.  That way, I do not even have to remember whose\npatches in the msysgit area I should blindly trust and apply, or keep\ntrack of which patches are still under discussion in general.\n\nThanks.\n"},{"id":"128234","messageId":"4B0B8CF5.6080208@viscovery.net","threadId":"21731","inReplyTo":"alpine.DEB.2.00.0911240054420.14228@cone.home.martin.st","subject":"Re: [PATCH 1/2] Refactor winsock initialization into a separate function","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-11-24T07:36:21Z","receivedAt":"2009-11-24T07:36:21Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Martin Storsjö schrieb:\n> Signed-off-by: Martin Storsjo <martin@martin.st>\n\nI have used this series in my tree for 6 weeks without negative\nsideffects. I haven't tested IPv6, though.\n\nHere's an updated commit message with my ACK:\n\n--- >8 ---\nRefactor winsock initialization into a separate function\n\nThe winsock library must be initialized. Since gethostbyname() is the\nfirst function that calls into winsock, it was overridden to do the\ninitialization. This refactoring helps the next patch, where other\nfunctions can be called earlier.\n\nSigned-off-by: Martin Storsjo <martin@martin.st>\nAcked-by: Johannes Sixt <j6t@kdbg.org>\n--- >8 ---\n\n\n> ---\n>  compat/mingw.c |   15 ++++++++++++---\n>  1 files changed, 12 insertions(+), 3 deletions(-)\n> \n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 15fe33e..f9d82ff 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -903,16 +903,25 @@ char **make_augmented_environ(const char *const *vars)\n>  \treturn env;\n>  }\n>  \n> -/* this is the first function to call into WS_32; initialize it */\n> -#undef gethostbyname\n> -struct hostent *mingw_gethostbyname(const char *host)\n> +static void ensure_socket_initialization(void)\n>  {\n>  \tWSADATA wsa;\n> +\tstatic int initialized = 0;\n> +\n> +\tif (initialized)\n> +\t\treturn;\n>  \n>  \tif (WSAStartup(MAKEWORD(2,2), &wsa))\n>  \t\tdie(\"unable to initialize winsock subsystem, error %d\",\n>  \t\t\tWSAGetLastError());\n>  \tatexit((void(*)(void)) WSACleanup);\n> +\tinitialized = 1;\n> +}\n> +\n> +#undef gethostbyname\n> +struct hostent *mingw_gethostbyname(const char *host)\n> +{\n> +\tensure_socket_initialization();\n>  \treturn gethostbyname(host);\n>  }\n>  \n"},{"id":"128235","messageId":"4B0B8E19.2090705@viscovery.net","threadId":"21731","inReplyTo":"alpine.DEB.2.00.0911240055170.14228@cone.home.martin.st","subject":"Re: [PATCH 2/2] Enable support for IPv6 on MinGW","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-11-24T07:41:13Z","receivedAt":"2009-11-24T07:41:13Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Martin Storsjö schrieb:\n> The IPv6 support functions are loaded dynamically, to maintain backwards\n> compatibility with versions of Windows prior to XP, and fallback wrappers\n> are provided, implemented in terms of gethostbyname and gethostbyaddr.\n> \n> Signed-off-by: Martin Storsjo <martin@martin.st>\n\nAcked-by: Johannes Sixt <j6t@kdbg.org>\n\n-- Hannes\n"},{"id":"128244","messageId":"alpine.DEB.2.00.0911241339090.14228@cone.home.martin.st","threadId":"21731","inReplyTo":"7vy6lwrb5p.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/2] Add support for IPv6 on MinGW","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2009-11-24T11:41:17Z","receivedAt":"2009-11-24T11:41:17Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"On Mon, 23 Nov 2009, Junio C Hamano wrote:\n\n> I am aware of the exchange between you and J6t on msysgit@googlegroups\n> where he suggested you to send them here.  Giving better visibility to\n> these patches for public review is good.\n> \n> But you didn't have to Cc: me; in Windows API issues I have no clue so I\n> won't be a good reviewer.  I do not even compile git on Windows myself,\n> let alone testing nor using.\n\nAh, sorry for notifying you prematurely there.\n\n> As hinted by J6t, he will be saying Ack or something else, so I'll act on\n> these patches when it happens.\n\nAnd thanks for handling this!\n\n// Martin\n"}]}