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