]> git.sur5r.net Git - openldap/blob - servers/ldapd/main.c
51d5791b465c31684d5cbcb74fb343f7c5cd7988
[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
44 #ifdef HAVE_TCPD
45 #include <tcpd.h>
46
47 int allow_severity = LOG_INFO;
48 int deny_severity = LOG_NOTICE;
49 #endif /* TCP_WRAPPERS */
50
51 void log_and_exit();
52 static set_socket();
53 static do_queries();
54 static RETSIGTYPE wait4child();
55 #ifdef LDAP_CONNECTIONLESS
56 static udp_init();
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 extern char Versionstr[];
86
87 static usage( name )
88 char    *name;
89 {
90         fprintf( stderr, "usage: %s [-d debuglvl] [-p port] [-l] [-c dsa] [-r referraltimeout]", name );
91 #ifdef LDAP_CONNECTIONLESS
92         fprintf( stderr, " [ -U | -t timeout ]" );
93 #else
94         fprintf( stderr, " [ -t timeout ]" );
95 #endif
96         fprintf( stderr, " [-I]" );
97 #ifdef HAVE_KERBEROS
98         fprintf( stderr, " [-i dsainstance]" );
99 #endif
100         fprintf( stderr, "\n" );
101 }
102
103 main (argc, argv)
104 int     argc;
105 char    **argv;
106 {
107         int                     tcps, ns;
108 #ifdef LDAP_CONNECTIONLESS
109         int                     udps;
110 #endif
111         int                     myport = LDAP_PORT;
112         int                     i, pid, socktype;
113         char                    *myname;
114         fd_set                  readfds;
115         struct hostent          *hp;
116         struct sockaddr_in      from;
117         int                     len;
118         int                     dsapargc;
119         char                    **dsapargv;
120         RETSIGTYPE                      wait4child();
121 #ifdef LDAP_PROCTITLE
122         char                    title[80];
123 #endif
124         extern char             *optarg;
125         extern int              optind;
126
127 #ifdef VMS
128         /* Pick up socket from inetd-type server on VMS */
129         if ( (ns = socket_from_server( NULL )) > 0 )
130                 RunFromInetd = 1;
131 #else
132         /* Socket from inetd is usually 0 */
133         ns = 0;
134 #endif
135
136         /* for dsap_init */
137         if ( (dsapargv = (char **) malloc( 4 * sizeof(char *) )) == NULL ) {
138                 perror( "malloc" );
139                 exit( 1 );
140         }
141         dsapargv[0] = argv[0];
142         dsapargv[1] = 0;
143         dsapargv[2] = 0;
144         dsapargv[3] = 0;
145         dsapargc = 1;
146 #ifdef HAVE_KERBEROS
147         kerberos_keyfile = "";
148 #endif
149
150         /* process command line arguments */
151         while ( (i = getopt( argc, argv, "d:lp:f:i:c:r:t:IuU" )) != EOF ) {
152                 switch ( i ) {
153                 case 'c':       /* specify dsa to contact */
154                         dsapargv[1] = "-call";
155                         dsapargv[2] = strdup( optarg );
156                         dsapargc = 3;
157                         break;
158
159                 case 'd':       /* turn on debugging */
160 #ifdef LDAP_DEBUG
161                         ldap_debug = atoi( optarg );
162                         if ( ldap_debug & LDAP_DEBUG_PACKETS )
163                                 lber_debug = ldap_debug;
164 #else
165                         fprintf( stderr, "Not compiled with -DLDAP_DEBUG!\n" );
166 #endif
167                         break;
168
169                 case 'l':       /* do syslogging */
170                         dosyslog = 1;
171                         break;
172
173                 case 'p':       /* specify port number */
174                         myport = atoi( optarg );
175                         break;
176
177                 case 'r':       /* timeout for referral connections */
178                         referral_connection_timeout = atoi( optarg );
179                         break;
180
181                 case 't':       /* timeout for idle connections */
182                         idletime = atoi( optarg );
183                         break;
184
185 #ifdef HAVE_KERBEROS
186                 case 'f':       /* kerberos key file */
187                         kerberos_keyfile = strdup( optarg );
188                         break;
189
190                 case 'i':       /* x500 dsa kerberos instance */
191                         if ( krb_x500_instance != NULL )
192                                 free( krb_x500_instance );
193                         krb_x500_instance = strdup( optarg );
194                         break;
195 #endif
196
197                 case 'I':       /* Run from inetd */
198                         RunFromInetd = 1;
199                         break;
200
201 #ifdef LDAP_CONNECTIONLESS
202                 case 'U':       /* UDP only (no TCP) */
203                         do_tcp = 0;
204                         do_udp = 1;
205                         break;
206
207 #ifdef NOTYET
208                 case 'u':       /* allow UDP requests (CLDAP) */
209                         do_udp = 1;
210                         break;
211 #endif /* NOTYET */
212
213 #endif /* LDAP_CONNECTIONLESS */
214
215                 default:
216                         usage( argv[0] );
217                         exit( 1 );
218                 }
219         }
220
221         if ( optind < argc ) {
222                 usage( argv[ 0 ] );
223                 exit( 1 );
224         }
225
226 #ifdef LDAP_CONNECTIONLESS
227         if ( do_udp && !do_tcp && idletime != DEFAULT_TIMEOUT ) {
228                 usage( argv[ 0 ] );
229                 exit( 1 );
230         }
231 #endif
232
233         Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
234
235 #ifdef HAVE_SYSCONF
236         dtblsize = sysconf( _SC_OPEN_MAX );
237 #elif HAVE_GETDTABLESIZE
238         dtblsize = getdtablesize();
239 #else
240         dtblsize = FD_SETSIZE;
241 #endif
242
243 #ifdef FD_SETSIZE
244         if( dtblsize > FD_SETSIZE ) {
245                 dtblsize = FD_SETSIZE;
246         }
247 #endif /* FD_SETSIZE */
248
249 #if defined(LDAP_PROCTITLE) && !defined( HAVE_SETPROCTITLE )
250         /* for setproctitle */
251         Argv = argv;
252         Argc = argc;
253 #endif
254
255         if ( (myname = strrchr( argv[0], '/' )) == NULL )
256                 myname = strdup( argv[0] );
257         else
258                 myname = strdup( myname + 1 );
259
260         /* 
261          * detach from the terminal if stderr is redirected or no
262          * debugging is wanted, and then arrange to reap children
263          * that have exited
264          */
265         if (!RunFromInetd) {
266 #ifdef LDAP_SETPROCTITLE
267                 setproctitle( "initializing" );
268 #endif
269 #ifndef VMS
270                 (void) detach();
271 #endif
272                 (void) SIGNAL( SIGCHLD, (void *) wait4child );
273                 (void) SIGNAL( SIGINT, (void *) 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, &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_SETPROCTITLE
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_SETPROCTITLE
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_SETPROCTITLE
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, (void *) 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_SETPROCTITLE
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, (void *) 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
489 do_queries(
490     int clientsock,
491     int udp             /* is this a UDP (CLDAP) request? */
492 )
493 {
494         fd_set          readfds;
495         int             rc, i;
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                 extern struct conn      *conns;
537
538                 FD_ZERO( &readfds );
539                 FD_SET( clientsock, &readfds );
540                 conn_setfds( &readfds );
541
542 #ifdef LDAP_DEBUG
543                 if ( ldap_debug & LDAP_DEBUG_CONNS ) {
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 set_socket(
603     int port,
604     int udp     /* UDP port? */
605 )
606 {
607         int                     s, i;
608         struct sockaddr_in      addr;
609
610         if ( (s = socket( AF_INET, udp ? SOCK_DGRAM:SOCK_STREAM, 0 )) == -1 ) {
611                 perror( "socket" );
612                 exit( 1 );
613         }
614
615         /* set option so clients can't keep us from coming back up */
616         i = 1;
617         if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof(i) )
618             < 0 ) {
619                 perror( "setsockopt" );
620                 exit( 1 );
621         }
622
623         /* bind to a name */
624         (void)memset( (void *)&addr, '\0', sizeof( addr ));
625         addr.sin_family = AF_INET;
626         addr.sin_addr.s_addr = INADDR_ANY;
627         addr.sin_port = htons( port );
628         if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
629                 perror( "bind" );
630                 exit( 1 );
631         }
632
633         if ( !udp ) {
634                 /* listen for connections */
635                 if ( listen( s, 5 ) == -1 ) {
636                         perror( "listen" );
637                         exit( 1 );
638                 }
639         }
640  
641         Debug( LDAP_DEBUG_TRACE, "listening on %s port %d\n",
642                 udp ? "udp" : "tcp", port, 0 );
643
644         return( s );
645 }
646
647 static RETSIGTYPE wait4child()
648 {
649 #ifndef HAVE_WAITPID
650         WAITSTATUSTYPE     status;
651 #endif
652
653         Debug( LDAP_DEBUG_TRACE, "parent: catching child status\n", 0, 0, 0 );
654
655 #ifdef HAVE_WAITPID
656         while( waitpid( (pid_t) -1, NULL, WAIT_FLAGS ) > 0 )
657                 ;       /* NULL */
658 #else
659         while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
660                 ;       /* NULL */
661 #endif
662
663         (void) SIGNAL( SIGCHLD, (void *) wait4child );
664 }
665
666
667 void
668 log_and_exit( int exitcode )
669 {
670         struct timeval  tv;
671
672         if ( dosyslog ) {
673                 if ( conn_start_tv.tv_sec == 0 ) {
674                         syslog( LOG_INFO, "UDP exit(%d)", exitcode );
675                 } else {
676                         gettimeofday( &tv, (struct timezone *)NULL );
677                         syslog( LOG_INFO, "TCP closed %d seconds,  exit(%d)",
678                             tv.tv_sec - conn_start_tv.tv_sec, exitcode );
679                 }
680         }
681
682         exit( exitcode );
683 }
684
685
686 #ifdef LDAP_CONNECTIONLESS
687 static int
688 udp_init(
689     int port,
690     int createsocket
691 )
692 {
693         int     s, bound;
694         char    *matched;
695         extern char             *dsa_address;
696         extern struct PSAPaddr  *psap_cpy();
697         extern struct conn      *conns;
698
699         if ( createsocket )
700                 s = set_socket( port, 1 );
701
702         conn_init();
703         conns->c_dn = strdup("");
704         conns->c_cred = strdup("");
705         conns->c_credlen = 0;
706         conns->c_method = LDAP_AUTH_SIMPLE;
707
708        if ( dsa_address == NULL || (conns->c_paddr = str2paddr( dsa_address ))
709             == NULLPA ) {
710                 fprintf(stderr, "Bad DSA address (%s)\n", dsa_address ?
711                     dsa_address : "NULL" );
712                 exit( 1 );
713         } else {
714                 conns->c_paddr = psap_cpy(conns->c_paddr);
715         }
716
717         if ( do_bind_real(conns, &bound, &matched) != LDAP_SUCCESS) {
718                 fprintf(stderr, "Cannot bind to directory\n");
719                 exit( 1 );
720         }
721         if ( matched != NULL )
722                 free( matched );
723
724         return( createsocket ? s : 0 );
725 }
726 #endif