]> git.sur5r.net Git - openldap/blob - servers/ldapd/main.c
abcbf2c4d8912097b7392032dc050c86e60199ce
[openldap] / servers / ldapd / main.c
1 /*
2  * Copyright (c) 1990-1996 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 /*
13  * Some code fragments to run from inetd stolen from the University
14  * of Minnesota gopher distribution, which had this copyright on it:
15  *
16  * Part of the Internet Gopher program, copyright (C) 1991
17  * University of Minnesota Microcomputer Workstation and Networks Center
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/signal.h>
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/syslog.h>
28 #include <ac/time.h>
29 #include <ac/unistd.h>
30 #include <ac/wait.h>
31
32 #ifdef LDAP_PROCTITLE
33 #include <ac/setproctitle.h>
34 #endif
35
36 #include <quipu/commonarg.h>
37 #include <quipu/ds_error.h>
38
39 #include "lber.h"
40 #include "ldap.h"
41 #include "common.h"
42
43 #ifdef HAVE_TCPD
44 #include <tcpd.h>
45
46 int allow_severity = LOG_INFO;
47 int deny_severity = LOG_NOTICE;
48 #endif /* TCP_WRAPPERS */
49
50 void log_and_exit();
51 static set_socket();
52 static do_queries();
53 static RETSIGTYPE wait4child();
54 #ifdef LDAP_CONNECTIONLESS
55 static udp_init();
56 #endif
57
58 #ifdef LDAP_DEBUG
59 int     ldap_debug;
60 #endif
61 int     version;
62 #ifdef LDAP_COMPAT
63 int     ldap_compat;
64 #endif
65 int     dosyslog;
66 int     do_tcp = 1;
67 #ifdef LDAP_CONNECTIONLESS
68 int     do_udp = 0;
69 #endif
70 int     idletime = DEFAULT_TIMEOUT;
71 int     referral_connection_timeout = DEFAULT_REFERRAL_TIMEOUT;
72 struct timeval  conn_start_tv;
73 #ifdef HAVE_KERBEROS
74 char    *krb_ldap_service = "ldapserver";
75 char    *krb_x500_service = "x500dsa";
76 char    *krb_x500_instance;
77 char    *krb_x500_nonce;
78 char    *kerberos_keyfile;
79 #endif
80
81 int     dtblsize;
82 int     RunFromInetd = 0;
83
84 extern char Versionstr[];
85
86 static usage( name )
87 char    *name;
88 {
89         fprintf( stderr, "usage: %s [-d debuglvl] [-p port] [-l] [-c dsa] [-r referraltimeout]", name );
90 #ifdef LDAP_CONNECTIONLESS
91         fprintf( stderr, " [ -U | -t timeout ]" );
92 #else
93         fprintf( stderr, " [ -t timeout ]" );
94 #endif
95         fprintf( stderr, " [-I]" );
96 #ifdef HAVE_KERBEROS
97         fprintf( stderr, " [-i dsainstance]" );
98 #endif
99         fprintf( stderr, "\n" );
100 }
101
102 main (argc, argv)
103 int     argc;
104 char    **argv;
105 {
106         int                     tcps, ns;
107 #ifdef LDAP_CONNECTIONLESS
108         int                     udps;
109 #endif
110         int                     myport = LDAP_PORT;
111         int                     i, pid, socktype;
112         char                    *myname;
113         fd_set                  readfds;
114         struct hostent          *hp;
115         struct sockaddr_in      from;
116         int                     len;
117         int                     dsapargc;
118         char                    **dsapargv;
119         RETSIGTYPE                      wait4child();
120 #ifdef LDAP_PROCTITLE
121         char                    title[80];
122 #endif
123         extern char             *optarg;
124         extern int              optind;
125
126 #ifdef VMS
127         /* Pick up socket from inetd-type server on VMS */
128         if ( (ns = socket_from_server( NULL )) > 0 )
129                 RunFromInetd = 1;
130 #else
131         /* Socket from inetd is usually 0 */
132         ns = 0;
133 #endif
134
135         /* for dsap_init */
136         if ( (dsapargv = (char **) malloc( 4 * sizeof(char *) )) == NULL ) {
137                 perror( "malloc" );
138                 exit( 1 );
139         }
140         dsapargv[0] = argv[0];
141         dsapargv[1] = 0;
142         dsapargv[2] = 0;
143         dsapargv[3] = 0;
144         dsapargc = 1;
145 #ifdef HAVE_KERBEROS
146         kerberos_keyfile = "";
147 #endif
148
149         /* process command line arguments */
150         while ( (i = getopt( argc, argv, "d:lp:f:i:c:r:t:IuU" )) != EOF ) {
151                 switch ( i ) {
152                 case 'c':       /* specify dsa to contact */
153                         dsapargv[1] = "-call";
154                         dsapargv[2] = strdup( optarg );
155                         dsapargc = 3;
156                         break;
157
158                 case 'd':       /* turn on debugging */
159 #ifdef LDAP_DEBUG
160                         ldap_debug = atoi( optarg );
161                         if ( ldap_debug & LDAP_DEBUG_PACKETS )
162                                 lber_debug = ldap_debug;
163 #else
164                         fprintf( stderr, "Not compiled with -DLDAP_DEBUG!\n" );
165 #endif
166                         break;
167
168                 case 'l':       /* do syslogging */
169                         dosyslog = 1;
170                         break;
171
172                 case 'p':       /* specify port number */
173                         myport = atoi( optarg );
174                         break;
175
176                 case 'r':       /* timeout for referral connections */
177                         referral_connection_timeout = atoi( optarg );
178                         break;
179
180                 case 't':       /* timeout for idle connections */
181                         idletime = atoi( optarg );
182                         break;
183
184 #ifdef HAVE_KERBEROS
185                 case 'f':       /* kerberos key file */
186                         kerberos_keyfile = strdup( optarg );
187                         break;
188
189                 case 'i':       /* x500 dsa kerberos instance */
190                         if ( krb_x500_instance != NULL )
191                                 free( krb_x500_instance );
192                         krb_x500_instance = strdup( optarg );
193                         break;
194 #endif
195
196                 case 'I':       /* Run from inetd */
197                         RunFromInetd = 1;
198                         break;
199
200 #ifdef LDAP_CONNECTIONLESS
201                 case 'U':       /* UDP only (no TCP) */
202                         do_tcp = 0;
203                         do_udp = 1;
204                         break;
205
206 #ifdef NOTYET
207                 case 'u':       /* allow UDP requests (CLDAP) */
208                         do_udp = 1;
209                         break;
210 #endif /* NOTYET */
211
212 #endif /* LDAP_CONNECTIONLESS */
213
214                 default:
215                         usage( argv[0] );
216                         exit( 1 );
217                 }
218         }
219
220         if ( optind < argc ) {
221                 usage( argv[ 0 ] );
222                 exit( 1 );
223         }
224
225 #ifdef LDAP_CONNECTIONLESS
226         if ( do_udp && !do_tcp && idletime != DEFAULT_TIMEOUT ) {
227                 usage( argv[ 0 ] );
228                 exit( 1 );
229         }
230 #endif
231
232         Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
233
234 #ifdef HAVE_SYSCONF
235         dtblsize = sysconf( _SC_OPEN_MAX );
236 #elif HAVE_GETDTABLESIZE
237         dtblsize = getdtablesize();
238 #else
239         dtblsize = FD_SETSIZE;
240 #endif
241
242 #ifdef FD_SETSIZE
243         if( dtblsize > FD_SETSIZE ) {
244                 dtblsize = FD_SETSIZE;
245         }
246 #endif /* FD_SETSIZE */
247
248 #if defined(LDAP_PROCTITLE) && !defined( HAVE_SETPROCTITLE )
249         /* for setproctitle */
250         Argv = argv;
251         Argc = argc;
252 #endif
253
254         if ( (myname = strrchr( argv[0], '/' )) == NULL )
255                 myname = strdup( argv[0] );
256         else
257                 myname = strdup( myname + 1 );
258
259         /* 
260          * detach from the terminal if stderr is redirected or no
261          * debugging is wanted, and then arrange to reap children
262          * that have exited
263          */
264         if (!RunFromInetd) {
265 #ifdef LDAP_SETPROCTITLE
266                 setproctitle( "initializing" );
267 #endif
268 #ifndef VMS
269                 (void) detach();
270 #endif
271                 (void) SIGNAL( SIGCHLD, (void *) wait4child );
272                 (void) SIGNAL( SIGINT, (void *) log_and_exit );
273         }
274
275         /* 
276          * set up syslogging (if desired)
277          */
278         if ( dosyslog ) {
279 #ifdef LOG_LOCAL4
280                 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
281 #else
282                 openlog( myname, OPENLOG_OPTIONS );
283 #endif
284         }
285
286         /* 
287          * load the syntax handlers, oidtables, and initialize some stuff,
288          * then start listening
289          */
290
291         (void) quipu_syntaxes();
292 #ifdef LDAP_USE_PP
293         (void) pp_quipu_init( argv[0] );
294 #endif
295 #if ISODEPACKAGE == IC
296 #if ICRELEASE > 2
297         dsa_operation_syntaxes();
298 #endif
299 #endif
300         (void) dsap_init( &dsapargc, &dsapargv );
301         (void) get_syntaxes();
302         if (RunFromInetd) {
303                 len = sizeof( socktype );
304                 getsockopt( ns, SOL_SOCKET, SO_TYPE, &socktype, &len );
305                 if ( socktype == SOCK_DGRAM ) {
306 #ifdef LDAP_CONNECTIONLESS
307                         Debug( LDAP_DEBUG_ARGS,
308                             "CLDAP request from unknown (%s)\n",
309                             inet_ntoa( from.sin_addr ), 0, 0 );
310                         conn_start_tv.tv_sec = 0;
311                         udp_init( 0, 0 );
312                         do_queries( ns, 1 );
313 #else /* LDAP_CONNECTIONLESS */
314                         Debug( LDAP_DEBUG_ARGS,
315                             "Compile with -DLDAP_CONNECTIONLESS for UDP support\n",0,0,0 );
316 #endif /* LDAP_CONNECTIONLESS */
317                         exit( 0 );
318                 }
319
320                 len = sizeof(from);
321                 if ( getpeername( ns, (struct sockaddr *) &from, &len )
322                     == 0 ) {
323                         hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
324                         sizeof(from.sin_addr.s_addr), AF_INET );
325                         Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
326                             (hp == NULL) ? "unknown" : hp->h_name,
327                             inet_ntoa( from.sin_addr ), 0 );
328
329                         if ( dosyslog ) {
330                                 syslog( LOG_INFO, "connection from %s (%s)",
331                                     (hp == NULL) ? "unknown" : hp->h_name,
332                                     inet_ntoa( from.sin_addr ) );
333                         }
334
335 #ifdef LDAP_SETPROCTITLE
336                         sprintf( title, "%s %d\n", hp == NULL ?
337                             inet_ntoa( from.sin_addr ) : hp->h_name, myport );
338                         setproctitle( title );
339 #endif
340                 }
341                 gettimeofday( &conn_start_tv, (struct timezone *) NULL );
342                 do_queries( ns, 0 );
343
344                 exit( 0 );
345         }
346
347         if ( do_tcp )
348             tcps = set_socket( myport, 0 );
349
350 #ifdef LDAP_CONNECTIONLESS
351         if ( do_udp )
352                 udps = udp_init( myport, 1 );
353 #endif
354
355         /*
356          * loop, wait for a connection, then fork off a child to handle it
357          * if we are doing CLDAP as well, handle those requests on the fly
358          */
359
360 #ifdef LDAP_SETPROCTITLE
361 #ifdef LDAP_CONNECTIONLESS
362         sprintf( title, "listening %s/%s %d", do_tcp ? "tcp" : "",
363             do_udp ? "udp" : "", myport );
364 #else
365         sprintf( title, "listening %s %d", do_tcp ? "tcp" : "", myport );
366 #endif
367         setproctitle( title );
368 #endif
369
370         for ( ;; ) {
371                 FD_ZERO( &readfds );
372                 if ( do_tcp )
373                         FD_SET( tcps, &readfds );
374 #ifdef LDAP_CONNECTIONLESS
375                 if ( do_udp )
376                         FD_SET( udps, &readfds );
377 #endif
378
379                 if ( select( dtblsize, &readfds, 0, 0, 0 ) < 1 ) {
380 #ifdef LDAP_DEBUG
381                         if ( ldap_debug ) perror( "main select" );
382 #endif
383                         continue;
384                 }
385
386 #ifdef LDAP_CONNECTIONLESS
387                 if ( do_udp && FD_ISSET( udps, &readfds ) ) {
388                         do_queries( udps, 1 );
389                 }
390 #endif
391
392                 if ( !do_tcp || ! FD_ISSET( tcps, &readfds ) ) {
393                         continue;
394                 }
395
396                 len = sizeof(from);
397                 if ( (ns = accept( tcps, (struct sockaddr *) &from, &len ))
398                     == -1 ) {
399 #ifdef LDAP_DEBUG
400                         if ( ldap_debug ) perror( "accept" );
401 #endif
402                         continue;
403                 }
404
405                 hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
406                     sizeof(from.sin_addr.s_addr), AF_INET );
407
408 #ifdef HAVE_TCPD
409                 if ( !hosts_ctl("ldapd", (hp == NULL) ? "unknown" : hp->h_name,
410                         inet_ntoa( from.sin_addr ), STRING_UNKNOWN ) {
411
412                         Debug( LDAP_DEBUG_ARGS, "connection from %s (%s) denied.\n",
413                                 (hp == NULL) ? "unknown" : hp->h_name,
414                                 inet_ntoa( from.sin_addr ), 0 );
415
416                         if ( dosyslog ) {
417                                 syslog( LOG_NOTICE, "connection from %s (%s) denied.",
418                                     (hp == NULL) ? "unknown" : hp->h_name,
419                                     inet_ntoa( from.sin_addr ) );
420                         }
421
422                         close(ns);
423                         continue;
424                 }
425 #endif /* TCP_WRAPPERS */
426
427                 Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
428                     (hp == NULL) ? "unknown" : hp->h_name,
429                     inet_ntoa( from.sin_addr ), 0 );
430
431
432                 if ( dosyslog ) {
433                         syslog( LOG_INFO, "connection from %s (%s)",
434                             (hp == NULL) ? "unknown" : hp->h_name,
435                             inet_ntoa( from.sin_addr ) );
436                 }
437
438 #ifdef VMS
439                 /* This is for debug on terminal on VMS */
440                 close( tcps );
441 #ifdef LDAP_SETPROCTITLE
442                 setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
443                     hp->h_name );
444 #endif
445                 gettimeofday( &conn_start_tv, (struct timezone *) NULL );
446                 (void) SIGNAL( SIGPIPE, (void *) log_and_exit );
447
448                 do_queries( ns, 0 );
449                 /* NOT REACHED */
450 #endif
451
452                 switch( pid = fork() ) {
453                 case 0:         /* child */
454                         close( tcps );
455 #ifdef LDAP_SETPROCTITLE
456                         sprintf( title, "%s (%d)\n", hp == NULL ?
457                                 inet_ntoa( from.sin_addr ) : hp->h_name,
458                                 myport );
459                         setproctitle( title );
460 #endif
461                         gettimeofday( &conn_start_tv, (struct timezone *) NULL );
462                         (void) SIGNAL( SIGPIPE, (void *) log_and_exit );
463
464                         do_queries( ns, 0 );
465                         break;
466
467                 case -1:        /* failed */
468 #ifdef LDAP_DEBUG
469                         if ( ldap_debug ) perror( "fork" );
470 #endif
471                         close( ns );
472                         syslog( LOG_ERR, "fork failed %m" );
473                         /* let things cool off */
474                         sleep( 15 );
475                         break;
476
477                 default:        /* parent */
478                         close( ns );
479                         Debug( LDAP_DEBUG_TRACE, "forked child %d\n", pid, 0,
480                             0 );
481                         break;
482                 }
483         }
484         /* NOT REACHED */
485 }
486
487 static
488 do_queries(
489     int clientsock,
490     int udp             /* is this a UDP (CLDAP) request? */
491 )
492 {
493         fd_set          readfds;
494         int             rc, i;
495         struct timeval  timeout;
496         Sockbuf         sb;
497 #ifdef LDAP_CONNECTIONLESS
498         struct sockaddr saddr, faddr;
499         struct sockaddr *saddrlist[ 1 ];
500 #endif /* LDAP_CONNECTIONLESS */
501
502         Debug( LDAP_DEBUG_TRACE, "do_queries%s\n",
503             udp ? " udp" : "", 0, 0 );
504
505         /*
506          * Loop, wait for a request from the client or a response from
507          * a dsa, then handle it.  Dsap_ad is always a connection to the
508          * "default" dsa.  Other connections can be made as a result of
509          * a referral being chased down.  These association descriptors
510          * are kept track of with the message that caused the referral.
511          * The set_dsa_fds() routine traverses the list of outstanding
512          * messages, setting the appropriate bits in readfds.
513          */
514
515         if ( !udp ) {
516                 conn_init();
517         }
518
519         (void) memset( (void *) &sb, '\0', sizeof( sb ) );
520         sb.sb_sd = clientsock;
521         sb.sb_naddr = ( udp ) ? 1 : 0;
522 #ifdef LDAP_CONNECTIONLESS
523         sb.sb_addrs = (void **)saddrlist;
524         sb.sb_fromaddr = &faddr;
525         sb.sb_useaddr = saddrlist[ 0 ] = &saddr;
526 #endif
527         sb.sb_ber.ber_buf = NULL;
528         sb.sb_ber.ber_ptr = NULL;
529         sb.sb_ber.ber_end = NULL;
530
531         timeout.tv_sec = idletime;
532         timeout.tv_usec = 0;
533         for ( ;; ) {
534                 struct conn             *dsaconn;
535                 extern struct conn      *conns;
536
537                 FD_ZERO( &readfds );
538                 FD_SET( clientsock, &readfds );
539                 conn_setfds( &readfds );
540
541 #ifdef LDAP_DEBUG
542                 if ( ldap_debug & LDAP_DEBUG_CONNS ) {
543                         Debug( LDAP_DEBUG_CONNS, "FDLIST:", 0, 0, 0 );
544                         for ( i = 0; i < dtblsize; i++ ) {
545                                 if ( FD_ISSET( i, &readfds ) ) {
546                                         Debug( LDAP_DEBUG_CONNS, " %d", i, 0,
547                                             0);
548                                 }
549                         }
550                         Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
551                 }
552 #endif
553
554                 /* 
555                  * hack - because of lber buffering, there might be stuff
556                  * already waiting for us on the client sock.
557                  */
558
559                 if ( sb.sb_ber.ber_ptr >= sb.sb_ber.ber_end ) {
560                         if ( (rc = select( dtblsize, &readfds, 0, 0,
561                             udp ? 0 : &timeout )) < 1 ) {
562 #ifdef LDAP_DEBUG
563                                 if ( ldap_debug ) perror( "do_queries select" );
564 #endif
565                                 if ( rc == 0 )
566                                         log_and_exit( 0 ); /* idle timeout */
567
568                                 Debug( LDAP_DEBUG_ANY, "select returns %d!\n",
569                                     rc, 0, 0 );
570
571                                 /* client gone away - we can too */
572                                 if ( isclosed( clientsock ) )
573                                         log_and_exit( 0 );
574
575                                 /*
576                                  * check if a dsa conn has gone away -
577                                  * mark it bad if so
578                                  */
579                                 conn_badfds();
580
581                                 continue;
582                         }
583                 }
584
585                 if ( sb.sb_ber.ber_ptr < sb.sb_ber.ber_end ||
586                     FD_ISSET( clientsock, &readfds ) ) {
587                         client_request( &sb, conns, udp );
588                 } else {
589                         if ( (dsaconn = conn_getfd( &readfds )) == NULL ) {
590                                 Debug( LDAP_DEBUG_ANY, "No DSA activity!\n",
591                                     0, 0, 0 );
592                                 continue;
593                         }
594
595                         dsa_response( dsaconn, &sb );
596                 }
597         }
598         /* NOT REACHED */
599 }
600
601 static set_socket(
602     int port,
603     int udp     /* UDP port? */
604 )
605 {
606         int                     s, i;
607         struct sockaddr_in      addr;
608
609         if ( (s = socket( AF_INET, udp ? SOCK_DGRAM:SOCK_STREAM, 0 )) == -1 ) {
610                 perror( "socket" );
611                 exit( 1 );
612         }
613
614         /* set option so clients can't keep us from coming back up */
615         i = 1;
616         if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof(i) )
617             < 0 ) {
618                 perror( "setsockopt" );
619                 exit( 1 );
620         }
621
622         /* bind to a name */
623         (void)memset( (void *)&addr, '\0', sizeof( addr ));
624         addr.sin_family = AF_INET;
625         addr.sin_addr.s_addr = INADDR_ANY;
626         addr.sin_port = htons( port );
627         if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
628                 perror( "bind" );
629                 exit( 1 );
630         }
631
632         if ( !udp ) {
633                 /* listen for connections */
634                 if ( listen( s, 5 ) == -1 ) {
635                         perror( "listen" );
636                         exit( 1 );
637                 }
638         }
639  
640         Debug( LDAP_DEBUG_TRACE, "listening on %s port %d\n",
641                 udp ? "udp" : "tcp", port, 0 );
642
643         return( s );
644 }
645
646 static RETSIGTYPE wait4child()
647 {
648 #ifndef HAVE_WAITPID
649         WAITSTATUSTYPE     status;
650 #endif
651
652         Debug( LDAP_DEBUG_TRACE, "parent: catching child status\n", 0, 0, 0 );
653
654 #ifdef HAVE_WAITPID
655         while( waitpid( (pid_t) -1, NULL, WAIT_FLAGS ) > 0 )
656                 ;       /* NULL */
657 #else
658         while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
659                 ;       /* NULL */
660 #endif
661
662         (void) SIGNAL( SIGCHLD, (void *) wait4child );
663 }
664
665
666 void
667 log_and_exit( int exitcode )
668 {
669         struct timeval  tv;
670
671         if ( dosyslog ) {
672                 if ( conn_start_tv.tv_sec == 0 ) {
673                         syslog( LOG_INFO, "UDP exit(%d)", exitcode );
674                 } else {
675                         gettimeofday( &tv, (struct timezone *)NULL );
676                         syslog( LOG_INFO, "TCP closed %d seconds,  exit(%d)",
677                             tv.tv_sec - conn_start_tv.tv_sec, exitcode );
678                 }
679         }
680
681         exit( exitcode );
682 }
683
684
685 #ifdef LDAP_CONNECTIONLESS
686 static int
687 udp_init(
688     int port,
689     int createsocket
690 )
691 {
692         int     s, bound;
693         char    *matched;
694         extern char             *dsa_address;
695         extern struct PSAPaddr  *psap_cpy();
696         extern struct conn      *conns;
697
698         if ( createsocket )
699                 s = set_socket( port, 1 );
700
701         conn_init();
702         conns->c_dn = strdup("");
703         conns->c_cred = strdup("");
704         conns->c_credlen = 0;
705         conns->c_method = LDAP_AUTH_SIMPLE;
706
707        if ( dsa_address == NULL || (conns->c_paddr = str2paddr( dsa_address ))
708             == NULLPA ) {
709                 fprintf(stderr, "Bad DSA address (%s)\n", dsa_address ?
710                     dsa_address : "NULL" );
711                 exit( 1 );
712         } else {
713                 conns->c_paddr = psap_cpy(conns->c_paddr);
714         }
715
716         if ( do_bind_real(conns, &bound, &matched) != LDAP_SUCCESS) {
717                 fprintf(stderr, "Cannot bind to directory\n");
718                 exit( 1 );
719         }
720         if ( matched != NULL )
721                 free( matched );
722
723         return( createsocket ? s : 0 );
724 }
725 #endif