scalab01.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. #ident "ldclt @(#)scalab01.c 1.8 01/05/03"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * This Program is free software; you can redistribute it and/or modify it under
  4. * the terms of the GNU General Public License as published by the Free Software
  5. * Foundation; version 2 of the License.
  6. *
  7. * This Program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with
  12. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  13. * Place, Suite 330, Boston, MA 02111-1307 USA.
  14. *
  15. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  16. * right to link the code of this Program with code not covered under the GNU
  17. * General Public License ("Non-GPL Code") and to distribute linked combinations
  18. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  19. * permitted under this exception must only link to the code of this Program
  20. * through those well defined interfaces identified in the file named EXCEPTION
  21. * found in the source code files (the "Approved Interfaces"). The files of
  22. * Non-GPL Code may instantiate templates or use macros or inline functions from
  23. * the Approved Interfaces without causing the resulting work to be covered by
  24. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  25. * additions to the list of Approved Interfaces. You must obey the GNU General
  26. * Public License in all respects for all of the Program code and other code used
  27. * in conjunction with the Program except the Non-GPL Code covered by this
  28. * exception. If you modify this file, you may extend this exception to your
  29. * version of the file, but you are not obligated to do so. If you do not wish to
  30. * provide this exception without modification, you must delete this exception
  31. * statement from your version and license this file solely under the GPL without
  32. * exception.
  33. *
  34. *
  35. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  36. * Copyright (C) 2006 Red Hat, Inc.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /*
  43. FILE : scalab01.c
  44. AUTHOR : Jean-Luc SCHWING
  45. VERSION : 1.0
  46. DATE : 08 January 2001
  47. DESCRIPTION :
  48. This file contains the implmentation of the specific
  49. scenario scalab01 of ldclt.
  50. I implement this set of functions in a separate file to
  51. reduce the interconnection(s) between the main ldclt
  52. and the add-ons, keeping in mind the possibility to use
  53. a dynamic load of plugins for a future release.
  54. LOCAL : None.
  55. HISTORY :
  56. ---------+--------------+------------------------------------------------------
  57. dd/mm/yy | Author | Comments
  58. ---------+--------------+------------------------------------------------------
  59. 08/01/01 | JL Schwing | Creation
  60. ---------+--------------+------------------------------------------------------
  61. 12/01/01 | JL Schwing | 1.2 : Second set of options for -e scalab01
  62. ---------+--------------+------------------------------------------------------
  63. 29/01/01 | B Kolics | 1.3 : readAttrValue() uses filter of requested attr
  64. ---------+--------------+------------------------------------------------------
  65. 01/02/01 | JL Schwing | 1.4 : Protect against multiple choice of same user.
  66. ---------+--------------+------------------------------------------------------
  67. 26/02/01 | JL Schwing | 1.5 : Port on non-solaris platforms...
  68. ---------+--------------+------------------------------------------------------
  69. 14/03/01 | JL Schwing | 1.6 : Lint cleanup.
  70. | Bug fix : forget to set ldap protocol version.
  71. ---------+--------------+------------------------------------------------------
  72. 26/04/01 | B Kolics | 1.7 : in case of lock failure, thread is not aborted
  73. ---------+--------------+------------------------------------------------------
  74. 03/05/01 | B Kolics | 1.8 : bug fix - forget to release more line.
  75. ---------+--------------+------------------------------------------------------
  76. */
  77. #include <stdio.h> /* printf(), etc... */
  78. #include <stdlib.h> /* malloc(), etc... */
  79. #include <string.h> /* strcpy(), etc... */
  80. #include <errno.h> /* perror(), etc... */
  81. #ifndef _WIN32
  82. #include <pthread.h> /* pthreads(), etc... */
  83. #endif
  84. #include <lber.h> /* ldap C-API BER declarations */
  85. #include <ldap.h> /* ldap C-API declarations */
  86. #if !defined(USE_OPENLDAP)
  87. #include <ldap_ssl.h> /* ldapssl_init(), etc... */
  88. #endif
  89. #include <prprf.h>
  90. #include "port.h" /* Portability definitions */
  91. #include "ldclt.h" /* This tool's include file */
  92. #include "utils.h" /* Utilities functions */
  93. #include "scalab01.h" /* Scalab01 specific definitions */
  94. /*
  95. * Private data structures.
  96. */
  97. scalab01_context s1ctx;
  98. /* ****************************************************************************
  99. FUNCTION : scalab01_init
  100. PURPOSE : Initiates the scalab01 scenario.
  101. INPUT : None.
  102. OUTPUT : None.
  103. RETURN : -1 if error, 0 else.
  104. DESCRIPTION :
  105. *****************************************************************************/
  106. int
  107. scalab01_init (void)
  108. {
  109. int ret; /* Return value */
  110. s1ctx.nbcnx = 0; /* No connection yet */
  111. s1ctx.list = NULL; /* No record yet */
  112. s1ctx.lockingMax = 0; /* No locking yet */
  113. /*
  114. * Initiates mutexes
  115. */
  116. if ((ret = ldclt_mutex_init (&(s1ctx.list_mutex))) != 0)
  117. {
  118. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  119. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.list_mutex\n", mctx.pid);
  120. fflush (stderr);
  121. return (-1);
  122. }
  123. if ((ret = ldclt_mutex_init (&(s1ctx.locking_mutex))) != 0)
  124. {
  125. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  126. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.locking_mutex\n", mctx.pid);
  127. fflush (stderr);
  128. return (-1);
  129. }
  130. if ((ret = ldclt_mutex_init (&(s1ctx.nbcnx_mutex))) != 0)
  131. {
  132. fprintf (stderr, "ldclt[%d]: %s\n", mctx.pid, strerror (ret));
  133. fprintf (stderr, "ldclt[%d]: Error: cannot initiate s1ctx.nbcnx_mutex\n", mctx.pid);
  134. fflush (stderr);
  135. return (-1);
  136. }
  137. /*
  138. * No error
  139. */
  140. return (0);
  141. }
  142. /* ****************************************************************************
  143. FUNCTION : scalab01Lock
  144. PURPOSE : Lock for single user trying to connect.
  145. INPUT : tttctx = thread context.
  146. OUTPUT : None.
  147. RETURN : -1 if error, 0 cannot lock, 1 if could lock.
  148. DESCRIPTION :
  149. *****************************************************************************/
  150. int
  151. scalab01Lock (
  152. thread_context *tttctx)
  153. {
  154. int i; /* For the loop */
  155. int ret; /* Return code */
  156. int res; /* Result of this function */
  157. /*
  158. * Get secure access to the common data structure.
  159. */
  160. if ((ret = ldclt_mutex_lock (&(s1ctx.locking_mutex))) != 0)
  161. {
  162. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  163. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  164. fflush (stderr);
  165. return (-1);
  166. }
  167. /*
  168. * Is it locked ?
  169. */
  170. res = 1;
  171. for (i=0 ; i<s1ctx.lockingMax ; i++)
  172. if ((s1ctx.locking[i] != NULL) &&
  173. (!strcmp (s1ctx.locking[i], tttctx->bufBindDN)))
  174. {
  175. res = 0;
  176. break;
  177. }
  178. if (res == 1)
  179. {
  180. for (i=0 ; (i<s1ctx.lockingMax) && (s1ctx.locking[i] != NULL) ; i++);
  181. if (i == s1ctx.lockingMax)
  182. {
  183. if (s1ctx.lockingMax == SCALAB01_MAX_LOCKING)
  184. res = 0;
  185. else
  186. s1ctx.lockingMax++;
  187. }
  188. if (res != 0)
  189. s1ctx.locking[i] = tttctx->bufBindDN;
  190. }
  191. /*
  192. * Free mutex
  193. */
  194. if ((ret = ldclt_mutex_unlock (&(s1ctx.locking_mutex))) != 0)
  195. {
  196. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  197. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  198. fflush (stderr);
  199. return (-1);
  200. }
  201. return (res);
  202. }
  203. /* ****************************************************************************
  204. FUNCTION : scalab01Unlock
  205. PURPOSE : Unlock for single user trying to connect.
  206. INPUT : tttctx = thread context.
  207. OUTPUT : None.
  208. RETURN : -1 if error, 0 else.
  209. DESCRIPTION :
  210. *****************************************************************************/
  211. int
  212. scalab01Unlock (
  213. thread_context *tttctx)
  214. {
  215. int i; /* For the loop */
  216. int ret; /* Return code */
  217. /*
  218. * Get secure access to the common data structure.
  219. */
  220. if ((ret = ldclt_mutex_lock (&(s1ctx.locking_mutex))) != 0)
  221. {
  222. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  223. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  224. fflush (stderr);
  225. return (-1);
  226. }
  227. /*
  228. * Find the entry and unlock it.
  229. */
  230. for (i=0 ; i<s1ctx.lockingMax ; i++)
  231. if ((s1ctx.locking[i] != NULL) &&
  232. (!strcmp (s1ctx.locking[i], tttctx->bufBindDN)))
  233. {
  234. s1ctx.locking[i] = NULL;
  235. break;
  236. }
  237. /*
  238. * Free mutex
  239. */
  240. if ((ret = ldclt_mutex_unlock (&(s1ctx.locking_mutex))) != 0)
  241. {
  242. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  243. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  244. fflush (stderr);
  245. return (-1);
  246. }
  247. return (0);
  248. }
  249. /* ****************************************************************************
  250. FUNCTION : scalab01_modemIncr
  251. PURPOSE : Increments the modem nb of cnx
  252. INPUT : ident = thread identifier
  253. OUTPUT : None.
  254. RETURN : -1 if error
  255. 0 if no modem available
  256. 1 if modem available
  257. DESCRIPTION :
  258. *****************************************************************************/
  259. int
  260. scalab01_modemIncr (
  261. char *ident)
  262. {
  263. int ret; /* Return value */
  264. int res; /* Result of this function */
  265. /*
  266. * Get secure access to the common data structure.
  267. */
  268. if ((ret = ldclt_mutex_lock (&(s1ctx.nbcnx_mutex))) != 0)
  269. {
  270. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  271. mctx.pid, ident, ret, strerror (ret));
  272. fflush (stderr);
  273. return (-1);
  274. }
  275. if (s1ctx.nbcnx >= s1ctx.maxcnxnb)
  276. res = 0;
  277. else
  278. {
  279. res = 1;
  280. s1ctx.nbcnx++;
  281. }
  282. /*
  283. * Free mutex
  284. */
  285. if ((ret = ldclt_mutex_unlock (&(s1ctx.nbcnx_mutex))) != 0)
  286. {
  287. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  288. mctx.pid, ident, ret, strerror (ret));
  289. fflush (stderr);
  290. return (-1);
  291. }
  292. return (res);
  293. }
  294. /* ****************************************************************************
  295. FUNCTION : scalab01_modemDecr
  296. PURPOSE : Decrements the modem nb of cnx
  297. INPUT : ident = thread identifier
  298. OUTPUT : None.
  299. RETURN : -1 if error, 0 else.
  300. DESCRIPTION :
  301. *****************************************************************************/
  302. int
  303. scalab01_modemDecr (
  304. char *ident)
  305. {
  306. int ret; /* Return value */
  307. /*
  308. * Get secure access to the common data structure.
  309. */
  310. if ((ret = ldclt_mutex_lock (&(s1ctx.nbcnx_mutex))) != 0)
  311. {
  312. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  313. mctx.pid, ident, ret, strerror (ret));
  314. fflush (stderr);
  315. return (-1);
  316. }
  317. s1ctx.nbcnx--;
  318. /*
  319. * Free mutex
  320. */
  321. if ((ret = ldclt_mutex_unlock (&(s1ctx.nbcnx_mutex))) != 0)
  322. {
  323. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  324. mctx.pid, ident, ret, strerror (ret));
  325. fflush (stderr);
  326. return (-1);
  327. }
  328. return (0);
  329. }
  330. /* ****************************************************************************
  331. FUNCTION : scalab01_addLogin
  332. PURPOSE : Add a new user login to the s1ctx structure.
  333. INPUT : tttctx = thread context.
  334. dn = user's dn.
  335. duration = duration of the connection.
  336. OUTPUT : None.
  337. RETURN : -1 if error, 0 else.
  338. DESCRIPTION :
  339. *****************************************************************************/
  340. int
  341. scalab01_addLogin (
  342. thread_context *tttctx,
  343. char *dn,
  344. int duration)
  345. {
  346. int ret; /* Return value */
  347. isp_user *new; /* New entry */
  348. isp_user *cur; /* Current entry */
  349. int rc = 0;
  350. /*
  351. * Create the new record.
  352. */
  353. new = (isp_user *) malloc (sizeof (isp_user));
  354. if (NULL == new) {
  355. fprintf (stderr, "ldclt[%d]: %s: cannot malloc(isp_user), error=%d (%s)\n",
  356. mctx.pid, tttctx->thrdId, errno, strerror (errno));
  357. fflush (stderr);
  358. return -1;
  359. }
  360. strncpy (new->dn, dn, sizeof(new->dn));
  361. new->dn[sizeof(new->dn)-1] = '\0';
  362. new->cost = new->counter = duration;
  363. new->next = NULL;
  364. /*
  365. * Get secure access to the common data structure.
  366. * Note : it should be possible to reduce the "size" of this critical
  367. * section but I am not 100% certain this won't mess up all things.
  368. */
  369. if ((ret = ldclt_mutex_lock (&(s1ctx.list_mutex))) != 0)
  370. {
  371. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(), error=%d (%s)\n",
  372. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  373. fflush (stderr);
  374. rc = -1;
  375. goto error;
  376. }
  377. /*
  378. * Maybe this is the first entry of the list ?
  379. */
  380. if (s1ctx.list == NULL)
  381. s1ctx.list = new;
  382. else
  383. {
  384. /*
  385. * Check with the list's head
  386. */
  387. if (s1ctx.list->counter >= duration)
  388. {
  389. new->next = s1ctx.list;
  390. s1ctx.list = new;
  391. }
  392. else
  393. {
  394. cur = s1ctx.list;
  395. /* If cur is NULL, we should just bail and free new. */
  396. if (cur == NULL)
  397. {
  398. goto error;
  399. }
  400. while (cur != NULL)
  401. {
  402. if (cur->next == NULL)
  403. {
  404. cur->next = new;
  405. cur = NULL; /* Exit loop */
  406. }
  407. else if (cur->next->counter >= duration)
  408. {
  409. new->next = cur->next;
  410. cur->next = new;
  411. cur = NULL; /* Exit loop */
  412. }
  413. else
  414. {
  415. cur = cur->next;
  416. }
  417. }
  418. }
  419. }
  420. goto done;
  421. error:
  422. if (new) free(new);
  423. done:
  424. /*
  425. * Free mutex
  426. */
  427. if ((ret = ldclt_mutex_unlock (&(s1ctx.list_mutex))) != 0)
  428. {
  429. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_unlock(), error=%d (%s)\n",
  430. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  431. fflush (stderr);
  432. rc = -1;
  433. }
  434. return rc;
  435. }
  436. /* ****************************************************************************
  437. FUNCTION : scalab01_connectSuperuser
  438. PURPOSE : Purpose of the fct
  439. INPUT : None.
  440. OUTPUT : None.
  441. RETURN : -1 if error, 0 else.
  442. DESCRIPTION :
  443. *****************************************************************************/
  444. int
  445. scalab01_connectSuperuser (void)
  446. {
  447. char bindDN [MAX_DN_LENGTH] = {0}; /* To bind */
  448. unsigned int mode = mctx.mode;
  449. unsigned int mod2 = mctx.mod2;
  450. if (!(mode & CLTAUTH)) {
  451. snprintf (bindDN, sizeof(bindDN), "%s,%s", SCALAB01_SUPER_USER_RDN, mctx.baseDN);
  452. bindDN[sizeof(bindDN)-1] = '\0';
  453. }
  454. /* clear bits not applicable to this mode */
  455. mod2 &= ~M2_RNDBINDFILE;
  456. mod2 &= ~M2_SASLAUTH;
  457. mod2 &= ~M2_RANDOM_SASLAUTHID;
  458. /* force bind to happen */
  459. mode |= BIND_EACH_OPER;
  460. s1ctx.ldapCtx = connectToLDAP(NULL, bindDN, SCALAB01_SUPER_USER_PASSWORD, mode, mod2);
  461. if (!s1ctx.ldapCtx) {
  462. return (-1);
  463. }
  464. /*
  465. * Normal end...
  466. */
  467. return (0);
  468. }
  469. /* ****************************************************************************
  470. FUNCTION : readAttrValue
  471. PURPOSE : This function will ldap_search the given entry for the
  472. value of the given attribute.
  473. INPUT : ident = thread identifier
  474. ldapCtx = LDAP context
  475. dn = dn of the entry to process
  476. attname = attribute name
  477. OUTPUT : value = attribute value. This buffer must be
  478. initiated with enough memory.
  479. value[0] == '\0' if not find.
  480. RETURN : -1 if error, 0 else.
  481. DESCRIPTION :
  482. *****************************************************************************/
  483. int
  484. readAttrValue (
  485. LDAP *ldapCtx,
  486. char *ident,
  487. char *dn,
  488. char *attname,
  489. char *value)
  490. {
  491. int ret; /* Return value */
  492. char *attrs[2]; /* Attribute to retrieve */
  493. LDAPMessage *res; /* LDAP responses */
  494. LDAPMessage *cur; /* Current message */
  495. BerElement *ber; /* To decode the response */
  496. char *aname; /* Current attribute name */
  497. char *filter; /* Filter used for searching */
  498. /*
  499. * First, ldap_search() the entry.
  500. */
  501. attrs[0] = attname;
  502. attrs[1] = NULL;
  503. filter = (char *)malloc((4+strlen(attname))*sizeof(char));
  504. if (NULL == filter)
  505. {
  506. printf ("ldclt[%d]: %s: Out of memory\n", mctx.pid, ident);
  507. fflush (stdout);
  508. return (-1);
  509. }
  510. sprintf(filter, "(%s=*)", attname);
  511. ret = ldap_search_ext_s (ldapCtx, dn, LDAP_SCOPE_BASE,
  512. filter, attrs, 0, NULL, NULL, NULL, -1, &res);
  513. free(filter);
  514. if (ret != LDAP_SUCCESS)
  515. {
  516. printf ("ldclt[%d]: %s: Cannot ldap_search (%s in %s), error=%d (%s)\n",
  517. mctx.pid, ident, attname, dn, ret, my_ldap_err2string (ret));
  518. fflush (stdout);
  519. return (-1);
  520. }
  521. /*
  522. * Decode the response
  523. */
  524. value[0] = '\0'; /* Not find yet */
  525. cur = ldap_first_entry (ldapCtx, res);
  526. while ((!value[0]) && (cur != NULL))
  527. {
  528. aname = ldap_first_attribute (ldapCtx, cur, &ber);
  529. while ((!value[0]) && (aname != NULL))
  530. {
  531. /*
  532. * We expect this attribute to be single-valued.
  533. */
  534. if (!strcmp (aname, attname))
  535. {
  536. struct berval **vals;
  537. vals = ldap_get_values_len (ldapCtx, cur, aname);
  538. if (vals == NULL)
  539. {
  540. printf ("ldclt[%d]: %s: no value for %s in %s\n",
  541. mctx.pid, ident, dn, attname);
  542. fflush (stdout);
  543. return (-1);
  544. }
  545. strncpy (value, vals[0]->bv_val, vals[0]->bv_len);
  546. value[vals[0]->bv_len] = '\0';
  547. ldap_value_free_len (vals);
  548. }
  549. /*
  550. * Next attribute
  551. */
  552. ldap_memfree (aname);
  553. if (!value[0])
  554. aname = ldap_next_attribute (ldapCtx, cur, ber);
  555. }
  556. /*
  557. * Next entry - shouldn't happen in theory
  558. */
  559. if (ber != NULL)
  560. ber_free (ber, 0);
  561. cur = ldap_next_entry (ldapCtx, cur);
  562. }
  563. ldap_msgfree (res); /* Free the response */
  564. return (0);
  565. }
  566. /* ****************************************************************************
  567. FUNCTION : writeAttrValue
  568. PURPOSE : This function will ldap_modify the given entry to
  569. replace the value of the given attribute.
  570. INPUT : ident = thread identifier
  571. ldapCtx = LDAP context
  572. dn = dn of the entry to process
  573. attname = attribute name
  574. value = attribute value
  575. OUTPUT : None.
  576. RETURN : -1 if error, 0 else.
  577. DESCRIPTION :
  578. *****************************************************************************/
  579. int
  580. writeAttrValue (
  581. LDAP *ldapCtx,
  582. char *ident,
  583. char *dn,
  584. char *attname,
  585. char *value)
  586. {
  587. int ret; /* Return value */
  588. LDAPMod attribute; /* To build the attributes */
  589. LDAPMod *attrsmod[2]; /* Modify attributes */
  590. char *pvalues[2]; /* To build the values list */
  591. /*
  592. * Prepear the data to be written
  593. */
  594. pvalues[0] = value;
  595. pvalues[1] = NULL;
  596. attribute.mod_op = LDAP_MOD_REPLACE;
  597. attribute.mod_type = attname;
  598. attribute.mod_values = pvalues;
  599. attrsmod[0] = &attribute;
  600. attrsmod[1] = NULL;
  601. /*
  602. * Store the data in the directory.
  603. */
  604. ret = ldap_modify_ext_s (ldapCtx, dn, attrsmod, NULL, NULL);
  605. if (ret != LDAP_SUCCESS)
  606. {
  607. printf ("ldclt[%d]: %s: Cannot ldap_modify_ext_s (%s in %s), error=%d (%s)\n",
  608. mctx.pid, ident, attname, dn, ret, my_ldap_err2string (ret));
  609. fflush (stdout);
  610. return (-1);
  611. }
  612. return (0);
  613. }
  614. /* ****************************************************************************
  615. FUNCTION : scalab01_unlock
  616. PURPOSE : Unlock the user given in argument.
  617. INPUT : entry = entry to unlock.
  618. OUTPUT : None.
  619. RETURN : -1 if error, 0 else.
  620. DESCRIPTION :
  621. *****************************************************************************/
  622. int
  623. scalab01_unlock (
  624. isp_user *user)
  625. {
  626. int account; /* Accounting value */
  627. char buf[20]; /* To read/write attribute */
  628. /*
  629. * Increment accounting counters
  630. * First, read the current value.
  631. */
  632. if (readAttrValue (s1ctx.ldapCtx,"ctrl",user->dn,SCALAB01_ACC_ATTRIB,buf) < 0)
  633. {
  634. printf ("ldclt[%d]: ctrl: Cannot read accounting attribute of %s\n",
  635. mctx.pid, user->dn);
  636. fflush (stdout);
  637. return (-1);
  638. }
  639. /*
  640. * If this attribute has no value (doesn't exist) we assume it is 0.
  641. */
  642. if (buf[0] != '\0')
  643. account = atoi (buf);
  644. else
  645. {
  646. printf ("ldclt[%d]: ctrl: No accounting attribute for %s - assume it is 0\n",
  647. mctx.pid, user->dn);
  648. fflush (stdout);
  649. account = 0;
  650. }
  651. /*
  652. * Compute the new value and store it in the directory.
  653. */
  654. sprintf (buf, "%d", account + user->cost);
  655. if (writeAttrValue (s1ctx.ldapCtx,"ctrl",user->dn,SCALAB01_ACC_ATTRIB,buf) <0)
  656. {
  657. printf ("ldclt[%d]: ctrl: Cannot write accounting attribute of %s\n",
  658. mctx.pid, user->dn);
  659. fflush (stdout);
  660. return (-1);
  661. }
  662. /*
  663. * Unlock the user
  664. */
  665. if (writeAttrValue (s1ctx.ldapCtx, "ctrl", user->dn,
  666. SCALAB01_LOCK_ATTRIB, SCALAB01_VAL_UNLOCKED) < 0)
  667. {
  668. printf ("ldclt[%d]: ctrl: Cannot write lock (unlock) attribute of %s\n",
  669. mctx.pid, user->dn);
  670. fflush (stdout);
  671. return (-1);
  672. }
  673. if (mctx.mode & VERY_VERBOSE)
  674. printf ("ldclt[%d]: ctrl: entry %s unlocked\n",
  675. mctx.pid, user->dn);
  676. /*
  677. * Decrement modem pool usage...
  678. */
  679. if (scalab01_modemDecr ("ctrl") < 0)
  680. return (-1);
  681. /*
  682. * Normal end
  683. */
  684. return (0);
  685. }
  686. /* ****************************************************************************
  687. FUNCTION : scalab01_control
  688. PURPOSE : This function implements the control loop/thread of
  689. the scalab01 scenario. Its main target is to manage
  690. the counters of each "connection" and to unlock the
  691. entry when time is reached.
  692. INPUT : None.
  693. OUTPUT : None.
  694. RETURN : -1 if error, 0 else.
  695. DESCRIPTION :
  696. *****************************************************************************/
  697. void *
  698. scalab01_control (
  699. void *arg)
  700. {
  701. isp_user *cur; /* Current entry */
  702. isp_user *head; /* Head of entries to process */
  703. int ret; /* Return value */
  704. int nbTot; /* Total nb entries locked */
  705. int nbU; /* Number unlocked */
  706. /*
  707. * Initialization
  708. * Failure to connect is a critical error...
  709. */
  710. if (scalab01_connectSuperuser () < 0)
  711. ldcltExit (EXIT_NOBIND);
  712. /*
  713. * Main loop
  714. */
  715. while (1 /*CONSTCOND*/) /*JLS 14-03-01*/
  716. {
  717. ldclt_sleep (1); /* Poll the connections every second */
  718. nbTot = nbU = 0; /* No entries processed yet */
  719. /*
  720. * Get protected access to the entries
  721. */
  722. if ((ret = ldclt_mutex_lock (&(s1ctx.list_mutex))) != 0)
  723. {
  724. fprintf (stderr, "ldclt[%d]: ctrl: cannot mutex_lock(), error=%d (%s)\n",
  725. mctx.pid, ret, strerror (ret));
  726. fflush (stderr);
  727. ldcltExit (EXIT_OTHER);
  728. }
  729. /*
  730. * Decrement all counters
  731. */
  732. for (cur=s1ctx.list ; cur!=NULL ; cur=cur->next)
  733. {
  734. cur->counter--;
  735. nbTot++;
  736. }
  737. /*
  738. * Find the entries to process.
  739. */
  740. if ((s1ctx.list == NULL) || (s1ctx.list->counter > 0))
  741. head = NULL;
  742. else
  743. {
  744. head = cur = s1ctx.list;
  745. while ((cur != NULL) && (cur->counter == 0))
  746. cur = cur->next;
  747. s1ctx.list = cur;
  748. }
  749. /*
  750. * Release mutex
  751. */
  752. if ((ret = ldclt_mutex_unlock (&(s1ctx.list_mutex))) != 0)
  753. {
  754. fprintf (stderr, "ldclt[%d]: ctrl: cannot mutex_unlock(), error=%d (%s)\n",
  755. mctx.pid, ret, strerror (ret));
  756. fflush (stderr);
  757. ldcltExit (EXIT_OTHER);
  758. }
  759. /*
  760. * Now, we have "head" that points either to NULL or to a list of
  761. * entries to process.
  762. * Attention, this list of entries is not terminated by NULL, but
  763. * we must rather check the field head->next->counter" for the last
  764. * entry...
  765. *
  766. * NOTE : implements this section as a separate thread to keep the
  767. * general timer working...
  768. */
  769. while (head != NULL)
  770. {
  771. if (scalab01_unlock (head) < 0)
  772. {
  773. printf ("ldclt[%d]: ctrl: cannot unlock %s\n", mctx.pid, head->dn);
  774. ldcltExit (EXIT_OTHER);
  775. }
  776. nbU++; /* One more entry unlocked */
  777. /*
  778. * Next entry...
  779. */
  780. cur = head;
  781. if (head->next == NULL)
  782. head = NULL;
  783. else
  784. if (head->next->counter != 0)
  785. head = NULL;
  786. else
  787. head = head->next;
  788. free (cur);
  789. } /* while (head =! NULL) */
  790. /*
  791. * Print some stats...
  792. */
  793. if (mctx.mode & VERBOSE)
  794. printf ("ldclt[%d]: ctrl: nb entries unlocked / total : %3d / %5d\n",
  795. mctx.pid, nbU, nbTot);
  796. } /* Main loop */
  797. /*
  798. * End of thread
  799. */
  800. }
  801. /* ****************************************************************************
  802. FUNCTION : doScalab01
  803. PURPOSE : Implements the client part of the scalab01 scenario.
  804. INPUT : tttctx = this thread context
  805. OUTPUT : None.
  806. RETURN : -1 if error, 0 else.
  807. DESCRIPTION :
  808. *****************************************************************************/
  809. int
  810. doScalab01 (
  811. thread_context *tttctx)
  812. {
  813. char buf[32]; /* To read attributes value */
  814. int duration; /* Use a variable for trace purpose */
  815. int res; /* Result of cnx to modem pool */
  816. int doloop; /* To know if we should loop */
  817. /*
  818. * Simulate connection to the modem pool.
  819. */
  820. while ((res = scalab01_modemIncr(tttctx->thrdId)) != 1)
  821. switch (res)
  822. {
  823. case 0:
  824. ldclt_sleep (s1ctx.wait==0?SCALAB01_DEF_WAIT_TIME:rndlim(0,s1ctx.wait));
  825. break;
  826. case -1:
  827. return (-1);
  828. break;
  829. }
  830. /*
  831. * Connection to the server
  832. * The function connectToServer() will take care of the various connection/
  833. * disconnection, bind/unbind/close etc... requested by the user.
  834. * The cost is one more function call in this application, but the
  835. * resulting source code will be much more easiest to maintain.
  836. */
  837. if (connectToServer (tttctx) < 0)
  838. return (-1);
  839. if (!(tttctx->binded))
  840. return (0);
  841. /*
  842. * Check that no other thread is using the same identity...
  843. */
  844. doloop = 1;
  845. while (doloop)
  846. {
  847. switch (scalab01Lock (tttctx))
  848. {
  849. case 0:
  850. ldclt_sleep (1);
  851. break;
  852. case 1:
  853. doloop = 0;
  854. break;
  855. case -1:
  856. return (-1);
  857. break;
  858. }
  859. }
  860. /*
  861. * Ok, we are now binded. Great ;-)
  862. * The DN we used to bind is available in tttctx->bufBindDN
  863. * Read lock attribute
  864. */
  865. if (readAttrValue (tttctx->ldapCtx, tttctx->thrdId, tttctx->bufBindDN,
  866. SCALAB01_LOCK_ATTRIB, buf) < 0)
  867. {
  868. printf ("ldclt[%d]: %s: Cannot read lock attribute of %s\n",
  869. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  870. fflush (stdout);
  871. (void) scalab01_modemDecr (tttctx->thrdId);
  872. return (-1);
  873. }
  874. if (mctx.mode & VERY_VERBOSE)
  875. printf ("ldclt[%d]: %s: entry %s lock read\n",
  876. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  877. /*
  878. * If locked, then we cannot login now...
  879. */
  880. if (!strcmp (buf, SCALAB01_VAL_LOCKED))
  881. {
  882. if (scalab01_modemDecr (tttctx->thrdId) < 0)
  883. return (-1);
  884. return (0);
  885. }
  886. /*
  887. * If not locked :
  888. * - lock the user
  889. * - decide how many times will be connected
  890. * - add information to the list of connected
  891. */
  892. if (writeAttrValue (tttctx->ldapCtx, tttctx->thrdId, tttctx->bufBindDN,
  893. SCALAB01_LOCK_ATTRIB, SCALAB01_VAL_LOCKED) < 0)
  894. {
  895. printf ("ldclt[%d]: %s: Cannot write lock attribute of %s\n",
  896. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  897. fflush (stdout);
  898. /*
  899. * It can still happen that two threads write this attribute at the same
  900. * time, so there can be failure in one of the threads
  901. * in this case just return
  902. */
  903. if (scalab01_modemDecr (tttctx->thrdId) < 0) /*JLS 03-05-01*/
  904. return (-1); /*JLS 03-05-01*/
  905. return (0); /*BK 26-04-01*/
  906. }
  907. if (mctx.mode & VERY_VERBOSE)
  908. printf ("ldclt[%d]: %s: entry %s lock written\n",
  909. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  910. if (scalab01Unlock (tttctx) < 0)
  911. return (-1);
  912. duration = rndlim (1, s1ctx.cnxduration);
  913. if (scalab01_addLogin (tttctx, tttctx->bufBindDN, duration) < 0)
  914. {
  915. printf ("ldclt[%d]: %s: Cannot memorize new login of %s\n",
  916. mctx.pid, tttctx->thrdId, tttctx->bufBindDN);
  917. fflush (stdout);
  918. return (-1);
  919. }
  920. if (mctx.mode & VERY_VERBOSE)
  921. printf ("ldclt[%d]: %s: entry %s login added duration %6d\n",
  922. mctx.pid, tttctx->thrdId, tttctx->bufBindDN, duration);
  923. /*
  924. * Memorize the operation
  925. */
  926. if (incrementNbOpers (tttctx) < 0)
  927. return (-1);
  928. /*
  929. * Wait before next operation...
  930. */
  931. if (s1ctx.wait > 0)
  932. ldclt_sleep (rndlim (0,s1ctx.wait));
  933. /*
  934. * Unbind
  935. */
  936. /*
  937. TBC - this is done in the next loop... - cf connectToServer()
  938. */
  939. return (0);
  940. }
  941. /* End of file */