| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include <string.h>
- #include <sys/types.h>
- #ifdef _WIN32
- #include <windows.h>
- #include <process.h> /* for getpid */
- #include "proto-ntutil.h"
- #include "ntslapdmessages.h"
- #else
- #include <unistd.h>
- #include <sys/socket.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/types.h>
- #include <netinet/tcp.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <pthread.h>
- #include <mntent.h>
- #endif
- #include <time.h>
- #include <signal.h>
- #if defined(IRIX6_2) || defined(IRIX6_3)
- #include <sys/param.h>
- #endif
- #if defined(_AIX)
- #include <sys/select.h>
- #include <sys/param.h>
- #endif
- #include <fcntl.h>
- #define TCPLEN_T int
- #if !defined( _WIN32 )
- #ifdef NEED_FILIO
- #include <sys/filio.h>
- #else /* NEED_FILIO */
- #include <sys/ioctl.h>
- #endif /* NEED_FILIO */
- #endif /* !defined( _WIN32 ) */
- /* for some reason, linux tty stuff defines CTIME */
- #ifdef LINUX
- #undef CTIME
- #include <sys/statfs.h>
- #else
- #include <sys/statvfs.h>
- #include <sys/mnttab.h>
- #endif
- #include "slap.h"
- #include "slapi-plugin.h"
- #include "snmp_collator.h"
- #include <private/pprio.h>
- #include <ssl.h>
- #include <stdio.h>
- #include "fe.h"
- #if defined(ENABLE_LDAPI)
- #include "getsocketpeer.h"
- #endif /* ENABLE_LDAPI */
- /*
- * Define the backlog number for use in listen() call.
- * We use the same definition as in ldapserver/include/base/systems.h
- */
- #ifndef DAEMON_LISTEN_SIZE
- #define DAEMON_LISTEN_SIZE 128
- #endif
- #if defined (LDAP_IOCP)
- #define SLAPD_WAKEUP_TIMER 250
- #else
- #define SLAPD_WAKEUP_TIMER 250
- #endif
- int slapd_wakeup_timer = SLAPD_WAKEUP_TIMER; /* time in ms to wakeup */
- #ifdef notdef /* GGOODREPL */
- /*
- * time in secs to do housekeeping:
- * this must be greater than slapd_wakeup_timer
- */
- short slapd_housekeeping_timer = 10;
- #endif /* notdef GGOODREPL */
- /* Do we support timeout on socket send() ? */
- int have_send_timeouts = 0;
- PRFileDesc* signalpipe[2];
- static int writesignalpipe = SLAPD_INVALID_SOCKET;
- static int readsignalpipe = SLAPD_INVALID_SOCKET;
- static PRThread *disk_thread_p = NULL;
- static PRCondVar *diskmon_cvar = NULL;
- static PRLock *diskmon_mutex = NULL;
- void disk_monitoring_stop();
- #define FDS_SIGNAL_PIPE 0
- typedef struct listener_info {
- int idx; /* index of this listener in the ct->fd array */
- PRFileDesc *listenfd; /* the listener fd */
- int secure;
- int local;
- } listener_info;
- #define SLAPD_POLL_LISTEN_READY(xxflagsxx) (xxflagsxx & PR_POLL_READ)
- static int get_configured_connection_table_size();
- #ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS
- static void get_loopback_by_addr( void );
- #endif
- #ifdef XP_WIN32
- static int createlistensocket(unsigned short port, const PRNetAddr *listenaddr);
- #endif
- static PRFileDesc **createprlistensockets(unsigned short port,
- PRNetAddr **listenaddr, int secure, int local);
- static const char *netaddr2string(const PRNetAddr *addr, char *addrbuf,
- size_t addrbuflen);
- static void set_shutdown (int);
- static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners);
- #ifdef HPUX10
- static void* catch_signals();
- #endif
- #if defined( _WIN32 )
- HANDLE hServDoneEvent = NULL;
- #endif
- static int createsignalpipe( void );
- #if defined( _WIN32 )
- /* Set an event to hook the NT Service termination */
- void *slapd_service_exit_wait()
- {
- #if defined( PURIFYING )
- #include <sys/types.h>
- #include <sys/stat.h>
- char module[_MAX_FNAME];
- char exit_file_name[_MAX_FNAME];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
- struct stat statbuf;
- memset( module, 0, sizeof( module ) );
- memset( exit_file_name, 0, sizeof( exit_file_name ) );
- GetModuleFileName(GetModuleHandle( NULL ), module, sizeof( module ) );
- _splitpath( module, drive, dir, fname, ext );
- PR_snprintf( exit_file_name, sizeof(exit_file_name), "%s%s%s", drive, dir, "exitnow.txt" );
- LDAPDebug( LDAP_DEBUG_ANY, "PURIFYING - Create %s to terminate the process.\n", exit_file_name, 0, 0 );
- while ( TRUE )
- {
- if( stat( exit_file_name, &statbuf ) < 0)
- {
- Sleep( 5000 ); /* 5 Seconds */
- continue;
- }
- LDAPDebug( LDAP_DEBUG_ANY, "slapd shutting down immediately, "
- "\"%s\" exists - don't forget to delete it\n", exit_file_name, 0, 0 );
- g_set_shutdown( SLAPI_SHUTDOWN_SIGNAL );
- return NULL;
- }
- #else /* PURIFYING */
- DWORD dwWait;
- char szDoneEvent[256];
- PR_snprintf(szDoneEvent, sizeof(szDoneEvent), "NS_%s", pszServerName);
- hServDoneEvent = CreateEvent( NULL, // default security attributes (LocalSystem)
- TRUE, // manual reset event
- FALSE, // not-signalled
- szDoneEvent );// named after the service itself.
- /* Wait indefinitely until hServDoneEvent is signaled. */
- dwWait = WaitForSingleObject( hServDoneEvent, // event object
- INFINITE ); // wait indefinitely
- /* The termination event has been signalled, log this occurrence, and signal to exit. */
- ReportSlapdEvent( EVENTLOG_INFORMATION_TYPE, MSG_SERVER_SHUTDOWN_STARTING, 0, NULL );
- g_set_shutdown( SLAPI_SHUTDOWN_SIGNAL );
- return NULL;
- #endif /* PURIFYING */
- }
- #endif /* _WIN32 */
- static char *
- get_pid_file()
- {
- return(pid_file);
- }
- static int daemon_configure_send_timeout(int s,size_t timeout /* Miliseconds*/)
- {
- /* Currently this function is only good for NT, and expects the s argument to be a SOCKET */
- #if defined(_WIN32)
- return setsockopt(
- s,
- SOL_SOCKET,
- SO_SNDTIMEO,
- (char*) &timeout,
- sizeof(timeout)
- );
- #else
- return 0;
- #endif
- }
- #if defined (_WIN32)
- /* This function is a workaround for accept problem on NT.
- Accept call fires on NT during syn scan even though the connection is not
- open. This causes a resource leak. For more details, see bug 391414.
- Experimentally, we determined that, in case of syn scan, the local
- address is set to 0. This in undocumented and my change in the future
-
- The function returns 0 if this is normal connection
- 1 if this is syn_scan connection
- -1 in case of any other error
- */
- static int
- syn_scan (int sock)
- {
- int rc;
- struct sockaddr_in addr;
- int size = sizeof (addr);
- if (sock == SLAPD_INVALID_SOCKET)
- return -1;
- rc = getsockname (sock, (struct sockaddr*)&addr, &size);
- if (rc != 0)
- return -1;
- else if (addr.sin_addr.s_addr == 0)
- return 1;
- else
- return 0;
- }
- #endif
- static int
- accept_and_configure(int s, PRFileDesc *pr_acceptfd, PRNetAddr *pr_netaddr,
- int addrlen, int secure, int local, PRFileDesc **pr_clonefd)
- {
- int ns = 0;
- PRIntervalTime pr_timeout = PR_MillisecondsToInterval(slapd_wakeup_timer);
- #if !defined( XP_WIN32 ) /* UNIX */
- (*pr_clonefd) = PR_Accept(pr_acceptfd, pr_netaddr, pr_timeout);
- if( !(*pr_clonefd) ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "PR_Accept() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- return(SLAPD_INVALID_SOCKET);
- }
- ns = configure_pr_socket( pr_clonefd, secure, local );
- #else /* Windows */
- if( secure ) {
- (*pr_clonefd) = PR_Accept(pr_acceptfd, pr_netaddr, pr_timeout);
- if( !(*pr_clonefd) ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "PR_Accept() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- /* Bug 613324: Call PR_NT_CancelIo if an error occurs */
- if( (prerr == PR_IO_TIMEOUT_ERROR ) ||
- (prerr == PR_PENDING_INTERRUPT_ERROR) ) {
- if( (PR_NT_CancelIo( pr_acceptfd )) != PR_SUCCESS) {
- prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_NT_CancelIo() failed, "
- SLAPI_COMPONENT_NAME_NSPR
- " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- }
- }
- return(SLAPD_INVALID_SOCKET);
- }
- ns = configure_pr_socket( pr_clonefd, secure, local );
- } else { /* !secure */
- struct sockaddr *addr; /* NOT IPv6 enabled */
- addr = (struct sockaddr *) slapi_ch_malloc( sizeof(struct sockaddr) );
- ns = accept (s, addr, (TCPLEN_T *)&addrlen);
- if (ns == SLAPD_INVALID_SOCKET) {
- int oserr = errno;
-
- LDAPDebug( LDAP_DEBUG_ANY,
- "accept(%d) failed errno %d (%s)\n",
- s, oserr, slapd_system_strerror(oserr));
- }
- else if (syn_scan (ns))
- {
- /* this is a work around for accept problem with SYN scan on NT.
- See bug 391414 for more details */
- LDAPDebug(LDAP_DEBUG_ANY, "syn-scan request is received - ignored\n", 0, 0, 0);
- closesocket (ns);
- ns = SLAPD_INVALID_SOCKET;
- }
- PRLDAP_SET_PORT( pr_netaddr, ((struct sockaddr_in *)addr)->sin_port );
- PR_ConvertIPv4AddrToIPv6(((struct sockaddr_in *)addr)->sin_addr.s_addr, &(pr_netaddr->ipv6.ip));
- (*pr_clonefd) = NULL;
- slapi_ch_free( (void **)&addr );
- configure_ns_socket( &ns );
- }
- #endif
- return ns;
- }
- /*
- * This is the shiny new re-born daemon function, without all the hair
- */
- #ifdef _WIN32
- static void setup_read_fds(Connection_Table *ct, fd_set *readfds, int n_tcps, int s_tcps );
- static void handle_read_ready(Connection_Table *ct, fd_set *readfds);
- static void set_timeval_ms(struct timeval *t, int ms);
- #endif
- /* GGOODREPL static void handle_timeout( void ); */
- static void handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll);
- static int handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local );
- #ifdef _WIN32
- static void unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, int n_tcps, PRFileDesc *s_tcps);
- #else
- static void unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix);
- #endif
- static int write_pid_file();
- static int init_shutdown_detect();
- #ifdef _WIN32
- static int clear_signal(fd_set *readfdset);
- #else
- static int clear_signal(struct POLL_STRUCT *fds);
- #endif
- /* Globals which are used to store the sockets between
- * calls to daemon_pre_setuid_init() and the daemon thread
- * creation. */
- int daemon_pre_setuid_init(daemon_ports_t *ports)
- {
- int rc = 0;
- if (0 != ports->n_port) {
- #if defined( XP_WIN32 )
- ports->n_socket = createlistensocket((unsigned short)ports->n_port,
- &ports->n_listenaddr);
- #else
- ports->n_socket = createprlistensockets(ports->n_port,
- ports->n_listenaddr, 0, 0);
- #endif
- }
- if ( config_get_security() && (0 != ports->s_port) ) {
- ports->s_socket = createprlistensockets((unsigned short)ports->s_port,
- ports->s_listenaddr, 1, 0);
- #ifdef XP_WIN32
- ports->s_socket_native = PR_FileDesc2NativeHandle(ports->s_socket);
- #endif
- } else {
- ports->s_socket = SLAPD_INVALID_SOCKET;
- #ifdef XP_WIN32
- ports->s_socket_native = SLAPD_INVALID_SOCKET;
- #endif
- }
- #ifndef XP_WIN32
- #if defined(ENABLE_LDAPI)
- /* ldapi */
- if(0 != ports->i_port) {
- ports->i_socket = createprlistensockets(1, ports->i_listenaddr, 0, 1);
- }
- #endif /* ENABLE_LDAPI */
- #endif
- return( rc );
- }
- /* Decide whether we're running on a platform which supports send with timeouts */
- static void detect_timeout_support()
- {
- /* Currently we know that NT4.0 or higher DOES support timeouts */
- #if defined _WIN32
- /* Get the OS revision */
- OSVERSIONINFO ver;
- ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&ver);
- if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 4) {
- have_send_timeouts = 1;
- }
- #else
- /* Some UNIXen do, but for now I don't feel confident which , and whether timeouts really work there */
- #endif
- }
- /*
- * The time_shutdown static variable is used to signal the time thread
- * to shutdown. We used to shut down the time thread when g_get_shutdown()
- * returned a non-zero value, but that caused the clock to stop, so to speak,
- * and all error log entries to have the same timestamp once the shutdown
- * process began.
- */
- static int time_shutdown = 0;
- void *
- time_thread(void *nothing)
- {
- PRIntervalTime interval;
- interval = PR_SecondsToInterval(1);
- while(!time_shutdown) {
- poll_current_time();
- csngen_update_time ();
- DS_Sleep(interval);
- }
- /*NOTREACHED*/
- return(NULL);
- }
- /*
- * Return a copy of the mount point for the specified directory
- */
- #ifdef SOLARIS
- char *
- disk_mon_get_mount_point(char *dir)
- {
- struct mnttab *mnt;
- struct stat s;
- dev_t dev_id;
- FILE *fp;
- fp = fopen("/etc/mnttab", "r");
- if (fp == NULL || stat(dir, &s) != 0) {
- return NULL;
- }
- dev_id = s.st_dev;
- while((mnt = getmntent(fp))){
- if (stat(mnt->mnt_mountp, &s) != 0) {
- continue;
- }
- if (s.st_dev == dev_id) {
- return (slapi_ch_strdup(mnt->mnt_mountp));
- }
- }
- return NULL;
- }
- #elif HPUX
- char *
- disk_mon_get_mount_point(char *dir)
- {
- struct mntent *mnt;
- struct stat s;
- dev_t dev_id;
- FILE *fp;
- if ((fp = setmntent("/etc/mnttab", "r")) == NULL) {
- return NULL;
- }
- if (stat(dir, &s) != 0) {
- return NULL;
- }
- dev_id = s.st_dev;
- while((mnt = getmntent(fp))){
- if (stat(mnt->mnt_dir, &s) != 0) {
- continue;
- }
- if (s.st_dev == dev_id) {
- endmntent(fp);
- return (slapi_ch_strdup(mnt->mnt_dir));
- }
- }
- endmntent(fp);
- return NULL;
- }
- #else /* Linux */
- char *
- disk_mon_get_mount_point(char *dir)
- {
- struct mntent *mnt;
- struct stat s;
- dev_t dev_id;
- FILE *fp;
- if (stat(dir, &s) != 0) {
- return NULL;
- }
- dev_id = s.st_dev;
- if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
- return NULL;
- }
- while((mnt = getmntent(fp))){
- if (stat(mnt->mnt_dir, &s) != 0) {
- continue;
- }
- if (s.st_dev == dev_id) {
- endmntent(fp);
- return (slapi_ch_strdup(mnt->mnt_dir));
- }
- }
- endmntent(fp);
- return NULL;
- }
- #endif
- /*
- * Get the mount point of the directory, and add it to the
- * list. Skip duplicate mount points.
- */
- void
- disk_mon_add_dir(char ***list, char *directory)
- {
- char *dir = disk_mon_get_mount_point(directory);
- if(dir == NULL)
- return;
- if(!charray_inlist(*list,dir)){
- slapi_ch_array_add(list, dir);
- } else {
- slapi_ch_free((void **)&dir);
- }
- }
- /*
- * We gather all the log, txn log, config, and db directories
- */
- void
- disk_mon_get_dirs(char ***list, int logs_critical){
- slapdFrontendConfig_t *config = getFrontendConfig();
- Slapi_Backend *be = NULL;
- char *cookie = NULL;
- char *dir = NULL;
- if(logs_critical){
- slapi_rwlock_rdlock(config->cfg_rwlock);
- disk_mon_add_dir(list, config->accesslog);
- disk_mon_add_dir(list, config->errorlog);
- disk_mon_add_dir(list, config->auditlog);
- slapi_rwlock_unlock(config->cfg_rwlock);
- }
- /* Add /var just to be safe */
- #ifdef LOCALSTATEDIR
- disk_mon_add_dir(list, LOCALSTATEDIR);
- #else
- disk_mon_add_dir(list, "/var");
- #endif
- /* config and backend directories */
- slapi_rwlock_rdlock(config->cfg_rwlock);
- disk_mon_add_dir(list, config->configdir);
- slapi_rwlock_unlock(config->cfg_rwlock);
- be = slapi_get_first_backend (&cookie);
- while (be) {
- if(slapi_back_get_info(be, BACK_INFO_DIRECTORY, (void **)&dir) == LDAP_SUCCESS){ /* db directory */
- disk_mon_add_dir(list, dir);
- }
- if(slapi_back_get_info(be, BACK_INFO_LOG_DIRECTORY, (void **)&dir) == LDAP_SUCCESS){ /* txn log dir */
- disk_mon_add_dir(list, dir);
- }
- be = (backend *)slapi_get_next_backend (cookie);
- }
- slapi_ch_free((void **)&cookie);
- }
- /*
- * This function checks the list of directories to see if any are below the
- * threshold. We return the the directory/free disk space of the most critical
- * directory.
- */
- char *
- disk_mon_check_diskspace(char **dirs, PRInt64 threshold, PRInt64 *disk_space)
- {
- #ifdef LINUX
- struct statfs buf;
- #else
- struct statvfs buf;
- #endif
- PRInt64 worst_disk_space = threshold;
- PRInt64 freeBytes = 0;
- PRInt64 blockSize = 0;
- char *worst_dir = NULL;
- int hit_threshold = 0;
- int i = 0;
- for(i = 0; dirs && dirs[i]; i++){
- #ifndef LINUX
- if (statvfs(dirs[i], &buf) != -1)
- #else
- if (statfs(dirs[i], &buf) != -1)
- #endif
- {
- LL_UI2L(freeBytes, buf.f_bavail);
- LL_UI2L(blockSize, buf.f_bsize);
- LL_MUL(freeBytes, freeBytes, blockSize);
- if(LL_UCMP(freeBytes, <, threshold)){
- hit_threshold = 1;
- if(LL_UCMP(freeBytes, <, worst_disk_space)){
- worst_disk_space = freeBytes;
- worst_dir = dirs[i];
- }
- }
- }
- }
- if(hit_threshold){
- *disk_space = worst_disk_space;
- return worst_dir;
- } else {
- *disk_space = 0;
- return NULL;
- }
- }
- #define LOGGING_OFF 0
- #define LOGGING_ON 1
- /*
- * Disk Space Monitoring Thread
- *
- * We need to monitor the free disk space of critical disks.
- *
- * If we get below the free disk space threshold, start taking measures
- * to avoid additional disk space consumption by stopping verbose logging,
- * access/audit logging, and deleting rotated logs.
- *
- * If this is not enough, then we need to shut slapd down to avoid
- * possibly corrupting the db.
- *
- * Future - it would be nice to be able to email an alert.
- */
- void
- disk_monitoring_thread(void *nothing)
- {
- char errorbuf[BUFSIZ];
- char **dirs = NULL;
- char *dirstr = NULL;
- PRInt64 previous_mark = 0;
- PRInt64 disk_space = 0;
- PRInt64 threshold = 0;
- time_t start = 0;
- time_t now = 0;
- int deleted_rotated_logs = 0;
- int logging_critical = 0;
- int preserve_logging = 0;
- int passed_threshold = 0;
- int verbose_logging = 0;
- int using_accesslog = 0;
- int using_auditlog = 0;
- int logs_disabled = 0;
- int grace_period = 0;
- int first_pass = 1;
- int halfway = 0;
- int ok_now = 0;
- while(!g_get_shutdown()) {
- if(!first_pass){
- PR_Lock(diskmon_mutex);
- PR_WaitCondVar(diskmon_cvar, PR_SecondsToInterval(10));
- PR_Unlock(diskmon_mutex);
- /*
- * We need to subtract from disk_space to account for the
- * logging we just did, it doesn't hurt if we subtract a
- * little more than necessary.
- */
- previous_mark = disk_space - 512;
- ok_now = 0;
- } else {
- first_pass = 0;
- }
- /*
- * Get the config settings, as they could have changed
- */
- logging_critical = config_get_disk_logging_critical();
- preserve_logging = config_get_disk_preserve_logging();
- grace_period = 60 * config_get_disk_grace_period(); /* convert it to seconds */
- verbose_logging = config_get_errorlog_level();
- threshold = config_get_disk_threshold();
- halfway = threshold / 2;
- if(config_get_auditlog_logging_enabled()){
- using_auditlog = 1;
- }
- if(config_get_accesslog_logging_enabled()){
- using_accesslog = 1;
- }
- /*
- * Check the disk space. Always refresh the list, as backends can be added
- */
- slapi_ch_array_free(dirs);
- dirs = NULL;
- disk_mon_get_dirs(&dirs, logging_critical);
- dirstr = disk_mon_check_diskspace(dirs, threshold, &disk_space);
- if(dirstr == NULL){
- /*
- * Good, none of our disks are within the threshold,
- * reset the logging if we turned it off
- */
- if(passed_threshold){
- if(logs_disabled){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is now within acceptable levels. "
- "Restoring the log settings.\n",0,0,0);
- if(using_accesslog){
- config_set_accesslog_enabled(LOGGING_ON);
- }
- if(using_auditlog){
- config_set_auditlog_enabled(LOGGING_ON);
- }
- } else {
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is now within acceptable levels.\n",0,0,0);
- }
- deleted_rotated_logs = 0;
- passed_threshold = 0;
- previous_mark = 0;
- logs_disabled = 0;
- }
- continue;
- } else {
- passed_threshold = 1;
- }
- /*
- * Check if we are already critical
- */
- if(disk_space < 4096){ /* 4 k */
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb. "
- "Signaling slapd for shutdown...\n", dirstr , (disk_space / 1024), 0);
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- return;
- }
- /*
- * If we are low, see if we are using verbose error logging, and turn it off
- */
- if(verbose_logging){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %d Kb, "
- "setting error loglevel to zero.\n", dirstr, (disk_space / 1024), 0);
- config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE, 0, errorbuf, CONFIG_APPLY);
- continue;
- }
- /*
- * If we are low, there's no verbose logging, logs are not critical, then disable the
- * access/audit logs, log another error, and continue.
- */
- if(!logs_disabled && (!preserve_logging || !logging_critical)){
- if(disk_space < previous_mark){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
- "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
- config_set_accesslog_enabled(LOGGING_OFF);
- config_set_auditlog_enabled(LOGGING_OFF);
- logs_disabled = 1;
- }
- continue;
- }
- /*
- * If we are low, we turned off verbose logging, logs are not critical, and we disabled
- * access/audit logging, then delete the rotated logs, log another error, and continue.
- */
- if(!deleted_rotated_logs && (!preserve_logging || !logging_critical)){
- if(disk_space < previous_mark){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
- "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
- log__delete_rotated_logs();
- deleted_rotated_logs = 1;
- }
- continue;
- }
- /*
- * Ok, we've done what we can, log a message if we continue to lose available disk space
- */
- if(disk_space < previous_mark){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb\n",
- dirstr, (disk_space / 1024), 0);
- }
- /*
- *
- * If we are below the halfway mark, and we did everything else,
- * go into shutdown mode. If the disk space doesn't get critical,
- * wait for the grace period before shutting down. This gives an
- * admin the chance to clean things up.
- *
- */
- if(disk_space < halfway){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%d bytes). "
- "Waiting %d minutes for disk space to be cleaned up before shutting slapd down...\n",
- dirstr, threshold, (grace_period / 60));
- time(&start);
- now = start;
- while( (now - start) < grace_period ){
- if(g_get_shutdown()){
- return;
- }
- /*
- * Sleep for a little bit, but we don't want to run out of disk space
- * while sleeping for the entire grace period
- */
- DS_Sleep(PR_SecondsToInterval(1));
- /*
- * Now check disk space again in hopes some space was freed up
- */
- dirstr = disk_mon_check_diskspace(dirs, threshold, &disk_space);
- if(!dirstr){
- /*
- * Excellent, we are back to acceptable levels, reset everything...
- */
- LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%d bytes). Aborting"
- " shutdown, and restoring the log settings.\n",disk_space,0,0);
- if(!preserve_logging && using_accesslog){
- config_set_accesslog_enabled(LOGGING_ON);
- }
- if(!preserve_logging && using_auditlog){
- config_set_auditlog_enabled(LOGGING_ON);
- }
- deleted_rotated_logs = 0;
- passed_threshold = 0;
- logs_disabled = 0;
- previous_mark = 0;
- ok_now = 1;
- start = 0;
- now = 0;
- break;
- } else if(disk_space < 4096){ /* 4 k */
- /*
- * Disk space is critical, log an error, and shut it down now!
- */
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb."
- " Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0);
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- return;
- }
- time(&now);
- }
- if(ok_now){
- /*
- * Disk space is acceptable, resume normal processing
- */
- continue;
- }
- /*
- * If disk space was freed up we would of detected in the above while loop. So shut it down.
- */
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is still too low (%d Kb). Signaling slapd for shutdown...\n",
- (disk_space / 1024), 0, 0);
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- return;
- }
- }
- }
- static void
- handle_listeners(Connection_Table *ct, listener_info *listener_idxs, int n_listeners)
- {
- int idx;
- for (idx = 0; idx < n_listeners; ++idx) {
- int fdidx = listener_idxs[idx].idx;
- PRFileDesc *listenfd = listener_idxs[idx].listenfd;
- int secure = listener_idxs[idx].secure;
- int local = listener_idxs[idx].local;
- if (fdidx && listenfd) {
- if (SLAPD_POLL_LISTEN_READY(ct->fd[fdidx].out_flags)) {
- /* accept() the new connection, put it on the active list for handle_pr_read_ready */
- int rc = handle_new_connection(ct, SLAPD_INVALID_SOCKET, listenfd, secure, local);
- if (rc) {
- LDAPDebug1Arg(LDAP_DEBUG_CONNS, "Error accepting new connection listenfd=%d\n",
- PR_FileDesc2NativeHandle(listenfd));
- continue;
- }
- }
- }
- }
- return;
- }
- void slapd_daemon( daemon_ports_t *ports )
- {
- /* We are passed some ports---one for regular connections, one
- * for SSL connections, one for ldapi connections.
- */
- /* Previously there was a ton of code #defined on NET_SSL.
- * This looked horrible, so now I'm doing it this way:
- * If you want me to do SSL, pass me something in the ssl port number.
- * If you don't, pass me zero.
- */
- #if defined( XP_WIN32 )
- int n_tcps = 0;
- int s_tcps_native = 0;
- PRFileDesc *s_tcps = NULL;
- #else
- PRFileDesc **n_tcps = NULL;
- PRFileDesc **s_tcps = NULL;
- PRFileDesc **i_unix = NULL;
- PRFileDesc **fdesp = NULL;
- #endif
- PRIntn num_poll = 0;
- PRIntervalTime pr_timeout = PR_MillisecondsToInterval(slapd_wakeup_timer);
- PRThread *time_thread_p;
- int threads;
- int in_referral_mode = config_check_referral_mode();
- int n_listeners = 0; /* number of listener sockets */
- listener_info *listener_idxs = NULL; /* array of indexes of listener sockets in the ct->fd array */
- int connection_table_size = get_configured_connection_table_size();
- the_connection_table= connection_table_new(connection_table_size);
- #ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS
- /*
- * Some DNS resolver implementations, such as the one built into
- * Solaris <= 8, need to use one or more low numbered file
- * descriptors internally (probably because they use a deficient
- * implementation of stdio). So we make a call now that uses the
- * resolver so it has an opportunity to grab whatever low file
- * descriptors it needs (before we use up all of the low numbered
- * ones for incoming client connections and so on).
- */
- get_loopback_by_addr();
- #endif
- /* Retrieve the sockets from their hiding place */
- n_tcps = ports->n_socket;
- s_tcps = ports->s_socket;
- #ifdef XP_WIN32
- s_tcps_native = ports->s_socket_native;
- #else
- #if defined(ENABLE_LDAPI)
- i_unix = ports->i_socket;
- #endif /* ENABLE_LDAPI */
- #endif
-
- createsignalpipe();
- init_shutdown_detect();
- if (
- #if defined( XP_WIN32 )
- (n_tcps == SLAPD_INVALID_SOCKET) &&
- #else
- (n_tcps == NULL) &&
- #if defined(ENABLE_LDAPI)
- (i_unix == NULL) &&
- #endif /* ENABLE_LDAPI */
- #endif
- (s_tcps == NULL) ) { /* nothing to do */
- LDAPDebug( LDAP_DEBUG_ANY,
- "no port to listen on\n", 0, 0, 0 );
- exit( 1 );
- }
- unfurl_banners(the_connection_table,ports,n_tcps,s_tcps,i_unix);
- init_op_threads ();
- detect_timeout_support();
- /* Start the time thread */
- time_thread_p = PR_CreateThread(PR_SYSTEM_THREAD,
- (VFP) (void *) time_thread, NULL,
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_JOINABLE_THREAD,
- SLAPD_DEFAULT_THREAD_STACKSIZE);
- if ( NULL == time_thread_p ) {
- PRErrorCode errorCode = PR_GetError();
- LDAPDebug(LDAP_DEBUG_ANY, "Unable to create time thread - Shutting Down ("
- SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n",
- errorCode, slapd_pr_strerror(errorCode), 0);
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- /*
- * If we are monitoring disk space, then create the mutex, the cvar,
- * and the monitoring thread.
- */
- if( config_get_disk_monitoring() ){
- if ( ( diskmon_mutex = PR_NewLock() ) == NULL ) {
- slapi_log_error(SLAPI_LOG_FATAL, NULL,
- "Cannot create new lock for disk space monitoring. "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- PR_GetError(), slapd_pr_strerror( PR_GetError() ));
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- if ( diskmon_mutex ){
- if(( diskmon_cvar = PR_NewCondVar( diskmon_mutex )) == NULL ) {
- slapi_log_error(SLAPI_LOG_FATAL, NULL,
- "Cannot create new condition variable for disk space monitoring. "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- PR_GetError(), slapd_pr_strerror( PR_GetError() ));
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- }
- if( diskmon_mutex && diskmon_cvar ){
- disk_thread_p = PR_CreateThread(PR_SYSTEM_THREAD,
- (VFP) (void *) disk_monitoring_thread, NULL,
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_JOINABLE_THREAD,
- SLAPD_DEFAULT_THREAD_STACKSIZE);
- if ( NULL == disk_thread_p ) {
- PRErrorCode errorCode = PR_GetError();
- LDAPDebug(LDAP_DEBUG_ANY, "Unable to create disk monitoring thread - Shutting Down ("
- SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n",
- errorCode, slapd_pr_strerror(errorCode), 0);
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- }
- }
- /* We are now ready to accept incoming connections */
- #if defined( XP_WIN32 )
- if ( n_tcps != SLAPD_INVALID_SOCKET
- && listen( n_tcps, DAEMON_LISTEN_SIZE ) == -1 ) {
- int oserr = errno;
- char addrbuf[ 256 ];
- slapi_log_error(SLAPI_LOG_FATAL, "slapd_daemon",
- "listen() on %s port %d failed: OS error %d (%s)\n",
- netaddr2string(&ports->n_listenaddr, addrbuf, sizeof(addrbuf)),
- ports->n_port, oserr, slapd_system_strerror( oserr ) );
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- n_listeners++;
- }
- #else
- if ( n_tcps != NULL ) {
- PRFileDesc **fdesp;
- PRNetAddr **nap = ports->n_listenaddr;
- for (fdesp = n_tcps; fdesp && *fdesp; fdesp++, nap++) {
- if ( PR_Listen( *fdesp, DAEMON_LISTEN_SIZE ) == PR_FAILURE ) {
- PRErrorCode prerr = PR_GetError();
- char addrbuf[ 256 ];
- slapi_log_error(SLAPI_LOG_FATAL, "slapd_daemon",
- "PR_Listen() on %s port %d failed: %s error %d (%s)\n",
- netaddr2string(*nap, addrbuf, sizeof(addrbuf)),
- ports->n_port, SLAPI_COMPONENT_NAME_NSPR, prerr,
- slapd_pr_strerror( prerr ));
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- n_listeners++;
- }
- }
- #endif
- if ( s_tcps != NULL ) {
- PRFileDesc **fdesp;
- PRNetAddr **sap = ports->s_listenaddr;
- for (fdesp = s_tcps; fdesp && *fdesp; fdesp++, sap++) {
- if ( PR_Listen( *fdesp, DAEMON_LISTEN_SIZE ) == PR_FAILURE ) {
- PRErrorCode prerr = PR_GetError();
- char addrbuf[ 256 ];
- slapi_log_error(SLAPI_LOG_FATAL, "slapd_daemon",
- "PR_Listen() on %s port %d failed: %s error %d (%s)\n",
- netaddr2string(*sap, addrbuf, sizeof(addrbuf)),
- ports->s_port, SLAPI_COMPONENT_NAME_NSPR, prerr,
- slapd_pr_strerror( prerr ));
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- n_listeners++;
- }
- }
- #if !defined( XP_WIN32 )
- #if defined(ENABLE_LDAPI)
- if( i_unix != NULL ) {
- PRFileDesc **fdesp;
- PRNetAddr **iap = ports->i_listenaddr;
- for (fdesp = i_unix; fdesp && *fdesp; fdesp++, iap++) {
- if ( PR_Listen(*fdesp, DAEMON_LISTEN_SIZE) == PR_FAILURE) {
- PRErrorCode prerr = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "slapd_daemon",
- "listen() on %s failed: error %d (%s)\n",
- (*iap)->local.path,
- prerr,
- slapd_pr_strerror( prerr ));
- g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
- }
- n_listeners++;
- }
- }
- #endif /* ENABLE_LDAPI */
- #endif
- listener_idxs = (listener_info *)slapi_ch_calloc(n_listeners, sizeof(*listener_idxs));
- /* Now we write the pid file, indicating that the server is finally and listening for connections */
- write_pid_file();
- /* The meat of the operation is in a loop on a call to select */
- while(!g_get_shutdown())
- {
- #ifdef _WIN32
- fd_set readfds;
- struct timeval wakeup_timer;
- int oserr;
- #endif
- int select_return = 0;
- #ifndef _WIN32
- PRErrorCode prerr;
- #endif
- #ifdef _WIN32
- set_timeval_ms(&wakeup_timer, slapd_wakeup_timer);
- setup_read_fds(the_connection_table,&readfds,n_tcps, s_tcps_native);
- /* This select needs to timeout to give the server a chance to test for shutdown */
- select_return = select(connection_table_size, &readfds, NULL, 0, &wakeup_timer);
- #else
- setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll,listener_idxs,n_listeners);
- select_return = POLL_FN(the_connection_table->fd, num_poll, pr_timeout);
- #endif
- switch (select_return) {
- case 0: /* Timeout */
- /* GGOODREPL handle_timeout(); */
- break;
- case -1: /* Error */
- #ifdef _WIN32
- oserr = errno;
- LDAPDebug( LDAP_DEBUG_TRACE,
- "select failed errno %d (%s)\n", oserr,
- slapd_system_strerror(oserr), 0 );
- #else
- prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_TRACE, "PR_Poll() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_system_strerror(prerr), 0 );
- #endif
- break;
- default: /* either a new connection or some new data ready */
- /* Figure out if we are dealing with one of the listen sockets */
- #ifdef _WIN32
- /* If so, then handle a new connection */
- if ( n_tcps != SLAPD_INVALID_SOCKET && FD_ISSET( n_tcps,&readfds ) ) {
- handle_new_connection(the_connection_table,n_tcps,NULL,0,0);
- }
- /* If so, then handle a new connection */
- if ( s_tcps != SLAPD_INVALID_SOCKET && FD_ISSET( s_tcps_native,&readfds ) ) {
- handle_new_connection(the_connection_table,SLAPD_INVALID_SOCKET,s_tcps,1,0);
- }
- /* handle new data ready */
- handle_read_ready(the_connection_table,&readfds);
- clear_signal(&readfds);
- #else
- /* handle new connections from the listeners */
- handle_listeners(the_connection_table, listener_idxs, n_listeners);
- /* handle new data ready */
- handle_pr_read_ready(the_connection_table, connection_table_size);
- clear_signal(the_connection_table->fd);
- #endif
- break;
- }
- }
- /* We get here when the server is shutting down */
- /* Do what we have to do before death */
- connection_table_abandon_all_operations(the_connection_table); /* abandon all operations in progress */
-
- if ( ! in_referral_mode ) {
- ps_stop_psearch_system(); /* stop any persistent searches */
- }
- #ifdef _WIN32
- if ( n_tcps != SLAPD_INVALID_SOCKET ) {
- closesocket( n_tcps );
- }
- if ( s_tcps != NULL ) {
- PR_Close( s_tcps );
- }
- #else
- for (fdesp = n_tcps; fdesp && *fdesp; fdesp++) {
- PR_Close( *fdesp );
- }
- slapi_ch_free ((void**)&n_tcps);
- for (fdesp = i_unix; fdesp && *fdesp; fdesp++) {
- PR_Close( *fdesp );
- }
- slapi_ch_free ((void**)&i_unix);
- for (fdesp = s_tcps; fdesp && *fdesp; fdesp++) {
- PR_Close( *fdesp );
- }
- slapi_ch_free ((void**)&s_tcps);
- /* freeing NetAddrs */
- {
- PRNetAddr **nap;
- for (nap = ports->n_listenaddr; nap && *nap; nap++) {
- slapi_ch_free ((void**)nap);
- }
- slapi_ch_free ((void**)&ports->n_listenaddr);
- for (nap = ports->s_listenaddr; nap && *nap; nap++) {
- slapi_ch_free ((void**)nap);
- }
- slapi_ch_free ((void**)&ports->s_listenaddr);
- #if defined(ENABLE_LDAPI)
- for (nap = ports->i_listenaddr; nap && *nap; nap++) {
- slapi_ch_free ((void**)nap);
- }
- slapi_ch_free ((void**)&ports->i_listenaddr);
- #endif
- }
- #endif
- /* Might compete with housecleaning thread, but so far so good */
- be_flushall();
- op_thread_cleanup();
- housekeeping_stop(); /* Run this after op_thread_cleanup() logged sth */
- disk_monitoring_stop(disk_thread_p);
- #ifndef _WIN32
- threads = g_get_active_threadcnt();
- if ( threads > 0 ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd shutting down - waiting for %d thread%s to terminate\n",
- threads, ( threads > 1 ) ? "s" : "", 0 );
- }
- #endif
- threads = g_get_active_threadcnt();
- while ( threads > 0 ) {
- PRPollDesc xpd;
- char x;
- int spe = 0;
- /* try to read from the signal pipe, in case threads are
- * blocked on it. */
- xpd.fd = signalpipe[0];
- xpd.in_flags = PR_POLL_READ;
- xpd.out_flags = 0;
- spe = PR_Poll(&xpd, 1, PR_INTERVAL_NO_WAIT);
- if (spe > 0) {
- spe = PR_Read(signalpipe[0], &x, 1);
- if (spe < 0) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "listener could not clear signal pipe, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_system_strerror(prerr), 0 );
- break;
- }
- } else if (spe == -1) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "PR_Poll() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_system_strerror(prerr), 0 );
- break;
- } else {
- /* no data */
- }
- DS_Sleep(PR_INTERVAL_NO_WAIT);
- if ( threads != g_get_active_threadcnt() ) {
- LDAPDebug( LDAP_DEBUG_TRACE,
- "slapd shutting down - waiting for %d threads to terminate\n",
- g_get_active_threadcnt(), 0, 0 );
- threads = g_get_active_threadcnt();
- }
- }
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd shutting down - closing down internal subsystems and plugins\n",
- 0, 0, 0 );
- log_access_flush();
- /* let backends do whatever cleanup they need to do */
- LDAPDebug( LDAP_DEBUG_TRACE,"slapd shutting down - waiting for backends to close down\n", 0, 0,0 );
- eq_stop();
- if ( ! in_referral_mode ) {
- task_shutdown();
- uniqueIDGenCleanup ();
- }
- plugin_closeall( 1 /* Close Backends */, 1 /* Close Gloabls */);
- if ( ! in_referral_mode ) {
- /* Close SNMP collator after the plugins closed...
- * Replication plugin still performs internal ops that
- * may try to increment snmp stats.
- * Fix for defect 523780
- */
- snmp_collator_stop();
- mapping_tree_free ();
- }
- /*
- * connection_table_free could use callbacks in the backend.
- * (e.g., be_search_results_release)
- * Thus, it needs to be called before be_cleanupall.
- */
- connection_table_free(the_connection_table);
- the_connection_table= NULL;
- be_cleanupall ();
- LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
- 0, 0, 0 );
- referrals_free();
- /* tell the time thread to shutdown and then wait for it */
- time_shutdown = 1;
- PR_JoinThread( time_thread_p );
- #ifdef _WIN32
- WSACleanup();
- #endif
- }
- int signal_listner()
- {
- /* Replaces previous macro---called to bump the thread out of select */
- #if defined( _WIN32 )
- if ( PR_Write( signalpipe[1], "", 1) != 1 ) {
- /* this now means that the pipe is full
- * this is not a problem just go-on
- */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "listener could not write to signal pipe %d\n",
- errno, 0, 0 );
- }
-
- #else
- if ( write( writesignalpipe, "", 1) != 1 ) {
- /* this now means that the pipe is full
- * this is not a problem just go-on
- */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "listener could not write to signal pipe %d\n",
- errno, 0, 0 );
- }
- #endif
- return( 0 );
- }
- #ifdef _WIN32
- static int clear_signal(fd_set *readfdset)
- #else
- static int clear_signal(struct POLL_STRUCT *fds)
- #endif
- {
- #ifdef _WIN32
- if ( FD_ISSET(readsignalpipe, readfdset)) {
- #else
- if ( fds[FDS_SIGNAL_PIPE].out_flags & SLAPD_POLL_FLAGS ) {
- #endif
- char buf[200];
- LDAPDebug( LDAP_DEBUG_CONNS,
- "listener got signaled\n",
- 0, 0, 0 );
- #ifdef _WIN32
- if ( PR_Read( signalpipe[0], buf, 20 ) < 1 ) {
- #else
- if ( read( readsignalpipe, buf, 200 ) < 1 ) {
- #endif
- LDAPDebug( LDAP_DEBUG_ANY,
- "listener could not clear signal pipe\n",
- 0, 0, 0 );
- }
- }
- return 0;
- }
- #ifdef _WIN32
- static void set_timeval_ms(struct timeval *t, int ms)
- {
- t->tv_sec = ms/1000;
- t->tv_usec = (ms % 1000)*1000;
- }
- #endif
- #ifdef _WIN32
- static void setup_read_fds(Connection_Table *ct, fd_set *readfds, int n_tcps, int s_tcps)
- {
- Connection *c= NULL;
- Connection *next= NULL;
- int accept_new_connections;
- static int last_accept_new_connections = -1;
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- LBER_SOCKET socketdesc = SLAPD_INVALID_SOCKET;
- FD_ZERO( readfds );
- accept_new_connections = ((ct->size - g_get_current_conn_count())
- > slapdFrontendConfig->reservedescriptors);
- if ( ! accept_new_connections ) {
- if ( last_accept_new_connections ) {
- LDAPDebug( LDAP_DEBUG_ANY, "Not listening for new "
- "connections - too many fds open\n", 0, 0, 0 );
- }
- } else {
- if ( ! last_accept_new_connections &&
- last_accept_new_connections != -1 ) {
- LDAPDebug( LDAP_DEBUG_ANY, "Listening for new "
- "connections again\n", 0, 0, 0 );
- }
- }
- last_accept_new_connections = accept_new_connections;
- if (n_tcps != SLAPD_INVALID_SOCKET && accept_new_connections) {
- FD_SET( n_tcps, readfds );
- LDAPDebug( LDAP_DEBUG_HOUSE,
- "listening for connections on %d\n", n_tcps, 0, 0 );
- }
- if (s_tcps != SLAPD_INVALID_SOCKET && accept_new_connections) {
- FD_SET( s_tcps, readfds );
- LDAPDebug( LDAP_DEBUG_HOUSE,
- "listening for connections on %d\n", s_tcps, 0, 0 );
- }
- if ((s_tcps != SLAPD_INVALID_SOCKET)
- && (readsignalpipe != SLAPD_INVALID_SOCKET)) {
- FD_SET( readsignalpipe, readfds );
- }
- /* Walk down the list of active connections to find
- * out which connections we should poll over. If a connection
- * is no longer in use, we should remove it from the linked
- * list. */
- c= connection_table_get_first_active_connection (ct);
- while (c)
- {
- next = connection_table_get_next_active_connection (ct, c);
- if ( c->c_mutex == NULL )
- {
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else
- {
- PR_Lock( c->c_mutex );
- if ( c->c_flags & CONN_FLAG_CLOSING )
- {
- /* A worker thread has marked that this connection
- * should be closed by calling disconnect_server.
- * move this connection out of the active list
- * the last thread to use the connection will close it
- */
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else if ( c->c_sd == SLAPD_INVALID_SOCKET )
- {
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else
- {
- #if defined(LDAP_IOCP) /* When we have IO completion ports, we don't want to do this */
- if ( !c->c_gettingber && (c->c_flags & CONN_FLAG_SSL) )
- #else
- if ( !c->c_gettingber )
- #endif
- {
- FD_SET( c->c_sd, readfds );
- }
- }
- PR_Unlock( c->c_mutex );
- }
- c = next;
- }
- }
- #endif /* _WIN32 */
- static int first_time_setup_pr_read_pds = 1;
- static int listen_addr_count = 0;
- static void
- setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners)
- {
- Connection *c= NULL;
- Connection *next= NULL;
- LBER_SOCKET socketdesc = SLAPD_INVALID_SOCKET;
- int accept_new_connections;
- static int last_accept_new_connections = -1;
- PRIntn count = 0;
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- int max_threads_per_conn = config_get_maxthreadsperconn();
- int n_listeners = 0;
- accept_new_connections = ((ct->size - g_get_current_conn_count())
- > slapdFrontendConfig->reservedescriptors);
- if ( ! accept_new_connections ) {
- if ( last_accept_new_connections ) {
- LDAPDebug( LDAP_DEBUG_ANY, "Not listening for new "
- "connections - too many fds open\n", 0, 0, 0 );
- /* reinitialize n_tcps and s_tcps to the pds */
- first_time_setup_pr_read_pds = 1;
- }
- } else {
- if ( ! last_accept_new_connections &&
- last_accept_new_connections != -1 ) {
- LDAPDebug( LDAP_DEBUG_ANY, "Listening for new "
- "connections again\n", 0, 0, 0 );
- /* reinitialize n_tcps and s_tcps to the pds */
- first_time_setup_pr_read_pds = 1;
- }
- }
- last_accept_new_connections = accept_new_connections;
- /* initialize the mapping from connection table entries to fds entries */
- if (first_time_setup_pr_read_pds)
- {
- int i;
- for (i = 0; i < ct->size; i++)
- {
- ct->c[i].c_fdi = SLAPD_INVALID_SOCKET_INDEX;
- }
- /* The fds entry for the signalpipe is always FDS_SIGNAL_PIPE (== 0) */
- count = FDS_SIGNAL_PIPE;
- #if !defined(_WIN32)
- ct->fd[count].fd = signalpipe[0];
- ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
- ct->fd[count].out_flags = 0;
- #else
- ct->fd[count].fd = NULL;
- #endif
- count++;
- /* The fds entry for n_tcps starts with n_tcps and less than n_tcpe */
- ct->n_tcps = count;
- if (n_tcps != NULL && accept_new_connections)
- {
- PRFileDesc **fdesc = NULL;
- for (fdesc = n_tcps; fdesc && *fdesc; fdesc++, count++) {
- ct->fd[count].fd = *fdesc;
- ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
- ct->fd[count].out_flags = 0;
- listener_idxs[n_listeners].listenfd = *fdesc;
- listener_idxs[n_listeners].idx = count;
- n_listeners++;
- LDAPDebug( LDAP_DEBUG_HOUSE,
- "listening for connections on %d\n", socketdesc, 0, 0 );
- }
- } else {
- ct->fd[count].fd = NULL;
- count++;
- }
- ct->n_tcpe = count;
-
- ct->s_tcps = count;
- /* The fds entry for s_tcps starts with s_tcps and less than s_tcpe */
- if (s_tcps != NULL && accept_new_connections)
- {
- PRFileDesc **fdesc = NULL;
- for (fdesc = s_tcps; fdesc && *fdesc; fdesc++, count++) {
- ct->fd[count].fd = *fdesc;
- ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
- ct->fd[count].out_flags = 0;
- listener_idxs[n_listeners].listenfd = *fdesc;
- listener_idxs[n_listeners].idx = count;
- listener_idxs[n_listeners].secure = 1;
- n_listeners++;
- LDAPDebug( LDAP_DEBUG_HOUSE,
- "listening for SSL connections on %d\n", socketdesc, 0, 0 );
- }
- } else {
- ct->fd[count].fd = NULL;
- count++;
- }
- ct->s_tcpe = count;
- #if !defined(_WIN32)
- #if defined(ENABLE_LDAPI)
- ct->i_unixs = count;
- /* The fds entry for i_unix starts with i_unixs and less than i_unixe */
- if (i_unix != NULL && accept_new_connections)
- {
- PRFileDesc **fdesc = NULL;
- for (fdesc = i_unix; fdesc && *fdesc; fdesc++, count++) {
- ct->fd[count].fd = *fdesc;
- ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
- ct->fd[count].out_flags = 0;
- listener_idxs[n_listeners].listenfd = *fdesc;
- listener_idxs[n_listeners].idx = count;
- listener_idxs[n_listeners].local = 1;
- n_listeners++;
- LDAPDebug( LDAP_DEBUG_HOUSE,
- "listening for LDAPI connections on %d\n", socketdesc, 0, 0 );
- }
- } else {
- ct->fd[count].fd = NULL;
- count++;
- }
- ct->i_unixe = count;
- #endif
- #endif
-
- first_time_setup_pr_read_pds = 0;
- listen_addr_count = count;
- if (n_listeners < max_listeners) {
- listener_idxs[n_listeners].idx = 0;
- listener_idxs[n_listeners].listenfd = NULL;
- }
- }
- /* count is the number of entries we've place in the fds array.
- * listen_addr_count is counted up when
- * first_time_setup_pr_read_pds is TURE. */
- count = listen_addr_count;
-
- /* Walk down the list of active connections to find
- * out which connections we should poll over. If a connection
- * is no longer in use, we should remove it from the linked
- * list. */
- c = connection_table_get_first_active_connection (ct);
- while (c)
- {
- next = connection_table_get_next_active_connection (ct, c);
- if ( c->c_mutex == NULL )
- {
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else
- {
- PR_Lock( c->c_mutex );
- if (c->c_flags & CONN_FLAG_CLOSING)
- {
- /* A worker thread has marked that this connection
- * should be closed by calling disconnect_server.
- * move this connection out of the active list
- * the last thread to use the connection will close it
- */
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else if ( c->c_sd == SLAPD_INVALID_SOCKET )
- {
- connection_table_move_connection_out_of_active_list(ct,c);
- }
- else if ( c->c_prfd != NULL)
- {
- if ((!c->c_gettingber)
- && (c->c_threadnumber < max_threads_per_conn))
- {
- int add_fd = 1;
- /* check timeout for PAGED RESULTS */
- if (pagedresults_is_timedout_nolock(c))
- {
- /* Exceeded the timelimit; disconnect the client */
- disconnect_server_nomutex(c, c->c_connid, -1,
- SLAPD_DISCONNECT_IO_TIMEOUT,
- 0);
- connection_table_move_connection_out_of_active_list(ct,
- c);
- add_fd = 0; /* do not poll on this fd */
- }
- if (add_fd)
- {
- ct->fd[count].fd = c->c_prfd;
- ct->fd[count].in_flags = SLAPD_POLL_FLAGS;
- /* slot i of the connection table is mapped to slot
- * count of the fds array */
- c->c_fdi = count;
- count++;
- }
- }
- else
- {
- c->c_fdi = SLAPD_INVALID_SOCKET_INDEX;
- }
- }
- PR_Unlock( c->c_mutex );
- }
- c = next;
- }
- if( num_to_read )
- (*num_to_read) = count;
- }
- #ifdef notdef /* GGOODREPL */
- static void
- handle_timeout( void )
- {
- static time_t prevtime = 0;
- static time_t housekeeping_fire_time = 0;
- time_t curtime = current_time();
- if (0 == prevtime) {
- prevtime = time (&housekeeping_fire_time);
- }
- if ( difftime(curtime, prevtime) >=
- slapd_housekeeping_timer ) {
- int num_active_threads;
- snmp_collator_update();
- prevtime = curtime;
- num_active_threads = g_get_active_threadcnt();
- if ( (num_active_threads == 0) ||
- (difftime(curtime, housekeeping_fire_time) >=
- slapd_housekeeping_timer*3) ) {
- housekeeping_fire_time = curtime;
- housekeeping_start(curtime);
- }
- }
- }
- #endif /* notdef */
- static int idletimeout_reslimit_handle = -1;
- /*
- * Register the idletimeout with the binder-based resource limits
- * subsystem. A SLAPI_RESLIMIT_STATUS_... code is returned.
- */
- int
- daemon_register_reslimits( void )
- {
- return( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT, "nsIdleTimeout",
- &idletimeout_reslimit_handle ));
- }
- /*
- * Compute the idle timeout for the connection.
- *
- * Note: this function must always be called with conn->c_mutex locked.
- */
- static int
- compute_idletimeout( slapdFrontendConfig_t *fecfg, Connection *conn )
- {
- int idletimeout;
- if ( slapi_reslimit_get_integer_limit( conn, idletimeout_reslimit_handle,
- &idletimeout ) != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- /*
- * No limit associated with binder/connection or some other error
- * occurred. If the user is anonymous and anonymous limits are
- * set, attempt to set the bind based resource limits. We do this
- * here since a BIND operation is not required prior to other
- * operations. We want to set the anonymous limits early on so
- * that they are put into effect if a BIND is never sent. If
- * this is not an anonymous user and no bind-based limits are set,
- * use the default idle timeout.
- */
- char *anon_dn = config_get_anon_limits_dn();
- if ((conn->c_dn == NULL) && anon_dn && (strlen(anon_dn) > 0)) {
- Slapi_DN *anon_sdn = slapi_sdn_new_dn_byref( anon_dn );
- reslimit_update_from_dn( conn, anon_sdn );
- if ( slapi_reslimit_get_integer_limit( conn,
- idletimeout_reslimit_handle, &idletimeout ) !=
- SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- idletimeout = fecfg->idletimeout;
- }
- slapi_sdn_free( &anon_sdn );
- } else if ( conn->c_isroot ) {
- idletimeout = 0; /* no limit for Directory Manager */
- } else {
- idletimeout = fecfg->idletimeout;
- }
- slapi_ch_free_string( &anon_dn );
- }
- return( idletimeout );
- }
- #ifdef _WIN32
- static void
- handle_read_ready(Connection_Table *ct, fd_set *readfds)
- {
- Connection *c= NULL;
- time_t curtime = current_time();
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- int idletimeout;
- #ifdef LDAP_DEBUG
- if ( slapd_ldap_debug & LDAP_DEBUG_CONNS )
- {
- connection_table_dump_activity_to_errors_log(ct);
- }
- #endif /* LDAP_DEBUG */
- /* Instead of going through the whole connection table to see which
- * connections we can read from, we'll only check the slots in the
- * linked list */
- c = connection_table_get_first_active_connection (ct);
- while ( c!=NULL )
- {
- if ( c->c_mutex != NULL )
- {
- PR_Lock( c->c_mutex );
- if (connection_is_active_nolock (c) && c->c_gettingber == 0 )
- {
- /* read activity */
- short readready= ( FD_ISSET( c->c_sd, readfds ) );
- /* read activity */
- if ( readready )
- {
- LDAPDebug( LDAP_DEBUG_CONNS, "read activity on %d\n", c->c_ci, 0, 0 );
- c->c_idlesince = curtime;
- /* This is where the work happens ! */
- connection_activity( c );
- /* idle timeout */
- }
- else if (( idletimeout = compute_idletimeout(
- slapdFrontendConfig, c )) > 0 &&
- (curtime - c->c_idlesince) >= idletimeout &&
- NULL == c->c_ops )
- {
- disconnect_server_nomutex( c, c->c_connid, -1,
- SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN );
- }
- }
- PR_Unlock( c->c_mutex );
- }
- c = connection_table_get_next_active_connection (ct, c);
- }
- }
- #endif /* _WIN32 */
- static void
- handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll)
- {
- Connection *c;
- time_t curtime = current_time();
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- int idletimeout;
- #if defined( XP_WIN32 )
- int i;
- #endif
- #if LDAP_DEBUG
- if ( slapd_ldap_debug & LDAP_DEBUG_CONNS )
- {
- connection_table_dump_activity_to_errors_log(ct);
- }
- #endif /* LDAP_DEBUG */
- #if defined( XP_WIN32 )
- /*
- * WIN32: this function is only called for SSL connections and
- * num_poll indicates exactly how many PR fds we polled on.
- */
- for ( i = 0; i < num_poll; i++ )
- {
- short readready;
- readready = (ct->fd[i].out_flags & SLAPD_POLL_FLAGS);
- /* Find the connection we are referring to */
- for ( c = connection_table_get_first_active_connection (ct); c != NULL;
- c = connection_table_get_next_active_connection (ct, c) )
- {
- if ( c->c_mutex != NULL )
- {
- PR_Lock( c->c_mutex );
- if ( c->c_prfd == ct->fd[i].fd )
- {
- break; /* c_mutex is still locked! */
- }
- PR_Unlock( c->c_mutex );
- }
- }
- if ( c == NULL )
- { /* connection not found! */
- LDAPDebug( LDAP_DEBUG_CONNS, "handle_pr_read_ready: "
- "connection not found for poll slot %d\n", i,0,0 );
- }
- else
- {
- /* c_mutex is still locked... check for activity and errors */
- if ( !readready && ct->fd[i].out_flags && c->c_prfd == ct->fd[i].fd )
- {
- /* some error occured */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "poll says connection on sd %d is bad "
- "(closing)\n", c->c_sd, 0, 0 );
- disconnect_server_nomutex( c, c->c_connid, -1, SLAPD_DISCONNECT_POLL, EPIPE );
- }
- else if ( readready && c->c_prfd == ct->fd[i].fd )
- {
- /* read activity */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "read activity on %d\n", i, 0, 0 );
- c->c_idlesince = curtime;
- /* This is where the work happens ! */
- connection_activity( c );
- }
- else if (( idletimeout = compute_idletimeout( slapdFrontendConfig,
- c )) > 0 &&
- c->c_prfd == ct->fd[i].fd &&
- (curtime - c->c_idlesince) >= idletimeout &&
- NULL == c->c_ops )
- {
- /* idle timeout */
- disconnect_server_nomutex( c, c->c_connid, -1,
- SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN );
- }
- PR_Unlock( c->c_mutex );
- }
- }
- #else
- /*
- * non-WIN32: this function is called for all connections, so we
- * traverse the entire active connection list to find any errors,
- * activity, etc.
- */
- for ( c = connection_table_get_first_active_connection (ct); c != NULL;
- c = connection_table_get_next_active_connection (ct, c) )
- {
- if ( c->c_mutex != NULL )
- {
- PR_Lock( c->c_mutex );
- if ( connection_is_active_nolock (c) && c->c_gettingber == 0 )
- {
- PRInt16 out_flags;
- short readready;
- if (c->c_fdi != SLAPD_INVALID_SOCKET_INDEX)
- {
- out_flags = ct->fd[c->c_fdi].out_flags;
- }
- else
- {
- out_flags = 0;
- }
- readready = ( out_flags & SLAPD_POLL_FLAGS );
- if ( !readready && out_flags )
- {
- /* some error occured */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "POLL_FN() says connection on sd %d is bad "
- "(closing)\n", c->c_sd, 0, 0 );
- disconnect_server_nomutex( c, c->c_connid, -1,
- SLAPD_DISCONNECT_POLL, EPIPE );
- }
- else if ( readready )
- {
- /* read activity */
- LDAPDebug( LDAP_DEBUG_CONNS,
- "read activity on %d\n", c->c_ci, 0, 0 );
- c->c_idlesince = curtime;
- /* This is where the work happens ! */
- /* MAB: 25 jan 01, error handling added */
- if ((connection_activity( c )) == -1) {
- /* This might happen as a result of
- * trying to acquire a closing connection
- */
- LDAPDebug (LDAP_DEBUG_ANY,
- "connection_activity: abandoning conn %" NSPRIu64 " as fd=%d is already closing\n",
- c->c_connid,c->c_sd,0);
- /* The call disconnect_server should do nothing,
- * as the connection c should be already set to CLOSING */
- disconnect_server_nomutex( c, c->c_connid, -1,
- SLAPD_DISCONNECT_POLL, EPIPE );
- }
- }
- else if (( idletimeout = compute_idletimeout(
- slapdFrontendConfig, c )) > 0 &&
- (curtime - c->c_idlesince) >= idletimeout &&
- NULL == c->c_ops )
- {
- /* idle timeout */
- disconnect_server_nomutex( c, c->c_connid, -1,
- SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN );
- }
- }
- PR_Unlock( c->c_mutex );
- }
- }
- #endif
- }
- /*
- * wrapper functions required so we can implement ioblock_timeout and
- * avoid blocking forever.
- */
- #define SLAPD_POLLIN 0
- #define SLAPD_POLLOUT 1
- /* Return 1 if the given handle is ready for input or output,
- * or if it becomes ready within g_ioblock_timeout [msec].
- * Return -1 if handle is not ready and g_ioblock_timeout > 0,
- * or something goes seriously wrong. Otherwise, return 0.
- * If -1 is returned, PR_GetError() explains why.
- * Revision: handle changed to void * to allow 64bit support
- */
- static int
- slapd_poll( void *handle, int output )
- {
- int rc;
- int ioblock_timeout = config_get_ioblocktimeout();
-
- #if defined( XP_WIN32 )
- if( !secure ) {
- fd_set handle_set;
- struct timeval timeout;
- int windows_handle = (int) handle;
- memset (&timeout, 0, sizeof(timeout));
- if (ioblock_timeout > 0) {
- timeout.tv_sec = ioblock_timeout / 1000;
- timeout.tv_usec = (ioblock_timeout % 1000) * 1000;
- }
- FD_ZERO(&handle_set);
- FD_SET(windows_handle, &handle_set);
- rc = output ? select(FD_SETSIZE, NULL, &handle_set, NULL, &timeout)
- : select(FD_SETSIZE, &handle_set, NULL, NULL, &timeout);
- } else {
- struct POLL_STRUCT pr_pd;
- PRIntervalTime timeout = PR_MillisecondsToInterval( ioblock_timeout );
- if (timeout < 0) timeout = 0;
- pr_pd.fd = (PRFileDesc *)handle;
- pr_pd.in_flags = output ? PR_POLL_WRITE : PR_POLL_READ;
- pr_pd.out_flags = 0;
- rc = POLL_FN(&pr_pd, 1, timeout);
- }
- #else
- struct POLL_STRUCT pr_pd;
- PRIntervalTime timeout = PR_MillisecondsToInterval(ioblock_timeout);
- pr_pd.fd = (PRFileDesc *)handle;
- pr_pd.in_flags = output ? PR_POLL_WRITE : PR_POLL_READ;
- pr_pd.out_flags = 0;
- rc = POLL_FN(&pr_pd, 1, timeout);
- #endif
- if (rc < 0) {
- #if defined( XP_WIN32 )
- if( !secure ) {
- int oserr = errno;
- LDAPDebug(LDAP_DEBUG_CONNS, "slapd_poll(%d) error %d (%s)\n",
- handle, oserr, slapd_system_strerror(oserr));
- if ( SLAPD_SYSTEM_WOULD_BLOCK_ERROR(oserr)) {
- rc = 0; /* try again */
- }
- } else {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug(LDAP_DEBUG_CONNS, "slapd_poll(%d) "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- handle, prerr, slapd_pr_strerror(prerr));
- if ( prerr == PR_PENDING_INTERRUPT_ERROR ||
- SLAPD_PR_WOULD_BLOCK_ERROR(prerr)) {
- rc = 0; /* try again */
- }
- }
- #else
- PRErrorCode prerr = PR_GetError();
- LDAPDebug(LDAP_DEBUG_ANY, "slapd_poll(%d) "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- handle, prerr, slapd_pr_strerror(prerr));
- if ( prerr == PR_PENDING_INTERRUPT_ERROR ||
- SLAPD_PR_WOULD_BLOCK_ERROR(prerr)) {
- rc = 0; /* try again */
- }
- #endif
- } else if (rc == 0 && ioblock_timeout > 0) {
- PRIntn ihandle;
- #if !defined( XP_WIN32 )
- ihandle = PR_FileDesc2NativeHandle((PRFileDesc *)handle);
- #else
- if( secure )
- ihandle = PR_FileDesc2NativeHandle((PRFileDesc *)handle);
- else
- ihandle = (PRIntn)handle;
- #endif
- LDAPDebug(LDAP_DEBUG_ANY, "slapd_poll(%d) timed out\n",
- ihandle, 0, 0);
- #if defined( XP_WIN32 )
- /*
- * Bug 624303 - This connection will be cleaned up soon.
- * During cleanup (see connection_cleanup()), SSL3_SendAlert()
- * will be called by PR_Close(), and its default wTimeout
- * in sslSocket associated with the handle
- * is no time out (I gave up after waited for 30 minutes).
- * It was during this closing period that server won't
- * response to new connection requests.
- * PR_Send() null is a hack here to change the default wTimeout
- * (see ssl_Send()) to one second which affects PR_Close()
- * only in the current scenario.
- */
- if( secure ) {
- PR_Send ((PRFileDesc *)handle, NULL, 0, 0, PR_SecondsToInterval(1));
- }
- #endif
- PR_SetError(PR_IO_TIMEOUT_ERROR, EAGAIN); /* timeout */
- rc = -1;
- }
- return rc;
- }
- /*
- * Revision: handle changed to void * and first
- * argument which used to be integer system fd is now ignored.
- */
- #if defined(USE_OPENLDAP)
- static int
- write_function( int ignore, void *buffer, int count, void *handle )
- #else
- static int
- write_function( int ignore, const void *buffer, int count, struct lextiof_socket_private *handle )
- #endif
- {
- int sentbytes = 0;
- int bytes;
- int fd = PR_FileDesc2NativeHandle((PRFileDesc *)handle);
- if (handle == SLAPD_INVALID_SOCKET) {
- PR_SetError(PR_NOT_SOCKET_ERROR, EBADF);
- } else {
- while (1) {
- if (slapd_poll(handle, SLAPD_POLLOUT) < 0) { /* error */
- break;
- }
- bytes = PR_Write((PRFileDesc *)handle, (char *)buffer + sentbytes,
- count - sentbytes);
- if (bytes > 0) {
- sentbytes += bytes;
- } else if (bytes < 0) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug(LDAP_DEBUG_CONNS, "PR_Write(%d) "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- fd, prerr, slapd_pr_strerror( prerr ));
- if ( !SLAPD_PR_WOULD_BLOCK_ERROR(prerr)) {
- if (prerr != PR_CONNECT_RESET_ERROR) {
- /* 'TCP connection reset by peer': no need to log */
- LDAPDebug(LDAP_DEBUG_ANY, "PR_Write(%d) "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- fd, prerr, slapd_pr_strerror( prerr ));
- }
- if (sentbytes < count) {
- LDAPDebug(LDAP_DEBUG_CONNS,
- "PR_Write(%d) - wrote only %d bytes (expected %d bytes) - 0 (EOF)\n", /* disconnected */
- fd, sentbytes, count);
- }
- break; /* fatal error */
- }
- } else if (bytes == 0) { /* disconnect */
- PRErrorCode prerr = PR_GetError();
- LDAPDebug(LDAP_DEBUG_CONNS,
- "PR_Write(%d) - 0 (EOF) %d:%s\n", /* disconnected */
- fd, prerr, slapd_pr_strerror(prerr));
- PR_SetError(PR_PIPE_ERROR, EPIPE);
- break;
- }
- if (sentbytes == count) { /* success */
- return count;
- } else if (sentbytes > count) { /* too many bytes */
- LDAPDebug(LDAP_DEBUG_ANY,
- "PR_Write(%d) overflow - sent %d bytes (expected %d bytes) - error\n",
- fd, sentbytes, count);
- PR_SetError(PR_BUFFER_OVERFLOW_ERROR, EMSGSIZE);
- break;
- }
- }
- }
- return -1;
- }
- #if defined(USE_OPENLDAP)
- /* The argument is a pointer to the socket descriptor */
- static int
- openldap_io_setup(Sockbuf_IO_Desc *sbiod, void *arg)
- {
- PR_ASSERT(sbiod);
- if (arg != NULL) {
- sbiod->sbiod_pvt = arg;
- }
- return 0;
- }
- static ber_slen_t
- openldap_write_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
- {
- Connection *conn = NULL;
- PRFileDesc *fd = NULL;
- PR_ASSERT(sbiod);
- PR_ASSERT(sbiod->sbiod_pvt);
- conn = (Connection *)sbiod->sbiod_pvt;
- PR_ASSERT(conn->c_prfd);
- fd = (PRFileDesc *)conn->c_prfd;
- PR_ASSERT(fd != SLAPD_INVALID_SOCKET);
- return write_function(0, buf, len, fd);
- }
- static int
- openldap_io_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
- {
- PR_ASSERT(0); /* not sure if this is needed */
- return -1;
- }
- static int
- openldap_io_close(Sockbuf_IO_Desc *sbiod)
- {
- return 0; /* closing done in connection_cleanup() */
- }
- static Sockbuf_IO openldap_sockbuf_io = {
- openldap_io_setup, /* sbi_setup */
- NULL, /* sbi_remove */
- openldap_io_ctrl, /* sbi_ctrl */
- openldap_read_function, /* sbi_read */ /* see connection.c */
- openldap_write_function, /* sbi_write */
- openldap_io_close /* sbi_close */
- };
- #endif /* USE_OPENLDAP */
- int connection_type = -1; /* The type number assigned by the Factory for 'Connection' */
- void
- daemon_register_connection()
- {
- if(connection_type==-1)
- {
- /* The factory is given the name of the object type, in
- * return for a type handle. Whenever the object is created
- * or destroyed the factory is called with the handle so
- * that it may call the constructors or destructors registered
- * with it.
- */
- connection_type= factory_register_type(SLAPI_EXT_CONNECTION,offsetof(Connection,c_extension));
- }
- }
- #if defined(ENABLE_LDAPI)
- int
- slapd_identify_local_user(Connection *conn)
- {
- int ret = -1;
- uid_t uid = 0;
- gid_t gid = 0;
- conn->c_local_valid = 0;
- if(0 == slapd_get_socket_peer(conn->c_prfd, &uid, &gid))
- {
- conn->c_local_uid = uid;
- conn->c_local_gid = gid;
- conn->c_local_valid = 1;
- ret = 0;
- }
- return ret;
- }
- #if defined(ENABLE_AUTOBIND)
- int
- slapd_bind_local_user(Connection *conn)
- {
- int ret = -1;
- uid_t uid = conn->c_local_uid;
- gid_t gid = conn->c_local_gid;
- if (!conn->c_local_valid)
- {
- goto bail;
- }
- /* observe configuration for auto binding */
- /* bind at all? */
- if(config_get_ldapi_bind_switch())
- {
- /* map users to a dn
- root may also map to an entry
- */
- /* require real entry? */
- if(config_get_ldapi_map_entries())
- {
- /* get uid type to map to (e.g. uidNumber) */
- char *utype = config_get_ldapi_uidnumber_type();
- /* get gid type to map to (e.g. gidNumber) */
- char *gtype = config_get_ldapi_gidnumber_type();
- /* get base dn for search */
- char *base_dn = config_get_ldapi_search_base_dn();
- /* search vars */
- Slapi_PBlock *search_pb = 0;
- Slapi_Entry **entries = 0;
- int result;
- /* filter manipulation vars */
- char *one_type = 0;
- char *filter_tpl = 0;
- char *filter = 0;
- /* create filter, matching whatever is given */
- if(utype && gtype)
- {
- filter_tpl = "(&(%s=%u)(%s=%u))";
- }
- else
- {
- if(utype || gtype)
- {
- filter_tpl = "(%s=%u)";
- if(utype)
- one_type = utype;
- else
- one_type = gtype;
- }
- else
- {
- goto entry_map_free;
- }
- }
- if(one_type)
- {
- if(one_type == utype)
- filter = slapi_ch_smprintf(filter_tpl,
- utype, uid);
- else
- filter = slapi_ch_smprintf(filter_tpl,
- gtype, gid);
- }
- else
- {
- filter = slapi_ch_smprintf(filter_tpl,
- utype, uid, gtype, gid);
- }
- /* search for single entry matching types */
- search_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(
- search_pb,
- base_dn,
- LDAP_SCOPE_SUBTREE,
- filter,
- NULL, 0, NULL, NULL,
- (void*)plugin_get_default_component_id(),
- 0);
- slapi_search_internal_pb(search_pb);
- slapi_pblock_get(
- search_pb,
- SLAPI_PLUGIN_INTOP_RESULT,
- &result);
- if(LDAP_SUCCESS == result)
- slapi_pblock_get(
- search_pb,
- SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
- if(entries)
- {
- /* zero or multiple entries fail */
- if(entries[0] && 0 == entries[1])
- {
- /* observe account locking */
- ret = slapi_check_account_lock(
- 0, /* pb not req */
- entries[0],
- 0, /* no response control */
- 0, /* don't check password policy */
- 0 /* don't send ldap result */
- );
- if(0 == ret)
- {
- char *auth_dn = slapi_ch_strdup(
- slapi_entry_get_ndn(
- entries[0]));
- auth_dn = slapi_dn_normalize(
- auth_dn);
- bind_credentials_set_nolock(
- conn,
- SLAPD_AUTH_OS,
- auth_dn,
- NULL, NULL,
- NULL , entries[0]);
- ret = 0;
- }
- }
- }
- entry_map_free:
- /* auth_dn consumed by bind creds set */
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
- slapi_ch_free_string(&filter);
- slapi_ch_free_string(&utype);
- slapi_ch_free_string(>ype);
- slapi_ch_free_string(&base_dn);
- }
- if(ret && 0 == uid)
- {
- /* map unix root (uidNumber:0)? */
- char *root_dn = config_get_ldapi_root_dn();
- if(root_dn)
- {
- Slapi_DN *edn = slapi_sdn_new_dn_byref(
- slapi_dn_normalize(root_dn));
- Slapi_Entry *e = 0;
- /* root might be locked too! :) */
- ret = slapi_search_internal_get_entry(
- edn, 0,
- &e,
- (void*)plugin_get_default_component_id()
- );
- if(0 == ret && e)
- {
- ret = slapi_check_account_lock(
- 0, /* pb not req */
- e,
- 0, /* no response control */
- 0, /* don't check password policy */
- 0 /* don't send ldap result */
- );
- if(1 == ret)
- /* sorry root,
- * just not cool enough
- */
- goto root_map_free;
- }
- /* it's ok not to find the entry,
- * dn doesn't have to have an entry
- * e.g. cn=Directory Manager
- */
- bind_credentials_set_nolock(
- conn, SLAPD_AUTH_OS, root_dn,
- NULL, NULL, NULL , e);
- root_map_free:
- /* root_dn consumed by bind creds set */
- slapi_sdn_free(&edn);
- slapi_entry_free(e);
- ret = 0;
- }
- }
- #if defined(ENABLE_AUTO_DN_SUFFIX)
- if(ret)
- {
- /* create phony auth dn? */
- char *base = config_get_ldapi_auto_dn_suffix();
- if(base)
- {
- char *tpl = "gidNumber=%u+uidNumber=%u,";
- int len =
- strlen(tpl) +
- strlen(base) +
- 51 /* uid,gid,null,w/padding */
- ;
- char *dn_str = (char*)slapi_ch_malloc(
- len);
- char *auth_dn = (char*)slapi_ch_malloc(
- len);
- dn_str[0] = 0;
- strcpy(dn_str, tpl);
- strcat(dn_str, base);
- sprintf(auth_dn, dn_str, gid, uid);
- auth_dn = slapi_dn_normalize(auth_dn);
- bind_credentials_set_nolock(
- conn,
- SLAPD_AUTH_OS,
- auth_dn,
- NULL, NULL, NULL , NULL);
- /* auth_dn consumed by bind creds set */
- slapi_ch_free_string(&dn_str);
- slapi_ch_free_string(&base);
- ret = 0;
- }
- }
- #endif
- }
- bail:
- /* if all fails, the peer is anonymous */
- if(conn->c_dn)
- {
- /* log the auto bind */
- slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 " AUTOBIND dn=\"%s\"\n", conn->c_connid, conn->c_dn);
- }
- return ret;
- }
- #endif /* ENABLE_AUTOBIND */
- #endif /* ENABLE_LDAPI */
- /* NOTE: this routine is not reentrant */
- static int
- handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local)
- {
- int ns = 0;
- Connection *conn = NULL;
- /* struct sockaddr_in from;*/
- PRNetAddr from;
- PRFileDesc *pr_clonefd = NULL;
- memset(&from, 0, sizeof(from)); /* reset to nulls so we can see what was set */
- if ( (ns = accept_and_configure( tcps, pr_acceptfd, &from,
- sizeof(from), secure, local, &pr_clonefd)) == SLAPD_INVALID_SOCKET ) {
- return -1;
- }
- /* get a new Connection from the Connection Table */
- conn= connection_table_get_connection(ct,ns);
- if(conn==NULL)
- {
- PR_Close(pr_acceptfd);
- return -1;
- }
- PR_Lock( conn->c_mutex );
- #if defined( XP_WIN32 )
- if( !secure )
- ber_sockbuf_set_option(conn->c_sb,LBER_SOCKBUF_OPT_DESC,&ns);
- #endif
- conn->c_sd = ns;
- conn->c_prfd = pr_clonefd;
- conn->c_flags &= ~CONN_FLAG_CLOSING;
- /* Store the fact that this new connection is an SSL connection */
- if (secure) {
- conn->c_flags |= CONN_FLAG_SSL;
- }
- #ifndef _WIN32
- /*
- * clear the "returned events" field in ns' slot within the poll fds
- * array so that handle_read_ready() doesn't look at out_flags for an
- * old connection by mistake and do something bad such as close the
- * connection we just accepted.
- */
- /* Dont have to worry about this now because of our mapping from
- * the connection table to the fds array. This new connection
- * won't have a mapping. */
- /* fds[ns].out_flags = 0; */
- #endif
- #if defined(USE_OPENLDAP)
- ber_sockbuf_add_io( conn->c_sb, &openldap_sockbuf_io,
- LBER_SBIOD_LEVEL_PROVIDER, conn );
- #else /* !USE_OPENLDAP */
- {
- struct lber_x_ext_io_fns func_pointers;
- memset(&func_pointers, 0, sizeof(func_pointers));
- func_pointers.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
- func_pointers.lbextiofn_read = NULL; /* see connection_read_function */
- func_pointers.lbextiofn_write = write_function;
- func_pointers.lbextiofn_writev = NULL;
- #ifdef _WIN32
- func_pointers.lbextiofn_socket_arg = (struct lextiof_socket_private *) ns;
- #else
- func_pointers.lbextiofn_socket_arg = (struct lextiof_socket_private *) pr_clonefd;
- #endif
- ber_sockbuf_set_option( conn->c_sb,
- LBER_SOCKBUF_OPT_EXT_IO_FNS, &func_pointers);
- }
- #endif /* !USE_OPENLDAP */
- if( secure && config_get_SSLclientAuth() != SLAPD_SSLCLIENTAUTH_OFF ) {
- /* Prepare to handle the client's certificate (if any): */
- int rv;
- rv = slapd_ssl_handshakeCallback (conn->c_prfd, (void*)handle_handshake_done, conn);
-
- if (rv < 0) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug (LDAP_DEBUG_ANY, "SSL_HandshakeCallback() %d "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- rv, prerr, slapd_pr_strerror( prerr ));
- }
- rv = slapd_ssl_badCertHook (conn->c_prfd, (void*)handle_bad_certificate, conn);
- if (rv < 0) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug (LDAP_DEBUG_ANY, "SSL_BadCertHook(%i) %i "
- SLAPI_COMPONENT_NAME_NSPR " error %d\n",
- conn->c_sd, rv, prerr);
- }
- }
- connection_reset(conn, ns, &from, sizeof(from), secure);
- /* Call the plugin extension constructors */
- conn->c_extension = factory_create_extension(connection_type,conn,NULL /* Parent */);
- #if defined(ENABLE_LDAPI)
- #if !defined( XP_WIN32 )
- /* ldapi */
- if( local )
- {
- conn->c_unix_local = 1;
- conn->c_local_ssf = config_get_localssf();
- slapd_identify_local_user(conn);
- }
- #endif
- #endif /* ENABLE_LDAPI */
- connection_new_private(conn);
- /* Add this connection slot to the doubly linked list of active connections. This
- * list is used to find the connections that should be used in the poll call. This
- * connection will be added directly after slot 0 which serves as the head of the list.
- * This must be done as the very last thing before we unlock the mutex, because once it
- * is added to the active list, it is live. */
- if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL )
- {
- /* Now give the new connection to the connection code */
- connection_table_move_connection_on_to_active_list(the_connection_table,conn);
- }
- PR_Unlock( conn->c_mutex );
- g_increment_current_conn_count();
- return 0;
- }
- static int init_shutdown_detect()
- {
- #ifdef _WIN32
- PRThread *service_exit_wait_tid;
- #else
- /* First of all, we must reset the signal mask to get rid of any blockages
- * the process may have inherited from its parent (such as the console), which
- * might result in the process not delivering those blocked signals, and thus,
- * misbehaving....
- */
- {
- int rc;
- sigset_t proc_mask;
-
- LDAPDebug( LDAP_DEBUG_TRACE, "Reseting signal mask....\n", 0, 0, 0);
- (void)sigemptyset( &proc_mask );
- rc = pthread_sigmask( SIG_SETMASK, &proc_mask, NULL );
- LDAPDebug( LDAP_DEBUG_TRACE, " %s \n",
- rc ? "Failed to reset signal mask":"....Done (signal mask reset)!!", 0, 0 );
- }
- #endif
-
- #ifdef _WIN32
- /* Create a thread to wait on the Win32 event which will
- be signalled by the watchdog when the Service is
- being halted. */
- service_exit_wait_tid = PR_CreateThread( PR_USER_THREAD,
- (VFP) (void *) slapd_service_exit_wait, (void *) NULL,
- PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
- SLAPD_DEFAULT_THREAD_STACKSIZE);
- if( service_exit_wait_tid == NULL ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Error: PR_CreateThread(slapd_service_exit_wait) failed\n", 0, 0, 0 );
- }
- #elif defined ( HPUX10 )
- PR_CreateThread ( PR_USER_THREAD,
- catch_signals,
- NULL,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- SLAPD_DEFAULT_THREAD_STACKSIZE);
- #else
- #ifdef HPUX11
- /* In the optimized builds for HPUX, the signal handler doesn't seem
- * to get set correctly unless the primordial thread gets a chance
- * to run before we make the call to SIGNAL. (At this point the
- * the primordial thread has spawned the daemon thread which called
- * this function.) The call to DS_Sleep will give the primordial
- * thread a chance to run.
- */
- DS_Sleep(0);
- #endif
- (void) SIGNAL( SIGPIPE, SIG_IGN );
- (void) SIGNAL( SIGCHLD, slapd_wait4child );
- #ifndef LINUX
- /* linux uses USR1/USR2 for thread synchronization, so we aren't
- * allowed to mess with those.
- */
- (void) SIGNAL( SIGUSR1, slapd_do_nothing );
- (void) SIGNAL( SIGUSR2, set_shutdown );
- #endif
- (void) SIGNAL( SIGTERM, set_shutdown );
- (void) SIGNAL( SIGHUP, set_shutdown );
- #endif /* _WIN32 */
- return 0;
- }
- #if defined( XP_WIN32 )
- static void
- unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, int n_tcps, PRFileDesc *s_tcps)
- #else
- static void
- unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix)
- #endif
- {
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- char addrbuf[ 256 ];
- int isfirsttime = 1;
- if ( ct->size <= slapdFrontendConfig->reservedescriptors ) {
- #ifdef _WIN32
- LDAPDebug( LDAP_DEBUG_ANY,
- "ERROR: Not enough descriptors to accept any connections. "
- "This may be because the maxdescriptors configuration "
- "directive is too small, or the reservedescriptors "
- "configuration directive is too large. "
- "Try increasing the number of descriptors available to "
- "the slapd process. The current value is %d. %d "
- "descriptors are currently reserved for internal "
- "slapd use, so the total number of descriptors available "
- "to the process must be greater than %d.\n",
- ct->size, slapdFrontendConfig->reservedescriptors, slapdFrontendConfig->reservedescriptors );
- #else /* _WIN32 */
- LDAPDebug( LDAP_DEBUG_ANY,
- "ERROR: Not enough descriptors to accept any connections. "
- "This may be because the maxdescriptors configuration "
- "directive is too small, the hard limit on descriptors is "
- "too small (see limit(1)), or the reservedescriptors "
- "configuration directive is too large. "
- "Try increasing the number of descriptors available to "
- "the slapd process. The current value is %d. %d "
- "descriptors are currently reserved for internal "
- "slapd use, so the total number of descriptors available "
- "to the process must be greater than %d.\n",
- ct->size, slapdFrontendConfig->reservedescriptors, slapdFrontendConfig->reservedescriptors );
- #endif /* _WIN32 */
- exit( 1 );
- }
- /*
- * This final startup message gives a definite signal to the admin
- * program that the server is up. It must contain the string
- * "slapd started." because some of the administrative programs
- * depend on this. See ldap/admin/lib/dsalib_updown.c.
- */
- #if !defined( XP_WIN32 )
- if ( n_tcps != NULL ) { /* standard LDAP */
- PRNetAddr **nap = NULL;
- for (nap = ports->n_listenaddr; nap && *nap; nap++) {
- if (isfirsttime) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAP requests\n",
- netaddr2string(*nap, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- isfirsttime = 0;
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAP requests\n",
- netaddr2string(*nap, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- }
- }
- }
- if ( s_tcps != NULL ) { /* LDAP over SSL; separate port */
- PRNetAddr **sap = NULL;
- for (sap = ports->s_listenaddr; sap && *sap; sap++) {
- if (isfirsttime) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAPS requests\n",
- netaddr2string(*sap, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- isfirsttime = 0;
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAPS requests\n",
- netaddr2string(*sap, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- }
- }
- }
- #else
- if ( n_tcps != SLAPD_INVALID_SOCKET ) { /* standard LDAP; XP_WIN32 */
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAP requests\n",
- netaddr2string(&ports->n_listenaddr, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- }
- if ( s_tcps != NULL ) { /* LDAP over SSL; separate port */
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAPS requests\n",
- netaddr2string(&ports->s_listenaddr, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- }
- #endif
- #if !defined( XP_WIN32 )
- #if defined(ENABLE_LDAPI)
- if ( i_unix != NULL ) { /* LDAPI */
- PRNetAddr **iap = ports->i_listenaddr;
- LDAPDebug( LDAP_DEBUG_ANY,
- "%sListening on %s for LDAPI requests\n", isfirsttime?"slapd started. ":"",
- (*iap)->local.path, 0 );
- }
- #endif /* ENABLE_LDAPI */
- #endif
- }
- #if defined( _WIN32 )
- /* On Windows, we signal the SCM when we're ready to accept connections */
- static int
- write_pid_file()
- {
- if( SlapdIsAService() )
- {
- /* Initialization complete and successful. Set service to running */
- LDAPServerStatus.dwCurrentState = SERVICE_RUNNING;
- LDAPServerStatus.dwCheckPoint = 0;
- LDAPServerStatus.dwWaitHint = 0;
-
- if (!SetServiceStatus(hLDAPServerServiceStatus, &LDAPServerStatus)) {
- ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_START_FAILED, 1,
- "Could not set Service status.");
- exit(1);
- }
- }
- ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_STARTED, 0, NULL );
- return 0;
- }
- #else /* WIN32 */
- /* On UNIX, we create a file with our PID in it */
- static int
- write_pid_file()
- {
- FILE *fp = NULL;
- /*
- * The following section of code is closely coupled with the
- * admin programs. Please do not make changes here without
- * consulting the start/stop code for the admin code.
- */
- if ( (fp = fopen( get_pid_file(), "w" )) != NULL ) {
- fprintf( fp, "%d\n", getpid() );
- fclose( fp );
- if ( chmod(get_pid_file(), S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) != 0 ) {
- unlink(get_pid_file());
- } else {
- return 0;
- }
- }
- return -1;
- }
- #endif /* WIN32 */
- static void
- set_shutdown (int sig)
- {
- /* don't log anything from a signal handler:
- * you could be holding a lock when the signal was trapped. more
- * specifically, you could be holding the logfile lock (and deadlock
- * yourself).
- */
- #if 0
- LDAPDebug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
- #endif
- g_set_shutdown( SLAPI_SHUTDOWN_SIGNAL );
- #ifndef _WIN32
- #ifndef LINUX
- /* don't mess with USR1/USR2 on linux, used by libpthread */
- (void) SIGNAL( SIGUSR2, set_shutdown );
- #endif
- (void) SIGNAL( SIGTERM, set_shutdown );
- (void) SIGNAL( SIGHUP, set_shutdown );
- #endif
- }
- #ifndef LINUX
- void
- slapd_do_nothing (int sig)
- {
- /* don't log anything from a signal handler:
- * you could be holding a lock when the signal was trapped. more
- * specifically, you could be holding the logfile lock (and deadlock
- * yourself).
- */
- #if 0
- LDAPDebug( LDAP_DEBUG_TRACE, "slapd got SIGUSR1\n", 0, 0, 0 );
- #endif
- #ifndef _WIN32
- (void) SIGNAL( SIGUSR1, slapd_do_nothing );
- #endif
- #if 0
- /*
- * Actually do a little more: dump the conn struct and
- * send it to a tmp file
- */
- connection_table_dump(connection_table);
- #endif
- }
- #endif /* LINUX */
- #ifndef _WIN32
- void
- slapd_wait4child(int sig)
- {
- WAITSTATUSTYPE status;
- /* don't log anything from a signal handler:
- * you could be holding a lock when the signal was trapped. more
- * specifically, you could be holding the logfile lock (and deadlock
- * yourself).
- */
- #if 0
- LDAPDebug( LDAP_DEBUG_ARGS, "listener: catching SIGCHLD\n", 0, 0, 0 );
- #endif
- #ifdef USE_WAITPID
- while (waitpid ((pid_t) -1, 0, WAIT_FLAGS) > 0)
- #else /* USE_WAITPID */
- while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
- #endif /* USE_WAITPID */
- ; /* NULL */
- (void) SIGNAL( SIGCHLD, slapd_wait4child );
- }
- #endif
- #ifdef XP_WIN32
- static int
- createlistensocket(unsigned short port, const PRNetAddr *listenaddr)
- {
- int tcps;
- struct sockaddr_in addr;
- char *logname = "createlistensocket";
- char addrbuf[ 256 ];
- if (!port) goto suppressed;
- PR_ASSERT( listenaddr != NULL );
- /* create TCP socket */
- if ((tcps = socket(AF_INET, SOCK_STREAM, 0))
- == SLAPD_INVALID_SOCKET) {
- int oserr = errno;
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "socket() failed: OS error %d (%s)\n",
- oserr, slapd_system_strerror( oserr ));
- goto failed;
- }
-
- /* initialize listener address */
- (void) memset( (void *) &addr, '\0', sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_port = htons( port );
- if (listenaddr->raw.family == PR_AF_INET) {
- addr.sin_addr.s_addr = listenaddr->inet.ip;
- } else if (PR_IsNetAddrType(listenaddr,PR_IpAddrAny)) {
- addr.sin_addr.s_addr = INADDR_ANY;
- } else {
- if (!PR_IsNetAddrType(listenaddr,PR_IpAddrV4Mapped)) {
- /*
- * When Win32 supports IPv6, we will be able to use IPv6
- * addresses here. But not yet.
- */
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "unable to listen on %s port %d (IPv6 addresses "
- "are not supported on this platform)\n",
- netaddr2string(listenaddr, addrbuf, sizeof(addrbuf)),
- port );
- goto failed;
- }
- addr.sin_addr.s_addr = listenaddr->ipv6.ip.pr_s6_addr32[3];
- }
- LDAPDebug( LDAP_DEBUG_TRACE, "%s - binding to %s:%d\n",
- logname, inet_ntoa( addr.sin_addr ), port )
- if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
- int oserr = errno;
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "bind() on %s port %d failed: OS error %d (%s)\n",
- inet_ntoa( addr.sin_addr ), port, oserr,
- slapd_system_strerror( oserr ));
- goto failed;
- }
- return tcps;
- failed:
- WSACleanup();
- exit( 1 );
- suppressed:
- return -1;
- } /* createlistensocket */
- #endif /* XP_WIN32 */
- static PRFileDesc **
- createprlistensockets(PRUint16 port, PRNetAddr **listenaddr,
- int secure, int local)
- {
- PRFileDesc **sock;
- PRNetAddr sa_server;
- PRErrorCode prerr = 0;
- PRSocketOptionData pr_socketoption;
- char addrbuf[ 256 ];
- char *logname = "createprlistensockets";
- int sockcnt = 0;
- int socktype;
- char *socktype_str = NULL;
- PRNetAddr **lap;
- int i;
- if (!port) goto suppressed;
- PR_ASSERT( listenaddr != NULL );
- /* need to know the count */
- sockcnt = 0;
- for (lap = listenaddr; lap && *lap; lap++) {
- sockcnt++;
- }
- if (0 == sockcnt) {
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "There is no address to listen\n");
- goto failed;
- }
- sock = (PRFileDesc **)slapi_ch_calloc(sockcnt + 1, sizeof(PRFileDesc *));
- pr_socketoption.option = PR_SockOpt_Reuseaddr;
- pr_socketoption.value.reuse_addr = 1;
- for (i = 0, lap = listenaddr; lap && *lap && i < sockcnt; i++, lap++) {
- /* create TCP socket */
- socktype = PR_NetAddrFamily(*lap);
- #if defined(ENABLE_LDAPI)
- if (PR_AF_LOCAL == socktype) {
- socktype_str = "PR_AF_LOCAL";
- } else
- #endif
- if (PR_AF_INET6 == socktype) {
- socktype_str = "PR_AF_INET6";
- } else {
- socktype_str = "PR_AF_INET";
- }
- if ((sock[i] = PR_OpenTCPSocket(socktype)) == SLAPD_INVALID_SOCKET) {
- prerr = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "PR_OpenTCPSocket(%s) failed: %s error %d (%s)\n",
- socktype_str,
- SLAPI_COMPONENT_NAME_NSPR, prerr, slapd_pr_strerror(prerr));
- goto failed;
- }
- if ( PR_SetSocketOption(sock[i], &pr_socketoption ) == PR_FAILURE) {
- prerr = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "PR_SetSocketOption(PR_SockOpt_Reuseaddr) failed: %s error %d (%s)\n",
- SLAPI_COMPONENT_NAME_NSPR, prerr, slapd_pr_strerror( prerr ));
- goto failed;
- }
- /* set up listener address, including port */
- memcpy(&sa_server, *lap, sizeof(sa_server));
- if(!local)
- PRLDAP_SET_PORT( &sa_server, port );
- if ( PR_Bind(sock[i], &sa_server) == PR_FAILURE) {
- prerr = PR_GetError();
- if(!local)
- {
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "PR_Bind() on %s port %d failed: %s error %d (%s)\n",
- netaddr2string(&sa_server, addrbuf, sizeof(addrbuf)), port,
- SLAPI_COMPONENT_NAME_NSPR, prerr, slapd_pr_strerror(prerr));
- }
- #if defined(ENABLE_LDAPI)
- else
- {
- slapi_log_error(SLAPI_LOG_FATAL, logname,
- "PR_Bind() on %s file %s failed: %s error %d (%s)\n",
- netaddr2string(&sa_server, addrbuf, sizeof(addrbuf)),
- sa_server.local.path,
- SLAPI_COMPONENT_NAME_NSPR, prerr, slapd_pr_strerror(prerr));
- }
- #endif /* ENABLE_LDAPI */
- goto failed;
- }
- }
- #if defined(ENABLE_LDAPI)
- if(local) { /* ldapi */
- if(chmod((*listenaddr)->local.path,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))
- {
- slapi_log_error(SLAPI_LOG_FATAL, logname, "err: %d", errno);
- }
- }
- #endif /* ENABLE_LDAPI */
- return( sock );
- failed:
- #ifdef XP_WIN32
- WSACleanup();
- #endif /* XP_WIN32 */
- exit( 1 );
- suppressed:
- return (PRFileDesc **)-1;
- } /* createprlistensockets */
- /*
- * Initialize the *addr structure based on listenhost.
- * Returns: 0 if successful and -1 if not (after logging an error message).
- */
- int
- slapd_listenhost2addr(const char *listenhost, PRNetAddr ***addr)
- {
- char *logname = "slapd_listenhost2addr";
- PRErrorCode prerr = 0;
- int rval = 0;
- PRNetAddr *netaddr = (PRNetAddr *)slapi_ch_calloc(1, sizeof(PRNetAddr));
- PR_ASSERT( addr != NULL );
- *addr = NULL;
- if (NULL == listenhost) {
- /* listen on all interfaces */
- if ( PR_SUCCESS != PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, netaddr)) {
- prerr = PR_GetError();
- slapi_log_error( SLAPI_LOG_FATAL, logname,
- "PR_SetNetAddr(PR_IpAddrAny) failed - %s error %d (%s)\n",
- SLAPI_COMPONENT_NAME_NSPR, prerr, slapd_pr_strerror(prerr));
- rval = -1;
- slapi_ch_free ((void**)&netaddr);
- }
- *addr = (PRNetAddr **)slapi_ch_calloc(2, sizeof (PRNetAddr *));
- (*addr)[0] = netaddr;
- } else if (PR_SUCCESS == PR_StringToNetAddr(listenhost, netaddr)) {
- /* PR_StringNetAddr newer than NSPR v4.6.2 supports both IPv4&v6 */;
- *addr = (PRNetAddr **)slapi_ch_calloc(2, sizeof (PRNetAddr *));
- (*addr)[0] = netaddr;
- } else {
- PRAddrInfo *infop = PR_GetAddrInfoByName( listenhost,
- PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME) );
- if ( NULL != infop ) {
- void *iter = NULL;
- int addrcnt = 0;
- int i = 0;
- memset( netaddr, 0, sizeof( PRNetAddr ));
- /* need to count the address, first */
- while ( (iter = PR_EnumerateAddrInfo( iter, infop, 0, netaddr ))
- != NULL ) {
- addrcnt++;
- }
- if ( 0 == addrcnt ) {
- slapi_log_error( SLAPI_LOG_FATAL, logname,
- "PR_EnumerateAddrInfo for %s failed - %s error %d (%s)\n",
- listenhost, SLAPI_COMPONENT_NAME_NSPR, prerr,
- slapd_pr_strerror(prerr));
- rval = -1;
- } else {
- char **strnetaddrs = NULL;
- *addr = (PRNetAddr **)slapi_ch_calloc(addrcnt + 1, sizeof (PRNetAddr *));
- iter = NULL; /* from the beginning */
- memset( netaddr, 0, sizeof( PRNetAddr ));
- for ( i = 0; i < addrcnt; i++ ) {
- char abuf[256];
- char *abp = abuf;
- iter = PR_EnumerateAddrInfo( iter, infop, 0, netaddr );
- if ( NULL == iter ) {
- break;
- }
- /*
- * Check if the netaddr is duplicated or not.
- * IPv4 mapped IPv6 could be the identical to IPv4 addr.
- */
- netaddr2string(netaddr, abuf, sizeof(abuf));
- if (PR_IsNetAddrType(netaddr, PR_IpAddrV4Mapped)) {
- /* IPv4 mapped IPv6; redundant to IPv4;
- * cut the "::ffff:" part. */
- abp = strrchr(abuf, ':');
- if (abp) {
- abp++;
- } else {
- abp = abuf;
- }
- }
- if (charray_inlist(strnetaddrs, abp)) {
- LDAPDebug2Args(LDAP_DEBUG_ANY,
- "slapd_listenhost2addr: "
- "detected duplicated address %s "
- "[%s]\n", abuf, abp);
- } else {
- LDAPDebug1Arg(LDAP_DEBUG_TRACE,
- "slapd_listenhost2addr: "
- "registering address %s\n", abp);
- slapi_ch_array_add(&strnetaddrs, slapi_ch_strdup(abp));
- (*addr)[i] = netaddr;
- netaddr =
- (PRNetAddr *)slapi_ch_calloc(1, sizeof(PRNetAddr));
- }
- }
- slapi_ch_free((void **)&netaddr); /* not used */
- slapi_ch_array_free(strnetaddrs);
- }
- PR_FreeAddrInfo( infop );
- } else {
- slapi_log_error( SLAPI_LOG_FATAL, logname,
- "PR_GetAddrInfoByName(%s) failed - %s error %d (%s)\n",
- listenhost, SLAPI_COMPONENT_NAME_NSPR, prerr,
- slapd_pr_strerror(prerr));
- rval = -1;
- }
- }
- return rval;
- }
- /*
- * Map addr to a string equivalent and place the result in addrbuf.
- */
- static const char *
- netaddr2string(const PRNetAddr *addr, char *addrbuf, size_t addrbuflen)
- {
- const char *retstr;
- if (NULL == addr || PR_IsNetAddrType(addr, PR_IpAddrAny)) {
- retstr = "All Interfaces";
- } else if (PR_IsNetAddrType(addr, PR_IpAddrLoopback)) {
- if ( addr->raw.family == PR_AF_INET6 &&
- !PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
- retstr = "IPv6 Loopback";
- } else {
- retstr = "Loopback";
- }
- } else if (PR_SUCCESS == PR_NetAddrToString( addr, addrbuf, addrbuflen)) {
- if (0 == strncmp( addrbuf, "::ffff:", 7 )) {
- /* IPv4 address mapped into IPv6 address space */
- retstr = addrbuf + 7;
- } else {
- /* full blown IPv6 address */
- retstr = addrbuf;
- }
- } else { /* punt */
- retstr = "address conversion failed";
- }
- return(retstr);
- }
- static int
- createsignalpipe( void )
- {
- #if defined( _WIN32 )
- if ( PR_NewTCPSocketPair(&signalpipe[0])) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "PR_CreatePipe() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), SLAPD_DEFAULT_THREAD_STACKSIZE );
- return( -1 );
- }
- writesignalpipe = PR_FileDesc2NativeHandle(signalpipe[1]);
- readsignalpipe = PR_FileDesc2NativeHandle(signalpipe[0]);
- #else
- if ( PR_CreatePipe( &signalpipe[0], &signalpipe[1] ) != 0 ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY, "PR_CreatePipe() failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), SLAPD_DEFAULT_THREAD_STACKSIZE );
- return( -1 );
- }
- writesignalpipe = PR_FileDesc2NativeHandle(signalpipe[1]);
- readsignalpipe = PR_FileDesc2NativeHandle(signalpipe[0]);
- if(fcntl(writesignalpipe, F_SETFD, O_NONBLOCK) == -1){
- LDAPDebug( LDAP_DEBUG_ANY,"createsignalpipe: failed to set FD for write pipe (%d).\n",
- errno, 0, 0 );
- }
- if(fcntl(readsignalpipe, F_SETFD, O_NONBLOCK) == -1){
- LDAPDebug( LDAP_DEBUG_ANY,"createsignalpipe: failed to set FD for read pipe (%d).\n",
- errno, 0, 0);
- }
- #endif
- return( 0 );
- }
- #ifdef HPUX10
- #include <pthread.h> /* for sigwait */
- /*
- * Set up a thread to catch signals
- * SIGUSR1 (ignore), SIGCHLD (call slapd_wait4child),
- * SIGUSR2 (set slapd_shutdown), SIGTERM (set slapd_shutdown),
- * SIGHUP (set slapd_shutdown)
- */
- static void *
- catch_signals()
- {
- sigset_t caught_signals;
- int sig;
-
- sigemptyset( &caught_signals );
-
- while ( !g_get_shutdown() ) {
-
- /* Set the signals we're interested in catching */
- sigaddset( &caught_signals, SIGUSR1 );
- sigaddset( &caught_signals, SIGCHLD );
- sigaddset( &caught_signals, SIGUSR2 );
- sigaddset( &caught_signals, SIGTERM );
- sigaddset( &caught_signals, SIGHUP );
-
- (void)sigprocmask( SIG_BLOCK, &caught_signals, NULL );
-
- if (( sig = sigwait( &caught_signals )) < 0 ) {
- LDAPDebug( LDAP_DEBUG_ANY, "catch_signals: sigwait returned -1\n",
- 0, 0, 0 );
- continue;
- } else {
- LDAPDebug( LDAP_DEBUG_TRACE, "catch_signals: detected signal %d\n",
- sig, 0, 0 );
- switch ( sig ) {
- case SIGUSR1:
- continue; /* ignore SIGUSR1 */
- case SIGUSR2: /* fallthrough */
- case SIGTERM: /* fallthrough */
- case SIGHUP:
- g_set_shutdown( SLAPI_SHUTDOWN_SIGNAL );
- return NULL;
- case SIGCHLD:
- slapd_wait4child( sig );
- break;
- default:
- LDAPDebug( LDAP_DEBUG_ANY,
- "catch_signals: unknown signal (%d) received\n",
- sig, 0, 0 );
- }
- }
- }
- }
- #endif /* HPUX */
-
- static int
- get_configured_connection_table_size()
- {
- int size;
- size = config_get_conntablesize();
- /*
- * Cap the table size at nsslapd-maxdescriptors.
- */
- #if !defined(_WIN32) && !defined(AIX)
- {
- int maxdesc = config_get_maxdescriptors();
- if ( maxdesc >= 0 && size > maxdesc ) {
- size = maxdesc;
- }
- }
- #endif
- return size;
- }
- PRFileDesc * get_ssl_listener_fd()
- {
- PRFileDesc * listener;
- listener = the_connection_table->fd[the_connection_table->s_tcps].fd;
- return listener;
- }
- int configure_pr_socket( PRFileDesc **pr_socket, int secure, int local )
- {
- int ns = 0;
- int reservedescriptors = config_get_reservedescriptors();
- int enable_nagle = config_get_nagle();
- PRSocketOptionData pr_socketoption;
-
- #if defined(LINUX)
- /* On Linux we use TCP_CORK so we must enable nagle */
- enable_nagle = 1;
- #endif
- ns = PR_FileDesc2NativeHandle( *pr_socket );
-
- #if !defined(_WIN32)
- /*
- * Some OS or third party libraries may require that low
- * numbered file descriptors be available, e.g., the DNS resolver
- * library on most operating systems. Therefore, we try to
- * replace the file descriptor returned by accept() with a
- * higher numbered one. If this fails, we log an error and
- * continue (not considered a truly fatal error).
- */
- if ( reservedescriptors > 0 && ns < reservedescriptors ) {
- int newfd = fcntl( ns, F_DUPFD, reservedescriptors );
- if ( newfd > 0 ) {
- PRFileDesc *nspr_layer_fd = PR_GetIdentitiesLayer( *pr_socket,
- PR_NSPR_IO_LAYER );
- if ( NULL == nspr_layer_fd ) {
- slapi_log_error( SLAPI_LOG_FATAL, "configure_pr_socket",
- "Unable to move socket file descriptor %d above %d:"
- " PR_GetIdentitiesLayer( %p, PR_NSPR_IO_LAYER )"
- " failed\n", ns, reservedescriptors, *pr_socket );
- close( newfd ); /* can't fix things up in NSPR -- close copy */
- } else {
- PR_ChangeFileDescNativeHandle( nspr_layer_fd, newfd );
- close( ns ); /* dup succeeded -- close the original */
- ns = newfd;
- }
- } else {
- int oserr = errno;
- slapi_log_error(SLAPI_LOG_FATAL, "configure_pr_socket",
- "Unable to move socket file descriptor %d above %d:"
- " OS error %d (%s)\n", ns, reservedescriptors, oserr,
- slapd_system_strerror( oserr ) );
- }
- }
- #endif /* !_WIN32 */
- /* Set keep_alive to keep old connections from lingering */
- pr_socketoption.option = PR_SockOpt_Keepalive;
- pr_socketoption.value.keep_alive = 1;
- if ( PR_SetSocketOption( *pr_socket, &pr_socketoption ) == PR_FAILURE ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_SetSocketOption(PR_SockOpt_Keepalive failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- }
- if ( secure ) {
-
- pr_socketoption.option = PR_SockOpt_Nonblocking;
- pr_socketoption.value.non_blocking = 0;
- if ( PR_SetSocketOption( *pr_socket, &pr_socketoption ) == PR_FAILURE ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_SetSocketOption(PR_SockOpt_Nonblocking) failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- }
- } else {
- /* We always want to have non-blocking I/O */
- pr_socketoption.option = PR_SockOpt_Nonblocking;
- pr_socketoption.value.non_blocking = 1;
- if ( PR_SetSocketOption( *pr_socket, &pr_socketoption ) == PR_FAILURE ) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_SetSocketOption(PR_SockOpt_Nonblocking) failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror(prerr), 0 );
- }
-
- if ( have_send_timeouts ) {
- daemon_configure_send_timeout(ns,config_get_ioblocktimeout());
- }
- } /* else (secure) */
- if ( !enable_nagle && !local ) {
- pr_socketoption.option = PR_SockOpt_NoDelay;
- pr_socketoption.value.no_delay = 1;
- if ( PR_SetSocketOption( *pr_socket, &pr_socketoption ) == PR_FAILURE) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_SetSocketOption(PR_SockOpt_NoDelay) failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror( prerr ), 0 );
- }
- } else if( !local) {
- pr_socketoption.option = PR_SockOpt_NoDelay;
- pr_socketoption.value.no_delay = 0;
- if ( PR_SetSocketOption( *pr_socket, &pr_socketoption ) == PR_FAILURE) {
- PRErrorCode prerr = PR_GetError();
- LDAPDebug( LDAP_DEBUG_ANY,
- "PR_SetSocketOption(PR_SockOpt_NoDelay) failed, "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- prerr, slapd_pr_strerror( prerr ), 0 );
- }
- } /* else (!enable_nagle) */
-
-
- return ns;
-
- }
- void configure_ns_socket( int * ns )
- {
- int enable_nagle = config_get_nagle();
- int on, rc;
- #if defined(LINUX)
- /* On Linux we use TCP_CORK so we must enable nagle */
- enable_nagle = 1;
- #endif
- if ( have_send_timeouts ) {
- daemon_configure_send_timeout( *ns, config_get_ioblocktimeout() );
- }
- /* set the nagle */
- if ( !enable_nagle ) {
- on = 1;
- } else {
- on = 0;
- }
- /* check for errors */
- if((rc = setsockopt( *ns, IPPROTO_TCP, TCP_NODELAY, (char * ) &on, sizeof(on) ) != 0)){
- LDAPDebug( LDAP_DEBUG_ANY,"configure_ns_socket: Failed to configure socket (%d).\n", rc, 0, 0);
- }
- return;
- }
- #ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS
- /*
- * A function that uses the DNS resolver in a simple way. This is only
- * used to ensure that the DNS resolver has opened its files, etc.
- * using low numbered file descriptors.
- */
- static void
- get_loopback_by_addr( void )
- {
- #ifdef GETHOSTBYADDR_BUF_T
- struct hostent hp;
- GETHOSTBYADDR_BUF_T hbuf;
- #endif
- unsigned long ipaddr;
- struct in_addr ia;
- int herrno, rc = 0;
- memset( (char *)&hp, 0, sizeof(hp));
- ipaddr = htonl( INADDR_LOOPBACK );
- (void) GETHOSTBYADDR( (char *)&ipaddr, sizeof( ipaddr ),
- AF_INET, &hp, hbuf, sizeof(hbuf), &herrno );
- }
- #endif /* RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS */
- void
- disk_monitoring_stop()
- {
- if ( disk_thread_p ) {
- PR_Lock( diskmon_mutex );
- PR_NotifyCondVar( diskmon_cvar );
- PR_Unlock( diskmon_mutex );
- }
- }
|