~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to libraries/libldap/os-ip.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/>.
 
4
 *
 
5
 * Copyright 1998-2008 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
#endif /* SO_KEEPALIVE */
 
146
#ifdef TCP_NODELAY
 
147
                if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
 
148
                        (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR )
 
149
                {
 
150
                        osip_debug( ld, "ldap_prepare_socket: "
 
151
                                "setsockopt(%d, TCP_NODELAY) failed (ignored).\n",
 
152
                                s, 0, 0 );
 
153
                }
 
154
#endif /* TCP_NODELAY */
 
155
        }
 
156
#endif /* SO_KEEPALIVE || TCP_NODELAY */
 
157
 
 
158
        return 0;
 
159
}
 
160
 
 
161
#ifndef HAVE_WINSOCK
 
162
 
 
163
#undef TRACE
 
164
#define TRACE do { \
 
165
        osip_debug(ld, \
 
166
                "ldap_is_socket_ready: error on socket %d: errno: %d (%s)\n", \
 
167
                s, \
 
168
                errno, \
 
169
                sock_errstr(errno) ); \
 
170
} while( 0 )
 
171
 
 
172
/*
 
173
 * check the socket for errors after select returned.
 
174
 */
 
175
static int
 
176
ldap_pvt_is_socket_ready(LDAP *ld, int s)
 
177
{
 
178
        osip_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0);
 
179
 
 
180
#if defined( notyet ) /* && defined( SO_ERROR ) */
 
181
{
 
182
        int so_errno;
 
183
        ber_socklen_t dummy = sizeof(so_errno);
 
184
        if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy )
 
185
                == AC_SOCKET_ERROR )
 
186
        {
 
187
                return -1;
 
188
        }
 
189
        if ( so_errno ) {
 
190
                ldap_pvt_set_errno(so_errno);
 
191
                TRACE;
 
192
                return -1;
 
193
        }
 
194
        return 0;
 
195
}
 
196
#else
 
197
{
 
198
        /* error slippery */
 
199
#ifdef LDAP_PF_INET6
 
200
        struct sockaddr_storage sin;
 
201
#else
 
202
        struct sockaddr_in sin;
 
203
#endif
 
204
        char ch;
 
205
        ber_socklen_t dummy = sizeof(sin);
 
206
        if ( getpeername( s, (struct sockaddr *) &sin, &dummy )
 
207
                == AC_SOCKET_ERROR )
 
208
        {
 
209
                /* XXX: needs to be replace with ber_stream_read() */
 
210
                read(s, &ch, 1);
 
211
                TRACE;
 
212
                return -1;
 
213
        }
 
214
        return 0;
 
215
}
 
216
#endif
 
217
        return -1;
 
218
}
 
219
#undef TRACE
 
220
 
 
221
#endif /* HAVE_WINSOCK */
 
222
 
 
223
/* NOTE: this is identical to analogous code in os-local.c */
 
224
int
 
225
ldap_int_poll(
 
226
        LDAP *ld,
 
227
        ber_socket_t s,
 
228
        struct timeval *tvp )
 
229
{
 
230
        int             rc;
 
231
                
 
232
 
 
233
        osip_debug(ld, "ldap_int_poll: fd: %d tm: %ld\n",
 
234
                s, tvp ? tvp->tv_sec : -1L, 0);
 
235
 
 
236
#ifdef HAVE_POLL
 
237
        {
 
238
                struct pollfd fd;
 
239
                int timeout = INFTIM;
 
240
 
 
241
                fd.fd = s;
 
242
                fd.events = POLL_WRITE;
 
243
 
 
244
                if ( tvp != NULL ) {
 
245
                        timeout = TV2MILLISEC( tvp );
 
246
                }
 
247
                do {
 
248
                        fd.revents = 0;
 
249
                        rc = poll( &fd, 1, timeout );
 
250
                
 
251
                } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
 
252
                        LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
 
253
 
 
254
                if ( rc == AC_SOCKET_ERROR ) {
 
255
                        return rc;
 
256
                }
 
257
 
 
258
                if ( timeout == 0 && rc == 0 ) {
 
259
                        return -2;
 
260
                }
 
261
 
 
262
                if ( fd.revents & POLL_WRITE ) {
 
263
                        if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
 
264
                                return -1;
 
265
                        }
 
266
 
 
267
                        if ( ldap_pvt_ndelay_off( ld, s ) == -1 ) {
 
268
                                return -1;
 
269
                        }
 
270
                        return 0;
 
271
                }
 
272
        }
 
