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