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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * snmptrap.c - send snmp traps to a network entity.
  3.  *
  4.  */
  5. /******************************************************************
  6. Copyright 1989, 1991, 1992 by Carnegie Mellon University
  7.                       All Rights Reserved
  8. Permission to use, copy, modify, and distribute this software and its
  9. documentation for any purpose and without fee is hereby granted,
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in
  12. supporting documentation, and that the name of CMU not be
  13. used in advertising or publicity pertaining to distribution of the
  14. software without specific, written prior permission.
  15. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22. ******************************************************************/
  23. #include <net-snmp/net-snmp-config.h>
  24. #if HAVE_STDLIB_H
  25. #include <stdlib.h>
  26. #endif
  27. #if HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #if HAVE_STRING_H
  31. #include <string.h>
  32. #else
  33. #include <strings.h>
  34. #endif
  35. #include <sys/types.h>
  36. #if HAVE_NETINET_IN_H
  37. # include <netinet/in.h>
  38. #endif
  39. #if TIME_WITH_SYS_TIME
  40. # ifdef WIN32
  41. #  include <sys/timeb.h>
  42. # else
  43. #  include <sys/time.h>
  44. # endif
  45. # include <time.h>
  46. #else
  47. # if HAVE_SYS_TIME_H
  48. #  include <sys/time.h>
  49. # else
  50. #  include <time.h>
  51. # endif
  52. #endif
  53. #if HAVE_SYS_SELECT_H
  54. #include <sys/select.h>
  55. #endif
  56. #include <stdio.h>
  57. #if HAVE_WINSOCK_H
  58. #include <winsock.h>
  59. #endif
  60. #if HAVE_SYS_SOCKET_H
  61. #include <sys/socket.h>
  62. #endif
  63. #if HAVE_NETDB_H
  64. #include <netdb.h>
  65. #endif
  66. #if HAVE_ARPA_INET_H
  67. #include <arpa/inet.h>
  68. #endif
  69. #include <net-snmp/net-snmp-includes.h>
  70. oid             objid_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
  71. oid             objid_sysdescr[] = { 1, 3, 6, 1, 2, 1, 1, 1, 0 };
  72. oid             objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
  73. oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
  74. int             inform = 0;
  75. void
  76. usage(void)
  77. {
  78.     fprintf(stderr, "USAGE: %s ", inform ? "snmpinform" : "snmptrap");
  79.     snmp_parse_args_usage(stderr);
  80.     fprintf(stderr, " TRAP-PARAMETERSnn");
  81.     snmp_parse_args_descriptions(stderr);
  82.     fprintf(stderr,
  83.             "  -C APPOPTSttSet various application specific behaviour:n");
  84.     fprintf(stderr, "ttt  i:  send an INFORM instead of a TRAPn");
  85.     fprintf(stderr,
  86.             "n  -v 1 TRAP-PARAMETERS:nt enterprise-oid agent trap-type specific-type uptime [OID TYPE VALUE]...n");
  87.     fprintf(stderr, "  orn");
  88.     fprintf(stderr,
  89.             "  -v 2 TRAP-PARAMETERS:nt uptime trapoid [OID TYPE VALUE] ...n");
  90. }
  91. int
  92. snmp_input(int operation,
  93.            netsnmp_session * session,
  94.            int reqid, netsnmp_pdu *pdu, void *magic)
  95. {
  96.     return 1;
  97. }
  98. in_addr_t
  99. parse_address(char *address)
  100. {
  101.     in_addr_t       addr;
  102.     struct sockaddr_in saddr;
  103.     struct hostent *hp;
  104.     if ((addr = inet_addr(address)) != -1)
  105.         return addr;
  106.     hp = gethostbyname(address);
  107.     if (hp == NULL) {
  108.         fprintf(stderr, "unknown host: %sn", address);
  109.         exit(1);
  110.     } else {
  111.         memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
  112.         return saddr.sin_addr.s_addr;
  113.     }
  114. }
  115. static void
  116. optProc(int argc, char *const *argv, int opt)
  117. {
  118.     switch (opt) {
  119.     case 'C':
  120.         while (*optarg) {
  121.             switch (*optarg++) {
  122.             case 'i':
  123.                 inform = 1;
  124.                 break;
  125.             default:
  126.                 fprintf(stderr,
  127.                         "Unknown flag passed to -C: %cn", optarg[-1]);
  128.                 exit(1);
  129.             }
  130.         }
  131.         break;
  132.     }
  133. }
  134. int
  135. main(int argc, char *argv[])
  136. {
  137.     netsnmp_session session, *ss;
  138.     netsnmp_pdu    *pdu, *response;
  139.     oid             name[MAX_OID_LEN];
  140.     size_t          name_length;
  141.     int             arg;
  142.     int             status;
  143.     char           *trap = NULL;
  144.     char           *prognam;
  145.     int             exitval = 0;
  146. #ifndef DISABLE_SNMPV1
  147.     char           *specific = NULL, *description = NULL, *agent = NULL;
  148.     in_addr_t      *pdu_in_addr_t;
  149. #endif
  150.     prognam = strrchr(argv[0], '/');
  151.     if (prognam)
  152.         prognam++;
  153.     else
  154.         prognam = argv[0];
  155.     putenv(strdup("POSIXLY_CORRECT=1"));
  156.     if (strcmp(prognam, "snmpinform") == 0)
  157.         inform = 1;
  158.     switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
  159.     case -2:
  160.         exit(0);
  161.     case -1:
  162.         usage();
  163.         exit(1);
  164.     default:
  165.         break;
  166.     }
  167.     SOCK_STARTUP;
  168.     session.callback = snmp_input;
  169.     session.callback_magic = NULL;
  170.     netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT, 
  171.        SNMP_TRAP_PORT);
  172.     if (session.version == SNMP_VERSION_3 && !inform) {
  173.         /*
  174.          * for traps, we use ourselves as the authoritative engine
  175.          * which is really stupid since command line apps don't have a
  176.          * notion of a persistent engine.  Hence, our boots and time
  177.          * values are probably always really wacked with respect to what
  178.          * a manager would like to see.
  179.          * 
  180.          * The following should be enough to:
  181.          * 
  182.          * 1) prevent the library from doing discovery for engineid & time.
  183.          * 2) use our engineid instead of the remote engineid for
  184.          * authoritative & privacy related operations.
  185.          * 3) The remote engine must be configured with users for our engineID.
  186.          * 
  187.          * -- Wes 
  188.          */
  189.         /*
  190.          * setup the engineID based on IP addr.  Need a different
  191.          * algorthim here.  This will cause problems with agents on the
  192.          * same machine sending traps. 
  193.          */
  194.         setup_engineID(NULL, NULL);
  195.         /*
  196.          * pick our own engineID 
  197.          */
  198.         if (session.securityEngineIDLen == 0 ||
  199.             session.securityEngineID == NULL) {
  200.             session.securityEngineID =
  201.                 snmpv3_generate_engineID(&session.securityEngineIDLen);
  202.         }
  203.         if (session.contextEngineIDLen == 0 ||
  204.             session.contextEngineID == NULL) {
  205.             session.contextEngineID =
  206.                 snmpv3_generate_engineID(&session.contextEngineIDLen);
  207.         }
  208.         /*
  209.          * set boots and time, which will cause problems if this
  210.          * machine ever reboots and a remote trap receiver has cached our
  211.          * boots and time...  I'll cause a not-in-time-window report to
  212.          * be sent back to this machine. 
  213.          */
  214.         if (session.engineBoots == 0)
  215.             session.engineBoots = 1;
  216.         if (session.engineTime == 0)    /* not really correct, */
  217.             session.engineTime = get_uptime();  /* but it'll work. Sort of. */
  218.     }
  219.     ss = snmp_open(&session);
  220.     if (ss == NULL) {
  221.         /*
  222.          * diagnose snmp_open errors with the input netsnmp_session pointer 
  223.          */
  224.         snmp_sess_perror("snmptrap", &session);
  225.         SOCK_CLEANUP;
  226.         exit(1);
  227.     }
  228. #ifndef DISABLE_SNMPV1
  229.     if (session.version == SNMP_VERSION_1) {
  230.         if (inform) {
  231.             fprintf(stderr, "Cannot send INFORM as SNMPv1 PDUn");
  232.             exit(1);
  233.         }
  234.         pdu = snmp_pdu_create(SNMP_MSG_TRAP);
  235.         pdu_in_addr_t = (in_addr_t *) pdu->agent_addr;
  236.         if (arg == argc) {
  237.             fprintf(stderr, "No enterprise oidn");
  238.             usage();
  239.             SOCK_CLEANUP;
  240.             exit(1);
  241.         }
  242.         if (argv[arg][0] == 0) {
  243.             pdu->enterprise = (oid *) malloc(sizeof(objid_enterprise));
  244.             memcpy(pdu->enterprise, objid_enterprise,
  245.                    sizeof(objid_enterprise));
  246.             pdu->enterprise_length =
  247.                 sizeof(objid_enterprise) / sizeof(oid);
  248.         } else {
  249.             name_length = MAX_OID_LEN;
  250.             if (!snmp_parse_oid(argv[arg], name, &name_length)) {
  251.                 snmp_perror(argv[arg]);
  252.                 usage();
  253.                 SOCK_CLEANUP;
  254.                 exit(1);
  255.             }
  256.             pdu->enterprise = (oid *) malloc(name_length * sizeof(oid));
  257.             memcpy(pdu->enterprise, name, name_length * sizeof(oid));
  258.             pdu->enterprise_length = name_length;
  259.         }
  260.         if (++arg >= argc) {
  261.             fprintf(stderr, "Missing agent parametern");
  262.             usage();
  263.             SOCK_CLEANUP;
  264.             exit(1);
  265.         }
  266.         agent = argv[arg];
  267.         if (agent != NULL && strlen(agent) != 0) {
  268.             *pdu_in_addr_t = parse_address(agent);
  269.         } else {
  270.             *pdu_in_addr_t = get_myaddr();
  271.         }
  272.         if (++arg == argc) {
  273.             fprintf(stderr, "Missing generic-trap parametern");
  274.             usage();
  275.             SOCK_CLEANUP;
  276.             exit(1);
  277.         }
  278.         trap = argv[arg];
  279.         pdu->trap_type = atoi(trap);
  280.         if (++arg == argc) {
  281.             fprintf(stderr, "Missing specific-trap parametern");
  282.             usage();
  283.             SOCK_CLEANUP;
  284.             exit(1);
  285.         }
  286.         specific = argv[arg];
  287.         pdu->specific_type = atoi(specific);
  288.         if (++arg == argc) {
  289.             fprintf(stderr, "Missing uptime parametern");
  290.             usage();
  291.             SOCK_CLEANUP;
  292.             exit(1);
  293.         }
  294.         description = argv[arg];
  295.         if (description == NULL || *description == 0)
  296.             pdu->time = get_uptime();
  297.         else
  298.             pdu->time = atol(description);
  299.     } else
  300. #endif
  301.     {
  302.         long            sysuptime;
  303.         char            csysuptime[20];
  304.         pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2);
  305.         if (arg == argc) {
  306.             fprintf(stderr, "Missing up-time parametern");
  307.             usage();
  308.             SOCK_CLEANUP;
  309.             exit(1);
  310.         }
  311.         trap = argv[arg];
  312.         if (*trap == 0) {
  313.             sysuptime = get_uptime();
  314.             sprintf(csysuptime, "%ld", sysuptime);
  315.             trap = csysuptime;
  316.         }
  317.         snmp_add_var(pdu, objid_sysuptime,
  318.                      sizeof(objid_sysuptime) / sizeof(oid), 't', trap);
  319.         if (++arg == argc) {
  320.             fprintf(stderr, "Missing trap-oid parametern");
  321.             usage();
  322.             SOCK_CLEANUP;
  323.             exit(1);
  324.         }
  325.         if (snmp_add_var
  326.             (pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid),
  327.              'o', argv[arg]) != 0) {
  328.             snmp_perror(argv[arg]);
  329.             SOCK_CLEANUP;
  330.             exit(1);
  331.         }
  332.     }
  333.     arg++;
  334.     while (arg < argc) {
  335.         arg += 3;
  336.         if (arg > argc) {
  337.             fprintf(stderr, "%s: Missing type/value for variablen",
  338.                     argv[arg - 3]);
  339.             SOCK_CLEANUP;
  340.             exit(1);
  341.         }
  342.         name_length = MAX_OID_LEN;
  343.         if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) {
  344.             snmp_perror(argv[arg - 3]);
  345.             SOCK_CLEANUP;
  346.             exit(1);
  347.         }
  348.         if (snmp_add_var
  349.             (pdu, name, name_length, argv[arg - 2][0],
  350.              argv[arg - 1]) != 0) {
  351.             snmp_perror(argv[arg - 3]);
  352.             SOCK_CLEANUP;
  353.             exit(1);
  354.         }
  355.     }
  356.     if (inform)
  357.         status = snmp_synch_response(ss, pdu, &response);
  358.     else
  359.         status = snmp_send(ss, pdu) == 0;
  360.     if (status) {
  361.         snmp_sess_perror(inform ? "snmpinform" : "snmptrap", ss);
  362.         if (!inform)
  363.             snmp_free_pdu(pdu);
  364.         exitval = 1;
  365.     } else if (inform)
  366.         snmp_free_pdu(response);
  367.     snmp_close(ss);
  368.     SOCK_CLEANUP;
  369.     return exitval;
  370. }