ldap-agent.c 30 KB

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