| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244 |
- /** 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>
- #if defined(HAVE_MNTENT_H)
- #include <mntent.h>
- #endif
- #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 */
- #include <stdio.h>
- #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 "fe.h"
- #if defined(ENABLE_LDAPI)
- #include "getsocketpeer.h"
- #endif /* ENABLE_LDAPI */
- #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 {
- #ifdef ENABLE_NUNC_STANS
- PRStackElem stackelem; /* must be first in struct for PRStack to work */
- #endif
- int idx; /* index of this listener in the ct->fd array */
- PRFileDesc *listenfd; /* the listener fd */
- int secure;
- int local;
- #ifdef ENABLE_NUNC_STANS
- Connection_Table *ct; /* for listen job callback */
- struct ns_job_t *ns_job; /* the ns accept job */
- #endif
- } listener_info;
- static int listeners = 0; /* number of listener sockets */
- static listener_info *listener_idxs = NULL; /* array of indexes of listener sockets in the ct->fd array */
- #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);
- #ifdef ENABLE_NUNC_STANS
- static void ns_set_shutdown (struct ns_job_t *job);
- #endif
- static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read);
- #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, Connection **newconn );
- #ifdef ENABLE_NUNC_STANS
- static void ns_handle_new_connection(struct ns_job_t *job);
- #endif
- #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((0 == getmntent(fp, &mnt))){
- 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;
- /* 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 */
- CFG_LOCK_READ(config);
- disk_mon_add_dir(list, config->configdir);
- disk_mon_add_dir(list, config->accesslog);
- disk_mon_add_dir(list, config->errorlog);
- disk_mon_add_dir(list, config->auditlog);
- CFG_UNLOCK_READ(config);
- 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, PRUint64 threshold, PRUint64 *disk_space)
- {
- #ifdef LINUX
- struct statfs buf;
- #else
- struct statvfs buf;
- #endif
- PRUint64 worst_disk_space = threshold;
- PRUint64 freeBytes = 0;
- PRUint64 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;
- PRUint64 previous_mark = 0;
- PRUint64 disk_space = 0;
- PRInt64 threshold = 0;
- PRUint64 halfway = 0;
- time_t start = 0;
- time_t now = 0;
- int deleted_rotated_logs = 0;
- int logging_critical = 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 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();
- 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: %" NSPRIu64 " 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 logging is not critical
- */
- if(verbose_logging != 0 && verbose_logging != LDAP_DEBUG_ANY){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %" NSPRIu64 " Kb, "
- "temporarily setting error loglevel to the default level(%d).\n", dirstr,
- (disk_space / 1024), SLAPD_DEFAULT_ERRORLOG_LEVEL);
- /* Setting the log level back to zero, actually sets the value to LDAP_DEBUG_ANY */
- config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE,
- STRINGIFYDEFINE(SLAPD_DEFAULT_ERRORLOG_LEVEL),
- 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 && !logging_critical){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " 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 && !logging_critical){
- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " 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: %" NSPRIu64 " 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(%" NSPRIu64 " 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 (%" NSPRIu64 " bytes). Aborting"
- " shutdown, and restoring the log settings.\n",disk_space,0,0);
- if(logs_disabled && using_accesslog){
- config_set_accesslog_enabled(LOGGING_ON);
- }
- if(logs_disabled && 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: %" NSPRIu64 " Kb."
- " Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0);
- g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
- 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 (%" NSPRIu64 " Kb). Signaling slapd for shutdown...\n",
- (disk_space / 1024), 0, 0);
- g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
- return;
- }
- }
- }
- static void
- handle_listeners(Connection_Table *ct)
- {
- int idx;
- for (idx = 0; idx < 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, NULL);
- if (rc) {
- LDAPDebug1Arg(LDAP_DEBUG_CONNS, "Error accepting new connection listenfd=%d\n",
- PR_FileDesc2NativeHandle(listenfd));
- continue;
- }
- }
- }
- }
- return;
- }
- /*
- * Convert any pre-existing DES passwords to AES.
- *
- * Grab the "password" attributes and search all the backends for
- * these attributes and convert them to AES if they are DES encoded.
- */
- static void
- convert_pbe_des_to_aes()
- {
- Slapi_PBlock *pb = NULL;
- Slapi_Entry **entries = NULL;
- struct slapdplugin *plugin = NULL;
- char **attrs = NULL;
- char **backends = NULL;
- char *val = NULL;
- int converted_des = 0;
- int result = -1;
- int have_aes = 0;
- int have_des = 0;
- int i = 0, ii = 0, be_idx = 0;
- /*
- * Check that AES plugin is enabled, and grab all the unique
- * password attributes.
- */
- for ( plugin = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME);
- plugin != NULL;
- plugin = plugin->plg_next )
- {
- char *arg = NULL;
- if(plugin->plg_started && strcasecmp(plugin->plg_name, "AES") == 0){
- /* We have the AES plugin, and its enabled */
- have_aes = 1;
- }
- if(plugin->plg_started && strcasecmp(plugin->plg_name, "DES") == 0){
- /* We have the DES plugin, and its enabled */
- have_des = 1;
- }
- /* Gather all the unique password attributes from all the PBE plugins */
- for ( i = 0, arg = plugin->plg_argv[i];
- i < plugin->plg_argc;
- arg = plugin->plg_argv[++i] )
- {
- if(charray_inlist(attrs, arg)){
- continue;
- }
- charray_add(&attrs, slapi_ch_strdup(arg));
- }
- }
- if(have_aes && have_des){
- /*
- * Build a list of all the backend dn's
- */
- Slapi_Backend *be = NULL;
- struct suffixlist *list;
- char *cookie = NULL;
- LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes: "
- "Converting DES passwords to AES...\n",0,0,0);
- be = slapi_get_first_backend(&cookie);
- while (be){
- int suffix_idx = 0;
- int count = slapi_counter_get_value(be->be_suffixcounter);
- list = be->be_suffixlist;
- for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) {
- char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix);
- if(charray_inlist(backends, suffix) || strlen(suffix) == 0){
- list = list->next;
- continue;
- }
- charray_add(&backends, slapi_ch_strdup(suffix));
- list = list->next;
- }
- be = slapi_get_next_backend (cookie);
- }
- slapi_ch_free ((void **)&cookie);
- /*
- * Search for the password attributes
- */
- for (i = 0; attrs && attrs[i]; i++){
- char *filter = PR_smprintf("%s=*", attrs[i]);
- /*
- * Loop over all the backends looking for the password attribute
- */
- for(be_idx = 0; backends && backends[be_idx]; be_idx++){
- pb = slapi_pblock_new();
- slapi_search_internal_set_pb(pb, backends[be_idx],
- LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
- (void *)plugin_get_default_component_id(),
- SLAPI_OP_FLAG_IGNORE_UNINDEXED);
- slapi_search_internal_pb(pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
- if (LDAP_SUCCESS != result) {
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "failed to search for password on (%s) error (%d)\n",
- backends[be_idx], result, 0);
- goto done;
- }
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- for (ii = 0; entries && entries[ii]; ii++){
- if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
- if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
- /*
- * We have a DES encoded password, convert it AES
- */
- Slapi_PBlock *mod_pb = NULL;
- Slapi_Value *sval = NULL;
- LDAPMod mod_replace;
- LDAPMod *mods[2];
- char *replace_val[2];
- char *passwd = NULL;
- /* decode the DES password */
- if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "failed to decode existing DES password for (%s)\n",
- slapi_entry_get_dn(entries[ii]), 0, 0);
- converted_des = 0;
- goto done;
- }
- /* encode the password */
- sval = slapi_value_new_string(passwd);
- if(pw_rever_encode(&sval, attrs[i]) == -1){
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "failed to encode AES password for (%s)\n",
- slapi_entry_get_dn(entries[ii]), 0, 0);
- slapi_ch_free_string(&passwd);
- slapi_value_free(&sval);
- converted_des = 0;
- goto done;
- }
- /* replace the attribute in the entry */
- replace_val[0] = (char *)slapi_value_get_string(sval);
- replace_val[1] = NULL;
- mod_replace.mod_op = LDAP_MOD_REPLACE;
- mod_replace.mod_type = attrs[i];
- mod_replace.mod_values = replace_val;
- mods[0] = &mod_replace;
- mods[1] = 0;
- mod_pb = slapi_pblock_new();
- slapi_modify_internal_set_pb(mod_pb, slapi_entry_get_dn(entries[ii]),
- mods, 0, 0, (void *)plugin_get_default_component_id(), 0);
- slapi_modify_internal_pb(mod_pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
- if (LDAP_SUCCESS != result) {
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "failed to convert password for (%s) error (%d)\n",
- slapi_entry_get_dn(entries[ii]), result, 0);
- converted_des = -1;
- } else {
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "successfully converted password for (%s)\n",
- slapi_entry_get_dn(entries[ii]), result, 0);
- converted_des = 1;
- }
- slapi_ch_free_string(&passwd);
- slapi_value_free(&sval);
- slapi_pblock_destroy(mod_pb);
- if(result){
- goto done;
- }
- }
- slapi_ch_free_string(&val);
- }
- }
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- pb = NULL;
- }
- slapi_ch_free_string(&filter);
- }
- }
- done:
- charray_free(attrs);
- charray_free(backends);
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- if (have_aes && have_des){
- /*
- * If a conversion attempt did not fail, disable DES plugin
- */
- if(converted_des != -1){
- /*
- * Disable the DES plugin - this also prevents potentially expensive
- * searches at every server startup.
- */
- LDAPMod mod_replace;
- LDAPMod *mods[2];
- char *replace_val[2];
- char *des_dn = "cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config";
- replace_val[0] = "off";
- replace_val[1] = NULL;
- mod_replace.mod_op = LDAP_MOD_REPLACE;
- mod_replace.mod_type = "nsslapd-pluginEnabled";
- mod_replace.mod_values = replace_val;
- mods[0] = &mod_replace;
- mods[1] = 0;
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb(pb, des_dn, mods, 0, 0,
- (void *)plugin_get_default_component_id(), 0);
- slapi_modify_internal_pb(pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
- if (LDAP_SUCCESS != result) {
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "Failed to disable DES plugin (%s), error (%d)\n",
- des_dn, result, 0);
- } else {
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "Successfully disabled DES plugin (%s)\n",
- des_dn, 0, 0);
- }
- slapi_pblock_destroy(pb);
- }
- if(converted_des == 1){
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
- "Finished - all DES passwords have been converted to AES.\n",
- 0, 0, 0);
- } else if (converted_des == 0){
- LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes: "
- "Finished - no DES passwords to convert.\n",0,0,0);
- }
- }
- }
- #ifdef ENABLE_NUNC_STANS
- static ns_job_type_t ns_listen_job_flags = NS_JOB_ACCEPT|NS_JOB_PERSIST|NS_JOB_PRESERVE_FD;
- static PRStack *ns_disabled_listeners; /* holds the disabled listeners, if any */
- static PRInt32 num_disabled_listeners;
- #endif
- #ifdef ENABLE_NUNC_STANS
- static void
- ns_disable_listener(listener_info *listener)
- {
- /* tell the event framework not to listen for new connections on this listener */
- ns_job_modify(listener->ns_job, NS_JOB_DISABLE_ONLY|NS_JOB_PRESERVE_FD);
- /* add the listener to our list of disabled listeners */
- PR_StackPush(ns_disabled_listeners, (PRStackElem *)listener);
- PR_AtomicIncrement(&num_disabled_listeners);
- LDAPDebug2Args(LDAP_DEBUG_ANY, "ns_disable_listener: "
- "disabling listener for fd [%d]: [%d] now disabled\n",
- PR_FileDesc2NativeHandle(listener->listenfd),
- num_disabled_listeners);
- }
- #endif
- void
- ns_enable_listeners()
- {
- #ifdef ENABLE_NUNC_STANS
- int num_enabled = 0;
- listener_info *listener;
- while ((listener = (listener_info *)PR_StackPop(ns_disabled_listeners))) {
- /* there was a disabled listener - re-enable it to listen for new connections */
- ns_job_modify(listener->ns_job, ns_listen_job_flags);
- PR_AtomicDecrement(&num_disabled_listeners);
- num_enabled++;
- }
- if (num_enabled) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY, "ns_enable_listeners: "
- "enabled [%d] listeners\n", num_enabled);
- }
- #endif
- }
- #ifdef ENABLE_NUNC_STANS
- /*
- * Nunc stans logging function.
- */
- static void
- nunc_stans_logging(int priority, const char *format, va_list varg)
- {
- va_list varg_copy;
- int severity = SLAPI_LOG_FATAL;
- if (priority == LOG_DEBUG){
- severity = SLAPI_LOG_NUNCSTANS;
- } else if(priority == LOG_INFO){
- severity = SLAPI_LOG_CONNS;
- }
- va_copy(varg_copy, varg);
- slapi_log_error_ext(severity, "nunc-stans", (char *)format, varg, varg_copy);
- va_end(varg_copy);
- }
- static void*
- nunc_stans_malloc(size_t size)
- {
- return (void*)slapi_ch_malloc((unsigned long)size);
- }
- static void*
- nunc_stans_calloc(size_t count, size_t size)
- {
- return (void*)slapi_ch_calloc((unsigned long)count, (unsigned long)size);
- }
- static void*
- nunc_stans_realloc(void *block, size_t size)
- {
- return (void*)slapi_ch_realloc((char *)block, (unsigned long)size);
- }
- static void
- nunc_stans_free(void *ptr)
- {
- slapi_ch_free((void **)&ptr);
- }
- #endif
- 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();
- #ifdef ENABLE_NUNC_STANS
- ns_thrpool_t *tp;
- struct ns_thrpool_config tp_config;
- #endif
- 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 );
- }
- 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, config_get_listen_backlog_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 );
- 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, config_get_listen_backlog_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 );
- }
- 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, config_get_listen_backlog_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 );
- }
- 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, config_get_listen_backlog_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 );
- }
- listeners++;
- }
- }
- #endif /* ENABLE_LDAPI */
- #endif
- listener_idxs = (listener_info *)slapi_ch_calloc(listeners, sizeof(*listener_idxs));
- #ifdef ENABLE_NUNC_STANS
- ns_disabled_listeners = PR_CreateStack("disabled_listeners");
- #endif
- /*
- * Convert old DES encoded passwords to AES
- */
- convert_pbe_des_to_aes();
- #ifdef ENABLE_NUNC_STANS
- if (!g_get_shutdown()) {
- int ii;
- PRInt32 maxthreads = 3;
- if (getenv("MAX_THREADS")) {
- maxthreads = atoi(getenv("MAX_THREADS"));
- }
- /* Set the nunc-stans thread pool config */
- ns_thrpool_config_init(&tp_config);
- tp_config.initial_threads = maxthreads;
- tp_config.max_threads = maxthreads;
- tp_config.stacksize = 0;
- tp_config.event_queue_size = config_get_maxdescriptors();
- tp_config.work_queue_size = config_get_maxdescriptors();
- tp_config.log_fct = nunc_stans_logging;
- tp_config.log_start_fct = NULL;
- tp_config.log_close_fct = NULL;
- tp_config.malloc_fct = nunc_stans_malloc;
- tp_config.calloc_fct = nunc_stans_calloc;
- tp_config.realloc_fct = nunc_stans_realloc;
- tp_config.free_fct = nunc_stans_free;
- tp = ns_thrpool_new(&tp_config);
- ns_add_signal_job(tp, SIGINT, NS_JOB_SIGNAL, ns_set_shutdown, NULL, NULL);
- ns_add_signal_job(tp, SIGTERM, NS_JOB_SIGNAL, ns_set_shutdown, NULL, NULL);
- ns_add_signal_job(tp, SIGHUP, NS_JOB_SIGNAL, ns_set_shutdown, NULL, NULL);
- setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll);
- for (ii = 0; ii < listeners; ++ii) {
- listener_idxs[ii].ct = the_connection_table; /* to pass to handle_new_connection */
- ns_add_io_job(tp, listener_idxs[ii].listenfd, ns_listen_job_flags,
- ns_handle_new_connection, &listener_idxs[ii], &listener_idxs[ii].ns_job);
- }
- }
- #endif
- /* Now we write the pid file, indicating that the server is finally and listening for connections */
- write_pid_file();
- /* The server is ready and listening for connections. Logging "slapd started" message. */
- unfurl_banners(the_connection_table,ports,n_tcps,s_tcps,i_unix);
- /* The meat of the operation is in a loop on a call to select */
- while(!g_get_shutdown())
- {
- #ifdef ENABLE_NUNC_STANS
- DS_Sleep(1);
- #else
- #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);
- 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);
- /* handle new data ready */
- handle_pr_read_ready(the_connection_table, connection_table_size);
- clear_signal(the_connection_table->fd);
- #endif
- break;
- }
- #endif
- }
- /* 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
- /* free the listener indexes */
- slapi_ch_free((void **)&listener_idxs);
- 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 Globals */);
- 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;
- #ifdef ENABLE_NUNC_STANS
- if (ns_thrpool_wait(tp)) {
- /* error */
- }
- ns_thrpool_destroy(tp);
- #endif
- be_cleanupall ();
- connection_post_shutdown_cleanup();
- LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
- 0, 0, 0 );
- referrals_free();
- schema_destroy_dse_lock();
- /* tell the time thread to shutdown and then wait for it */
- time_shutdown = 1;
- PR_JoinThread( time_thread_p );
- #ifdef _WIN32
- WSACleanup();
- #else
- if ( g_get_shutdown() == SLAPI_SHUTDOWN_DISKFULL ){
- /* This is a server-induced shutdown, we need to manually remove the pid file */
- if( unlink(get_pid_file()) ){
- LDAPDebug( LDAP_DEBUG_ANY, "Failed to remove pid file %s\n", get_pid_file(), 0, 0 );
- }
- }
- #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)
- {
- 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 < 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
- {
- if(c->c_threadnumber >= max_threads_per_conn){
- c->c_maxthreadsblocked++;
- }
- 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 ));
- }
- #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;
- int maxthreads = config_get_maxthreadsperconn();
- #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, maxthreads);
- /* idle timeout */
- }
- else if (( c->c_idletimeout > 0 &&
- (curtime - c->c_idlesince) >= c->c_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();
- int maxthreads = config_get_maxthreadsperconn();
- #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 (( c->c_ideltimeout > 0 &&
- c->c_prfd == ct->fd[i].fd &&
- (curtime - c->c_idlesince) >= c->c_ideltimeout &&
- 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, maxthreads )) == -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 (c->c_idletimeout > 0 &&
- (curtime - c->c_idlesince) >= c->c_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
- }
- #ifdef ENABLE_NUNC_STANS
- /* This function is called when the connection has been marked
- * as closing and needs to be cleaned up. It will keep trying
- * and re-arming itself until there are no references.
- */
- static void
- ns_handle_closure(struct ns_job_t *job)
- {
- Connection *c = (Connection *)ns_job_get_data(job);
- int do_yield = 0;
- /* this function must be called from the event loop thread */
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
- PR_Lock(c->c_mutex);
- c->c_ns_close_jobs--;
- connection_release_nolock(c); /* release ref acquired when job was added */
- if (connection_table_move_connection_out_of_active_list(c->c_ct, c)) {
- do_yield = 1;
- ns_connection_post_io_or_closing(c);
- }
- PR_Unlock(c->c_mutex);
- ns_job_done(job);
- if (do_yield) {
- /* yield thread after unlocking conn mutex */
- PR_Sleep(PR_INTERVAL_NO_WAIT); /* yield to allow other thread to release conn */
- }
- return;
- }
- #endif
- #define CONN_NEEDS_CLOSING(c) (c->c_flags & CONN_FLAG_CLOSING) || (c->c_sd == SLAPD_INVALID_SOCKET)
- /**
- * Schedule more I/O for this connection, or make sure that it
- * is closed in the event loop.
- */
- void
- ns_connection_post_io_or_closing(Connection *conn)
- {
- #ifdef ENABLE_NUNC_STANS
- struct timeval tv;
- ns_job_func_t job_func;
- if (CONN_NEEDS_CLOSING(conn)) {
- if (conn->c_ns_close_jobs) {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "already a close job in progress on conn %" NSPRIu64 " for fd=%d\n",
- conn->c_connid, conn->c_sd);
- return;
- } else {
- /* just make sure the event is processed at the next possible event loop run */
- tv.tv_sec = 0;
- tv.tv_usec = 1000;
- job_func = ns_handle_closure;
- conn->c_ns_close_jobs++;
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "post closure job for conn %" NSPRIu64 " for fd=%d\n",
- conn->c_connid, conn->c_sd);
- }
- } else {
- /* process event normally - wait for I/O until idletimeout */
- tv.tv_sec = conn->c_idletimeout;
- tv.tv_usec = 0;
- job_func = ns_handle_pr_read_ready;
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "post I/O job for conn %" NSPRIu64 " for fd=%d\n",
- conn->c_connid, conn->c_sd);
- }
- connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework will have reference */
- ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
- NS_JOB_READ|NS_JOB_PRESERVE_FD,
- job_func, conn, NULL);
- #endif
- }
- #ifdef ENABLE_NUNC_STANS
- /* This function must be called without the thread flag, in the
- * event loop. This function may free the connection. This can
- * only be done in the event loop thread.
- */
- void
- ns_handle_pr_read_ready(struct ns_job_t *job)
- {
- int need_closure = 0;
- int maxthreads = config_get_maxthreadsperconn();
- Connection *c = (Connection *)ns_job_get_data(job);
- /* this function must be called from the event loop thread */
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
- PR_Lock(c->c_mutex);
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "activity on conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- /* if we were called due to some i/o event, see what the state of the socket is */
- if (slapi_is_loglevel_set(SLAPI_LOG_CONNS) && !NS_JOB_IS_TIMER(ns_job_get_output_type(job)) && c && c->c_sd) {
- /* see if socket is closed */
- char buf[1];
- ssize_t rc = recv(c->c_sd, buf, sizeof(buf), MSG_PEEK);
- if (!rc) {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "socket is closed conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- } else if (rc > 0) {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "socket has data available for conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- } else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "socket has no data available conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- } else {
- LDAPDebug(LDAP_DEBUG_CONNS, "socket has error [%d] conn %" NSPRIu64 " for fd=%d\n",
- errno, c->c_connid, c->c_sd);
- }
- }
- connection_release_nolock(c); /* release ref acquired when job was added */
- if (CONN_NEEDS_CLOSING(c)) {
- need_closure = 1;
- } else if (NS_JOB_IS_TIMER(ns_job_get_output_type(job))) {
- /* idle timeout */
- disconnect_server_nomutex(c, c->c_connid, -1,
- SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN);
- need_closure = 1;
- } else if ((connection_activity(c, maxthreads)) == -1) {
- /* This might happen as a result of
- * trying to acquire a closing connection
- */
- LDAPDebug2Args(LDAP_DEBUG_ANY, "connection_activity: abandoning conn %" NSPRIu64
- " as fd=%d is already closing\n", c->c_connid, c->c_sd);
- /* 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);
- need_closure = 1;
- } else {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "queued conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- }
- if (need_closure) {
- ns_connection_post_io_or_closing(c);
- }
- PR_Unlock(c->c_mutex);
- ns_job_done(job);
- return;
- }
- #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 */
- void
- handle_closed_connection(Connection *conn)
- {
- #ifdef USE_OPENLDAP
- ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io, LBER_SBIOD_LEVEL_PROVIDER);
- #endif
- }
- /* NOTE: this routine is not reentrant */
- static int
- handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local, Connection **newconn)
- {
- int ns = 0;
- Connection *conn = NULL;
- /* struct sockaddr_in from;*/
- PRNetAddr from;
- PRFileDesc *pr_clonefd = NULL;
- ber_len_t maxbersize;
- slapdFrontendConfig_t *fecfg = getFrontendConfig();
- if (newconn) {
- *newconn = 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 );
- /*
- * Set the default idletimeout and the handle. We'll update c_idletimeout
- * after each bind so we can correctly set the resource limit.
- */
- conn->c_idletimeout = fecfg->idletimeout;
- conn->c_idletimeout_handle = idletimeout_reslimit_handle;
- #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 */
- maxbersize = config_get_maxbersize();
- #if defined(USE_OPENLDAP)
- ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize );
- #endif
- 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();
- if (newconn) {
- *newconn = conn;
- }
- return 0;
- }
- #ifdef ENABLE_NUNC_STANS
- static void
- ns_handle_new_connection(struct ns_job_t *job)
- {
- int rc;
- Connection *c = NULL;
- listener_info *li = (listener_info *)ns_job_get_data(job);
- /* only accept new connections if we have enough fds, more than
- * the number of reserved descriptors
- */
- if ((li->ct->size - g_get_current_conn_count())
- <= config_get_reservedescriptors()) {
- /* too many open fds - shut off this listener - when an fd is
- * closed, try to resume this listener
- */
- ns_disable_listener(li);
- return;
- }
- rc = handle_new_connection(li->ct, SLAPD_INVALID_SOCKET, li->listenfd, li->secure, li->local, &c);
- if (rc) {
- PRErrorCode prerr = PR_GetError();
- if (PR_PROC_DESC_TABLE_FULL_ERROR == prerr) {
- /* too many open fds - shut off this listener - when an fd is
- * closed, try to resume this listener
- */
- ns_disable_listener(li);
- } else {
- LDAPDebug(LDAP_DEBUG_CONNS, "Error accepting new connection listenfd=%d [%d:%s]\n",
- PR_FileDesc2NativeHandle(li->listenfd), prerr,
- slapd_pr_strerror(prerr));
- }
- return;
- }
- /* now, set up the conn for reading - no thread - ns_handle_pr_read_ready
- * must be run in the event loop thread
- */
- c->c_tp = ns_job_get_tp(job);
- connection_acquire_nolock(c); /* event framework now has ref */
- ns_add_job(ns_job_get_tp(job), NULL, NS_JOB_NONE, ns_handle_pr_read_ready, c);
- return;
- }
- #endif
- 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
- #ifndef ENABLE_NUNC_STANS
- (void) SIGNAL( SIGTERM, set_shutdown );
- (void) SIGNAL( SIGHUP, set_shutdown );
- #endif
- #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
- }
- #ifdef ENABLE_NUNC_STANS
- static void
- ns_set_shutdown(struct ns_job_t *job)
- {
- int i;
- set_shutdown(0);
- /* Stop all the long running jobs */
- for (i = 0; i < listeners; ++i) {
- ns_job_done(listener_idxs[i].ns_job);
- listener_idxs[i].ns_job = NULL;
- }
- /* Signal all the worker threads to stop */
- ns_thrpool_shutdown(ns_job_get_tp(job));
- ns_job_done(job);
- }
- #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;
-
- 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 );
- }
- }
|