273
#else
 
274
        {
 
275
                fd_set          wfds, *z = NULL;
 
276
#ifdef HAVE_WINSOCK
 
277
                fd_set          efds;
 
278
#endif
 
279
                struct timeval  tv = { 0 };
 
280
 
 
281
#if defined( FD_SETSIZE ) && !defined( HAVE_WINSOCK )
 
282
                if ( s >= FD_SETSIZE ) {
 
283
                        rc = AC_SOCKET_ERROR;
 
284
                        tcp_close( s );
 
285
                        ldap_pvt_set_errno( EMFILE );
 
286
                        return rc;
 
287
                }
 
288
#endif
 
289
 
 
290
                if ( tvp != NULL ) {
 
291
                        tv = *tvp;
 
292
                }
 
293
 
 
294
                do {
 
295
                        FD_ZERO(&wfds);
 
296
                        FD_SET(s, &wfds );
 
297
 
 
298
#ifdef HAVE_WINSOCK
 
299
                        FD_ZERO(&efds);
 
300
                        FD_SET(s, &efds );
 
301
#endif
 
302
 
 
303
                        rc = select( ldap_int_tblsize, z, &wfds,
 
304
#ifdef HAVE_WINSOCK
 
305
                                &efds,
 
306
#else
 
307
                                z,
 
308
#endif
 
309
                                tvp ? &tv : NULL );
 
310
                } while ( rc == AC_SOCKET_ERROR && errno == EINTR &&
 
311
                        LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_RESTART ) );
 
312
 
 
313
                if ( rc == AC_SOCKET_ERROR ) {
 
314
                        return rc;
 
315
                }
 
316
 
 
317
                if ( rc == 0 && tvp && tvp->tv_sec == 0 && tvp->tv_usec == 0 ) {
 
318
                        return -2;
 
319
                }
 
320
 
 
321
#ifdef HAVE_WINSOCK
 
322
                /* This means the connection failed */
 
323
                if ( FD_ISSET(s, &efds) ) {
 
324
                        int so_errno;
 
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 )
 
328
                        {
 
329
                                /* impossible */
 
330
                                so_errno = WSAGetLastError();
 
331
                        }
 
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 ));
 
335
                        return -1;
 
336
                }
 
337
#endif
 
338
                if ( FD_ISSET(s, &wfds) ) {
 
339
#ifndef HAVE_WINSOCK
 
340
                        if ( ldap_pvt_is_socket_ready( ld, s ) == -1 ) {
 
341
                                return -1;
 
342
                        }
 
343
#endif
 
344
                        if ( ldap_pvt_ndelay_off(ld, s) == -1 ) {
 
345
                                return -1;
 
346
                        }
 
347
                        return 0;
 
348
                }
 
349
        }
 
350
#endif
 
351
 
 
352
        osip_debug(ld, "ldap_int_poll: timed out\n",0,0,0);
 
353
        ldap_pvt_set_errno( ETIMEDOUT );
 
354
        return -1;
 
355
}
 
356
 
 
357
static int
 
358
ldap_pvt_connect(LDAP *ld, ber_socket_t s,
 
359
        struct sockaddr *sin, ber_socklen_t addrlen,
 
360
        int async)
 
361
{
 
362
        int rc, err;
 
363
        struct timeval  tv, *opt_tv = NULL;
 
364
 
 
365
#ifdef LDAP_CONNECTIONLESS
 
366
        /* We could do a connect() but that would interfere with
 
367
         * attempts to poll a broadcast address
 
368
         */
 
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));
 
374
                return ( 0 );
 
375
        }
 
376
#endif
 
