ldap-agent.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  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) 2005 Red Hat, Inc.
  35. * All rights reserved.
  36. * --- END COPYRIGHT BLOCK --- */
  37. #ifdef HAVE_CONFIG_H
  38. # include <config.h>
  39. #endif
  40. #include <stdio.h>
  41. #include <time.h>
  42. #include "ldap-agent.h"
  43. static netsnmp_handler_registration *ops_handler = NULL;
  44. static netsnmp_handler_registration *entries_handler = NULL;
  45. static netsnmp_handler_registration *entity_handler = NULL;
  46. static netsnmp_table_array_callbacks ops_cb;
  47. static netsnmp_table_array_callbacks entries_cb;
  48. static netsnmp_table_array_callbacks entity_cb;
  49. extern server_instance *server_head;
  50. /* Set table oids */
  51. oid dsOpsTable_oid[] = { dsOpsTable_TABLE_OID };
  52. size_t dsOpsTable_oid_len = OID_LENGTH(dsOpsTable_oid);
  53. oid dsEntriesTable_oid[] = { dsEntriesTable_TABLE_OID };
  54. size_t dsEntriesTable_oid_len = OID_LENGTH(dsEntriesTable_oid);
  55. oid dsEntityTable_oid[] = {dsEntityTable_TABLE_OID };
  56. size_t dsEntityTable_oid_len = OID_LENGTH(dsEntityTable_oid);
  57. /* Set trap oids */
  58. oid snmptrap_oid[] = { snmptrap_OID };
  59. size_t snmptrap_oid_len = OID_LENGTH(snmptrap_oid);
  60. oid enterprise_oid[] = { enterprise_OID };
  61. size_t enterprise_oid_len = OID_LENGTH(enterprise_oid);
  62. /************************************************************
  63. * init_ldap_agent
  64. *
  65. * Initializes the agent and populates the stats table
  66. * with initial data.
  67. */
  68. void
  69. init_ldap_agent(void)
  70. {
  71. server_instance *serv_p = NULL;
  72. stats_table_context *new_row = NULL;
  73. /* Define and create the table */
  74. initialize_stats_table();
  75. /* Initialize data for each server in conf file */
  76. for (serv_p = server_head; serv_p != NULL; serv_p = serv_p->next) {
  77. /* Check if this row already exists. */
  78. if (stats_table_find_row(serv_p->port) == NULL) {
  79. /* Create a new row */
  80. if ((new_row = stats_table_create_row(serv_p->port)) != NULL) {
  81. /* Set pointer for entity table */
  82. new_row->entity_tbl = serv_p;
  83. /* Set previous state of server to unknown */
  84. serv_p->server_state = STATE_UNKNOWN;
  85. /* Insert new row into the table */
  86. snmp_log(LOG_DEBUG, "Inserting row for server: %d\n", serv_p->port);
  87. CONTAINER_INSERT(ops_cb.container, new_row);
  88. } else {
  89. /* error during malloc of row */
  90. snmp_log(LOG_ERR, "Error creating row for server: %d\n",
  91. serv_p->port);
  92. }
  93. }
  94. }
  95. /* Force load data into stats table */
  96. load_stats_table(NULL, NULL);
  97. }
  98. /************************************************************
  99. * initialize_stats_table
  100. *
  101. * Initializes the stats table by defining its contents,
  102. * how it's structured, and registering callbacks.
  103. */
  104. void
  105. initialize_stats_table(void)
  106. {
  107. netsnmp_table_registration_info *ops_table_info = NULL;
  108. netsnmp_table_registration_info *entries_table_info = NULL;
  109. netsnmp_table_registration_info *entity_table_info = NULL;
  110. /* This is a hacky way of figuring out if we are on Net-SNMP 5.2 or later */
  111. #ifdef NETSNMP_CACHE_AUTO_RELOAD
  112. netsnmp_cache *stats_table_cache = NULL;
  113. #endif
  114. if (ops_handler || entries_handler || entity_handler) {
  115. snmp_log(LOG_ERR, "initialize_stats_table called more than once.\n");
  116. return;
  117. }
  118. memset(&ops_cb, 0x00, sizeof(ops_cb));
  119. memset(&entries_cb, 0x00, sizeof(entries_cb));
  120. memset(&entity_cb, 0x00, sizeof(entity_cb));
  121. /* create table structures */
  122. ops_table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
  123. entries_table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
  124. entity_table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
  125. /* create handlers */
  126. ops_handler = netsnmp_create_handler_registration("dsOpsTable",
  127. netsnmp_table_array_helper_handler,
  128. dsOpsTable_oid,
  129. dsOpsTable_oid_len,
  130. HANDLER_CAN_RONLY);
  131. entries_handler = netsnmp_create_handler_registration("dsEntriesTable",
  132. netsnmp_table_array_helper_handler,
  133. dsEntriesTable_oid,
  134. dsEntriesTable_oid_len,
  135. HANDLER_CAN_RONLY);
  136. entity_handler = netsnmp_create_handler_registration("dsEntityTable",
  137. netsnmp_table_array_helper_handler,
  138. dsEntityTable_oid,
  139. dsEntityTable_oid_len,
  140. HANDLER_CAN_RONLY);
  141. if (!ops_handler || !entries_handler || !entity_handler ||
  142. !ops_table_info || !entries_table_info || !entity_table_info) {
  143. /* malloc failed */
  144. snmp_log(LOG_ERR, "malloc failed in initialize_stats_table\n");
  145. SNMP_FREE(ops_table_info);
  146. SNMP_FREE(entries_table_info);
  147. SNMP_FREE(entity_table_info);
  148. return;
  149. }
  150. /* define table structures */
  151. netsnmp_table_helper_add_index(ops_table_info, ASN_INTEGER);
  152. netsnmp_table_helper_add_index(entries_table_info, ASN_INTEGER);
  153. netsnmp_table_helper_add_index(entity_table_info, ASN_INTEGER);
  154. ops_table_info->min_column = dsOpsTable_COL_MIN;
  155. ops_table_info->max_column = dsOpsTable_COL_MAX;
  156. entries_table_info->min_column = dsEntriesTable_COL_MIN;
  157. entries_table_info->max_column = dsEntriesTable_COL_MAX;
  158. entity_table_info->min_column = dsEntityTable_COL_MIN;
  159. entity_table_info->max_column = dsEntityTable_COL_MAX;
  160. /*
  161. * Define callbacks and the container. We only use one container that
  162. * all of the tables use.
  163. */
  164. ops_cb.get_value = dsOpsTable_get_value;
  165. ops_cb.container = netsnmp_container_find("dsOpsTable_primary:"
  166. "dsOpsTable:" "table_container");
  167. entries_cb.get_value = dsEntriesTable_get_value;
  168. entries_cb.container = ops_cb.container;
  169. entity_cb.get_value = dsEntityTable_get_value;
  170. entity_cb.container = ops_cb.container;
  171. /* registering the tables with the master agent */
  172. netsnmp_table_container_register(ops_handler, ops_table_info, &ops_cb,
  173. ops_cb.container, 1);
  174. netsnmp_table_container_register(entries_handler, entries_table_info, &entries_cb,
  175. entries_cb.container, 1);
  176. netsnmp_table_container_register(entity_handler, entity_table_info, &entity_cb,
  177. entity_cb.container, 1);
  178. /* Setup cache for auto reloading of stats */
  179. #ifdef NETSNMP_CACHE_AUTO_RELOAD
  180. /* This is new api as of Net-SNMP 5.2 */
  181. stats_table_cache = netsnmp_cache_create(CACHE_REFRESH_INTERVAL, load_stats_table,
  182. NULL, dsOpsTable_oid, dsOpsTable_oid_len);
  183. stats_table_cache->flags |= NETSNMP_CACHE_DONT_FREE_EXPIRED;
  184. stats_table_cache->flags |= NETSNMP_CACHE_DONT_AUTO_RELEASE;
  185. stats_table_cache->flags |= NETSNMP_CACHE_AUTO_RELOAD;
  186. netsnmp_inject_handler(ops_handler, netsnmp_cache_handler_get(stats_table_cache));
  187. #else
  188. /* Do things the old way. This is only needed for Net-SNMP 5.1 and earlier. */
  189. netsnmp_inject_handler(ops_handler, netsnmp_get_cache_handler(CACHE_REFRESH_INTERVAL, load_stats_table,
  190. free_stats_table, dsOpsTable_oid, dsOpsTable_oid_len));
  191. #endif
  192. }
  193. /************************************************************
  194. * stats_table_create_row
  195. *
  196. * Creates a new table row using the supplied port number as
  197. * the index, then returns a pointer to the new row.
  198. */
  199. stats_table_context *
  200. stats_table_create_row(unsigned long portnum)
  201. {
  202. netsnmp_index index;
  203. stats_table_context *ctx = SNMP_MALLOC_TYPEDEF(stats_table_context);
  204. oid *index_oid = (oid *)malloc(sizeof(oid) * MAX_OID_LEN);
  205. if (!ctx || !index_oid) {
  206. /* Error during malloc */
  207. snmp_log(LOG_ERR, "malloc failed in stats_table_create_row\n");
  208. goto error;
  209. }
  210. /* Create index using port number */
  211. index_oid[0] = portnum;
  212. index.oids = index_oid;
  213. index.len = 1;
  214. /* Copy index into row structure */
  215. memcpy(&ctx->index, &index, sizeof(index));
  216. return ctx;
  217. error:
  218. if (index_oid) free(index_oid);
  219. if (ctx) SNMP_FREE(ctx);
  220. return NULL;
  221. }
  222. /************************************************************
  223. * stats_table_find_row
  224. *
  225. * Searches for a row by the port number. Returns NULL if
  226. * the row doesn't exist.
  227. */
  228. stats_table_context *
  229. stats_table_find_row(unsigned long portnum)
  230. {
  231. netsnmp_index index;
  232. oid index_oid[MAX_OID_LEN];
  233. index_oid[0] = portnum;
  234. index.oids = index_oid;
  235. index.len = 1;
  236. return (stats_table_context *)
  237. CONTAINER_FIND(ops_cb.container, &index);
  238. }
  239. /************************************************************
  240. * load_stats_table
  241. *
  242. * Reloads the stats into the table. This is called
  243. * automatically from the cache handler. This function
  244. * does not reload the entity table since it's static
  245. * information. We also check if any traps need to
  246. * be sent here.
  247. */
  248. int
  249. load_stats_table(netsnmp_cache *cache, void *foo)
  250. {
  251. server_instance *serv_p = NULL;
  252. stats_table_context *ctx = NULL;
  253. time_t previous_start;
  254. int previous_state;
  255. int stats_hdl = -1;
  256. sem_t *stats_sem = NULL;
  257. snmp_log(LOG_INFO, "Reloading stats.\n");
  258. /* Initialize data for each server in conf file */
  259. for (serv_p = server_head; serv_p != NULL; serv_p = serv_p->next) {
  260. if ((ctx = stats_table_find_row(serv_p->port)) != NULL) {
  261. /* Save previous state of the server to
  262. * see if a trap needs to be sent */
  263. previous_state = serv_p->server_state;
  264. previous_start = ctx->hdr_tbl.startTime;
  265. snmp_log(LOG_INFO, "Opening stats file (%s) for server: %d\n",
  266. serv_p->stats_file, serv_p->port);
  267. /* Open and acquire semaphore */
  268. if ((stats_sem = sem_open(serv_p->stats_sem_name, 0)) == SEM_FAILED) {
  269. stats_sem = NULL;
  270. snmp_log(LOG_INFO, "Unable to open semaphore for server: %d\n", serv_p->port);
  271. } else {
  272. int i = 0;
  273. int got_sem = 0;
  274. for (i=0; i < SNMP_NUM_SEM_WAITS; i++) {
  275. if (sem_trywait(stats_sem) == 0) {
  276. got_sem = 1;
  277. break;
  278. }
  279. PR_Sleep(PR_SecondsToInterval(1));
  280. }
  281. if (!got_sem) {
  282. /* We're unable to get the semaphore. Assume
  283. * that the server is down. */
  284. snmp_log(LOG_INFO, "Unable to acquire semaphore for server: %d\n", serv_p->port);
  285. sem_close(stats_sem);
  286. stats_sem = NULL;
  287. }
  288. }
  289. /* Open the stats file */
  290. if ((stats_sem == NULL) || (agt_mopen_stats(serv_p->stats_file, O_RDONLY, &stats_hdl) != 0)) {
  291. if (stats_sem) {
  292. /* Release and close semaphore */
  293. sem_post(stats_sem);
  294. sem_close(stats_sem);
  295. }
  296. /* Server must be down */
  297. serv_p->server_state = SERVER_DOWN;
  298. /* Zero out the ops and entries tables */
  299. memset(&ctx->ops_tbl, 0x00, sizeof(ctx->ops_tbl));
  300. memset(&ctx->entries_tbl, 0x00, sizeof(ctx->entries_tbl));
  301. if (previous_state != SERVER_DOWN)
  302. snmp_log(LOG_INFO, "Unable to open stats file (%s) for server: %d\n",
  303. serv_p->stats_file, serv_p->port);
  304. } else {
  305. /* Initialize ops table */
  306. if ( agt_mread_stats(stats_hdl, &ctx->hdr_tbl, &ctx->ops_tbl,
  307. &ctx->entries_tbl) != 0 )
  308. snmp_log(LOG_ERR, "Unable to read stats file: %s\n",
  309. serv_p->stats_file);
  310. /* Close stats file */
  311. if ( agt_mclose_stats(stats_hdl) != 0 )
  312. snmp_log(LOG_ERR, "Error closing stats file: %s\n",
  313. serv_p->stats_file);
  314. /* Release and close semaphore */
  315. sem_post(stats_sem);
  316. sem_close(stats_sem);
  317. /* Server must be down if the stats file hasn't been
  318. * updated in a while */
  319. if (difftime(time(NULL), ctx->hdr_tbl.updateTime) >= UPDATE_THRESHOLD) {
  320. serv_p->server_state = SERVER_DOWN;
  321. if (previous_state != SERVER_DOWN)
  322. snmp_log(LOG_INFO, "Stats file for server %d hasn't been updated"
  323. " in %d seconds.\n", serv_p->port, UPDATE_THRESHOLD);
  324. } else {
  325. serv_p->server_state = SERVER_UP;
  326. }
  327. }
  328. /* If the state of the server changed since the last
  329. * load of the stats, send a trap. */
  330. if (previous_state != STATE_UNKNOWN) {
  331. if (serv_p->server_state != previous_state) {
  332. if (serv_p->server_state == SERVER_UP) {
  333. snmp_log(LOG_INFO, "Detected start of server: %d\n",
  334. serv_p->port);
  335. send_DirectoryServerStart_trap(serv_p);
  336. } else {
  337. send_DirectoryServerDown_trap(serv_p);
  338. /* Zero out the ops and entries tables */
  339. memset(&ctx->ops_tbl, 0x00, sizeof(ctx->ops_tbl));
  340. memset(&ctx->entries_tbl, 0x00, sizeof(ctx->entries_tbl));
  341. }
  342. } else if (ctx->hdr_tbl.startTime != previous_start) {
  343. /* Send traps if the server has restarted since the last load */
  344. snmp_log(LOG_INFO, "Detected restart of server: %d\n", serv_p->port);
  345. send_DirectoryServerDown_trap(serv_p);
  346. send_DirectoryServerStart_trap(serv_p);
  347. }
  348. }
  349. } else {
  350. /* Can't find our row. This shouldn't ever happen. */
  351. snmp_log(LOG_ERR, "Row not found for server: %d\n",
  352. serv_p->port);
  353. }
  354. }
  355. return 0;
  356. }
  357. /************************************************************
  358. * free_stats_table
  359. *
  360. * This function doesn't need to free anything since the
  361. * load_stats_table function doesn't allocate any memory
  362. * itself. The cache handler requires us to have a callback
  363. * function for freeing the cache, so here it is.
  364. */
  365. void
  366. free_stats_table(netsnmp_cache *cache, void *foo)
  367. {
  368. return;
  369. }
  370. /************************************************************
  371. * dsOpsTable_get_value
  372. *
  373. * This routine is called for get requests to copy the data
  374. * from the context to the varbind for the request. If the
  375. * context has been properly maintained, you don't need to
  376. * change in code in this fuction.
  377. */
  378. int
  379. dsOpsTable_get_value(netsnmp_request_info *request,
  380. netsnmp_index * item,
  381. netsnmp_table_request_info *table_info)
  382. {
  383. PRUint64 *the_stat = NULL;
  384. integer64 new_val;
  385. netsnmp_variable_list *var = request->requestvb;
  386. stats_table_context *context = (stats_table_context *) item;
  387. switch (table_info->colnum) {
  388. case COLUMN_DSANONYMOUSBINDS:
  389. the_stat = &context->ops_tbl.dsAnonymousBinds;
  390. break;
  391. case COLUMN_DSUNAUTHBINDS:
  392. the_stat = &context->ops_tbl.dsUnAuthBinds;
  393. break;
  394. case COLUMN_DSSIMPLEAUTHBINDS:
  395. the_stat = &context->ops_tbl.dsSimpleAuthBinds;
  396. break;
  397. case COLUMN_DSSTRONGAUTHBINDS:
  398. the_stat = &context->ops_tbl.dsStrongAuthBinds;
  399. break;
  400. case COLUMN_DSBINDSECURITYERRORS:
  401. the_stat = &context->ops_tbl.dsBindSecurityErrors;
  402. break;
  403. case COLUMN_DSINOPS:
  404. the_stat = &context->ops_tbl.dsInOps;
  405. break;
  406. case COLUMN_DSREADOPS:
  407. the_stat = &context->ops_tbl.dsReadOps;
  408. break;
  409. case COLUMN_DSCOMPAREOPS:
  410. the_stat = &context->ops_tbl.dsCompareOps;
  411. break;
  412. case COLUMN_DSADDENTRYOPS:
  413. the_stat = &context->ops_tbl.dsAddEntryOps;
  414. break;
  415. case COLUMN_DSREMOVEENTRYOPS:
  416. the_stat = &context->ops_tbl.dsRemoveEntryOps;
  417. break;
  418. case COLUMN_DSMODIFYENTRYOPS:
  419. the_stat = &context->ops_tbl.dsModifyEntryOps;
  420. break;
  421. case COLUMN_DSMODIFYRDNOPS:
  422. the_stat = &context->ops_tbl.dsModifyRDNOps;
  423. break;
  424. case COLUMN_DSLISTOPS:
  425. the_stat = &context->ops_tbl.dsListOps;
  426. break;
  427. case COLUMN_DSSEARCHOPS:
  428. the_stat = &context->ops_tbl.dsSearchOps;
  429. break;
  430. case COLUMN_DSONELEVELSEARCHOPS:
  431. the_stat = &context->ops_tbl.dsOneLevelSearchOps;
  432. break;
  433. case COLUMN_DSWHOLESUBTREESEARCHOPS:
  434. the_stat = &context->ops_tbl.dsWholeSubtreeSearchOps;
  435. break;
  436. case COLUMN_DSREFERRALS:
  437. the_stat = &context->ops_tbl.dsReferrals;
  438. break;
  439. case COLUMN_DSCHAININGS:
  440. the_stat = &context->ops_tbl.dsChainings;
  441. break;
  442. case COLUMN_DSSECURITYERRORS:
  443. the_stat = &context->ops_tbl.dsSecurityErrors;
  444. break;
  445. case COLUMN_DSERRORS:
  446. the_stat = &context->ops_tbl.dsErrors;
  447. break;
  448. case COLUMN_DSCONNECTIONS:
  449. the_stat = &context->ops_tbl.dsConnections;
  450. break;
  451. case COLUMN_DSCONNECTIONSINMAXTHREADS:
  452. the_stat = &context->ops_tbl.dsConnectionsInMaxThreads;
  453. break;
  454. case COLUMN_DSMAXTHREADSHIT:
  455. the_stat = &context->ops_tbl.dsMaxThreadsHit;
  456. break;
  457. default:/* We shouldn't get here */
  458. snmp_log(LOG_ERR, "Unknown column in dsOpsTable_get_value\n");
  459. return SNMP_ERR_GENERR;
  460. }
  461. /* The Net-SNMP integer64 type isn't a true 64-bit value, but instead
  462. * a structure containing the high and low bits separately. We need
  463. * to split our value appropriately. */
  464. new_val.low = *the_stat & 0x00000000ffffffff;
  465. new_val.high = (*the_stat >> 32) & 0x00000000ffffffff;
  466. snmp_set_var_typed_value(var, ASN_COUNTER64,
  467. (u_char *) &new_val,
  468. sizeof(new_val));
  469. return SNMP_ERR_NOERROR;
  470. }
  471. /************************************************************
  472. * dsEntriesTable_get_value
  473. *
  474. * This routine is called for get requests to copy the data
  475. * from the context to the varbind for the request. If the
  476. * context has been properly maintained, you don't need to
  477. * change in code in this fuction.
  478. */
  479. int
  480. dsEntriesTable_get_value(netsnmp_request_info *request,
  481. netsnmp_index * item,
  482. netsnmp_table_request_info *table_info)
  483. {
  484. PRUint64 *the_stat = NULL;
  485. integer64 new_val;
  486. netsnmp_variable_list *var = request->requestvb;
  487. stats_table_context *context = (stats_table_context *) item;
  488. switch (table_info->colnum) {
  489. case COLUMN_DSMASTERENTRIES:
  490. the_stat = &context->entries_tbl.dsMasterEntries;
  491. break;
  492. case COLUMN_DSCOPYENTRIES:
  493. the_stat = &context->entries_tbl.dsCopyEntries;
  494. break;
  495. case COLUMN_DSCACHEENTRIES:
  496. the_stat = &context->entries_tbl.dsCacheEntries;
  497. break;
  498. case COLUMN_DSCACHEHITS:
  499. the_stat = &context->entries_tbl.dsCacheHits;
  500. break;
  501. case COLUMN_DSSLAVEHITS:
  502. the_stat = &context->entries_tbl.dsSlaveHits;
  503. break;
  504. default:/* We shouldn't get here */
  505. snmp_log(LOG_ERR, "Unknown column in dsEntriesTable_get_value\n");
  506. return SNMP_ERR_GENERR;
  507. }
  508. /* The Net-SNMP integer64 type isn't a true 64-bit value, but instead
  509. * a structure containing the high and low bits separately. We need
  510. * to split our value appropriately. */
  511. new_val.low = *the_stat & 0x00000000ffffffff;
  512. new_val.high = (*the_stat >> 32) & 0x00000000ffffffff;
  513. snmp_set_var_typed_value(var, ASN_COUNTER64,
  514. (u_char *) &new_val,
  515. sizeof(new_val));
  516. return SNMP_ERR_NOERROR;
  517. }
  518. /************************************************************
  519. * dsEntityTable_get_value
  520. *
  521. * This routine is called for get requests to copy the data
  522. * from the context to the varbind for the request. If the
  523. * context has been properly maintained, you don't need to
  524. * change in code in this fuction.
  525. */
  526. int
  527. dsEntityTable_get_value(netsnmp_request_info *request,
  528. netsnmp_index * item,
  529. netsnmp_table_request_info *table_info)
  530. {
  531. netsnmp_variable_list *var = request->requestvb;
  532. stats_table_context *context = (stats_table_context *) item;
  533. switch (table_info->colnum) {
  534. case COLUMN_DSENTITYDESCR:
  535. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  536. (u_char *) context->hdr_tbl.dsDescription,
  537. strlen(context->hdr_tbl.dsDescription));
  538. break;
  539. case COLUMN_DSENTITYVERS:
  540. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  541. (u_char *) context->hdr_tbl.dsVersion,
  542. strlen(context->hdr_tbl.dsVersion));
  543. break;
  544. case COLUMN_DSENTITYORG:
  545. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  546. (u_char *) context->hdr_tbl.dsOrganization,
  547. strlen(context->hdr_tbl.dsOrganization));
  548. break;
  549. case COLUMN_DSENTITYLOCATION:
  550. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  551. (u_char *) context->hdr_tbl.dsLocation,
  552. strlen(context->hdr_tbl.dsLocation));
  553. break;
  554. case COLUMN_DSENTITYCONTACT:
  555. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  556. (u_char *) context->hdr_tbl.dsContact,
  557. strlen(context->hdr_tbl.dsContact));
  558. break;
  559. case COLUMN_DSENTITYNAME:
  560. snmp_set_var_typed_value(var, ASN_OCTET_STR,
  561. (u_char *) context->hdr_tbl.dsName,
  562. strlen(context->hdr_tbl.dsName));
  563. break;
  564. default:/* We shouldn't get here */
  565. snmp_log(LOG_ERR, "Unknown column in dsEntityTable_get_value\n");
  566. return SNMP_ERR_GENERR;
  567. }
  568. return SNMP_ERR_NOERROR;
  569. }
  570. /************************************************************
  571. * send_DirectoryServerDown_trap
  572. *
  573. * Sends off the server down trap.
  574. */
  575. int
  576. send_DirectoryServerDown_trap(server_instance *serv_p)
  577. {
  578. netsnmp_variable_list *var_list = NULL;
  579. stats_table_context *ctx = NULL;
  580. /* Define the oids for the trap */
  581. oid DirectoryServerDown_oid[] = { DirectoryServerDown_OID };
  582. oid dsEntityDescr_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYDESCR, 0 };
  583. oid dsEntityVers_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYVERS, 0 };
  584. oid dsEntityLocation_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYLOCATION, 0 };
  585. oid dsEntityContact_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYCONTACT, 0 };
  586. dsEntityDescr_oid[3] = serv_p->port;
  587. dsEntityVers_oid[3] = serv_p->port;
  588. dsEntityLocation_oid[3] = serv_p->port;
  589. dsEntityContact_oid[3] = serv_p->port;
  590. snmp_log(LOG_INFO, "Sending down trap for server: %d\n", serv_p->port);
  591. /* Lookup row to get version string */
  592. if ((ctx = stats_table_find_row(serv_p->port)) == NULL) {
  593. snmp_log(LOG_ERR, "Malloc error finding row for server: %d\n", serv_p->port);
  594. return 1;
  595. }
  596. /* Setup the variable list to send with the trap */
  597. snmp_varlist_add_variable(&var_list,
  598. snmptrap_oid, OID_LENGTH(snmptrap_oid),
  599. ASN_OBJECT_ID,
  600. (u_char *) &DirectoryServerDown_oid,
  601. sizeof(DirectoryServerDown_oid));
  602. snmp_varlist_add_variable(&var_list,
  603. dsEntityDescr_oid,
  604. OID_LENGTH(dsEntityDescr_oid), ASN_OCTET_STR,
  605. (u_char *) ctx->hdr_tbl.dsDescription,
  606. strlen(ctx->hdr_tbl.dsDescription));
  607. snmp_varlist_add_variable(&var_list,
  608. dsEntityVers_oid,
  609. OID_LENGTH(dsEntityVers_oid), ASN_OCTET_STR,
  610. (u_char *) ctx->hdr_tbl.dsVersion,
  611. strlen(ctx->hdr_tbl.dsVersion));
  612. snmp_varlist_add_variable(&var_list,
  613. dsEntityLocation_oid,
  614. OID_LENGTH(dsEntityLocation_oid),
  615. ASN_OCTET_STR,
  616. (u_char *) ctx->hdr_tbl.dsLocation,
  617. strlen(ctx->hdr_tbl.dsLocation));
  618. snmp_varlist_add_variable(&var_list,
  619. dsEntityContact_oid,
  620. OID_LENGTH(dsEntityContact_oid),
  621. ASN_OCTET_STR,
  622. (u_char *) ctx->hdr_tbl.dsContact,
  623. strlen(ctx->hdr_tbl.dsContact));
  624. /* Send the trap */
  625. send_v2trap(var_list);
  626. snmp_free_varbind(var_list);
  627. return SNMP_ERR_NOERROR;
  628. }
  629. /************************************************************
  630. * send_DirectoryServerStart_trap
  631. *
  632. * Sends off the server start trap.
  633. */
  634. int
  635. send_DirectoryServerStart_trap(server_instance *serv_p)
  636. {
  637. netsnmp_variable_list *var_list = NULL;
  638. stats_table_context *ctx = NULL;
  639. /* Define the oids for the trap */
  640. oid DirectoryServerStart_oid[] = { DirectoryServerStart_OID };
  641. oid dsEntityDescr_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYDESCR, 0 };
  642. oid dsEntityVers_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYVERS, 0 };
  643. oid dsEntityLocation_oid[] = { dsEntityTable_TABLE_OID, 1, COLUMN_DSENTITYLOCATION, 0 };
  644. dsEntityDescr_oid[3] = serv_p->port;
  645. dsEntityVers_oid[3] = serv_p->port;
  646. dsEntityLocation_oid[3] = serv_p->port;
  647. snmp_log(LOG_INFO, "Sending start trap for server: %d\n", serv_p->port);
  648. /* Lookup row to get version string */
  649. if ((ctx = stats_table_find_row(serv_p->port)) == NULL) {
  650. snmp_log(LOG_ERR, "Malloc error finding row for server: %d\n", serv_p->port);
  651. return 1;
  652. }
  653. /* Setup the variable list to send with the trap */
  654. snmp_varlist_add_variable(&var_list,
  655. snmptrap_oid, OID_LENGTH(snmptrap_oid),
  656. ASN_OBJECT_ID,
  657. (u_char *) &DirectoryServerStart_oid,
  658. sizeof(DirectoryServerStart_oid));
  659. snmp_varlist_add_variable(&var_list,
  660. dsEntityDescr_oid,
  661. OID_LENGTH(dsEntityDescr_oid), ASN_OCTET_STR,
  662. (u_char *) ctx->hdr_tbl.dsDescription,
  663. strlen(ctx->hdr_tbl.dsDescription));
  664. snmp_varlist_add_variable(&var_list,
  665. dsEntityVers_oid,
  666. OID_LENGTH(dsEntityVers_oid), ASN_OCTET_STR,
  667. (u_char *) ctx->hdr_tbl.dsVersion,
  668. strlen(ctx->hdr_tbl.dsVersion));
  669. snmp_varlist_add_variable(&var_list,
  670. dsEntityLocation_oid,
  671. OID_LENGTH(dsEntityLocation_oid),
  672. ASN_OCTET_STR,
  673. (u_char *) ctx->hdr_tbl.dsLocation,
  674. strlen(ctx->hdr_tbl.dsLocation));
  675. /* Send the trap */
  676. send_v2trap(var_list);
  677. snmp_free_varbind(var_list);
  678. return SNMP_ERR_NOERROR;
  679. }