2 * Copyright (c) 1995 Regents of the University of Michigan.
5 * os-ip.c -- platform-specific TCP & UDP related code
9 static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
12 #define DISABLE_BRIDGE
17 #include <ac/string.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
33 #include <sys/select.h>
36 #include "ucx_select.h"
46 #endif /* USE_SYSCONF */
49 #include <sys/filio.h>
50 #else /* NEED_FILIO */
51 #include <sys/ioctl.h>
52 #endif /* NEED_FILIO */
54 #endif /* LDAP_REFERRALS */
57 #define tcp_close( s ) tcpclose( s )
61 #define tcp_close( s ) close( s )
64 #define tcp_close( s ) netclose( s ); netshut()
67 #define tcp_close( s ) closesocket( s ); WSACleanup();
70 #define tcp_close( s ) close( s )
77 ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
80 * if host == NULL, connect using address
81 * "address" and "port" must be in network byte order
82 * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
83 * async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
84 * XXX async is not used yet!
88 int connected, use_hp;
89 struct sockaddr_in sin;
90 struct hostent *hp = NULL;
93 int status; /* for ioctl call */
94 #endif /* LDAP_REFERRALS */
97 Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
98 ( host == NULL ) ? "(by address)" : host, ntohs( port ), 0 );
100 connected = use_hp = 0;
102 if ( host != NULL && ( address = inet_addr( host )) == -1 ) {
103 if ( (hp = gethostbyname( host )) == NULL ) {
104 errno = EHOSTUNREACH; /* not exactly right, but... */
111 for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
112 if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
116 #ifdef LDAP_REFERRALS
118 if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
119 Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
122 #endif /* LDAP_REFERRALS */
124 (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
125 sin.sin_family = AF_INET;
127 SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
128 ( use_hp ? (char *) hp->h_addr_list[ i ] :
129 (char *) &address ), sizeof( sin.sin_addr.s_addr) );
131 if ( connect( s, (struct sockaddr *)&sin,
132 sizeof( struct sockaddr_in )) >= 0 ) {
138 #ifdef LDAP_REFERRALS
140 if ( errno == EINPROGRESS || errno == EAGAIN ) {
142 if ( errno == EINPROGRESS ) {
144 Debug( LDAP_DEBUG_TRACE,
145 "connect would block...\n", 0, 0, 0 );
149 #endif /* LDAP_REFERRALS */
153 if ( ldap_debug & LDAP_DEBUG_TRACE ) {
154 perror( (char *)inet_ntoa( sin.sin_addr ));
168 #ifdef LDAP_REFERRALS
170 if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
171 Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
174 #endif /* LDAP_REFERRALS */
177 Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
178 s, inet_ntoa( sin.sin_addr ), 0 );
186 ldap_close_connection( Sockbuf *sb )
188 tcp_close( sb->sb_sd );
194 ldap_host_connected_to( Sockbuf *sb )
199 struct sockaddr_in sin;
201 (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
203 if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
208 * do a reverse lookup on the addr to get the official hostname.
209 * this is necessary for kerberos to work right, since the official
210 * hostname is used as the kerberos instance.
212 if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
213 sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
214 if ( hp->h_name != NULL ) {
215 return( strdup( hp->h_name ));
221 #endif /* KERBEROS */
224 #ifdef LDAP_REFERRALS
229 fd_set si_use_readfds;
230 fd_set si_use_writefds;
235 ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
237 struct selectinfo *sip;
239 sip = (struct selectinfo *)ld->ld_selectinfo;
241 if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
242 FD_SET( sb->sb_sd, &sip->si_writefds );
248 ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
250 struct selectinfo *sip;
252 sip = (struct selectinfo *)ld->ld_selectinfo;
254 if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
255 FD_SET( sb->sb_sd, &sip->si_readfds );
261 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
263 struct selectinfo *sip;
265 sip = (struct selectinfo *)ld->ld_selectinfo;
267 FD_CLR( sb->sb_sd, &sip->si_writefds );
268 FD_CLR( sb->sb_sd, &sip->si_readfds );
273 ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
275 struct selectinfo *sip;
277 sip = (struct selectinfo *)ld->ld_selectinfo;
279 return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
284 ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
286 struct selectinfo *sip;
288 sip = (struct selectinfo *)ld->ld_selectinfo;
290 return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
295 ldap_new_select_info()
297 struct selectinfo *sip;
299 if (( sip = (struct selectinfo *)calloc( 1,
300 sizeof( struct selectinfo ))) != NULL ) {
301 FD_ZERO( &sip->si_readfds );
302 FD_ZERO( &sip->si_writefds );
305 return( (void *)sip );
310 ldap_free_select_info( void *sip )
317 do_ldap_select( LDAP *ld, struct timeval *timeout )
319 struct selectinfo *sip;
322 Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
324 if ( tblsize == 0 ) {
326 tblsize = sysconf( _SC_OPEN_MAX );
327 #else /* !USE_SYSCONF */
328 tblsize = getdtablesize();
329 #endif /* !USE_SYSCONF */
332 if( tblsize > FD_SETSIZE ) {
333 tblsize = FD_SETSIZE;
335 #endif /* FD_SETSIZE*/
338 sip = (struct selectinfo *)ld->ld_selectinfo;
339 sip->si_use_readfds = sip->si_readfds;
340 sip->si_use_writefds = sip->si_writefds;
342 return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
345 #endif /* LDAP_REFERRALS */