1 /* os-ip.c -- platform-specific TCP & UDP related code */
2 /* $OpenLDAP: pkg/ldap/libraries/libldap/os-ip.c,v 1.118.2.8 2008/05/20 00:05:30 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
6 * Portions Copyright 1999 Lars Uffmann.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
17 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
18 * All rights reserved.
20 /* Significant additional contributors include:
28 #include <ac/stdlib.h>
31 #include <ac/socket.h>
32 #include <ac/string.h>
34 #include <ac/unistd.h>
38 #endif /* HAVE_IO_H */
45 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
47 int ldap_int_inet4or6
= AF_UNSPEC
;
49 int ldap_int_inet4or6
= AF_INET
;
55 #define osip_debug(ld,fmt,arg1,arg2,arg3) \
57 ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \
62 #define osip_debug(ld,fmt,arg1,arg2,arg3) ((void)0)
64 #endif /* LDAP_DEBUG */
67 ldap_pvt_set_errno(int err
)
73 ldap_int_timeval_dup( struct timeval
**dest
, const struct timeval
*src
)
77 assert( dest
!= NULL
);
84 new = (struct timeval
*) LDAP_MALLOC(sizeof(struct timeval
));
91 AC_MEMCPY( (char *) new, (const char *) src
, sizeof(struct timeval
));
98 ldap_pvt_ndelay_on(LDAP
*ld
, int fd
)
100 osip_debug(ld
, "ldap_ndelay_on: %d\n",fd
,0,0);
101 return ber_pvt_socket_set_nonblock( fd
, 1 );
105 ldap_pvt_ndelay_off(LDAP
*ld
, int fd
)
107 osip_debug(ld
, "ldap_ndelay_off: %d\n",fd
,0,0);
108 return ber_pvt_socket_set_nonblock( fd
, 0 );
112 ldap_int_socket(LDAP
*ld
, int family
, int type
)
114 ber_socket_t s
= socket(family
, type
, 0);
115 osip_debug(ld
, "ldap_new_socket: %d\n",s
,0,0);
117 fcntl(s
, F_SETFD
, FD_CLOEXEC
);
123 ldap_pvt_close_socket(LDAP
*ld
, int s
)
125 osip_debug(ld
, "ldap_close_socket: %d\n",s
,0,0);
130 ldap_int_prepare_socket(LDAP
*ld
, int s
, int proto
)
132 osip_debug( ld
, "ldap_prepare_socket: %d\n", s
, 0, 0 );
134 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
135 if ( proto
== LDAP_PROTO_TCP
) {
138 if ( setsockopt( s
, SOL_SOCKET
, SO_KEEPALIVE
,
139 (char*) &dummy
, sizeof(dummy
) ) == AC_SOCKET_ERROR
)
141 osip_debug( ld
, "ldap_prepare_socket: "
142 "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n",
145 #endif /* SO_KEEPALIVE */
147 if ( setsockopt( s
, IPPROTO_TCP
, TCP_NODELAY
,
148 (char*) &dummy
, sizeof(dummy
) ) == AC_SOCKET_ERROR
)
150 osip_debug( ld
, "ldap_prepare_socket: "
151 "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
154 #endif /* TCP_NODELAY */
156 #endif /* SO_KEEPALIVE || TCP_NODELAY */
166 "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \
169 sock_errstr(errno) ); \
173 * check the socket for errors after select returned.
176 ldap_pvt_is_socket_ready(LDAP
*ld
, int s
)
178 osip_debug(ld
, "ldap_is_sock_ready: %d\n",s
,0,0);
180 #if defined( notyet ) /* && defined( SO_ERROR ) */
183 ber_socklen_t dummy
= sizeof(so_errno
);
184 if ( getsockopt( s
, SOL_SOCKET
, SO_ERROR
, &so_errno
, &dummy
)
190 ldap_pvt_set_errno(so_errno
);
200 struct sockaddr_storage sin
;
202 struct sockaddr_in sin
;
205 ber_socklen_t dummy
= sizeof(sin
);
206 if ( getpeername( s
, (struct sockaddr
*) &sin
, &dummy
)
209 /* XXX: needs to be replace with ber_stream_read() */
221 #endif /* HAVE_WINSOCK */
223 /* NOTE: this is identical to analogous code in os-local.c */
228 struct timeval
*tvp
)
233 osip_debug(ld
, "ldap_int_poll: fd: %d tm: %ld\n",
234 s
, tvp
? tvp
->tv_sec
: -1L, 0);
239 int timeout
= INFTIM
;
242 fd
.events
= POLL_WRITE
;
245 timeout
= TV2MILLISEC( tvp
);
249 rc
= poll( &fd
, 1, timeout
);
251 } while ( rc
== AC_SOCKET_ERROR
&& errno
== EINTR
&&
252 LDAP_BOOL_GET( &ld
->ld_options
, LDAP_BOOL_RESTART
) );
254 if ( rc
== AC_SOCKET_ERROR
) {
258 if ( timeout
== 0 && rc
== 0 ) {
262 if ( fd
.revents
& POLL_WRITE
) {
263 if ( ldap_pvt_is_socket_ready( ld
, s
) == -1 ) {
267 if ( ldap_pvt_ndelay_off( ld
, s
) == -1 ) {
275 fd_set wfds
, *z
= NULL
;
279 struct timeval tv
= { 0 };
281 #if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
282 if ( s
>= FD_SETSIZE
) {
283 rc
= AC_SOCKET_ERROR
;
285 ldap_pvt_set_errno( EMFILE
);
303 rc
= select( ldap_int_tblsize
, z
, &wfds
,
310 } while ( rc
== AC_SOCKET_ERROR
&& errno
== EINTR
&&
311 LDAP_BOOL_GET( &ld
->ld_options
, LDAP_BOOL_RESTART
) );
313 if ( rc
== AC_SOCKET_ERROR
) {
317 if ( rc
== 0 && tvp
&& tvp
->tv_sec
== 0 && tvp
->tv_usec
== 0 ) {
322 /* This means the connection failed */
323 if ( FD_ISSET(s
, &efds
) ) {
325 ber_socklen_t dummy
= sizeof(so_errno
);
326 if ( getsockopt( s
, SOL_SOCKET
, SO_ERROR
,
327 (char *) &so_errno
, &dummy
) == AC_SOCKET_ERROR
|| !so_errno
)
330 so_errno
= WSAGetLastError();
332 ldap_pvt_set_errno( so_errno
);
333 osip_debug(ld
, "ldap_int_poll: error on socket %d: "
334 "errno: %d (%s)\n", s
, errno
, sock_errstr( errno
));
338 if ( FD_ISSET(s
, &wfds
) ) {
340 if ( ldap_pvt_is_socket_ready( ld
, s
) == -1 ) {
344 if ( ldap_pvt_ndelay_off(ld
, s
) == -1 ) {
352 osip_debug(ld
, "ldap_int_poll: timed out\n",0,0,0);
353 ldap_pvt_set_errno( ETIMEDOUT
);
358 ldap_pvt_connect(LDAP
*ld
, ber_socket_t s
,
359 struct sockaddr
*sin
, ber_socklen_t addrlen
,
363 struct timeval tv
, *opt_tv
= NULL
;
365 #ifdef LDAP_CONNECTIONLESS
366 /* We could do a connect() but that would interfere with
367 * attempts to poll a broadcast address
369 if (LDAP_IS_UDP(ld
)) {
370 if (ld
->ld_options
.ldo_peer
)
371 ldap_memfree(ld
->ld_options
.ldo_peer
);
372 ld
->ld_options
.ldo_peer
=ldap_memalloc(sizeof(struct sockaddr
));
373 AC_MEMCPY(ld
->ld_options
.ldo_peer
,sin
,sizeof(struct sockaddr
));
377 if ( ld
->ld_options
.ldo_tm_net
.tv_sec
>= 0 ) {
378 tv
= ld
->ld_options
.ldo_tm_net
;
382 osip_debug(ld
, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
383 s
, opt_tv
? tv
.tv_sec
: -1L, async
);
385 if ( opt_tv
&& ldap_pvt_ndelay_on(ld
, s
) == -1 )
388 if ( connect(s
, sin
, addrlen
) != AC_SOCKET_ERROR
) {
389 if ( opt_tv
&& ldap_pvt_ndelay_off(ld
, s
) == -1 )
395 if ( err
!= EINPROGRESS
&& err
!= EWOULDBLOCK
) {
400 /* caller will call ldap_int_poll() as appropriate? */
404 rc
= ldap_int_poll( ld
, s
, opt_tv
);
406 osip_debug(ld
, "ldap_pvt_connect: %d\n", rc
, 0, 0);
411 #ifndef HAVE_INET_ATON
413 ldap_pvt_inet_aton( const char *host
, struct in_addr
*in
)
415 unsigned long u
= inet_addr( host
);
418 if ( u
== INADDR_NONE
) return 0;
420 if ( u
== 0xffffffffUL
|| u
== (unsigned long) -1L ) return 0;
429 ldap_connect_to_host(LDAP
*ld
, Sockbuf
*sb
,
431 const char *host
, int port
,
436 ber_socket_t s
= AC_SOCKET_INVALID
;
438 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
441 struct addrinfo hints
, *res
, *sai
;
445 struct hostent
*hp
= NULL
;
446 struct hostent he_buf
;
451 if( host
== NULL
) host
= "localhost";
454 case LDAP_PROTO_TCP
: socktype
= SOCK_STREAM
;
456 "ldap_connect_to_host: TCP %s:%d\n",
459 case LDAP_PROTO_UDP
: socktype
= SOCK_DGRAM
;
461 "ldap_connect_to_host: UDP %s:%d\n",
465 osip_debug( ld
, "ldap_connect_to_host: unknown proto: %d\n",
470 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
471 memset( &hints
, '\0', sizeof(hints
) );
472 #ifdef USE_AI_ATTRCONFIG /* FIXME: configure test needed */
473 /* Use AI_ATTRCONFIG only on systems where its known to be needed. */
474 hints
.ai_flags
= AI_ATTRCONFIG
;
476 hints
.ai_family
= ldap_int_inet4or6
;
477 hints
.ai_socktype
= socktype
;
478 snprintf(serv
, sizeof serv
, "%d", port
);
480 #ifdef LDAP_R_COMPILE
481 /* most getaddrinfo(3) use non-threadsafe resolver libraries */
482 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex
);
485 err
= getaddrinfo( host
, serv
, &hints
, &res
);
487 #ifdef LDAP_R_COMPILE
488 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex
);
492 osip_debug(ld
, "ldap_connect_to_host: getaddrinfo failed: %s\n",
493 AC_GAI_STRERROR(err
), 0, 0);
498 for( sai
=res
; sai
!= NULL
; sai
=sai
->ai_next
) {
499 if( sai
->ai_addr
== NULL
) {
500 osip_debug(ld
, "ldap_connect_to_host: getaddrinfo "
501 "ai_addr is NULL?\n", 0, 0, 0);
505 /* we assume AF_x and PF_x are equal for all x */
506 s
= ldap_int_socket( ld
, sai
->ai_family
, socktype
);
507 if ( s
== AC_SOCKET_INVALID
) {
511 if ( ldap_int_prepare_socket(ld
, s
, proto
) == -1 ) {
512 ldap_pvt_close_socket(ld
, s
);
516 switch (sai
->ai_family
) {
519 char addr
[INET6_ADDRSTRLEN
];
521 &((struct sockaddr_in6
*)sai
->ai_addr
)->sin6_addr
,
523 osip_debug(ld
, "ldap_connect_to_host: Trying %s %s\n",
528 char addr
[INET_ADDRSTRLEN
];
530 &((struct sockaddr_in
*)sai
->ai_addr
)->sin_addr
,
532 osip_debug(ld
, "ldap_connect_to_host: Trying %s:%s\n",
537 rc
= ldap_pvt_connect( ld
, s
,
538 sai
->ai_addr
, sai
->ai_addrlen
, async
);
539 if ( rc
== 0 || rc
== -2 ) {
540 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_SET_FD
, &s
);
543 ldap_pvt_close_socket(ld
, s
);
548 if (! inet_aton( host
, &in
) ) {
550 rc
= ldap_pvt_gethostbyname_a( host
, &he_buf
, &ha_buf
,
551 &hp
, &local_h_errno
);
553 if ( (rc
< 0) || (hp
== NULL
) ) {
555 ldap_pvt_set_errno( WSAGetLastError() );
557 /* not exactly right, but... */
558 ldap_pvt_set_errno( EHOSTUNREACH
);
560 if (ha_buf
) LDAP_FREE(ha_buf
);
568 for ( i
= 0; !use_hp
|| (hp
->h_addr_list
[i
] != 0); ++i
, rc
= -1 ) {
569 struct sockaddr_in sin
;
571 s
= ldap_int_socket( ld
, PF_INET
, socktype
);
572 if ( s
== AC_SOCKET_INVALID
) {
573 /* use_hp ? continue : break; */
577 if ( ldap_int_prepare_socket( ld
, s
, proto
) == -1 ) {
578 ldap_pvt_close_socket(ld
, s
);
582 (void)memset((char *)&sin
, '\0', sizeof sin
);
583 sin
.sin_family
= AF_INET
;
584 sin
.sin_port
= htons((unsigned short) port
);
587 AC_MEMCPY( &sin
.sin_addr
, hp
->h_addr_list
[i
],
588 sizeof(sin
.sin_addr
) );
590 AC_MEMCPY( &sin
.sin_addr
, &in
.s_addr
,
591 sizeof(sin
.sin_addr
) );
594 #ifdef HAVE_INET_NTOA_B
597 char address
[INET_ADDR_LEN
];
598 inet_ntoa_b(sin
.sin_address
, address
);
599 osip_debug(ld
, "ldap_connect_to_host: Trying %s:%d\n",
603 osip_debug(ld
, "ldap_connect_to_host: Trying %s:%d\n",
604 inet_ntoa(sin
.sin_addr
), port
, 0);
607 rc
= ldap_pvt_connect(ld
, s
,
608 (struct sockaddr
*)&sin
, sizeof(sin
),
611 if ( (rc
== 0) || (rc
== -2) ) {
612 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_SET_FD
, &s
);
616 ldap_pvt_close_socket(ld
, s
);
620 if (ha_buf
) LDAP_FREE(ha_buf
);
626 #if defined( HAVE_CYRUS_SASL )
628 ldap_host_connected_to( Sockbuf
*sb
, const char *host
)
632 struct sockaddr_storage sabuf
;
634 struct sockaddr sabuf
;
636 struct sockaddr
*sa
= (struct sockaddr
*) &sabuf
;
639 (void)memset( (char *)sa
, '\0', sizeof sabuf
);
642 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
643 if ( getpeername( sd
, sa
, &len
) == -1 ) {
648 * do a reverse lookup on the addr to get the official hostname.
649 * this is necessary for kerberos to work right, since the official
650 * hostname is used as the kerberos instance.
653 switch (sa
->sa_family
) {
656 return LDAP_STRDUP( ldap_int_hostname
);
661 struct in6_addr localhost
= IN6ADDR_LOOPBACK_INIT
;
662 if( memcmp ( &((struct sockaddr_in6
*)sa
)->sin6_addr
,
663 &localhost
, sizeof(localhost
)) == 0 )
665 return LDAP_STRDUP( ldap_int_hostname
);
672 struct in_addr localhost
;
673 localhost
.s_addr
= htonl( INADDR_ANY
);
675 if( memcmp ( &((struct sockaddr_in
*)sa
)->sin_addr
,
676 &localhost
, sizeof(localhost
) ) == 0 )
678 return LDAP_STRDUP( ldap_int_hostname
);
681 #ifdef INADDR_LOOPBACK
682 localhost
.s_addr
= htonl( INADDR_LOOPBACK
);
684 if( memcmp ( &((struct sockaddr_in
*)sa
)->sin_addr
,
685 &localhost
, sizeof(localhost
) ) == 0 )
687 return LDAP_STRDUP( ldap_int_hostname
);
701 char hbuf
[NI_MAXHOST
];
702 #elif defined( MAXHOSTNAMELEN
703 char hbuf
[MAXHOSTNAMELEN
];
709 if (ldap_pvt_get_hname( sa
, len
, hbuf
, sizeof(hbuf
), &herr
) == 0
712 return LDAP_STRDUP( hbuf
);
716 return host
? LDAP_STRDUP( host
) : NULL
;
723 /* for UNIX poll(2) */
725 struct pollfd si_fds
[FD_SETSIZE
];
727 /* for UNIX select(2) */
730 fd_set si_use_readfds
;
731 fd_set si_use_writefds
;
736 ldap_mark_select_write( LDAP
*ld
, Sockbuf
*sb
)
738 struct selectinfo
*sip
;
741 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
743 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
746 /* for UNIX poll(2) */
750 for(i
=0; i
< sip
->si_maxfd
; i
++) {
751 if( sip
->si_fds
[i
].fd
== sd
) {
752 sip
->si_fds
[i
].events
|= POLL_WRITE
;
755 if( empty
==-1 && sip
->si_fds
[i
].fd
== -1 ) {
761 if( sip
->si_maxfd
>= FD_SETSIZE
) {
765 empty
= sip
->si_maxfd
++;
768 sip
->si_fds
[empty
].fd
= sd
;
769 sip
->si_fds
[empty
].events
= POLL_WRITE
;
772 /* for UNIX select(2) */
773 if ( !FD_ISSET( sd
, &sip
->si_writefds
)) {
774 FD_SET( sd
, &sip
->si_writefds
);
781 ldap_mark_select_read( LDAP
*ld
, Sockbuf
*sb
)
783 struct selectinfo
*sip
;
786 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
788 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
791 /* for UNIX poll(2) */
795 for(i
=0; i
< sip
->si_maxfd
; i
++) {
796 if( sip
->si_fds
[i
].fd
== sd
) {
797 sip
->si_fds
[i
].events
|= POLL_READ
;
800 if( empty
==-1 && sip
->si_fds
[i
].fd
== -1 ) {
806 if( sip
->si_maxfd
>= FD_SETSIZE
) {
810 empty
= sip
->si_maxfd
++;
813 sip
->si_fds
[empty
].fd
= sd
;
814 sip
->si_fds
[empty
].events
= POLL_READ
;
817 /* for UNIX select(2) */
818 if ( !FD_ISSET( sd
, &sip
->si_readfds
)) {
819 FD_SET( sd
, &sip
->si_readfds
);
826 ldap_mark_select_clear( LDAP
*ld
, Sockbuf
*sb
)
828 struct selectinfo
*sip
;
831 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
833 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
836 /* for UNIX poll(2) */
839 for(i
=0; i
< sip
->si_maxfd
; i
++) {
840 if( sip
->si_fds
[i
].fd
== sd
) {
841 sip
->si_fds
[i
].fd
= -1;
846 /* for UNIX select(2) */
847 FD_CLR( sd
, &sip
->si_writefds
);
848 FD_CLR( sd
, &sip
->si_readfds
);
854 ldap_is_write_ready( LDAP
*ld
, Sockbuf
*sb
)
856 struct selectinfo
*sip
;
859 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
861 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
864 /* for UNIX poll(2) */
867 for(i
=0; i
< sip
->si_maxfd
; i
++) {
868 if( sip
->si_fds
[i
].fd
== sd
) {
869 return sip
->si_fds
[i
].revents
& POLL_WRITE
;
876 /* for UNIX select(2) */
877 return( FD_ISSET( sd
, &sip
->si_use_writefds
));
883 ldap_is_read_ready( LDAP
*ld
, Sockbuf
*sb
)
885 struct selectinfo
*sip
;
888 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
890 ber_sockbuf_ctrl( sb
, LBER_SB_OPT_GET_FD
, &sd
);
893 /* for UNIX poll(2) */
896 for(i
=0; i
< sip
->si_maxfd
; i
++) {
897 if( sip
->si_fds
[i
].fd
== sd
) {
898 return sip
->si_fds
[i
].revents
& POLL_READ
;
905 /* for UNIX select(2) */
906 return( FD_ISSET( sd
, &sip
->si_use_readfds
));
912 ldap_new_select_info( void )
914 struct selectinfo
*sip
;
916 sip
= (struct selectinfo
*)LDAP_CALLOC( 1, sizeof( struct selectinfo
));
918 if ( sip
== NULL
) return NULL
;
921 /* for UNIX poll(2) */
922 /* sip->si_maxfd=0 */
924 /* for UNIX select(2) */
925 FD_ZERO( &sip
->si_readfds
);
926 FD_ZERO( &sip
->si_writefds
);
929 return( (void *)sip
);
934 ldap_free_select_info( void *sip
)
941 int ldap_int_tblsize
= 0;
944 ldap_int_ip_init( void )
946 #if defined( HAVE_SYSCONF )
947 long tblsize
= sysconf( _SC_OPEN_MAX
);
948 if( tblsize
> INT_MAX
) tblsize
= INT_MAX
;
950 #elif defined( HAVE_GETDTABLESIZE )
951 int tblsize
= getdtablesize();
953 int tblsize
= FD_SETSIZE
;
954 #endif /* !USE_SYSCONF */
957 if( tblsize
> FD_SETSIZE
) tblsize
= FD_SETSIZE
;
958 #endif /* FD_SETSIZE */
960 ldap_int_tblsize
= tblsize
;
966 ldap_int_select( LDAP
*ld
, struct timeval
*timeout
)
969 struct selectinfo
*sip
;
971 Debug( LDAP_DEBUG_TRACE
, "ldap_int_select\n", 0, 0, 0 );
974 if ( ldap_int_tblsize
== 0 ) ldap_int_ip_init();
977 sip
= (struct selectinfo
*)ld
->ld_selectinfo
;
978 assert( sip
!= NULL
);
982 int to
= timeout
? TV2MILLISEC( timeout
) : INFTIM
;
983 rc
= poll( sip
->si_fds
, sip
->si_maxfd
, to
);
986 sip
->si_use_readfds
= sip
->si_readfds
;
987 sip
->si_use_writefds
= sip
->si_writefds
;
989 rc
= select( ldap_int_tblsize
,
990 &sip
->si_use_readfds
, &sip
->si_use_writefds
,