abandon.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /* abandon.c */
  2. /* $OpenLDAP$ */
  3. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  4. *
  5. * Copyright 1998-2022 The OpenLDAP Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted only as authorized by the OpenLDAP
  10. * Public License.
  11. *
  12. * A copy of this license is available in the file LICENSE in the
  13. * top-level directory of the distribution or, alternatively, at
  14. * <http://www.OpenLDAP.org/license.html>.
  15. */
  16. /* Portions Copyright (c) 1990 Regents of the University of Michigan.
  17. * All rights reserved.
  18. */
  19. #include "portable.h"
  20. #include <stdio.h>
  21. #include <ac/stdlib.h>
  22. #include <ac/socket.h>
  23. #include <ac/string.h>
  24. #include <ac/time.h>
  25. #include "ldap-int.h"
  26. /*
  27. * An abandon request looks like this:
  28. * AbandonRequest ::= [APPLICATION 16] MessageID
  29. * and has no response. (Source: RFC 4511)
  30. */
  31. #include "lutil.h"
  32. static int
  33. do_abandon(
  34. LDAP *ld,
  35. ber_int_t origid,
  36. LDAPRequest *lr,
  37. LDAPControl **sctrls,
  38. int sendabandon );
  39. /*
  40. * ldap_abandon_ext - perform an ldap extended abandon operation.
  41. *
  42. * Parameters:
  43. * ld LDAP descriptor
  44. * msgid The message id of the operation to abandon
  45. * scntrls Server Controls
  46. * ccntrls Client Controls
  47. *
  48. * ldap_abandon_ext returns a LDAP error code.
  49. * (LDAP_SUCCESS if everything went ok)
  50. *
  51. * Example:
  52. * ldap_abandon_ext( ld, msgid, scntrls, ccntrls );
  53. */
  54. int
  55. ldap_abandon_ext(
  56. LDAP *ld,
  57. int msgid,
  58. LDAPControl **sctrls,
  59. LDAPControl **cctrls )
  60. {
  61. int rc;
  62. Debug1( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid );
  63. /* check client controls */
  64. LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
  65. rc = ldap_int_client_controls( ld, cctrls );
  66. if ( rc == LDAP_SUCCESS ) {
  67. rc = do_abandon( ld, msgid, NULL, sctrls, 1 );
  68. }
  69. LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
  70. return rc;
  71. }
  72. /*
  73. * ldap_abandon - perform an ldap abandon operation. Parameters:
  74. *
  75. * ld LDAP descriptor
  76. * msgid The message id of the operation to abandon
  77. *
  78. * ldap_abandon returns 0 if everything went ok, -1 otherwise.
  79. *
  80. * Example:
  81. * ldap_abandon( ld, msgid );
  82. */
  83. int
  84. ldap_abandon( LDAP *ld, int msgid )
  85. {
  86. Debug1( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid );
  87. return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
  88. ? 0 : -1;
  89. }
  90. int
  91. ldap_pvt_discard(
  92. LDAP *ld,
  93. ber_int_t msgid )
  94. {
  95. int rc;
  96. LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
  97. rc = do_abandon( ld, msgid, NULL, NULL, 0 );
  98. LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
  99. return rc;
  100. }
  101. static int
  102. do_abandon(
  103. LDAP *ld,
  104. ber_int_t origid,
  105. LDAPRequest *lr,
  106. LDAPControl **sctrls,
  107. int sendabandon )
  108. {
  109. BerElement *ber;
  110. int i, err;
  111. ber_int_t msgid = origid;
  112. Sockbuf *sb;
  113. LDAPRequest needle = {0};
  114. needle.lr_msgid = origid;
  115. if ( lr != NULL ) {
  116. msgid = lr->lr_msgid;
  117. Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
  118. origid, msgid );
  119. } else if ( (lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp )) != NULL ) {
  120. Debug2( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
  121. origid, msgid );
  122. if ( lr->lr_parent != NULL ) {
  123. /* don't let caller abandon child requests! */
  124. ld->ld_errno = LDAP_PARAM_ERROR;
  125. return( LDAP_PARAM_ERROR );
  126. }
  127. msgid = lr->lr_msgid;
  128. }
  129. if ( lr != NULL ) {
  130. LDAPRequest **childp = &lr->lr_child;
  131. needle.lr_msgid = lr->lr_msgid;
  132. if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
  133. /* no need to send abandon message */
  134. sendabandon = 0;
  135. }
  136. while ( *childp ) {
  137. /* Abandon children */
  138. LDAPRequest *child = *childp;
  139. (void)do_abandon( ld, lr->lr_origid, child, sctrls, sendabandon );
  140. if ( *childp == child ) {
  141. childp = &child->lr_refnext;
  142. }
  143. }
  144. }
  145. /* ldap_msgdelete locks the res_mutex. Give up the req_mutex
  146. * while we're in there.
  147. */
  148. LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
  149. err = ldap_msgdelete( ld, msgid );
  150. LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
  151. if ( err == 0 ) {
  152. ld->ld_errno = LDAP_SUCCESS;
  153. return LDAP_SUCCESS;
  154. }
  155. /* fetch again the request that we are abandoning */
  156. if ( lr != NULL ) {
  157. lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp );
  158. }
  159. err = 0;
  160. if ( sendabandon ) {
  161. if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
  162. /* not connected */
  163. err = -1;
  164. ld->ld_errno = LDAP_SERVER_DOWN;
  165. } else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
  166. /* BER element allocation failed */
  167. err = -1;
  168. ld->ld_errno = LDAP_NO_MEMORY;
  169. } else {
  170. /*
  171. * We already have the mutex in LDAP_R_COMPILE, so
  172. * don't try to get it again.
  173. * LDAP_NEXT_MSGID(ld, i);
  174. */
  175. LDAP_NEXT_MSGID(ld, i);
  176. #ifdef LDAP_CONNECTIONLESS
  177. if ( LDAP_IS_UDP(ld) ) {
  178. struct sockaddr_storage sa = {0};
  179. /* dummy, filled with ldo_peer in request.c */
  180. err = ber_write( ber, (char *) &sa, sizeof(sa), 0 );
  181. }
  182. if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
  183. LDAP_VERSION2 )
  184. {
  185. char *dn;
  186. LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
  187. dn = ld->ld_options.ldo_cldapdn;
  188. if (!dn) dn = "";
  189. err = ber_printf( ber, "{isti", /* '}' */
  190. i, dn,
  191. LDAP_REQ_ABANDON, msgid );
  192. LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
  193. } else
  194. #endif
  195. {
  196. /* create a message to send */
  197. err = ber_printf( ber, "{iti", /* '}' */
  198. i,
  199. LDAP_REQ_ABANDON, msgid );
  200. }
  201. if ( err == -1 ) {
  202. /* encoding error */
  203. ld->ld_errno = LDAP_ENCODING_ERROR;
  204. } else {
  205. /* Put Server Controls */
  206. if ( ldap_int_put_controls( ld, sctrls, ber )
  207. != LDAP_SUCCESS )
  208. {
  209. err = -1;
  210. } else {
  211. /* close '{' */
  212. err = ber_printf( ber, /*{*/ "N}" );
  213. if ( err == -1 ) {
  214. /* encoding error */
  215. ld->ld_errno = LDAP_ENCODING_ERROR;
  216. }
  217. }
  218. }
  219. if ( err == -1 ) {
  220. ber_free( ber, 1 );
  221. } else {
  222. /* send the message */
  223. if ( lr != NULL ) {
  224. assert( lr->lr_conn != NULL );
  225. sb = lr->lr_conn->lconn_sb;
  226. } else {
  227. sb = ld->ld_sb;
  228. }
  229. if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
  230. ld->ld_errno = LDAP_SERVER_DOWN;
  231. err = -1;
  232. } else {
  233. err = 0;
  234. }
  235. }
  236. }
  237. }
  238. if ( lr != NULL ) {
  239. LDAPConn *lc;
  240. int freeconn = 0;
  241. if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
  242. freeconn = 1;
  243. lc = lr->lr_conn;
  244. }
  245. if ( origid == msgid ) {
  246. ldap_free_request( ld, lr );
  247. } else {
  248. lr->lr_abandoned = 1;
  249. }
  250. if ( freeconn ) {
  251. /* release ld_req_mutex while grabbing ld_conn_mutex to
  252. * prevent deadlock.
  253. */
  254. LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
  255. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  256. ldap_free_connection( ld, lc, 0, 1 );
  257. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  258. LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
  259. }
  260. }
  261. LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
  262. /* use bisection */
  263. i = 0;
  264. if ( ld->ld_nabandoned == 0 ||
  265. ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 )
  266. {
  267. ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i );
  268. }
  269. if ( err != -1 ) {
  270. ld->ld_errno = LDAP_SUCCESS;
  271. }
  272. LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
  273. return( ld->ld_errno );
  274. }
  275. /*
  276. * ldap_int_bisect_find
  277. *
  278. * args:
  279. * v: array of length n (in)
  280. * n: length of array v (in)
  281. * id: value to look for (in)
  282. * idxp: pointer to location of value/insert point
  283. *
  284. * return:
  285. * 0: not found
  286. * 1: found
  287. * -1: error
  288. */
  289. int
  290. ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp )
  291. {
  292. int begin,
  293. end,
  294. rc = 0;
  295. assert( id >= 0 );
  296. begin = 0;
  297. end = n - 1;
  298. if ( n <= 0 || id < v[ begin ] ) {
  299. *idxp = 0;
  300. } else if ( id > v[ end ] ) {
  301. *idxp = n;
  302. } else {
  303. int pos;
  304. ber_int_t curid;
  305. do {
  306. pos = (begin + end)/2;
  307. curid = v[ pos ];
  308. if ( id < curid ) {
  309. end = pos - 1;
  310. } else if ( id > curid ) {
  311. begin = ++pos;
  312. } else {
  313. /* already abandoned? */
  314. rc = 1;
  315. break;
  316. }
  317. } while ( end >= begin );
  318. *idxp = pos;
  319. }
  320. return rc;
  321. }
  322. /*
  323. * ldap_int_bisect_insert
  324. *
  325. * args:
  326. * vp: pointer to array of length *np (in/out)
  327. * np: pointer to length of array *vp (in/out)
  328. * id: value to insert (in)
  329. * idx: location of insert point (as computed by ldap_int_bisect_find())
  330. *
  331. * return:
  332. * 0: inserted
  333. * -1: error
  334. */
  335. int
  336. ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx )
  337. {
  338. ber_int_t *v;
  339. ber_len_t n;
  340. int i;
  341. assert( vp != NULL );
  342. assert( np != NULL );
  343. assert( idx >= 0 );
  344. assert( (unsigned) idx <= *np );
  345. n = *np;
  346. v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) );
  347. if ( v == NULL ) {
  348. return -1;
  349. }
  350. *vp = v;
  351. for ( i = n; i > idx; i-- ) {
  352. v[ i ] = v[ i - 1 ];
  353. }
  354. v[ idx ] = id;
  355. ++(*np);
  356. return 0;
  357. }
  358. /*
  359. * ldap_int_bisect_delete
  360. *
  361. * args:
  362. * vp: pointer to array of length *np (in/out)
  363. * np: pointer to length of array *vp (in/out)
  364. * id: value to delete (in)
  365. * idx: location of value to delete (as computed by ldap_int_bisect_find())
  366. *
  367. * return:
  368. * 0: deleted
  369. */
  370. int
  371. ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx )
  372. {
  373. ber_int_t *v;
  374. ber_len_t i, n;
  375. assert( vp != NULL );
  376. assert( np != NULL );
  377. assert( idx >= 0 );
  378. assert( (unsigned) idx < *np );
  379. v = *vp;
  380. assert( v[ idx ] == id );
  381. --(*np);
  382. n = *np;
  383. for ( i = idx; i < n; i++ ) {
  384. v[ i ] = v[ i + 1 ];
  385. }
  386. return 0;
  387. }