X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ftcpip.c;h=ba3853abe54b1ed9c216d59cbff979fab939c46b;hb=30be9a32fd26a2d08aa4413942408500c93ad4a3;hp=fcdcce12a695d74c1635d65491f4fbe70700b9c7;hpb=bf95c509245f5cb4025ef2db348d5f7ace3b5994;p=yaz-moved-to-github.git diff --git a/src/tcpip.c b/src/tcpip.c index fcdcce1..ba3853a 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -1,5 +1,5 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2008 Index Data + * Copyright (C) 1995-2009 Index Data * See the file LICENSE for details. */ /** @@ -25,7 +25,6 @@ #endif #ifdef WIN32 - /* VS 2003 or later has getaddrinfo; older versions do not */ #include #if _MSC_VER >= 1300 @@ -34,14 +33,20 @@ #else #define HAVE_GETADDRINFO 0 #endif +#endif -#else +#if HAVE_NETINET_IN_H #include +#endif +#if HAVE_NETDB_H #include +#endif +#if HAVE_ARPA_INET_H #include +#endif +#if HAVE_NETINET_TCP_H #include #endif - #if HAVE_SYS_SOCKET_H #include #endif @@ -413,8 +418,27 @@ int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add, return 1; } - #if HAVE_GETADDRINFO +/** \brief Creates socket using particular address family (AF_) + \param ai getaddrinfo result + \param mask family mask + \returns socket or -1 if none could be created + +*/ +static int create_socket_family(struct addrinfo *ai, unsigned mask) +{ + for (; ai; ai = ai->ai_next) + { + if ((ai->ai_family & mask) == mask) + { + int s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s != -1) + return s; + } + } + return -1; +} + void *tcpip_straddr(COMSTACK h, const char *str) { tcpip_state *sp = (tcpip_state *)h->cprivate; @@ -429,14 +453,13 @@ void *tcpip_straddr(COMSTACK h, const char *str) sp->ai = tcpip_getaddrinfo(str, port); if (sp->ai && h->state == CS_ST_UNBND) { - int s = -1; - struct addrinfo *ai = sp->ai; - for (; ai; ai = ai->ai_next) - { - s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (s != -1) - break; - } + /* The getaddrinfo call may return multiple addresses when passive + flags are used (AI_PASSIVE). This function picks the IPV6 if a + socket can be created for it. Otherwise IPV4 is used. + See also bug #2350 */ + int s = create_socket_family(sp->ai, AF_INET6); + if (s == -1) + s = create_socket_family(sp->ai, AF_INET); if (s == -1) return 0; h->iofile = s; @@ -806,7 +829,11 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, h->cerrno = CSOUTSTATE; return -1; } +#ifdef WIN32 + h->newfd = accept(h->iofile, 0, 0); +#else h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len); +#endif if (h->newfd < 0) { if ( @@ -1662,6 +1689,7 @@ static int tcpip_get_connect(COMSTACK h, char **buf, int *bufsize) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab