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