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
34 #include <sys/types.h>
35 #ifdef HAVE_SYS_SOCKET_H
36 # include <sys/socket.h>
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>
48 # ifdef HAVE_LINUX_TYPES_H
49 # include <linux/types.h>
51 # include <linux/ipx.h>
53 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
57 #ifdef HAVE_LINUX_IRDA_H
58 # ifdef HAVE_LINUX_TYPES_H
59 # include <linux/types.h>
61 # include <linux/irda.h>
66 #define WIN32_NO_STATUS
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
;
84 #define MAP(x) {WS_ ## x, x}
86 static const int addrinfo_flag_map
[][2] =
90 MAP( AI_NUMERICHOST
),
92 MAP( AI_NUMERICSERV
),
101 static const int nameinfo_flag_map
[][2] =
106 MAP( NI_NUMERICHOST
),
107 MAP( NI_NUMERICSERV
),
110 static const int family_map
[][2] =
123 static const int socktype_map
[][2] =
130 static const int ip_protocol_map
[][2] =
139 {WS_IPPROTO_IPV4
, IPPROTO_IPIP
},
144 static int addrinfo_flags_from_unix( int flags
)
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];
159 FIXME( "unhandled flags %#x\n", flags
);
163 static int addrinfo_flags_to_unix( int flags
)
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];
178 FIXME( "unhandled flags %#x\n", flags
);
182 static int nameinfo_flags_to_unix( int flags
)
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];
197 FIXME( "unhandled flags %#x\n", flags
);
201 static int family_from_unix( int family
)
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
);
215 static int family_to_unix( int family
)
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
);
229 static int socktype_from_unix( int type
)
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
);
243 static int socktype_to_unix( int type
)
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
);
257 static int protocol_from_unix( int protocol
)
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)
270 FIXME( "unhandled protocol %u\n", protocol
);
274 static int protocol_to_unix( int protocol
)
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)
287 FIXME( "unhandled protocol %u\n", protocol
);
291 static unsigned int errno_from_unix( int err
)
295 case EINTR
: return WSAEINTR
;
296 case EBADF
: return WSAEBADF
;
298 case EACCES
: return WSAEACCES
;
299 case EFAULT
: return WSAEFAULT
;
300 case EINVAL
: return WSAEINVAL
;
301 case EMFILE
: return WSAEMFILE
;
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
;
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
;
336 case EPROCLIM
: return WSAEPROCLIM
;
339 case EUSERS
: return WSAEUSERS
;
342 case EDQUOT
: return WSAEDQUOT
;
345 case ESTALE
: return WSAESTALE
;
348 case EREMOTE
: return WSAEREMOTE
;
351 FIXME( "unknown error: %s", strerror( err
) );
356 static UINT
host_errno_from_unix( int 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
;
369 WARN( "Unknown h_errno %d!\n", err
);
370 return WSAEOPNOTSUPP
;
374 static int addrinfo_err_from_unix( int 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. */
386 case EAI_NODATA
: return WS_EAI_NODATA
;
389 case EAI_NONAME
: return WS_EAI_NODATA
;
391 case EAI_SERVICE
: return WS_EAI_SERVICE
;
392 case EAI_SOCKTYPE
: return WS_EAI_SOCKTYPE
;
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
;
399 FIXME( "unhandled error %d\n", err
);
406 struct sockaddr addr
;
407 struct sockaddr_in in
;
408 struct sockaddr_in6 in6
;
410 struct sockaddr_ipx ipx
;
413 struct sockaddr_irda irda
;
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
)
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
) );
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
;
452 memcpy( wsaddr
, &win
, sizeof(win
) );
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
) );
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
);
486 memcpy( win
.irdaServiceName
, uaddr
->irda
.sir_name
, sizeof(win
.irdaServiceName
) );
487 memcpy( wsaddr
, &win
, sizeof(win
) );
497 FIXME( "unknown address family %d\n", uaddr
->addr
.sa_family
);
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
)
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
);
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
;
533 return sizeof(uaddr
->in6
);
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
);
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
;
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
);
575 default: /* likely an ipv4 address */
576 case sizeof(struct WS_sockaddr_in
):
577 return sizeof(uaddr
->in
);
580 case sizeof(struct WS_sockaddr_ipx
):
581 return sizeof(uaddr
->ipx
);
585 case sizeof(SOCKADDR_IRDA
):
586 return sizeof(uaddr
->irda
);
589 case sizeof(struct WS_sockaddr_in6
):
590 return sizeof(uaddr
->in6
);
594 FIXME( "unknown address family %u\n", wsaddr
->sa_family
);
599 static BOOL
addrinfo_in_list( const struct WS_addrinfo
*list
, const struct WS_addrinfo
*ai
)
601 const struct WS_addrinfo
*cursor
= list
;
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
)))
615 cursor
= cursor
->ai_next
;
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;
630 /* servname tweak required by OSX and BSD kernels */
631 if (service
&& !service
[0]) service
= "0";
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
);
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
)
690 freeaddrinfo( unix_info
);
691 return ERROR_INSUFFICIENT_BUFFER
;
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
);
706 dst
->ai_socktype
= hints
->ai_socktype
;
707 dst
->ai_protocol
= hints
->ai_protocol
;
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 );
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
))
739 freeaddrinfo( unix_info
);
742 FIXME( "getaddrinfo() not found during build time\n" );
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
;
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
)
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
);
799 strcpy( host
->h_name
, unix_host
->h_name
);
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
;
813 if (family
== WS_AF_INET
&& len
== 4 && !memcmp( addr
, magic_loopback_addr
, 4 ))
816 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
818 char *unix_buffer
, *new_buffer
;
819 struct hostent stack_host
;
820 int unix_size
= 1024;
823 if (!(unix_buffer
= malloc( unix_size
)))
826 while (gethostbyaddr_r( addr
, len
, unix_family
, &stack_host
, unix_buffer
,
827 unix_size
, &unix_host
, &locerr
) == ERANGE
)
830 if (!(new_buffer
= realloc( unix_buffer
, unix_size
)))
835 unix_buffer
= new_buffer
;
839 return (locerr
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( locerr
));
841 ret
= hostent_from_unix( unix_host
, host
, size
);
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
);
856 ret
= hostent_from_unix( unix_host
, host
, size
);
858 pthread_mutex_unlock( &host_mutex
);
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;
873 if (!(unix_buffer
= malloc( unix_size
)))
876 while (gethostbyname_r( name
, &stack_host
, unix_buffer
, unix_size
, &unix_host
, &locerr
) == ERANGE
)
879 if (!(new_buffer
= realloc( unix_buffer
, unix_size
)))
884 unix_buffer
= new_buffer
;
888 return (locerr
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( locerr
));
890 ret
= hostent_from_unix( unix_host
, host
, size
);
896 static int CDECL
unix_gethostbyname( const char *name
, struct WS_hostent
*const host
, unsigned int *size
)
898 struct hostent
*unix_host
;
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
);
910 ret
= hostent_from_unix( unix_host
, host
, size
);
912 pthread_mutex_unlock( &host_mutex
);
918 static int CDECL
unix_gethostname( char *name
, int len
)
920 if (!gethostname( name
, len
))
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
=
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
;