377
        if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
 
378
                tv = ld->ld_options.ldo_tm_net;
 
379
                opt_tv = &tv;
 
380
        }
 
381
 
 
382
        osip_debug(ld, "ldap_pvt_connect: fd: %d tm: %ld async: %d\n",
 
383
                        s, opt_tv ? tv.tv_sec : -1L, async);
 
384
 
 
385
        if ( opt_tv && ldap_pvt_ndelay_on(ld, s) == -1 )
 
386
                return ( -1 );
 
387
 
 
388
        if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) {
 
389
                if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 )
 
390
                        return ( -1 );
 
391
                return ( 0 );
 
392
        }
 
393
 
 
394
        err = sock_errno();
 
395
        if ( err != EINPROGRESS && err != EWOULDBLOCK ) {
 
396
                return ( -1 );
 
397
        }
 
398
        
 
399
        if ( async ) {
 
400
                /* caller will call ldap_int_poll() as appropriate? */
 
401
                return ( -2 );
 
402
        }
 
403
 
 
404
        rc = ldap_int_poll( ld, s, opt_tv );
 
405
 
 
406
        osip_debug(ld, "ldap_pvt_connect: %d\n", rc, 0, 0);
 
407
 
 
408
        return rc;
 
409
}
 
410
 
 
411
#ifndef HAVE_INET_ATON
 
412
int
 
413
ldap_pvt_inet_aton( const char *host, struct in_addr *in)
 
414
{
 
415
        unsigned long u = inet_addr( host );
 
416
 
 
417
#ifdef INADDR_NONE
 
418
        if ( u == INADDR_NONE ) return 0;
 
419
#endif
 
420
        if ( u == 0xffffffffUL || u == (unsigned long) -1L ) return 0;
 
421
 
 
422
        in->s_addr = u;
 
423
        return 1;
 
424
}
 
425
#endif
 
426
 
 
427
 
 
428
int
 
429
ldap_connect_to_host(LDAP *ld, Sockbuf *sb,
 
430
        int proto,
 
431
        const char *host, int port,
 
432
        int async )
 
433
{
 
434
        int     rc;
 
435
        int     socktype;
 
436
        ber_socket_t            s = AC_SOCKET_INVALID;
 
437
 
 
438
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
 
439
        char serv[7];
 
440
        int err;
 
441
        struct addrinfo hints, *res, *sai;
 
442
#else
 
443
        int i;
 
444
        int use_hp = 0;
 
445
        struct hostent *hp = NULL;
 
446
        struct hostent he_buf;
 
447
        struct in_addr in;
 
448
        char *ha_buf=NULL;
 
449
#endif
 
450
 
 
451
        if( host == NULL ) host = "localhost";
 
452
        
 
453
        switch(proto) {
 
454
        case LDAP_PROTO_TCP: socktype = SOCK_STREAM;
 
455
                osip_debug( ld,
 
456
                        "ldap_connect_to_host: TCP %s:%d\n",
 
457
                        host, port, 0);
 
458
                break;
 
459
        case LDAP_PROTO_UDP: socktype = SOCK_DGRAM;
 
460
                osip_debug( ld,
 
461
                        "ldap_connect_to_host: UDP %s:%d\n",
 
462
                        host, port, 0);
 
463
                break;
 
464
        default:
 
465
                osip_debug( ld, "ldap_connect_to_host: unknown proto: %d\n",
 
466
                        proto, 0, 0 );
 
467
                return -1;
 
468
        }
 
469
 
 
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;
 
475
#endif
 
476
        hints.ai_family = ldap_int_inet4or6;
 
477
        hints.ai_socktype = socktype;
 
478
        snprintf(serv, sizeof serv, "%d", port );
 
479
 
 
480
#ifdef LDAP_R_COMPILE
 
481
        /* most getaddrinfo(3) use non-threadsafe resolver libraries */
 
482
        ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
 
483
#endif
 
484
 
 
485
        err = getaddrinfo( host, serv, &hints, &res );
 
486
 
 
487
#ifdef LDAP_R_COMPILE
 
488
        ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
 
489
#endif
 
490
 
 
491
        if ( err != 0 ) {
 
492
                osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n",
 
493
                        AC_GAI_STRERROR(err), 0, 0);
 
494
                return -1;
 
495
        }
 
