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 #include <sys/socket.h>
40 #ifdef HAVE_SYS_PARAM_H
41 # include <sys/param.h>
43 #ifdef HAVE_SYS_SOCKIO_H
44 # include <sys/sockio.h>
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
49 #ifdef HAVE_NETINET_TCP_H
50 # include <netinet/tcp.h>
52 #ifdef HAVE_ARPA_INET_H
53 # include <arpa/inet.h>
56 # define if_indextoname unix_if_indextoname
57 # define if_nametoindex unix_if_nametoindex
59 # undef if_indextoname
60 # undef if_nametoindex
67 #ifdef HAVE_NETIPX_IPX_H
68 # include <netipx/ipx.h>
69 #elif defined(HAVE_LINUX_IPX_H)
70 # ifdef HAVE_ASM_TYPES_H
71 # include <asm/types.h>
73 # ifdef HAVE_LINUX_TYPES_H
74 # include <linux/types.h>
76 # include <linux/ipx.h>
78 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
82 #ifdef HAVE_LINUX_IRDA_H
83 # ifdef HAVE_LINUX_TYPES_H
84 # include <linux/types.h>
86 # include <linux/irda.h>
91 #define WIN32_NO_STATUS
100 #include "wine/debug.h"
102 #include "ws2_32_private.h"
104 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
106 #ifndef HAVE_LINUX_GETHOSTBYNAME_R_6
107 static pthread_mutex_t host_mutex
= PTHREAD_MUTEX_INITIALIZER
;
110 #define MAP(x) {WS_ ## x, x}
112 static const int addrinfo_flag_map
[][2] =
116 MAP( AI_NUMERICHOST
),
117 #ifdef AI_NUMERICSERV
118 MAP( AI_NUMERICSERV
),
124 MAP( AI_ADDRCONFIG
),
127 static const int nameinfo_flag_map
[][2] =
132 MAP( NI_NUMERICHOST
),
133 MAP( NI_NUMERICSERV
),
136 static const int family_map
[][2] =
149 static const int socktype_map
[][2] =
156 static const int ip_protocol_map
[][2] =
165 {WS_IPPROTO_IPV4
, IPPROTO_IPIP
},
170 static int addrinfo_flags_from_unix( int flags
)
175 for (i
= 0; i
< ARRAY_SIZE(addrinfo_flag_map
); ++i
)
177 if (flags
& addrinfo_flag_map
[i
][1])
179 ws_flags
|= addrinfo_flag_map
[i
][0];
180 flags
&= ~addrinfo_flag_map
[i
][1];
185 FIXME( "unhandled flags %#x\n", flags
);
189 static int addrinfo_flags_to_unix( int flags
)
194 for (i
= 0; i
< ARRAY_SIZE(addrinfo_flag_map
); ++i
)
196 if (flags
& addrinfo_flag_map
[i
][0])
198 unix_flags
|= addrinfo_flag_map
[i
][1];
199 flags
&= ~addrinfo_flag_map
[i
][0];
204 FIXME( "unhandled flags %#x\n", flags
);
208 static int nameinfo_flags_to_unix( int flags
)
213 for (i
= 0; i
< ARRAY_SIZE(nameinfo_flag_map
); ++i
)
215 if (flags
& nameinfo_flag_map
[i
][0])
217 unix_flags
|= nameinfo_flag_map
[i
][1];
218 flags
&= ~nameinfo_flag_map
[i
][0];
223 FIXME( "unhandled flags %#x\n", flags
);
227 static int family_from_unix( int family
)
231 for (i
= 0; i
< ARRAY_SIZE(family_map
); ++i
)
233 if (family
== family_map
[i
][1])
234 return family_map
[i
][0];
237 FIXME( "unhandled family %u\n", family
);
241 static int family_to_unix( int family
)
245 for (i
= 0; i
< ARRAY_SIZE(family_map
); ++i
)
247 if (family
== family_map
[i
][0])
248 return family_map
[i
][1];
251 FIXME( "unhandled family %u\n", family
);
255 static int socktype_from_unix( int type
)
259 for (i
= 0; i
< ARRAY_SIZE(socktype_map
); ++i
)
261 if (type
== socktype_map
[i
][1])
262 return socktype_map
[i
][0];
265 FIXME( "unhandled type %u\n", type
);
269 static int socktype_to_unix( int type
)
273 for (i
= 0; i
< ARRAY_SIZE(socktype_map
); ++i
)
275 if (type
== socktype_map
[i
][0])
276 return socktype_map
[i
][1];
279 FIXME( "unhandled type %u\n", type
);
283 static int protocol_from_unix( int protocol
)
287 for (i
= 0; i
< ARRAY_SIZE(ip_protocol_map
); ++i
)
289 if (protocol
== ip_protocol_map
[i
][1])
290 return ip_protocol_map
[i
][0];
293 if (protocol
>= WS_NSPROTO_IPX
&& protocol
<= WS_NSPROTO_IPX
+ 255)
296 FIXME( "unhandled protocol %u\n", protocol
);
300 static int protocol_to_unix( int protocol
)
304 for (i
= 0; i
< ARRAY_SIZE(ip_protocol_map
); ++i
)
306 if (protocol
== ip_protocol_map
[i
][0])
307 return ip_protocol_map
[i
][1];
310 if (protocol
>= WS_NSPROTO_IPX
&& protocol
<= WS_NSPROTO_IPX
+ 255)
313 FIXME( "unhandled protocol %u\n", protocol
);
317 static unsigned int errno_from_unix( int err
)
321 case EINTR
: return WSAEINTR
;
322 case EBADF
: return WSAEBADF
;
324 case EACCES
: return WSAEACCES
;
325 case EFAULT
: return WSAEFAULT
;
326 case EINVAL
: return WSAEINVAL
;
327 case EMFILE
: return WSAEMFILE
;
329 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
330 case EALREADY
: return WSAEALREADY
;
331 case ENOTSOCK
: return WSAENOTSOCK
;
332 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
333 case EMSGSIZE
: return WSAEMSGSIZE
;
334 case EPROTOTYPE
: return WSAEPROTOTYPE
;
335 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
336 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
337 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
338 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
339 case EPFNOSUPPORT
: return WSAEPFNOSUPPORT
;
340 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
341 case EADDRINUSE
: return WSAEADDRINUSE
;
342 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
343 case ENETDOWN
: return WSAENETDOWN
;
344 case ENETUNREACH
: return WSAENETUNREACH
;
345 case ENETRESET
: return WSAENETRESET
;
346 case ECONNABORTED
: return WSAECONNABORTED
;
348 case ECONNRESET
: return WSAECONNRESET
;
349 case ENOBUFS
: return WSAENOBUFS
;
350 case EISCONN
: return WSAEISCONN
;
351 case ENOTCONN
: return WSAENOTCONN
;
352 case ESHUTDOWN
: return WSAESHUTDOWN
;
353 case ETOOMANYREFS
: return WSAETOOMANYREFS
;
354 case ETIMEDOUT
: return WSAETIMEDOUT
;
355 case ECONNREFUSED
: return WSAECONNREFUSED
;
356 case ELOOP
: return WSAELOOP
;
357 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
358 case EHOSTDOWN
: return WSAEHOSTDOWN
;
359 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
360 case ENOTEMPTY
: return WSAENOTEMPTY
;
362 case EPROCLIM
: return WSAEPROCLIM
;
365 case EUSERS
: return WSAEUSERS
;
368 case EDQUOT
: return WSAEDQUOT
;
371 case ESTALE
: return WSAESTALE
;
374 case EREMOTE
: return WSAEREMOTE
;
377 FIXME( "unknown error: %s\n", strerror( err
) );
382 static UINT
host_errno_from_unix( int err
)
388 case HOST_NOT_FOUND
: return WSAHOST_NOT_FOUND
;
389 case TRY_AGAIN
: return WSATRY_AGAIN
;
390 case NO_RECOVERY
: return WSANO_RECOVERY
;
391 case NO_DATA
: return WSANO_DATA
;
392 case ENOBUFS
: return WSAENOBUFS
;
395 WARN( "Unknown h_errno %d!\n", err
);
396 return WSAEOPNOTSUPP
;
400 static int addrinfo_err_from_unix( int err
)
405 case EAI_AGAIN
: return WS_EAI_AGAIN
;
406 case EAI_BADFLAGS
: return WS_EAI_BADFLAGS
;
407 case EAI_FAIL
: return WS_EAI_FAIL
;
408 case EAI_FAMILY
: return WS_EAI_FAMILY
;
409 case EAI_MEMORY
: return WS_EAI_MEMORY
;
410 /* EAI_NODATA is deprecated, but still used by Windows and Linux. We map
411 * the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
413 case EAI_NODATA
: return WS_EAI_NODATA
;
416 case EAI_NONAME
: return WS_EAI_NODATA
;
418 case EAI_SERVICE
: return WS_EAI_SERVICE
;
419 case EAI_SOCKTYPE
: return WS_EAI_SOCKTYPE
;
421 /* some broken versions of glibc return EAI_SYSTEM and set errno to
422 * 0 instead of returning EAI_NONAME */
423 return errno
? errno_from_unix( errno
) : WS_EAI_NONAME
;
426 FIXME( "unhandled error %d\n", err
);
433 struct sockaddr addr
;
434 struct sockaddr_in in
;
435 struct sockaddr_in6 in6
;
437 struct sockaddr_ipx ipx
;
440 struct sockaddr_irda irda
;
444 /* different from the version in ntdll and server; it does not return failure if
445 * given a short buffer */
446 static int sockaddr_from_unix( const union unix_sockaddr
*uaddr
, struct WS_sockaddr
*wsaddr
, socklen_t wsaddrlen
)
448 memset( wsaddr
, 0, wsaddrlen
);
450 switch (uaddr
->addr
.sa_family
)
454 struct WS_sockaddr_in win
= {0};
456 if (wsaddrlen
>= sizeof(win
))
458 win
.sin_family
= WS_AF_INET
;
459 win
.sin_port
= uaddr
->in
.sin_port
;
460 memcpy( &win
.sin_addr
, &uaddr
->in
.sin_addr
, sizeof(win
.sin_addr
) );
461 memcpy( wsaddr
, &win
, sizeof(win
) );
468 struct WS_sockaddr_in6 win
= {0};
470 if (wsaddrlen
>= sizeof(win
))
472 win
.sin6_family
= WS_AF_INET6
;
473 win
.sin6_port
= uaddr
->in6
.sin6_port
;
474 win
.sin6_flowinfo
= uaddr
->in6
.sin6_flowinfo
;
475 memcpy( &win
.sin6_addr
, &uaddr
->in6
.sin6_addr
, sizeof(win
.sin6_addr
) );
476 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
477 win
.sin6_scope_id
= uaddr
->in6
.sin6_scope_id
;
479 memcpy( wsaddr
, &win
, sizeof(win
) );
487 struct WS_sockaddr_ipx win
= {0};
489 if (wsaddrlen
>= sizeof(win
))
491 win
.sa_family
= WS_AF_IPX
;
492 memcpy( win
.sa_netnum
, &uaddr
->ipx
.sipx_network
, sizeof(win
.sa_netnum
) );
493 memcpy( win
.sa_nodenum
, &uaddr
->ipx
.sipx_node
, sizeof(win
.sa_nodenum
) );
494 win
.sa_socket
= uaddr
->ipx
.sipx_port
;
495 memcpy( wsaddr
, &win
, sizeof(win
) );
506 if (wsaddrlen
>= sizeof(win
))
508 win
.irdaAddressFamily
= WS_AF_IRDA
;
509 memcpy( win
.irdaDeviceID
, &uaddr
->irda
.sir_addr
, sizeof(win
.irdaDeviceID
) );
510 if (uaddr
->irda
.sir_lsap_sel
!= LSAP_ANY
)
511 snprintf( win
.irdaServiceName
, sizeof(win
.irdaServiceName
), "LSAP-SEL%u", uaddr
->irda
.sir_lsap_sel
);
513 memcpy( win
.irdaServiceName
, uaddr
->irda
.sir_name
, sizeof(win
.irdaServiceName
) );
514 memcpy( wsaddr
, &win
, sizeof(win
) );
524 FIXME( "unknown address family %d\n", uaddr
->addr
.sa_family
);
529 static socklen_t
sockaddr_to_unix( const struct WS_sockaddr
*wsaddr
, int wsaddrlen
, union unix_sockaddr
*uaddr
)
531 memset( uaddr
, 0, sizeof(*uaddr
) );
533 switch (wsaddr
->sa_family
)
537 struct WS_sockaddr_in win
= {0};
539 if (wsaddrlen
< sizeof(win
)) return 0;
540 memcpy( &win
, wsaddr
, sizeof(win
) );
541 uaddr
->in
.sin_family
= AF_INET
;
542 uaddr
->in
.sin_port
= win
.sin_port
;
543 memcpy( &uaddr
->in
.sin_addr
, &win
.sin_addr
, sizeof(win
.sin_addr
) );
544 return sizeof(uaddr
->in
);
549 struct WS_sockaddr_in6 win
= {0};
551 if (wsaddrlen
< sizeof(win
)) return 0;
552 memcpy( &win
, wsaddr
, sizeof(win
) );
553 uaddr
->in6
.sin6_family
= AF_INET6
;
554 uaddr
->in6
.sin6_port
= win
.sin6_port
;
555 uaddr
->in6
.sin6_flowinfo
= win
.sin6_flowinfo
;
556 memcpy( &uaddr
->in6
.sin6_addr
, &win
.sin6_addr
, sizeof(win
.sin6_addr
) );
557 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
558 uaddr
->in6
.sin6_scope_id
= win
.sin6_scope_id
;
560 return sizeof(uaddr
->in6
);
566 struct WS_sockaddr_ipx win
= {0};
568 if (wsaddrlen
< sizeof(win
)) return 0;
569 memcpy( &win
, wsaddr
, sizeof(win
) );
570 uaddr
->ipx
.sipx_family
= AF_IPX
;
571 memcpy( &uaddr
->ipx
.sipx_network
, win
.sa_netnum
, sizeof(win
.sa_netnum
) );
572 memcpy( &uaddr
->ipx
.sipx_node
, win
.sa_nodenum
, sizeof(win
.sa_nodenum
) );
573 uaddr
->ipx
.sipx_port
= win
.sa_socket
;
574 return sizeof(uaddr
->ipx
);
581 SOCKADDR_IRDA win
= {0};
582 unsigned int lsap_sel
;
584 if (wsaddrlen
< sizeof(win
)) return 0;
585 memcpy( &win
, wsaddr
, sizeof(win
) );
586 uaddr
->irda
.sir_family
= AF_IRDA
;
587 if (sscanf( win
.irdaServiceName
, "LSAP-SEL%u", &lsap_sel
) == 1)
588 uaddr
->irda
.sir_lsap_sel
= lsap_sel
;
591 uaddr
->irda
.sir_lsap_sel
= LSAP_ANY
;
592 memcpy( uaddr
->irda
.sir_name
, win
.irdaServiceName
, sizeof(win
.irdaServiceName
) );
594 memcpy( &uaddr
->irda
.sir_addr
, win
.irdaDeviceID
, sizeof(win
.irdaDeviceID
) );
595 return sizeof(uaddr
->irda
);
602 default: /* likely an ipv4 address */
603 case sizeof(struct WS_sockaddr_in
):
604 return sizeof(uaddr
->in
);
607 case sizeof(struct WS_sockaddr_ipx
):
608 return sizeof(uaddr
->ipx
);
612 case sizeof(SOCKADDR_IRDA
):
613 return sizeof(uaddr
->irda
);
616 case sizeof(struct WS_sockaddr_in6
):
617 return sizeof(uaddr
->in6
);
621 FIXME( "unknown address family %u\n", wsaddr
->sa_family
);
626 static BOOL
addrinfo_in_list( const struct WS_addrinfo
*list
, const struct WS_addrinfo
*ai
)
628 const struct WS_addrinfo
*cursor
= list
;
631 if (ai
->ai_flags
== cursor
->ai_flags
&&
632 ai
->ai_family
== cursor
->ai_family
&&
633 ai
->ai_socktype
== cursor
->ai_socktype
&&
634 ai
->ai_protocol
== cursor
->ai_protocol
&&
635 ai
->ai_addrlen
== cursor
->ai_addrlen
&&
636 !memcmp( ai
->ai_addr
, cursor
->ai_addr
, ai
->ai_addrlen
) &&
637 ((ai
->ai_canonname
&& cursor
->ai_canonname
&& !strcmp( ai
->ai_canonname
, cursor
->ai_canonname
))
638 || (!ai
->ai_canonname
&& !cursor
->ai_canonname
)))
642 cursor
= cursor
->ai_next
;
647 static NTSTATUS
unix_getaddrinfo( void *args
)
649 #ifdef HAVE_GETADDRINFO
650 struct getaddrinfo_params
*params
= args
;
651 const char *service
= params
->service
;
652 const struct WS_addrinfo
*hints
= params
->hints
;
653 struct addrinfo unix_hints
= {0};
654 struct addrinfo
*unix_info
, *src
;
655 struct WS_addrinfo
*dst
, *prev
= NULL
;
656 unsigned int needed_size
= 0;
659 /* servname tweak required by OSX and BSD kernels */
660 if (service
&& !service
[0]) service
= "0";
664 unix_hints
.ai_flags
= addrinfo_flags_to_unix( hints
->ai_flags
);
666 if (hints
->ai_family
)
667 unix_hints
.ai_family
= family_to_unix( hints
->ai_family
);
669 if (hints
->ai_socktype
)
671 if ((unix_hints
.ai_socktype
= socktype_to_unix( hints
->ai_socktype
)) < 0)
672 return WSAESOCKTNOSUPPORT
;
675 if (hints
->ai_protocol
)
676 unix_hints
.ai_protocol
= max( protocol_to_unix( hints
->ai_protocol
), 0 );
678 /* Windows allows some invalid combinations */
679 if (unix_hints
.ai_protocol
== IPPROTO_TCP
680 && unix_hints
.ai_socktype
!= SOCK_STREAM
681 && unix_hints
.ai_socktype
!= SOCK_SEQPACKET
)
683 WARN( "ignoring invalid type %u for TCP\n", unix_hints
.ai_socktype
);
684 unix_hints
.ai_socktype
= 0;
686 else if (unix_hints
.ai_protocol
== IPPROTO_UDP
&& unix_hints
.ai_socktype
!= SOCK_DGRAM
)
688 WARN( "ignoring invalid type %u for UDP\n", unix_hints
.ai_socktype
);
689 unix_hints
.ai_socktype
= 0;
691 else if (unix_hints
.ai_protocol
>= WS_NSPROTO_IPX
&& unix_hints
.ai_protocol
<= WS_NSPROTO_IPX
+ 255
692 && unix_hints
.ai_socktype
!= SOCK_DGRAM
)
694 WARN( "ignoring invalid type %u for IPX\n", unix_hints
.ai_socktype
);
695 unix_hints
.ai_socktype
= 0;
697 else if (unix_hints
.ai_protocol
== IPPROTO_IPV6
)
699 WARN( "ignoring protocol IPv6\n" );
700 unix_hints
.ai_protocol
= 0;
704 ret
= getaddrinfo( params
->node
, service
, hints
? &unix_hints
: NULL
, &unix_info
);
706 return addrinfo_err_from_unix( ret
);
708 for (src
= unix_info
; src
!= NULL
; src
= src
->ai_next
)
710 needed_size
+= sizeof(struct WS_addrinfo
);
711 if (src
->ai_canonname
)
712 needed_size
+= strlen( src
->ai_canonname
) + 1;
713 needed_size
+= sockaddr_from_unix( (const union unix_sockaddr
*)src
->ai_addr
, NULL
, 0 );
716 if (*params
->size
< needed_size
)
718 *params
->size
= needed_size
;
719 freeaddrinfo( unix_info
);
720 return ERROR_INSUFFICIENT_BUFFER
;
725 memset( params
->info
, 0, needed_size
);
727 for (src
= unix_info
; src
!= NULL
; src
= src
->ai_next
)
729 void *next
= dst
+ 1;
731 dst
->ai_flags
= addrinfo_flags_from_unix( src
->ai_flags
);
732 dst
->ai_family
= family_from_unix( src
->ai_family
);
735 dst
->ai_socktype
= hints
->ai_socktype
;
736 dst
->ai_protocol
= hints
->ai_protocol
;
740 dst
->ai_socktype
= socktype_from_unix( src
->ai_socktype
);
741 dst
->ai_protocol
= protocol_from_unix( src
->ai_protocol
);
743 if (src
->ai_canonname
)
745 size_t len
= strlen( src
->ai_canonname
) + 1;
747 dst
->ai_canonname
= next
;
748 memcpy( dst
->ai_canonname
, src
->ai_canonname
, len
);
749 next
= dst
->ai_canonname
+ len
;
752 dst
->ai_addrlen
= sockaddr_from_unix( (const union unix_sockaddr
*)src
->ai_addr
, NULL
, 0 );
754 sockaddr_from_unix( (const union unix_sockaddr
*)src
->ai_addr
, dst
->ai_addr
, dst
->ai_addrlen
);
756 next
= (char *)dst
->ai_addr
+ dst
->ai_addrlen
;
758 if (dst
== params
->info
|| !addrinfo_in_list( params
->info
, dst
))
767 freeaddrinfo( unix_info
);
770 FIXME( "getaddrinfo() not found during build time\n" );
776 static int hostent_from_unix( const struct hostent
*unix_host
, struct WS_hostent
*host
, unsigned int *const size
)
778 unsigned int needed_size
= sizeof( struct WS_hostent
), alias_count
= 0, addr_count
= 0, i
;
781 needed_size
+= strlen( unix_host
->h_name
) + 1;
783 for (alias_count
= 0; unix_host
->h_aliases
[alias_count
] != NULL
; ++alias_count
)
784 needed_size
+= sizeof(char *) + strlen( unix_host
->h_aliases
[alias_count
] ) + 1;
785 needed_size
+= sizeof(char *); /* null terminator */
787 for (addr_count
= 0; unix_host
->h_addr_list
[addr_count
] != NULL
; ++addr_count
)
788 needed_size
+= sizeof(char *) + unix_host
->h_length
;
789 needed_size
+= sizeof(char *); /* null terminator */
791 if (*size
< needed_size
)
794 return ERROR_INSUFFICIENT_BUFFER
;
797 memset( host
, 0, needed_size
);
799 /* arrange the memory in the same order as windows >= XP */
801 host
->h_addrtype
= family_from_unix( unix_host
->h_addrtype
);
802 host
->h_length
= unix_host
->h_length
;
804 p
= (char *)(host
+ 1);
805 host
->h_aliases
= (char **)p
;
806 p
+= (alias_count
+ 1) * sizeof(char *);
807 host
->h_addr_list
= (char **)p
;
808 p
+= (addr_count
+ 1) * sizeof(char *);
810 for (i
= 0; i
< addr_count
; ++i
)
812 host
->h_addr_list
[i
] = p
;
813 memcpy( host
->h_addr_list
[i
], unix_host
->h_addr_list
[i
], unix_host
->h_length
);
814 p
+= unix_host
->h_length
;
817 for (i
= 0; i
< alias_count
; ++i
)
819 size_t len
= strlen( unix_host
->h_aliases
[i
] ) + 1;
821 host
->h_aliases
[i
] = p
;
822 memcpy( host
->h_aliases
[i
], unix_host
->h_aliases
[i
], len
);
827 strcpy( host
->h_name
, unix_host
->h_name
);
833 static NTSTATUS
unix_gethostbyaddr( void *args
)
835 struct gethostbyaddr_params
*params
= args
;
836 const void *addr
= params
->addr
;
837 const struct in_addr loopback
= { htonl( INADDR_LOOPBACK
) };
838 int unix_family
= family_to_unix( params
->family
);
839 struct hostent
*unix_host
;
842 if (params
->family
== WS_AF_INET
&& params
->len
== 4 && !memcmp( addr
, magic_loopback_addr
, 4 ))
845 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
847 char *unix_buffer
, *new_buffer
;
848 struct hostent stack_host
;
849 int unix_size
= 1024;
852 if (!(unix_buffer
= malloc( unix_size
)))
855 while (gethostbyaddr_r( addr
, params
->len
, unix_family
, &stack_host
, unix_buffer
,
856 unix_size
, &unix_host
, &locerr
) == ERANGE
)
859 if (!(new_buffer
= realloc( unix_buffer
, unix_size
)))
864 unix_buffer
= new_buffer
;
868 ret
= (locerr
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( locerr
));
870 ret
= hostent_from_unix( unix_host
, params
->host
, params
->size
);
876 pthread_mutex_lock( &host_mutex
);
878 if (!(unix_host
= gethostbyaddr( addr
, params
->len
, unix_family
)))
880 ret
= (h_errno
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( h_errno
));
881 pthread_mutex_unlock( &host_mutex
);
885 ret
= hostent_from_unix( unix_host
, params
->host
, params
->size
);
887 pthread_mutex_unlock( &host_mutex
);
893 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
894 static NTSTATUS
unix_gethostbyname( void *args
)
896 struct gethostbyname_params
*params
= args
;
897 struct hostent stack_host
, *unix_host
;
898 char *unix_buffer
, *new_buffer
;
899 int unix_size
= 1024;
903 if (!(unix_buffer
= malloc( unix_size
)))
906 while (gethostbyname_r( params
->name
, &stack_host
, unix_buffer
, unix_size
, &unix_host
, &locerr
) == ERANGE
)
909 if (!(new_buffer
= realloc( unix_buffer
, unix_size
)))
914 unix_buffer
= new_buffer
;
918 ret
= (locerr
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( locerr
));
920 ret
= hostent_from_unix( unix_host
, params
->host
, params
->size
);
926 static NTSTATUS
unix_gethostbyname( void *args
)
928 struct gethostbyname_params
*params
= args
;
929 struct hostent
*unix_host
;
932 pthread_mutex_lock( &host_mutex
);
934 if (!(unix_host
= gethostbyname( params
->name
)))
936 ret
= (h_errno
< 0 ? errno_from_unix( errno
) : host_errno_from_unix( h_errno
));
937 pthread_mutex_unlock( &host_mutex
);
941 ret
= hostent_from_unix( unix_host
, params
->host
, params
->size
);
943 pthread_mutex_unlock( &host_mutex
);
949 static NTSTATUS
unix_gethostname( void *args
)
951 struct gethostname_params
*params
= args
;
953 if (!gethostname( params
->name
, params
->size
))
955 return errno_from_unix( errno
);
959 static NTSTATUS
unix_getnameinfo( void *args
)
961 struct getnameinfo_params
*params
= args
;
962 union unix_sockaddr unix_addr
;
963 socklen_t unix_addr_len
;
965 unix_addr_len
= sockaddr_to_unix( params
->addr
, params
->addr_len
, &unix_addr
);
967 return addrinfo_err_from_unix( getnameinfo( &unix_addr
.addr
, unix_addr_len
, params
->host
, params
->host_len
,
968 params
->serv
, params
->serv_len
,
969 nameinfo_flags_to_unix( params
->flags
) ) );
973 const unixlib_entry_t __wine_unix_call_funcs
[] =
1007 static NTSTATUS
put_addrinfo32( const struct WS_addrinfo
*info
, struct WS_addrinfo32
*info32
,
1008 unsigned int *size
)
1010 struct WS_addrinfo32
*dst
= info32
, *prev
= NULL
;
1011 const struct WS_addrinfo
*src
;
1012 unsigned int needed_size
= 0;
1014 for (src
= info
; src
!= NULL
; src
= src
->ai_next
)
1016 needed_size
+= sizeof(struct WS_addrinfo32
);
1017 if (src
->ai_canonname
) needed_size
+= strlen( src
->ai_canonname
) + 1;
1018 needed_size
+= src
->ai_addrlen
;
1021 if (*size
< needed_size
)
1023 *size
= needed_size
;
1024 return ERROR_INSUFFICIENT_BUFFER
;
1027 memset( info32
, 0, needed_size
);
1029 for (src
= info
; src
!= NULL
; src
= src
->ai_next
)
1031 char *next
= (char *)(dst
+ 1);
1033 dst
->ai_flags
= src
->ai_flags
;
1034 dst
->ai_family
= src
->ai_family
;
1035 dst
->ai_socktype
= src
->ai_socktype
;
1036 dst
->ai_protocol
= src
->ai_protocol
;
1037 if (src
->ai_canonname
)
1039 dst
->ai_canonname
= PtrToUlong( next
);
1040 strcpy( next
, src
->ai_canonname
);
1041 next
+= strlen(next
) + 1;
1043 dst
->ai_addrlen
= src
->ai_addrlen
;
1044 dst
->ai_addr
= PtrToUlong(next
);
1045 memcpy( next
, src
->ai_addr
, dst
->ai_addrlen
);
1046 next
+= dst
->ai_addrlen
;
1047 if (prev
) prev
->ai_next
= PtrToUlong(dst
);
1049 dst
= (struct WS_addrinfo32
*)next
;
1051 return STATUS_SUCCESS
;
1054 static NTSTATUS
put_hostent32( const struct WS_hostent
*host
, struct WS_hostent32
*host32
,
1055 unsigned int *size
)
1057 unsigned int needed_size
= sizeof( struct WS_hostent32
), alias_count
= 0, addr_count
= 0, i
;
1059 ULONG
*aliases
, *addr_list
;
1061 needed_size
+= strlen( host
->h_name
) + 1;
1063 for (alias_count
= 0; host
->h_aliases
[alias_count
] != NULL
; ++alias_count
)
1064 needed_size
+= sizeof(ULONG
) + strlen( host
->h_aliases
[alias_count
] ) + 1;
1065 needed_size
+= sizeof(ULONG
); /* null terminator */
1067 for (addr_count
= 0; host
->h_addr_list
[addr_count
] != NULL
; ++addr_count
)
1068 needed_size
+= sizeof(ULONG
) + host
->h_length
;
1069 needed_size
+= sizeof(ULONG
); /* null terminator */
1071 if (*size
< needed_size
)
1073 *size
= needed_size
;
1074 return ERROR_INSUFFICIENT_BUFFER
;
1077 memset( host32
, 0, needed_size
);
1079 /* arrange the memory in the same order as windows >= XP */
1081 host32
->h_addrtype
= host
->h_addrtype
;
1082 host32
->h_length
= host
->h_length
;
1084 aliases
= (ULONG
*)(host32
+ 1);
1085 addr_list
= aliases
+ alias_count
+ 1;
1086 p
= (char *)(addr_list
+ addr_count
+ 1);
1088 host32
->h_aliases
= PtrToUlong( aliases
);
1089 host32
->h_addr_list
= PtrToUlong( addr_list
);
1091 for (i
= 0; i
< addr_count
; ++i
)
1093 addr_list
[i
] = PtrToUlong( p
);
1094 memcpy( p
, host
->h_addr_list
[i
], host
->h_length
);
1095 p
+= host
->h_length
;
1098 for (i
= 0; i
< alias_count
; ++i
)
1100 size_t len
= strlen( host
->h_aliases
[i
] ) + 1;
1102 aliases
[i
] = PtrToUlong( p
);
1103 memcpy( p
, host
->h_aliases
[i
], len
);
1107 host32
->h_name
= PtrToUlong( p
);
1108 strcpy( p
, host
->h_name
);
1109 return STATUS_SUCCESS
;
1113 static NTSTATUS
wow64_unix_getaddrinfo( void *args
)
1122 } const *params32
= args
;
1125 struct WS_addrinfo hints
;
1126 struct getaddrinfo_params params
=
1128 ULongToPtr( params32
->node
),
1129 ULongToPtr( params32
->service
),
1132 ULongToPtr(params32
->size
)
1135 if (params32
->hints
)
1137 const struct WS_addrinfo32
*hints32
= ULongToPtr(params32
->hints
);
1138 hints
.ai_flags
= hints32
->ai_flags
;
1139 hints
.ai_family
= hints32
->ai_family
;
1140 hints
.ai_socktype
= hints32
->ai_socktype
;
1141 hints
.ai_protocol
= hints32
->ai_protocol
;
1142 params
.hints
= &hints
;
1145 if (!(params
.info
= malloc( *params
.size
))) return WSAENOBUFS
;
1146 status
= unix_getaddrinfo( ¶ms
);
1147 if (!status
) put_addrinfo32( params
.info
, ULongToPtr(params32
->info
), ULongToPtr(params32
->size
) );
1148 free( params
.info
);
1153 static NTSTATUS
wow64_unix_gethostbyaddr( void *args
)
1162 } const *params32
= args
;
1165 struct gethostbyaddr_params params
=
1167 ULongToPtr( params32
->addr
),
1171 ULongToPtr(params32
->size
)
1174 if (!(params
.host
= malloc( *params
.size
))) return WSAENOBUFS
;
1175 status
= unix_gethostbyaddr( ¶ms
);
1177 status
= put_hostent32( params
.host
, ULongToPtr(params32
->host
), ULongToPtr(params32
->size
) );
1178 free( params
.host
);
1183 static NTSTATUS
wow64_unix_gethostbyname( void *args
)
1190 } const *params32
= args
;
1193 struct gethostbyname_params params
=
1195 ULongToPtr( params32
->name
),
1197 ULongToPtr(params32
->size
)
1200 if (!(params
.host
= malloc( *params
.size
))) return WSAENOBUFS
;
1201 status
= unix_gethostbyname( ¶ms
);
1203 status
= put_hostent32( params
.host
, ULongToPtr(params32
->host
), ULongToPtr(params32
->size
) );
1204 free( params
.host
);
1209 static NTSTATUS
wow64_unix_gethostname( void *args
)
1215 } const *params32
= args
;
1217 struct gethostname_params params
= { ULongToPtr(params32
->name
), params32
->size
};
1219 if (!unix_gethostname( ¶ms
)) return 0;
1220 return errno_from_unix( errno
);
1224 static NTSTATUS
wow64_unix_getnameinfo( void *args
)
1235 } const *params32
= args
;
1237 struct getnameinfo_params params
=
1239 ULongToPtr( params32
->addr
),
1241 ULongToPtr( params32
->host
),
1243 ULongToPtr( params32
->serv
),
1248 return unix_getnameinfo( ¶ms
);
1251 const unixlib_entry_t __wine_unix_call_wow64_funcs
[] =
1253 wow64_unix_getaddrinfo
,
1254 wow64_unix_gethostbyaddr
,
1255 wow64_unix_gethostbyname
,
1256 wow64_unix_gethostname
,
1257 wow64_unix_getnameinfo
,