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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * header complex:  More complex storage and data sorting for mib modules 
  3.  */
  4. #include <net-snmp/net-snmp-config.h>
  5. #include <sys/types.h>
  6. #if HAVE_WINSOCK_H
  7. #include <winsock.h>
  8. #endif
  9. #if HAVE_STDLIB_H
  10. #include <stdlib.h>
  11. #endif
  12. #if HAVE_STRING_H
  13. #include <string.h>
  14. #else
  15. #include <strings.h>
  16. #endif
  17. #include <net-snmp/net-snmp-includes.h>
  18. #include <net-snmp/agent/net-snmp-agent-includes.h>
  19. #include "header_complex.h"
  20. int
  21. header_complex_generate_varoid(netsnmp_variable_list * var)
  22. {
  23.     int             i;
  24.     if (var->name == NULL) {
  25.         /*
  26.          * assume cached value is correct 
  27.          */
  28.         switch (var->type) {
  29.         case ASN_INTEGER:
  30.         case ASN_COUNTER:
  31.         case ASN_GAUGE:
  32.         case ASN_TIMETICKS:
  33.             var->name_length = 1;
  34.             var->name = (oid *) malloc(sizeof(oid));
  35.             if (var->name == NULL)
  36.                 return SNMPERR_GENERR;
  37.             var->name[0] = *(var->val.integer);
  38.             break;
  39.         case ASN_PRIV_IMPLIED_OBJECT_ID:
  40.             var->name_length = var->val_len / sizeof(oid);
  41.             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
  42.             if (var->name == NULL)
  43.                 return SNMPERR_GENERR;
  44.             for (i = 0; i < (int) var->name_length; i++)
  45.                 var->name[i] = var->val.objid[i];
  46.             break;
  47.         case ASN_OBJECT_ID:
  48.             var->name_length = var->val_len / sizeof(oid) + 1;
  49.             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
  50.             if (var->name == NULL)
  51.                 return SNMPERR_GENERR;
  52.             var->name[0] = var->name_length - 1;
  53.             for (i = 0; i < (int) var->name_length - 1; i++)
  54.                 var->name[i + 1] = var->val.objid[i];
  55.             break;
  56.         case ASN_PRIV_IMPLIED_OCTET_STR:
  57.             var->name_length = var->val_len;
  58.             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
  59.             if (var->name == NULL)
  60.                 return SNMPERR_GENERR;
  61.             for (i = 0; i < (int) var->val_len; i++)
  62.                 var->name[i] = (oid) var->val.string[i];
  63.             break;
  64.         case ASN_OPAQUE:
  65.         case ASN_OCTET_STR:
  66.             var->name_length = var->val_len + 1;
  67.             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
  68.             if (var->name == NULL)
  69.                 return SNMPERR_GENERR;
  70.             var->name[0] = (oid) var->val_len;
  71.             for (i = 0; i < (int) var->val_len; i++)
  72.                 var->name[i + 1] = (oid) var->val.string[i];
  73.             break;
  74.         default:
  75.             DEBUGMSGTL(("header_complex_generate_varoid",
  76.                         "invalid asn type: %dn", var->type));
  77.             return SNMPERR_GENERR;
  78.         }
  79.     }
  80.     if (var->name_length > MAX_OID_LEN) {
  81.         DEBUGMSGTL(("header_complex_generate_varoid",
  82.                     "Something terribly wrong, namelen = %dn",
  83.                     var->name_length));
  84.         return SNMPERR_GENERR;
  85.     }
  86.     return SNMPERR_SUCCESS;
  87. }
  88. /*
  89.  * header_complex_parse_oid(): parses an index to the usmTable to
  90.  * break it down into a engineID component and a name component.
  91.  * The results are stored in the data pointer, as a varbindlist:
  92.  * 
  93.  * 
  94.  * returns 1 if an error is encountered, or 0 if successful.
  95.  */
  96. int
  97. header_complex_parse_oid(oid * oidIndex, size_t oidLen,
  98.                          netsnmp_variable_list * data)
  99. {
  100.     netsnmp_variable_list *var = data;
  101.     int             i, itmp;
  102.     while (var && oidLen > 0) {
  103.         switch (var->type) {
  104.         case ASN_INTEGER:
  105.         case ASN_COUNTER:
  106.         case ASN_GAUGE:
  107.         case ASN_TIMETICKS:
  108.             var->val.integer = (long *) calloc(1, sizeof(long));
  109.             if (var->val.string == NULL)
  110.                 return SNMPERR_GENERR;
  111.             *var->val.integer = (long) *oidIndex++;
  112.             var->val_len = sizeof(long);
  113.             oidLen--;
  114.             DEBUGMSGTL(("header_complex_parse_oid",
  115.                         "Parsed int(%d): %dn", var->type,
  116.                         *var->val.integer));
  117.             break;
  118.         case ASN_OBJECT_ID:
  119.         case ASN_PRIV_IMPLIED_OBJECT_ID:
  120.             if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
  121.                 itmp = oidLen;
  122.             } else {
  123.                 itmp = (long) *oidIndex++;
  124.                 oidLen--;
  125.                 if (itmp > (int) oidLen)
  126.                     return SNMPERR_GENERR;
  127.             }
  128.             if (itmp == 0)
  129.                 break;          /* zero length strings shouldn't malloc */
  130.             var->val_len = itmp * sizeof(oid);
  131.             var->val.objid = (oid *) calloc(1, var->val_len);
  132.             if (var->val.objid == NULL)
  133.                 return SNMPERR_GENERR;
  134.             for (i = 0; i < itmp; i++)
  135.                 var->val.objid[i] = (u_char) * oidIndex++;
  136.             oidLen -= itmp;
  137.             DEBUGMSGTL(("header_complex_parse_oid", "Parsed oid: "));
  138.             DEBUGMSGOID(("header_complex_parse_oid", var->val.objid,
  139.                          var->val_len / sizeof(oid)));
  140.             DEBUGMSG(("header_complex_parse_oid", "n"));
  141.             break;
  142.         case ASN_OPAQUE:
  143.         case ASN_OCTET_STR:
  144.         case ASN_PRIV_IMPLIED_OCTET_STR:
  145.             if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
  146.                 itmp = oidLen;
  147.             } else {
  148.                 itmp = (long) *oidIndex++;
  149.                 oidLen--;
  150.                 if (itmp > (int) oidLen)
  151.                     return SNMPERR_GENERR;
  152.             }
  153.             if (itmp == 0)
  154.                 break;          /* zero length strings shouldn't malloc */
  155.             /*
  156.              * malloc by size+1 to allow a null to be appended. 
  157.              */
  158.             var->val_len = itmp;
  159.             var->val.string = (u_char *) calloc(1, itmp + 1);
  160.             if (var->val.string == NULL)
  161.                 return SNMPERR_GENERR;
  162.             for (i = 0; i < itmp; i++)
  163.                 var->val.string[i] = (u_char) * oidIndex++;
  164.             var->val.string[itmp] = '';
  165.             oidLen -= itmp;
  166.             DEBUGMSGTL(("header_complex_parse_oid",
  167.                         "Parsed str(%d): %sn", var->type,
  168.                         var->val.string));
  169.             break;
  170.         default:
  171.             DEBUGMSGTL(("header_complex_parse_oid",
  172.                         "invalid asn type: %dn", var->type));
  173.             return SNMPERR_GENERR;
  174.         }
  175.         var = var->next_variable;
  176.     }
  177.     if (var != NULL || oidLen > 0)
  178.         return SNMPERR_GENERR;
  179.     return SNMPERR_SUCCESS;
  180. }
  181. void
  182. header_complex_generate_oid(oid * name, /* out */
  183.                             size_t * length,    /* out */
  184.                             oid * prefix,
  185.                             size_t prefix_len,
  186.                             netsnmp_variable_list * data)
  187. {
  188.     oid            *oidptr;
  189.     netsnmp_variable_list *var;
  190.     if (prefix) {
  191.         memcpy(name, prefix, prefix_len * sizeof(oid));
  192.         oidptr = (name + (prefix_len));
  193.         *length = prefix_len;
  194.     } else {
  195.         oidptr = name;
  196.         *length = 0;
  197.     }
  198.     for (var = data; var != NULL; var = var->next_variable) {
  199.         header_complex_generate_varoid(var);
  200.         memcpy(oidptr, var->name, sizeof(oid) * var->name_length);
  201.         oidptr = oidptr + var->name_length;
  202.         *length += var->name_length;
  203.     }
  204.     DEBUGMSGTL(("header_complex_generate_oid", "generated: "));
  205.     DEBUGMSGOID(("header_complex_generate_oid", name, *length));
  206.     DEBUGMSG(("header_complex_generate_oid", "n"));
  207. }
  208. /*
  209.  * finds the data in "datalist" stored at "index" 
  210.  */
  211. void           *
  212. header_complex_get(struct header_complex_index *datalist,
  213.                    netsnmp_variable_list * index)
  214. {
  215.     oid             searchfor[MAX_OID_LEN];
  216.     size_t          searchfor_len;
  217.     header_complex_generate_oid(searchfor,      /* out */
  218.                                 &searchfor_len, /* out */
  219.                                 NULL, 0, index);
  220.     return header_complex_get_from_oid(datalist, searchfor, searchfor_len);
  221. }
  222. void           *
  223. header_complex_get_from_oid(struct header_complex_index *datalist,
  224.                             oid * searchfor, size_t searchfor_len)
  225. {
  226.     struct header_complex_index *nptr;
  227.     for (nptr = datalist; nptr != NULL; nptr = nptr->next) {
  228.         if (netsnmp_oid_equals(searchfor, searchfor_len,
  229.                              nptr->name, nptr->namelen) == 0)
  230.             return nptr->data;
  231.     }
  232.     return NULL;
  233. }
  234. void           *
  235. header_complex(struct header_complex_index *datalist,
  236.                struct variable *vp,
  237.                oid * name,
  238.                size_t * length,
  239.                int exact, size_t * var_len, WriteMethod ** write_method)
  240. {
  241.     struct header_complex_index *nptr, *found = NULL;
  242.     oid             indexOid[MAX_OID_LEN];
  243.     size_t          len;
  244.     int             result;
  245.     /*
  246.      * set up some nice defaults for the user 
  247.      */
  248.     if (write_method)
  249.         *write_method = NULL;
  250.     if (var_len)
  251.         *var_len = sizeof(long);
  252.     for (nptr = datalist; nptr != NULL && found == NULL; nptr = nptr->next) {
  253.         if (vp) {
  254.             memcpy(indexOid, vp->name, vp->namelen * sizeof(oid));
  255.             memcpy(indexOid + vp->namelen, nptr->name,
  256.                    nptr->namelen * sizeof(oid));
  257.             len = vp->namelen + nptr->namelen;
  258.         } else {
  259.             memcpy(indexOid, nptr->name, nptr->namelen * sizeof(oid));
  260.             len = nptr->namelen;
  261.         }
  262.         result = snmp_oid_compare(name, *length, indexOid, len);
  263.         DEBUGMSGTL(("header_complex", "Checking: "));
  264.         DEBUGMSGOID(("header_complex", indexOid, len));
  265.         DEBUGMSG(("header_complex", "n"));
  266.         if (exact) {
  267.             if (result == 0) {
  268.                 found = nptr;
  269.             }
  270.         } else {
  271.             if (result == 0) {
  272.                 /*
  273.                  * found an exact match.  Need the next one for !exact 
  274.                  */
  275.                 if (nptr->next)
  276.                     found = nptr->next;
  277.             } else if (result == -1) {
  278.                 found = nptr;
  279.             }
  280.         }
  281.     }
  282.     if (found) {
  283.         if (vp) {
  284.             memcpy(name, vp->name, vp->namelen * sizeof(oid));
  285.             memcpy(name + vp->namelen, found->name,
  286.                    found->namelen * sizeof(oid));
  287.             *length = vp->namelen + found->namelen;
  288.         } else {
  289.             memcpy(name, found->name, found->namelen * sizeof(oid));
  290.             *length = found->namelen;
  291.         }
  292.         return found->data;
  293.     }
  294.     return NULL;
  295. }
  296. struct header_complex_index *
  297. header_complex_add_data(struct header_complex_index **thedata,
  298.                         netsnmp_variable_list * var, void *data)
  299. {
  300.     oid             newoid[MAX_OID_LEN];
  301.     size_t          newoid_len;
  302.     struct header_complex_index *ret;
  303.     if (thedata == NULL || var == NULL || data == NULL)
  304.         return NULL;
  305.     header_complex_generate_oid(newoid, &newoid_len, NULL, 0, var);
  306.     ret =
  307.         header_complex_add_data_by_oid(thedata, newoid, newoid_len, data);
  308.     /*
  309.      * free the variable list, but not the enclosed data!  it's not ours! 
  310.      */
  311.     snmp_free_varbind(var);
  312.     return (ret);
  313. }
  314. struct header_complex_index *
  315. header_complex_add_data_by_oid(struct header_complex_index **thedata,
  316.                                oid * newoid, size_t newoid_len, void *data)
  317. {
  318.     struct header_complex_index *hciptrn, *hciptrp, *ourself;
  319.     if (thedata == NULL || newoid == NULL || data == NULL)
  320.         return NULL;
  321.     for (hciptrn = *thedata, hciptrp = NULL;
  322.          hciptrn != NULL; hciptrp = hciptrn, hciptrn = hciptrn->next)
  323.         /*
  324.          * XXX: check for == and error (overlapping table entries) 
  325.          */
  326.         if (snmp_oid_compare
  327.             (hciptrn->name, hciptrn->namelen, newoid, newoid_len)
  328.             > 0)
  329.             break;
  330.     /*
  331.      * nptr should now point to the spot that we need to add ourselves
  332.      * in front of, and pptr should be our new 'prev'. 
  333.      */
  334.     /*
  335.      * create ourselves 
  336.      */
  337.     ourself = (struct header_complex_index *)
  338.         SNMP_MALLOC_STRUCT(header_complex_index);
  339.     /*
  340.      * change our pointers 
  341.      */
  342.     ourself->prev = hciptrp;
  343.     ourself->next = hciptrn;
  344.     if (ourself->next)
  345.         ourself->next->prev = ourself;
  346.     if (ourself->prev)
  347.         ourself->prev->next = ourself;
  348.     ourself->data = data;
  349.     ourself->name = snmp_duplicate_objid(newoid, newoid_len);
  350.     ourself->namelen = newoid_len;
  351.     /*
  352.      * rewind to the head of the list and return it (since the new head
  353.      * could be us, we need to notify the above routine who the head now is. 
  354.      */
  355.     for (hciptrp = ourself; hciptrp->prev != NULL;
  356.          hciptrp = hciptrp->prev);
  357.     *thedata = hciptrp;
  358.     DEBUGMSGTL(("header_complex_add_data", "adding something...n"));
  359.     return hciptrp;
  360. }
  361. /*
  362.  * extracts an entry from the storage space (removing it from future
  363.  * accesses) and returns the data stored there
  364.  * 
  365.  * Modifies "thetop" pointer as needed (and if present) if were
  366.  * extracting the first node.
  367.  */
  368. void           *
  369. header_complex_extract_entry(struct header_complex_index **thetop,
  370.                              struct header_complex_index *thespot)
  371. {
  372.     struct header_complex_index *hciptrp, *hciptrn;
  373.     void           *retdata = thespot->data;
  374.     if (thespot == NULL) {
  375.         DEBUGMSGTL(("header_complex_extract_entry",
  376.                     "Null pointer asked to be extractedn"));
  377.         return NULL;
  378.     }
  379.     hciptrp = thespot->prev;
  380.     hciptrn = thespot->next;
  381.     if (hciptrp)
  382.         hciptrp->next = hciptrn;
  383.     else if (thetop)
  384.         *thetop = hciptrn;
  385.     if (hciptrn)
  386.         hciptrn->prev = hciptrp;
  387.     if (thespot->name)
  388.         free(thespot->name);
  389.     free(thespot);
  390.     return retdata;
  391. }
  392. /*
  393.  * wipe out a single entry 
  394.  */
  395. void
  396. header_complex_free_entry(struct header_complex_index *theentry,
  397.                           HeaderComplexCleaner * cleaner)
  398. {
  399.     void           *data;
  400.     data = header_complex_extract_entry(NULL, theentry);
  401.     (*cleaner) (data);
  402. }
  403. /*
  404.  * completely wipe out all entries in our data store 
  405.  */
  406. void
  407. header_complex_free_all(struct header_complex_index *thestuff,
  408.                         HeaderComplexCleaner * cleaner)
  409. {
  410.     struct header_complex_index *hciptr, *hciptrn;
  411.     for (hciptr = thestuff; hciptr != NULL; hciptr = hciptrn) {
  412.         hciptrn = hciptr->next; /* need to extract this before deleting it */
  413.         header_complex_free_entry(hciptr, cleaner);
  414.     }
  415. }
  416. struct header_complex_index *
  417. header_complex_find_entry(struct header_complex_index *thestuff,
  418.                           void *theentry)
  419. {
  420.     struct header_complex_index *hciptr;
  421.     for (hciptr = thestuff; hciptr != NULL && hciptr->data != theentry;
  422.          hciptr = hciptr->next);
  423.     return hciptr;
  424. }
  425. #ifdef TESTING
  426. void
  427. header_complex_dump(struct header_complex_index *thestuff)
  428. {
  429.     struct header_complex_index *hciptr;
  430.     oid             oidsave[MAX_OID_LEN];
  431.     size_t          len;
  432.     for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
  433.         DEBUGMSGTL(("header_complex_dump", "var:  "));
  434.         header_complex_generate_oid(oidsave, &len, NULL, 0, hciptr->);
  435.         DEBUGMSGOID(("header_complex_dump", oidsave, len));
  436.         DEBUGMSG(("header_complex_dump", "n"));
  437.     }
  438. }
  439. main()
  440. {
  441.     oid             oidsave[MAX_OID_LEN];
  442.     int             len = MAX_OID_LEN, len2;
  443.     netsnmp_variable_list *vars;
  444.     long            ltmp = 4242, ltmp2 = 88, ltmp3 = 1, ltmp4 = 4200;
  445.     oid             ourprefix[] = { 1, 2, 3, 4 };
  446.     oid             testparse[] = { 4, 116, 101, 115, 116, 4200 };
  447.     int             ret;
  448.     char           *string = "wes", *string2 = "dawn", *string3 = "test";
  449.     struct header_complex_index *thestorage = NULL;
  450.     debug_register_tokens("header_complex");
  451.     snmp_set_do_debugging(1);
  452.     vars = NULL;
  453.     len2 = sizeof(ltmp);
  454.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp,
  455.                               len2);
  456.     header_complex_add_data(&thestorage, vars, ourprefix);
  457.     vars = NULL;
  458.     len2 = strlen(string);
  459.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string, len2);
  460.     header_complex_add_data(&thestorage, vars, ourprefix);
  461.     vars = NULL;
  462.     len2 = sizeof(ltmp2);
  463.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp2,
  464.                               len2);
  465.     header_complex_add_data(&thestorage, vars, ourprefix);
  466.     vars = NULL;
  467.     len2 = strlen(string2);
  468.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string2,
  469.                               len2);
  470.     header_complex_add_data(&thestorage, vars, ourprefix);
  471.     vars = NULL;
  472.     len2 = sizeof(ltmp3);
  473.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp3,
  474.                               len2);
  475.     header_complex_add_data(&thestorage, vars, ourprefix);
  476.     vars = NULL;
  477.     len2 = strlen(string3);
  478.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string3,
  479.                               len2);
  480.     len2 = sizeof(ltmp4);
  481.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp4,
  482.                               len2);
  483.     header_complex_add_data(&thestorage, vars, ourprefix);
  484.     header_complex_dump(thestorage);
  485.     vars = NULL;
  486.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);
  487.     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, NULL, 0);
  488.     ret =
  489.         header_complex_parse_oid(testparse,
  490.                                  sizeof(testparse) / sizeof(oid), vars);
  491.     DEBUGMSGTL(("header_complex_test", "parse returned %d...n", ret));
  492. }
  493. #endif