os-ip.c 7.79 KB
Newer Older
1
/* os-ip.c -- platform-specific TCP & UDP related code */
2
/* $OpenLDAP$ */
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 1998-2008 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
 * Portions Copyright 1999 Lars Uffmann.
7
 * All rights reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
 *
9
10
11
12
13
14
15
16
17
18
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
19
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
20
21
22
/* Significant additional contributors include:
 *    Lars Uffman
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
23

Kurt Zeilenga's avatar
Kurt Zeilenga committed
24
#include "portable.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
26

#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
27
28

#include <ac/stdlib.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
29

Kurt Zeilenga's avatar
Kurt Zeilenga committed
30
31
32
33
34
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
35

Kurt Zeilenga's avatar
Kurt Zeilenga committed
36
37
38
#ifdef HAVE_IO_H
#include <io.h>
#endif /* HAVE_IO_H */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
39

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
40
41
42
43
#if defined( HAVE_SYS_FILIO_H )
#include <sys/filio.h>
#elif defined( HAVE_SYS_IOCTL_H )
#include <sys/ioctl.h>
44
45
#endif

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
46
#include "ldap-int.h"
47

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
48
int ldap_int_tblsize = 0;
49

50
51

int
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
52
53
ldap_connect_to_host( Sockbuf *sb, const char *host, unsigned long address,
	int port, int async )
54
/*
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
55
56
57
58
59
 * if host == NULL, connect using address
 * "address" and "port" must be in network byte order
 * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
 * async is only used ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS (non-0 means don't wait for connect)
 * XXX async is not used yet!
60
61
 */
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	int			rc, i;
	ber_socket_t s = AC_SOCKET_INVALID;
	int			connected, use_hp;
	struct sockaddr_in	sin;
	struct hostent		*hp = NULL;
#ifdef notyet
	ioctl_t			status;	/* for ioctl call */
#endif /* notyet */
   
   	/* buffers for ldap_pvt_gethostbyname_a */
   	struct hostent		he_buf;
   	int			local_h_errno;
   	char   			*ha_buf=NULL;
#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
   
	Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
	    ( host == NULL ) ? "(by address)" : host, (int) ntohs( (short) port ), 0 );

	connected = use_hp = 0;

	if ( host != NULL ) {
	    address = inet_addr( host );
	    /* This was just a test for -1 until OSF1 let inet_addr return
	       unsigned int, which is narrower than 'unsigned long address' */
	    if ( address == 0xffffffff || address == (unsigned long) -1 ) {
		if ( ( ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
			&hp, &local_h_errno) < 0) || (hp==NULL))
		{
90
#ifdef HAVE_WINSOCK
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
91
			errno = WSAGetLastError();
92
#else
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
93
			errno = EHOSTUNREACH;	/* not exactly right, but... */
94
#endif
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
95
			DO_RETURN( -1 );
96
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
97
98
		use_hp = 1;
	    }
99
100
	}

101
	rc = -1;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
	for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
		if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
			DO_RETURN( -1 );
		}
#ifdef notyet
		status = 1;
		if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
			Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
			    s, 0, 0 );
		}
#endif /* notyet */
		(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
		sin.sin_family = AF_INET;
		sin.sin_port = port;
		SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
		    ( use_hp ? (char *) hp->h_addr_list[ i ] :
		    (char *) &address ), sizeof( sin.sin_addr.s_addr) );

		if ( connect( s, (struct sockaddr *)&sin,
		    sizeof( struct sockaddr_in )) >= 0 ) {
			connected = 1;
			rc = 0;
124
			break;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
125
		} else {
126
#ifdef HAVE_WINSOCK
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
		        errno = WSAGetLastError();
#endif
#ifdef notyet
#ifdef EAGAIN
			if ( errno == EINPROGRESS || errno == EAGAIN ) {
#else /* EAGAIN */
			if ( errno == EINPROGRESS ) {
#endif /* EAGAIN */
				Debug( LDAP_DEBUG_TRACE,
					"connect would block...\n", 0, 0, 0 );
				rc = -2;
				break;
			}
#endif /* notyet */

#ifdef LDAP_DEBUG		
			if ( ldap_debug & LDAP_DEBUG_TRACE ) {
				perror( (char *)inet_ntoa( sin.sin_addr ));
			}
146
#endif
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
147
148
149
150
			tcp_close( s );
			if ( !use_hp ) {
				break;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
151
152
153
		}
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
154
	ber_pvt_sb_set_desc( sb, s );		
155

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
156
	if ( connected ) {
157
	   
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
158
159
160
161
162
#ifdef notyet
		status = 0;
		if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
			Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
			    s, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
163
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
164
#endif /* notyet */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
165

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
166
167
168
		Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
		    s, (char *) inet_ntoa( sin.sin_addr ), 0 );
	}
169

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
170
171
	DO_RETURN( rc );
}
172
   
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
173
#undef DO_RETURN
174

