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