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