Kurt Zeilenga's avatar
Kurt Zeilenga committed
175

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
176
177
178
179
void
ldap_close_connection( Sockbuf *sb )
{
	ber_pvt_sb_close( sb );
180
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
181

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
182
183

#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
184
char *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
185
ldap_host_connected_to( Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
186
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
187
188
189
190
191
192
193
194
195
196
197
198
199
	struct hostent		*hp;
	char			*p;
	int			len;
	struct sockaddr_in	sin;

   	/* buffers for gethostbyaddr_r */
   	struct hostent		he_buf;
        int			local_h_errno;
   	char			*ha_buf=NULL;
#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
   
	(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
	len = sizeof( sin );
200

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
201
	if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
202
203
204
205
206
207
208
209
		return( NULL );
	}

	/*
	 * do a reverse lookup on the addr to get the official hostname.
	 * this is necessary for kerberos to work right, since the official
	 * hostname is used as the kerberos instance.
	 */
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
210
211
212
213
	if ((ldap_pvt_gethostbyaddr_a( (char *) &sin.sin_addr,
		sizeof( sin.sin_addr ), 
		AF_INET, &he_buf, &ha_buf,
		&hp,&local_h_errno ) ==0 ) && (hp != NULL) )
214
	{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
215
216
217
		if ( hp->h_name != NULL ) {
			char *host = LDAP_STRDUP( hp->h_name );   
			DO_RETURN( host );
218
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
219
220
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
221
	DO_RETURN( NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
222
}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
223
224
225
#undef DO_RETURN   
   
#endif /* HAVE_KERBEROS || HAVE_TLS */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
226
227


Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
228
/* for UNIX */
229
struct selectinfo {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
230
231
232
233
	fd_set	si_readfds;
	fd_set	si_writefds;
	fd_set	si_use_readfds;
	fd_set	si_use_writefds;
234
};
Kurt Zeilenga's avatar
Kurt Zeilenga committed
235

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
236

Kurt Zeilenga's avatar
Kurt Zeilenga committed
237
void
238
ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
239
240
241
242
{
	struct selectinfo	*sip;

	sip = (struct selectinfo *)ld->ld_selectinfo;
243
	
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
244
245
	if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) {
		FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
246
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
247
248
249
250
}


void
251
ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
252
253
254
255
256
{
	struct selectinfo	*sip;

	sip = (struct selectinfo *)ld->ld_selectinfo;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
257
258
	if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) {
		FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
259
260
261
262
263
	}
}


void
264
ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
265
266
267
268
269
{
	struct selectinfo	*sip;

	sip = (struct selectinfo *)ld->ld_selectinfo;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
270
271
	FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds );
	FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
272
273
274
275
}


int
276
ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
277
278
279
280
281
{
	struct selectinfo	*sip;

	sip = (struct selectinfo *)ld->ld_selectinfo;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
282
	return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds ));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
283
284
285
286
}


int
287
ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
288
289
290
291
292
{
	struct selectinfo	*sip;

	sip = (struct selectinfo *)ld->ld_selectinfo;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
293
	return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds ));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
294
295
296
297
}


void *
298
ldap_new_select_info( void )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
299
300
301
{
	struct selectinfo	*sip;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
302
303
304
305
306
	if (( sip = (struct selectinfo *)LDAP_CALLOC( 1,
	    sizeof( struct selectinfo ))) != NULL ) {
		FD_ZERO( &sip->si_readfds );
		FD_ZERO( &sip->si_writefds );
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
307
308
309
310
311
312

	return( (void *)sip );
}


void
313
ldap_free_select_info( void *sip )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
314
{
315
	LDAP_FREE( sip );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
316
317
318
}


Hallvard Furuseth's avatar
Hallvard Furuseth committed
319
320
void
ldap_int_ip_init( void )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
321
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
322
	int tblsize;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
323
#if defined( HAVE_SYSCONF )
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
324
	tblsize = sysconf( _SC_OPEN_MAX );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
325
#elif defined( HAVE_GETDTABLESIZE )
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
326
	tblsize = getdtablesize();
327
#else
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
328
	tblsize = FD_SETSIZE;
329
330
331
#endif /* !USE_SYSCONF */

#ifdef FD_SETSIZE
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
332
333
334
	if( tblsize > FD_SETSIZE )
		tblsize = FD_SETSIZE;
#endif	/* FD_SETSIZE*/
Hallvard Furuseth's avatar
Hallvard Furuseth committed
335
336
337
338
339
	ldap_int_tblsize = tblsize;
}


int
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
340
do_ldap_select( LDAP *ld, struct timeval *timeout )
Hallvard Furuseth's avatar
Hallvard Furuseth committed
341
342
343
{
	struct selectinfo	*sip;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
344
	Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
Hallvard Furuseth's avatar
Hallvard Furuseth committed
345

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
346
347
	if ( ldap_int_tblsize == 0 )
		ldap_int_ip_init();
Kurt Zeilenga's avatar
Kurt Zeilenga committed
348
349
350
351
352

	sip = (struct selectinfo *)ld->ld_selectinfo;
	sip->si_use_readfds = sip->si_readfds;
	sip->si_use_writefds = sip->si_writefds;
	
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
353
354
355
	return( select( ldap_int_tblsize,
	                &sip->si_use_readfds, &sip->si_use_writefds,
	                NULL, timeout ));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
356
}