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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *   AgentX utility routines
  3.  */
  4. #include <net-snmp/net-snmp-config.h>
  5. #include <stdio.h>
  6. #include <errno.h>
  7. #if HAVE_STDLIB_H
  8. #include <stdlib.h>
  9. #endif
  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 <sys/types.h>
  19. #if TIME_WITH_SYS_TIME
  20. # ifdef WIN32
  21. #  include <sys/timeb.h>
  22. # else
  23. #  include <sys/time.h>
  24. # endif
  25. # include <time.h>
  26. #else
  27. # if HAVE_SYS_TIME_H
  28. #  include <sys/time.h>
  29. # else
  30. #  include <time.h>
  31. # endif
  32. #endif
  33. #if HAVE_NETINET_IN_H
  34. #include <netinet/in.h>
  35. #endif
  36. #if HAVE_WINSOCK_H
  37. #include <winsock.h>
  38. #endif
  39. #if HAVE_DMALLOC_H
  40. #include <dmalloc.h>
  41. #endif
  42. #include <net-snmp/net-snmp-includes.h>
  43. #include <net-snmp/agent/net-snmp-agent-includes.h>
  44. #include <net-snmp/agent/agent_index.h>
  45. #include "agentx/protocol.h"
  46. #include "agentx/client.h"
  47. #include "agentx/subagent.h"
  48. extern struct timeval starttime;
  49.         /*
  50.          * AgentX handling utility routines
  51.          *
  52.          * Mostly wrappers round, or re-writes of
  53.          *   the SNMP equivalents
  54.          */
  55. int
  56. agentx_synch_input(int op,
  57.                    netsnmp_session * session,
  58.                    int reqid, netsnmp_pdu *pdu, void *magic)
  59. {
  60.     struct synch_state *state = (struct synch_state *) magic;
  61.     struct timeval  now, diff;
  62.     if (reqid != state->reqid) {
  63.         return handle_agentx_packet(op, session, reqid, pdu, magic);
  64.     }
  65.     DEBUGMSGTL(("agentx/subagent", "synching input, op 0x%02xn", op));
  66.     state->waiting = 0;
  67.     if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
  68.         if (pdu->command == AGENTX_MSG_RESPONSE) {
  69.             state->pdu = snmp_clone_pdu(pdu);
  70.             state->status = STAT_SUCCESS;
  71.             session->s_snmp_errno = SNMPERR_SUCCESS;
  72.             /*
  73.              * Synchronise sysUpTime with the master agent
  74.              */
  75.             gettimeofday(&now, NULL);
  76.             now.tv_sec--;
  77.             now.tv_usec += 1000000L;
  78.             diff.tv_sec = pdu->time / 100;
  79.             diff.tv_usec = (pdu->time - (diff.tv_sec * 100)) * 10000;
  80.             starttime.tv_sec = now.tv_sec - diff.tv_sec;
  81.             starttime.tv_usec = now.tv_usec - diff.tv_usec;
  82.             if (starttime.tv_usec > 1000000L) {
  83.                 starttime.tv_usec -= 1000000L;
  84.                 starttime.tv_sec++;
  85.             }
  86.         }
  87.     } else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) {
  88.         state->pdu = NULL;
  89.         state->status = STAT_TIMEOUT;
  90.         session->s_snmp_errno = SNMPERR_TIMEOUT;
  91.     } else if (op == NETSNMP_CALLBACK_OP_DISCONNECT) {
  92.         return handle_agentx_packet(op, session, reqid, pdu, magic);
  93.     }
  94.     return 1;
  95. }
  96. int
  97. agentx_synch_response(netsnmp_session * ss, netsnmp_pdu *pdu,
  98.                       netsnmp_pdu **response)
  99. {
  100.     return snmp_synch_response_cb(ss, pdu, response, agentx_synch_input);
  101. }
  102.         /*
  103.          * AgentX PofE convenience functions
  104.          */
  105. int
  106. agentx_open_session(netsnmp_session * ss)
  107. {
  108.     netsnmp_pdu    *pdu, *response;
  109.     extern oid      version_sysoid[];
  110.     extern int      version_sysoid_len;
  111.     DEBUGMSGTL(("agentx/subagent", "opening session n"));
  112.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  113.         return 0;
  114.     }
  115.     pdu = snmp_pdu_create(AGENTX_MSG_OPEN);
  116.     if (pdu == NULL)
  117.         return 0;
  118.     pdu->time = 0;
  119.     snmp_add_var(pdu, version_sysoid, version_sysoid_len,
  120.  's', "Net-SNMP AgentX sub-agent");
  121.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  122.         return 0;
  123.     if (response->errstat != SNMP_ERR_NOERROR) {
  124.         snmp_free_pdu(response);
  125.         return 0;
  126.     }
  127.     ss->sessid = response->sessid;
  128.     snmp_free_pdu(response);
  129.     DEBUGMSGTL(("agentx/subagent", "open n"));
  130.     return 1;
  131. }
  132. int
  133. agentx_close_session(netsnmp_session * ss, int why)
  134. {
  135.     netsnmp_pdu    *pdu, *response;
  136.     DEBUGMSGTL(("agentx/subagent", "closing sessionn"));
  137.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  138.         return 0;
  139.     }
  140.     pdu = snmp_pdu_create(AGENTX_MSG_CLOSE);
  141.     if (pdu == NULL)
  142.         return 0;
  143.     pdu->time = 0;
  144.     pdu->errstat = why;
  145.     pdu->sessid = ss->sessid;
  146.     (void) agentx_synch_response(ss, pdu, &response);
  147.     snmp_free_pdu(response);
  148.     DEBUGMSGTL(("agentx/subagent", "closedn"));
  149.     return 1;
  150. }
  151. int
  152. agentx_register(netsnmp_session * ss, oid start[], size_t startlen,
  153.                 int priority, int range_subid, oid range_ubound,
  154.                 int timeout, u_char flags, const char *contextName)
  155. {
  156.     netsnmp_pdu    *pdu, *response;
  157.     DEBUGMSGTL(("agentx/subagent", "registering: "));
  158.     DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
  159.                       range_ubound));
  160.     DEBUGMSG(("agentx/subagent", "n"));
  161.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  162.         return 0;
  163.     }
  164.     pdu = snmp_pdu_create(AGENTX_MSG_REGISTER);
  165.     if (pdu == NULL) {
  166.         return 0;
  167.     }
  168.     pdu->time = timeout;
  169.     pdu->priority = priority;
  170.     pdu->sessid = ss->sessid;
  171.     pdu->range_subid = range_subid;
  172.     if (contextName) {
  173.         pdu->flags |= AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT;
  174.         pdu->community = strdup(contextName);
  175.         pdu->community_len = strlen(contextName);
  176.     }
  177.     if (flags & FULLY_QUALIFIED_INSTANCE) {
  178.         pdu->flags |= AGENTX_MSG_FLAG_INSTANCE_REGISTER;
  179.     }
  180.     if (range_subid) {
  181.         snmp_pdu_add_variable(pdu, start, startlen, ASN_OBJECT_ID,
  182.                               (u_char *) start, startlen * sizeof(oid));
  183.         pdu->variables->val.objid[range_subid - 1] = range_ubound;
  184.     } else {
  185.         snmp_add_null_var(pdu, start, startlen);
  186.     }
  187.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS) {
  188.         DEBUGMSGTL(("agentx/subagent", "registering failed!n"));
  189.         return 0;
  190.     }
  191.     if (response->errstat != SNMP_ERR_NOERROR) {
  192.         snmp_log(LOG_ERR,"registering pdu failed: %ld!n", response->errstat);
  193.         snmp_free_pdu(response);
  194.         return 0;
  195.     }
  196.     snmp_free_pdu(response);
  197.     DEBUGMSGTL(("agentx/subagent", "registeredn"));
  198.     return 1;
  199. }
  200. int
  201. agentx_unregister(netsnmp_session * ss, oid start[], size_t startlen,
  202.                   int priority, int range_subid, oid range_ubound,
  203.                   const char *contextName)
  204. {
  205.     netsnmp_pdu    *pdu, *response;
  206.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  207.         return 0;
  208.     }
  209.     DEBUGMSGTL(("agentx/subagent", "unregistering: "));
  210.     DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
  211.                       range_ubound));
  212.     DEBUGMSG(("agentx/subagent", "n"));
  213.     pdu = snmp_pdu_create(AGENTX_MSG_UNREGISTER);
  214.     if (pdu == NULL) {
  215.         return 0;
  216.     }
  217.     pdu->time = 0;
  218.     pdu->priority = priority;
  219.     pdu->sessid = ss->sessid;
  220.     pdu->range_subid = range_subid;
  221.     if (contextName) {
  222.         pdu->flags |= AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT;
  223.         pdu->community = strdup(contextName);
  224.         pdu->community_len = strlen(contextName);
  225.     }
  226.     if (range_subid) {
  227.         snmp_pdu_add_variable(pdu, start, startlen, ASN_OBJECT_ID,
  228.                               (u_char *) start, startlen * sizeof(oid));
  229.         pdu->variables->val.objid[range_subid - 1] = range_ubound;
  230.     } else {
  231.         snmp_add_null_var(pdu, start, startlen);
  232.     }
  233.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  234.         return 0;
  235.     if (response->errstat != SNMP_ERR_NOERROR) {
  236.         snmp_free_pdu(response);
  237.         return 0;
  238.     }
  239.     snmp_free_pdu(response);
  240.     DEBUGMSGTL(("agentx/subagent", "unregisteredn"));
  241.     return 1;
  242. }
  243. netsnmp_variable_list *
  244. agentx_register_index(netsnmp_session * ss,
  245.                       netsnmp_variable_list * varbind, int flags)
  246. {
  247.     netsnmp_pdu    *pdu, *response;
  248.     netsnmp_variable_list *varbind2;
  249.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  250.         return NULL;
  251.     }
  252.     /*
  253.      * Make a copy of the index request varbind
  254.      *    for the AgentX request PDU
  255.      *    (since the pdu structure will be freed)
  256.      */
  257.     varbind2 =
  258.         (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
  259.     if (varbind2 == NULL)
  260.         return NULL;
  261.     if (snmp_clone_var(varbind, varbind2)) {
  262.         snmp_free_varbind(varbind2);
  263.         return NULL;
  264.     }
  265.     if (varbind2->val.string == NULL)
  266.         varbind2->val.string = varbind2->buf;   /* ensure it points somewhere */
  267.     pdu = snmp_pdu_create(AGENTX_MSG_INDEX_ALLOCATE);
  268.     if (pdu == NULL) {
  269.         snmp_free_varbind(varbind2);
  270.         return NULL;
  271.     }
  272.     pdu->time = 0;
  273.     pdu->sessid = ss->sessid;
  274.     if (flags == ALLOCATE_ANY_INDEX)
  275.         pdu->flags |= AGENTX_MSG_FLAG_ANY_INSTANCE;
  276.     if (flags == ALLOCATE_NEW_INDEX)
  277.         pdu->flags |= AGENTX_MSG_FLAG_NEW_INSTANCE;
  278.     /*
  279.      *  Just send a single index request varbind.
  280.      *  Although the AgentX protocol supports
  281.      *    multiple index allocations in a single
  282.      *    request, the model used in the net-snmp agent
  283.      *    doesn't currently take advantage of this.
  284.      *  I believe this is our prerogative - just as
  285.      *    long as the master side Index request handler
  286.      *    can cope with multiple index requests.
  287.      */
  288.     pdu->variables = varbind2;
  289.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  290.         return NULL;
  291.     if (response->errstat != SNMP_ERR_NOERROR) {
  292.         snmp_free_pdu(response);
  293.         return NULL;
  294.     }
  295.     /*
  296.      * Unlink the (single) response varbind to return
  297.      *  to the main driving index request routine.
  298.      *
  299.      * This is a memory leak, as nothing will ever
  300.      *  release this varbind.  If this becomes a problem,
  301.      *  we'll need to keep a list of these here, and
  302.      *  free the memory in the "index release" routine.
  303.      * But the master side never frees these either (by
  304.      *  design, since it still needs them), so expecting
  305.      *  the subagent to is discrimination, pure & simple :-)
  306.      */
  307.     varbind2 = response->variables;
  308.     response->variables = NULL;
  309.     snmp_free_pdu(response);
  310.     return varbind2;
  311. }
  312. int
  313. agentx_unregister_index(netsnmp_session * ss,
  314.                         netsnmp_variable_list * varbind)
  315. {
  316.     netsnmp_pdu    *pdu, *response;
  317.     netsnmp_variable_list *varbind2;
  318.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  319.         return -1;
  320.     }
  321.     /*
  322.      * Make a copy of the index request varbind
  323.      *    for the AgentX request PDU
  324.      *    (since the pdu structure will be freed)
  325.      */
  326.     varbind2 =
  327.         (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
  328.     if (varbind2 == NULL)
  329.         return -1;
  330.     if (snmp_clone_var(varbind, varbind2)) {
  331.         snmp_free_varbind(varbind2);
  332.         return -1;
  333.     }
  334.     pdu = snmp_pdu_create(AGENTX_MSG_INDEX_DEALLOCATE);
  335.     if (pdu == NULL) {
  336.         snmp_free_varbind(varbind2);
  337.         return -1;
  338.     }
  339.     pdu->time = 0;
  340.     pdu->sessid = ss->sessid;
  341.     /*
  342.      *  Just send a single index release varbind.
  343.      *      (as above)
  344.      */
  345.     pdu->variables = varbind2;
  346.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  347.         return -1;
  348.     if (response->errstat != SNMP_ERR_NOERROR) {
  349.         snmp_free_pdu(response);
  350.         return -1;              /* XXX - say why */
  351.     }
  352.     snmp_free_pdu(response);
  353.     return SNMP_ERR_NOERROR;
  354. }
  355. int
  356. agentx_add_agentcaps(netsnmp_session * ss,
  357.                      oid * agent_cap, size_t agent_caplen,
  358.                      const char *descr)
  359. {
  360.     netsnmp_pdu    *pdu, *response;
  361.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  362.         return 0;
  363.     }
  364.     pdu = snmp_pdu_create(AGENTX_MSG_ADD_AGENT_CAPS);
  365.     if (pdu == NULL)
  366.         return 0;
  367.     pdu->time = 0;
  368.     pdu->sessid = ss->sessid;
  369.     snmp_add_var(pdu, agent_cap, agent_caplen, 's', descr);
  370.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  371.         return 0;
  372.     if (response->errstat != SNMP_ERR_NOERROR) {
  373.         snmp_free_pdu(response);
  374.         return 0;
  375.     }
  376.     snmp_free_pdu(response);
  377.     return 1;
  378. }
  379. int
  380. agentx_remove_agentcaps(netsnmp_session * ss,
  381.                         oid * agent_cap, size_t agent_caplen)
  382. {
  383.     netsnmp_pdu    *pdu, *response;
  384.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  385.         return 0;
  386.     }
  387.     pdu = snmp_pdu_create(AGENTX_MSG_REMOVE_AGENT_CAPS);
  388.     if (pdu == NULL)
  389.         return 0;
  390.     pdu->time = 0;
  391.     pdu->sessid = ss->sessid;
  392.     snmp_add_null_var(pdu, agent_cap, agent_caplen);
  393.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  394.         return 0;
  395.     if (response->errstat != SNMP_ERR_NOERROR) {
  396.         snmp_free_pdu(response);
  397.         return 0;
  398.     }
  399.     snmp_free_pdu(response);
  400.     return 1;
  401. }
  402. int
  403. agentx_send_ping(netsnmp_session * ss)
  404. {
  405.     netsnmp_pdu    *pdu, *response;
  406.     if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
  407.         return 0;
  408.     }
  409.     pdu = snmp_pdu_create(AGENTX_MSG_PING);
  410.     if (pdu == NULL)
  411.         return 0;
  412.     pdu->time = 0;
  413.     pdu->sessid = ss->sessid;
  414.     if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
  415.         return 0;
  416.     if (response->errstat != SNMP_ERR_NOERROR) {
  417.         snmp_free_pdu(response);
  418.         return 0;
  419.     }
  420.     snmp_free_pdu(response);
  421.     return 1;
  422. }