dlmod.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:16k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Dynamic Loadable Agent Modules MIB (UCD-DLMOD-MIB) - dlmod.c
  3.  *
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #if HAVE_STDLIB_H
  7. #include <stdlib.h>
  8. #endif
  9. #include <stdio.h>
  10. #if HAVE_STRING_H
  11. #include <string.h>
  12. #else
  13. #include <strings.h>
  14. #endif
  15. #if HAVE_UNISTD_H
  16. #include <unistd.h>
  17. #endif
  18. #include <ctype.h>
  19. #if HAVE_WINSOCK_H
  20. #include <winsock.h>
  21. #endif
  22. #include <net-snmp/net-snmp-includes.h>
  23. #include <net-snmp/agent/net-snmp-agent-includes.h>
  24. #include "struct.h"
  25. #include "util_funcs.h"
  26. #if defined(HAVE_DLFCN_H) && ( defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) )
  27. #include <dlfcn.h>
  28. #include "dlmod.h"
  29. static struct dlmod *dlmods = NULL;
  30. static int      dlmod_next_index = 1;
  31. static char     dlmod_path[1024];
  32. static void     dlmod_parse_config(const char *, char *);
  33. static void     dlmod_free_config(void);
  34. /*
  35.  * this variable defines function callbacks and type return
  36.  * information for the dlmod mib
  37.  */
  38. static struct variable4 dlmod_variables[] = {
  39.     {DLMODNEXTINDEX, ASN_INTEGER, RONLY, var_dlmod, 1, {1}},
  40.     {DLMODNAME, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 2}},
  41.     {DLMODPATH, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 3}},
  42.     {DLMODERROR, ASN_OCTET_STR, RONLY, var_dlmodEntry, 3, {2, 1, 4}},
  43.     {DLMODSTATUS, ASN_INTEGER, RWRITE, var_dlmodEntry, 3, {2, 1, 5}},
  44. };
  45. static oid      dlmod_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 14 };
  46. static int      dlmod_variables_oid_len = 9;
  47. void
  48. init_dlmod(void)
  49. {
  50.     char           *p;
  51.     int             len;
  52.     REGISTER_MIB("dlmod", dlmod_variables, variable4, dlmod_variables_oid);
  53.     /*
  54.      * TODO: REGISTER_SYSOR_ENTRY 
  55.      */
  56.     DEBUGMSGTL(("dlmod", "register mibn"));
  57.     snmpd_register_config_handler("dlmod", dlmod_parse_config,
  58.                                   dlmod_free_config,
  59.                                   "module-name module-path");
  60.     p = getenv("SNMPDLMODPATH");
  61.     strncpy(dlmod_path, SNMPDLMODPATH, sizeof(dlmod_path));
  62.     dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
  63.     if (p) {
  64.         if (p[0] == ':') {
  65.             len = strlen(dlmod_path);
  66.             if (dlmod_path[len - 1] != ':') {
  67.                 strncat(dlmod_path, ":", sizeof(dlmod_path) - len -1);
  68.                 len++;
  69.             }
  70.             strncat(dlmod_path, p + 1,   sizeof(dlmod_path) - len);
  71.         } else
  72.             strncpy(dlmod_path, p, sizeof(dlmod_path));
  73.     }
  74.     dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
  75.     DEBUGMSGTL(("dlmod", "dlmod_path: %sn", dlmod_path));
  76. }
  77. void
  78. deinit_dlmod(void)
  79. {
  80.     unregister_mib(dlmod_variables_oid, dlmod_variables_oid_len);
  81.     snmpd_unregister_config_handler("dlmod");
  82. }
  83. struct dlmod   *
  84. dlmod_create_module(void)
  85. {
  86.     struct dlmod  **pdlmod, *dlm;
  87.     DEBUGMSGTL(("dlmod", "dlmod_create_modulen"));
  88.     dlm = (struct dlmod *) calloc(1, sizeof(struct dlmod));
  89.     if (dlm == NULL)
  90.         return NULL;
  91.     dlm->index = dlmod_next_index++;
  92.     dlm->status = DLMOD_UNLOADED;
  93.     for (pdlmod = &dlmods; *pdlmod != NULL; pdlmod = &((*pdlmod)->next));
  94.     (*pdlmod) = dlm;
  95.     return dlm;
  96. }
  97. void
  98. dlmod_delete_module(struct dlmod *dlm)
  99. {
  100.     struct dlmod  **pdlmod;
  101.     DEBUGMSGTL(("dlmod", "dlmod_delete_modulen"));
  102.     if (!dlm || dlm->status != DLMOD_UNLOADED)
  103.         return;
  104.     for (pdlmod = &dlmods; *pdlmod; pdlmod = &((*pdlmod)->next))
  105.         if (*pdlmod == dlm) {
  106.             *pdlmod = dlm->next;
  107.             free(dlm);
  108.             return;
  109.         }
  110. }
  111. void
  112. dlmod_load_module(struct dlmod *dlm)
  113. {
  114.     char            sym_init[64];
  115.     char           *p, tmp_path[255];
  116.     int             (*dl_init) (void);
  117.     char           *st;
  118.     DEBUGMSGTL(("dlmod", "dlmod_load_module %s: %sn", dlm->name,
  119.                 dlm->path));
  120.     if (!dlm || !dlm->path || !dlm->name ||
  121.         (dlm->status != DLMOD_UNLOADED && dlm->status != DLMOD_ERROR))
  122.         return;
  123.     if (dlm->path[0] == '/') {
  124. #ifdef RTLD_NOW
  125.         dlm->handle = dlopen(dlm->path, RTLD_NOW);
  126. #else
  127.         dlm->handle = dlopen(dlm->path, RTLD_LAZY);
  128. #endif
  129.         if (dlm->handle == NULL) {
  130.             snprintf(dlm->error, sizeof(dlm->error),
  131.                      "dlopen failed: %s", dlerror());
  132.             dlm->status = DLMOD_ERROR;
  133.             return;
  134.         }
  135.     } else {
  136.         for (p = strtok_r(dlmod_path, ":", &st); p; p = strtok_r(NULL, ":", &st)) {
  137.             snprintf(tmp_path, sizeof(tmp_path), "%s/%s.so", p, dlm->path);
  138.             DEBUGMSGTL(("dlmod", "p: %s tmp_path: %sn", p, tmp_path));
  139. #ifdef RTLD_NOW
  140.             dlm->handle = dlopen(tmp_path, RTLD_NOW);
  141. #else
  142.             dlm->handle = dlopen(tmp_path, RTLD_LAZY);
  143. #endif
  144.             if (dlm->handle == NULL) {
  145.                 snprintf(dlm->error, sizeof(dlm->error),
  146.                          "dlopen failed: %s", dlerror());
  147.                 dlm->status = DLMOD_ERROR;
  148.             }
  149.         }
  150.         strncpy(dlm->path, tmp_path, sizeof(dlm->path));
  151.         if (dlm->status == DLMOD_ERROR)
  152.             return;
  153.     }
  154.     snprintf(sym_init, sizeof(sym_init), "init_%s", dlm->name);
  155.     dl_init = dlsym(dlm->handle, sym_init);
  156.     if (dl_init == NULL) {
  157.         dlclose(dlm->handle);
  158.         snprintf(dlm->error, sizeof(dlm->error),
  159.                  "dlsym failed: can't find '%s'", sym_init);
  160.         dlm->status = DLMOD_ERROR;
  161.         return;
  162.     }
  163.     dl_init();
  164.     dlm->error[0] = '';
  165.     dlm->status = DLMOD_LOADED;
  166. }
  167. void
  168. dlmod_unload_module(struct dlmod *dlm)
  169. {
  170.     char            sym_deinit[64];
  171.     int             (*dl_deinit) (void);
  172.     if (!dlm || dlm->status != DLMOD_LOADED)
  173.         return;
  174.     snprintf(sym_deinit, sizeof(sym_deinit), "deinit_%s", dlm->name);
  175.     dl_deinit = dlsym(dlm->handle, sym_deinit);
  176.     if (dl_deinit == NULL) {
  177.         snprintf(dlm->error, sizeof(dlm->error),
  178.                  "dlsym failed: can't find '%s'", sym_deinit);
  179.     } else {
  180.         dl_deinit();
  181.     }
  182.     dlclose(dlm->handle);
  183.     dlm->status = DLMOD_UNLOADED;
  184.     DEBUGMSGTL(("dlmod", "Module %s unloadedn", dlm->name));
  185. }
  186. struct dlmod   *
  187. dlmod_get_by_index(int iindex)
  188. {
  189.     struct dlmod   *dlmod;
  190.     for (dlmod = dlmods; dlmod; dlmod = dlmod->next)
  191.         if (dlmod->index == iindex)
  192.             return dlmod;
  193.     return NULL;
  194. }
  195. static void
  196. dlmod_parse_config(const char *token, char *cptr)
  197. {
  198.     char           *dlm_name, *dlm_path;
  199.     struct dlmod   *dlm;
  200.     char           *st;
  201.     if (cptr == NULL) {
  202.         config_perror("Bad dlmod line");
  203.         return;
  204.     }
  205.     /*
  206.      * remove comments 
  207.      */
  208.     *(cptr + strcspn(cptr, "#;rn")) = '';
  209.     dlm = dlmod_create_module();
  210.     if (!dlm)
  211.         return;
  212.     /*
  213.      * dynamic module name 
  214.      */
  215.     dlm_name = strtok_r(cptr, "t ", &st);
  216.     if (dlm_name == NULL) {
  217.         config_perror("Bad dlmod line");
  218.         dlmod_delete_module(dlm);
  219.         return;
  220.     }
  221.     strncpy(dlm->name, dlm_name, sizeof(dlm->name));
  222.     /*
  223.      * dynamic module path 
  224.      */
  225.     dlm_path = strtok_r(NULL, "t ", &st);
  226.     if (dlm_path)
  227.         strncpy(dlm->path, dlm_path, sizeof(dlm->path));
  228.     else
  229.         strncpy(dlm->path, dlm_name, sizeof(dlm->path));
  230.     dlmod_load_module(dlm);
  231.     if (dlm->status == DLMOD_ERROR)
  232.         snmp_log(LOG_ERR, "%sn", dlm->error);
  233. }
  234. static void
  235. dlmod_free_config(void)
  236. {
  237.     struct dlmod   *dtmp, *dtmp2;
  238.     for (dtmp = dlmods; dtmp != NULL;) {
  239.         dtmp2 = dtmp;
  240.         dtmp = dtmp->next;
  241.         dlmod_unload_module(dtmp2);
  242.         free(dtmp2);
  243.     }
  244.     dlmods = NULL;
  245. }
  246. /*
  247.  * header_dlmod(...
  248.  * Arguments:
  249.  * vp     IN      - pointer to variable entry that points here
  250.  * name    IN/OUT  - IN/name requested, OUT/name found
  251.  * length  IN/OUT  - length of IN/OUT oid's 
  252.  * exact   IN      - TRUE if an exact match was requested
  253.  * var_len OUT     - length of variable or 0 if function returned
  254.  * write_method
  255.  */
  256. static int
  257. header_dlmod(struct variable *vp,
  258.              oid * name,
  259.              size_t * length,
  260.              int exact, size_t * var_len, WriteMethod ** write_method)
  261. {
  262. #define DLMOD_NAME_LENGTH 10
  263.     oid             newname[MAX_OID_LEN];
  264.     int             result;
  265.     memcpy((char *) newname, (char *) vp->name,
  266.            (int) vp->namelen * sizeof(oid));
  267.     newname[DLMOD_NAME_LENGTH] = 0;
  268.     result =
  269.         snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
  270.     if ((exact && (result != 0)) || (!exact && (result >= 0))) {
  271.         return MATCH_FAILED;
  272.     }
  273.     memcpy((char *) name, (char *) newname,
  274.            ((int) vp->namelen + 1) * sizeof(oid));
  275.     *length = vp->namelen + 1;
  276.     *write_method = 0;
  277.     *var_len = sizeof(long);    /* default to 'long' results */
  278.     return MATCH_SUCCEEDED;
  279. }
  280. u_char         *
  281. var_dlmod(struct variable * vp,
  282.           oid * name,
  283.           size_t * length,
  284.           int exact, size_t * var_len, WriteMethod ** write_method)
  285. {
  286.     /*
  287.      * variables we may use later 
  288.      */
  289.     *write_method = 0;          /* assume it isnt writable for the time being */
  290.     *var_len = sizeof(int);     /* assume an integer and change later
  291.                                  * if not */
  292.     if (header_dlmod(vp, name, length, exact,
  293.                      var_len, write_method) == MATCH_FAILED)
  294.         return 0;
  295.     /*
  296.      * this is where we do the value assignments for the mib results. 
  297.      */
  298.     switch (vp->magic) {
  299.     case DLMODNEXTINDEX:
  300.         long_return = dlmod_next_index;
  301.         return (unsigned char *) &long_return;
  302.     default:
  303.         DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmodn",
  304.                     vp->magic));
  305.     }
  306.     return 0;
  307. }
  308. /*
  309.  * header_dlmodEntry(...
  310.  * Arguments:
  311.  * vp     IN      - pointer to variable entry that points here
  312.  * name    IN/OUT  - IN/name requested, OUT/name found
  313.  * length  IN/OUT  - length of IN/OUT oid's 
  314.  * exact   IN      - TRUE if an exact match was requested
  315.  * var_len OUT     - length of variable or 0 if function returned
  316.  * write_method
  317.  * 
  318.  */
  319. static struct dlmod *
  320. header_dlmodEntry(struct variable *vp,
  321.                   oid * name,
  322.                   size_t * length,
  323.                   int exact, size_t * var_len, WriteMethod ** write_method)
  324. {
  325. #define DLMODENTRY_NAME_LENGTH 12
  326.     oid             newname[MAX_OID_LEN];
  327.     int             result;
  328.     struct dlmod   *dlm = 0;
  329.     int             dlmod_index;
  330.     memcpy((char *) newname, (char *) vp->name,
  331.            (int) vp->namelen * sizeof(oid));
  332.     *write_method = 0;
  333.     for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++) {
  334.         dlm = dlmod_get_by_index(dlmod_index);
  335.         DEBUGMSGTL(("dlmod", "dlmodEntry dlm: %p dlmod_index: %dn",
  336.                     dlm, dlmod_index));
  337.         if (dlm) {
  338.             newname[12] = dlmod_index;
  339.             result = snmp_oid_compare(name, *length, newname,
  340.                                       (int) vp->namelen + 1);
  341.             if ((exact && (result == 0)) || (!exact && (result < 0)))
  342.                 break;
  343.         }
  344.     }
  345.     if (dlmod_index >= dlmod_next_index) {
  346.         if (dlmod_index == dlmod_next_index &&
  347.             exact && vp->magic == DLMODSTATUS)
  348.             *write_method = write_dlmodStatus;
  349.         return NULL;
  350.     }
  351.     memcpy((char *) name, (char *) newname,
  352.            ((int) vp->namelen + 1) * sizeof(oid));
  353.     *length = vp->namelen + 1;
  354.     *var_len = sizeof(long);
  355.     return dlm;
  356. }
  357. u_char         *
  358. var_dlmodEntry(struct variable * vp,
  359.                oid * name,
  360.                size_t * length,
  361.                int exact, size_t * var_len, WriteMethod ** write_method)
  362. {
  363.     /*
  364.      * variables we may use later 
  365.      */
  366.     struct dlmod   *dlm;
  367.     *var_len = sizeof(int);     /* assume an integer and change later
  368.                                  * if not */
  369.     dlm =
  370.         header_dlmodEntry(vp, name, length, exact, var_len, write_method);
  371.     if (dlm == NULL)
  372.         return 0;
  373.     /*
  374.      * this is where we do the value assignments for the mib results. 
  375.      */
  376.     switch (vp->magic) {
  377.     case DLMODNAME:
  378.         *write_method = write_dlmodName;
  379.         *var_len = strlen(dlm->name);
  380.         return (unsigned char *) dlm->name;
  381.     case DLMODPATH:
  382.         *write_method = write_dlmodPath;
  383.         *var_len = strlen(dlm->path);
  384.         return (unsigned char *) dlm->path;
  385.     case DLMODERROR:
  386.         *var_len = strlen(dlm->error);
  387.         return (unsigned char *) dlm->error;
  388.     case DLMODSTATUS:
  389.         *write_method = write_dlmodStatus;
  390.         long_return = dlm->status;
  391.         return (unsigned char *) &long_return;
  392.     default:
  393.         DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmodEntryn",
  394.                     vp->magic));
  395.     }
  396.     return 0;
  397. }
  398. int
  399. write_dlmodName(int action,
  400.                 u_char * var_val,
  401.                 u_char var_val_type,
  402.                 size_t var_val_len,
  403.                 u_char * statP, oid * name, size_t name_len)
  404. {
  405.     static struct dlmod *dlm;
  406.     if (var_val_type != ASN_OCTET_STR) {
  407.         snmp_log(LOG_ERR, "write to dlmodName not ASN_OCTET_STRn");
  408.         return SNMP_ERR_WRONGTYPE;
  409.     }
  410.     if (var_val_len > sizeof(dlm->name)) {
  411.         snmp_log(LOG_ERR, "write to dlmodName: bad lengthn");
  412.         return SNMP_ERR_WRONGLENGTH;
  413.     }
  414.     if (action == COMMIT) {
  415.         dlm = dlmod_get_by_index(name[12]);
  416.         if (!dlm || dlm->status == DLMOD_LOADED)
  417.             return SNMP_ERR_RESOURCEUNAVAILABLE;
  418.         strncpy(dlm->name, (const char *) var_val, var_val_len);
  419.         dlm->name[var_val_len] = 0;
  420.     }
  421.     return SNMP_ERR_NOERROR;
  422. }
  423. int
  424. write_dlmodPath(int action,
  425.                 u_char * var_val,
  426.                 u_char var_val_type,
  427.                 size_t var_val_len,
  428.                 u_char * statP, oid * name, size_t name_len)
  429. {
  430.     static struct dlmod *dlm;
  431.     if (var_val_type != ASN_OCTET_STR) {
  432.         snmp_log(LOG_ERR, "write to dlmodPath not ASN_OCTET_STRn");
  433.         return SNMP_ERR_WRONGTYPE;
  434.     }
  435.     if (var_val_len > sizeof(dlm->path)) {
  436.         snmp_log(LOG_ERR, "write to dlmodPath: bad lengthn");
  437.         return SNMP_ERR_WRONGLENGTH;
  438.     }
  439.     if (action == COMMIT) {
  440.         dlm = dlmod_get_by_index(name[12]);
  441.         if (!dlm || dlm->status == DLMOD_LOADED)
  442.             return SNMP_ERR_RESOURCEUNAVAILABLE;
  443.         strncpy(dlm->path, (const char *) var_val, var_val_len);
  444.         dlm->path[var_val_len] = 0;
  445.     }
  446.     return SNMP_ERR_NOERROR;
  447. }
  448. int
  449. write_dlmodStatus(int action,
  450.                   u_char * var_val,
  451.                   u_char var_val_type,
  452.                   size_t var_val_len,
  453.                   u_char * statP, oid * name, size_t name_len)
  454. {
  455.     /*
  456.      * variables we may use later 
  457.      */
  458.     struct dlmod   *dlm;
  459.     if (var_val_type != ASN_INTEGER) {
  460.         snmp_log(LOG_ERR, "write to dlmodStatus not ASN_INTEGERn");
  461.         return SNMP_ERR_WRONGTYPE;
  462.     }
  463.     if (var_val_len > sizeof(long)) {
  464.         snmp_log(LOG_ERR, "write to dlmodStatus: bad lengthn");
  465.         return SNMP_ERR_WRONGLENGTH;
  466.     }
  467.     if (action == COMMIT) {
  468.         /*
  469.          * object identifier in form .1.3.6.1.4.1.2021.13.14.2.1.4.x 
  470.          * where X is index with offset 12 
  471.          */
  472.         dlm = dlmod_get_by_index(name[12]);
  473.         switch (*((long *) var_val)) {
  474.         case DLMOD_CREATE:
  475.             if (dlm || (name[12] != dlmod_next_index))
  476.                 return SNMP_ERR_RESOURCEUNAVAILABLE;
  477.             dlm = dlmod_create_module();
  478.             if (!dlm)
  479.                 return SNMP_ERR_RESOURCEUNAVAILABLE;
  480.             break;
  481.         case DLMOD_LOAD:
  482.             if (!dlm || dlm->status == DLMOD_LOADED)
  483.                 return SNMP_ERR_RESOURCEUNAVAILABLE;
  484.             dlmod_load_module(dlm);
  485.             break;
  486.         case DLMOD_UNLOAD:
  487.             if (!dlm || dlm->status != DLMOD_LOADED)
  488.                 return SNMP_ERR_RESOURCEUNAVAILABLE;
  489.             dlmod_unload_module(dlm);
  490.             break;
  491.         case DLMOD_DELETE:
  492.             if (!dlm || dlm->status == DLMOD_LOADED)
  493.                 return SNMP_ERR_RESOURCEUNAVAILABLE;
  494.             dlmod_delete_module(dlm);
  495.             break;
  496.         default:
  497.             return SNMP_ERR_WRONGVALUE;
  498.         }
  499.     }
  500.     return SNMP_ERR_NOERROR;
  501. }
  502. #else                           /* no dlopen support */
  503. void
  504. init_dlmod(void)
  505. {
  506.     DEBUGMSGTL(("dlmod",
  507.                 "Dynamic modules not support on this platformn"));
  508. }
  509. #endif