| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297 |
- /** 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;
- #define FDS_SIGNAL_PIPE 0
- static PRThread *disk_thread_p = NULL;
- static PRCondVar *diskmon_cvar = NULL;
- static PRLock *diskmon_mutex = NULL;
- void disk_monitoring_stop();
- 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 */
- static int enable_nunc_stans = 0; /* if nunc-stans is set to enabled, set to 1 in slapd_daemon */
- #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
- struct ns_job_t *ns_signal_job[3];
- 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 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
- static void handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll);
- #ifdef _WIN32
- static int clear_signal(fd_set *readfdset);
- #else
- static int clear_signal(struct POLL_STRUCT *fds);
- #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();
- /* 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
- if (!enable_nunc_stans) {
- return;
- }
- 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 /* ENABLE_NUNC_STANS */
- 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 ENABLE_NUNC_STANS
- enable_nunc_stans = config_get_enable_nunc_stans();
- #endif
- #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
- if (!enable_nunc_stans) {
- 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
- if (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 (enable_nunc_stans && !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, &ns_signal_job[0]);
- ns_add_signal_job(tp, SIGTERM, NS_JOB_SIGNAL, ns_set_shutdown, NULL, &ns_signal_job[1]);
- ns_add_signal_job(tp, SIGHUP, NS_JOB_SIGNAL, ns_set_shutdown, NULL, &ns_signal_job[2]);
- 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 /* ENABLE_NUNC_STANS */
- /* 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);
- #ifdef ENABLE_NUNC_STANS
- if (enable_nunc_stans && ns_thrpool_wait(tp)) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ns_thrpool_wait failed errno %d (%s)\n", errno,
- slapd_system_strerror(errno), 0 );
- }
- #endif
- /* The meat of the operation is in a loop on a call to select */
- while(!enable_nunc_stans && !g_get_shutdown())
- {
- #ifdef _WIN32
- fd_set readfds;
- struct timeval wakeup_timer;
- int oserr;
- #endif
- int select_return = 0;
- #ifndef _WIN32
- PRErrorCode prerr;
- #endif
- #ifdef _WIN32
- set_timeval_ms(&wakeup_timer, slapd_wakeup_timer);
- setup_read_fds(the_connection_table,&readfds,n_tcps, s_tcps_native);
- /* This select needs to timeout to give the server a chance to test for shutdown */
- select_return = select(connection_table_size, &readfds, NULL, 0, &wakeup_timer);
- #else
- setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll);
- 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;
- }
- }
- /* 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 ) {
- if (!enable_nunc_stans) {
- 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 (enable_nunc_stans) {
- 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()
- {
- if (enable_nunc_stans) {
- return( 0 );
- }
- /* 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
- {
- if (enable_nunc_stans) {
- return 0;
- }
- #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;
- }
- if (!enable_nunc_stans) {
- /* 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
- #define CONN_NEEDS_CLOSING(c) (c->c_flags & CONN_FLAG_CLOSING) || (c->c_sd == SLAPD_INVALID_SOCKET)
- /* Used internally by ns_handle_closure and ns_handle_pr_read_ready.
- * Returns 0 if the connection was successfully closed, or 1 otherwise.
- * Must be called with the c->c_mutex locked.
- */
- static int
- ns_handle_closure_nomutex(Connection *c)
- {
- int rc = 0;
- PR_ASSERT(c->c_refcnt > 0); /* one for the conn active list, plus possible other threads */
- PR_ASSERT(CONN_NEEDS_CLOSING(c));
- if (connection_table_move_connection_out_of_active_list(c->c_ct, c)) {
- /* not closed - another thread still has a ref */
- rc = 1;
- /* reschedule closure job */
- ns_connection_post_io_or_closing(c);
- }
- return rc;
- }
- /* 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);
- connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
- PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
- c->c_ns_close_jobs--; /* this job is processing closure */
- do_yield = ns_handle_closure_nomutex(c);
- PR_Unlock(c->c_mutex);
- ns_job_done(job);
- if (do_yield) {
- /* closure not done - another reference still outstanding */
- /* yield thread after unlocking conn mutex */
- PR_Sleep(PR_INTERVAL_NO_WAIT); /* yield to allow other thread to release conn */
- }
- return;
- }
- #endif
- /**
- * 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;
- if (!enable_nunc_stans) {
- return;
- }
- if (CONN_NEEDS_CLOSING(conn)) {
- /* there should only ever be 0 or 1 active closure jobs */
- PR_ASSERT((conn->c_ns_close_jobs == 0) || (conn->c_ns_close_jobs == 1));
- 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 we schedule the event to be closed in a timely manner */
- tv.tv_sec = 0;
- tv.tv_usec = slapd_wakeup_timer * 1000;
- conn->c_ns_close_jobs++; /* now 1 active closure job */
- connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework now has a reference */
- ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
- ns_handle_closure, conn, NULL);
- 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;
- PR_ASSERT(0 == connection_acquire_nolock(conn)); /* event framework now has a reference */
- ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
- NS_JOB_READ|NS_JOB_PRESERVE_FD,
- ns_handle_pr_read_ready, conn, NULL);
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "post I/O job for conn %" NSPRIu64 " for fd=%d\n",
- conn->c_connid, conn->c_sd);
- }
- #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 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) {
- /* check socket state */
- 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 read 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_ext(c, 1); /* release ref acquired when job was added */
- if (CONN_NEEDS_CLOSING(c)) {
- ns_handle_closure_nomutex(c);
- } else if (NS_JOB_IS_TIMER(ns_job_get_output_type(job))) {
- /* idle timeout */
- disconnect_server_nomutex_ext(c, c->c_connid, -1,
- SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN,
- 0 /* do not schedule closure, do it next */);
- ns_handle_closure_nomutex(c);
- } 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_ext(c, c->c_connid, -1,
- SLAPD_DISCONNECT_POLL, EPIPE,
- 0 /* do not schedule closure, do it next */);
- ns_handle_closure_nomutex(c);
- } else {
- LDAPDebug2Args(LDAP_DEBUG_CONNS, "queued conn %" NSPRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- }
- 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;
- }
- c->c_tp = ns_job_get_tp(job);
- /* This originally just called ns_handle_pr_read_ready directly - however, there
- * are certain cases where accept() will return a file descriptor that is not
- * immediately available for reading - this would cause the poll() in
- * connection_read_operation() to be hit - it seemed to perform better when
- * that poll() was avoided, even at the expense of putting this new fd back
- * in nunc-stans to poll for read ready.
- */
- ns_connection_post_io_or_closing(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
- if (!enable_nunc_stans) {
- (void) SIGNAL( SIGTERM, set_shutdown );
- (void) SIGNAL( SIGHUP, set_shutdown );
- }
- #endif /* _WIN32 */
- return 0;
- }
- #if defined( XP_WIN32 )
- static void
- unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, int n_tcps, PRFileDesc *s_tcps)
- #else
- static void
- unfurl_banners(Connection_Table *ct,daemon_ports_t *ports, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix)
- #endif
- {
- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- char addrbuf[ 256 ];
- int isfirsttime = 1;
- if ( ct->size <= slapdFrontendConfig->reservedescriptors ) {
- #ifdef _WIN32
- LDAPDebug( LDAP_DEBUG_ANY,
- "ERROR: Not enough descriptors to accept any connections. "
- "This may be because the maxdescriptors configuration "
- "directive is too small, or the reservedescriptors "
- "configuration directive is too large. "
- "Try increasing the number of descriptors available to "
- "the slapd process. The current value is %d. %d "
- "descriptors are currently reserved for internal "
- "slapd use, so the total number of descriptors available "
- "to the process must be greater than %d.\n",
- ct->size, slapdFrontendConfig->reservedescriptors, slapdFrontendConfig->reservedescriptors );
- #else /* _WIN32 */
- LDAPDebug( LDAP_DEBUG_ANY,
- "ERROR: Not enough descriptors to accept any connections. "
- "This may be because the maxdescriptors configuration "
- "directive is too small, the hard limit on descriptors is "
- "too small (see limit(1)), or the reservedescriptors "
- "configuration directive is too large. "
- "Try increasing the number of descriptors available to "
- "the slapd process. The current value is %d. %d "
- "descriptors are currently reserved for internal "
- "slapd use, so the total number of descriptors available "
- "to the process must be greater than %d.\n",
- ct->size, slapdFrontendConfig->reservedescriptors, slapdFrontendConfig->reservedescriptors );
- #endif /* _WIN32 */
- exit( 1 );
- }
- /*
- * This final startup message gives a definite signal to the admin
- * program that the server is up. It must contain the string
- * "slapd started." because some of the administrative programs
- * depend on this. See ldap/admin/lib/dsalib_updown.c.
- */
- #if !defined( XP_WIN32 )
- if ( n_tcps != NULL ) { /* standard LDAP */
- PRNetAddr **nap = NULL;
- for (nap = ports->n_listenaddr; nap && *nap; nap++) {
- if (isfirsttime) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAP requests\n",
- netaddr2string(*nap, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- isfirsttime = 0;
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAP requests\n",
- netaddr2string(*nap, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- }
- }
- }
- if ( s_tcps != NULL ) { /* LDAP over SSL; separate port */
- PRNetAddr **sap = NULL;
- for (sap = ports->s_listenaddr; sap && *sap; sap++) {
- if (isfirsttime) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAPS requests\n",
- netaddr2string(*sap, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- isfirsttime = 0;
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAPS requests\n",
- netaddr2string(*sap, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- }
- }
- }
- #else
- if ( n_tcps != SLAPD_INVALID_SOCKET ) { /* standard LDAP; XP_WIN32 */
- LDAPDebug( LDAP_DEBUG_ANY,
- "slapd started. Listening on %s port %d for LDAP requests\n",
- netaddr2string(&ports->n_listenaddr, addrbuf, sizeof(addrbuf)),
- ports->n_port, 0 );
- }
- if ( s_tcps != NULL ) { /* LDAP over SSL; separate port */
- LDAPDebug( LDAP_DEBUG_ANY,
- "Listening on %s port %d for LDAPS requests\n",
- netaddr2string(&ports->s_listenaddr, addrbuf, sizeof(addrbuf)),
- ports->s_port, 0 );
- }
- #endif
- #if !defined( XP_WIN32 )
- #if defined(ENABLE_LDAPI)
- if ( i_unix != NULL ) { /* LDAPI */
- PRNetAddr **iap = ports->i_listenaddr;
- LDAPDebug( LDAP_DEBUG_ANY,
- "%sListening on %s for LDAPI requests\n", isfirsttime?"slapd started. ":"",
- (*iap)->local.path, 0 );
- }
- #endif /* ENABLE_LDAPI */
- #endif
- }
- #if defined( _WIN32 )
- /* On Windows, we signal the SCM when we're ready to accept connections */
- static int
- write_pid_file()
- {
- if( SlapdIsAService() )
- {
- /* Initialization complete and successful. Set service to running */
- LDAPServerStatus.dwCurrentState = SERVICE_RUNNING;
- LDAPServerStatus.dwCheckPoint = 0;
- LDAPServerStatus.dwWaitHint = 0;
-
- if (!SetServiceStatus(hLDAPServerServiceStatus, &LDAPServerStatus)) {
- ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_START_FAILED, 1,
- "Could not set Service status.");
- exit(1);
- }
- }
- ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_STARTED, 0, NULL );
- return 0;
- }
- #else /* WIN32 */
- /* On UNIX, we create a file with our PID in it */
- static int
- write_pid_file()
- {
- FILE *fp = NULL;
- /*
- * The following section of code is closely coupled with the
- * admin programs. Please do not make changes here without
- * consulting the start/stop code for the admin code.
- */
- if ( (fp = fopen( get_pid_file(), "w" )) != NULL ) {
- fprintf( fp, "%d\n", getpid() );
- fclose( fp );
- if ( chmod(get_pid_file(), S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) != 0 ) {
- unlink(get_pid_file());
- } else {
- return 0;
- }
- }
- return -1;
- }
- #endif /* WIN32 */
- static void
- set_shutdown (int sig)
- {
- /* don't log anything from a signal handler:
- * you could be holding a lock when the signal was trapped. more
- * specifically, you could be holding the logfile lock (and deadlock
- * yourself).
- */
- #if 0
- LDAPDebug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
- #endif
- g_set_shutdown( SLAPI_SHUTDOWN_SIGNAL );
- #ifndef _WIN32
- #ifndef LINUX
- /* don't mess with USR1/USR2 on linux, used by libpthread */
- (void) SIGNAL( SIGUSR2, set_shutdown );
- #endif
- (void) SIGNAL( SIGTERM, set_shutdown );
- (void) SIGNAL( SIGHUP, set_shutdown );
- #endif
- }
- #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));
- /* Free all the signal jobs */
- ns_job_done(ns_signal_job[0]);
- ns_job_done(ns_signal_job[1]);
- ns_job_done(ns_signal_job[2]);
- }
- #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 (enable_nunc_stans) {
- return( 0 );
- }
- #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 );
- }
- }
|