]> git.sur5r.net Git - openldap/blob - libraries/libldap/os-ip.c
Happy New Year
[openldap] / libraries / libldap / os-ip.c
1 /* os-ip.c -- platform-specific TCP & UDP related code */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2018 The OpenLDAP Foundation.
6  * Portions Copyright 1999 Lars Uffmann.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
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>.
16  */
17 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
18  * All rights reserved.
19  */
20 /* Significant additional contributors include:
21  *    Lars Uffman
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/stdlib.h>
29
30 #include <ac/errno.h>
31 #include <ac/socket.h>
32 #include <ac/string.h>
33 #include <ac/time.h>
34 #include <ac/unistd.h>
35
36 #ifdef HAVE_IO_H
37 #include <io.h>
38 #endif /* HAVE_IO_H */
39 #ifdef HAVE_FCNTL_H
40 #include <fcntl.h>
41 #endif
42
43 #include "ldap-int.h"
44
45 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
46 #  ifdef LDAP_PF_INET6
47 int ldap_int_inet4or6 = AF_UNSPEC;
48 #  else
49 int ldap_int_inet4or6 = AF_INET;
50 #  endif
51 #endif
52
53 #ifdef LDAP_DEBUG
54
55 #define osip_debug(ld,fmt,arg1,arg2,arg3) \
56 do { \
57         ldap_log_printf(NULL, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \
58 } while(0)
59
60 #else
61
62 #define osip_debug(ld,fmt,arg1,arg2,arg3) ((void)0)
63
64 #endif /* LDAP_DEBUG */
65
66 static void
67 ldap_pvt_set_errno(int err)
68 {
69         sock_errset(err);
70 }
71
72 int
73 ldap_int_timeval_dup( struct timeval **dest, const struct timeval *src )
74 {
75         struct timeval *new;
76
77         assert( dest != NULL );
78
79         if (src == NULL) {
80                 *dest = NULL;
81                 return 0;
82         }
83
84         new = (struct timeval *) LDAP_MALLOC(sizeof(struct timeval));
85
86         if( new == NULL ) {
87                 *dest = NULL;
88                 return 1;
89         }
90
91         AC_MEMCPY( (char *) new, (const char *) src, sizeof(struct timeval));
92
93         *dest = new;
94         return 0;
95 }
96
97 static int
98 ldap_pvt_ndelay_on(LDAP *ld, int fd)
99 {
100         osip_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0);
101         return ber_pvt_socket_set_nonblock( fd, 1 );
102 }
103    
104 static int
105 ldap_pvt_ndelay_off(LDAP *ld, int fd)
106 {
107         osip_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0);
108         return ber_pvt_socket_set_nonblock( fd, 0 );
109 }
110
111 static ber_socket_t
112 ldap_int_socket(LDAP *ld, int family, int type )
113 {
114         ber_socket_t s = socket(family, type, 0);
115         osip_debug(ld, "ldap_new_socket: %d\n",s,0,0);
116 #ifdef FD_CLOEXEC
117         fcntl(s, F_SETFD, FD_CLOEXEC);
118 #endif
119         return ( s );
120 }
121
122 static int
123 ldap_pvt_close_socket(LDAP *ld, int s)
124 {
125         osip_debug(ld, "ldap_close_socket: %d\n",s,0,0);
126         return tcp_close(s);
127 }
128
129 static int
130 ldap_int_prepare_socket(LDAP *ld, int s, int proto )
131 {
132         osip_debug( ld, "ldap_prepare_socket: %d\n", s, 0, 0 );
133
134 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
135         if ( proto == LDAP_PROTO_TCP ) {
136                 int dummy = 1;
137 #ifdef SO_KEEPALIVE
138                 if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
139                         (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
140                 {
141                         osip_debug( ld, "ldap_prepare_socket: "
142                                 "setsockopt(%d, SO_KEEPALIVE) failed (ignored).\n",
143                                 s, 0, 0 );
144                 }
145                 if ( ld->ld_options.ldo_keepalive_idle > 0 )
146                 {
147 #ifdef TCP_KEEPIDLE
148                         if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPIDLE,
149                                         (void*) &ld->ld_options.ldo_keepalive_idle,
150                                         sizeof(ld->ld_options.ldo_keepalive_idle) ) == AC_SOCKET_ERROR )
151                         {
152                                 osip_debug( ld, "ldap_prepare_socket: "
153                                         "setsockopt(%d, TCP_KEEPIDLE) failed (ignored).\n",
154                                         s, 0, 0 );
155                         }
156 #else
157                         osip_debug( ld, "ldap_prepare_socket: "
158                                         "sockopt TCP_KEEPIDLE not supported on this system.\n", 
159                                         0, 0, 0 );
160 #endif /* TCP_KEEPIDLE */
161                 }
162                 if ( ld->ld_options.ldo_keepalive_probes > 0 )
163                 {
164 #ifdef TCP_KEEPCNT
165                         if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPCNT,
166                                         (void*) &ld->ld_options.ldo_keepalive_probes,
167                                         sizeof(ld->ld_options.ldo_keepalive_probes) ) == AC_SOCKET_ERROR )
168                         {
169                                 osip_debug( ld, "ldap_prepare_socket: "
170                                         "setsockopt(%d, TCP_KEEPCNT) failed (ignored).\n",
171                                         s, 0, 0 );
172                         }
173 #else
174                         osip_debug( ld, "ldap_prepare_socket: "
175                                         "sockopt TCP_KEEPCNT not supported on this system.\n", 
176                                         0, 0, 0 );
177 #endif /* TCP_KEEPCNT */
178                 }
179                 if ( ld->ld_options.ldo_keepalive_interval > 0 )
180                 {
181 #ifdef TCP_KEEPINTVL
182                         if ( setsockopt( s, IPPROTO_TCP, TCP_KEEPINTVL,
183                                         (void*) &ld->ld_options.ldo_keepalive_interval,
184                                         sizeof(ld->ld_options.ldo_keepalive_interval) ) == AC_SOCKET_ERROR )
185                         {
186                                 osip_debug( ld, "ldap_prepare_socket: "
187                                         "setsockopt(%d, TCP_KEEPINTVL) failed (ignored).\n",
188                                         s, 0, 0 );
189                         } 
190 #else
191                         osip_debug( ld, "ldap_prepare_socket: "
192                                         "sockopt TCP_KEEPINTVL not supported on this system.\n", 
193                                         0, 0, 0 );
194 #endif /* TCP_KEEPINTVL */
195                 }
196 #endif /* SO_KEEPALIVE */
197 #ifdef TCP_NODELAY
198                 if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
199                         (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
200                 {
201                         osip_debug( ld, "ldap_prepare_socket: "
202                                 "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
203                                 s, 0, 0 );
204                 }
205 #endif /* TCP_NODELAY */
206         }
207 #endif /* SO_KEEPALIVE || TCP_NODELAY */
208
209         return 0;
210 }
211
212 #ifndef HAVE_WINSOCK
213
214 #undef TRACE
215 #define TRACE do { \
216         osip_debug(ld, \
217                 "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \
218                 s, \
219                 errno, \
220                 sock_errstr(errno) ); \
221 } while( 0 )
222
223 /*
224  * check the socket for errors after select returned.
225  */
226 static int
227 ldap_pvt_is_socket_ready(LDAP *ld, int s)
228 {
229         osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0);
230
231 #if defined( notyet ) /* && defined( SO_ERROR ) */
232 {
233         int so_errno;
234         ber_socklen_t dummy = sizeof(so_errno);
235         if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
236                 == AC_SOCKET_ERROR )
237         {
238                 return -1;
239         }
240         if ( so_errno ) {
241                 ldap_pvt_set_errno(so_errno);
242                 TRACE;
243                 return -1;
244         }
245         return 0;
246 }
247 #else
248 {
249         /* error slippery */
250 #ifdef LDAP_PF_INET6
251         struct sockaddr_storage sin;
252 #else
253         struct sockaddr_in sin;
254 #endif
255         char ch;
256         ber_socklen_t dummy = sizeof(sin);
257         if ( getpeername( s, (struct sockaddr *) &sin, &dummy )
258                 == AC_SOCKET_ERROR )
259         {
260                 /* XXX: needs to be replace with ber_stream_read() */
261                 (void)read(s, &ch, 1);
262                 TRACE;
263                 return -1;
264         }
265         return 0;
266 }
267 #endif
268         return -1;
269 }
270 #undef TRACE
271
272 #endif /* HAVE_WINSOCK */
273
274 /* NOTE: this is identical to analogous code in os-local.c */
275 int
276 ldap_int_poll(
277         LDAP *ld,
278         ber_socket_t s,
279         struct timeval *tvp,
280         int wr )
281 {
282         int             rc;
283                 
284
285         osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n",
286                 s, tvp ? tvp->tv_sec : -1L, 0);
287
288 #ifdef HAVE_POLL
289         {
290                 struct pollfd fd;
291                 int timeout = INFTIM;
292                 short event = wr ? POLL_WRITE : POLL_READ;
293
294                 fd.fd = s;
295                 fd.events = event;
296
297                 if ( tvp != NULL ) {
298                         timeout = TV2MILLISEC( tvp );
299                 }
300                 do {
301                         fd.revents = 0;
302                         rc = poll( &fd, 1, timeout );
303                 
304                 } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
305                         LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
306
307                 if ( rc == AC_SOCKET_ERROR ) {
308                         return rc;
309                 }
310
311                 if ( timeout == 0 && rc == 0 ) {
312                         return -2;
313                 }
314
315                 if ( fd.revents & event ) {
316                         if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
317                                 return -1;
318                         }
319
320                         if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) {
321                                 return -1;
322                         }
323                         return 0;
324                 }
325         }
326 #else
327         {
328                 fd_set          wfds, *z = NULL;
329 #ifdef HAVE_WINSOCK
330                 fd_set          efds;
331 #endif
332                 struct timeval  tv = { 0 };
333
334 #if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
335                 if ( s >= FD_SETSIZE ) {
336                         rc = AC_SOCKET_ERROR;
337                         tcp_close( s );
338                         ldap_pvt_set_errno( EMFILE );
339                         return rc;
340                 }
341 #endif
342
343                 if ( tvp != NULL ) {
344                         tv = *tvp;
345                 }
346
347                 do {
348                         FD_ZERO(&wfds);
349                         FD_SET(s, &wfds );
350
351 #ifdef HAVE_WINSOCK
352                         FD_ZERO(&efds);
353                         FD_SET(s, &efds );
354 #endif
355
356                         rc = select( ldap_int_tblsize, z, &wfds,
357 #ifdef HAVE_WINSOCK
358                                 &efds,
359 #else
360                                 z,
361 #endif
362                                 tvp ? &tv : NULL );
363                 } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
364                         LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
365
366                 if ( rc == AC_SOCKET_ERROR ) {
367                         return rc;
368                 }
369
370                 if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) {
371                         return -2;
372                 }
373
374 #ifdef HAVE_WINSOCK
375                 /* This means the connection failed */
376                 if ( FD_ISSET(s, &efds) ) {
377                         int so_errno;
378                         ber_socklen_t dummy = sizeof(so_errno);
379                         if ( getsockopt( s, SOL_SOCKET, SO_ERROR,
380                                 (char *) &so_errno, &dummy ) == AC_SOCKET_ERROR || !so_errno )
381                         {
382                                 /* impossible */
383                                 so_errno = WSAGetLastError();
384                         }
385                         ldap_pvt_set_errno( so_errno );
386                         osip_debug(ld, "ldap_int_poll: error on socket %d: "
387                                "errno: %d (%s)\n", s, errno, sock_errstr( errno ));
388                         return -1;
389                 }
390 #endif
391                 if ( FD_ISSET(s, &wfds) ) {
392 #ifndef HAVE_WINSOCK
393                         if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
394                                 return -1;
395                         }
396 #endif
397                         if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
398                                 return -1;
399                         }
400                         return 0;
401                 }
402         }
403 #endif
404
405         osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0);
406         ldap_pvt_set_errno( ETIMEDOUT );
407         return -1;
408 }
409
410 static int
411 ldap_pvt_connect(LDAP *ld, ber_socket_t s,
412         struct sockaddr *sin, ber_socklen_t addrlen,
413         int async)
414 {
415         int rc, err;
416         struct timeval  tv, *opt_tv = NULL;
417
418 #ifdef LDAP_CONNECTIONLESS
419         /* We could do a connect() but that would interfere with
420          * attempts to poll a broadcast address
421          */
422         if (LDAP_IS_UDP(ld)) {
423                 if (ld->ld_options.ldo_peer)
424                         ldap_memfree(ld->ld_options.ldo_peer);
425                 ld->ld_options.ldo_peer=ldap_memcalloc(1, sizeof(struct sockaddr_storage));
426                 AC_MEMCPY(ld->ld_options.ldo_peer,sin,addrlen);
427                 return ( 0 );
428         }
429 #endif
430         if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
431                 tv = ld->ld_options.ldo_tm_net;
432                 opt_tv = &tv;
433         }
434
435         osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
436                         s, opt_tv ? tv.tv_sec : -1L, async);
437
438         if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 )
439                 return ( -1 );
440
441         do{
442                 osip_debug(ld, "attempting to connect: \n", 0, 0, 0);
443                 if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
444                         osip_debug(ld, "connect success\n", 0, 0, 0);
445
446                         if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
447                                 return ( -1 );
448                         return ( 0 );
449                 }
450                 err = sock_errno();
451                 osip_debug(ld, "connect errno: %d\n", err, 0, 0);
452
453         } while(err == EINTR &&
454                 LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ));
455
456         if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
457                 return ( -1 );
458         }
459         
460         if ( async ) {
461                 /* caller will call ldap_int_poll() as appropriate? */
462                 return ( -2 );
463         }
464
465         rc = ldap_int_poll( ld, s, opt_tv, 1 );
466
467         osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);
468
469         return rc;
470 }
471
472 #ifndef HAVE_INET_ATON
473 int
474 ldap_pvt_inet_aton( const char *host, struct in_addr *in)
475 {
476         unsigned long u = inet_addr( host );
477
478 #ifdef INADDR_NONE
479         if ( u == INADDR_NONE ) return 0;
480 #endif
481         if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0;
482
483         in->s_addr = u;
484         return 1;
485 }
486 #endif
487
488 int
489 ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr)
490 {
491         struct ldapoptions *lo;
492         ldaplist *ll;
493         ldap_conncb *cb;
494         int rc;
495
496         ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s );
497
498         /* Invoke all handle-specific callbacks first */
499         lo = &ld->ld_options;
500         for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
501                 cb = ll->ll_data;
502                 rc = cb->lc_add( ld, sb, srv, addr, cb );
503                 /* on any failure, call the teardown functions for anything
504                  * that previously succeeded
505                  */
506                 if ( rc ) {
507                         ldaplist *l2;
508                         for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
509                                 cb = l2->ll_data;
510                                 cb->lc_del( ld, sb, cb );
511                         }
512                         /* a failure might have implicitly closed the fd */
513                         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
514                         return rc;
515                 }
516         }
517         lo = LDAP_INT_GLOBAL_OPT();
518         for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
519                 cb = ll->ll_data;
520                 rc = cb->lc_add( ld, sb, srv, addr, cb );
521                 if ( rc ) {
522                         ldaplist *l2;
523                         for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
524                                 cb = l2->ll_data;
525                                 cb->lc_del( ld, sb, cb );
526                         }
527                         lo = &ld->ld_options;
528                         for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) {
529                                 cb = l2->ll_data;
530                                 cb->lc_del( ld, sb, cb );
531                         }
532                         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
533                         return rc;
534                 }
535         }
536         return 0;
537 }
538
539 int
540 ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
541         int proto, LDAPURLDesc *srv,
542         int async )
543 {
544         int     rc;
545         int     socktype, port;
546         ber_socket_t            s = AC_SOCKET_INVALID;
547         char *host;
548
549 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
550         char serv[7];
551         int err;
552         struct addrinfo hints, *res, *sai;
553 #else
554         int i;
555         int use_hp = 0;
556         struct hostent *hp = NULL;
557         struct hostent he_buf;
558         struct in_addr in;
559         char *ha_buf=NULL;
560 #endif
561
562         if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
563                 host = "localhost";
564         } else {
565                 host = srv->lud_host;
566         }
567
568         port = srv->lud_port;
569
570         if( !port ) {
571                 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) {
572                         port = LDAPS_PORT;
573                 } else {
574                         port = LDAP_PORT;
575                 }
576         }
577
578         switch(proto) {
579         case LDAP_PROTO_TCP: socktype = SOCK_STREAM;
580                 osip_debug( ld,
581                         "ldap_connect_to_host: TCP %s:%d\n",
582                         host, port, 0);
583                 break;
584         case LDAP_PROTO_UDP: socktype = SOCK_DGRAM;
585                 osip_debug( ld,
586                         "ldap_connect_to_host: UDP %s:%d\n",
587                         host, port, 0);
588                 break;
589         default:
590                 osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n",
591                         proto, 0, 0 );
592                 return -1;
593         }
594
595 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
596         memset( &hints, '\0', sizeof(hints) );
597 #ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */
598         /* Use AI_ADDRCONFIG only on systems where its known to be needed. */
599         hints.ai_flags = AI_ADDRCONFIG;
600 #endif
601         hints.ai_family = ldap_int_inet4or6;
602         hints.ai_socktype = socktype;
603         snprintf(serv, sizeof serv, "%d", port );
604
605         /* most getaddrinfo(3) use non-threadsafe resolver libraries */
606         LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
607
608         err = getaddrinfo( host, serv, &hints, &res );
609
610         LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
611
612         if ( err != 0 ) {
613                 osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n",
614                         AC_GAI_STRERROR(err), 0, 0);
615                 return -1;
616         }
617         rc = -1;
618
619         for( sai=res; sai != NULL; sai=sai->ai_next) {
620                 if( sai->ai_addr == NULL ) {
621                         osip_debug(ld, "ldap_connect_to_host: getaddrinfo "
622                                 "ai_addr is NULL?\n", 0, 0, 0);
623                         continue;
624                 }
625
626                 /* we assume AF_x and PF_x are equal for all x */
627                 s = ldap_int_socket( ld, sai->ai_family, socktype );
628                 if ( s == AC_SOCKET_INVALID ) {
629                         continue;
630                 }
631
632                 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) {
633                         ldap_pvt_close_socket(ld, s);
634                         break;
635                 }
636
637                 switch (sai->ai_family) {
638 #ifdef LDAP_PF_INET6
639                         case AF_INET6: {
640                                 char addr[INET6_ADDRSTRLEN];
641                                 inet_ntop( AF_INET6,
642                                         &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
643                                         addr, sizeof addr);
644                                 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 
645                                         addr, serv, 0);
646                         } break;
647 #endif
648                         case AF_INET: {
649                                 char addr[INET_ADDRSTRLEN];
650                                 inet_ntop( AF_INET,
651                                         &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
652                                         addr, sizeof addr);
653                                 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 
654                                         addr, serv, 0);
655                         } break;
656                 }
657
658                 rc = ldap_pvt_connect( ld, s,
659                         sai->ai_addr, sai->ai_addrlen, async );
660                 if ( rc == 0 || rc == -2 ) {
661                         err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr );
662                         if ( err )
663                                 rc = err;
664                         else
665                                 break;
666                 }
667                 ldap_pvt_close_socket(ld, s);
668         }
669         freeaddrinfo(res);
670
671 #else
672         if (! inet_aton( host, &in ) ) {
673                 int local_h_errno;
674                 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
675                         &hp, &local_h_errno );
676
677                 if ( (rc < 0) || (hp == NULL) ) {
678 #ifdef HAVE_WINSOCK
679                         ldap_pvt_set_errno( WSAGetLastError() );
680 #else
681                         /* not exactly right, but... */
682                         ldap_pvt_set_errno( EHOSTUNREACH );
683 #endif
684                         if (ha_buf) LDAP_FREE(ha_buf);
685                         return -1;
686                 }
687
688                 use_hp = 1;
689         }
690
691         rc = s = -1;
692         for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
693                 struct sockaddr_in      sin;
694
695                 s = ldap_int_socket( ld, PF_INET, socktype );
696                 if ( s == AC_SOCKET_INVALID ) {
697                         /* use_hp ? continue : break; */
698                         break;
699                 }
700            
701                 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) {
702                         ldap_pvt_close_socket(ld, s);
703                         break;
704                 }
705
706                 (void)memset((char *)&sin, '\0', sizeof sin);
707                 sin.sin_family = AF_INET;
708                 sin.sin_port = htons((unsigned short) port);
709
710                 if( use_hp ) {
711                         AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i],
712                                 sizeof(sin.sin_addr) );
713                 } else {
714                         AC_MEMCPY( &sin.sin_addr, &in.s_addr,
715                                 sizeof(sin.sin_addr) );
716                 }
717
718 #ifdef HAVE_INET_NTOA_B
719                 {
720                         /* for VxWorks */
721                         char address[INET_ADDR_LEN];
722                         inet_ntoa_b(sin.sin_address, address);
723                         osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
724                                 address, port, 0);
725                 }
726 #else
727                 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
728                         inet_ntoa(sin.sin_addr), port, 0);
729 #endif
730
731                 rc = ldap_pvt_connect(ld, s,
732                         (struct sockaddr *)&sin, sizeof(sin),
733                         async);
734    
735                 if ( (rc == 0) || (rc == -2) ) {
736                         int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin );
737                         if ( err )
738                                 rc = err;
739                         else
740                                 break;
741                 }
742
743                 ldap_pvt_close_socket(ld, s);
744
745                 if (!use_hp) break;
746         }
747         if (ha_buf) LDAP_FREE(ha_buf);
748 #endif
749
750         return rc;
751 }
752
753 #if defined( HAVE_CYRUS_SASL )
754 char *
755 ldap_host_connected_to( Sockbuf *sb, const char *host )
756 {
757         ber_socklen_t   len;
758 #ifdef LDAP_PF_INET6
759         struct sockaddr_storage sabuf;
760 #else
761         struct sockaddr sabuf;
762 #endif
763         struct sockaddr *sa = (struct sockaddr *) &sabuf;
764         ber_socket_t    sd;
765
766         (void)memset( (char *)sa, '\0', sizeof sabuf );
767         len = sizeof sabuf;
768
769         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
770         if ( getpeername( sd, sa, &len ) == -1 ) {
771                 return( NULL );
772         }
773
774         /*
775          * do a reverse lookup on the addr to get the official hostname.
776          * this is necessary for kerberos to work right, since the official
777          * hostname is used as the kerberos instance.
778          */
779
780         switch (sa->sa_family) {
781 #ifdef LDAP_PF_LOCAL
782         case AF_LOCAL:
783                 return LDAP_STRDUP( ldap_int_hostname );
784 #endif
785 #ifdef LDAP_PF_INET6
786         case AF_INET6:
787                 {
788                         struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT;
789                         if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr,
790                                 &localhost, sizeof(localhost)) == 0 )
791                         {
792                                 return LDAP_STRDUP( ldap_int_hostname );
793                         }
794                 }
795                 break;
796 #endif
797         case AF_INET:
798                 {
799                         struct in_addr localhost;
800                         localhost.s_addr = htonl( INADDR_ANY );
801
802                         if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
803                                 &localhost, sizeof(localhost) ) == 0 )
804                         {
805                                 return LDAP_STRDUP( ldap_int_hostname );
806                         }
807
808 #ifdef INADDR_LOOPBACK
809                         localhost.s_addr = htonl( INADDR_LOOPBACK );
810
811                         if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
812                                 &localhost, sizeof(localhost) ) == 0 )
813                         {
814                                 return LDAP_STRDUP( ldap_int_hostname );
815                         }
816 #endif
817                 }
818                 break;
819
820         default:
821                 return( NULL );
822                 break;
823         }
824
825         {
826                 char *herr;
827 #ifdef NI_MAXHOST
828                 char hbuf[NI_MAXHOST];
829 #elif defined( MAXHOSTNAMELEN )
830                 char hbuf[MAXHOSTNAMELEN];
831 #else
832                 char hbuf[256];
833 #endif
834                 hbuf[0] = 0;
835
836                 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0
837                         && hbuf[0] ) 
838                 {
839                         return LDAP_STRDUP( hbuf );   
840                 }
841         }
842
843         return host ? LDAP_STRDUP( host ) : NULL;
844 }
845 #endif
846
847
848 struct selectinfo {
849 #ifdef HAVE_POLL
850         /* for UNIX poll(2) */
851         int si_maxfd;
852         struct pollfd si_fds[FD_SETSIZE];
853 #else
854         /* for UNIX select(2) */
855         fd_set  si_readfds;
856         fd_set  si_writefds;
857         fd_set  si_use_readfds;
858         fd_set  si_use_writefds;
859 #endif
860 };
861
862 void
863 ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
864 {
865         struct selectinfo       *sip;
866         ber_socket_t            sd;
867
868         sip = (struct selectinfo *)ld->ld_selectinfo;
869         
870         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
871
872 #ifdef HAVE_POLL
873         /* for UNIX poll(2) */
874         {
875                 int empty=-1;
876                 int i;
877                 for(i=0; i < sip->si_maxfd; i++) {
878                         if( sip->si_fds[i].fd == sd ) {
879                                 sip->si_fds[i].events |= POLL_WRITE;
880                                 return;
881                         }
882                         if( empty==-1 && sip->si_fds[i].fd == -1 ) {
883                                 empty=i;
884                         }
885                 }
886
887                 if( empty == -1 ) {
888                         if( sip->si_maxfd >= FD_SETSIZE ) {
889                                 /* FIXME */
890                                 return;
891                         }
892                         empty = sip->si_maxfd++;
893                 }
894
895                 sip->si_fds[empty].fd = sd;
896                 sip->si_fds[empty].events = POLL_WRITE;
897         }
898 #else
899         /* for UNIX select(2) */
900         if ( !FD_ISSET( sd, &sip->si_writefds )) {
901                 FD_SET( sd, &sip->si_writefds );
902         }
903 #endif
904 }
905
906
907 void
908 ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
909 {
910         struct selectinfo       *sip;
911         ber_socket_t            sd;
912
913         sip = (struct selectinfo *)ld->ld_selectinfo;
914
915         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
916
917 #ifdef HAVE_POLL
918         /* for UNIX poll(2) */
919         {
920                 int empty=-1;
921                 int i;
922                 for(i=0; i < sip->si_maxfd; i++) {
923                         if( sip->si_fds[i].fd == sd ) {
924                                 sip->si_fds[i].events |= POLL_READ;
925                                 return;
926                         }
927                         if( empty==-1 && sip->si_fds[i].fd == -1 ) {
928                                 empty=i;
929                         }
930                 }
931
932                 if( empty == -1 ) {
933                         if( sip->si_maxfd >= FD_SETSIZE ) {
934                                 /* FIXME */
935                                 return;
936                         }
937                         empty = sip->si_maxfd++;
938                 }
939
940                 sip->si_fds[empty].fd = sd;
941                 sip->si_fds[empty].events = POLL_READ;
942         }
943 #else
944         /* for UNIX select(2) */
945         if ( !FD_ISSET( sd, &sip->si_readfds )) {
946                 FD_SET( sd, &sip->si_readfds );
947         }
948 #endif
949 }
950
951
952 void
953 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
954 {
955         struct selectinfo       *sip;
956         ber_socket_t            sd;
957
958         sip = (struct selectinfo *)ld->ld_selectinfo;
959
960         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
961
962 #ifdef HAVE_POLL
963         /* for UNIX poll(2) */
964         {
965                 int i;
966                 for(i=0; i < sip->si_maxfd; i++) {
967                         if( sip->si_fds[i].fd == sd ) {
968                                 sip->si_fds[i].fd = -1;
969                         }
970                 }
971         }
972 #else
973         /* for UNIX select(2) */
974         FD_CLR( sd, &sip->si_writefds );
975         FD_CLR( sd, &sip->si_readfds );
976 #endif
977 }
978
979 void
980 ldap_clear_select_write( LDAP *ld, Sockbuf *sb )
981 {
982         struct selectinfo       *sip;
983         ber_socket_t            sd;
984
985         sip = (struct selectinfo *)ld->ld_selectinfo;
986
987         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
988
989 #ifdef HAVE_POLL
990         /* for UNIX poll(2) */
991         {
992                 int i;
993                 for(i=0; i < sip->si_maxfd; i++) {
994                         if( sip->si_fds[i].fd == sd ) {
995                                 sip->si_fds[i].events &= ~POLL_WRITE;
996                         }
997                 }
998         }
999 #else
1000         /* for UNIX select(2) */
1001         FD_CLR( sd, &sip->si_writefds );
1002 #endif
1003 }
1004
1005
1006 int
1007 ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
1008 {
1009         struct selectinfo       *sip;
1010         ber_socket_t            sd;
1011
1012         sip = (struct selectinfo *)ld->ld_selectinfo;
1013
1014         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
1015
1016 #ifdef HAVE_POLL
1017         /* for UNIX poll(2) */
1018         {
1019                 int i;
1020                 for(i=0; i < sip->si_maxfd; i++) {
1021                         if( sip->si_fds[i].fd == sd ) {
1022                                 return sip->si_fds[i].revents & POLL_WRITE;
1023                         }
1024                 }
1025
1026                 return 0;
1027         }
1028 #else
1029         /* for UNIX select(2) */
1030         return( FD_ISSET( sd, &sip->si_use_writefds ));
1031 #endif
1032 }
1033
1034
1035 int
1036 ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
1037 {
1038         struct selectinfo       *sip;
1039         ber_socket_t            sd;
1040
1041         sip = (struct selectinfo *)ld->ld_selectinfo;
1042
1043         if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ))
1044                 return 1;
1045
1046         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
1047
1048 #ifdef HAVE_POLL
1049         /* for UNIX poll(2) */
1050         {
1051                 int i;
1052                 for(i=0; i < sip->si_maxfd; i++) {
1053                         if( sip->si_fds[i].fd == sd ) {
1054                                 return sip->si_fds[i].revents & POLL_READ;
1055                         }
1056                 }
1057
1058                 return 0;
1059         }
1060 #else
1061         /* for UNIX select(2) */
1062         return( FD_ISSET( sd, &sip->si_use_readfds ));
1063 #endif
1064 }
1065
1066
1067 void *
1068 ldap_new_select_info( void )
1069 {
1070         struct selectinfo       *sip;
1071
1072         sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo ));
1073
1074         if ( sip == NULL ) return NULL;
1075
1076 #ifdef HAVE_POLL
1077         /* for UNIX poll(2) */
1078         /* sip->si_maxfd=0 */
1079 #else
1080         /* for UNIX select(2) */
1081         FD_ZERO( &sip->si_readfds );
1082         FD_ZERO( &sip->si_writefds );
1083 #endif
1084
1085         return( (void *)sip );
1086 }
1087
1088
1089 void
1090 ldap_free_select_info( void *sip )
1091 {
1092         LDAP_FREE( sip );
1093 }
1094
1095
1096 #ifndef HAVE_POLL
1097 int ldap_int_tblsize = 0;
1098
1099 void
1100 ldap_int_ip_init( void )
1101 {
1102 #if defined( HAVE_SYSCONF )
1103         long tblsize = sysconf( _SC_OPEN_MAX );
1104         if( tblsize > INT_MAX ) tblsize = INT_MAX;
1105
1106 #elif defined( HAVE_GETDTABLESIZE )
1107         int tblsize = getdtablesize();
1108 #else
1109         int tblsize = FD_SETSIZE;
1110 #endif /* !USE_SYSCONF */
1111
1112 #ifdef FD_SETSIZE
1113         if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE;
1114 #endif  /* FD_SETSIZE */
1115
1116         ldap_int_tblsize = tblsize;
1117 }
1118 #endif
1119
1120
1121 int
1122 ldap_int_select( LDAP *ld, struct timeval *timeout )
1123 {
1124         int rc;
1125         struct selectinfo       *sip;
1126
1127         Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 );
1128
1129 #ifndef HAVE_POLL
1130         if ( ldap_int_tblsize == 0 ) ldap_int_ip_init();
1131 #endif
1132
1133         sip = (struct selectinfo *)ld->ld_selectinfo;
1134         assert( sip != NULL );
1135
1136 #ifdef HAVE_POLL
1137         {
1138                 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM;
1139                 rc = poll( sip->si_fds, sip->si_maxfd, to );
1140         }
1141 #else
1142         sip->si_use_readfds = sip->si_readfds;
1143         sip->si_use_writefds = sip->si_writefds;
1144         
1145         rc = select( ldap_int_tblsize,
1146                 &sip->si_use_readfds, &sip->si_use_writefds,
1147                 NULL, timeout );
1148 #endif
1149
1150         return rc;
1151 }