496
        rc = -1;
 
497
 
 
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);
 
502
                        continue;
 
503
                }
 
504
 
 
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 ) {
 
508
                        continue;
 
509
                }
 
510
 
 
511
                if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) {
 
512
                        ldap_pvt_close_socket(ld, s);
 
513
                        break;
 
514
                }
 
515
 
 
516
                switch (sai->ai_family) {
 
517
#ifdef LDAP_PF_INET6
 
518
                        case AF_INET6: {
 
519
                                char addr[INET6_ADDRSTRLEN];
 
520
                                inet_ntop( AF_INET6,
 
521
                                        &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
 
522
                                        addr, sizeof addr);
 
523
                                osip_debug(ld, "ldap_connect_to_host: Trying %s %s\n", 
 
524
                                        addr, serv, 0);
 
525
                        } break;
 
526
#endif
 
527
                        case AF_INET: {
 
528
                                char addr[INET_ADDRSTRLEN];
 
529
                                inet_ntop( AF_INET,
 
530
                                        &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
 
531
                                        addr, sizeof addr);
 
532
                                osip_debug(ld, "ldap_connect_to_host: Trying %s:%s\n", 
 
533
                                        addr, serv, 0);
 
534
                        } break;
 
535
                }
 
536
 
 
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 );
 
541
                        break;
 
542
                }
 
543
                ldap_pvt_close_socket(ld, s);
 
544
        }
 
545
        freeaddrinfo(res);
 
546
 
 
547
#else
 
548
        if (! inet_aton( host, &in ) ) {
 
549
                int local_h_errno;
 
550
                rc = ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
 
551
                        &hp, &local_h_errno );
 
552
 
 
553
                if ( (rc < 0) || (hp == NULL) ) {
 
554
#ifdef HAVE_WINSOCK
 
555
                        ldap_pvt_set_errno( WSAGetLastError() );
 
556
#else
 
557
                        /* not exactly right, but... */
 
558
                        ldap_pvt_set_errno( EHOSTUNREACH );
 
559
#endif
 
560
                        if (ha_buf) LDAP_FREE(ha_buf);
 
561
                        return -1;
 
562
                }
 
563
 
 
564
                use_hp = 1;
 
565
        }
 
566
 
 
567
        rc = s = -1;
 
568
        for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) {
 
569
                struct sockaddr_in      sin;
 
570
 
 
571
                s = ldap_int_socket( ld, PF_INET, socktype );
 
572
                if ( s == AC_SOCKET_INVALID ) {
 
573
                        /* use_hp ? continue : break; */
 
574
                        break;
 
575
                }
 
576
           
 
577
                if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) {
 
578
                        ldap_pvt_close_socket(ld, s);
 
579
                        break;
 
580
                }
 
581
 
 
582
                (void)memset((char *)&sin, '\0', sizeof sin);
 
583
                sin.sin_family = AF_INET;
 
584
                sin.sin_port = htons((unsigned short) port);
 
585
 
 
586
                if( use_hp ) {
 
587
                        AC_MEMCPY( &sin.sin_addr, hp->h_addr_list[i],
 
588
                                sizeof(sin.sin_addr) );
 
589
                } else {
 
590
                        AC_MEMCPY( &sin.sin_addr, &in.s_addr,
 
591
                                sizeof(sin.sin_addr) );
 
592
                }
 
593
 
 
594
#ifdef HAVE_INET_NTOA_B
 
595
                {
 
596
                        /* for VxWorks */
 
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", 
 
600
                                address, port, 0);
 
601
                }
 
602
#else
 
603
                osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", 
 
604
                        inet_ntoa(sin.sin_addr), port, 0);
 
605
#endif
 
606
 
 
607
                rc = ldap_pvt_connect(ld, s,
 
608
                        (struct sockaddr *)&sin, sizeof(sin),
 
609
                        async);
 
