]> git.sur5r.net Git - openldap/blob - libraries/libldap/os-ip.c
Updates for MSVC 5.0. Fix libraries names to be ol{ber,dap,..}32.lib.
[openldap] / libraries / libldap / os-ip.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*  Portions
6  *  Copyright (c) 1995 Regents of the University of Michigan.
7  *  All rights reserved.
8  *
9  *  os-ip.c -- platform-specific TCP & UDP related code
10  */
11
12 #include "portable.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16
17 #include <ac/errno.h>
18 #include <ac/socket.h>
19 #include <ac/string.h>
20 #include <ac/time.h>
21 #include <ac/unistd.h>
22
23 #ifdef HAVE_IO_H
24 #include <io.h>
25 #endif /* HAVE_IO_H */
26
27 #if defined( HAVE_SYS_FILIO_H )
28 #include <sys/filio.h>
29 #elif defined( HAVE_SYS_IOCTL_H )
30 #include <sys/ioctl.h>
31 #endif
32
33 #include "ldap-int.h"
34
35 int
36 ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
37         int port, int async )
38 /*
39  * if host == NULL, connect using address
40  * "address" and "port" must be in network byte order
41  * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
42  * async is only used ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS (non-0 means don't wait for connect)
43  * XXX async is not used yet!
44  */
45 {
46         int                     rc, i, s = 0;
47         int                     connected, use_hp;
48         struct sockaddr_in      sin;
49         struct hostent          *hp = NULL;
50 #ifdef notyet
51 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
52         int                     status; /* for ioctl call */
53 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
54 #endif /* notyet */
55    
56         /* buffers for ldap_pvt_gethostbyname_a */
57         struct hostent          he_buf;
58         int                     local_h_errno;
59         char                    *ha_buf=NULL;
60 #define DO_RETURN(x) if (ha_buf) free(ha_buf); return (x);
61    
62         Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
63             ( host == NULL ) ? "(by address)" : host, (int) ntohs( (short) port ), 0 );
64
65         connected = use_hp = 0;
66
67         if ( host != NULL ) {
68             address = inet_addr( host );
69             /* This was just a test for -1 until OSF1 let inet_addr return
70                unsigned int, which is narrower than 'unsigned long address' */
71             if ( address == 0xffffffff || address == (unsigned long) -1 ) {
72                 if ( ( ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
73                         &hp, &local_h_errno) < 0) || (hp==NULL))
74                 {
75 #ifdef HAVE_WINSOCK
76                         errno = WSAGetLastError();
77 #else
78                         errno = EHOSTUNREACH;   /* not exactly right, but... */
79 #endif
80                         DO_RETURN( -1 );
81                 }
82                 use_hp = 1;
83             }
84         }
85
86         rc = -1;
87         for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
88                 if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
89                         DO_RETURN( -1 );
90                 }
91 #ifdef notyet
92 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
93                 status = 1;
94                 if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
95                         Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
96                             s, 0, 0 );
97                 }
98 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
99 #endif /* notyet */
100                 (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
101                 sin.sin_family = AF_INET;
102                 sin.sin_port = port;
103                 SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
104                     ( use_hp ? (char *) hp->h_addr_list[ i ] :
105                     (char *) &address ), sizeof( sin.sin_addr.s_addr) );
106
107                 if ( connect( s, (struct sockaddr *)&sin,
108                     sizeof( struct sockaddr_in )) >= 0 ) {
109                         connected = 1;
110                         rc = 0;
111                         break;
112                 } else {
113 #ifdef HAVE_WINSOCK
114                         errno = WSAGetLastError();
115 #endif
116 #ifdef notyet
117 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
118 #ifdef EAGAIN
119                         if ( errno == EINPROGRESS || errno == EAGAIN ) {
120 #else /* EAGAIN */
121                         if ( errno == EINPROGRESS ) {
122 #endif /* EAGAIN */
123                                 Debug( LDAP_DEBUG_TRACE,
124                                         "connect would block...\n", 0, 0, 0 );
125                                 rc = -2;
126                                 break;
127                         }
128 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
129 #endif /* notyet */
130
131 #ifdef LDAP_DEBUG               
132                         if ( ldap_debug & LDAP_DEBUG_TRACE ) {
133                                 perror( (char *)inet_ntoa( sin.sin_addr ));
134                         }
135 #endif
136                         tcp_close( s );
137                         if ( !use_hp ) {
138                                 break;
139                         }
140                 }
141         }
142
143         sb->sb_sd = s;
144
145         if ( connected ) {
146 #ifdef notyet
147 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
148                 status = 0;
149                 if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
150                         Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
151                             s, 0, 0 );
152                 }
153 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
154 #endif /* notyet */
155
156                 Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
157                     s, (char *) inet_ntoa( sin.sin_addr ), 0 );
158         }
159
160         DO_RETURN( rc );
161         
162         
163 }
164    
165 #undef DO_RETURN
166
167
168 void
169 ldap_close_connection( Sockbuf *sb )
170 {
171     tcp_close( sb->sb_sd );
172 }
173
174
175 #ifdef HAVE_KERBEROS
176 char *
177 ldap_host_connected_to( Sockbuf *sb )
178 {
179         struct hostent          *hp;
180         char                    *p;
181         int                     len;
182         struct sockaddr_in      sin;
183
184         /* buffers for gethostbyaddr_r */
185         struct hostent          he_buf;
186         int                     local_h_errno;
187         char                    *ha_buf=NULL;
188 #define DO_RETURN(x) if (ha_buf) free(ha_buf); return (x);
189    
190         (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
191         len = sizeof( sin );
192         if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
193                 return( NULL );
194         }
195
196         /*
197          * do a reverse lookup on the addr to get the official hostname.
198          * this is necessary for kerberos to work right, since the official
199          * hostname is used as the kerberos instance.
200          */
201         if ((ldap_pvt_gethostbyaddr_a( (char *) &sin.sin_addr,
202                 sizeof( sin.sin_addr ), 
203                 AF_INET, &he_buf, &ha_buf,
204                 &hp,&local_h_errno ) ==0 ) && (hp != NULL) )
205         {
206                 if ( hp->h_name != NULL ) {
207                         DO_RETURN( strdup( hp->h_name ));
208                 }
209         }
210
211         DO_RETURN( NULL );
212 }
213 #undef DO_RETURN   
214    
215 #endif /* HAVE_KERBEROS */
216
217
218 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
219 /* for UNIX */
220 struct selectinfo {
221         fd_set  si_readfds;
222         fd_set  si_writefds;
223         fd_set  si_use_readfds;
224         fd_set  si_use_writefds;
225 };
226
227
228 void
229 ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
230 {
231         struct selectinfo       *sip;
232
233         sip = (struct selectinfo *)ld->ld_selectinfo;
234
235         if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
236                 FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
237         }
238 }
239
240
241 void
242 ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
243 {
244         struct selectinfo       *sip;
245
246         sip = (struct selectinfo *)ld->ld_selectinfo;
247
248         if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
249                 FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
250         }
251 }
252
253
254 void
255 ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
256 {
257         struct selectinfo       *sip;
258
259         sip = (struct selectinfo *)ld->ld_selectinfo;
260
261         FD_CLR( (u_int) sb->sb_sd, &sip->si_writefds );
262         FD_CLR( (u_int) sb->sb_sd, &sip->si_readfds );
263 }
264
265
266 int
267 ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
268 {
269         struct selectinfo       *sip;
270
271         sip = (struct selectinfo *)ld->ld_selectinfo;
272
273         return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
274 }
275
276
277 int
278 ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
279 {
280         struct selectinfo       *sip;
281
282         sip = (struct selectinfo *)ld->ld_selectinfo;
283
284         return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
285 }
286
287
288 void *
289 ldap_new_select_info( void )
290 {
291         struct selectinfo       *sip;
292
293         if (( sip = (struct selectinfo *)calloc( 1,
294             sizeof( struct selectinfo ))) != NULL ) {
295                 FD_ZERO( &sip->si_readfds );
296                 FD_ZERO( &sip->si_writefds );
297         }
298
299         return( (void *)sip );
300 }
301
302
303 void
304 ldap_free_select_info( void *sip )
305 {
306         free( sip );
307 }
308
309
310 int
311 do_ldap_select( LDAP *ld, struct timeval *timeout )
312 {
313         struct selectinfo       *sip;
314         static int              tblsize;
315
316         Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
317
318         if ( tblsize == 0 ) {
319 #if defined( HAVE_SYSCONF )
320                 tblsize = sysconf( _SC_OPEN_MAX );
321 #elif defined( HAVE_GETDTABLESIZE )
322                 tblsize = getdtablesize();
323 #else
324                 tblsize = FD_SETSIZE;
325 #endif /* !USE_SYSCONF */
326
327 #ifdef FD_SETSIZE
328                 if( tblsize > FD_SETSIZE ) {
329                         tblsize = FD_SETSIZE;
330                 }
331 #endif  /* FD_SETSIZE*/
332         }
333
334         sip = (struct selectinfo *)ld->ld_selectinfo;
335         sip->si_use_readfds = sip->si_readfds;
336         sip->si_use_writefds = sip->si_writefds;
337         
338         return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
339             NULL, timeout ));
340 }
341 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */