snmp_collator.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #ifndef _WIN32
  43. #include <sys/ipc.h>
  44. #include <sys/msg.h>
  45. #include <dirent.h>
  46. #endif
  47. #include <time.h>
  48. #include <signal.h>
  49. #include <string.h>
  50. #include <errno.h>
  51. #include "agtmmap.h"
  52. #include "slap.h"
  53. #include "prthread.h"
  54. #include "prlock.h"
  55. #include "prerror.h"
  56. #include "prcvar.h"
  57. #include "snmp_collator.h"
  58. #include "../snmp/ntagt/nslagtcom_nt.h"
  59. /* stevross: safe to assume port should be at most 5 digits ? */
  60. #define PORT_LEN 5
  61. /* strlen of url portions ie "ldap://:/" */
  62. #define URL_CHARS_LEN 9
  63. char *make_ds_url(char *host, int port);
  64. void print_snmp_interaction_table();
  65. int search_interaction_table(char *dsURL, int *isnew);
  66. static void loadConfigStats();
  67. static Slapi_Entry *getConfigEntry( Slapi_Entry **e );
  68. static void freeConfigEntry( Slapi_Entry **e );
  69. /* snmp stats stuff */
  70. struct agt_stats_t *stats=NULL;
  71. /* mmap stuff */
  72. static int hdl;
  73. /* collator stuff */
  74. static char *tmpstatsfile = AGT_STATS_FILE;
  75. #ifdef _WIN32
  76. static TCHAR szStatsFile[_MAX_PATH];
  77. static TCHAR szTempDir[_MAX_PATH];
  78. static HANDLE hParentProcess = NULL;
  79. static HANDLE hStatSlot = NULL;
  80. static HANDLE hLogFile = INVALID_HANDLE_VALUE;
  81. static TCHAR szSpoolRootDir[_MAX_PATH];
  82. #else
  83. static char szStatsFile[_MAX_PATH];
  84. #endif /* _WIN32*/
  85. static Slapi_Eq_Context snmp_eq_ctx;
  86. static int snmp_collator_stopped = 0;
  87. /* lock stuff */
  88. static PRLock *interaction_table_mutex;
  89. /***********************************************************************************
  90. *
  91. * int snmp_collator_init()
  92. *
  93. * initializes the global variables used by snmp
  94. *
  95. ************************************************************************************/
  96. int snmp_collator_init(){
  97. int i;
  98. /*
  99. * Initialize the mmap structure
  100. */
  101. memset((void *) stats, 0, sizeof(*stats));
  102. strncpy(stats->hdr_stats.dsVersion, SLAPD_VERSION_STR,
  103. (sizeof(stats->hdr_stats.dsVersion)/sizeof(char)) - 1);
  104. stats->hdr_stats.restarted = 0;
  105. stats->hdr_stats.startTime = time(0); /* This is a bit off, hope it's ok */
  106. /* load config stats */
  107. loadConfigStats();
  108. /* point these at the mmaped data */
  109. g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds = &(stats->ops_stats.dsAnonymousBinds);
  110. g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds = &(stats->ops_stats.dsUnAuthBinds);
  111. g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds = &(stats->ops_stats.dsSimpleAuthBinds);
  112. g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds = &(stats->ops_stats.dsStrongAuthBinds);
  113. g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors = &(stats->ops_stats.dsBindSecurityErrors);
  114. g_get_global_snmp_vars()->ops_tbl.dsInOps = &(stats->ops_stats.dsInOps);
  115. g_get_global_snmp_vars()->ops_tbl.dsReadOps = &(stats->ops_stats.dsReadOps);
  116. g_get_global_snmp_vars()->ops_tbl.dsCompareOps = &(stats->ops_stats.dsCompareOps);
  117. g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps = &(stats->ops_stats.dsAddEntryOps);
  118. g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps = &(stats->ops_stats.dsRemoveEntryOps);
  119. g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps = &(stats->ops_stats.dsModifyEntryOps);
  120. g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps = &(stats->ops_stats.dsModifyRDNOps);
  121. g_get_global_snmp_vars()->ops_tbl.dsListOps = &(stats->ops_stats.dsListOps);
  122. g_get_global_snmp_vars()->ops_tbl.dsSearchOps = &(stats->ops_stats.dsSearchOps);
  123. g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps = &(stats->ops_stats.dsOneLevelSearchOps);
  124. g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps = &(stats->ops_stats.dsWholeSubtreeSearchOps);
  125. g_get_global_snmp_vars()->ops_tbl.dsReferrals = &(stats->ops_stats.dsReferrals);
  126. g_get_global_snmp_vars()->ops_tbl.dsChainings = &(stats->ops_stats.dsChainings);
  127. g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors = &(stats->ops_stats.dsSecurityErrors);
  128. g_get_global_snmp_vars()->ops_tbl.dsErrors = &(stats->ops_stats.dsErrors);
  129. g_get_global_snmp_vars()->ops_tbl.dsConnections = &(stats->ops_stats.dsConnections);
  130. g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq = &(stats->ops_stats.dsConnectionSeq);
  131. g_get_global_snmp_vars()->ops_tbl.dsBytesRecv = &(stats->ops_stats.dsBytesRecv);
  132. g_get_global_snmp_vars()->ops_tbl.dsBytesSent = &(stats->ops_stats.dsBytesSent);
  133. g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned = &(stats->ops_stats.dsEntriesReturned);
  134. g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned = &(stats->ops_stats.dsReferralsReturned);
  135. /* entries table */
  136. g_get_global_snmp_vars()->entries_tbl.dsMasterEntries = &(stats->entries_stats.dsMasterEntries);
  137. g_get_global_snmp_vars()->entries_tbl.dsCopyEntries = &(stats->entries_stats.dsCopyEntries);
  138. g_get_global_snmp_vars()->entries_tbl.dsCacheEntries = &(stats->entries_stats.dsCacheEntries);
  139. g_get_global_snmp_vars()->entries_tbl.dsCacheHits = &(stats->entries_stats.dsCacheHits);
  140. g_get_global_snmp_vars()->entries_tbl.dsSlaveHits = &(stats->entries_stats.dsSlaveHits);
  141. /* interaction table */
  142. /* set pointers to table */
  143. for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
  144. {
  145. stats->int_stats[i].dsIntIndex=i;
  146. g_get_global_snmp_vars()->int_tbl[i].dsIntIndex = &(stats->int_stats[i].dsIntIndex);
  147. g_get_global_snmp_vars()->int_tbl[i].dsName = stats->int_stats[i].dsName;
  148. g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation = &(stats->int_stats[i].dsTimeOfCreation);
  149. g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt = &(stats->int_stats[i].dsTimeOfLastAttempt);
  150. g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess = &(stats->int_stats[i].dsTimeOfLastSuccess);
  151. g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess
  152. = &(stats->int_stats[i].dsFailuresSinceLastSuccess);
  153. g_get_global_snmp_vars()->int_tbl[i].dsFailures = &(stats->int_stats[i].dsFailures);
  154. g_get_global_snmp_vars()->int_tbl[i].dsSuccesses = &(stats->int_stats[i].dsSuccesses);
  155. g_get_global_snmp_vars()->int_tbl[i].dsURL = stats->int_stats[i].dsURL;
  156. }
  157. /* initialize table contents */
  158. for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
  159. {
  160. *(g_get_global_snmp_vars()->int_tbl[i].dsIntIndex) = i + 1;
  161. strcpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available");
  162. *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation) = 0;
  163. *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt) = 0;
  164. *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess) = 0;
  165. *(g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess) = 0;
  166. *(g_get_global_snmp_vars()->int_tbl[i].dsFailures) = 0;
  167. *(g_get_global_snmp_vars()->int_tbl[i].dsSuccesses) = 0;
  168. strcpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available");
  169. }
  170. /* create lock for interaction table */
  171. interaction_table_mutex = PR_NewLock();
  172. return 0;
  173. }
  174. /***********************************************************************************
  175. * given the name, wether or not it was successfull and the URL updates snmp
  176. * interaction table appropriately
  177. *
  178. *
  179. ************************************************************************************/
  180. void set_snmp_interaction_row(char *host, int port, int error)
  181. {
  182. int index;
  183. int isnew;
  184. char *dsName;
  185. char *dsURL;
  186. /* stevross: our servers don't have a concept of dsName as a distinguished name
  187. as specified in the MIB. Make this "Not Available" for now waiting for
  188. sometime in the future when we do
  189. */
  190. dsName = "Not Available";
  191. dsURL= make_ds_url(host, port);
  192. /* lock around here to avoid race condition of two threads trying to update table at same time */
  193. PR_Lock(interaction_table_mutex);
  194. index = search_interaction_table(dsURL, &isnew);
  195. if(isnew){
  196. /* fillin the new row from scratch*/
  197. *(g_get_global_snmp_vars()->int_tbl[index].dsIntIndex) = index;
  198. strcpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName);
  199. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation) = time(0);
  200. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt) = time(0);
  201. if(error == 0){
  202. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess) = time(0);
  203. *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess) = 0;
  204. *(g_get_global_snmp_vars()->int_tbl[index].dsFailures) = 0;
  205. *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses) = 1;
  206. }else{
  207. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess) = 0;
  208. *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess) = 1;
  209. *(g_get_global_snmp_vars()->int_tbl[index].dsFailures) = 1;
  210. *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses) = 0;
  211. }
  212. strcpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL);
  213. }else{
  214. /* just update the appropriate fields */
  215. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt) = time(0);
  216. if(error == 0){
  217. *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess) = time(0);
  218. *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess) = 0;
  219. *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses) += 1;
  220. }else{
  221. *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess) +=1;
  222. *(g_get_global_snmp_vars()->int_tbl[index].dsFailures) +=1;
  223. }
  224. }
  225. PR_Unlock(interaction_table_mutex);
  226. /* free the memory allocated for dsURL in call to ds_make_url */
  227. if(dsURL != NULL){
  228. slapi_ch_free( (void**)&dsURL );
  229. }
  230. }
  231. /***********************************************************************************
  232. * Given: host and port
  233. * Returns: ldapUrl in form of
  234. * ldap://host.mcom.com:port/
  235. *
  236. * this should point to root DSE
  237. ************************************************************************************/
  238. char *make_ds_url(char *host, int port){
  239. char *url;
  240. url = slapi_ch_smprintf("ldap://%s:%d/",host, port);
  241. return url;
  242. }
  243. /***********************************************************************************
  244. * searches the table for the url specified
  245. * If there, returns index to update stats
  246. * if, not there returns index of oldest interaction, and isnew flag is set
  247. * so caller can rewrite this row
  248. ************************************************************************************/
  249. int search_interaction_table(char *dsURL, int *isnew)
  250. {
  251. int i;
  252. int index = 0;
  253. time_t oldestattempt;
  254. time_t currentattempt;
  255. oldestattempt = *(g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt);
  256. *isnew = 1;
  257. for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++){
  258. if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available"))
  259. {
  260. /* found it -- this is new, first time for this row */
  261. index = i;
  262. break;
  263. }else if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, dsURL)){
  264. /* found it -- it was already there*/
  265. *isnew = 0;
  266. index = i;
  267. break;
  268. }else{
  269. /* not found so figure out oldest row */
  270. currentattempt = *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
  271. if(currentattempt <= oldestattempt){
  272. index=i;
  273. oldestattempt = currentattempt;
  274. }
  275. }
  276. }
  277. return index;
  278. }
  279. /* for debuging until subagent part working, print contents of interaction table */
  280. void print_snmp_interaction_table()
  281. {
  282. int i;
  283. for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
  284. {
  285. fprintf(stderr, " dsIntIndex: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsIntIndex));
  286. fprintf(stderr, " dsName: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsName);
  287. fprintf(stderr, " dsTimeOfCreation: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation));
  288. fprintf(stderr, " dsTimeOfLastAttempt: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt));
  289. fprintf(stderr, " dsTimeOfLastSuccess: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess));
  290. fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess));
  291. fprintf(stderr, " dsFailures: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsFailures));
  292. fprintf(stderr, " dsSuccesses: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsSuccesses));
  293. fprintf(stderr, " dsURL: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsURL);
  294. fprintf(stderr, "\n");
  295. }
  296. }
  297. /*-------------------------------------------------------------------------
  298. *
  299. * sc_setevent: Sets the specified event (NT only). The input event has
  300. * to be created by the subagent during its initialization.
  301. *
  302. * Returns: None
  303. *
  304. *-----------------------------------------------------------------------*/
  305. #ifdef _WIN32
  306. void sc_setevent(char *ev)
  307. {
  308. HANDLE hTrapEvent;
  309. DWORD err = NO_ERROR;
  310. /*
  311. * Set the event handle to force NT SNMP service to call the subagent
  312. * DLL to generate a trap. Any error will be ignored as the subagent
  313. * may not have been loaded.
  314. */
  315. if ((hTrapEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE,
  316. (LPCTSTR) ev)) != NULL)
  317. {
  318. if (SetEvent(hTrapEvent) == FALSE)
  319. err = GetLastError();
  320. }
  321. else
  322. err = GetLastError();
  323. if (err != NO_ERROR)
  324. {
  325. fprintf(stderr, "Failed to set trap (error = %d).\n", err);
  326. }
  327. }
  328. #endif
  329. /***********************************************************************************
  330. *
  331. * int snmp_collator_start()
  332. *
  333. * open the memory map and initialize the variables
  334. * initializes the global variables used by snmp
  335. *
  336. * starts the collator thread
  337. ************************************************************************************/
  338. int snmp_collator_start()
  339. {
  340. int err;
  341. char *instancedir = config_get_instancedir();
  342. /*
  343. * Get directory for our stats file
  344. */
  345. PR_snprintf(szStatsFile, sizeof(szStatsFile), "%s/logs/%s", instancedir,
  346. AGT_STATS_FILE);
  347. tmpstatsfile = szStatsFile;
  348. slapi_ch_free((void **) &instancedir);
  349. /* open the memory map */
  350. if ((err = agt_mopen_stats(tmpstatsfile, O_RDWR, &hdl) != 0))
  351. {
  352. if (err != EEXIST) /* Ignore if file already exists */
  353. {
  354. printf("Failed to open stats file (%s) (error %d).\n",
  355. AGT_STATS_FILE, err);
  356. exit(1);
  357. }
  358. }
  359. /* read config entry for entity table data */
  360. /* point stats struct at mmap data */
  361. stats = (struct agt_stats_t *) mmap_tbl [hdl].fp;
  362. /* initialize stats data */
  363. snmp_collator_init();
  364. /*
  365. * now that memmap is open and things point the right way
  366. * an atomic set or increment anywhere in slapd should set
  367. * the snmp memmap vars correctly and be able to be polled by snmp
  368. */
  369. /* Arrange to be called back periodically */
  370. snmp_eq_ctx = slapi_eq_repeat(snmp_collator_update, NULL, (time_t)0,
  371. SLAPD_SNMP_UPDATE_INTERVAL);
  372. return 0;
  373. }
  374. /***********************************************************************************
  375. *
  376. * int snmp_collator_stop()
  377. *
  378. * stops the collator thread
  379. * closes the memory map
  380. * cleans up any needed memory
  381. *
  382. ************************************************************************************/
  383. int snmp_collator_stop()
  384. {
  385. int err;
  386. /* Abort any pending events */
  387. slapi_eq_cancel(snmp_eq_ctx);
  388. snmp_collator_stopped = 1;
  389. /* close the memory map */
  390. if ((err = agt_mclose_stats(hdl)) != 0)
  391. {
  392. fprintf(stderr, "Failed to close stats file (%s) (error = %d).",
  393. AGT_STATS_FILE, err);
  394. }
  395. if (remove(tmpstatsfile) != 0)
  396. {
  397. fprintf(stderr, "Failed to remove (%s) (error = %d).\n",
  398. tmpstatsfile, errno);
  399. }
  400. /* delete lock */
  401. PR_DestroyLock(interaction_table_mutex);
  402. #ifdef _WIN32
  403. /* send the event so server down trap gets set on NT */
  404. sc_setevent(MAGT_NSEV_SNMPTRAP);
  405. #endif
  406. /* stevross: I probably need to free stats too... make sure to add that later */
  407. return 0;
  408. }
  409. /***********************************************************************************
  410. *
  411. * int snmp_collator_update()
  412. *
  413. * our architecture changed from mail server and we right to mmapped
  414. * area as soon as operation completed, rather than maintining the same data twice
  415. * and doing a polled update. However, to keep traps working correctly (as they depend)
  416. * on the time in the header, it is more efficient to write the header info
  417. * in a polled fashion (ever 1 sec)
  418. *
  419. ************************************************************************************/
  420. void
  421. snmp_collator_update(time_t start_time, void *arg)
  422. {
  423. Slapi_Backend *be, *be_next;
  424. char *cookie = NULL;
  425. Slapi_PBlock *search_result_pb = NULL;
  426. Slapi_Entry **search_entries;
  427. Slapi_Attr *attr = NULL;
  428. Slapi_Value *sval = NULL;
  429. int search_result;
  430. if (snmp_collator_stopped) {
  431. return;
  432. }
  433. /* just update the update time in the header */
  434. if( stats != NULL){
  435. stats->hdr_stats.updateTime = time(0);
  436. }
  437. /* set the cache hits/cache entries info */
  438. be = slapi_get_first_backend(&cookie);
  439. if (!be)
  440. return;
  441. be_next = slapi_get_next_backend(cookie);
  442. slapi_ch_free ((void **) &cookie);
  443. /* for now, only do it if there is only 1 backend, otherwise don't know
  444. which backend to pick */
  445. if(be_next == NULL)
  446. {
  447. Slapi_DN monitordn;
  448. slapi_sdn_init(&monitordn);
  449. be_getmonitordn(be,&monitordn);
  450. /* do a search on the monitor dn to get info */
  451. search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
  452. LDAP_SCOPE_BASE,
  453. "objectclass=*",
  454. NULL,
  455. NULL,
  456. 0);
  457. slapi_sdn_done(&monitordn);
  458. slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
  459. if(search_result == 0)
  460. {
  461. const struct berval *val = NULL;
  462. /* get the entrycachehits */
  463. slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
  464. &search_entries);
  465. if(slapi_entry_attr_find( search_entries[0], "entrycachehits", &attr) == 0 )
  466. {
  467. /* get the values out of the attribute */
  468. val = NULL;
  469. slapi_attr_first_value( attr, &sval );
  470. if(NULL != sval)
  471. {
  472. val= slapi_value_get_berval( sval );
  473. }
  474. }
  475. /* if we got a value for entrycachehits, then set it */
  476. if(val != NULL)
  477. {
  478. PR_AtomicSet(g_get_global_snmp_vars()->entries_tbl.dsCacheHits, atoi(val->bv_val));
  479. }
  480. /* get the currententrycachesize */
  481. attr = NULL;
  482. val = NULL;
  483. sval = NULL;
  484. if(slapi_entry_attr_find( search_entries[0], "currententrycachesize", &attr) == 0 )
  485. {
  486. /* get the values out of the attribute */
  487. slapi_attr_first_value( attr,&sval );
  488. if(NULL != sval) {
  489. val= slapi_value_get_berval( sval );
  490. }
  491. }
  492. /* if we got a value for currententrycachesize, then set it */
  493. if(val != NULL)
  494. {
  495. PR_AtomicSet(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries, atoi(val->bv_val));
  496. }
  497. }
  498. slapi_free_search_results_internal(search_result_pb);
  499. slapi_pblock_destroy(search_result_pb);
  500. }
  501. }
  502. static void
  503. add_counter_to_value(Slapi_Entry *e, const char *type, int countervalue)
  504. {
  505. char value[40];
  506. sprintf(value,"%d",countervalue);
  507. slapi_entry_attr_set_charptr( e, type, value);
  508. }
  509. void
  510. snmp_as_entry(Slapi_Entry *e)
  511. {
  512. add_counter_to_value(e,"AnonymousBinds",stats->ops_stats.dsAnonymousBinds);
  513. add_counter_to_value(e,"UnAuthBinds",stats->ops_stats.dsUnAuthBinds);
  514. add_counter_to_value(e,"SimpleAuthBinds",stats->ops_stats.dsSimpleAuthBinds);
  515. add_counter_to_value(e,"StrongAuthBinds",stats->ops_stats.dsStrongAuthBinds);
  516. add_counter_to_value(e,"BindSecurityErrors",stats->ops_stats.dsBindSecurityErrors);
  517. add_counter_to_value(e,"InOps",stats->ops_stats.dsInOps);
  518. add_counter_to_value(e,"ReadOps",stats->ops_stats.dsReadOps);
  519. add_counter_to_value(e,"CompareOps",stats->ops_stats.dsCompareOps);
  520. add_counter_to_value(e,"AddEntryOps",stats->ops_stats.dsAddEntryOps);
  521. add_counter_to_value(e,"RemoveEntryOps",stats->ops_stats.dsRemoveEntryOps);
  522. add_counter_to_value(e,"ModifyEntryOps",stats->ops_stats.dsModifyEntryOps);
  523. add_counter_to_value(e,"ModifyRDNOps",stats->ops_stats.dsModifyRDNOps);
  524. add_counter_to_value(e,"ListOps",stats->ops_stats.dsListOps);
  525. add_counter_to_value(e,"SearchOps",stats->ops_stats.dsSearchOps);
  526. add_counter_to_value(e,"OneLevelSearchOps",stats->ops_stats.dsOneLevelSearchOps);
  527. add_counter_to_value(e,"WholeSubtreeSearchOps",stats->ops_stats.dsWholeSubtreeSearchOps);
  528. add_counter_to_value(e,"Referrals",stats->ops_stats.dsReferrals);
  529. add_counter_to_value(e,"Chainings",stats->ops_stats.dsChainings);
  530. add_counter_to_value(e,"SecurityErrors",stats->ops_stats.dsSecurityErrors);
  531. add_counter_to_value(e,"Errors",stats->ops_stats.dsErrors);
  532. add_counter_to_value(e,"Connections",stats->ops_stats.dsConnections);
  533. add_counter_to_value(e,"ConnectionSeq",stats->ops_stats.dsConnectionSeq);
  534. add_counter_to_value(e,"BytesRecv",stats->ops_stats.dsBytesRecv);
  535. add_counter_to_value(e,"BytesSent",stats->ops_stats.dsBytesSent);
  536. add_counter_to_value(e,"EntriesReturned",stats->ops_stats.dsEntriesReturned);
  537. add_counter_to_value(e,"ReferralsReturned",stats->ops_stats.dsReferralsReturned);
  538. add_counter_to_value(e,"MasterEntries",stats->entries_stats.dsMasterEntries);
  539. add_counter_to_value(e,"CopyEntries",stats->entries_stats.dsCopyEntries);
  540. add_counter_to_value(e,"CacheEntries",stats->entries_stats.dsCacheEntries);
  541. add_counter_to_value(e,"CacheHits",stats->entries_stats.dsCacheHits);
  542. add_counter_to_value(e,"SlaveHits",stats->entries_stats.dsSlaveHits);
  543. }
  544. static void
  545. loadConfigStats() {
  546. Slapi_Entry *entry = NULL;
  547. char *name = NULL;
  548. char *desc = NULL;
  549. char *org = NULL;
  550. char *loc = NULL;
  551. char *contact = NULL;
  552. /* Read attributes from SNMP config entry */
  553. getConfigEntry( &entry );
  554. if ( entry != NULL ) {
  555. name = slapi_entry_attr_get_charptr( entry, SNMP_NAME_ATTR );
  556. desc = slapi_entry_attr_get_charptr( entry, SNMP_DESC_ATTR );
  557. org = slapi_entry_attr_get_charptr( entry, SNMP_ORG_ATTR );
  558. loc = slapi_entry_attr_get_charptr( entry, SNMP_LOC_ATTR );
  559. contact = slapi_entry_attr_get_charptr( entry, SNMP_CONTACT_ATTR );
  560. freeConfigEntry( &entry );
  561. }
  562. /* Load stats into table */
  563. if ( name != NULL) {
  564. PL_strncpyz(stats->hdr_stats.dsName, name, SNMP_FIELD_LENGTH);
  565. }
  566. if ( desc != NULL) {
  567. PL_strncpyz(stats->hdr_stats.dsDescription, desc, SNMP_FIELD_LENGTH);
  568. }
  569. if ( org != NULL) {
  570. PL_strncpyz(stats->hdr_stats.dsOrganization, org, SNMP_FIELD_LENGTH);
  571. }
  572. if ( loc != NULL) {
  573. PL_strncpyz(stats->hdr_stats.dsLocation, loc, SNMP_FIELD_LENGTH);
  574. }
  575. if ( contact != NULL) {
  576. PL_strncpyz(stats->hdr_stats.dsContact, contact, SNMP_FIELD_LENGTH);
  577. }
  578. /* Free strings */
  579. slapi_ch_free((void **) &name);
  580. slapi_ch_free((void **) &desc);
  581. slapi_ch_free((void **) &org);
  582. slapi_ch_free((void **) &loc);
  583. slapi_ch_free((void **) &contact);
  584. }
  585. static Slapi_Entry *
  586. getConfigEntry( Slapi_Entry **e ) {
  587. Slapi_DN sdn;
  588. slapi_sdn_init_dn_byref( &sdn, SNMP_CONFIG_DN );
  589. slapi_search_internal_get_entry( &sdn, NULL, e,
  590. plugin_get_default_component_id());
  591. slapi_sdn_done( &sdn );
  592. return *e;
  593. }
  594. static void
  595. freeConfigEntry( Slapi_Entry **e ) {
  596. if ( (e != NULL) && (*e != NULL) ) {
  597. slapi_entry_free( *e );
  598. *e = NULL;
  599. }
  600. }