ws2_32: Move getnameinfo() to the Unix library.
[wine.git] / dlls / ws2_32 / unixlib.c
blob240389aeeaa5d7cd67c4144b06473c2855cfca10
1 /*
2 * Unix library functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #if 0
26 #pragma makedep unix
27 #endif
29 #include "config.h"
30 #include <errno.h>
31 #include <pthread.h>
32 #include <stdarg.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #ifdef HAVE_SYS_SOCKET_H
36 # include <sys/socket.h>
37 #endif
38 #ifdef HAVE_NETDB_H
39 # include <netdb.h>
40 #endif
42 #ifdef HAVE_NETIPX_IPX_H
43 # include <netipx/ipx.h>
44 #elif defined(HAVE_LINUX_IPX_H)
45 # ifdef HAVE_ASM_TYPES_H
46 # include <asm/types.h>
47 # endif
48 # ifdef HAVE_LINUX_TYPES_H
49 # include <linux/types.h>
50 # endif
51 # include <linux/ipx.h>
52 #endif
53 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
54 # define HAS_IPX
55 #endif
57 #ifdef HAVE_LINUX_IRDA_H
58 # ifdef HAVE_LINUX_TYPES_H
59 # include <linux/types.h>
60 # endif
61 # include <linux/irda.h>
62 # define HAS_IRDA
63 #endif
65 #include "ntstatus.h"
66 #define WIN32_NO_STATUS
67 #include "windef.h"
68 #include "winerror.h"
69 #include "winternl.h"
70 #include "winsock2.h"
71 #include "ws2tcpip.h"
72 #include "wsipx.h"
73 #include "af_irda.h"
74 #include "wine/debug.h"
76 #include "ws2_32_private.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
80 #ifndef HAVE_LINUX_GETHOSTBYNAME_R_6
81 static pthread_mutex_t host_mutex = PTHREAD_MUTEX_INITIALIZER;
82 #endif
84 #define MAP(x) {WS_ ## x, x}
86 static const int addrinfo_flag_map[][2] =
88 MAP( AI_PASSIVE ),
89 MAP( AI_CANONNAME ),
90 MAP( AI_NUMERICHOST ),
91 #ifdef AI_NUMERICSERV
92 MAP( AI_NUMERICSERV ),
93 #endif
94 #ifdef AI_V4MAPPED
95 MAP( AI_V4MAPPED ),
96 #endif
97 MAP( AI_ALL ),
98 MAP( AI_ADDRCONFIG ),
101 static const int nameinfo_flag_map[][2] =
103 MAP( NI_DGRAM ),
104 MAP( NI_NAMEREQD ),
105 MAP( NI_NOFQDN ),
106 MAP( NI_NUMERICHOST ),
107 MAP( NI_NUMERICSERV ),
110 static const int family_map[][2] =
112 MAP( AF_UNSPEC ),
113 MAP( AF_INET ),
114 MAP( AF_INET6 ),
115 #ifdef AF_IPX
116 MAP( AF_IPX ),
117 #endif
118 #ifdef AF_IRDA
119 MAP( AF_IRDA ),
120 #endif
123 static const int socktype_map[][2] =
125 MAP( SOCK_STREAM ),
126 MAP( SOCK_DGRAM ),
127 MAP( SOCK_RAW ),
130 static const int ip_protocol_map[][2] =
132 MAP( IPPROTO_IP ),
133 MAP( IPPROTO_TCP ),
134 MAP( IPPROTO_UDP ),
135 MAP( IPPROTO_IPV6 ),
136 MAP( IPPROTO_ICMP ),
137 MAP( IPPROTO_IGMP ),
138 MAP( IPPROTO_RAW ),
139 {WS_IPPROTO_IPV4, IPPROTO_IPIP},
142 #undef MAP
144 static int addrinfo_flags_from_unix( int flags )
146 int ws_flags = 0;
147 unsigned int i;
149 for (i = 0; i < ARRAY_SIZE(addrinfo_flag_map); ++i)
151 if (flags & addrinfo_flag_map[i][1])
153 ws_flags |= addrinfo_flag_map[i][0];
154 flags &= ~addrinfo_flag_map[i][1];
158 if (flags)
159 FIXME( "unhandled flags %#x\n", flags );
160 return ws_flags;
163 static int addrinfo_flags_to_unix( int flags )
165 int unix_flags = 0;
166 unsigned int i;
168 for (i = 0; i < ARRAY_SIZE(addrinfo_flag_map); ++i)
170 if (flags & addrinfo_flag_map[i][0])
172 unix_flags |= addrinfo_flag_map[i][1];
173 flags &= ~addrinfo_flag_map[i][0];
177 if (flags)
178 FIXME( "unhandled flags %#x\n", flags );
179 return unix_flags;
182 static int nameinfo_flags_to_unix( int flags )
184 int unix_flags = 0;
185 unsigned int i;
187 for (i = 0; i < ARRAY_SIZE(nameinfo_flag_map); ++i)
189 if (flags & nameinfo_flag_map[i][0])
191 unix_flags |= nameinfo_flag_map[i][1];
192 flags &= ~nameinfo_flag_map[i][0];
196 if (flags)
197 FIXME( "unhandled flags %#x\n", flags );
198 return unix_flags;
201 static int family_from_unix( int family )
203 unsigned int i;
205 for (i = 0; i < ARRAY_SIZE(family_map); ++i)
207 if (family == family_map[i][1])
208 return family_map[i][0];
211 FIXME( "unhandled family %u\n", family );
212 return -1;
215 static int family_to_unix( int family )
217 unsigned int i;
219 for (i = 0; i < ARRAY_SIZE(family_map); ++i)
221 if (family == family_map[i][0])
222 return family_map[i][1];
225 FIXME( "unhandled family %u\n", family );
226 return -1;
229 static int socktype_from_unix( int type )
231 unsigned int i;
233 for (i = 0; i < ARRAY_SIZE(socktype_map); ++i)
235 if (type == socktype_map[i][1])
236 return socktype_map[i][0];
239 FIXME( "unhandled type %u\n", type );
240 return -1;
243 static int socktype_to_unix( int type )
245 unsigned int i;
247 for (i = 0; i < ARRAY_SIZE(socktype_map); ++i)
249 if (type == socktype_map[i][0])
250 return socktype_map[i][1];
253 FIXME( "unhandled type %u\n", type );
254 return -1;
257 static int protocol_from_unix( int protocol )
259 unsigned int i;
261 for (i = 0; i < ARRAY_SIZE(ip_protocol_map); ++i)
263 if (protocol == ip_protocol_map[i][1])
264 return ip_protocol_map[i][0];
267 if (protocol >= WS_NSPROTO_IPX && protocol <= WS_NSPROTO_IPX + 255)
268 return protocol;
270 FIXME( "unhandled protocol %u\n", protocol );
271 return -1;
274 static int protocol_to_unix( int protocol )
276 unsigned int i;
278 for (i = 0; i < ARRAY_SIZE(ip_protocol_map); ++i)
280 if (protocol == ip_protocol_map[i][0])
281 return ip_protocol_map[i][1];
284 if (protocol >= WS_NSPROTO_IPX && protocol <= WS_NSPROTO_IPX + 255)
285 return protocol;
287 FIXME( "unhandled protocol %u\n", protocol );
288 return -1;
291 static unsigned int errno_from_unix( int err )
293 switch (err)
295 case EINTR: return WSAEINTR;
296 case EBADF: return WSAEBADF;
297 case EPERM:
298 case EACCES: return WSAEACCES;
299 case EFAULT: return WSAEFAULT;
300 case EINVAL: return WSAEINVAL;
301 case EMFILE: return WSAEMFILE;
302 case EINPROGRESS:
303 case EWOULDBLOCK: return WSAEWOULDBLOCK;
304 case EALREADY: return WSAEALREADY;
305 case ENOTSOCK: return WSAENOTSOCK;
306 case EDESTADDRREQ: return WSAEDESTADDRREQ;
307 case EMSGSIZE: return WSAEMSGSIZE;
308 case EPROTOTYPE: return WSAEPROTOTYPE;
309 case ENOPROTOOPT: return WSAENOPROTOOPT;
310 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
311 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
312 case EOPNOTSUPP: return WSAEOPNOTSUPP;
313 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
314 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
315 case EADDRINUSE: return WSAEADDRINUSE;
316 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
317 case ENETDOWN: return WSAENETDOWN;
318 case ENETUNREACH: return WSAENETUNREACH;
319 case ENETRESET: return WSAENETRESET;
320 case ECONNABORTED: return WSAECONNABORTED;
321 case EPIPE:
322 case ECONNRESET: return WSAECONNRESET;
323 case ENOBUFS: return WSAENOBUFS;
324 case EISCONN: return WSAEISCONN;
325 case ENOTCONN: return WSAENOTCONN;
326 case ESHUTDOWN: return WSAESHUTDOWN;
327 case ETOOMANYREFS: return WSAETOOMANYREFS;
328 case ETIMEDOUT: return WSAETIMEDOUT;
329 case ECONNREFUSED: return WSAECONNREFUSED;
330 case ELOOP: return WSAELOOP;
331 case ENAMETOOLONG: return WSAENAMETOOLONG;
332 case EHOSTDOWN: return WSAEHOSTDOWN;
333 case EHOSTUNREACH: return WSAEHOSTUNREACH;
334 case ENOTEMPTY: return WSAENOTEMPTY;
335 #ifdef EPROCLIM
336 case EPROCLIM: return WSAEPROCLIM;
337 #endif
338 #ifdef EUSERS
339 case EUSERS: return WSAEUSERS;
340 #endif
341 #ifdef EDQUOT
342 case EDQUOT: return WSAEDQUOT;
343 #endif
344 #ifdef ESTALE
345 case ESTALE: return WSAESTALE;
346 #endif
347 #ifdef EREMOTE
348 case EREMOTE: return WSAEREMOTE;
349 #endif
350 default:
351 FIXME( "unknown error: %s", strerror( err ) );
352 return WSAEFAULT;
356 static UINT host_errno_from_unix( int err )
358 WARN( "%d\n", err );
360 switch (err)
362 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
363 case TRY_AGAIN: return WSATRY_AGAIN;
364 case NO_RECOVERY: return WSANO_RECOVERY;
365 case NO_DATA: return WSANO_DATA;
366 case ENOBUFS: return WSAENOBUFS;
367 case 0: return 0;
368 default:
369 WARN( "Unknown h_errno %d!\n", err );
370 return WSAEOPNOTSUPP;
374 static int addrinfo_err_from_unix( int err )
376 switch (err)
378 case EAI_AGAIN: return WS_EAI_AGAIN;
379 case EAI_BADFLAGS: return WS_EAI_BADFLAGS;
380 case EAI_FAIL: return WS_EAI_FAIL;
381 case EAI_FAMILY: return WS_EAI_FAMILY;
382 case EAI_MEMORY: return WS_EAI_MEMORY;
383 /* EAI_NODATA is deprecated, but still used by Windows and Linux. We map
384 * the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
385 #ifdef EAI_NODATA
386 case EAI_NODATA: return WS_EAI_NODATA;
387 #endif
388 #ifdef EAI_NONAME
389 case EAI_NONAME: return WS_EAI_NODATA;
390 #endif
391 case EAI_SERVICE: return WS_EAI_SERVICE;
392 case EAI_SOCKTYPE: return WS_EAI_SOCKTYPE;
393 case EAI_SYSTEM:
394 /* some broken versions of glibc return EAI_SYSTEM and set errno to
395 * 0 instead of returning EAI_NONAME */
396 return errno ? errno_from_unix( errno ) : WS_EAI_NONAME;
398 default:
399 FIXME( "unhandled error %d\n", err );
400 return err;
404 union unix_sockaddr
406 struct sockaddr addr;
407 struct sockaddr_in in;
408 struct sockaddr_in6 in6;
409 #ifdef HAS_IPX
410 struct sockaddr_ipx ipx;
411 #endif
412 #ifdef HAS_IRDA
413 struct sockaddr_irda irda;
414 #endif
417 /* different from the version in ntdll and server; it does not return failure if
418 * given a short buffer */
419 static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_sockaddr *wsaddr, socklen_t wsaddrlen )
421 memset( wsaddr, 0, wsaddrlen );
423 switch (uaddr->addr.sa_family)
425 case AF_INET:
427 struct WS_sockaddr_in win = {0};
429 if (wsaddrlen >= sizeof(win))
431 win.sin_family = WS_AF_INET;
432 win.sin_port = uaddr->in.sin_port;
433 memcpy( &win.sin_addr, &uaddr->in.sin_addr, sizeof(win.sin_addr) );
434 memcpy( wsaddr, &win, sizeof(win) );
436 return sizeof(win);
439 case AF_INET6:
441 struct WS_sockaddr_in6 win = {0};
443 if (wsaddrlen >= sizeof(win))
445 win.sin6_family = WS_AF_INET6;
446 win.sin6_port = uaddr->in6.sin6_port;
447 win.sin6_flowinfo = uaddr->in6.sin6_flowinfo;
448 memcpy( &win.sin6_addr, &uaddr->in6.sin6_addr, sizeof(win.sin6_addr) );
449 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
450 win.sin6_scope_id = uaddr->in6.sin6_scope_id;
451 #endif
452 memcpy( wsaddr, &win, sizeof(win) );
454 return sizeof(win);
457 #ifdef HAS_IPX
458 case AF_IPX:
460 struct WS_sockaddr_ipx win = {0};
462 if (wsaddrlen >= sizeof(win))
464 win.sa_family = WS_AF_IPX;
465 memcpy( win.sa_netnum, &uaddr->ipx.sipx_network, sizeof(win.sa_netnum) );
466 memcpy( win.sa_nodenum, &uaddr->ipx.sipx_node, sizeof(win.sa_nodenum) );
467 win.sa_socket = uaddr->ipx.sipx_port;
468 memcpy( wsaddr, &win, sizeof(win) );
470 return sizeof(win);
472 #endif
474 #ifdef HAS_IRDA
475 case AF_IRDA:
477 SOCKADDR_IRDA win;
479 if (wsaddrlen >= sizeof(win))
481 win.irdaAddressFamily = WS_AF_IRDA;
482 memcpy( win.irdaDeviceID, &uaddr->irda.sir_addr, sizeof(win.irdaDeviceID) );
483 if (uaddr->irda.sir_lsap_sel != LSAP_ANY)
484 snprintf( win.irdaServiceName, sizeof(win.irdaServiceName), "LSAP-SEL%u", uaddr->irda.sir_lsap_sel );
485 else
486 memcpy( win.irdaServiceName, uaddr->irda.sir_name, sizeof(win.irdaServiceName) );
487 memcpy( wsaddr, &win, sizeof(win) );
489 return sizeof(win);
491 #endif
493 case AF_UNSPEC:
494 return 0;
496 default:
497 FIXME( "unknown address family %d\n", uaddr->addr.sa_family );
498 return 0;
502 static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrlen, union unix_sockaddr *uaddr )
504 memset( uaddr, 0, sizeof(*uaddr) );
506 switch (wsaddr->sa_family)
508 case WS_AF_INET:
510 struct WS_sockaddr_in win = {0};
512 if (wsaddrlen < sizeof(win)) return 0;
513 memcpy( &win, wsaddr, sizeof(win) );
514 uaddr->in.sin_family = AF_INET;
515 uaddr->in.sin_port = win.sin_port;
516 memcpy( &uaddr->in.sin_addr, &win.sin_addr, sizeof(win.sin_addr) );
517 return sizeof(uaddr->in);
520 case WS_AF_INET6:
522 struct WS_sockaddr_in6 win = {0};
524 if (wsaddrlen < sizeof(win)) return 0;
525 memcpy( &win, wsaddr, sizeof(win) );
526 uaddr->in6.sin6_family = AF_INET6;
527 uaddr->in6.sin6_port = win.sin6_port;
528 uaddr->in6.sin6_flowinfo = win.sin6_flowinfo;
529 memcpy( &uaddr->in6.sin6_addr, &win.sin6_addr, sizeof(win.sin6_addr) );
530 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
531 uaddr->in6.sin6_scope_id = win.sin6_scope_id;
532 #endif
533 return sizeof(uaddr->in6);
536 #ifdef HAS_IPX
537 case WS_AF_IPX:
539 struct WS_sockaddr_ipx win = {0};
541 if (wsaddrlen < sizeof(win)) return 0;
542 memcpy( &win, wsaddr, sizeof(win) );
543 uaddr->ipx.sipx_family = AF_IPX;
544 memcpy( &uaddr->ipx.sipx_network, win.sa_netnum, sizeof(win.sa_netnum) );
545 memcpy( &uaddr->ipx.sipx_node, win.sa_nodenum, sizeof(win.sa_nodenum) );
546 uaddr->ipx.sipx_port = win.sa_socket;
547 return sizeof(uaddr->ipx);
549 #endif
551 #ifdef HAS_IRDA
552 case WS_AF_IRDA:
554 SOCKADDR_IRDA win = {0};
555 unsigned int lsap_sel;
557 if (wsaddrlen < sizeof(win)) return 0;
558 memcpy( &win, wsaddr, sizeof(win) );
559 uaddr->irda.sir_family = AF_IRDA;
560 if (sscanf( win.irdaServiceName, "LSAP-SEL%u", &lsap_sel ) == 1)
561 uaddr->irda.sir_lsap_sel = lsap_sel;
562 else
564 uaddr->irda.sir_lsap_sel = LSAP_ANY;
565 memcpy( uaddr->irda.sir_name, win.irdaServiceName, sizeof(win.irdaServiceName) );
567 memcpy( &uaddr->irda.sir_addr, win.irdaDeviceID, sizeof(win.irdaDeviceID) );
568 return sizeof(uaddr->irda);
570 #endif
572 case WS_AF_UNSPEC:
573 switch (wsaddrlen)
575 default: /* likely an ipv4 address */
576 case sizeof(struct WS_sockaddr_in):
577 return sizeof(uaddr->in);
579 #ifdef HAS_IPX
580 case sizeof(struct WS_sockaddr_ipx):
581 return sizeof(uaddr->ipx);
582 #endif
584 #ifdef HAS_IRDA
585 case sizeof(SOCKADDR_IRDA):
586 return sizeof(uaddr->irda);
587 #endif
589 case sizeof(struct WS_sockaddr_in6):
590 return sizeof(uaddr->in6);
593 default:
594 FIXME( "unknown address family %u\n", wsaddr->sa_family );
595 return 0;
599 static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
601 const struct WS_addrinfo *cursor = list;
602 while (cursor)
604 if (ai->ai_flags == cursor->ai_flags &&
605 ai->ai_family == cursor->ai_family &&
606 ai->ai_socktype == cursor->ai_socktype &&
607 ai->ai_protocol == cursor->ai_protocol &&
608 ai->ai_addrlen == cursor->ai_addrlen &&
609 !memcmp( ai->ai_addr, cursor->ai_addr, ai->ai_addrlen ) &&
610 ((ai->ai_canonname && cursor->ai_canonname && !strcmp( ai->ai_canonname, cursor->ai_canonname ))
611 || (!ai->ai_canonname && !cursor->ai_canonname)))
613 return TRUE;
615 cursor = cursor->ai_next;
617 return FALSE;
620 static int CDECL unix_getaddrinfo( const char *node, const char *service, const struct WS_addrinfo *hints,
621 struct WS_addrinfo *info, unsigned int *size )
623 #ifdef HAVE_GETADDRINFO
624 struct addrinfo unix_hints = {0};
625 struct addrinfo *unix_info, *src;
626 struct WS_addrinfo *dst, *prev = NULL;
627 unsigned int needed_size = 0;
628 int ret;
630 /* servname tweak required by OSX and BSD kernels */
631 if (service && !service[0]) service = "0";
633 if (hints)
635 unix_hints.ai_flags = addrinfo_flags_to_unix( hints->ai_flags );
637 if (hints->ai_family)
638 unix_hints.ai_family = family_to_unix( hints->ai_family );
640 if (hints->ai_socktype)
642 if ((unix_hints.ai_socktype = socktype_to_unix( hints->ai_socktype )) < 0)
643 return WSAESOCKTNOSUPPORT;
646 if (hints->ai_protocol)
647 unix_hints.ai_protocol = max( protocol_to_unix( hints->ai_protocol ), 0 );
649 /* Windows allows some invalid combinations */
650 if (unix_hints.ai_protocol == IPPROTO_TCP
651 && unix_hints.ai_socktype != SOCK_STREAM
652 && unix_hints.ai_socktype != SOCK_SEQPACKET)
654 WARN( "ignoring invalid type %u for TCP\n", unix_hints.ai_socktype );
655 unix_hints.ai_socktype = 0;
657 else if (unix_hints.ai_protocol == IPPROTO_UDP && unix_hints.ai_socktype != SOCK_DGRAM)
659 WARN( "ignoring invalid type %u for UDP\n", unix_hints.ai_socktype );
660 unix_hints.ai_socktype = 0;
662 else if (unix_hints.ai_protocol >= WS_NSPROTO_IPX && unix_hints.ai_protocol <= WS_NSPROTO_IPX + 255
663 && unix_hints.ai_socktype != SOCK_DGRAM)
665 WARN( "ignoring invalid type %u for IPX\n", unix_hints.ai_socktype );
666 unix_hints.ai_socktype = 0;
668 else if (unix_hints.ai_protocol == IPPROTO_IPV6)
670 WARN( "ignoring protocol IPv6\n" );
671 unix_hints.ai_protocol = 0;
675 ret = getaddrinfo( node, service, hints ? &unix_hints : NULL, &unix_info );
676 if (ret)
677 return addrinfo_err_from_unix( ret );
679 for (src = unix_info; src != NULL; src = src->ai_next)
681 needed_size += sizeof(struct WS_addrinfo);
682 if (src->ai_canonname)
683 needed_size += strlen( src->ai_canonname ) + 1;
684 needed_size += sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, NULL, 0 );
687 if (*size < needed_size)
689 *size = needed_size;
690 freeaddrinfo( unix_info );
691 return ERROR_INSUFFICIENT_BUFFER;
694 dst = info;
696 memset( info, 0, needed_size );
698 for (src = unix_info; src != NULL; src = src->ai_next)
700 void *next = dst + 1;
702 dst->ai_flags = addrinfo_flags_from_unix( src->ai_flags );
703 dst->ai_family = family_from_unix( src->ai_family );
704 if (hints)
706 dst->ai_socktype = hints->ai_socktype;
707 dst->ai_protocol = hints->ai_protocol;
709 else
711 dst->ai_socktype = socktype_from_unix( src->ai_socktype );
712 dst->ai_protocol = protocol_from_unix( src->ai_protocol );
714 if (src->ai_canonname)
716 size_t len = strlen( src->ai_canonname ) + 1;
718 dst->ai_canonname = next;
719 memcpy( dst->ai_canonname, src->ai_canonname, len );
720 next = dst->ai_canonname + len;
723 dst->ai_addrlen = sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, NULL, 0 );
724 dst->ai_addr = next;
725 sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, dst->ai_addr, dst->ai_addrlen );
726 next = (char *)dst->ai_addr + dst->ai_addrlen;
728 if (dst == info || !addrinfo_in_list( info, dst ))
730 if (prev)
731 prev->ai_next = dst;
732 prev = dst;
733 dst = next;
737 dst->ai_next = NULL;
739 freeaddrinfo( unix_info );
740 return 0;
741 #else
742 FIXME( "getaddrinfo() not found during build time\n" );
743 return WS_EAI_FAIL;
744 #endif
748 static int hostent_from_unix( const struct hostent *unix_host, struct WS_hostent *host, unsigned int *const size )
750 unsigned int needed_size = sizeof( struct WS_hostent ), alias_count = 0, addr_count = 0, i;
751 char *p;
753 needed_size += strlen( unix_host->h_name );
755 for (alias_count = 0; unix_host->h_aliases[alias_count] != NULL; ++alias_count)
756 needed_size += sizeof(char *) + strlen( unix_host->h_aliases[alias_count] ) + 1;
757 needed_size += sizeof(char *); /* null terminator */
759 for (addr_count = 0; unix_host->h_addr_list[addr_count] != NULL; ++addr_count)
760 needed_size += sizeof(char *) + unix_host->h_length;
761 needed_size += sizeof(char *); /* null terminator */
763 if (*size < needed_size)
765 *size = needed_size;
766 return ERROR_INSUFFICIENT_BUFFER;
769 memset( host, 0, needed_size );
771 /* arrange the memory in the same order as windows >= XP */
773 host->h_addrtype = family_from_unix( unix_host->h_addrtype );
774 host->h_length = unix_host->h_length;
776 p = (char *)(host + 1);
777 host->h_aliases = (char **)p;
778 p += (alias_count + 1) * sizeof(char *);
779 host->h_addr_list = (char **)p;
780 p += (addr_count + 1) * sizeof(char *);
782 for (i = 0; i < addr_count; ++i)
784 host->h_addr_list[i] = p;
785 memcpy( host->h_addr_list[i], unix_host->h_addr_list[i], unix_host->h_length );
786 p += unix_host->h_length;
789 for (i = 0; i < alias_count; ++i)
791 size_t len = strlen( unix_host->h_aliases[i] ) + 1;
793 host->h_aliases[i] = p;
794 memcpy( host->h_aliases[i], unix_host->h_aliases[i], len );
795 p += len;
798 host->h_name = p;
799 strcpy( host->h_name, unix_host->h_name );
801 return 0;
805 static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
806 struct WS_hostent *const host, unsigned int *size )
808 const struct in_addr loopback = { htonl( INADDR_LOOPBACK ) };
809 int unix_family = family_to_unix( family );
810 struct hostent *unix_host;
811 int ret;
813 if (family == WS_AF_INET && len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
814 addr = &loopback;
816 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
818 char *unix_buffer, *new_buffer;
819 struct hostent stack_host;
820 int unix_size = 1024;
821 int locerr;
823 if (!(unix_buffer = malloc( unix_size )))
824 return WSAENOBUFS;
826 while (gethostbyaddr_r( addr, len, unix_family, &stack_host, unix_buffer,
827 unix_size, &unix_host, &locerr ) == ERANGE)
829 unix_size *= 2;
830 if (!(new_buffer = realloc( unix_buffer, unix_size )))
832 free( unix_buffer );
833 return WSAENOBUFS;
835 unix_buffer = new_buffer;
838 if (!unix_host)
839 return (locerr < 0 ? errno_from_unix( errno ) : host_errno_from_unix( locerr ));
841 ret = hostent_from_unix( unix_host, host, size );
843 free( unix_buffer );
844 return ret;
846 #else
847 pthread_mutex_lock( &host_mutex );
849 if (!(unix_host = gethostbyaddr( addr, len, unix_family )))
851 ret = (h_errno < 0 ? errno_from_unix( errno ) : host_errno_from_unix( h_errno ));
852 pthread_mutex_unlock( &host_mutex );
853 return ret;
856 ret = hostent_from_unix( unix_host, host, size );
858 pthread_mutex_unlock( &host_mutex );
859 return ret;
860 #endif
864 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
865 static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const host, unsigned int *size )
867 struct hostent stack_host, *unix_host;
868 char *unix_buffer, *new_buffer;
869 int unix_size = 1024;
870 int locerr;
871 int ret;
873 if (!(unix_buffer = malloc( unix_size )))
874 return WSAENOBUFS;
876 while (gethostbyname_r( name, &stack_host, unix_buffer, unix_size, &unix_host, &locerr ) == ERANGE)
878 unix_size *= 2;
879 if (!(new_buffer = realloc( unix_buffer, unix_size )))
881 free( unix_buffer );
882 return WSAENOBUFS;
884 unix_buffer = new_buffer;
887 if (!unix_host)
888 return (locerr < 0 ? errno_from_unix( errno ) : host_errno_from_unix( locerr ));
890 ret = hostent_from_unix( unix_host, host, size );
892 free( unix_buffer );
893 return ret;
895 #else
896 static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const host, unsigned int *size )
898 struct hostent *unix_host;
899 int ret;
901 pthread_mutex_lock( &host_mutex );
903 if (!(unix_host = gethostbyname( name )))
905 ret = (h_errno < 0 ? errno_from_unix( errno ) : host_errno_from_unix( h_errno ));
906 pthread_mutex_unlock( &host_mutex );
907 return ret;
910 ret = hostent_from_unix( unix_host, host, size );
912 pthread_mutex_unlock( &host_mutex );
913 return ret;
915 #endif
918 static int CDECL unix_gethostname( char *name, int len )
920 if (!gethostname( name, len ))
921 return 0;
922 return errno_from_unix( errno );
926 static int CDECL unix_getnameinfo( const struct WS(sockaddr) *addr, int addr_len, char *host,
927 DWORD host_len, char *serv, DWORD serv_len, int flags )
929 union unix_sockaddr unix_addr;
930 socklen_t unix_addr_len;
932 unix_addr_len = sockaddr_to_unix( addr, addr_len, &unix_addr );
934 return addrinfo_err_from_unix( getnameinfo( &unix_addr.addr, unix_addr_len, host, host_len,
935 serv, serv_len, nameinfo_flags_to_unix( flags ) ) );
939 static const struct unix_funcs funcs =
941 unix_getaddrinfo,
942 unix_gethostbyaddr,
943 unix_gethostbyname,
944 unix_gethostname,
945 unix_getnameinfo,
948 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
950 if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
952 *(const struct unix_funcs **)ptr_out = &funcs;
953 return STATUS_SUCCESS;