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