610
   
 
611
                if ( (rc == 0) || (rc == -2) ) {
 
612
                        ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
 
613
                        break;
 
614
                }
 
615
 
 
616
                ldap_pvt_close_socket(ld, s);
 
617
 
 
618
                if (!use_hp) break;
 
619
        }
 
620
        if (ha_buf) LDAP_FREE(ha_buf);
 
621
#endif
 
622
 
 
623
        return rc;
 
624
}
 
625
 
 
626
#if defined( HAVE_CYRUS_SASL )
 
627
char *
 
628
ldap_host_connected_to( Sockbuf *sb, const char *host )
 
629
{
 
630
        ber_socklen_t   len;
 
631
#ifdef LDAP_PF_INET6
 
632
        struct sockaddr_storage sabuf;
 
633
#else
 
634
        struct sockaddr sabuf;
 
635
#endif
 
636
        struct sockaddr *sa = (struct sockaddr *) &sabuf;
 
637
        ber_socket_t    sd;
 
638
 
 
639
        (void)memset( (char *)sa, '\0', sizeof sabuf );
 
640
        len = sizeof sabuf;
 
641
 
 
642
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
643
        if ( getpeername( sd, sa, &len ) == -1 ) {
 
644
                return( NULL );
 
645
        }
 
646
 
 
647
        /*
 
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.
 
651
         */
 
652
 
 
653
        switch (sa->sa_family) {
 
654
#ifdef LDAP_PF_LOCAL
 
655
        case AF_LOCAL:
 
656
                return LDAP_STRDUP( ldap_int_hostname );
 
657
#endif
 
658
#ifdef LDAP_PF_INET6
 
659
        case AF_INET6:
 
660
                {
 
661
                        struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT;
 
662
                        if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr,
 
663
                                &localhost, sizeof(localhost)) == 0 )
 
664
                        {
 
665
                                return LDAP_STRDUP( ldap_int_hostname );
 
666
                        }
 
667
                }
 
668
                break;
 
669
#endif
 
670
        case AF_INET:
 
671
                {
 
672
                        struct in_addr localhost;
 
673
                        localhost.s_addr = htonl( INADDR_ANY );
 
674
 
 
675
                        if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
 
676
                                &localhost, sizeof(localhost) ) == 0 )
 
677
                        {
 
678
                                return LDAP_STRDUP( ldap_int_hostname );
 
679
                        }
 
680
 
 
681
#ifdef INADDR_LOOPBACK
 
682
                        localhost.s_addr = htonl( INADDR_LOOPBACK );
 
683
 
 
684
                        if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr,
 
685
                                &localhost, sizeof(localhost) ) == 0 )
 
686
                        {
 
687
                                return LDAP_STRDUP( ldap_int_hostname );
 
688
                        }
 
689
#endif
 
690
                }
 
691
                break;
 
692
 
 
693
        default:
 
694
                return( NULL );
 
695
                break;
 
696
        }
 
697
 
 
698
        {
 
699
                char *herr;
 
700
#ifdef NI_MAXHOST
 
701
                char hbuf[NI_MAXHOST];
 
702
#elif defined( MAXHOSTNAMELEN
 
703
                char hbuf[MAXHOSTNAMELEN];
 
704
#else
 
705
                char hbuf[256];
 
706
#endif
 
707
                hbuf[0] = 0;
 
708
 
 
709
                if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0
 
710
                        && hbuf[0] ) 
 
711
                {
 
712
                        return LDAP_STRDUP( hbuf );   
 
713
                }
 
714
        }
 
715
 
 
716
        return host ? LDAP_STRDUP( host ) : NULL;
 
717
}
 
718
#endif
 
719
 
 
720
 
 
721
struct selectinfo {
 
722
#ifdef HAVE_POLL
 
723
        /* for UNIX poll(2) */
 
724
        int si_maxfd;
 
725
        struct pollfd si_fds[FD_SETSIZE];
 
726
#else
 
727
        /* for UNIX select(2) */
 
728
        fd_set  si_readfds;
 
729
        fd_set  si_writefds;
 
730
        fd_set  si_use_readfds;
 
731
        fd_set  si_use_writefds;
 
732
#endif
 
733
};
 
734
 
 
735
void
 
736
ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
 
737
{
 
738
        struct selectinfo       *sip;
 
739
        ber_socket_t            sd;
 
740
 
 
741
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
742
        
 
743
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
744
 
 
745
#ifdef HAVE_POLL
 
746
        /* for UNIX poll(2) */
 
747
        {
 
748
                int empty=-1;
 
749
                int i;
 
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;
 
753
                                return;
 
754
                        }
 
755
                        if( empty==-1 && sip->si_fds[i].fd == -1 ) {
 
756
                                empty=i;
 
757
                        }
 
758
                }
 
759
 
 
760
                if( empty == -1 ) {
 
761
                        if( sip->si_maxfd >= FD_SETSIZE ) {
 
762
                                /* FIXME */
 
763
                                return;
 
764
                        }
 
765
                        empty = sip->si_maxfd++;
 
766
                }
 
767
 
 
768
                sip->si_fds[empty].fd = sd;
 
769
                sip->si_fds[empty].events = POLL_WRITE;
 
770
        }
 
771
#else
 
772
        /* for UNIX select(2) */
 
773
        if ( !FD_ISSET( sd, &sip->si_writefds )) {
 
774
                FD_SET( sd, &sip->si_writefds );
 
775
        }
 
776
#endif
 
777
}
 
778
 
 
779
 
 
780
void
 
781
ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
 
782
{
 
783
        struct selectinfo       *sip;
 
784
        ber_socket_t            sd;
 
785
 
 
786
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
787
 
 
788
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
789
 
 
790
#ifdef HAVE_POLL
 
791
        /* for UNIX poll(2) */
 
792
        {
 
793
                int empty=-1;
 
794
                int i;
 
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;
 
798
                                return;
 
799
                        }
 
800
                        if( empty==-1 && sip->si_fds[i].fd == -1 ) {
 
801
                                empty=i;
 
802
                        }
 
803
                }
 
804
 
 
805
                if( empty == -1 ) {
 
806
                        if( sip->si_maxfd >= FD_SETSIZE ) {
 
807
                                /* FIXME */
 
808
                                return;
 
809
                        }
 
810
                        empty = sip->si_maxfd++;
 
811
                }
 
812
 
 
813
                sip->si_fds[empty].fd = sd;
 
814
                sip->si_fds[empty].events = POLL_READ;
 
815
        }
 
816
#else
 
817
        /* for UNIX select(2) */
 
818
        if ( !FD_ISSET( sd, &sip->si_readfds )) {
 
819
                FD_SET( sd, &sip->si_readfds );
 
820
        }
 
821
#endif
 
822
}
 
823
 
 
824
 
 
825
void
 
826
ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
 
827
{
 
828
        struct selectinfo       *sip;
 
829
        ber_socket_t            sd;
 
830
 
 
831
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
832
 
 
833
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
834
 
 
835
#ifdef HAVE_POLL
 
836
        /* for UNIX poll(2) */
 
837
        {
 
838
                int i;
 
839
                for(i=0; i < sip->si_maxfd; i++) {
 
840
                        if( sip->si_fds[i].fd == sd ) {
 
841
                                sip->si_fds[i].fd = -1;
 
842
                        }
 
843
                }
 
844
        }
 
845
#else
 
846
        /* for UNIX select(2) */
 
847
        FD_CLR( sd, &sip->si_writefds );
 
848
        FD_CLR( sd, &sip->si_readfds );
 
849
#endif
 
850
}
 
851
 
 
852
 
 
853
int
 
854
ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
 
855
{
 
856
        struct selectinfo       *sip;
 
857
        ber_socket_t            sd;
 
858
 
 
859
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
860
 
 
861
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
862
 
 
863
#ifdef HAVE_POLL
 
864
        /* for UNIX poll(2) */
 
865
        {
 
866
                int i;
 
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;
 
870
                        }
 
871
                }
 
872
 
 
873
                return 0;
 
