connection.c 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #include <stdlib.h>
  18. #include <signal.h>
  19. #include "slap.h"
  20. #include "prcvar.h"
  21. #include "prlog.h" /* for PR_ASSERT */
  22. #include "fe.h"
  23. #include <sasl.h>
  24. #if defined(LINUX)
  25. #include <netinet/tcp.h> /* for TCP_CORK */
  26. #endif
  27. typedef Connection work_q_item;
  28. static void connection_threadmain( void );
  29. static void connection_add_operation(Connection* conn, Operation *op);
  30. static void connection_free_private_buffer(Connection *conn);
  31. static void op_copy_identity(Connection *conn, Operation *op);
  32. static void connection_set_ssl_ssf(Connection *conn);
  33. static int is_ber_too_big(const Connection *conn, ber_len_t ber_len);
  34. static void log_ber_too_big_error(const Connection *conn,
  35. ber_len_t ber_len, ber_len_t maxbersize);
  36. static PRStack *op_stack; /* stack of Slapi_Operation * objects so we don't have to malloc/free every time */
  37. static PRInt32 op_stack_size; /* size of op_stack */
  38. struct Slapi_op_stack {
  39. PRStackElem stackelem; /* must be first in struct for PRStack to work */
  40. Slapi_Operation *op;
  41. };
  42. static void add_work_q( work_q_item *, struct Slapi_op_stack * );
  43. static work_q_item *get_work_q( struct Slapi_op_stack ** );
  44. /*
  45. * We maintain a global work queue of items that have not yet
  46. * been handed off to an operation thread.
  47. */
  48. struct Slapi_work_q {
  49. PRStackElem stackelem; /* must be first in struct for PRStack to work */
  50. work_q_item *work_item;
  51. struct Slapi_op_stack *op_stack_obj;
  52. struct Slapi_work_q *next_work_item;
  53. };
  54. static struct Slapi_work_q *head_work_q= NULL; /* global work queue head */
  55. static struct Slapi_work_q *tail_work_q= NULL; /* global work queue tail */
  56. static PRLock *work_q_lock=NULL; /* protects head_conn_q and tail_conn_q */
  57. static PRCondVar *work_q_cv; /* used by operation threads to wait for work - when there is a conn in the queue waiting to be processed */
  58. static PRInt32 work_q_size; /* size of conn_q */
  59. static PRInt32 work_q_size_max; /* high water mark of work_q_size */
  60. #define WORK_Q_EMPTY (work_q_size == 0)
  61. static PRStack *work_q_stack; /* stack of work_q structs so we don't have to malloc/free every time */
  62. static PRInt32 work_q_stack_size; /* size of work_q_stack */
  63. static PRInt32 work_q_stack_size_max; /* max size of work_q_stack */
  64. static PRInt32 op_shutdown= 0; /* if non-zero, server is shutting down */
  65. #define LDAP_SOCKET_IO_BUFFER_SIZE 512 /* Size of the buffer we give to the I/O system for reads */
  66. static struct Slapi_work_q *
  67. create_work_q()
  68. {
  69. struct Slapi_work_q *work_q = (struct Slapi_work_q *)PR_StackPop(work_q_stack);
  70. if (!work_q) {
  71. work_q = (struct Slapi_work_q *)slapi_ch_malloc(sizeof(struct Slapi_work_q));
  72. } else {
  73. PR_AtomicDecrement(&work_q_stack_size);
  74. }
  75. return work_q;
  76. }
  77. static void
  78. destroy_work_q(struct Slapi_work_q **work_q)
  79. {
  80. if (work_q && *work_q) {
  81. (*work_q)->op_stack_obj = NULL;
  82. (*work_q)->work_item = NULL;
  83. PR_StackPush(work_q_stack, (PRStackElem *)*work_q);
  84. PR_AtomicIncrement(&work_q_stack_size);
  85. if (work_q_stack_size > work_q_stack_size_max) {
  86. work_q_stack_size_max = work_q_stack_size;
  87. }
  88. }
  89. }
  90. static struct Slapi_op_stack *
  91. connection_get_operation(void)
  92. {
  93. struct Slapi_op_stack *stack_obj = (struct Slapi_op_stack *)PR_StackPop(op_stack);
  94. if (!stack_obj) {
  95. stack_obj = (struct Slapi_op_stack *)slapi_ch_malloc(sizeof(struct Slapi_op_stack));
  96. stack_obj->op = operation_new( plugin_build_operation_action_bitmap( 0,
  97. plugin_get_server_plg() ));
  98. } else {
  99. PR_AtomicDecrement(&op_stack_size);
  100. if(!stack_obj->op){
  101. stack_obj->op = operation_new( plugin_build_operation_action_bitmap( 0,
  102. plugin_get_server_plg() ));
  103. } else {
  104. operation_init(stack_obj->op,
  105. plugin_build_operation_action_bitmap( 0, plugin_get_server_plg() ));
  106. }
  107. }
  108. return stack_obj;
  109. }
  110. static void
  111. connection_done_operation(Connection *conn, struct Slapi_op_stack *stack_obj)
  112. {
  113. operation_done(&(stack_obj->op), conn);
  114. PR_StackPush(op_stack, (PRStackElem *)stack_obj);
  115. PR_AtomicIncrement(&op_stack_size);
  116. }
  117. /*
  118. * We really are done with this connection. Get rid of everything.
  119. *
  120. * Note: this function should be called with conn->c_mutex already locked
  121. * or at a time when multiple threads are not in play that might touch the
  122. * connection structure.
  123. */
  124. void
  125. connection_done(Connection *conn)
  126. {
  127. connection_cleanup(conn);
  128. /* free the private content, the buffer has been freed by above connection_cleanup */
  129. slapi_ch_free((void**)&conn->c_private);
  130. if (NULL != conn->c_sb)
  131. {
  132. ber_sockbuf_free(conn->c_sb);
  133. }
  134. if (NULL != conn->c_mutex)
  135. {
  136. PR_DestroyMonitor(conn->c_mutex);
  137. }
  138. if (NULL != conn->c_pdumutex)
  139. {
  140. PR_DestroyLock(conn->c_pdumutex);
  141. }
  142. /* PAGED_RESULTS */
  143. pagedresults_cleanup_all(conn, 0);
  144. }
  145. /*
  146. * We're going to be making use of this connection again.
  147. * So, get rid of everything we can't make use of.
  148. *
  149. * Note: this function should be called with conn->c_mutex already locked
  150. * or at a time when multiple threads are not in play that might touch the
  151. * connection structure.
  152. */
  153. void
  154. connection_cleanup(Connection *conn)
  155. {
  156. int enable_listeners = 0;
  157. bind_credentials_clear( conn, PR_FALSE /* do not lock conn */,
  158. PR_TRUE /* clear external creds. */ );
  159. slapi_ch_free((void**)&conn->c_authtype);
  160. /* Call the plugin extension destructors */
  161. factory_destroy_extension(connection_type,conn,NULL/*Parent*/,&(conn->c_extension));
  162. /*
  163. * We hang onto these, since we can reuse them.
  164. * Sockbuf *c_sb;
  165. * PRLock *c_mutex;
  166. * PRLock *c_pdumutex;
  167. * Conn_private *c_private;
  168. */
  169. if (conn->c_prfd)
  170. {
  171. PR_Close(conn->c_prfd);
  172. enable_listeners = 1; /* re-enable listeners disabled due to no fds */
  173. }
  174. conn->c_sd= SLAPD_INVALID_SOCKET;
  175. conn->c_ldapversion= 0;
  176. conn->c_isreplication_session = 0;
  177. slapi_ch_free((void**)&conn->cin_addr );
  178. slapi_ch_free((void**)&conn->cin_destaddr );
  179. if ( conn->c_domain != NULL )
  180. {
  181. ber_bvecfree( conn->c_domain );
  182. conn->c_domain = NULL;
  183. }
  184. /* conn->c_ops= NULL; */
  185. conn->c_gettingber= 0;
  186. conn->c_currentber= NULL;
  187. conn->c_starttime= 0;
  188. conn->c_connid= 0;
  189. conn->c_opsinitiated= 0;
  190. conn->c_opscompleted= 0;
  191. conn->c_threadnumber= 0;
  192. conn->c_refcnt= 0;
  193. conn->c_idlesince= 0;
  194. conn->c_flags= 0;
  195. conn->c_needpw= 0;
  196. conn->c_prfd= NULL;
  197. /* c_ci stays as it is */
  198. conn->c_fdi= SLAPD_INVALID_SOCKET_INDEX;
  199. conn->c_next= NULL;
  200. conn->c_prev= NULL;
  201. conn->c_extension= NULL;
  202. conn->c_ssl_ssf = 0;
  203. conn->c_local_ssf = 0;
  204. conn->c_unix_local = 0;
  205. /* destroy any sasl context */
  206. sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
  207. /* PAGED_RESULTS */
  208. handle_closed_connection(conn); /* Clean up sockbufs */
  209. pagedresults_cleanup(conn, 0 /* do not need to lock inside */);
  210. /* free the connection socket buffer */
  211. connection_free_private_buffer(conn);
  212. if (enable_listeners && !g_get_shutdown()) {
  213. ns_enable_listeners();
  214. }
  215. #ifdef ENABLE_NUNC_STANS
  216. /* even if !config_get_enable_nunc_stans, it is ok to set to 0 here */
  217. conn->c_ns_close_jobs = 0;
  218. #endif
  219. }
  220. /*
  221. * Callers of connection_reset() must hold the conn->c_mutex lock.
  222. */
  223. void
  224. connection_reset(Connection* conn, int ns, PRNetAddr * from, int fromLen, int is_SSL)
  225. {
  226. char *pTmp = is_SSL ? "SSL " : "";
  227. char *str_ip = NULL, *str_destip;
  228. char buf_ip[ 256 ], buf_destip[ 256 ];
  229. char *str_unknown = "unknown";
  230. int in_referral_mode = config_check_referral_mode();
  231. LDAPDebug( LDAP_DEBUG_CONNS, "new %sconnection on %d\n", pTmp, conn->c_sd, 0 );
  232. /* bump our count of connections and update SNMP stats */
  233. conn->c_connid = slapi_counter_increment(num_conns);
  234. if (! in_referral_mode) {
  235. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
  236. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnections);
  237. }
  238. /*
  239. * get peer address (IP address of this client)
  240. */
  241. slapi_ch_free( (void**)&conn->cin_addr ); /* just to be conservative */
  242. if ( from->raw.family == PR_AF_LOCAL ) { /* ldapi */
  243. conn->cin_addr = (PRNetAddr *) slapi_ch_malloc( sizeof( PRNetAddr ) );
  244. PL_strncpyz(buf_ip, from->local.path, sizeof(from->local.path));
  245. memcpy( conn->cin_addr, from, sizeof( PRNetAddr ) );
  246. if (!buf_ip[0]) {
  247. PR_GetPeerName( conn->c_prfd, from );
  248. PL_strncpyz(buf_ip, from->local.path, sizeof(from->local.path));
  249. memcpy( conn->cin_addr, from, sizeof( PRNetAddr ) );
  250. if (!buf_ip[0]) {
  251. /* Cannot derive local address, need something for logging */
  252. PL_strncpyz(buf_ip, "local", sizeof(buf_ip));
  253. }
  254. }
  255. str_ip = buf_ip;
  256. } else if ( ((from->ipv6.ip.pr_s6_addr32[0] != 0) || /* from contains non zeros */
  257. (from->ipv6.ip.pr_s6_addr32[1] != 0) ||
  258. (from->ipv6.ip.pr_s6_addr32[2] != 0) ||
  259. (from->ipv6.ip.pr_s6_addr32[3] != 0)) ||
  260. ((conn->c_prfd != NULL) && (PR_GetPeerName( conn->c_prfd, from ) == 0)) )
  261. {
  262. conn->cin_addr = (PRNetAddr *) slapi_ch_malloc( sizeof( PRNetAddr ) );
  263. memcpy( conn->cin_addr, from, sizeof( PRNetAddr ) );
  264. if ( PR_IsNetAddrType( conn->cin_addr, PR_IpAddrV4Mapped ) ) {
  265. PRNetAddr v4addr;
  266. memset( &v4addr, 0, sizeof( v4addr ) );
  267. v4addr.inet.family = PR_AF_INET;
  268. v4addr.inet.ip = conn->cin_addr->ipv6.ip.pr_s6_addr32[3];
  269. PR_NetAddrToString( &v4addr, buf_ip, sizeof( buf_ip ) );
  270. } else {
  271. PR_NetAddrToString( conn->cin_addr, buf_ip, sizeof( buf_ip ) );
  272. }
  273. buf_ip[ sizeof( buf_ip ) - 1 ] = '\0';
  274. str_ip = buf_ip;
  275. } else {
  276. /* try syscall since "from" was not given and PR_GetPeerName failed */
  277. /* a corner case */
  278. struct sockaddr_in addr; /* assuming IPv4 */
  279. #if ( defined( hpux ) )
  280. int addrlen;
  281. #else
  282. socklen_t addrlen;
  283. #endif
  284. addrlen = sizeof( addr );
  285. memset( &addr, 0, addrlen );
  286. if ( (conn->c_prfd == NULL) &&
  287. (getpeername( conn->c_sd, (struct sockaddr *)&addr, &addrlen ) == 0) )
  288. {
  289. conn->cin_addr = (PRNetAddr *)slapi_ch_malloc( sizeof( PRNetAddr ));
  290. memset( conn->cin_addr, 0, sizeof( PRNetAddr ) );
  291. PR_NetAddrFamily( conn->cin_addr ) = AF_INET6;
  292. /* note: IPv4-mapped IPv6 addr does not work on Windows */
  293. PR_ConvertIPv4AddrToIPv6(addr.sin_addr.s_addr, &(conn->cin_addr->ipv6.ip));
  294. PRLDAP_SET_PORT(conn->cin_addr, addr.sin_port);
  295. /* copy string equivalent of address into a buffer to use for
  296. * logging since each call to inet_ntoa() returns a pointer to a
  297. * single thread-specific buffer (which prevents us from calling
  298. * inet_ntoa() twice in one call to slapi_log_access()).
  299. */
  300. str_ip = inet_ntoa( addr.sin_addr );
  301. strncpy( buf_ip, str_ip, sizeof( buf_ip ) - 1 );
  302. buf_ip[ sizeof( buf_ip ) - 1 ] = '\0';
  303. str_ip = buf_ip;
  304. } else {
  305. str_ip = str_unknown;
  306. }
  307. }
  308. /*
  309. * get destination address (server IP address this client connected to)
  310. */
  311. slapi_ch_free( (void**)&conn->cin_destaddr ); /* just to be conservative */
  312. if ( conn->c_prfd != NULL ) {
  313. conn->cin_destaddr = (PRNetAddr *) slapi_ch_malloc( sizeof( PRNetAddr ) );
  314. memset( conn->cin_destaddr, 0, sizeof( PRNetAddr ));
  315. if (PR_GetSockName( conn->c_prfd, conn->cin_destaddr ) == 0) {
  316. if ( conn->cin_destaddr->raw.family == PR_AF_LOCAL ) { /* ldapi */
  317. PL_strncpyz(buf_destip, conn->cin_destaddr->local.path,
  318. sizeof(conn->cin_destaddr->local.path));
  319. if (!buf_destip[0]) {
  320. PL_strncpyz(buf_destip, "unknown local file", sizeof(buf_destip));
  321. }
  322. } else if ( PR_IsNetAddrType( conn->cin_destaddr, PR_IpAddrV4Mapped ) ) {
  323. PRNetAddr v4destaddr;
  324. memset( &v4destaddr, 0, sizeof( v4destaddr ) );
  325. v4destaddr.inet.family = PR_AF_INET;
  326. v4destaddr.inet.ip = conn->cin_destaddr->ipv6.ip.pr_s6_addr32[3];
  327. PR_NetAddrToString( &v4destaddr, buf_destip, sizeof( buf_destip ) );
  328. } else {
  329. PR_NetAddrToString( conn->cin_destaddr, buf_destip, sizeof( buf_destip ) );
  330. }
  331. buf_destip[ sizeof( buf_destip ) - 1 ] = '\0';
  332. str_destip = buf_destip;
  333. } else {
  334. str_destip = str_unknown;
  335. }
  336. } else {
  337. /* try syscall since c_prfd == NULL */
  338. /* a corner case */
  339. struct sockaddr_in destaddr; /* assuming IPv4 */
  340. #if ( defined( hpux ) )
  341. int destaddrlen;
  342. #else
  343. socklen_t destaddrlen;
  344. #endif
  345. destaddrlen = sizeof( destaddr );
  346. memset( &destaddr, 0, destaddrlen );
  347. if ( (getsockname( conn->c_sd, (struct sockaddr *)&destaddr, &destaddrlen ) == 0) ) {
  348. conn->cin_destaddr = (PRNetAddr *)slapi_ch_malloc( sizeof( PRNetAddr ));
  349. memset( conn->cin_destaddr, 0, sizeof( PRNetAddr ));
  350. PR_NetAddrFamily( conn->cin_destaddr ) = AF_INET6;
  351. PRLDAP_SET_PORT( conn->cin_destaddr, destaddr.sin_port );
  352. /* note: IPv4-mapped IPv6 addr does not work on Windows */
  353. PR_ConvertIPv4AddrToIPv6(destaddr.sin_addr.s_addr, &(conn->cin_destaddr->ipv6.ip));
  354. /* copy string equivalent of address into a buffer to use for
  355. * logging since each call to inet_ntoa() returns a pointer to a
  356. * single thread-specific buffer (which prevents us from calling
  357. * inet_ntoa() twice in one call to slapi_log_access()).
  358. */
  359. str_destip = inet_ntoa( destaddr.sin_addr );
  360. strncpy( buf_destip, str_destip, sizeof( buf_destip ) - 1 );
  361. buf_destip[ sizeof( buf_destip ) - 1 ] = '\0';
  362. str_destip = buf_destip;
  363. } else {
  364. str_destip = str_unknown;
  365. }
  366. }
  367. if ( !in_referral_mode ) {
  368. /* create a sasl connection */
  369. ids_sasl_server_new(conn);
  370. }
  371. /* log useful stuff to our access log */
  372. slapi_log_access( LDAP_DEBUG_STATS,
  373. "conn=%" NSPRIu64 " fd=%d slot=%d %sconnection from %s to %s\n",
  374. conn->c_connid, conn->c_sd, ns, pTmp, str_ip, str_destip );
  375. /* initialize the remaining connection fields */
  376. conn->c_ldapversion = LDAP_VERSION3;
  377. conn->c_starttime = current_time();
  378. conn->c_idlesince = conn->c_starttime;
  379. conn->c_flags = is_SSL ? CONN_FLAG_SSL : 0;
  380. conn->c_authtype = slapi_ch_strdup(SLAPD_AUTH_NONE);
  381. /* Just initialize the SSL SSF to 0 now since the handshake isn't complete
  382. * yet, which prevents us from getting the effective key length. */
  383. conn->c_ssl_ssf = 0;
  384. conn->c_local_ssf = 0;
  385. }
  386. /* Create a pool of threads for handling the operations */
  387. void
  388. init_op_threads()
  389. {
  390. int i;
  391. PRErrorCode errorCode;
  392. int max_threads = config_get_threadnumber();
  393. /* Initialize the locks and cv */
  394. if ((work_q_lock = PR_NewLock()) == NULL ) {
  395. errorCode = PR_GetError();
  396. LDAPDebug( LDAP_DEBUG_ANY,
  397. "init_op_threads: PR_NewLock failed for work_q_lock, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
  398. errorCode, slapd_pr_strerror(errorCode), 0 );
  399. exit(-1);
  400. }
  401. if ((work_q_cv = PR_NewCondVar( work_q_lock )) == NULL) {
  402. errorCode = PR_GetError();
  403. LDAPDebug( LDAP_DEBUG_ANY, "init_op_threads: PR_NewCondVar failed for work_q_cv, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
  404. errorCode, slapd_pr_strerror(errorCode), 0 );
  405. exit(-1);
  406. }
  407. work_q_stack = PR_CreateStack("connection_work_q");
  408. op_stack = PR_CreateStack("connection_operation");
  409. /* start the operation threads */
  410. for (i=0; i < max_threads; i++) {
  411. PR_SetConcurrency(4);
  412. if (PR_CreateThread (PR_USER_THREAD,
  413. (VFP) (void *) connection_threadmain, NULL,
  414. PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
  415. PR_UNJOINABLE_THREAD,
  416. SLAPD_DEFAULT_THREAD_STACKSIZE ) == NULL )
  417. {
  418. int prerr = PR_GetError();
  419. LDAPDebug( LDAP_DEBUG_ANY, "PR_CreateThread failed, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
  420. prerr, slapd_pr_strerror( prerr ), 0 );
  421. } else {
  422. g_incr_active_threadcnt();
  423. }
  424. }
  425. }
  426. static void
  427. referral_mode_reply(Slapi_PBlock *pb)
  428. {
  429. struct slapdplugin *plugin;
  430. plugin = (struct slapdplugin *) slapi_ch_calloc(1, sizeof(struct slapdplugin));
  431. if (plugin!=NULL)
  432. {
  433. struct berval *urls[2], url;
  434. char *refer;
  435. refer = config_get_referral_mode();
  436. pb->pb_plugin = plugin;
  437. set_db_default_result_handlers(pb);
  438. urls[0] = &url;
  439. urls[1] = NULL;
  440. url.bv_val = refer;
  441. url.bv_len = refer ? strlen(refer) : 0;
  442. slapi_send_ldap_result(pb, LDAP_REFERRAL, NULL, NULL, 0, urls);
  443. slapi_ch_free((void **)&plugin);
  444. slapi_ch_free((void **)&refer);
  445. }
  446. }
  447. static int
  448. connection_need_new_password(const Connection *conn, const Operation *op, Slapi_PBlock *pb)
  449. {
  450. int r= 0;
  451. /*
  452. * add tag != LDAP_REQ_SEARCH to allow admin server 3.5 to do
  453. * searches when the user needs to reset
  454. * the pw the first time logon.
  455. * LP: 22 Dec 2000: Removing LDAP_REQ_SEARCH. It's very unlikely that AS 3.5 will
  456. * be used to manage DS5.0
  457. */
  458. if ( conn->c_needpw && op->o_tag != LDAP_REQ_MODIFY &&
  459. op->o_tag != LDAP_REQ_BIND && op->o_tag != LDAP_REQ_UNBIND &&
  460. op->o_tag != LDAP_REQ_ABANDON && op->o_tag != LDAP_REQ_EXTENDED)
  461. {
  462. slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
  463. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d %s\n",
  464. pb->pb_conn->c_connid, pb->pb_op->o_opid,
  465. "UNPROCESSED OPERATION - need new password" );
  466. send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM,
  467. NULL, NULL, 0, NULL );
  468. r= 1;
  469. }
  470. return r;
  471. }
  472. static void
  473. connection_dispatch_operation(Connection *conn, Operation *op, Slapi_PBlock *pb)
  474. {
  475. int minssf = config_get_minssf();
  476. int minssf_exclude_rootdse = 0;
  477. #ifdef TCP_CORK
  478. int enable_nagle = config_get_nagle();
  479. int pop_cork = 0;
  480. #endif
  481. /* Get the effective key length now since the first SSL handshake should be complete */
  482. connection_set_ssl_ssf( conn );
  483. /* Copy the Connection DN and SSF into the operation struct */
  484. op_copy_identity( conn, op );
  485. #if defined(USE_OPENLDAP)
  486. if (slapi_operation_is_flag_set(op, OP_FLAG_REPLICATED)) {
  487. /* If it is replicated op, ignore the maxbersize. */
  488. ber_len_t maxbersize = 0;
  489. ber_sockbuf_ctrl(conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize);
  490. }
  491. #endif
  492. /* If the minimum SSF requirements are not met, only allow
  493. * bind and extended operations through. The bind and extop
  494. * code will ensure that only SASL binds and startTLS are
  495. * allowed, which gives the connection a chance to meet the
  496. * SSF requirements. We also allow UNBIND and ABANDON.*/
  497. /*
  498. * If nsslapd-minssf-exclude-rootdse is on, we have to go to the
  499. * next step and check if the operation is against rootdse or not.
  500. * Once found it's not on rootdse, return LDAP_UNWILLING_TO_PERFORM there.
  501. */
  502. minssf_exclude_rootdse = config_get_minssf_exclude_rootdse();
  503. if (!minssf_exclude_rootdse &&
  504. (conn->c_sasl_ssf < minssf) && (conn->c_ssl_ssf < minssf) &&
  505. (conn->c_local_ssf < minssf) &&(op->o_tag != LDAP_REQ_BIND) &&
  506. (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND) &&
  507. (op->o_tag != LDAP_REQ_ABANDON)) {
  508. slapi_log_access( LDAP_DEBUG_STATS,
  509. "conn=%" NSPRIu64 " op=%d UNPROCESSED OPERATION"
  510. " - Insufficient SSF (local_ssf=%d sasl_ssf=%d ssl_ssf=%d)\n",
  511. conn->c_connid, op->o_opid, conn->c_local_ssf,
  512. conn->c_sasl_ssf, conn->c_ssl_ssf );
  513. send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  514. "Minimum SSF not met.", 0, NULL );
  515. return;
  516. }
  517. /* If anonymous access is disabled and the connection is
  518. * not authenticated, only allow bind and extended operations.
  519. * We allow extended operations so one can do a startTLS prior
  520. * to binding to protect their credentials in transit.
  521. * We also allow UNBIND and ABANDON.
  522. *
  523. * If anonymous access is only allowed for root DSE searches,
  524. * we let SEARCH operations through as well. The search code
  525. * is responsible for checking if the operation is a root DSE
  526. * search. */
  527. if ((slapi_sdn_get_dn(&(op->o_sdn)) == NULL ) &&
  528. /* anon access off and something other than BIND, EXTOP, UNBIND or ABANDON */
  529. (((config_get_anon_access_switch() == SLAPD_ANON_ACCESS_OFF) && (op->o_tag != LDAP_REQ_BIND) &&
  530. (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND) && (op->o_tag != LDAP_REQ_ABANDON)) ||
  531. /* root DSE access only and something other than BIND, EXTOP, UNBIND, ABANDON, or SEARCH */
  532. ((config_get_anon_access_switch() == SLAPD_ANON_ACCESS_ROOTDSE) && (op->o_tag != LDAP_REQ_BIND) &&
  533. (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND) &&
  534. (op->o_tag != LDAP_REQ_ABANDON) && (op->o_tag != LDAP_REQ_SEARCH))))
  535. {
  536. slapi_log_access( LDAP_DEBUG_STATS,
  537. "conn=%" NSPRIu64 " op=%d UNPROCESSED OPERATION"
  538. " - Anonymous access not allowed\n",
  539. conn->c_connid, op->o_opid );
  540. send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
  541. "Anonymous access is not allowed.",
  542. 0, NULL );
  543. return;
  544. }
  545. /* process the operation */
  546. switch ( op->o_tag ) {
  547. case LDAP_REQ_BIND:
  548. operation_set_type(op,SLAPI_OPERATION_BIND);
  549. do_bind( pb );
  550. break;
  551. case LDAP_REQ_UNBIND:
  552. operation_set_type(op,SLAPI_OPERATION_UNBIND);
  553. do_unbind( pb );
  554. break;
  555. case LDAP_REQ_ADD:
  556. operation_set_type(op,SLAPI_OPERATION_ADD);
  557. do_add( pb );
  558. break;
  559. case LDAP_REQ_DELETE:
  560. operation_set_type(op,SLAPI_OPERATION_DELETE);
  561. do_delete( pb );
  562. break;
  563. case LDAP_REQ_MODRDN:
  564. operation_set_type(op,SLAPI_OPERATION_MODRDN);
  565. do_modrdn( pb );
  566. break;
  567. case LDAP_REQ_MODIFY:
  568. operation_set_type(op,SLAPI_OPERATION_MODIFY);
  569. do_modify( pb );
  570. break;
  571. case LDAP_REQ_COMPARE:
  572. operation_set_type(op,SLAPI_OPERATION_COMPARE);
  573. do_compare( pb );
  574. break;
  575. case LDAP_REQ_SEARCH:
  576. operation_set_type(op,SLAPI_OPERATION_SEARCH);
  577. /* On Linux we can use TCP_CORK to get us 5-10% speed benefit when one entry is returned */
  578. /* Nagle needs to be turned _on_, the default is _on_ on linux, in daemon.c */
  579. #ifdef TCP_CORK
  580. if (enable_nagle && !conn->c_unix_local)
  581. {
  582. int i = 1;
  583. int ret = setsockopt(conn->c_sd,IPPROTO_TCP,TCP_CORK,&i,sizeof(i));
  584. if (ret < 0) {
  585. LDAPDebug(LDAP_DEBUG_ANY, "Failed to set TCP_CORK on connection %" NSPRIu64 "\n",conn->c_connid, 0, 0);
  586. }
  587. pop_cork = 1;
  588. }
  589. #endif
  590. do_search( pb );
  591. #ifdef TCP_CORK
  592. if (pop_cork) {
  593. /* Clear TCP_CORK to flush any unsent data but only if not LDAPI*/
  594. int i = 0;
  595. int ret = setsockopt(conn->c_sd,IPPROTO_TCP,TCP_CORK,&i,sizeof(i));
  596. if (ret < 0) {
  597. LDAPDebug(LDAP_DEBUG_ANY, "Failed to clear TCP_CORK on connection %" NSPRIu64 "\n",conn->c_connid, 0, 0);
  598. }
  599. }
  600. #endif
  601. break;
  602. /* for some strange reason, the console is using this old obsolete
  603. * value for ABANDON so we have to support it until the console
  604. * get fixed
  605. * otherwise the console has VERY BAD performances when a fair amount
  606. * of entries are created in the DIT
  607. */
  608. case LDAP_REQ_ABANDON_30:
  609. case LDAP_REQ_ABANDON:
  610. operation_set_type(op,SLAPI_OPERATION_ABANDON);
  611. do_abandon( pb );
  612. break;
  613. case LDAP_REQ_EXTENDED:
  614. operation_set_type(op,SLAPI_OPERATION_EXTENDED);
  615. do_extended( pb );
  616. break;
  617. default:
  618. LDAPDebug( LDAP_DEBUG_ANY,
  619. "ignoring unknown LDAP request (conn=%" NSPRIu64 ", tag=0x%lx)\n",
  620. conn->c_connid, op->o_tag, 0 );
  621. break;
  622. }
  623. }
  624. /* this function should be called under c_mutex */
  625. int connection_release_nolock_ext (Connection *conn, int release_only)
  626. {
  627. if (conn->c_refcnt <= 0)
  628. {
  629. slapi_log_error(SLAPI_LOG_FATAL, "connection",
  630. "conn=%" NSPRIu64 " fd=%d Attempt to release connection that is not acquired\n",
  631. conn->c_connid, conn->c_sd);
  632. PR_ASSERT (PR_FALSE);
  633. return -1;
  634. }
  635. else
  636. {
  637. conn->c_refcnt--;
  638. if (!release_only && (conn->c_refcnt == 1) && (conn->c_flags & CONN_FLAG_CLOSING)) {
  639. /* if refcnt == 1 usually means only the active connection list has a ref */
  640. /* refcnt == 0 means conntable just dropped the last ref */
  641. ns_connection_post_io_or_closing(conn);
  642. }
  643. return 0;
  644. }
  645. }
  646. int connection_release_nolock (Connection *conn)
  647. {
  648. return connection_release_nolock_ext(conn, 0);
  649. }
  650. /* this function should be called under c_mutex */
  651. int connection_acquire_nolock_ext (Connection *conn, int allow_when_closing)
  652. {
  653. /* connection in the closing state can't be acquired */
  654. if (!allow_when_closing && (conn->c_flags & CONN_FLAG_CLOSING))
  655. {
  656. /* This may happen while other threads are still working on this connection */
  657. slapi_log_error(SLAPI_LOG_FATAL, "connection",
  658. "conn=%" NSPRIu64 " fd=%d Attempt to acquire connection in the closing state\n",
  659. conn->c_connid, conn->c_sd);
  660. return -1;
  661. }
  662. else
  663. {
  664. conn->c_refcnt++;
  665. return 0;
  666. }
  667. }
  668. int connection_acquire_nolock (Connection *conn) {
  669. return connection_acquire_nolock_ext(conn, 0);
  670. }
  671. /* returns non-0 if connection can be reused and 0 otherwise */
  672. int connection_is_free (Connection *conn)
  673. {
  674. int rc;
  675. PR_EnterMonitor(conn->c_mutex);
  676. rc = conn->c_sd == SLAPD_INVALID_SOCKET && conn->c_refcnt == 0 &&
  677. !(conn->c_flags & CONN_FLAG_CLOSING);
  678. PR_ExitMonitor(conn->c_mutex);
  679. return rc;
  680. }
  681. int connection_is_active_nolock (Connection *conn)
  682. {
  683. return (conn->c_sd != SLAPD_INVALID_SOCKET) &&
  684. !(conn->c_flags & CONN_FLAG_CLOSING);
  685. }
  686. /* The connection private structure for UNIX turbo mode */
  687. struct Conn_private
  688. {
  689. int previous_op_count; /* the operation counter value last time we sampled it, used to compute operation rate */
  690. int operation_rate; /* rate (ops/sample period) at which this connection has been processing operations */
  691. time_t previous_count_check_time; /* The wall clock time we last sampled the operation count */
  692. size_t c_buffer_size; /* size of the socket read buffer */
  693. char *c_buffer; /* pointer to the socket read buffer */
  694. size_t c_buffer_bytes; /* number of bytes currently stored in the buffer */
  695. size_t c_buffer_offset; /* offset to the location of new data in the buffer */
  696. int use_buffer; /* if true, use the buffer - if false, ber_get_next reads directly from socket */
  697. };
  698. #if defined(USE_OPENLDAP)
  699. /* Copy up to bytes_to_read bytes from b into return_buffer.
  700. * Returns a count of bytes copied (always >= 0).
  701. */
  702. ber_slen_t
  703. openldap_read_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
  704. {
  705. Connection *conn = NULL;
  706. /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */
  707. ber_slen_t bytes_to_copy = 0;
  708. char *readbuf; /* buffer to "read" from */
  709. size_t max; /* number of bytes currently stored in the buffer */
  710. size_t offset; /* offset to the location of new data in the buffer */
  711. PR_ASSERT(sbiod);
  712. PR_ASSERT(sbiod->sbiod_pvt);
  713. conn = (Connection *)sbiod->sbiod_pvt;
  714. if (CONNECTION_BUFFER_OFF == conn->c_private->use_buffer) {
  715. bytes_to_copy = PR_Recv(conn->c_prfd,buf,len,0,PR_INTERVAL_NO_WAIT);
  716. goto done;
  717. }
  718. PR_ASSERT(conn->c_private->c_buffer);
  719. readbuf = conn->c_private->c_buffer;
  720. max = conn->c_private->c_buffer_bytes;
  721. offset = conn->c_private->c_buffer_offset;
  722. if (len <= (max - offset)) {
  723. bytes_to_copy = len; /* we have enough buffered data */
  724. } else {
  725. bytes_to_copy = max - offset; /* just return what we have */
  726. }
  727. if (bytes_to_copy <= 0) {
  728. bytes_to_copy = 0; /* never return a negative result */
  729. /* in this case, we don't have enough data to satisfy the
  730. caller, so we have to let it know we need more */
  731. #if defined(EWOULDBLOCK)
  732. errno = EWOULDBLOCK;
  733. #elif defined(EAGAIN)
  734. errno = EAGAIN;
  735. #endif
  736. PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
  737. } else {
  738. /* copy buffered data into output buf */
  739. SAFEMEMCPY(buf, readbuf + offset, bytes_to_copy);
  740. conn->c_private->c_buffer_offset += bytes_to_copy;
  741. }
  742. done:
  743. return bytes_to_copy;
  744. }
  745. #endif
  746. int
  747. connection_new_private(Connection *conn)
  748. {
  749. if (NULL == conn->c_private) {
  750. Conn_private *new_private = (Conn_private *)slapi_ch_calloc(1,sizeof(Conn_private));
  751. if (NULL == new_private) {
  752. /* memory allocation failed */
  753. return -1;
  754. }
  755. conn->c_private = new_private;
  756. conn->c_private->use_buffer = config_get_connection_buffer();
  757. }
  758. /* The c_buffer is supposed to be NULL here, cleaned by connection_cleanup,
  759. double check to avoid memory leak */
  760. if ((CONNECTION_BUFFER_OFF != conn->c_private->use_buffer) && (NULL == conn->c_private->c_buffer)) {
  761. conn->c_private->c_buffer = (char*)slapi_ch_malloc(LDAP_SOCKET_IO_BUFFER_SIZE);
  762. if (NULL == conn->c_private->c_buffer) {
  763. /* memory allocation failure */
  764. return -1;
  765. }
  766. conn->c_private->c_buffer_size = LDAP_SOCKET_IO_BUFFER_SIZE;
  767. }
  768. /*
  769. * Clear the private structure, preserving the buffer and length in
  770. * case we are reusing the buffer.
  771. */
  772. {
  773. char *c_buffer = conn->c_private->c_buffer;
  774. size_t c_buffer_size = conn->c_private->c_buffer_size;
  775. int use_buffer = conn->c_private->use_buffer;
  776. memset( conn->c_private, 0, sizeof(Conn_private));
  777. conn->c_private->c_buffer = c_buffer;
  778. conn->c_private->c_buffer_size = c_buffer_size;
  779. conn->c_private->use_buffer = use_buffer;
  780. }
  781. return 0;
  782. }
  783. static void
  784. connection_free_private_buffer(Connection *conn)
  785. {
  786. if (NULL != conn->c_private) {
  787. slapi_ch_free((void*)&(conn->c_private->c_buffer));
  788. }
  789. }
  790. /*
  791. * Turbo Mode:
  792. * Turbo Connection Mode is designed to more efficiently
  793. * serve a small number of highly active connections performing
  794. * mainly search operations. It is only used on UNIX---completion
  795. * ports on NT make it unnecessary.
  796. * A connection can be in turbo mode, or not in turbo mode.
  797. * For non-turbo mode, the code path is the same as was before:
  798. * worker threads wait on a condition variable for work.
  799. * When they awake they consult the operation queue for
  800. * something to do, read the operation from the connection's socket,
  801. * perform the operation and go back to waiting on the condition variable.
  802. * In Turbo Mode, a worker thread becomes associated with a connection.
  803. * It then waits not on the condition variable, but directly on read ready
  804. * state on the connection's socket. When new data arrives, it decodes
  805. * the operation and executes it, and then goes back to read another
  806. * operation from the same socket, or block waiting on new data.
  807. * The read is done non-blocking, wait in poll with a timeout.
  808. *
  809. * There is a mechanism to ensure that only the most active
  810. * connections are in turbo mode at any time. If this were not
  811. * the case we could starve out some client operation requests
  812. * due to waiting on I/O in many turbo threads at the same time.
  813. *
  814. * Each worker thread periodically (every 10 seconds) examines
  815. * the activity level for the connection it is processing.
  816. * This applies regardless of whether the connection is
  817. * currently in turbo mode or not. Activity is measured as
  818. * the number of operations initiated since the last check was done.
  819. * The N connections with the highest activity level are allowed
  820. * to enter turbo mode. If the current connection is in the top N,
  821. * then we decide to enter turbo mode. If the current connection
  822. * is no longer in the top N, then we leave turbo mode.
  823. * The decision to enter or leave turbo mode is taken under
  824. * the connection mutex, preventing race conditions where
  825. * more than one thread can change the turbo state of a connection
  826. * concurrently.
  827. */
  828. /* Connection status values returned by
  829. connection_wait_for_new_work(), connection_read_operation(), etc. */
  830. #define CONN_FOUND_WORK_TO_DO 0
  831. #define CONN_SHUTDOWN 1
  832. #define CONN_NOWORK 2
  833. #define CONN_DONE 3
  834. #define CONN_TIMEDOUT 4
  835. #define CONN_TURBO_TIMEOUT_INTERVAL 1000 /* milliseconds */
  836. #define CONN_TURBO_CHECK_INTERVAL 5 /* seconds */
  837. #define CONN_TURBO_PERCENTILE 50 /* proportion of threads allowed to be in turbo mode */
  838. #define CONN_TURBO_HYSTERESIS 0 /* avoid flip flopping in and out of turbo mode */
  839. void connection_make_new_pb(Slapi_PBlock *pb, Connection *conn)
  840. {
  841. struct Slapi_op_stack *stack_obj = NULL;
  842. /* we used to malloc/free the pb for each operation - now, just use a local stack pb
  843. * in connection_threadmain, and just clear it out
  844. */
  845. /* *ppb = (Slapi_PBlock *) slapi_ch_calloc( 1, sizeof(Slapi_PBlock) ); */
  846. /* *ppb = slapi_pblock_new(); */
  847. pb->pb_conn = conn;
  848. stack_obj = connection_get_operation();
  849. pb->pb_op = stack_obj->op;
  850. pb->op_stack_elem = stack_obj;
  851. connection_add_operation( conn, pb->pb_op );
  852. }
  853. int connection_wait_for_new_work(Slapi_PBlock *pb, PRIntervalTime interval)
  854. {
  855. int ret = CONN_FOUND_WORK_TO_DO;
  856. work_q_item *wqitem = NULL;
  857. struct Slapi_op_stack *op_stack_obj = NULL;
  858. PR_Lock( work_q_lock );
  859. while( !op_shutdown && WORK_Q_EMPTY ) {
  860. PR_WaitCondVar( work_q_cv, interval );
  861. }
  862. if ( op_shutdown ) {
  863. LDAPDebug0Args( LDAP_DEBUG_TRACE, "connection_wait_for_new_work: shutdown\n" );
  864. ret = CONN_SHUTDOWN;
  865. } else if ( NULL == ( wqitem = get_work_q( &op_stack_obj ) ) ) {
  866. /* not sure how this can happen */
  867. LDAPDebug0Args( LDAP_DEBUG_TRACE, "connection_wait_for_new_work: no work to do\n" );
  868. ret = CONN_NOWORK;
  869. } else {
  870. /* make new pb */
  871. pb->pb_conn = (Connection *)wqitem;
  872. pb->op_stack_elem = op_stack_obj;
  873. pb->pb_op = op_stack_obj->op;
  874. }
  875. PR_Unlock( work_q_lock );
  876. return ret;
  877. }
  878. #ifdef USE_OPENLDAP
  879. #include "openldapber.h"
  880. #else
  881. #include "mozldap.h"
  882. #endif
  883. static ber_tag_t
  884. _ber_get_len(BerElement *ber, ber_len_t *lenp)
  885. {
  886. #ifdef USE_OPENLDAP
  887. OLBerElement *lber = (OLBerElement *)ber;
  888. #else
  889. MozElement *lber = (MozElement *)ber;
  890. #endif
  891. if (NULL == lenp) {
  892. return LBER_DEFAULT;
  893. }
  894. *lenp = 0;
  895. if (NULL == lber) {
  896. return LBER_DEFAULT;
  897. }
  898. *lenp = lber->ber_len;
  899. return lber->ber_tag;
  900. }
  901. /*
  902. * Utility function called by connection_read_operation(). This is a
  903. * small wrapper on top of libldap's ber_get_next_buffer_ext().
  904. *
  905. * Caller must hold conn->c_mutex
  906. *
  907. * Return value:
  908. * 0: Success
  909. * case 1) If there was not enough data in the buffer to complete the
  910. * message, go to the next cycle. In this case, bytes_scanned is set
  911. * to a positive number and *tagp is set to LBER_DEFAULT.
  912. * case 2) Complete. *tagp == (tag of the message) and bytes_scanned is
  913. * set to a positive number.
  914. * -1: Failure
  915. * case 1) *tagp == LBER_OVERFLOW: the length is either bigger than
  916. * ber_uint_t type or the value preset via
  917. * LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE option
  918. * case 2) *tagp == LBER_DEFAULT: memory error or tag mismatch
  919. */
  920. static int
  921. get_next_from_buffer( void *buffer, size_t buffer_size, ber_len_t *lenp,
  922. ber_tag_t *tagp, BerElement *ber, Connection *conn )
  923. {
  924. PRErrorCode err = 0;
  925. PRInt32 syserr = 0;
  926. ber_len_t bytes_scanned = 0;
  927. *lenp = 0;
  928. #if defined(USE_OPENLDAP)
  929. *tagp = ber_get_next( conn->c_sb, &bytes_scanned, ber );
  930. #else
  931. *tagp = ber_get_next_buffer_ext( buffer, buffer_size, lenp, ber,
  932. &bytes_scanned, conn->c_sb );
  933. #endif
  934. /* openldap ber_get_next doesn't return partial bytes_scanned if it hasn't
  935. read a whole pdu - so we have to check the errno for the
  936. "would block" condition meaning openldap needs more data to read */
  937. if ((LBER_OVERFLOW == *tagp || LBER_DEFAULT == *tagp) && 0 == bytes_scanned &&
  938. !SLAPD_SYSTEM_WOULD_BLOCK_ERROR(errno))
  939. {
  940. if ((LBER_OVERFLOW == *tagp) || (errno == ERANGE))
  941. {
  942. ber_len_t maxbersize = config_get_maxbersize();
  943. ber_len_t tmplen = 0;
  944. (void)_ber_get_len(ber, &tmplen);
  945. /* openldap does not differentiate between length == 0
  946. and length > max - all we know is that there was a
  947. problem with the length - assume too big */
  948. err = SLAPD_DISCONNECT_BER_TOO_BIG;
  949. log_ber_too_big_error(conn, tmplen, maxbersize);
  950. }
  951. else
  952. {
  953. err = SLAPD_DISCONNECT_BAD_BER_TAG;
  954. }
  955. syserr = errno;
  956. /* Bad stuff happened, like the client sent us some junk */
  957. LDAPDebug( LDAP_DEBUG_CONNS,
  958. "ber_get_next failed for connection %" NSPRIu64 "\n", conn->c_connid, 0, 0 );
  959. /* reset private buffer */
  960. conn->c_private->c_buffer_bytes = conn->c_private->c_buffer_offset = 0;
  961. /* drop connection */
  962. disconnect_server_nomutex( conn, conn->c_connid, -1, err, syserr );
  963. return -1;
  964. } else if (CONNECTION_BUFFER_OFF == conn->c_private->use_buffer) {
  965. *lenp = bytes_scanned;
  966. if ((LBER_OVERFLOW == *tagp || LBER_DEFAULT == *tagp) && 0 == bytes_scanned &&
  967. SLAPD_SYSTEM_WOULD_BLOCK_ERROR(errno)) {
  968. return -2; /* tells connection_read_operation we need to try again */
  969. }
  970. } else {
  971. /* openldap_read_function will advance c_buffer_offset */
  972. #if !defined(USE_OPENLDAP)
  973. /* success, or need to wait for more data */
  974. /* if openldap could not read a whole pdu, bytes_scanned will be zero -
  975. it does not return partial results */
  976. conn->c_private->c_buffer_offset += bytes_scanned;
  977. #endif
  978. }
  979. return 0;
  980. }
  981. /* Either read read data into the connection buffer, or fail with err set */
  982. static int
  983. connection_read_ldap_data(Connection *conn, PRInt32 *err)
  984. {
  985. int ret = 0;
  986. ret = PR_Recv(conn->c_prfd,conn->c_private->c_buffer,conn->c_private->c_buffer_size,0,PR_INTERVAL_NO_WAIT);
  987. if (ret < 0) {
  988. *err = PR_GetError();
  989. } else if (CONNECTION_BUFFER_ADAPT == conn->c_private->use_buffer) {
  990. if ((ret == conn->c_private->c_buffer_size) && (conn->c_private->c_buffer_size < BUFSIZ)) {
  991. /* we read exactly what we requested - there could be more that we could have read */
  992. /* so increase the buffer size */
  993. conn->c_private->c_buffer_size *= 2;
  994. if (conn->c_private->c_buffer_size > BUFSIZ) {
  995. conn->c_private->c_buffer_size = BUFSIZ;
  996. }
  997. conn->c_private->c_buffer = slapi_ch_realloc(conn->c_private->c_buffer, conn->c_private->c_buffer_size);
  998. }
  999. }
  1000. return ret;
  1001. }
  1002. static size_t
  1003. conn_buffered_data_avail_nolock(Connection *conn, int *conn_closed)
  1004. {
  1005. if ( (conn->c_sd == SLAPD_INVALID_SOCKET) || (conn->c_flags & CONN_FLAG_CLOSING) ) {
  1006. /* connection is closed - ignore the buffer */
  1007. *conn_closed = 1;
  1008. return 0;
  1009. } else {
  1010. *conn_closed = 0;
  1011. return conn->c_private->c_buffer_bytes - conn->c_private->c_buffer_offset;
  1012. }
  1013. }
  1014. /* Upon returning from this function, we have either:
  1015. 1. Read a PDU successfully.
  1016. 2. Detected some error condition with the connection which requires closing it.
  1017. 3. In Turbo mode, we Timed out without seeing any data.
  1018. We also handle the case where we read ahead beyond the current PDU
  1019. by buffering the data and setting the 'remaining_data' flag.
  1020. */
  1021. int connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int *remaining_data)
  1022. {
  1023. ber_len_t len = 0;
  1024. int ret = 0;
  1025. int waits_done = 0;
  1026. ber_int_t msgid;
  1027. int new_operation = 1; /* Are we doing the first I/O read for a new operation ? */
  1028. char *buffer = conn->c_private->c_buffer;
  1029. PRErrorCode err = 0;
  1030. PRInt32 syserr = 0;
  1031. size_t buffer_data_avail;
  1032. int conn_closed = 0;
  1033. PR_EnterMonitor(conn->c_mutex);
  1034. /*
  1035. * if the socket is still valid, get the ber element
  1036. * waiting for us on this connection. timeout is handled
  1037. * in the low-level read_function.
  1038. */
  1039. if ( (conn->c_sd == SLAPD_INVALID_SOCKET) ||
  1040. (conn->c_flags & CONN_FLAG_CLOSING) ) {
  1041. ret = CONN_DONE;
  1042. goto done;
  1043. }
  1044. *tag = LBER_DEFAULT;
  1045. /* First check to see if we have buffered data from "before" */
  1046. if ((buffer_data_avail = conn_buffered_data_avail_nolock(conn, &conn_closed))) {
  1047. /* If so, use that data first */
  1048. if ( 0 != get_next_from_buffer( buffer
  1049. + conn->c_private->c_buffer_offset,
  1050. buffer_data_avail,
  1051. &len, tag, op->o_ber, conn )) {
  1052. ret = CONN_DONE;
  1053. goto done;
  1054. }
  1055. new_operation = 0;
  1056. }
  1057. /* If we still haven't seen a complete PDU, read from the network */
  1058. while (*tag == LBER_DEFAULT) {
  1059. int ioblocktimeout_waits = config_get_ioblocktimeout() / CONN_TURBO_TIMEOUT_INTERVAL;
  1060. /* We should never get here with data remaining in the buffer */
  1061. PR_ASSERT( !new_operation || !conn_buffered_data_avail_nolock(conn, &conn_closed));
  1062. /* We make a non-blocking read call */
  1063. if (CONNECTION_BUFFER_OFF != conn->c_private->use_buffer) {
  1064. ret = connection_read_ldap_data(conn,&err);
  1065. } else {
  1066. ret = get_next_from_buffer( NULL, 0, &len, tag, op->o_ber, conn );
  1067. if (ret == -1) {
  1068. ret = CONN_DONE;
  1069. goto done; /* get_next_from_buffer does the disconnect stuff */
  1070. } else if (ret == 0) {
  1071. ret = len;
  1072. }
  1073. *remaining_data = 0;
  1074. }
  1075. if (ret <= 0) {
  1076. if (0 == ret) {
  1077. /* Connection is closed */
  1078. disconnect_server_nomutex( conn, conn->c_connid, -1, SLAPD_DISCONNECT_BAD_BER_TAG, 0 );
  1079. conn->c_gettingber = 0;
  1080. signal_listner();
  1081. ret = CONN_DONE;
  1082. goto done;
  1083. }
  1084. /* err = PR_GetError(); */
  1085. /* If we would block, we need to poll for a while */
  1086. syserr = PR_GetOSError();
  1087. if ( SLAPD_PR_WOULD_BLOCK_ERROR( err ) ||
  1088. SLAPD_SYSTEM_WOULD_BLOCK_ERROR( syserr ) ) {
  1089. struct PRPollDesc pr_pd;
  1090. PRIntervalTime timeout = PR_MillisecondsToInterval(CONN_TURBO_TIMEOUT_INTERVAL);
  1091. pr_pd.fd = (PRFileDesc *)conn->c_prfd;
  1092. pr_pd.in_flags = PR_POLL_READ;
  1093. pr_pd.out_flags = 0;
  1094. ret = PR_Poll(&pr_pd, 1, timeout);
  1095. waits_done++;
  1096. /* Did we time out ? */
  1097. if (0 == ret) {
  1098. /* We timed out, should the server shutdown ? */
  1099. if (op_shutdown) {
  1100. ret = CONN_SHUTDOWN;
  1101. goto done;
  1102. }
  1103. /* We timed out, is this the first read in a PDU ? */
  1104. if (new_operation) {
  1105. /* If so, we return */
  1106. ret = CONN_TIMEDOUT;
  1107. goto done;
  1108. } else {
  1109. /* Otherwise we loop, unless we exceeded the ioblock timeout */
  1110. if (waits_done > ioblocktimeout_waits) {
  1111. LDAPDebug( LDAP_DEBUG_CONNS,"ioblock timeout expired on connection %" NSPRIu64 "\n", conn->c_connid, 0, 0 );
  1112. disconnect_server_nomutex( conn, conn->c_connid, -1,
  1113. SLAPD_DISCONNECT_IO_TIMEOUT, 0 );
  1114. ret = CONN_DONE;
  1115. goto done;
  1116. } else {
  1117. /* The turbo mode may cause threads starvation.
  1118. Do a yield here to reduce the starving.
  1119. */
  1120. PR_Sleep(PR_INTERVAL_NO_WAIT);
  1121. continue;
  1122. }
  1123. }
  1124. }
  1125. if (-1 == ret) {
  1126. /* PR_Poll call failed */
  1127. err = PR_GetError();
  1128. syserr = PR_GetOSError();
  1129. LDAPDebug( LDAP_DEBUG_ANY,
  1130. "PR_Poll for connection %" NSPRIu64 " returns %d (%s)\n", conn->c_connid, err, slapd_pr_strerror( err ) );
  1131. /* If this happens we should close the connection */
  1132. disconnect_server_nomutex( conn, conn->c_connid, -1, err, syserr );
  1133. ret = CONN_DONE;
  1134. goto done;
  1135. }
  1136. LDAPDebug( LDAP_DEBUG_CONNS,
  1137. "connection %" NSPRIu64 " waited %d times for read to be ready\n", conn->c_connid, waits_done, 0 );
  1138. } else {
  1139. /* Some other error, typically meaning bad stuff */
  1140. syserr = PR_GetOSError();
  1141. LDAPDebug( LDAP_DEBUG_CONNS,
  1142. "PR_Recv for connection %" NSPRIu64 " returns %d (%s)\n", conn->c_connid, err, slapd_pr_strerror( err ) );
  1143. /* If this happens we should close the connection */
  1144. disconnect_server_nomutex( conn, conn->c_connid, -1, err, syserr );
  1145. ret = CONN_DONE;
  1146. goto done;
  1147. }
  1148. } else {
  1149. /* We read some data off the network, do something with it */
  1150. if (CONNECTION_BUFFER_OFF != conn->c_private->use_buffer) {
  1151. conn->c_private->c_buffer_bytes = ret;
  1152. conn->c_private->c_buffer_offset = 0;
  1153. if ( get_next_from_buffer( buffer,
  1154. conn->c_private->c_buffer_bytes
  1155. - conn->c_private->c_buffer_offset,
  1156. &len, tag, op->o_ber, conn ) != 0 ) {
  1157. ret = CONN_DONE;
  1158. goto done;
  1159. }
  1160. }
  1161. LDAPDebug( LDAP_DEBUG_CONNS,
  1162. "connection %" NSPRIu64 " read %d bytes\n", conn->c_connid, ret, 0 );
  1163. new_operation = 0;
  1164. ret = CONN_FOUND_WORK_TO_DO;
  1165. waits_done = 0; /* got some data: reset counter */
  1166. }
  1167. }
  1168. /* If there is remaining buffered data, set the flag to tell the caller */
  1169. if (conn_buffered_data_avail_nolock(conn, &conn_closed)) {
  1170. *remaining_data = 1;
  1171. } else if (conn_closed){
  1172. /* connection closed */
  1173. ret = CONN_DONE;
  1174. goto done;
  1175. }
  1176. if ( *tag != LDAP_TAG_MESSAGE ) {
  1177. /*
  1178. * We received a non-LDAP message. Log and close connection.
  1179. */
  1180. LDAPDebug( LDAP_DEBUG_ANY,
  1181. "conn=%" NSPRIu64 " received a non-LDAP message (tag 0x%lx, expected 0x%lx)\n",
  1182. conn->c_connid, *tag, LDAP_TAG_MESSAGE );
  1183. disconnect_server_nomutex( conn, conn->c_connid, -1,
  1184. SLAPD_DISCONNECT_BAD_BER_TAG, EPROTO );
  1185. ret = CONN_DONE;
  1186. goto done;
  1187. }
  1188. if ( (*tag = ber_get_int( op->o_ber, &msgid ))
  1189. != LDAP_TAG_MSGID ) {
  1190. /* log, close and send error */
  1191. LDAPDebug( LDAP_DEBUG_ANY,
  1192. "conn=%" NSPRIu64 " unable to read tag for incoming request\n", conn->c_connid, 0, 0 );
  1193. disconnect_server_nomutex( conn, conn->c_connid, -1, SLAPD_DISCONNECT_BAD_BER_TAG, EPROTO );
  1194. ret = CONN_DONE;
  1195. goto done;
  1196. }
  1197. if(is_ber_too_big(conn,len)) {
  1198. disconnect_server_nomutex( conn, conn->c_connid, -1, SLAPD_DISCONNECT_BER_TOO_BIG, 0 );
  1199. ret = CONN_DONE;
  1200. goto done;
  1201. }
  1202. op->o_msgid = msgid;
  1203. *tag = ber_peek_tag( op->o_ber, &len );
  1204. switch ( *tag ) {
  1205. case LBER_ERROR:
  1206. case LDAP_TAG_LDAPDN: /* optional username, for CLDAP */
  1207. /* log, close and send error */
  1208. LDAPDebug( LDAP_DEBUG_ANY,
  1209. "conn=%" NSPRIu64 " ber_peek_tag returns 0x%lx\n", conn->c_connid, *tag, 0 );
  1210. disconnect_server_nomutex( conn, conn->c_connid, -1, SLAPD_DISCONNECT_BER_PEEK, EPROTO );
  1211. ret = CONN_DONE;
  1212. goto done;
  1213. default:
  1214. break;
  1215. }
  1216. op->o_tag = *tag;
  1217. done:
  1218. PR_ExitMonitor(conn->c_mutex);
  1219. return ret;
  1220. }
  1221. void connection_make_readable(Connection *conn)
  1222. {
  1223. PR_EnterMonitor(conn->c_mutex);
  1224. conn->c_gettingber = 0;
  1225. PR_ExitMonitor(conn->c_mutex);
  1226. signal_listner();
  1227. }
  1228. void connection_make_readable_nolock(Connection *conn)
  1229. {
  1230. conn->c_gettingber = 0;
  1231. LDAPDebug2Args(LDAP_DEBUG_CONNS, "making readable conn %" NSPRIu64 " fd=%d\n",
  1232. conn->c_connid, conn->c_sd);
  1233. if (!(conn->c_flags & CONN_FLAG_CLOSING)) {
  1234. /* if the connection is closing, try the close in connection_release_nolock */
  1235. ns_connection_post_io_or_closing(conn);
  1236. }
  1237. }
  1238. /*
  1239. * Figure out the operation completion rate for this connection
  1240. */
  1241. void connection_check_activity_level(Connection *conn)
  1242. {
  1243. int current_count = 0;
  1244. int delta_count = 0;
  1245. PR_EnterMonitor(conn->c_mutex);
  1246. /* get the current op count */
  1247. current_count = conn->c_opscompleted;
  1248. /* compare to the previous op count */
  1249. delta_count = current_count - conn->c_private->previous_op_count;
  1250. /* delta is the rate, store that */
  1251. conn->c_private->operation_rate = delta_count;
  1252. /* store current count in the previous count slot */
  1253. conn->c_private->previous_op_count = current_count;
  1254. /* update the last checked time */
  1255. conn->c_private->previous_count_check_time = current_time();
  1256. PR_ExitMonitor(conn->c_mutex);
  1257. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " activity level = %d\n",conn->c_connid,delta_count,0);
  1258. }
  1259. typedef struct table_iterate_info_struct {
  1260. int connection_count;
  1261. int rank_count;
  1262. int our_rate;
  1263. } table_iterate_info;
  1264. int table_iterate_function(Connection *conn, void *arg)
  1265. {
  1266. int ret = 0;
  1267. table_iterate_info *pinfo = (table_iterate_info*)arg;
  1268. pinfo->connection_count++;
  1269. if (conn->c_private->operation_rate > pinfo->our_rate) {
  1270. pinfo->rank_count++;
  1271. }
  1272. return ret;
  1273. }
  1274. /*
  1275. * Scan the list of active connections, evaluate our relative rank
  1276. * for connection activity.
  1277. */
  1278. void connection_find_our_rank(Connection *conn,int *connection_count, int *our_rank)
  1279. {
  1280. table_iterate_info info = {0};
  1281. info.our_rate = conn->c_private->operation_rate;
  1282. connection_table_iterate_active_connections(the_connection_table, &info, &table_iterate_function);
  1283. *connection_count = info.connection_count;
  1284. *our_rank = info.rank_count;
  1285. }
  1286. /*
  1287. * Evaluate the turbo policy for this connection
  1288. */
  1289. void connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int *new_turbo_flag)
  1290. {
  1291. int current_mode = 0;
  1292. int new_mode = 0;
  1293. int connection_count = 0;
  1294. int our_rank = 0;
  1295. int threshold_rank = 0;
  1296. PR_EnterMonitor(conn->c_mutex);
  1297. /* We can already be in turbo mode, or not */
  1298. current_mode = current_turbo_flag;
  1299. if (pagedresults_in_use_nolock(conn)) {
  1300. /* PAGED_RESULTS does not need turbo mode */
  1301. new_mode = 0;
  1302. } else if (conn->c_private->operation_rate == 0) {
  1303. /* The connection is ranked by the passed activities. If some other
  1304. * connection have more activity, increase rank by one. The highest
  1305. * rank is least activity, good candidates to move out of turbo mode.
  1306. * However, if no activity on all the connections, then every
  1307. * connection gets 0 rank, so none move out.
  1308. * No bother to do so much calcuation, short-cut to non-turbo mode
  1309. * if no activities in passed interval */
  1310. new_mode = 0;
  1311. } else {
  1312. double activet = 0.0;
  1313. connection_find_our_rank(conn,&connection_count, &our_rank);
  1314. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " turbo rank = %d out of %d conns\n",conn->c_connid,our_rank,connection_count);
  1315. activet = (double)g_get_active_threadcnt();
  1316. threshold_rank = (int)(activet * ((double)CONN_TURBO_PERCENTILE / 100.0));
  1317. /* adjust threshold_rank according number of connections,
  1318. less turbo threads as more connections,
  1319. one measure to reduce thread startvation.
  1320. */
  1321. if (connection_count > threshold_rank) {
  1322. threshold_rank -= (connection_count - threshold_rank) / 5;
  1323. }
  1324. if (current_mode) {
  1325. /* We're currently in turbo mode */
  1326. /* Policy says that we stay in turbo mode provided
  1327. connection activity is still high.
  1328. */
  1329. if (our_rank - CONN_TURBO_HYSTERESIS < threshold_rank) {
  1330. /* Stay in turbo mode */
  1331. new_mode = 1;
  1332. } else {
  1333. /* Exit turbo mode */
  1334. new_mode = 0;
  1335. }
  1336. } else {
  1337. /* We're currently not in turbo mode */
  1338. /* Policy says that we go into turbo mode if
  1339. recent connection activity is high.
  1340. */
  1341. if (our_rank + CONN_TURBO_HYSTERESIS < threshold_rank) {
  1342. /* Enter turbo mode */
  1343. new_mode = 1;
  1344. } else {
  1345. /* Stay out of turbo mode */
  1346. new_mode = 0;
  1347. }
  1348. }
  1349. }
  1350. PR_ExitMonitor(conn->c_mutex);
  1351. if (current_mode != new_mode) {
  1352. if (current_mode) {
  1353. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " leaving turbo mode\n",conn->c_connid,0,0);
  1354. } else {
  1355. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " entering turbo mode\n",conn->c_connid,0,0);
  1356. }
  1357. }
  1358. *new_turbo_flag = new_mode;
  1359. }
  1360. static void
  1361. connection_threadmain()
  1362. {
  1363. Slapi_PBlock local_pb;
  1364. Slapi_PBlock *pb = &local_pb;
  1365. /* wait forever for new pb until one is available or shutdown */
  1366. PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT; /* PR_SecondsToInterval(10); */
  1367. Connection *conn = NULL;
  1368. Operation *op;
  1369. ber_tag_t tag = 0;
  1370. int need_wakeup = 0;
  1371. int thread_turbo_flag = 0;
  1372. int ret = 0;
  1373. int more_data = 0;
  1374. int replication_connection = 0; /* If this connection is from a replication supplier, we want to ensure that operation processing is serialized */
  1375. int doshutdown = 0;
  1376. int maxthreads = 0;
  1377. int enable_nunc_stans = 0;
  1378. long bypasspollcnt = 0;
  1379. #ifdef ENABLE_NUNC_STANS
  1380. enable_nunc_stans = config_get_enable_nunc_stans();
  1381. #endif
  1382. #if defined( hpux )
  1383. /* Arrange to ignore SIGPIPE signals. */
  1384. SIGNAL( SIGPIPE, SIG_IGN );
  1385. #endif
  1386. pblock_init(pb);
  1387. while (1) {
  1388. int is_timedout = 0;
  1389. time_t curtime = 0;
  1390. if( op_shutdown ) {
  1391. LDAPDebug( LDAP_DEBUG_TRACE,
  1392. "op_thread received shutdown signal\n", 0, 0, 0 );
  1393. g_decr_active_threadcnt();
  1394. return;
  1395. }
  1396. if (!thread_turbo_flag && !more_data) {
  1397. /* If more data is left from the previous connection_read_operation,
  1398. we should finish the op now. Client might be thinking it's
  1399. done sending the request and wait for the response forever.
  1400. [blackflag 624234] */
  1401. ret = connection_wait_for_new_work(pb,interval);
  1402. switch (ret) {
  1403. case CONN_NOWORK:
  1404. PR_ASSERT(interval != PR_INTERVAL_NO_TIMEOUT); /* this should never happen with PR_INTERVAL_NO_TIMEOUT */
  1405. continue;
  1406. case CONN_SHUTDOWN:
  1407. LDAPDebug( LDAP_DEBUG_TRACE,
  1408. "op_thread received shutdown signal\n", 0, 0, 0 );
  1409. g_decr_active_threadcnt();
  1410. return;
  1411. case CONN_FOUND_WORK_TO_DO:
  1412. /* note - don't need to lock here - connection should only
  1413. be used by this thread - since c_gettingber is set to 1
  1414. in connection_activity when the conn is added to the
  1415. work queue, setup_pr_read_pds won't add the connection prfd
  1416. to the poll list */
  1417. if(pb->pb_conn->c_opscompleted == 0){
  1418. /*
  1419. * We have a new connection, set the anonymous reslimit idletimeout
  1420. * if applicable.
  1421. */
  1422. char *anon_dn = config_get_anon_limits_dn();
  1423. int idletimeout;
  1424. /* If an anonymous limits dn is set, use it to set the limits. */
  1425. if (anon_dn && (strlen(anon_dn) > 0)) {
  1426. Slapi_DN *anon_sdn = slapi_sdn_new_normdn_byref( anon_dn );
  1427. reslimit_update_from_dn( pb->pb_conn, anon_sdn );
  1428. slapi_sdn_free( &anon_sdn );
  1429. if (slapi_reslimit_get_integer_limit(pb->pb_conn,
  1430. pb->pb_conn->c_idletimeout_handle,
  1431. &idletimeout)
  1432. == SLAPI_RESLIMIT_STATUS_SUCCESS)
  1433. {
  1434. pb->pb_conn->c_idletimeout = idletimeout;
  1435. }
  1436. }
  1437. slapi_ch_free_string( &anon_dn );
  1438. }
  1439. if (connection_call_io_layer_callbacks(pb->pb_conn)) {
  1440. LDAPDebug0Args( LDAP_DEBUG_ANY, "Error: could not add/remove IO layers from connection\n" );
  1441. }
  1442. default:
  1443. break;
  1444. }
  1445. } else {
  1446. /* The turbo mode may cause threads starvation.
  1447. Do a yield here to reduce the starving
  1448. */
  1449. PR_Sleep(PR_INTERVAL_NO_WAIT);
  1450. PR_EnterMonitor(conn->c_mutex);
  1451. /* Make our own pb in turbo mode */
  1452. connection_make_new_pb(pb,conn);
  1453. if (connection_call_io_layer_callbacks(conn)) {
  1454. LDAPDebug0Args( LDAP_DEBUG_ANY, "Error: could not add/remove IO layers from connection\n" );
  1455. }
  1456. PR_ExitMonitor(conn->c_mutex);
  1457. if (! config_check_referral_mode()) {
  1458. slapi_counter_increment(ops_initiated);
  1459. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps);
  1460. }
  1461. }
  1462. /* Once we're here we have a pb */
  1463. conn = pb->pb_conn;
  1464. op = pb->pb_op;
  1465. maxthreads = config_get_maxthreadsperconn();
  1466. more_data = 0;
  1467. ret = connection_read_operation(conn, op, &tag, &more_data);
  1468. if ((ret == CONN_DONE) || (ret == CONN_TIMEDOUT)) {
  1469. slapi_log_error(SLAPI_LOG_CONNS, "connection_threadmain",
  1470. "conn %" NSPRIu64 " read not ready due to %d - thread_turbo_flag %d more_data %d "
  1471. "ops_initiated %d refcnt %d flags %d\n", conn->c_connid, ret, thread_turbo_flag, more_data,
  1472. conn->c_opsinitiated, conn->c_refcnt, conn->c_flags);
  1473. } else if (ret == CONN_FOUND_WORK_TO_DO) {
  1474. slapi_log_error(SLAPI_LOG_CONNS, "connection_threadmain",
  1475. "conn %" NSPRIu64 " read operation successfully - thread_turbo_flag %d more_data %d "
  1476. "ops_initiated %d refcnt %d flags %d\n", conn->c_connid, thread_turbo_flag, more_data,
  1477. conn->c_opsinitiated, conn->c_refcnt, conn->c_flags);
  1478. }
  1479. curtime = current_time();
  1480. #define DB_PERF_TURBO 1
  1481. #if defined(DB_PERF_TURBO)
  1482. /* If it's been a while since we last did it ... */
  1483. if (curtime - conn->c_private->previous_count_check_time > CONN_TURBO_CHECK_INTERVAL) {
  1484. if (config_get_enable_turbo_mode()) {
  1485. int new_turbo_flag = 0;
  1486. /* Check the connection's activity level */
  1487. connection_check_activity_level(conn);
  1488. /* And if appropriate, change into or out of turbo mode */
  1489. connection_enter_leave_turbo(conn,thread_turbo_flag,&new_turbo_flag);
  1490. thread_turbo_flag = new_turbo_flag;
  1491. } else {
  1492. thread_turbo_flag = 0;
  1493. }
  1494. }
  1495. /* turn off turbo mode immediately if any pb waiting in global queue */
  1496. if (thread_turbo_flag && !WORK_Q_EMPTY) {
  1497. thread_turbo_flag = 0;
  1498. LDAPDebug2Args(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " leaving turbo mode - pb_q is not empty %d\n",
  1499. conn->c_connid,work_q_size);
  1500. }
  1501. #endif
  1502. switch (ret) {
  1503. case CONN_DONE:
  1504. /* This means that the connection was closed, so clear turbo mode */
  1505. /*FALLTHROUGH*/
  1506. case CONN_TIMEDOUT:
  1507. thread_turbo_flag = 0;
  1508. is_timedout = 1;
  1509. /* In the case of CONN_DONE, more_data could have been set to 1
  1510. * in connection_read_operation before an error was encountered.
  1511. * In that case, we need to set more_data to 0 - even if there is
  1512. * more data available, we're not going to use it anyway.
  1513. * In the case of CONN_TIMEDOUT, it is only used in one place, and
  1514. * more_data will never be set to 1, so it is safe to set it to 0 here.
  1515. * We need more_data to be 0 so the connection will be processed
  1516. * correctly at the end of this function.
  1517. */
  1518. more_data = 0;
  1519. /* note:
  1520. * should call connection_make_readable after the op is removed
  1521. * connection_make_readable(conn);
  1522. */
  1523. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " leaving turbo mode due to %d\n",
  1524. conn->c_connid,ret,0);
  1525. goto done;
  1526. case CONN_SHUTDOWN:
  1527. LDAPDebug( LDAP_DEBUG_TRACE,
  1528. "op_thread received shutdown signal\n", 0, 0, 0 );
  1529. g_decr_active_threadcnt();
  1530. doshutdown = 1;
  1531. goto done; /* To destroy pb, jump to done once */
  1532. default:
  1533. break;
  1534. }
  1535. /* if we got here, then we had some read activity */
  1536. if (thread_turbo_flag) {
  1537. /* turbo mode avoids handle_pr_read_ready which avoids setting c_idlesince
  1538. update c_idlesince here since, if we got some read activity, we are
  1539. not idle */
  1540. conn->c_idlesince = curtime;
  1541. }
  1542. /*
  1543. * Do not put the connection back to the read ready poll list
  1544. * if the operation is unbind. Unbind will close the socket.
  1545. * Similarly, if we are in turbo mode, don't send the socket
  1546. * back to the poll set.
  1547. * more_data: [blackflag 624234]
  1548. * If the connection is from a replication supplier, don't make it readable here.
  1549. * We want to ensure that replication operations are processed strictly in the order
  1550. * they are received off the wire.
  1551. */
  1552. replication_connection = conn->c_isreplication_session;
  1553. if ((tag != LDAP_REQ_UNBIND) && !thread_turbo_flag && !replication_connection) {
  1554. if (!more_data) {
  1555. conn->c_flags &= ~CONN_FLAG_MAX_THREADS;
  1556. connection_make_readable_nolock(conn);
  1557. /* once the connection is readable, another thread may access conn,
  1558. * so need locking from here on */
  1559. signal_listner();
  1560. /* with nunc-stans, I see an enormous amount of time spent in the poll() in
  1561. * connection_read_operation() when the below code is enabled - not sure why
  1562. * nunc-stans makes such a huge difference - for now, just disable this code
  1563. * when using nunc-stans - it is supposed to be an optimization but turns out
  1564. * to not be the opposite with nunc-stans
  1565. */
  1566. } else if (!enable_nunc_stans) { /* more data in conn - just put back on work_q - bypass poll */
  1567. bypasspollcnt++;
  1568. PR_EnterMonitor(conn->c_mutex);
  1569. /* don't do this if it would put us over the max threads per conn */
  1570. if (conn->c_threadnumber < maxthreads) {
  1571. /* for turbo, c_idlesince is set above - for !turbo and
  1572. * !more_data, we put the conn back in the poll loop and
  1573. * c_idlesince is set in handle_pr_read_ready - since we
  1574. * are bypassing both of those, we set idlesince here
  1575. */
  1576. conn->c_idlesince = curtime;
  1577. connection_activity(conn, maxthreads);
  1578. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " queued because more_data\n",
  1579. conn->c_connid,0,0);
  1580. } else {
  1581. /* keep count of how many times maxthreads has blocked an operation */
  1582. conn->c_maxthreadsblocked++;
  1583. }
  1584. PR_ExitMonitor(conn->c_mutex);
  1585. }
  1586. }
  1587. /* are we in referral-only mode? */
  1588. if (config_check_referral_mode() && tag != LDAP_REQ_UNBIND) {
  1589. referral_mode_reply(pb);
  1590. goto done;
  1591. }
  1592. /* check if new password is required */
  1593. if(connection_need_new_password(conn, op, pb)) {
  1594. goto done;
  1595. }
  1596. /* if this is a bulk import, only "add" and "import done"
  1597. * are allowed */
  1598. if (conn->c_flags & CONN_FLAG_IMPORT) {
  1599. if ((tag != LDAP_REQ_ADD) && (tag != LDAP_REQ_EXTENDED)) {
  1600. /* no cookie for you. */
  1601. LDAPDebug(LDAP_DEBUG_ANY, "Attempted operation %d "
  1602. "from within bulk import\n",
  1603. tag, 0, 0);
  1604. slapi_send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL,
  1605. NULL, 0, NULL);
  1606. goto done;
  1607. }
  1608. }
  1609. /*
  1610. * Call the do_<operation> function to process this request.
  1611. */
  1612. connection_dispatch_operation(conn, op, pb);
  1613. done:
  1614. if (doshutdown) {
  1615. PR_EnterMonitor(conn->c_mutex);
  1616. connection_remove_operation_ext(pb, conn, op);
  1617. connection_make_readable_nolock(conn);
  1618. conn->c_threadnumber--;
  1619. slapi_counter_decrement(conns_in_maxthreads);
  1620. slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
  1621. connection_release_nolock(conn);
  1622. PR_ExitMonitor(conn->c_mutex);
  1623. signal_listner();
  1624. return;
  1625. }
  1626. /*
  1627. * done with this operation. delete it from the op
  1628. * queue for this connection, delete the number of
  1629. * threads devoted to this connection, and see if
  1630. * there's more work to do right now on this conn.
  1631. */
  1632. /* number of ops on this connection */
  1633. PR_AtomicIncrement(&conn->c_opscompleted);
  1634. /* total number of ops for the server */
  1635. slapi_counter_increment(ops_completed);
  1636. /* If this op isn't a persistent search, remove it */
  1637. if ( pb->pb_op->o_flags & OP_FLAG_PS ) {
  1638. PR_EnterMonitor(conn->c_mutex);
  1639. connection_release_nolock (conn); /* psearch acquires ref to conn - release this one now */
  1640. PR_ExitMonitor(conn->c_mutex);
  1641. /* ps_add makes a shallow copy of the pb - so we
  1642. * can't free it or init it here - just memset it to 0
  1643. * ps_send_results will call connection_remove_operation_ext to free it
  1644. */
  1645. memset(pb, 0, sizeof(*pb));
  1646. } else {
  1647. /* delete from connection operation queue & decr refcnt */
  1648. int conn_closed = 0;
  1649. PR_EnterMonitor(conn->c_mutex);
  1650. connection_remove_operation_ext( pb, conn, op );
  1651. /* If we're in turbo mode, we keep our reference to the connection alive */
  1652. /* can't use the more_data var because connection could have changed in another thread */
  1653. more_data = conn_buffered_data_avail_nolock(conn, &conn_closed) ? 1 : 0;
  1654. LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " check more_data %d thread_turbo_flag %d\n",
  1655. conn->c_connid,more_data,thread_turbo_flag);
  1656. if (!more_data) {
  1657. if (!thread_turbo_flag) {
  1658. /*
  1659. * Don't release the connection now.
  1660. * But note down what to do.
  1661. */
  1662. if (replication_connection || (1 == is_timedout)) {
  1663. connection_make_readable_nolock(conn);
  1664. need_wakeup = 1;
  1665. }
  1666. if (!need_wakeup) {
  1667. if (conn->c_threadnumber == maxthreads)
  1668. need_wakeup = 1;
  1669. else
  1670. need_wakeup = 0;
  1671. }
  1672. if(conn->c_threadnumber == maxthreads){
  1673. conn->c_flags &= ~CONN_FLAG_MAX_THREADS;
  1674. slapi_counter_decrement(conns_in_maxthreads);
  1675. slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
  1676. }
  1677. conn->c_threadnumber--;
  1678. connection_release_nolock(conn);
  1679. /* Call signal_listner after releasing the
  1680. * connection if required. */
  1681. if (need_wakeup) {
  1682. signal_listner();
  1683. }
  1684. } else if (1 == is_timedout) {
  1685. connection_make_readable_nolock(conn);
  1686. signal_listner();
  1687. }
  1688. }
  1689. PR_ExitMonitor(conn->c_mutex);
  1690. }
  1691. } /* while (1) */
  1692. }
  1693. /* thread need to hold conn->c_mutex before calling this function */
  1694. int
  1695. connection_activity(Connection *conn, int maxthreads)
  1696. {
  1697. struct Slapi_op_stack *op_stack_obj;
  1698. if (connection_acquire_nolock (conn) == -1) {
  1699. LDAPDebug(LDAP_DEBUG_CONNS,
  1700. "could not acquire lock in connection_activity as conn %" NSPRIu64 " closing fd=%d\n",
  1701. conn->c_connid,conn->c_sd,0);
  1702. /* XXX how to handle this error? */
  1703. /* MAB: 25 Jan 01: let's return on error and pray this won't leak */
  1704. return (-1);
  1705. }
  1706. /* set these here so setup_pr_read_pds will not add this conn back to the poll array */
  1707. conn->c_gettingber = 1;
  1708. conn->c_threadnumber++;
  1709. if(conn->c_threadnumber == maxthreads){
  1710. conn->c_flags |= CONN_FLAG_MAX_THREADS;
  1711. conn->c_maxthreadscount++;
  1712. slapi_counter_increment(max_threads_count);
  1713. slapi_counter_increment(conns_in_maxthreads);
  1714. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
  1715. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHit);
  1716. }
  1717. op_stack_obj = connection_get_operation();
  1718. connection_add_operation(conn, op_stack_obj->op);
  1719. /* Add conn to the end of the work queue. */
  1720. /* have to do this last - add_work_q will signal waiters in connection_wait_for_new_work */
  1721. add_work_q( (work_q_item *)conn, op_stack_obj );
  1722. if (! config_check_referral_mode()) {
  1723. slapi_counter_increment(ops_initiated);
  1724. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps);
  1725. }
  1726. return 0;
  1727. }
  1728. /* add_work_q(): will add a work_q_item to the end of the global work queue. The work queue
  1729. is implemented as a single link list. */
  1730. static void
  1731. add_work_q( work_q_item *wqitem, struct Slapi_op_stack *op_stack_obj )
  1732. {
  1733. struct Slapi_work_q *new_work_q=NULL;
  1734. LDAPDebug( LDAP_DEBUG_TRACE, "add_work_q \n", 0, 0, 0 );
  1735. new_work_q = create_work_q();
  1736. new_work_q->work_item = wqitem;
  1737. new_work_q->op_stack_obj = op_stack_obj;
  1738. new_work_q->next_work_item =NULL;
  1739. PR_Lock( work_q_lock );
  1740. if (tail_work_q == NULL) {
  1741. tail_work_q = new_work_q;
  1742. head_work_q = new_work_q;
  1743. }
  1744. else {
  1745. tail_work_q->next_work_item = new_work_q;
  1746. tail_work_q = new_work_q;
  1747. }
  1748. PR_AtomicIncrement( &work_q_size ); /* increment q size */
  1749. if ( work_q_size > work_q_size_max ) {
  1750. work_q_size_max = work_q_size;
  1751. }
  1752. PR_NotifyCondVar( work_q_cv ); /* notify waiters in connection_wait_for_new_work */
  1753. PR_Unlock( work_q_lock );
  1754. }
  1755. /* get_work_q(): will get a work_q_item from the beginning of the work queue, return NULL if
  1756. the queue is empty. This should only be called from connection_wait_for_new_work
  1757. with the work_q_lock held */
  1758. static work_q_item *
  1759. get_work_q(struct Slapi_op_stack **op_stack_obj)
  1760. {
  1761. struct Slapi_work_q *tmp = NULL;
  1762. work_q_item *wqitem;
  1763. LDAPDebug0Args( LDAP_DEBUG_TRACE, "get_work_q \n" );
  1764. if (head_work_q == NULL) {
  1765. LDAPDebug0Args( LDAP_DEBUG_TRACE, "get_work_q: the work queue is empty.\n" );
  1766. return NULL;
  1767. }
  1768. tmp = head_work_q;
  1769. if ( head_work_q == tail_work_q ) {
  1770. tail_work_q = NULL;
  1771. }
  1772. head_work_q = tmp->next_work_item;
  1773. wqitem = tmp->work_item;
  1774. *op_stack_obj = tmp->op_stack_obj;
  1775. PR_AtomicDecrement( &work_q_size ); /* decrement q size */
  1776. /* Free the memory used by the item found. */
  1777. destroy_work_q(&tmp);
  1778. return (wqitem);
  1779. }
  1780. /* Helper functions common to both varieties of connection code: */
  1781. /* op_thread_cleanup() : This function is called by daemon thread when it gets
  1782. the slapd_shutdown signal. It will set op_shutdown to 1 and notify
  1783. all thread waiting on op_thread_cv to terminate. */
  1784. void
  1785. op_thread_cleanup()
  1786. {
  1787. LDAPDebug( LDAP_DEBUG_ANY,
  1788. "slapd shutting down - signaling operation threads - op stack size %d max work q size %d max work q stack size %d\n",
  1789. op_stack_size, work_q_size_max, work_q_stack_size_max);
  1790. PR_AtomicIncrement(&op_shutdown);
  1791. PR_Lock( work_q_lock );
  1792. PR_NotifyAllCondVar ( work_q_cv ); /* tell any thread waiting in connection_wait_for_new_work to shutdown */
  1793. PR_Unlock( work_q_lock );
  1794. }
  1795. /* do this after all worker threads have terminated */
  1796. void
  1797. connection_post_shutdown_cleanup()
  1798. {
  1799. struct Slapi_op_stack *stack_obj;
  1800. int stack_cnt = 0;
  1801. struct Slapi_work_q *work_q;
  1802. int work_cnt = 0;
  1803. while ((work_q = (struct Slapi_work_q *)PR_StackPop(work_q_stack))) {
  1804. Connection *conn = (Connection *)work_q->work_item;
  1805. stack_obj = work_q->op_stack_obj;
  1806. if (stack_obj) {
  1807. if (conn) {
  1808. connection_remove_operation(conn, stack_obj->op);
  1809. }
  1810. connection_done_operation(conn, stack_obj);
  1811. }
  1812. slapi_ch_free((void **)&work_q);
  1813. work_cnt++;
  1814. }
  1815. PR_DestroyStack(work_q_stack);
  1816. work_q_stack = NULL;
  1817. while ((stack_obj = (struct Slapi_op_stack *)PR_StackPop(op_stack))) {
  1818. operation_free(&stack_obj->op, NULL);
  1819. slapi_ch_free((void **)&stack_obj);
  1820. stack_cnt++;
  1821. }
  1822. PR_DestroyStack(op_stack);
  1823. op_stack = NULL;
  1824. LDAPDebug2Args( LDAP_DEBUG_ANY,
  1825. "slapd shutting down - freed %d work q stack objects - freed %d op stack objects\n",
  1826. work_cnt, stack_cnt);
  1827. }
  1828. static void
  1829. connection_add_operation(Connection* conn,Operation* op)
  1830. {
  1831. Operation **olist= &conn->c_ops;
  1832. int id= conn->c_opsinitiated++;
  1833. PRUint64 connid = conn->c_connid;
  1834. Operation **tmp;
  1835. /* slapi_ch_stop_recording(); */
  1836. for ( tmp = olist; *tmp != NULL; tmp = &(*tmp)->o_next )
  1837. ; /* NULL */
  1838. *tmp= op;
  1839. op->o_opid = id;
  1840. op->o_connid = connid;
  1841. /* Call the plugin extension constructors */
  1842. op->o_extension = factory_create_extension(get_operation_object_type(),op,conn);
  1843. }
  1844. /*
  1845. * Find an Operation on the Connection, and zap it in the butt.
  1846. * Call this function with conn->c_mutex locked.
  1847. */
  1848. void
  1849. connection_remove_operation( Connection *conn, Operation *op )
  1850. {
  1851. Operation **olist= &conn->c_ops;
  1852. Operation **tmp;
  1853. for ( tmp = olist; *tmp != NULL && *tmp != op; tmp = &(*tmp)->o_next )
  1854. ; /* NULL */
  1855. if ( *tmp == NULL )
  1856. {
  1857. LDAPDebug( LDAP_DEBUG_ANY, "connection_remove_operation: can't find op %d for conn %" NSPRIu64 "\n",
  1858. (int)op->o_msgid, conn->c_connid, 0 );
  1859. }
  1860. else
  1861. {
  1862. *tmp = (*tmp)->o_next;
  1863. }
  1864. }
  1865. void
  1866. connection_remove_operation_ext( Slapi_PBlock *pb, Connection *conn, Operation *op )
  1867. {
  1868. connection_remove_operation(conn, op);
  1869. connection_done_operation(conn, pb->op_stack_elem);
  1870. pb->pb_op = NULL;
  1871. slapi_pblock_init(pb);
  1872. }
  1873. /*
  1874. * Return a non-zero value if any operations are pending on conn.
  1875. * Operation op2ignore is ignored (okay to pass NULL). Typically, op2ignore
  1876. * is the caller's op (because the caller wants to check if all other
  1877. * ops are done).
  1878. * If test_resultsent is non-zero, operations that have already sent
  1879. * a result to the client are ignored.
  1880. * Call this function with conn->c_mutex locked.
  1881. */
  1882. int
  1883. connection_operations_pending( Connection *conn, Operation *op2ignore,
  1884. int test_resultsent )
  1885. {
  1886. Operation *op;
  1887. PR_ASSERT( conn != NULL );
  1888. for ( op = conn->c_ops; op != NULL; op = op->o_next ) {
  1889. if ( op == op2ignore ) {
  1890. continue;
  1891. }
  1892. if ( !test_resultsent || op->o_status != SLAPI_OP_STATUS_RESULT_SENT ) {
  1893. break;
  1894. }
  1895. }
  1896. return( op != NULL );
  1897. }
  1898. /* Copy the authorization identity from the connection struct into the
  1899. * operation struct. We do this late, because an operation might start
  1900. * before authentication is complete, at least on an SSL connection.
  1901. * We want each operation to get its authorization identity after the
  1902. * SSL software has had its chance to finish the SSL handshake;
  1903. * that is, after the first few bytes of the request are received.
  1904. * In particular, we want the first request from an LDAPS client
  1905. * to have an authorization identity derived from the initial SSL
  1906. * handshake. We also copy the SSF at this time.
  1907. */
  1908. static void
  1909. op_copy_identity(Connection *conn, Operation *op)
  1910. {
  1911. size_t dnlen;
  1912. size_t typelen;
  1913. PR_EnterMonitor(conn->c_mutex);
  1914. dnlen= conn->c_dn ? strlen (conn->c_dn) : 0;
  1915. typelen= conn->c_authtype ? strlen (conn->c_authtype) : 0;
  1916. slapi_sdn_done(&op->o_sdn);
  1917. slapi_ch_free_string(&(op->o_authtype));
  1918. if (dnlen <= 0 && typelen <= 0) {
  1919. op->o_authtype = NULL;
  1920. } else {
  1921. slapi_sdn_set_dn_byval(&op->o_sdn,conn->c_dn);
  1922. op->o_authtype = slapi_ch_strdup(conn->c_authtype);
  1923. /* set the thread data bind dn index */
  1924. slapi_td_set_dn(slapi_ch_strdup(conn->c_dn));
  1925. }
  1926. /* XXX We should also copy c_client_cert into *op here; it's
  1927. * part of the authorization identity. The operation's copy
  1928. * (not c_client_cert) should be used for access control.
  1929. */
  1930. /* copy isroot flag as well so root DN privileges are preserved */
  1931. op->o_isroot = conn->c_isroot;
  1932. /* copy the highest SSF (between local, SASL, and SSL/TLS)
  1933. * into the operation for use by access control. */
  1934. if ((conn->c_sasl_ssf >= conn->c_ssl_ssf) && (conn->c_sasl_ssf >= conn->c_local_ssf)) {
  1935. op->o_ssf = conn->c_sasl_ssf;
  1936. } else if ((conn->c_ssl_ssf >= conn->c_sasl_ssf) && (conn->c_ssl_ssf >= conn->c_local_ssf)){
  1937. op->o_ssf = conn->c_ssl_ssf;
  1938. } else {
  1939. op->o_ssf = conn->c_local_ssf;
  1940. }
  1941. PR_ExitMonitor(conn->c_mutex);
  1942. }
  1943. /* Sets the SSL SSF in the connection struct. */
  1944. static void
  1945. connection_set_ssl_ssf(Connection *conn)
  1946. {
  1947. PR_EnterMonitor(conn->c_mutex);
  1948. if (conn->c_flags & CONN_FLAG_SSL) {
  1949. SSL_SecurityStatus(conn->c_prfd, NULL, NULL, NULL, &(conn->c_ssl_ssf), NULL, NULL);
  1950. } else {
  1951. conn->c_ssl_ssf = 0;
  1952. }
  1953. PR_ExitMonitor(conn->c_mutex);
  1954. }
  1955. static int
  1956. is_ber_too_big(const Connection *conn, ber_len_t ber_len)
  1957. {
  1958. ber_len_t maxbersize = config_get_maxbersize();
  1959. if(ber_len > maxbersize)
  1960. {
  1961. log_ber_too_big_error(conn, ber_len, maxbersize);
  1962. return 1;
  1963. }
  1964. return 0;
  1965. }
  1966. /*
  1967. * Pass 0 for maxbersize if you do not have it handy. It is also OK to pass
  1968. * 0 for ber_len, in which case a slightly less informative message is
  1969. * logged.
  1970. */
  1971. static void
  1972. log_ber_too_big_error(const Connection *conn, ber_len_t ber_len,
  1973. ber_len_t maxbersize)
  1974. {
  1975. if (0 == maxbersize) {
  1976. maxbersize = config_get_maxbersize();
  1977. }
  1978. if (0 == ber_len) {
  1979. slapi_log_error( SLAPI_LOG_FATAL, "connection",
  1980. "conn=%" NSPRIu64 " fd=%d Incoming BER Element was too long, max allowable"
  1981. " is %" BERLEN_T " bytes. Change the nsslapd-maxbersize attribute in"
  1982. " cn=config to increase.\n",
  1983. conn->c_connid, conn->c_sd, maxbersize );
  1984. } else {
  1985. slapi_log_error( SLAPI_LOG_FATAL, "connection",
  1986. "conn=%" NSPRIu64 " fd=%d Incoming BER Element was %" BERLEN_T " bytes, max allowable"
  1987. " is %" BERLEN_T " bytes. Change the nsslapd-maxbersize attribute in"
  1988. " cn=config to increase.\n",
  1989. conn->c_connid, conn->c_sd, ber_len, maxbersize );
  1990. }
  1991. }
  1992. void
  1993. disconnect_server( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error )
  1994. {
  1995. PR_EnterMonitor(conn->c_mutex);
  1996. disconnect_server_nomutex( conn, opconnid, opid, reason, error );
  1997. PR_ExitMonitor(conn->c_mutex);
  1998. }
  1999. static ps_wakeup_all_fn_ptr ps_wakeup_all_fn = NULL;
  2000. /*
  2001. * disconnect_server - close a connection. takes the connection to close,
  2002. * the connid associated with the operation generating the close (so we
  2003. * don't accidentally close a connection that's not ours), and the opid
  2004. * of the operation generating the close (for logging purposes).
  2005. */
  2006. void
  2007. disconnect_server_nomutex_ext( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error, int schedule_closure_job )
  2008. {
  2009. if ( ( conn->c_sd != SLAPD_INVALID_SOCKET &&
  2010. conn->c_connid == opconnid ) && !(conn->c_flags & CONN_FLAG_CLOSING) )
  2011. {
  2012. LDAPDebug(LDAP_DEBUG_CONNS, "setting conn %" NSPRIu64 " fd=%d "
  2013. "to be disconnected: reason %d\n", conn->c_connid, conn->c_sd, reason);
  2014. /*
  2015. * PR_Close must be called before anything else is done because
  2016. * of NSPR problem on NT which requires that the socket on which
  2017. * I/O timed out is closed before any other I/O operation is
  2018. * attempted by the thread.
  2019. * WARNING : As of today the current code does not fulfill the
  2020. * requirements above.
  2021. */
  2022. /* Mark that the socket should be closed on this connection.
  2023. * We don't want to actually close the socket here, because
  2024. * the listener thread could be PR_Polling over it right now.
  2025. * The last thread to stop using the connection will do the closing.
  2026. */
  2027. conn->c_flags |= CONN_FLAG_CLOSING;
  2028. g_decrement_current_conn_count();
  2029. /*
  2030. * Print the error captured above.
  2031. */
  2032. if (error && (EPIPE != error) ) {
  2033. slapi_log_access( LDAP_DEBUG_STATS,
  2034. "conn=%" NSPRIu64 " op=%d fd=%d closed error %d (%s) - %s\n",
  2035. conn->c_connid, opid, conn->c_sd, error,
  2036. slapd_system_strerror(error),
  2037. slapd_pr_strerror(reason));
  2038. } else {
  2039. slapi_log_access( LDAP_DEBUG_STATS,
  2040. "conn=%" NSPRIu64 " op=%d fd=%d closed - %s\n",
  2041. conn->c_connid, opid, conn->c_sd,
  2042. slapd_pr_strerror(reason));
  2043. }
  2044. if (! config_check_referral_mode()) {
  2045. slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnections);
  2046. }
  2047. conn->c_gettingber = 0;
  2048. connection_abandon_operations( conn );
  2049. /* needed here to ensure simple paged results timeout properly and
  2050. * don't impact subsequent ops */
  2051. pagedresults_reset_timedout_nolock(conn);
  2052. if (! config_check_referral_mode()) {
  2053. /*
  2054. * If any of the outstanding operations on this
  2055. * connection were persistent searches, then
  2056. * ding all the persistent searches to get them
  2057. * to notice that their operations have been abandoned.
  2058. */
  2059. int found_ps = 0;
  2060. Operation *o;
  2061. for ( o = conn->c_ops; !found_ps && o != NULL; o = o->o_next ) {
  2062. if ( o->o_flags & OP_FLAG_PS ) {
  2063. found_ps = 1;
  2064. }
  2065. }
  2066. if ( found_ps ) {
  2067. if ( NULL == ps_wakeup_all_fn ) {
  2068. if ( get_entry_point( ENTRY_POINT_PS_WAKEUP_ALL,
  2069. (caddr_t *)(&ps_wakeup_all_fn )) == 0 )
  2070. {
  2071. (ps_wakeup_all_fn)();
  2072. }
  2073. } else {
  2074. (ps_wakeup_all_fn)();
  2075. }
  2076. }
  2077. }
  2078. if (schedule_closure_job) {
  2079. ns_connection_post_io_or_closing(conn); /* make sure event loop wakes up and closes this conn */
  2080. }
  2081. } else {
  2082. LDAPDebug2Args(LDAP_DEBUG_CONNS, "not setting conn %d to be disconnected: %s\n",
  2083. conn->c_sd,
  2084. (conn->c_sd == SLAPD_INVALID_SOCKET) ? "socket is invalid" :
  2085. ((conn->c_connid != opconnid) ? "conn id does not match op conn id" :
  2086. ((conn->c_flags & CONN_FLAG_CLOSING) ? "conn is closing" : "unknown")));
  2087. }
  2088. }
  2089. void
  2090. disconnect_server_nomutex( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error )
  2091. {
  2092. disconnect_server_nomutex_ext(conn, opconnid, opid, reason, error, 1);
  2093. }
  2094. void
  2095. connection_abandon_operations( Connection *c )
  2096. {
  2097. Operation *op;
  2098. for ( op = c->c_ops; op != NULL; op = op->o_next )
  2099. {
  2100. /* abandon the operation only if it is not yet
  2101. completed (i.e., no result has been sent yet to
  2102. the client */
  2103. /* sync repl uses the persist mode, and it cannot prevent
  2104. * setting o_status, but has to be abandonned
  2105. * handle it here until a better solution is found
  2106. */
  2107. if ( op->o_status != SLAPI_OP_STATUS_RESULT_SENT ||
  2108. (op->o_flags & OP_FLAG_PS) ) {
  2109. op->o_status = SLAPI_OP_STATUS_ABANDONED;
  2110. }
  2111. }
  2112. }
  2113. /* must be called within c->c_mutex */
  2114. void
  2115. connection_set_io_layer_cb( Connection *c, Conn_IO_Layer_cb push_cb, Conn_IO_Layer_cb pop_cb, void *cb_data )
  2116. {
  2117. c->c_push_io_layer_cb = push_cb;
  2118. c->c_pop_io_layer_cb = pop_cb;
  2119. c->c_io_layer_cb_data = cb_data;
  2120. }
  2121. /* must be called within c->c_mutex */
  2122. int
  2123. connection_call_io_layer_callbacks( Connection *c )
  2124. {
  2125. int rv = 0;
  2126. if (c->c_pop_io_layer_cb) {
  2127. rv = (c->c_pop_io_layer_cb)(c, c->c_io_layer_cb_data);
  2128. c->c_pop_io_layer_cb = NULL;
  2129. }
  2130. if (!rv && c->c_push_io_layer_cb) {
  2131. rv = (c->c_push_io_layer_cb)(c, c->c_io_layer_cb_data);
  2132. c->c_push_io_layer_cb = NULL;
  2133. }
  2134. c->c_io_layer_cb_data = NULL;
  2135. return rv;
  2136. }