Print this page
4823 don't open-code NSEC2MSEC and MSEC2NSEC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libldap5/sources/ldap/common/os-ip.c
+++ new/usr/src/lib/libldap5/sources/ldap/common/os-ip.c
1 1 /*
2 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 -#pragma ident "%Z%%M% %I% %E% SMI"
7 -
8 6 /*
9 7 * The contents of this file are subject to the Netscape Public
10 8 * License Version 1.1 (the "License"); you may not use this file
11 9 * except in compliance with the License. You may obtain a copy of
12 10 * the License at http://www.mozilla.org/NPL/
13 11 *
14 12 * Software distributed under the License is distributed on an "AS
15 13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16 14 * implied. See the License for the specific language governing
17 15 * rights and limitations under the License.
18 16 *
19 17 * The Original Code is Mozilla Communicator client code, released
20 18 * March 31, 1998.
21 19 *
22 20 * The Initial Developer of the Original Code is Netscape
23 21 * Communications Corporation. Portions created by Netscape are
24 22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25 23 * Rights Reserved.
26 24 *
27 25 * Contributor(s):
28 26 */
29 27 /*
30 28 * Copyright (c) 1995 Regents of the University of Michigan.
31 29 * All rights reserved.
32 30 */
33 31 /*
34 32 * os-ip.c -- platform-specific TCP & UDP related code
35 33 */
36 34
37 35 #if 0
38 36 #ifndef lint
39 37 static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
40 38 #endif
41 39 #endif
42 40
43 41 #include "ldap-int.h"
44 42 #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
45 43 #include <signal.h>
46 44 #endif
47 45
48 46 #ifdef NSLDAPI_HAVE_POLL
49 47 #include <poll.h>
50 48 #endif
51 49
52 50
53 51 #ifdef _WINDOWS
54 52 #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) == INVALID_SOCKET)
55 53 #else
56 54 #define NSLDAPI_INVALID_OS_SOCKET( s ) ((s) < 0 )
57 55 #endif
58 56
59 57
60 58 #define NSLDAPI_POLL_ARRAY_GROWTH 5 /* grow arrays 5 elements at a time */
61 59
62 60
63 61 /*
64 62 * Structures and union for tracking status of network sockets
65 63 */
66 64 #ifdef NSLDAPI_HAVE_POLL
67 65 struct nsldapi_os_statusinfo { /* used with native OS poll() */
68 66 struct pollfd *ossi_pollfds;
69 67 int ossi_pollfds_size;
70 68 };
71 69 #else /* NSLDAPI_HAVE_POLL */
72 70 struct nsldapi_os_statusinfo { /* used with native OS select() */
73 71 fd_set ossi_readfds;
74 72 fd_set ossi_writefds;
75 73 fd_set ossi_use_readfds;
76 74 fd_set ossi_use_writefds;
77 75 };
78 76 #endif /* else NSLDAPI_HAVE_POLL */
79 77
80 78 struct nsldapi_cb_statusinfo { /* used with ext. I/O poll() callback */
81 79 LDAP_X_PollFD *cbsi_pollfds;
82 80 int cbsi_pollfds_size;
83 81 };
84 82
85 83 /*
86 84 * NSLDAPI_CB_POLL_MATCH() evaluates to non-zero (true) if the Sockbuf *sdp
87 85 * matches the LDAP_X_PollFD pollfd.
88 86 */
89 87 #ifdef _WINDOWS
90 88 #define NSLDAPI_CB_POLL_SD_CAST (unsigned int)
91 89 #else
92 90 #define NSLDAPI_CB_POLL_SD_CAST
93 91 #endif
94 92 #if defined(LDAP_SASLIO_HOOKS)
95 93 #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
96 94 ( ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd)) && \
97 95 (((sbp)->sb_sasl_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) || \
98 96 ((sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg) ) )
99 97 #else
100 98 #define NSLDAPI_CB_POLL_MATCH( sbp, pollfd ) \
101 99 ((sbp)->sb_sd == NSLDAPI_CB_POLL_SD_CAST ((pollfd).lpoll_fd) && \
102 100 (sbp)->sb_ext_io_fns.lbextiofn_socket_arg == (pollfd).lpoll_socketarg)
103 101 #endif
104 102
105 103
106 104 struct nsldapi_iostatus_info {
107 105 int ios_type;
108 106 #define NSLDAPI_IOSTATUS_TYPE_OSNATIVE 1 /* poll() or select() */
109 107 #define NSLDAPI_IOSTATUS_TYPE_CALLBACK 2 /* poll()-like */
110 108 int ios_read_count;
111 109 int ios_write_count;
112 110 union {
113 111 struct nsldapi_os_statusinfo ios_osinfo;
114 112 struct nsldapi_cb_statusinfo ios_cbinfo;
115 113 } ios_status;
116 114 };
117 115
118 116
119 117 #ifdef NSLDAPI_HAVE_POLL
120 118 static int nsldapi_add_to_os_pollfds( int fd,
121 119 struct nsldapi_os_statusinfo *pip, short events );
122 120 static int nsldapi_clear_from_os_pollfds( int fd,
123 121 struct nsldapi_os_statusinfo *pip, short events );
124 122 static int nsldapi_find_in_os_pollfds( int fd,
125 123 struct nsldapi_os_statusinfo *pip, short revents );
126 124 #endif /* NSLDAPI_HAVE_POLL */
127 125
128 126 static int nsldapi_iostatus_init_nolock( LDAP *ld );
129 127 static int nsldapi_add_to_cb_pollfds( Sockbuf *sb,
130 128 struct nsldapi_cb_statusinfo *pip, short events );
131 129 static int nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
132 130 struct nsldapi_cb_statusinfo *pip, short events );
133 131 static int nsldapi_find_in_cb_pollfds( Sockbuf *sb,
134 132 struct nsldapi_cb_statusinfo *pip, short revents );
135 133
136 134
137 135 #ifdef irix
138 136 #ifndef _PR_THREADS
139 137 /*
140 138 * XXXmcs: on IRIX NSPR's poll() and select() wrappers will crash if NSPR
141 139 * has not been initialized. We work around the problem by bypassing
142 140 * the NSPR wrapper functions and going directly to the OS' functions.
143 141 */
144 142 #define NSLDAPI_POLL _poll
145 143 #define NSLDAPI_SELECT _select
146 144 extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
147 145 extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
148 146 fd_set *exceptfds, struct timeval *timeout);
149 147 #else /* _PR_THREADS */
150 148 #define NSLDAPI_POLL poll
151 149 #define NSLDAPI_SELECT select
152 150 #endif /* else _PR_THREADS */
153 151 #else /* irix */
154 152 #define NSLDAPI_POLL poll
155 153 #define NSLDAPI_SELECT select
156 154 #endif /* else irix */
157 155
158 156
159 157 static LBER_SOCKET nsldapi_os_socket( LDAP *ld, int secure, int domain,
160 158 int type, int protocol );
161 159 static int nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp );
162 160 static int nsldapi_os_connect_with_to( LBER_SOCKET s, struct sockaddr *name,
163 161 int namelen, LDAP *ld);
164 162
165 163 /*
166 164 * Function typedefs used by nsldapi_try_each_host()
167 165 */
168 166 typedef LBER_SOCKET (NSLDAPI_SOCKET_FN)( LDAP *ld, int secure, int domain,
169 167 int type, int protocol );
170 168 typedef int (NSLDAPI_IOCTL_FN)( LBER_SOCKET s, int option, int *statusp );
171 169 typedef int (NSLDAPI_CONNECT_WITH_TO_FN )( LBER_SOCKET s, struct sockaddr *name,
172 170 int namelen, LDAP *ld);
173 171 typedef int (NSLDAPI_CONNECT_FN )( LBER_SOCKET s, struct sockaddr *name,
174 172 int namelen );
175 173 typedef int (NSLDAPI_CLOSE_FN )( LBER_SOCKET s );
176 174
177 175 static int nsldapi_try_each_host( LDAP *ld, const char *hostlist, int defport,
178 176 int secure, NSLDAPI_SOCKET_FN *socketfn, NSLDAPI_IOCTL_FN *ioctlfn,
179 177 NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
180 178 NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn );
181 179
182 180
183 181 static int
184 182 nsldapi_os_closesocket( LBER_SOCKET s )
185 183 {
186 184 int rc;
187 185
188 186 #ifdef _WINDOWS
189 187 rc = closesocket( s );
190 188 #else
191 189 rc = close( s );
192 190 #endif
193 191 return( rc );
194 192 }
195 193
196 194
197 195 static LBER_SOCKET
198 196 nsldapi_os_socket( LDAP *ld, int secure, int domain, int type, int protocol )
199 197 {
200 198 int s, invalid_socket;
201 199 char *errmsg = NULL;
202 200
203 201 if ( secure ) {
204 202 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
205 203 nsldapi_strdup( dgettext(TEXT_DOMAIN,
206 204 "secure mode not supported") ));
207 205 return( -1 );
208 206 }
209 207
210 208 s = socket( domain, type, protocol );
211 209
212 210 /*
213 211 * if the socket() call failed or it returned a socket larger
214 212 * than we can deal with, return a "local error."
215 213 */
216 214 if ( NSLDAPI_INVALID_OS_SOCKET( s )) {
217 215 errmsg = dgettext(TEXT_DOMAIN, "unable to create a socket");
218 216 invalid_socket = 1;
219 217 } else { /* valid socket -- check for overflow */
220 218 invalid_socket = 0;
221 219 #if !defined(NSLDAPI_HAVE_POLL) && !defined(_WINDOWS)
222 220 /* not on Windows and do not have poll() */
223 221 if ( s >= FD_SETSIZE ) {
224 222 errmsg = "can't use socket >= FD_SETSIZE";
225 223 }
226 224 #endif
227 225 }
228 226
229 227 if ( errmsg != NULL ) { /* local socket error */
230 228 if ( !invalid_socket ) {
231 229 nsldapi_os_closesocket( s );
232 230 }
233 231 errmsg = nsldapi_strdup( errmsg );
234 232 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, errmsg );
235 233 return( -1 );
236 234 }
237 235
238 236 return( s );
239 237 }
240 238
241 239
242 240
243 241 /*
244 242 * Non-blocking connect call function
245 243 */
246 244 static int
247 245 nsldapi_os_connect_with_to(LBER_SOCKET sockfd, struct sockaddr *saptr,
248 246 int salen, LDAP *ld)
249 247 {
250 248 #ifndef _WINDOWS
251 249 int flags;
252 250 #endif /* _WINDOWS */
253 251 int n, error;
254 252 int len;
255 253 fd_set rset, wset;
256 254 struct timeval tval;
257 255 #ifdef _WINDOWS
258 256 int nonblock = 1;
259 257 int block = 0;
260 258 fd_set eset;
261 259 #endif /* _WINDOWS */
262 260 int msec = ld->ld_connect_timeout; /* milliseconds */
263 261 int continue_on_intr = 0;
264 262 #ifdef _SOLARIS_SDK
265 263 hrtime_t start_time = 0, tmp_time, tv_time; /* nanoseconds */
266 264 #else
267 265 long start_time = 0, tmp_time; /* seconds */
268 266 #endif
269 267
270 268
271 269 LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_nonblock timeout: %d (msec)\n",
272 270 msec, 0, 0);
273 271
274 272 #ifdef _WINDOWS
275 273 ioctlsocket(sockfd, FIONBIO, &nonblock);
276 274 #else
277 275 flags = fcntl(sockfd, F_GETFL, 0);
278 276 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
279 277 #endif /* _WINDOWS */
280 278
281 279 error = 0;
282 280 if ((n = connect(sockfd, saptr, salen)) < 0)
283 281 #ifdef _WINDOWS
284 282 if ((n != SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) {
285 283 #else
286 284 if (errno != EINPROGRESS) {
287 285 #endif /* _WINDOWS */
288 286 #ifdef LDAP_DEBUG
289 287 if ( ldap_debug & LDAP_DEBUG_TRACE ) {
290 288 perror("connect");
291 289 }
292 290 #endif
293 291 return (-1);
294 292 }
295 293
296 294 /* success */
297 295 if (n == 0)
298 296 goto done;
299 297
300 298 FD_ZERO(&rset);
301 299 FD_SET(sockfd, &rset);
302 300 wset = rset;
303 301
304 302 #ifdef _WINDOWS
305 303 eset = rset;
306 304 #endif /* _WINDOWS */
307 305
308 306 if (msec < 0 && msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) {
309 307 LDAPDebug( LDAP_DEBUG_TRACE, "Invalid timeout value detected.."
↓ open down ↓ |
292 lines elided |
↑ open up ↑ |
310 308 "resetting connect timeout to default value "
311 309 "(LDAP_X_IO_TIMEOUT_NO_TIMEOUT\n", 0, 0, 0);
312 310 msec = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
313 311 } else {
314 312 if (msec != 0) {
315 313 tval.tv_sec = msec / MILLISEC;
316 314 tval.tv_usec = (MICROSEC / MILLISEC) *
317 315 (msec % MILLISEC);
318 316 #ifdef _SOLARIS_SDK
319 317 start_time = gethrtime();
320 - tv_time = (hrtime_t)msec * (NANOSEC / MILLISEC);
318 + tv_time = MSEC2NSEC(msec);
321 319 #else
322 320 start_time = (long)time(NULL);
323 321 #endif
324 322 } else {
325 323 tval.tv_sec = 0;
326 324 tval.tv_usec = 0;
327 325 }
328 326 }
329 327
330 328 /* if timeval structure == NULL, select will block indefinitely */
331 329 /* != NULL, and value == 0, select will */
332 330 /* not block */
333 331 /* Windows is a bit quirky on how it behaves w.r.t nonblocking */
334 332 /* connects. If the connect fails, the exception fd, eset, is */
335 333 /* set to show the failure. The first argument in select is */
336 334 /* ignored */
337 335
338 336 #ifdef _WINDOWS
339 337 if ((n = select(sockfd +1, &rset, &wset, &eset,
340 338 (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? &tval : NULL)) == 0) {
341 339 errno = WSAETIMEDOUT;
342 340 return (-1);
343 341 }
344 342 /* if wset is set, the connect worked */
345 343 if (FD_ISSET(sockfd, &wset) || FD_ISSET(sockfd, &rset)) {
346 344 len = sizeof(error);
347 345 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
348 346 < 0)
349 347 return (-1);
350 348 goto done;
351 349 }
352 350
353 351 /* if eset is set, the connect failed */
354 352 if (FD_ISSET(sockfd, &eset)) {
355 353 return (-1);
356 354 }
357 355
358 356 /* failure on select call */
359 357 if (n == SOCKET_ERROR) {
360 358 perror("select error: SOCKET_ERROR returned");
361 359 return (-1);
362 360 }
363 361 #else
364 362 /*
365 363 * if LDAP_BITOPT_RESTART and select() is interrupted
366 364 * try again.
367 365 */
368 366 do {
369 367 continue_on_intr = 0;
370 368 if ((n = select(sockfd +1, &rset, &wset, NULL,
371 369 (msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) ? \
372 370 &tval : NULL)) == 0) {
373 371 errno = ETIMEDOUT;
374 372 return (-1);
375 373 }
376 374 if (n < 0) {
377 375 if ((ld->ld_options & LDAP_BITOPT_RESTART) &&
378 376 (errno == EINTR)) {
379 377 continue_on_intr = 1;
380 378 errno = 0;
381 379 FD_ZERO(&rset);
382 380 FD_SET(sockfd, &rset);
383 381 wset = rset;
384 382 /* honour the timeout */
385 383 if ((msec != LDAP_X_IO_TIMEOUT_NO_TIMEOUT) &&
386 384 (msec != 0)) {
387 385 #ifdef _SOLARIS_SDK
388 386 tmp_time = gethrtime();
389 387 if ((tv_time -=
390 388 (tmp_time - start_time)) <= 0) {
391 389 #else
392 390 tmp_time = (long)time(NULL);
393 391 if ((tval.tv_sec -=
394 392 (tmp_time - start_time)) <= 0) {
395 393 #endif
396 394 /* timeout */
397 395 errno = ETIMEDOUT;
398 396 return (-1);
399 397 }
400 398 #ifdef _SOLARIS_SDK
401 399 tval.tv_sec = tv_time / NANOSEC;
402 400 tval.tv_usec = (tv_time % NANOSEC) /
403 401 (NANOSEC / MICROSEC);
404 402 #endif
405 403 start_time = tmp_time;
406 404 }
407 405 } else {
408 406 #ifdef LDAP_DEBUG
409 407 perror("select error: ");
410 408 #endif
411 409 return (-1);
412 410 }
413 411 }
414 412 } while (continue_on_intr == 1);
415 413
416 414 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
417 415 len = sizeof(error);
418 416 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)
419 417 < 0)
420 418 return (-1);
421 419 #ifdef LDAP_DEBUG
422 420 } else if ( ldap_debug & LDAP_DEBUG_TRACE ) {
423 421 perror("select error: sockfd not set");
424 422 #endif
425 423 }
426 424 #endif /* _WINDOWS */
427 425
428 426 done:
429 427 #ifdef _WINDOWS
430 428 ioctlsocket(sockfd, FIONBIO, &block);
431 429 #else
432 430 fcntl(sockfd, F_SETFL, flags);
433 431 #endif /* _WINDOWS */
434 432
435 433 if (error) {
436 434 errno = error;
437 435 return (-1);
438 436 }
439 437
440 438 return (0);
441 439 }
442 440
443 441
444 442 static int
445 443 nsldapi_os_ioctl( LBER_SOCKET s, int option, int *statusp )
446 444 {
447 445 int err;
448 446 #ifdef _WINDOWS
449 447 u_long iostatus;
450 448 #endif
451 449
452 450 if ( FIONBIO != option ) {
453 451 return( -1 );
454 452 }
455 453
456 454 #ifdef _WINDOWS
457 455 iostatus = *(u_long *)statusp;
458 456 err = ioctlsocket( s, FIONBIO, &iostatus );
459 457 #else
460 458 err = ioctl( s, FIONBIO, (caddr_t)statusp );
461 459 #endif
462 460
463 461 return( err );
464 462 }
465 463
466 464
467 465 int
468 466 nsldapi_connect_to_host( LDAP *ld, Sockbuf *sb, const char *hostlist,
469 467 int defport, int secure, char **krbinstancep )
470 468 /*
471 469 * "defport" must be in host byte order
472 470 * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
473 471 * if -1 is returned, ld_errno is set
474 472 */
475 473 {
476 474 int s;
477 475
478 476 LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_connect_to_host: %s, port: %d\n",
479 477 NULL == hostlist ? "NULL" : hostlist, defport, 0 );
480 478
481 479 /*
482 480 * If an extended I/O connect callback has been defined, just use it.
483 481 */
484 482 if ( NULL != ld->ld_extconnect_fn ) {
485 483 unsigned long connect_opts = 0;
486 484
487 485 if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
488 486 connect_opts |= LDAP_X_EXTIOF_OPT_NONBLOCKING;
489 487 }
490 488 if ( secure ) {
491 489 connect_opts |= LDAP_X_EXTIOF_OPT_SECURE;
492 490 }
493 491 s = ld->ld_extconnect_fn( hostlist, defport,
494 492 ld->ld_connect_timeout, connect_opts,
495 493 ld->ld_ext_session_arg,
496 494 &sb->sb_ext_io_fns.lbextiofn_socket_arg
497 495 #ifdef _SOLARIS_SDK
498 496 , NULL );
499 497 #else
500 498 );
501 499 #endif /* _SOLARIS_SDK */
502 500
503 501 } else {
504 502 s = nsldapi_try_each_host( ld, hostlist,
505 503 defport, secure, nsldapi_os_socket,
506 504 nsldapi_os_ioctl, nsldapi_os_connect_with_to,
507 505 NULL, nsldapi_os_closesocket );
508 506 }
509 507
510 508 if ( s < 0 ) {
511 509 LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
512 510 return( -1 );
513 511 }
514 512
515 513 sb->sb_sd = s;
516 514
517 515 /*
518 516 * Set krbinstancep (canonical name of host for use by Kerberos).
519 517 */
520 518 #ifdef KERBEROS
521 519 char *p;
522 520
523 521 if (( *krbinstancep = nsldapi_host_connected_to( sb )) != NULL
524 522 && ( p = strchr( *krbinstancep, '.' )) != NULL ) {
525 523 *p = '\0';
526 524 }
527 525 #else /* KERBEROS */
528 526 *krbinstancep = NULL;
529 527 #endif /* KERBEROS */
530 528
531 529 return( 0 );
532 530 }
533 531
534 532
535 533 /*
536 534 * Returns a socket number if successful and -1 if an error occurs.
537 535 */
538 536 static int
539 537 nsldapi_try_each_host( LDAP *ld, const char *hostlist,
540 538 int defport, int secure, NSLDAPI_SOCKET_FN *socketfn,
541 539 NSLDAPI_IOCTL_FN *ioctlfn, NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn,
542 540 NSLDAPI_CONNECT_FN *connectfn, NSLDAPI_CLOSE_FN *closefn )
543 541 {
544 542 int rc, i, s, err, connected, use_hp;
545 543 int parse_err, port;
546 544 struct sockaddr_in sin;
547 545 nsldapi_in_addr_t address;
548 546 char **addrlist, *ldhpbuf, *ldhpbuf_allocd;
549 547 char *host;
550 548 LDAPHostEnt ldhent, *ldhp;
551 549 struct hostent *hp;
552 550 struct ldap_x_hostlist_status *status;
553 551 #ifdef GETHOSTBYNAME_BUF_T
554 552 GETHOSTBYNAME_BUF_T hbuf;
555 553 struct hostent hent;
556 554 #endif /* GETHOSTBYNAME_BUF_T */
557 555
558 556 connected = 0;
559 557 parse_err = ldap_x_hostlist_first( hostlist, defport, &host, &port,
560 558 &status );
561 559 while ( !connected && LDAP_SUCCESS == parse_err && host != NULL ) {
562 560 ldhpbuf_allocd = NULL;
563 561 ldhp = NULL;
564 562 hp = NULL;
565 563 s = 0;
566 564 use_hp = 0;
567 565 addrlist = NULL;
568 566
569 567
570 568 if (( address = inet_addr( host )) == -1 ) {
571 569 if ( ld->ld_dns_gethostbyname_fn == NULL ) {
572 570 if (( hp = GETHOSTBYNAME( host, &hent, hbuf,
573 571 sizeof(hbuf), &err )) != NULL ) {
574 572 addrlist = hp->h_addr_list;
575 573 }
576 574 } else {
577 575 /*
578 576 * DNS callback installed... use it.
579 577 */
580 578 #ifdef GETHOSTBYNAME_buf_t
581 579 /* avoid allocation by using hbuf if large enough */
582 580 if ( sizeof( hbuf ) < ld->ld_dns_bufsize ) {
583 581 ldhpbuf = ldhpbuf_allocd
584 582 = NSLDAPI_MALLOC( ld->ld_dns_bufsize );
585 583 } else {
586 584 ldhpbuf = (char *)hbuf;
587 585 }
588 586 #else /* GETHOSTBYNAME_buf_t */
589 587 ldhpbuf = ldhpbuf_allocd = NSLDAPI_MALLOC(
590 588 ld->ld_dns_bufsize );
591 589 #endif /* else GETHOSTBYNAME_buf_t */
592 590
593 591 if ( ldhpbuf == NULL ) {
594 592 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY,
595 593 NULL, NULL );
596 594 ldap_memfree( host );
597 595 ldap_x_hostlist_statusfree( status );
598 596 return( -1 );
599 597 }
600 598
601 599 if (( ldhp = ld->ld_dns_gethostbyname_fn( host,
602 600 &ldhent, ldhpbuf, ld->ld_dns_bufsize, &err,
603 601 ld->ld_dns_extradata )) != NULL ) {
604 602 addrlist = ldhp->ldaphe_addr_list;
605 603 }
606 604 }
607 605
608 606 if ( addrlist == NULL ) {
609 607 LDAP_SET_LDERRNO( ld, LDAP_CONNECT_ERROR, NULL, NULL );
610 608 LDAP_SET_ERRNO( ld, EHOSTUNREACH ); /* close enough */
611 609 if ( ldhpbuf_allocd != NULL ) {
612 610 NSLDAPI_FREE( ldhpbuf_allocd );
613 611 }
614 612 ldap_memfree( host );
615 613 ldap_x_hostlist_statusfree( status );
616 614 return( -1 );
617 615 }
618 616 use_hp = 1;
619 617 }
620 618
621 619 rc = -1;
622 620 for ( i = 0; !use_hp || ( addrlist[ i ] != 0 ); i++ ) {
623 621 if ( -1 == ( s = (*socketfn)( ld, secure, AF_INET,
624 622 SOCK_STREAM, 0 ))) {
625 623 if ( ldhpbuf_allocd != NULL ) {
626 624 NSLDAPI_FREE( ldhpbuf_allocd );
627 625 }
628 626 ldap_memfree( host );
629 627 ldap_x_hostlist_statusfree( status );
630 628 return( -1 );
631 629 }
632 630
633 631 if ( ld->ld_options & LDAP_BITOPT_ASYNC ) {
634 632 int iostatus = 1;
635 633
636 634 err = (*ioctlfn)( s, FIONBIO, &iostatus );
637 635 if ( err == -1 ) {
638 636 LDAPDebug( LDAP_DEBUG_ANY,
639 637 "FIONBIO ioctl failed on %d\n",
640 638 s, 0, 0 );
641 639 }
642 640 }
643 641
644 642 (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
645 643 sin.sin_family = AF_INET;
646 644 sin.sin_port = htons( (unsigned short)port );
647 645
648 646 SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
649 647 ( use_hp ? (char *) addrlist[ i ] :
650 648 (char *) &address ), sizeof( sin.sin_addr.s_addr) );
651 649
652 650 {
653 651 #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
654 652 /*
655 653 * Block all of the signals that might interrupt connect() since there
656 654 * is an OS bug that causes connect() to fail if it is restarted. Look in
657 655 * ns/netsite/ldap/include/portable.h for the definition of
658 656 * LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
659 657 */
660 658 sigset_t ints_off, oldset;
661 659
662 660 sigemptyset( &ints_off );
663 661 sigaddset( &ints_off, SIGALRM );
664 662 sigaddset( &ints_off, SIGIO );
665 663 sigaddset( &ints_off, SIGCLD );
666 664
667 665 sigprocmask( SIG_BLOCK, &ints_off, &oldset );
668 666 #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
669 667
670 668 if ( NULL != connectwithtofn ) {
671 669 err = (*connectwithtofn)(s,
672 670 (struct sockaddr *)&sin,
673 671 sizeof(struct sockaddr_in),
674 672 ld);
675 673 } else {
676 674 err = (*connectfn)(s,
677 675 (struct sockaddr *)&sin,
678 676 sizeof(struct sockaddr_in));
679 677 }
680 678 #ifdef LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED
681 679 /*
682 680 * restore original signal mask
683 681 */
684 682 sigprocmask( SIG_SETMASK, &oldset, 0 );
685 683 #endif /* LDAP_CONNECT_MUST_NOT_BE_INTERRUPTED */
686 684
687 685 }
688 686 if ( err >= 0 ) {
689 687 connected = 1;
690 688 rc = 0;
691 689 break;
692 690 } else {
693 691 if ( ld->ld_options & LDAP_BITOPT_ASYNC) {
694 692 #ifdef _WINDOWS
695 693 if (err == -1 && WSAGetLastError() == WSAEWOULDBLOCK)
696 694 LDAP_SET_ERRNO( ld, EWOULDBLOCK );
697 695 #endif /* _WINDOWS */
698 696 err = LDAP_GET_ERRNO( ld );
699 697 if ( NSLDAPI_ERRNO_IO_INPROGRESS( err )) {
700 698 LDAPDebug( LDAP_DEBUG_TRACE, "connect would block...\n",
701 699 0, 0, 0 );
702 700 rc = -2;
703 701 break;
704 702 }
705 703 }
706 704
707 705 #ifdef LDAP_DEBUG
708 706 if ( ldap_debug & LDAP_DEBUG_TRACE ) {
709 707 perror( (char *)inet_ntoa( sin.sin_addr ));
710 708 }
711 709 #endif
712 710 (*closefn)( s );
713 711 if ( !use_hp ) {
714 712 break;
715 713 }
716 714 }
717 715 }
718 716
719 717 ldap_memfree( host );
720 718 parse_err = ldap_x_hostlist_next( &host, &port, status );
721 719 }
722 720
723 721 if ( ldhpbuf_allocd != NULL ) {
724 722 NSLDAPI_FREE( ldhpbuf_allocd );
725 723 }
726 724 ldap_memfree( host );
727 725 ldap_x_hostlist_statusfree( status );
728 726
729 727 if ( connected ) {
730 728 LDAPDebug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
731 729 s, inet_ntoa( sin.sin_addr ), 0 );
732 730 }
733 731
734 732 return( rc == 0 ? s : -1 );
735 733 }
736 734
737 735
738 736 void
739 737 nsldapi_close_connection( LDAP *ld, Sockbuf *sb )
740 738 {
741 739 if ( ld->ld_extclose_fn == NULL ) {
742 740 nsldapi_os_closesocket( sb->sb_sd );
743 741 } else {
744 742 ld->ld_extclose_fn( sb->sb_sd,
745 743 sb->sb_ext_io_fns.lbextiofn_socket_arg );
746 744 }
747 745 }
748 746
749 747
750 748 #ifdef KERBEROS
751 749 char *
752 750 nsldapi_host_connected_to( Sockbuf *sb )
753 751 {
754 752 struct hostent *hp;
755 753 char *p;
756 754 int len;
757 755 struct sockaddr_in sin;
758 756
759 757 (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
760 758 len = sizeof( sin );
761 759 if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
762 760 return( NULL );
763 761 }
764 762
765 763 /*
766 764 * do a reverse lookup on the addr to get the official hostname.
767 765 * this is necessary for kerberos to work right, since the official
768 766 * hostname is used as the kerberos instance.
769 767 */
770 768 #error XXXmcs: need to use DNS callbacks here
771 769 if (( hp = gethostbyaddr((char *) &sin.sin_addr,
772 770 sizeof( sin.sin_addr ), AF_INET)) != NULL ) {
773 771 if ( hp->h_name != NULL ) {
774 772 return( nsldapi_strdup( hp->h_name ));
775 773 }
776 774 }
777 775
778 776 return( NULL );
779 777 }
780 778 #endif /* KERBEROS */
781 779
782 780
783 781 /*
784 782 * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
785 783 * Also allocates initializes ld->ld_iostatus if needed..
786 784 */
787 785 int
788 786 nsldapi_iostatus_interest_write( LDAP *ld, Sockbuf *sb )
789 787 {
790 788 NSLDAPIIOStatus *iosp;
791 789
792 790 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
793 791
794 792 if ( ld->ld_iostatus == NULL
795 793 && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
796 794 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
797 795 return( -1 );
798 796 }
799 797
800 798 iosp = ld->ld_iostatus;
801 799
802 800 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
803 801 #ifdef NSLDAPI_HAVE_POLL
804 802 if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
805 803 &iosp->ios_status.ios_osinfo, POLLOUT )) {
806 804 ++iosp->ios_write_count;
807 805 }
808 806 #else /* NSLDAPI_HAVE_POLL */
809 807 if ( !FD_ISSET( sb->sb_sd,
810 808 &iosp->ios_status.ios_osinfo.ossi_writefds )) {
811 809 FD_SET( sb->sb_sd,
812 810 &iosp->ios_status.ios_osinfo.ossi_writefds );
813 811 ++iosp->ios_write_count;
814 812 }
815 813 #endif /* else NSLDAPI_HAVE_POLL */
816 814
817 815 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
818 816 if ( nsldapi_add_to_cb_pollfds( sb,
819 817 &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
820 818 ++iosp->ios_write_count;
821 819 }
822 820
823 821 } else {
824 822 LDAPDebug( LDAP_DEBUG_ANY,
825 823 "nsldapi_iostatus_interest_write: unknown I/O type %d\n",
826 824 iosp->ios_type, 0, 0 );
827 825 }
828 826
829 827 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
830 828
831 829 return( 0 );
832 830 }
833 831
834 832
835 833 /*
836 834 * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
837 835 * Also allocates initializes ld->ld_iostatus if needed..
838 836 */
839 837 int
840 838 nsldapi_iostatus_interest_read( LDAP *ld, Sockbuf *sb )
841 839 {
842 840 NSLDAPIIOStatus *iosp;
843 841
844 842 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
845 843
846 844 if ( ld->ld_iostatus == NULL
847 845 && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
848 846 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
849 847 return( -1 );
850 848 }
851 849
852 850 iosp = ld->ld_iostatus;
853 851
854 852 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
855 853 #ifdef NSLDAPI_HAVE_POLL
856 854 if ( nsldapi_add_to_os_pollfds( sb->sb_sd,
857 855 &iosp->ios_status.ios_osinfo, POLLIN )) {
858 856 ++iosp->ios_read_count;
859 857 }
860 858 #else /* NSLDAPI_HAVE_POLL */
861 859 if ( !FD_ISSET( sb->sb_sd,
862 860 &iosp->ios_status.ios_osinfo.ossi_readfds )) {
863 861 FD_SET( sb->sb_sd,
864 862 &iosp->ios_status.ios_osinfo.ossi_readfds );
865 863 ++iosp->ios_read_count;
866 864 }
867 865 #endif /* else NSLDAPI_HAVE_POLL */
868 866
869 867 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
870 868 if ( nsldapi_add_to_cb_pollfds( sb,
871 869 &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
872 870 ++iosp->ios_read_count;
873 871 }
874 872 } else {
875 873 LDAPDebug( LDAP_DEBUG_ANY,
876 874 "nsldapi_iostatus_interest_read: unknown I/O type %d\n",
877 875 iosp->ios_type, 0, 0 );
878 876 }
879 877
880 878 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
881 879
882 880 return( 0 );
883 881 }
884 882
885 883
886 884 /*
887 885 * Returns 0 if all goes well and -1 if an error occurs (error code set in ld)
888 886 * Also allocates initializes ld->ld_iostatus if needed..
889 887 */
890 888 int
891 889 nsldapi_iostatus_interest_clear( LDAP *ld, Sockbuf *sb )
892 890 {
893 891 NSLDAPIIOStatus *iosp;
894 892
895 893 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
896 894
897 895 if ( ld->ld_iostatus == NULL
898 896 && nsldapi_iostatus_init_nolock( ld ) < 0 ) {
899 897 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
900 898 return( -1 );
901 899 }
902 900
903 901 iosp = ld->ld_iostatus;
904 902
905 903 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
906 904 #ifdef NSLDAPI_HAVE_POLL
907 905 if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
908 906 &iosp->ios_status.ios_osinfo, POLLOUT )) {
909 907 --iosp->ios_write_count;
910 908 }
911 909 if ( nsldapi_clear_from_os_pollfds( sb->sb_sd,
912 910 &iosp->ios_status.ios_osinfo, POLLIN )) {
913 911 --iosp->ios_read_count;
914 912 }
915 913 #else /* NSLDAPI_HAVE_POLL */
916 914 if ( FD_ISSET( sb->sb_sd,
917 915 &iosp->ios_status.ios_osinfo.ossi_writefds )) {
918 916 FD_CLR( sb->sb_sd,
919 917 &iosp->ios_status.ios_osinfo.ossi_writefds );
920 918 --iosp->ios_write_count;
921 919 }
922 920 if ( FD_ISSET( sb->sb_sd,
923 921 &iosp->ios_status.ios_osinfo.ossi_readfds )) {
924 922 FD_CLR( sb->sb_sd,
925 923 &iosp->ios_status.ios_osinfo.ossi_readfds );
926 924 --iosp->ios_read_count;
927 925 }
928 926 #endif /* else NSLDAPI_HAVE_POLL */
929 927
930 928 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
931 929 if ( nsldapi_clear_from_cb_pollfds( sb,
932 930 &iosp->ios_status.ios_cbinfo, LDAP_X_POLLOUT )) {
933 931 --iosp->ios_write_count;
934 932 }
935 933 if ( nsldapi_clear_from_cb_pollfds( sb,
936 934 &iosp->ios_status.ios_cbinfo, LDAP_X_POLLIN )) {
937 935 --iosp->ios_read_count;
938 936 }
939 937 } else {
940 938 LDAPDebug( LDAP_DEBUG_ANY,
941 939 "nsldapi_iostatus_interest_clear: unknown I/O type %d\n",
942 940 iosp->ios_type, 0, 0 );
943 941 }
944 942
945 943 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
946 944
947 945 return( 0 );
948 946 }
949 947
950 948
951 949 /*
952 950 * Return a non-zero value if sb is ready for write.
953 951 */
954 952 int
955 953 nsldapi_iostatus_is_write_ready( LDAP *ld, Sockbuf *sb )
956 954 {
957 955 int rc;
958 956 NSLDAPIIOStatus *iosp;
959 957
960 958 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
961 959 iosp = ld->ld_iostatus;
962 960
963 961 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
964 962 #ifdef NSLDAPI_HAVE_POLL
965 963 /*
966 964 * if we are using poll() we do something a little tricky: if
967 965 * any bits in the socket's returned events field other than
968 966 * POLLIN (ready for read) are set, we return true. This
969 967 * is done so we notice when a server closes a connection
970 968 * or when another error occurs. The actual error will be
971 969 * noticed later when we call write() or send().
972 970 */
973 971 rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
974 972 &iosp->ios_status.ios_osinfo, ~POLLIN );
975 973
976 974 #else /* NSLDAPI_HAVE_POLL */
977 975 rc = FD_ISSET( sb->sb_sd,
978 976 &iosp->ios_status.ios_osinfo.ossi_use_writefds );
979 977 #endif /* else NSLDAPI_HAVE_POLL */
980 978
981 979 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
982 980 rc = nsldapi_find_in_cb_pollfds( sb,
983 981 &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLIN );
984 982
985 983 } else {
986 984 LDAPDebug( LDAP_DEBUG_ANY,
987 985 "nsldapi_iostatus_is_write_ready: unknown I/O type %d\n",
988 986 iosp->ios_type, 0, 0 );
989 987 rc = 0;
990 988 }
991 989
992 990 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
993 991 return( rc );
994 992 }
995 993
996 994
997 995 /*
998 996 * Return a non-zero value if sb is ready for read.
999 997 */
1000 998 int
1001 999 nsldapi_iostatus_is_read_ready( LDAP *ld, Sockbuf *sb )
1002 1000 {
1003 1001 int rc;
1004 1002 NSLDAPIIOStatus *iosp;
1005 1003
1006 1004 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
1007 1005 iosp = ld->ld_iostatus;
1008 1006
1009 1007 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1010 1008 #ifdef NSLDAPI_HAVE_POLL
1011 1009 /*
1012 1010 * if we are using poll() we do something a little tricky: if
1013 1011 * any bits in the socket's returned events field other than
1014 1012 * POLLOUT (ready for write) are set, we return true. This
1015 1013 * is done so we notice when a server closes a connection
1016 1014 * or when another error occurs. The actual error will be
1017 1015 * noticed later when we call read() or recv().
1018 1016 */
1019 1017 rc = nsldapi_find_in_os_pollfds( sb->sb_sd,
1020 1018 &iosp->ios_status.ios_osinfo, ~POLLOUT );
1021 1019
1022 1020 #else /* NSLDAPI_HAVE_POLL */
1023 1021 rc = FD_ISSET( sb->sb_sd,
1024 1022 &iosp->ios_status.ios_osinfo.ossi_use_readfds );
1025 1023 #endif /* else NSLDAPI_HAVE_POLL */
1026 1024
1027 1025 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1028 1026 rc = nsldapi_find_in_cb_pollfds( sb,
1029 1027 &iosp->ios_status.ios_cbinfo, ~LDAP_X_POLLOUT );
1030 1028
1031 1029 } else {
1032 1030 LDAPDebug( LDAP_DEBUG_ANY,
1033 1031 "nsldapi_iostatus_is_read_ready: unknown I/O type %d\n",
1034 1032 iosp->ios_type, 0, 0 );
1035 1033 rc = 0;
1036 1034 }
1037 1035
1038 1036 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
1039 1037 return( rc );
1040 1038 }
1041 1039
1042 1040
1043 1041 /*
1044 1042 * Allocated and initialize ld->ld_iostatus if not already done.
1045 1043 * Should be called with LDAP_IOSTATUS_LOCK locked.
1046 1044 * Returns 0 if all goes well and -1 if not (sets error in ld)
1047 1045 */
1048 1046 static int
1049 1047 nsldapi_iostatus_init_nolock( LDAP *ld )
1050 1048 {
1051 1049 NSLDAPIIOStatus *iosp;
1052 1050
1053 1051 if ( ld->ld_iostatus != NULL ) {
1054 1052 return( 0 );
1055 1053 }
1056 1054
1057 1055 if (( iosp = (NSLDAPIIOStatus *)NSLDAPI_CALLOC( 1,
1058 1056 sizeof( NSLDAPIIOStatus ))) == NULL ) {
1059 1057 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
1060 1058 return( -1 );
1061 1059 }
1062 1060
1063 1061 if ( ld->ld_extpoll_fn == NULL ) {
1064 1062 iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_OSNATIVE;
1065 1063 #ifndef NSLDAPI_HAVE_POLL
1066 1064 FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_readfds );
1067 1065 FD_ZERO( &iosp->ios_status.ios_osinfo.ossi_writefds );
1068 1066 #endif /* !NSLDAPI_HAVE_POLL */
1069 1067
1070 1068 } else {
1071 1069 iosp->ios_type = NSLDAPI_IOSTATUS_TYPE_CALLBACK;
1072 1070 }
1073 1071
1074 1072 ld->ld_iostatus = iosp;
1075 1073 return( 0 );
1076 1074 }
1077 1075
1078 1076
1079 1077 void
1080 1078 nsldapi_iostatus_free( LDAP *ld )
1081 1079 {
1082 1080 if ( ld == NULL ) {
1083 1081 return;
1084 1082 }
1085 1083
1086 1084
1087 1085 /* clean up classic I/O compatibility glue */
1088 1086 if ( ld->ld_io_fns_ptr != NULL ) {
1089 1087 if ( ld->ld_ext_session_arg != NULL ) {
1090 1088 NSLDAPI_FREE( ld->ld_ext_session_arg );
1091 1089 }
1092 1090 NSLDAPI_FREE( ld->ld_io_fns_ptr );
1093 1091 }
1094 1092
1095 1093 /* clean up I/O status tracking info. */
1096 1094 if ( ld->ld_iostatus != NULL ) {
1097 1095 NSLDAPIIOStatus *iosp = ld->ld_iostatus;
1098 1096
1099 1097 if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1100 1098 #ifdef NSLDAPI_HAVE_POLL
1101 1099 if ( iosp->ios_status.ios_osinfo.ossi_pollfds
1102 1100 != NULL ) {
1103 1101 NSLDAPI_FREE(
1104 1102 iosp->ios_status.ios_osinfo.ossi_pollfds );
1105 1103 }
1106 1104 #endif /* NSLDAPI_HAVE_POLL */
1107 1105
1108 1106 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1109 1107 if ( iosp->ios_status.ios_cbinfo.cbsi_pollfds
1110 1108 != NULL ) {
1111 1109 NSLDAPI_FREE(
1112 1110 iosp->ios_status.ios_cbinfo.cbsi_pollfds );
1113 1111 }
1114 1112 } else {
1115 1113 LDAPDebug( LDAP_DEBUG_ANY,
1116 1114 "nsldapi_iostatus_free: unknown I/O type %d\n",
1117 1115 iosp->ios_type, 0, 0 );
1118 1116 }
1119 1117
1120 1118 NSLDAPI_FREE( iosp );
1121 1119 }
1122 1120 }
1123 1121
1124 1122
1125 1123 static int
1126 1124 nsldapi_get_select_table_size( void )
1127 1125 {
1128 1126 static int tblsize = 0; /* static */
1129 1127
1130 1128 if ( tblsize == 0 ) {
1131 1129 #if defined(_WINDOWS) || defined(XP_OS2)
1132 1130 tblsize = FOPEN_MAX; /* ANSI spec. */
1133 1131 #else
1134 1132 #ifdef USE_SYSCONF
1135 1133 tblsize = sysconf( _SC_OPEN_MAX );
1136 1134 #else /* USE_SYSCONF */
1137 1135 tblsize = getdtablesize();
1138 1136 #endif /* else USE_SYSCONF */
1139 1137 #endif /* else _WINDOWS */
1140 1138
1141 1139 if ( tblsize >= FD_SETSIZE ) {
1142 1140 /*
1143 1141 * clamp value so we don't overrun the fd_set structure
1144 1142 */
1145 1143 tblsize = FD_SETSIZE - 1;
1146 1144 }
1147 1145 }
1148 1146
1149 1147 return( tblsize );
1150 1148 }
1151 1149
1152 1150 static int
1153 1151 nsldapi_tv2ms( struct timeval *tv )
1154 1152 {
1155 1153 if ( tv == NULL ) {
1156 1154 return( -1 ); /* infinite timout for poll() */
1157 1155 }
1158 1156
1159 1157 return( tv->tv_sec * 1000 + tv->tv_usec / 1000 );
1160 1158 }
1161 1159
1162 1160
1163 1161 int
1164 1162 nsldapi_iostatus_poll( LDAP *ld, struct timeval *timeout )
1165 1163 {
1166 1164 int rc;
1167 1165 NSLDAPIIOStatus *iosp;
1168 1166
1169 1167 LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_iostatus_poll\n", 0, 0, 0 );
1170 1168
1171 1169 LDAP_MUTEX_LOCK( ld, LDAP_IOSTATUS_LOCK );
1172 1170 iosp = ld->ld_iostatus;
1173 1171
1174 1172 if ( iosp == NULL ||
1175 1173 ( iosp->ios_read_count <= 0 && iosp->ios_read_count <= 0 )) {
1176 1174 rc = 0; /* simulate a timeout */
1177 1175
1178 1176 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_OSNATIVE ) {
1179 1177 #ifdef NSLDAPI_HAVE_POLL
1180 1178
1181 1179 rc = NSLDAPI_POLL( iosp->ios_status.ios_osinfo.ossi_pollfds,
1182 1180 iosp->ios_status.ios_osinfo.ossi_pollfds_size,
1183 1181 nsldapi_tv2ms( timeout ));
1184 1182
1185 1183 #else /* NSLDAPI_HAVE_POLL */
1186 1184
1187 1185 /* two (potentially large) struct copies */
1188 1186 iosp->ios_status.ios_osinfo.ossi_use_readfds
1189 1187 = iosp->ios_status.ios_osinfo.ossi_readfds;
1190 1188 iosp->ios_status.ios_osinfo.ossi_use_writefds
1191 1189 = iosp->ios_status.ios_osinfo.ossi_writefds;
1192 1190
1193 1191 #ifdef HPUX9
1194 1192 rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
1195 1193 (int *)&iosp->ios_status.ios_osinfo.ossi_use_readfds
1196 1194 (int *)&iosp->ios_status.ios_osinfo.ossi_use_writefds,
1197 1195 NULL, timeout );
1198 1196 #else
1199 1197 rc = NSLDAPI_SELECT( nsldapi_get_select_table_size(),
1200 1198 &iosp->ios_status.ios_osinfo.ossi_use_readfds,
1201 1199 &iosp->ios_status.ios_osinfo.ossi_use_writefds,
1202 1200 NULL, timeout );
1203 1201 #endif /* else HPUX9 */
1204 1202 #endif /* else NSLDAPI_HAVE_POLL */
1205 1203
1206 1204 } else if ( iosp->ios_type == NSLDAPI_IOSTATUS_TYPE_CALLBACK ) {
1207 1205 /*
1208 1206 * We always pass the session extended I/O argument to
1209 1207 * the extended poll() callback.
1210 1208 */
1211 1209 rc = ld->ld_extpoll_fn(
1212 1210 iosp->ios_status.ios_cbinfo.cbsi_pollfds,
1213 1211 iosp->ios_status.ios_cbinfo.cbsi_pollfds_size,
1214 1212 nsldapi_tv2ms( timeout ), ld->ld_ext_session_arg );
1215 1213
1216 1214 } else {
1217 1215 LDAPDebug( LDAP_DEBUG_ANY,
1218 1216 "nsldapi_iostatus_poll: unknown I/O type %d\n",
1219 1217 iosp->ios_type, 0, 0 );
1220 1218 rc = 0; /* simulate a timeout (what else to do?) */
1221 1219 }
1222 1220
1223 1221 LDAP_MUTEX_UNLOCK( ld, LDAP_IOSTATUS_LOCK );
1224 1222 return( rc );
1225 1223 }
1226 1224
1227 1225
1228 1226 #ifdef NSLDAPI_HAVE_POLL
1229 1227 /*
1230 1228 * returns 1 if "fd" was added to pollfds.
1231 1229 * returns 1 if some of the bits in "events" were added to pollfds.
1232 1230 * returns 0 if no changes were made.
1233 1231 */
1234 1232 static int
1235 1233 nsldapi_add_to_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1236 1234 short events )
1237 1235 {
1238 1236 int i, openslot;
1239 1237
1240 1238 /* first we check to see if "fd" is already in our pollfds */
1241 1239 openslot = -1;
1242 1240 for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1243 1241 if ( pip->ossi_pollfds[ i ].fd == fd ) {
1244 1242 if (( pip->ossi_pollfds[ i ].events & events )
1245 1243 != events ) {
1246 1244 pip->ossi_pollfds[ i ].events |= events;
1247 1245 return( 1 );
1248 1246 } else {
1249 1247 return( 0 );
1250 1248 }
1251 1249 }
1252 1250 if ( pip->ossi_pollfds[ i ].fd == -1 && openslot == -1 ) {
1253 1251 openslot = i; /* remember for later */
1254 1252 }
1255 1253 }
1256 1254
1257 1255 /*
1258 1256 * "fd" is not currently being poll'd on -- add to array.
1259 1257 * if we need to expand the pollfds array, we do it in increments of
1260 1258 * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
1261 1259 */
1262 1260 if ( openslot == -1 ) {
1263 1261 struct pollfd *newpollfds;
1264 1262
1265 1263 if ( pip->ossi_pollfds_size == 0 ) {
1266 1264 newpollfds = (struct pollfd *)NSLDAPI_MALLOC(
1267 1265 NSLDAPI_POLL_ARRAY_GROWTH
1268 1266 * sizeof( struct pollfd ));
1269 1267 } else {
1270 1268 newpollfds = (struct pollfd *)NSLDAPI_REALLOC(
1271 1269 pip->ossi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
1272 1270 + pip->ossi_pollfds_size)
1273 1271 * sizeof( struct pollfd ));
1274 1272 }
1275 1273 if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
1276 1274 return( 0 );
1277 1275 }
1278 1276 pip->ossi_pollfds = newpollfds;
1279 1277 openslot = pip->ossi_pollfds_size;
1280 1278 pip->ossi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
1281 1279 for ( i = openslot + 1; i < pip->ossi_pollfds_size; ++i ) {
1282 1280 pip->ossi_pollfds[ i ].fd = -1;
1283 1281 pip->ossi_pollfds[ i ].events =
1284 1282 pip->ossi_pollfds[ i ].revents = 0;
1285 1283 }
1286 1284 }
1287 1285 pip->ossi_pollfds[ openslot ].fd = fd;
1288 1286 pip->ossi_pollfds[ openslot ].events = events;
1289 1287 pip->ossi_pollfds[ openslot ].revents = 0;
1290 1288 return( 1 );
1291 1289 }
1292 1290
1293 1291
1294 1292 /*
1295 1293 * returns 1 if any "events" from "fd" were removed from pollfds
1296 1294 * returns 0 of "fd" wasn't in pollfds or if events did not overlap.
1297 1295 */
1298 1296 static int
1299 1297 nsldapi_clear_from_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1300 1298 short events )
1301 1299 {
1302 1300 int i;
1303 1301
1304 1302 for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1305 1303 if ( pip->ossi_pollfds[i].fd == fd ) {
1306 1304 if (( pip->ossi_pollfds[ i ].events & events ) != 0 ) {
1307 1305 pip->ossi_pollfds[ i ].events &= ~events;
1308 1306 if ( pip->ossi_pollfds[ i ].events == 0 ) {
1309 1307 pip->ossi_pollfds[i].fd = -1;
1310 1308 }
1311 1309 return( 1 ); /* events overlap */
1312 1310 } else {
1313 1311 return( 0 ); /* events do not overlap */
1314 1312 }
1315 1313 }
1316 1314 }
1317 1315
1318 1316 return( 0 ); /* "fd" was not found */
1319 1317 }
1320 1318
1321 1319
1322 1320 /*
1323 1321 * returns 1 if any "revents" from "fd" were set in pollfds revents field.
1324 1322 * returns 0 if not.
1325 1323 */
1326 1324 static int
1327 1325 nsldapi_find_in_os_pollfds( int fd, struct nsldapi_os_statusinfo *pip,
1328 1326 short revents )
1329 1327 {
1330 1328 int i;
1331 1329
1332 1330 for ( i = 0; i < pip->ossi_pollfds_size; ++i ) {
1333 1331 if ( pip->ossi_pollfds[i].fd == fd ) {
1334 1332 if (( pip->ossi_pollfds[ i ].revents & revents ) != 0 ) {
1335 1333 return( 1 ); /* revents overlap */
1336 1334 } else {
1337 1335 return( 0 ); /* revents do not overlap */
1338 1336 }
1339 1337 }
1340 1338 }
1341 1339
1342 1340 return( 0 ); /* "fd" was not found */
1343 1341 }
1344 1342 #endif /* NSLDAPI_HAVE_POLL */
1345 1343
1346 1344
1347 1345 /*
1348 1346 * returns 1 if "sb" was added to pollfds.
1349 1347 * returns 1 if some of the bits in "events" were added to pollfds.
1350 1348 * returns 0 if no changes were made.
1351 1349 */
1352 1350 static int
1353 1351 nsldapi_add_to_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
1354 1352 short events )
1355 1353 {
1356 1354 int i, openslot;
1357 1355
1358 1356 /* first we check to see if "sb" is already in our pollfds */
1359 1357 openslot = -1;
1360 1358 for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1361 1359 if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1362 1360 if (( pip->cbsi_pollfds[ i ].lpoll_events & events )
1363 1361 != events ) {
1364 1362 pip->cbsi_pollfds[ i ].lpoll_events |= events;
1365 1363 return( 1 );
1366 1364 } else {
1367 1365 return( 0 );
1368 1366 }
1369 1367 }
1370 1368 if ( pip->cbsi_pollfds[ i ].lpoll_fd == -1 && openslot == -1 ) {
1371 1369 openslot = i; /* remember for later */
1372 1370 }
1373 1371 }
1374 1372
1375 1373 /*
1376 1374 * "sb" is not currently being poll'd on -- add to array.
1377 1375 * if we need to expand the pollfds array, we do it in increments of
1378 1376 * NSLDAPI_POLL_ARRAY_GROWTH (#define near the top of this file).
1379 1377 */
1380 1378 if ( openslot == -1 ) {
1381 1379 LDAP_X_PollFD *newpollfds;
1382 1380
1383 1381 if ( pip->cbsi_pollfds_size == 0 ) {
1384 1382 newpollfds = (LDAP_X_PollFD *)NSLDAPI_MALLOC(
1385 1383 NSLDAPI_POLL_ARRAY_GROWTH
1386 1384 * sizeof( LDAP_X_PollFD ));
1387 1385 } else {
1388 1386 newpollfds = (LDAP_X_PollFD *)NSLDAPI_REALLOC(
1389 1387 pip->cbsi_pollfds, (NSLDAPI_POLL_ARRAY_GROWTH
1390 1388 + pip->cbsi_pollfds_size)
1391 1389 * sizeof( LDAP_X_PollFD ));
1392 1390 }
1393 1391 if ( newpollfds == NULL ) { /* XXXmcs: no way to return err! */
1394 1392 return( 0 );
1395 1393 }
1396 1394 pip->cbsi_pollfds = newpollfds;
1397 1395 openslot = pip->cbsi_pollfds_size;
1398 1396 pip->cbsi_pollfds_size += NSLDAPI_POLL_ARRAY_GROWTH;
1399 1397 for ( i = openslot + 1; i < pip->cbsi_pollfds_size; ++i ) {
1400 1398 pip->cbsi_pollfds[ i ].lpoll_fd = -1;
1401 1399 pip->cbsi_pollfds[ i ].lpoll_socketarg = NULL;
1402 1400 pip->cbsi_pollfds[ i ].lpoll_events =
1403 1401 pip->cbsi_pollfds[ i ].lpoll_revents = 0;
1404 1402 }
1405 1403 }
1406 1404 pip->cbsi_pollfds[ openslot ].lpoll_fd = sb->sb_sd;
1407 1405 pip->cbsi_pollfds[ openslot ].lpoll_socketarg =
1408 1406 sb->sb_ext_io_fns.lbextiofn_socket_arg;
1409 1407 pip->cbsi_pollfds[ openslot ].lpoll_events = events;
1410 1408 pip->cbsi_pollfds[ openslot ].lpoll_revents = 0;
1411 1409 return( 1 );
1412 1410 }
1413 1411
1414 1412
1415 1413 /*
1416 1414 * returns 1 if any "events" from "sb" were removed from pollfds
1417 1415 * returns 0 of "sb" wasn't in pollfds or if events did not overlap.
1418 1416 */
1419 1417 static int
1420 1418 nsldapi_clear_from_cb_pollfds( Sockbuf *sb,
1421 1419 struct nsldapi_cb_statusinfo *pip, short events )
1422 1420 {
1423 1421 int i;
1424 1422
1425 1423 for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1426 1424 if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1427 1425 if (( pip->cbsi_pollfds[ i ].lpoll_events
1428 1426 & events ) != 0 ) {
1429 1427 pip->cbsi_pollfds[ i ].lpoll_events &= ~events;
1430 1428 if ( pip->cbsi_pollfds[ i ].lpoll_events
1431 1429 == 0 ) {
1432 1430 pip->cbsi_pollfds[i].lpoll_fd = -1;
1433 1431 }
1434 1432 return( 1 ); /* events overlap */
1435 1433 } else {
1436 1434 return( 0 ); /* events do not overlap */
1437 1435 }
1438 1436 }
1439 1437 }
1440 1438
1441 1439 return( 0 ); /* "sb" was not found */
1442 1440 }
1443 1441
1444 1442
1445 1443 /*
1446 1444 * returns 1 if any "revents" from "sb" were set in pollfds revents field.
1447 1445 * returns 0 if not.
1448 1446 */
1449 1447 static int
1450 1448 nsldapi_find_in_cb_pollfds( Sockbuf *sb, struct nsldapi_cb_statusinfo *pip,
1451 1449 short revents )
1452 1450 {
1453 1451 int i;
1454 1452
1455 1453 for ( i = 0; i < pip->cbsi_pollfds_size; ++i ) {
1456 1454 if ( NSLDAPI_CB_POLL_MATCH( sb, pip->cbsi_pollfds[ i ] )) {
1457 1455 if (( pip->cbsi_pollfds[ i ].lpoll_revents
1458 1456 & revents ) != 0 ) {
1459 1457 return( 1 ); /* revents overlap */
1460 1458 } else {
1461 1459 return( 0 ); /* revents do not overlap */
1462 1460 }
1463 1461 }
1464 1462 }
1465 1463
1466 1464 return( 0 ); /* "sb" was not found */
1467 1465 }
1468 1466
1469 1467
1470 1468 /*
1471 1469 * Install read and write functions into lber layer / sb
1472 1470 */
1473 1471 int
1474 1472 nsldapi_install_lber_extiofns( LDAP *ld, Sockbuf *sb )
1475 1473 {
1476 1474 struct lber_x_ext_io_fns lberiofns;
1477 1475
1478 1476 memset( &lberiofns, 0, sizeof(struct lber_x_ext_io_fns) );
1479 1477 if ( NULL != sb ) {
1480 1478 lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
1481 1479 lberiofns.lbextiofn_read = ld->ld_extread_fn;
1482 1480 lberiofns.lbextiofn_write = ld->ld_extwrite_fn;
1483 1481 lberiofns.lbextiofn_writev = ld->ld_extwritev_fn;
1484 1482 lberiofns.lbextiofn_socket_arg = ld->ld_ext_session_arg;
1485 1483
1486 1484 if ( ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS,
1487 1485 &lberiofns ) != 0 ) {
1488 1486 return( LDAP_LOCAL_ERROR );
1489 1487 }
1490 1488 }
1491 1489
1492 1490 return( LDAP_SUCCESS );
1493 1491 }
1494 1492
1495 1493
1496 1494 /*
1497 1495 ******************************************************************************
1498 1496 * One struct and several functions to bridge the gap between new extended
1499 1497 * I/O functions that are installed using ldap_set_option( ...,
1500 1498 * LDAP_OPT_EXTIO_FN_PTRS, ... ) and the original "classic" I/O functions
1501 1499 * (installed using LDAP_OPT_IO_FN_PTRS) follow.
1502 1500 *
1503 1501 * Our basic strategy is to use the new extended arg to hold a pointer to a
1504 1502 * structure that contains a pointer to the LDAP * (which contains pointers
1505 1503 * to the old functions so we can call them) as well as a pointer to an
1506 1504 * LBER_SOCKET to hold the socket used by the classic functions (the new
1507 1505 * functions use a simple int for the socket).
1508 1506 */
1509 1507 typedef struct nsldapi_compat_socket_info {
1510 1508 LBER_SOCKET csi_socket;
1511 1509 LDAP *csi_ld;
1512 1510 } NSLDAPICompatSocketInfo;
1513 1511
1514 1512 static int LDAP_CALLBACK
1515 1513 nsldapi_ext_compat_read( int s, void *buf, int len,
1516 1514 struct lextiof_socket_private *arg )
1517 1515 {
1518 1516 NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1519 1517 struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1520 1518
1521 1519 return( iofns->liof_read( csip->csi_socket, buf, len ));
1522 1520 }
1523 1521
1524 1522
1525 1523 static int LDAP_CALLBACK
1526 1524 nsldapi_ext_compat_write( int s, const void *buf, int len,
1527 1525 struct lextiof_socket_private *arg )
1528 1526 {
1529 1527 NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1530 1528 struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1531 1529
1532 1530 return( iofns->liof_write( csip->csi_socket, buf, len ));
1533 1531 }
1534 1532
1535 1533
1536 1534 static int LDAP_CALLBACK
1537 1535 nsldapi_ext_compat_poll( LDAP_X_PollFD fds[], int nfds, int timeout,
1538 1536 struct lextiof_session_private *arg )
1539 1537 {
1540 1538 NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1541 1539 struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1542 1540 fd_set readfds, writefds;
1543 1541 int i, rc, maxfd = 0;
1544 1542 struct timeval tv, *tvp;
1545 1543
1546 1544 /*
1547 1545 * Prepare fd_sets for select()
1548 1546 */
1549 1547 FD_ZERO( &readfds );
1550 1548 FD_ZERO( &writefds );
1551 1549 for ( i = 0; i < nfds; ++i ) {
1552 1550 if ( fds[ i ].lpoll_fd < 0 ) {
1553 1551 continue;
1554 1552 }
1555 1553
1556 1554 if ( fds[ i ].lpoll_fd >= FD_SETSIZE ) {
1557 1555 LDAP_SET_ERRNO( csip->csi_ld, EINVAL );
1558 1556 return( -1 );
1559 1557 }
1560 1558
1561 1559 if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )) {
1562 1560 FD_SET( fds[i].lpoll_fd, &readfds );
1563 1561 }
1564 1562
1565 1563 if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )) {
1566 1564 FD_SET( fds[i].lpoll_fd, &writefds );
1567 1565 }
1568 1566
1569 1567 fds[i].lpoll_revents = 0; /* clear revents */
1570 1568
1571 1569 if ( fds[i].lpoll_fd >= maxfd ) {
1572 1570 maxfd = fds[i].lpoll_fd;
1573 1571 }
1574 1572 }
1575 1573
1576 1574 /*
1577 1575 * select() using callback.
1578 1576 */
1579 1577 ++maxfd;
1580 1578 if ( timeout == -1 ) {
1581 1579 tvp = NULL;
1582 1580 } else {
1583 1581 tv.tv_sec = timeout / 1000;
1584 1582 tv.tv_usec = 1000 * ( timeout - tv.tv_sec * 1000 );
1585 1583 tvp = &tv;
1586 1584 }
1587 1585 rc = iofns->liof_select( maxfd, &readfds, &writefds, NULL, tvp );
1588 1586 if ( rc <= 0 ) { /* timeout or fatal error */
1589 1587 return( rc );
1590 1588 }
1591 1589
1592 1590 /*
1593 1591 * Use info. in fd_sets to populate poll() revents.
1594 1592 */
1595 1593 for ( i = 0; i < nfds; ++i ) {
1596 1594 if ( fds[ i ].lpoll_fd < 0 ) {
1597 1595 continue;
1598 1596 }
1599 1597
1600 1598 if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLIN )
1601 1599 && FD_ISSET( fds[i].lpoll_fd, &readfds )) {
1602 1600 fds[i].lpoll_revents |= LDAP_X_POLLIN;
1603 1601 }
1604 1602
1605 1603 if ( 0 != ( fds[i].lpoll_events & LDAP_X_POLLOUT )
1606 1604 && FD_ISSET( fds[i].lpoll_fd, &writefds )) {
1607 1605 fds[i].lpoll_revents |= LDAP_X_POLLOUT;
1608 1606 }
1609 1607
1610 1608 /* XXXmcs: any other cases to deal with? LDAP_X_POLLERR? */
1611 1609 }
1612 1610
1613 1611 return( rc );
1614 1612 }
1615 1613
1616 1614
1617 1615 static LBER_SOCKET
1618 1616 nsldapi_compat_socket( LDAP *ld, int secure, int domain, int type,
1619 1617 int protocol )
1620 1618 {
1621 1619 int s;
1622 1620
1623 1621 s = ld->ld_io_fns_ptr->liof_socket( domain, type, protocol );
1624 1622
1625 1623 if ( s >= 0 ) {
1626 1624 char *errmsg = NULL;
1627 1625
1628 1626 #ifdef NSLDAPI_HAVE_POLL
1629 1627 if ( ld->ld_io_fns_ptr->liof_select != NULL
1630 1628 && s >= FD_SETSIZE ) {
1631 1629 errmsg = dgettext(TEXT_DOMAIN,
1632 1630 "can't use socket >= FD_SETSIZE");
1633 1631 }
1634 1632 #elif !defined(_WINDOWS) /* not on Windows and do not have poll() */
1635 1633 if ( s >= FD_SETSIZE ) {
1636 1634 errmsg = "can't use socket >= FD_SETSIZE";
1637 1635 }
1638 1636 #endif
1639 1637
1640 1638 if ( NULL == errmsg && secure &&
1641 1639 ld->ld_io_fns_ptr->liof_ssl_enable( s ) < 0 ) {
1642 1640 errmsg = dgettext(TEXT_DOMAIN,
1643 1641 "failed to enable secure mode");
1644 1642 }
1645 1643
1646 1644 if ( NULL != errmsg ) {
1647 1645 if ( NULL == ld->ld_io_fns_ptr->liof_close ) {
1648 1646 nsldapi_os_closesocket( s );
1649 1647 } else {
1650 1648 ld->ld_io_fns_ptr->liof_close( s );
1651 1649 }
1652 1650 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL,
1653 1651 nsldapi_strdup( errmsg ));
1654 1652 return( -1 );
1655 1653 }
1656 1654 }
1657 1655
1658 1656 return( s );
1659 1657 }
1660 1658
1661 1659
1662 1660 /*
1663 1661 * Note: timeout is ignored because we have no way to pass it via
1664 1662 * the old I/O callback interface.
1665 1663 */
1666 1664 static int LDAP_CALLBACK
1667 1665 nsldapi_ext_compat_connect( const char *hostlist, int defport, int timeout,
1668 1666 unsigned long options, struct lextiof_session_private *sessionarg,
1669 1667 struct lextiof_socket_private **socketargp
1670 1668 #ifdef _SOLARIS_SDK
1671 1669 , void **not_used )
1672 1670 #else
1673 1671 )
1674 1672 #endif /* _SOLARIS_SDK */
1675 1673 {
1676 1674 NSLDAPICompatSocketInfo *defcsip;
1677 1675 struct ldap_io_fns *iofns;
1678 1676 int s, secure;
1679 1677 NSLDAPI_SOCKET_FN *socketfn;
1680 1678 NSLDAPI_IOCTL_FN *ioctlfn;
1681 1679 NSLDAPI_CONNECT_WITH_TO_FN *connectwithtofn;
1682 1680 NSLDAPI_CONNECT_FN *connectfn;
1683 1681 NSLDAPI_CLOSE_FN *closefn;
1684 1682
1685 1683 defcsip = (NSLDAPICompatSocketInfo *)sessionarg;
1686 1684 iofns = defcsip->csi_ld->ld_io_fns_ptr;
1687 1685
1688 1686 if ( 0 != ( options & LDAP_X_EXTIOF_OPT_SECURE )) {
1689 1687 if ( NULL == iofns->liof_ssl_enable ) {
1690 1688 LDAP_SET_ERRNO( defcsip->csi_ld, EINVAL );
1691 1689 return( -1 );
1692 1690 }
1693 1691 secure = 1;
1694 1692 } else {
1695 1693 secure = 0;
1696 1694 }
1697 1695
1698 1696 socketfn = ( iofns->liof_socket == NULL ) ?
1699 1697 nsldapi_os_socket : nsldapi_compat_socket;
1700 1698 ioctlfn = ( iofns->liof_ioctl == NULL ) ?
1701 1699 nsldapi_os_ioctl : (NSLDAPI_IOCTL_FN *)(iofns->liof_ioctl);
1702 1700 if ( NULL == iofns->liof_connect ) {
1703 1701 connectwithtofn = nsldapi_os_connect_with_to;
1704 1702 connectfn = NULL;
1705 1703 } else {
1706 1704 connectwithtofn = NULL;
1707 1705 connectfn = iofns->liof_connect;
1708 1706 }
1709 1707 closefn = ( iofns->liof_close == NULL ) ?
1710 1708 nsldapi_os_closesocket : iofns->liof_close;
1711 1709
1712 1710 s = nsldapi_try_each_host( defcsip->csi_ld, hostlist, defport,
1713 1711 secure, socketfn, ioctlfn, connectwithtofn,
1714 1712 connectfn, closefn );
1715 1713
1716 1714 if ( s >= 0 ) {
1717 1715 NSLDAPICompatSocketInfo *csip;
1718 1716
1719 1717 if (( csip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
1720 1718 sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
1721 1719 (*closefn)( s );
1722 1720 LDAP_SET_LDERRNO( defcsip->csi_ld, LDAP_NO_MEMORY,
1723 1721 NULL, NULL );
1724 1722 return( -1 );
1725 1723 }
1726 1724
1727 1725 csip->csi_socket = s;
1728 1726 csip->csi_ld = defcsip->csi_ld;
1729 1727 *socketargp = (void *)csip;
1730 1728
1731 1729 /*
1732 1730 * We always return 1, which is a valid but not unique socket
1733 1731 * (file descriptor) number. The extended I/O functions only
1734 1732 * require that the combination of the void *arg and the int
1735 1733 * socket be unique. Since we allocate the
1736 1734 * NSLDAPICompatSocketInfo that we assign to arg, we meet
1737 1735 * that requirement.
1738 1736 */
1739 1737 s = 1;
1740 1738 }
1741 1739
1742 1740 return( s );
1743 1741 }
1744 1742
1745 1743
1746 1744 static int LDAP_CALLBACK
1747 1745 nsldapi_ext_compat_close( int s, struct lextiof_socket_private *arg )
1748 1746 {
1749 1747 NSLDAPICompatSocketInfo *csip = (NSLDAPICompatSocketInfo *)arg;
1750 1748 struct ldap_io_fns *iofns = csip->csi_ld->ld_io_fns_ptr;
1751 1749 int rc;
1752 1750
1753 1751 rc = iofns->liof_close( csip->csi_socket );
1754 1752
1755 1753 NSLDAPI_FREE( csip );
1756 1754
1757 1755 return( rc );
1758 1756 }
1759 1757
1760 1758 /*
1761 1759 * Install the I/O functions.
1762 1760 * Return an LDAP error code (LDAP_SUCCESS if all goes well).
1763 1761 */
1764 1762 int
1765 1763 nsldapi_install_compat_io_fns( LDAP *ld, struct ldap_io_fns *iofns )
1766 1764 {
1767 1765 NSLDAPICompatSocketInfo *defcsip;
1768 1766
1769 1767 if (( defcsip = (NSLDAPICompatSocketInfo *)NSLDAPI_CALLOC( 1,
1770 1768 sizeof( NSLDAPICompatSocketInfo ))) == NULL ) {
1771 1769 return( LDAP_NO_MEMORY );
1772 1770 }
1773 1771
1774 1772 defcsip->csi_socket = -1;
1775 1773 defcsip->csi_ld = ld;
1776 1774
1777 1775 if ( ld->ld_io_fns_ptr != NULL ) {
1778 1776 (void)memset( (char *)ld->ld_io_fns_ptr, 0,
1779 1777 sizeof( struct ldap_io_fns ));
1780 1778 } else if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_CALLOC(
1781 1779 1, sizeof( struct ldap_io_fns ))) == NULL ) {
1782 1780 NSLDAPI_FREE( defcsip );
1783 1781 return( LDAP_NO_MEMORY );
1784 1782 }
1785 1783
1786 1784 /* struct copy */
1787 1785 *(ld->ld_io_fns_ptr) = *iofns;
1788 1786
1789 1787 ld->ld_extio_size = LBER_X_EXTIO_FNS_SIZE;
1790 1788 ld->ld_ext_session_arg = defcsip;
1791 1789 ld->ld_extread_fn = nsldapi_ext_compat_read;
1792 1790 ld->ld_extwrite_fn = nsldapi_ext_compat_write;
1793 1791 ld->ld_extpoll_fn = nsldapi_ext_compat_poll;
1794 1792 ld->ld_extconnect_fn = nsldapi_ext_compat_connect;
1795 1793 ld->ld_extclose_fn = nsldapi_ext_compat_close;
1796 1794
1797 1795 return( nsldapi_install_lber_extiofns( ld, ld->ld_sbp ));
1798 1796 }
1799 1797 /*
1800 1798 * end of compat I/O functions
1801 1799 ******************************************************************************
1802 1800 */
1803 1801 #ifdef _SOLARIS_SDK
1804 1802 /*
1805 1803 * _ns_gethostbyaddr is a helper function for the ssl layer so that
1806 1804 * it can use the ldap layer's gethostbyaddr resolver.
1807 1805 */
1808 1806
1809 1807 LDAPHostEnt *
1810 1808 _ns_gethostbyaddr(LDAP *ld, const char *addr, int length, int type,
1811 1809 LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
1812 1810 void *extradata)
1813 1811 {
1814 1812 if (ld == NULL || ld->ld_dns_gethostbyaddr_fn == NULL)
1815 1813 return (NULL);
1816 1814 return (ld->ld_dns_gethostbyaddr_fn(addr, length, type,
1817 1815 result, buffer, buflen, statusp, extradata));
1818 1816 }
1819 1817
1820 1818 #endif /* _SOLARIS_SDK */
1821 1819
1822 1820
↓ open down ↓ |
1492 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX