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