]> git.sur5r.net Git - openldap/blob - libraries/libldap/os-ip.c
Merge remote-tracking branch 'origin/mdb.master'
[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-2012 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_memalloc(sizeof(struct sockaddr));
426                 AC_MEMCPY(ld->ld_options.ldo_peer,sin,sizeof(struct sockaddr));
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         if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
442                 if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
443                         return ( -1 );
444                 return ( 0 );
445         }
446
447         err = sock_errno();
448         if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
449                 return ( -1 );
450         }
451         
452         if ( async ) {
453                 /* caller will call ldap_int_poll() as appropriate? */
454                 return ( -2 );
455         }
456
457         rc = ldap_int_poll( ld, s, opt_tv, 1 );
458
459         osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);
460
461         return rc;
462 }
463
464 #ifndef HAVE_INET_ATON
465 int
466 ldap_pvt_inet_aton( const char *host, struct in_addr *in)
467 {
468         unsigned long u = inet_addr( host );
469
470 #ifdef INADDR_NONE
471         if ( u == INADDR_NONE ) return 0;
472 #endif
473         if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0;
474
475         in->s_addr = u;
476         return 1;
477 }
478 #endif
479
480 int
481 ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, LDAPURLDesc *srv, struct sockaddr *addr)
482 {
483         struct ldapoptions *lo;
484         ldaplist *ll;
485         ldap_conncb *cb;
486         int rc;
487
488         ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s );
489
490         /* Invoke all handle-specific callbacks first */
491         lo = &ld->ld_options;
492         for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
493                 cb = ll->ll_data;
494                 rc = cb->lc_add( ld, sb, srv, addr, cb );
495                 /* on any failure, call the teardown functions for anything
496                  * that previously succeeded
497                  */
498                 if ( rc ) {
499                         ldaplist *l2;
500                         for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
501                                 cb = l2->ll_data;
502                                 cb->lc_del( ld, sb, cb );
503                         }
504                         /* a failure might have implicitly closed the fd */
505                         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
506                         return rc;
507                 }
508         }
509         lo = LDAP_INT_GLOBAL_OPT();
510         for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) {
511                 cb = ll->ll_data;
512                 rc = cb->lc_add( ld, sb, srv, addr, cb );
513                 if ( rc ) {
514                         ldaplist *l2;
515                         for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) {
516                                 cb = l2->ll_data;
517                                 cb->lc_del( ld, sb, cb );
518                         }
519                         lo = &ld->ld_options;
520                         for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) {
521                                 cb = l2->ll_data;
522                                 cb->lc_del( ld, sb, cb );
523                         }
524                         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s );
525                         return rc;
526                 }
527         }
528         return 0;
529 }
530
531 int
532 ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
533         int proto, LDAPURLDesc *srv,
534         int async )
535 {
536         int     rc;
537         int     socktype, port;
538         ber_socket_t            s = AC_SOCKET_INVALID;
539         char *host;
540
541 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
542         char serv[7];
543         int err;
544         struct addrinfo hints, *res, *sai;
545 #else
546         int i;
547         int use_hp = 0;
548         struct hostent *hp = NULL;
549         struct hostent he_buf;
550         struct in_addr in;
551         char *ha_buf=NULL;
552 #endif
553
554         if ( srv->lud_host == NULL || *srv->lud_host == 0 ) {
555                 host = "localhost";
556         } else {
557                 host = srv->lud_host;
558         }
559
560         port = srv->lud_port;
561
562         if( !port ) {
563                 if( strcmp(srv->lud_scheme, "ldaps") == 0 ) {
564                         port = LDAPS_PORT;
565                 } else {
566                         port = LDAP_PORT;
567                 }
568         }
569
570         switch(proto) {
571         case LDAP_PROTO_TCP: socktype = SOCK_STREAM;
572                 osip_debug( ld,
573                         "ldap_connect_to_host: TCP %s:%d\n",
574                         host, port, 0);
575                 break;
576         case LDAP_PROTO_UDP: socktype = SOCK_DGRAM;
577                 osip_debug( ld,
578                         "ldap_connect_to_host: UDP %s:%d\n",
579                         host, port, 0);
580                 break;
581         default:
582                 osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n",
583                         proto, 0, 0 );
584                 return -1;
585         }
586
587 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
588         memset( &hints, '\0', sizeof(hints) );
589 #ifdef USE_AI_ADDRCONFIG /* FIXME: configure test needed */
590         /* Use AI_ADDRCONFIG only on systems where its known to be needed. */
591         hints.ai_flags = AI_ADDRCONFIG;
592 #endif
593         hints.ai_family = ldap_int_inet4or6;
594         hints.ai_socktype = socktype;
595         snprintf(serv, sizeof serv, "%d", port );
596
597         /* most getaddrinfo(3) use non-threadsafe resolver libraries */
598         LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
599
600         err = getaddrinfo( host, serv, &hints, &res );
601
602         LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
603
604         if ( err != 0 ) {
605                 osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n",
606                         AC_GAI_STRERROR(err), 0, 0);
607                 return -1;
608         }
609         rc = -1;
610
611         for( sai=res; sai != NULL; sai=sai->ai_next) {
612                 if( sai->ai_addr == NULL ) {
613                         osip_debug(ld, "ldap_connect_to_host: getaddrinfo "
614                                 "ai_addr is NULL?\n", 0, 0, 0);
615                         continue;
616                 }
617
618                 /* we assume AF_x and PF_x are equal for all x */
619                 s = ldap_int_socket( ld, sai->ai_family, socktype );
620                 if ( s == AC_SOCKET_INVALID ) {
621                         continue;
622                 }
623
624                 if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) {
625                         ldap_pvt_close_socket(ld, s);
626                         break;
627                 }
628
629                 switch (sai->ai_family) {
630 #ifdef LDAP_PF_INET6
631                         case AF_INET6: {
632                                 char addr[INET6_ADDRSTRLEN];
633                                 inet_ntop( AF_INET6,
634                                         &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
635                                         addr, sizeof addr);
636                                 osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 
637                                         addr, serv, 0);
638                         } break;
639 #endif
640                         case AF_INET: {
641                                 char addr[INET_ADDRSTRLEN];
642                                 inet_ntop( AF_INET,
643                                         &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
644                                         addr, sizeof addr);
645                                 osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 
646                                         addr, serv, 0);
647                         } break;
648                 }
649
650                 rc = ldap_pvt_connect( ld, s,
651                         sai->ai_addr, sai->ai_addrlen, async );
652                 if ( rc == 0 || rc == -2 ) {
653                         err = ldap_int_connect_cbs( ld, sb, &s, srv, sai->ai_addr );
654                         if ( err )
655                                 rc = err;
656                         else
657                                 break;
658                 }
659                 ldap_pvt_close_socket(ld, s);
660         }
661         freeaddrinfo(res);
662
663 #else
664         if (! inet_aton( host, &in ) ) {
665                 int local_h_errno;
666                 rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
667                         &hp, &local_h_errno );
668
669                 if ( (rc < 0) || (hp == NULL) ) {
670 #ifdef HAVE_WINSOCK
671                         ldap_pvt_set_errno( WSAGetLastError() );
672 #else
673                         /* not exactly right, but... */
674                         ldap_pvt_set_errno( EHOSTUNREACH );
675 #endif
676                         if (ha_buf) LDAP_FREE(ha_buf);
677                         return -1;
678                 }
679
680                 use_hp = 1;
681         }
682
683         rc = s = -1;
684         for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
685                 struct sockaddr_in      sin;
686
687                 s = ldap_int_socket( ld, PF_INET, socktype );
688                 if ( s == AC_SOCKET_INVALID ) {
689                         /* use_hp ? continue : break; */
690                         break;
691                 }
692            
693                 if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) {
694                         ldap_pvt_close_socket(ld, s);
695                         break;
696                 }
697
698                 (void)memset((char *)&sin, '\0', sizeof sin);
699                 sin.sin_family = AF_INET;
700                 sin.sin_port = htons((unsigned short) port);
701
702                 if( use_hp ) {
703                         AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i],
704                                 sizeof(sin.sin_addr) );
705                 } else {
706                         AC_MEMCPY( &sin.sin_addr, &in.s_addr,
707                                 sizeof(sin.sin_addr) );
708                 }
709
710 #ifdef HAVE_INET_NTOA_B
711                 {
712                         /* for VxWorks */
713                         char address[INET_ADDR_LEN];
714                         inet_ntoa_b(sin.sin_address, address);
715                         osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
716                                 address, port, 0);
717                 }
718 #else
719                 osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
720                         inet_ntoa(sin.sin_addr), port, 0);
721 #endif
722
723                 rc = ldap_pvt_connect(ld, s,
724                         (struct sockaddr *)&sin, sizeof(sin),
725                         async);
726    
727                 if ( (rc == 0) || (rc == -2) ) {
728                         int err = ldap_int_connect_cbs( ld, sb, &s, srv, (struct sockaddr *)&sin );
729                         if ( err )
730                                 rc = err;
731                         else
732                                 break;
733                 }
734
735                 ldap_pvt_close_socket(ld, s);
736
737                 if (!use_hp) break;
738         }
739         if (ha_buf) LDAP_FREE(ha_buf);
740 #endif
741
742         return rc;
743 }
744
745 #if defined( HAVE_CYRUS_SASL )
746 char *
747 ldap_host_connected_to( Sockbuf *sb, const char *host )
748 {
749         ber_socklen_t   len;
750 #ifdef LDAP_PF_INET6
751         struct sockaddr_storage sabuf;
752 #else
753         struct sockaddr sabuf;
754 #endif
755         struct sockaddr *sa = (struct sockaddr *) &sabuf;
756         ber_socket_t    sd;
757
758         (void)memset( (char *)sa, '\0', sizeof sabuf );
759         len = sizeof sabuf;
760
761         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
762         if ( getpeername( sd, sa, &len ) == -1 ) {
763                 return( NULL );
764         }
765
766         /*
767          * do a reverse lookup on the addr to get the official hostname.
768          * this is necessary for kerberos to work right, since the official
769          * hostname is used as the kerberos instance.
770          */
771
772         switch (sa->sa_family) {
773 #ifdef LDAP_PF_LOCAL
774         case AF_LOCAL:
775                 return LDAP_STRDUP( ldap_int_hostname );
776 #endif
777 #ifdef LDAP_PF_INET6
778         case AF_INET6:
779                 {
780                         struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT;
781                         if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr,
782                                 &localhost, sizeof(localhost)) == 0 )
783                         {
784                                 return LDAP_STRDUP( ldap_int_hostname );
785                         }
786                 }
787                 break;
788 #endif
789         case AF_INET:
790                 {
791                         struct in_addr localhost;
792                         localhost.s_addr = htonl( INADDR_ANY );
793
794                         if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
795                                 &localhost, sizeof(localhost) ) == 0 )
796                         {
797                                 return LDAP_STRDUP( ldap_int_hostname );
798                         }
799
800 #ifdef INADDR_LOOPBACK
801                         localhost.s_addr = htonl( INADDR_LOOPBACK );
802
803                         if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
804                                 &localhost, sizeof(localhost) ) == 0 )
805                         {
806                                 return LDAP_STRDUP( ldap_int_hostname );
807                         }
808 #endif
809                 }
810                 break;
811
812         default:
813                 return( NULL );
814                 break;
815         }
816
817         {
818                 char *herr;
819 #ifdef NI_MAXHOST
820                 char hbuf[NI_MAXHOST];
821 #elif defined( MAXHOSTNAMELEN )
822                 char hbuf[MAXHOSTNAMELEN];
823 #else
824                 char hbuf[256];
825 #endif
826                 hbuf[0] = 0;
827
828                 if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0
829                         && hbuf[0] ) 
830                 {
831                         return LDAP_STRDUP( hbuf );   
832                 }
833         }
834
835         return host ? LDAP_STRDUP( host ) : NULL;
836 }
837 #endif
838
839
840 struct selectinfo {
841 #ifdef HAVE_POLL
842         /* for UNIX poll(2) */
843         int si_maxfd;
844         struct pollfd si_fds[FD_SETSIZE];
845 #else
846         /* for UNIX select(2) */
847         fd_set  si_readfds;
848         fd_set  si_writefds;
849         fd_set  si_use_readfds;
850         fd_set  si_use_writefds;
851 #endif
852 };
853
854 void
855 ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
856 {
857         struct selectinfo       *sip;
858         ber_socket_t            sd;
859
860         sip = (struct selectinfo *)ld->ld_selectinfo;
861         
862         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
863
864 #ifdef HAVE_POLL
865         /* for UNIX poll(2) */
866         {
867                 int empty=-1;
868                 int i;
869                 for(i=0; i < sip->si_maxfd; i++) {
870                         if( sip->si_fds[i].fd == sd ) {
871                                 sip->si_fds[i].events |= POLL_WRITE;
872                                 return;
873                         }
874                         if( empty==-1 && sip->si_fds[i].fd == -1 ) {
875                                 empty=i;
876                         }
877                 }
878
879                 if( empty == -1 ) {
880                         if( sip->si_maxfd >= FD_SETSIZE ) {
881                                 /* FIXME */
882                                 return;
883                         }
884                         empty = sip->si_maxfd++;
885                 }
886
887                 sip->si_fds[empty].fd = sd;
888                 sip->si_fds[empty].events = POLL_WRITE;
889         }
890 #else
891         /* for UNIX select(2) */
892         if ( !FD_ISSET( sd, &sip->si_writefds )) {
893                 FD_SET( sd, &sip->si_writefds );
894         }
895 #endif
896 }
897
898
899 void
900 ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
901 {
902         struct selectinfo       *sip;
903         ber_socket_t            sd;
904
905         sip = (struct selectinfo *)ld->ld_selectinfo;
906
907         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
908
909 #ifdef HAVE_POLL
910         /* for UNIX poll(2) */
911         {
912                 int empty=-1;
913                 int i;
914                 for(i=0; i < sip->si_maxfd; i++) {
915                         if( sip->si_fds[i].fd == sd ) {
916                                 sip->si_fds[i].events |= POLL_READ;
917                                 return;
918                         }
919                         if( empty==-1 && sip->si_fds[i].fd == -1 ) {
920                                 empty=i;
921                         }
922                 }
923
924                 if( empty == -1 ) {
925                         if( sip->si_maxfd >= FD_SETSIZE ) {
926                                 /* FIXME */
927                                 return;
928                         }
929                         empty = sip->si_maxfd++;
930                 }
931
932                 sip->si_fds[empty].fd = sd;
933                 sip->si_fds[empty].events = POLL_READ;
934         }
935 #else
936         /* for UNIX select(2) */
937         if ( !FD_ISSET( sd, &sip->si_readfds )) {
938                 FD_SET( sd, &sip->si_readfds );
939         }
940 #endif
941 }
942
943
944 void
945 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
946 {
947         struct selectinfo       *sip;
948         ber_socket_t            sd;
949
950         sip = (struct selectinfo *)ld->ld_selectinfo;
951
952         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
953
954 #ifdef HAVE_POLL
955         /* for UNIX poll(2) */
956         {
957                 int i;
958                 for(i=0; i < sip->si_maxfd; i++) {
959                         if( sip->si_fds[i].fd == sd ) {
960                                 sip->si_fds[i].fd = -1;
961                         }
962                 }
963         }
964 #else
965         /* for UNIX select(2) */
966         FD_CLR( sd, &sip->si_writefds );
967         FD_CLR( sd, &sip->si_readfds );
968 #endif
969 }
970
971 void
972 ldap_clear_select_write( LDAP *ld, Sockbuf *sb )
973 {
974         struct selectinfo       *sip;
975         ber_socket_t            sd;
976
977         sip = (struct selectinfo *)ld->ld_selectinfo;
978
979         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
980
981 #ifdef HAVE_POLL
982         /* for UNIX poll(2) */
983         {
984                 int i;
985                 for(i=0; i < sip->si_maxfd; i++) {
986                         if( sip->si_fds[i].fd == sd ) {
987                                 sip->si_fds[i].events &= ~POLL_WRITE;
988                         }
989                 }
990         }
991 #else
992         /* for UNIX select(2) */
993         FD_CLR( sd, &sip->si_writefds );
994 #endif
995 }
996
997
998 int
999 ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
1000 {
1001         struct selectinfo       *sip;
1002         ber_socket_t            sd;
1003
1004         sip = (struct selectinfo *)ld->ld_selectinfo;
1005
1006         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
1007
1008 #ifdef HAVE_POLL
1009         /* for UNIX poll(2) */
1010         {
1011                 int i;
1012                 for(i=0; i < sip->si_maxfd; i++) {
1013                         if( sip->si_fds[i].fd == sd ) {
1014                                 return sip->si_fds[i].revents & POLL_WRITE;
1015                         }
1016                 }
1017
1018                 return 0;
1019         }
1020 #else
1021         /* for UNIX select(2) */
1022         return( FD_ISSET( sd, &sip->si_use_writefds ));
1023 #endif
1024 }
1025
1026
1027 int
1028 ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
1029 {
1030         struct selectinfo       *sip;
1031         ber_socket_t            sd;
1032
1033         sip = (struct selectinfo *)ld->ld_selectinfo;
1034
1035         if (ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ))
1036                 return 1;
1037
1038         ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
1039
1040 #ifdef HAVE_POLL
1041         /* for UNIX poll(2) */
1042         {
1043                 int i;
1044                 for(i=0; i < sip->si_maxfd; i++) {
1045                         if( sip->si_fds[i].fd == sd ) {
1046                                 return sip->si_fds[i].revents & POLL_READ;
1047                         }
1048                 }
1049
1050                 return 0;
1051         }
1052 #else
1053         /* for UNIX select(2) */
1054         return( FD_ISSET( sd, &sip->si_use_readfds ));
1055 #endif
1056 }
1057
1058
1059 void *
1060 ldap_new_select_info( void )
1061 {
1062         struct selectinfo       *sip;
1063
1064         sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo ));
1065
1066         if ( sip == NULL ) return NULL;
1067
1068 #ifdef HAVE_POLL
1069         /* for UNIX poll(2) */
1070         /* sip->si_maxfd=0 */
1071 #else
1072         /* for UNIX select(2) */
1073         FD_ZERO( &sip->si_readfds );
1074         FD_ZERO( &sip->si_writefds );
1075 #endif
1076
1077         return( (void *)sip );
1078 }
1079
1080
1081 void
1082 ldap_free_select_info( void *sip )
1083 {
1084         LDAP_FREE( sip );
1085 }
1086
1087
1088 #ifndef HAVE_POLL
1089 int ldap_int_tblsize = 0;
1090
1091 void
1092 ldap_int_ip_init( void )
1093 {
1094 #if defined( HAVE_SYSCONF )
1095         long tblsize = sysconf( _SC_OPEN_MAX );
1096         if( tblsize > INT_MAX ) tblsize = INT_MAX;
1097
1098 #elif defined( HAVE_GETDTABLESIZE )
1099         int tblsize = getdtablesize();
1100 #else
1101         int tblsize = FD_SETSIZE;
1102 #endif /* !USE_SYSCONF */
1103
1104 #ifdef FD_SETSIZE
1105         if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE;
1106 #endif  /* FD_SETSIZE */
1107
1108         ldap_int_tblsize = tblsize;
1109 }
1110 #endif
1111
1112
1113 int
1114 ldap_int_select( LDAP *ld, struct timeval *timeout )
1115 {
1116         int rc;
1117         struct selectinfo       *sip;
1118
1119         Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 );
1120
1121 #ifndef HAVE_POLL
1122         if ( ldap_int_tblsize == 0 ) ldap_int_ip_init();
1123 #endif
1124
1125         sip = (struct selectinfo *)ld->ld_selectinfo;
1126         assert( sip != NULL );
1127
1128 #ifdef HAVE_POLL
1129         {
1130                 int to = timeout ? TV2MILLISEC( timeout ) : INFTIM;
1131                 rc = poll( sip->si_fds, sip->si_maxfd, to );
1132         }
1133 #else
1134         sip->si_use_readfds = sip->si_readfds;
1135         sip->si_use_writefds = sip->si_writefds;
1136         
1137         rc = select( ldap_int_tblsize,
1138                 &sip->si_use_readfds, &sip->si_use_writefds,
1139                 NULL, timeout );
1140 #endif
1141
1142         return rc;
1143 }