874
        }
 
875
#else
 
876
        /* for UNIX select(2) */
 
877
        return( FD_ISSET( sd, &sip->si_use_writefds ));
 
878
#endif
 
879
}
 
880
 
 
881
 
 
882
int
 
883
ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
 
884
{
 
885
        struct selectinfo       *sip;
 
886
        ber_socket_t            sd;
 
887
 
 
888
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
889
 
 
890
        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
 
891
 
 
892
#ifdef HAVE_POLL
 
893
        /* for UNIX poll(2) */
 
894
        {
 
895
                int i;
 
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;
 
899
                        }
 
900
                }
 
901
 
 
902
                return 0;
 
903
        }
 
904
#else
 
905
        /* for UNIX select(2) */
 
906
        return( FD_ISSET( sd, &sip->si_use_readfds ));
 
907
#endif
 
908
}
 
909
 
 
910
 
 
911
void *
 
912
ldap_new_select_info( void )
 
913
{
 
914
        struct selectinfo       *sip;
 
915
 
 
916
        sip = (struct selectinfo *)LDAP_CALLOC( 1, sizeof( struct selectinfo ));
 
917
 
 
918
        if ( sip == NULL ) return NULL;
 
919
 
 
920
#ifdef HAVE_POLL
 
921
        /* for UNIX poll(2) */
 
922
        /* sip->si_maxfd=0 */
 
923
#else
 
924
        /* for UNIX select(2) */
 
925
        FD_ZERO( &sip->si_readfds );
 
926
        FD_ZERO( &sip->si_writefds );
 
927
#endif
 
928
 
 
929
        return( (void *)sip );
 
930
}
 
931
 
 
932
 
 
933
void
 
934
ldap_free_select_info( void *sip )
 
935
{
 
936
        LDAP_FREE( sip );
 
937
}
 
938
 
 
939
 
 
940
#ifndef HAVE_POLL
 
941
int ldap_int_tblsize = 0;
 
942
 
 
943
void
 
944
ldap_int_ip_init( void )
 
945
{
 
946
#if defined( HAVE_SYSCONF )
 
947
        long tblsize = sysconf( _SC_OPEN_MAX );
 
948
        if( tblsize > INT_MAX ) tblsize = INT_MAX;
 
949
 
 
950
#elif defined( HAVE_GETDTABLESIZE )
 
951
        int tblsize = getdtablesize();
 
952
#else
 
953
        int tblsize = FD_SETSIZE;
 
954
#endif /* !USE_SYSCONF */
 
955
 
 
956
#ifdef FD_SETSIZE
 
957
        if( tblsize > FD_SETSIZE ) tblsize = FD_SETSIZE;
 
958
#endif  /* FD_SETSIZE */
 
959
 
 
960
        ldap_int_tblsize = tblsize;
 
961
}
 
962
#endif
 
963
 
 
964
 
 
965
int
 
966
ldap_int_select( LDAP *ld, struct timeval *timeout )
 
967
{
 
968
        int rc;
 
969
        struct selectinfo       *sip;
 
970
 
 
971
        Debug( LDAP_DEBUG_TRACE, "ldap_int_select\n", 0, 0, 0 );
 
972
 
 
973
#ifndef HAVE_POLL
 
974
        if ( ldap_int_tblsize == 0 ) ldap_int_ip_init();
 
975
#endif
 
976
 
 
977
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
978
        assert( sip != NULL );
 
979
 
 
980
#ifdef HAVE_POLL
 
981
        {
 
982
                int to = timeout ? TV2MILLISEC( timeout ) : INFTIM;
 
983
                rc = poll( sip->si_fds, sip->si_maxfd, to );
 
984
        }
 
985
#else
 
986
        sip->si_use_readfds = sip->si_readfds;
 
987
        sip->si_use_writefds = sip->si_writefds;
 
988
        
 
989
        rc = select( ldap_int_tblsize,
 
990
                &sip->si_use_readfds, &sip->si_use_writefds,
 
991
                NULL, timeout );
 
992
#endif
 
993
 
 
994
        return rc;
 
995
}