📄 snmp_api.c
字号:
/****************************************************************** Copyright 1989, 1991, 1992 by Carnegie Mellon University All Rights ReservedPermission to use, copy, modify, and distribute this software and itsdocumentation for any purpose and without fee is hereby granted,provided that the above copyright notice appear in all copies and thatboth that copyright notice and this permission notice appear insupporting documentation, and that the name of CMU not beused in advertising or publicity pertaining to distribution of thesoftware without specific, written prior permission.CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDINGALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALLCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ORANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THISSOFTWARE.******************************************************************//** @defgroup library The Net-SNMP library * @{ *//* * snmp_api.c - API for access to snmp. */#include <net-snmp/net-snmp-config.h>#include <stdio.h>#include <ctype.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#include <sys/types.h>#if HAVE_SYS_PARAM_H#include <sys/param.h>#endif#if TIME_WITH_SYS_TIME# ifdef WIN32# include <sys/timeb.h># else# include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_SYS_SELECT_H#include <sys/select.h>#endif#if HAVE_IO_H#include <io.h>#endif#if HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_SYS_UN_H#include <sys/un.h>#endif#if HAVE_NETDB_H#include <netdb.h>#endif#if HAVE_NET_IF_DL_H#ifndef dynix#include <net/if_dl.h>#else#include <sys/net/if_dl.h>#endif#endif#include <errno.h>#if HAVE_LOCALE_H#include <locale.h>#endif#if HAVE_DMALLOC_H#include <dmalloc.h>#endif#define SNMP_NEED_REQUEST_LIST#include <net-snmp/types.h>#include <net-snmp/output_api.h>#include <net-snmp/config_api.h>#include <net-snmp/utilities.h>#include <net-snmp/library/asn1.h>#include <net-snmp/library/snmp.h> /* for xdump & {build,parse}_var_op */#include <net-snmp/library/snmp_api.h>#include <net-snmp/library/snmp_client.h>#include <net-snmp/library/parse.h>#include <net-snmp/library/mib.h>#include <net-snmp/library/int64.h>#include <net-snmp/library/snmpv3.h>#include <net-snmp/library/callback.h>#include <net-snmp/library/container.h>#include <net-snmp/library/snmp_secmod.h>#ifdef SNMP_SECMOD_USM#include <net-snmp/library/snmpusm.h>#endif#ifdef SNMP_SECMOD_KSM#include <net-snmp/library/snmpksm.h>#endif#include <net-snmp/library/keytools.h>#include <net-snmp/library/lcd_time.h>#include <net-snmp/library/snmp_alarm.h>#include <net-snmp/library/snmp_transport.h>static void _init_snmp(void);#include <net-snmp/library/transform_oids.h>#ifndef timercmp#define timercmp(tvp, uvp, cmp) \ /* CSTYLED */ \ ((tvp)->tv_sec cmp (uvp)->tv_sec || \ ((tvp)->tv_sec == (uvp)->tv_sec && \ /* CSTYLED */ \ (tvp)->tv_usec cmp (uvp)->tv_usec))#endif#ifndef timerclear#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0#endif/* * Globals. */#define MAX_PACKET_LENGTH (0x7fffffff)#ifndef NETSNMP_STREAM_QUEUE_LEN#define NETSNMP_STREAM_QUEUE_LEN 5#endif#ifndef BSD4_3#define BSD4_2#endif#ifndef FD_SETtypedef long fd_mask;#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))#define FD_ZERO(p) memset((p), 0, sizeof(*(p)))#endifstatic oid default_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };/* * enterprises.cmu.systems.cmuSNMP */#define DEFAULT_COMMUNITY "public"#define DEFAULT_RETRIES 5#define DEFAULT_TIMEOUT 1000000L#define DEFAULT_REMPORT SNMP_PORT#define DEFAULT_ENTERPRISE default_enterprise#define DEFAULT_TIME 0/* * don't set higher than 0x7fffffff, and I doubt it should be that high * * = 4 gig snmp messages max */#define MAXIMUM_PACKET_SIZE 0x7fffffff/* * Internal information about the state of the snmp session. */struct snmp_internal_session { netsnmp_request_list *requests; /* Info about outstanding requests */ netsnmp_request_list *requestsEnd; /* ptr to end of list */ int (*hook_pre) (netsnmp_session *, netsnmp_transport *, void *, int); int (*hook_parse) (netsnmp_session *, netsnmp_pdu *, u_char *, size_t); int (*hook_post) (netsnmp_session *, netsnmp_pdu *, int); int (*hook_build) (netsnmp_session *, netsnmp_pdu *, u_char *, size_t *); int (*hook_realloc_build) (netsnmp_session *, netsnmp_pdu *, u_char **, size_t *, size_t *); int (*check_packet) (u_char *, size_t); netsnmp_pdu *(*hook_create_pdu) (netsnmp_transport *, void *, size_t); u_char *packet; size_t packet_len, packet_size;};/* * The list of active/open sessions. */struct session_list { struct session_list *next; netsnmp_session *session; netsnmp_transport *transport; struct snmp_internal_session *internal;};static const char *api_errors[-SNMPERR_MAX + 1] = { "No error", /* SNMPERR_SUCCESS */ "Generic error", /* SNMPERR_GENERR */ "Invalid local port", /* SNMPERR_BAD_LOCPORT */ "Unknown host", /* SNMPERR_BAD_ADDRESS */ "Unknown session", /* SNMPERR_BAD_SESSION */ "Too long", /* SNMPERR_TOO_LONG */ "No socket", /* SNMPERR_NO_SOCKET */ "Cannot send V2 PDU on V1 session", /* SNMPERR_V2_IN_V1 */ "Cannot send V1 PDU on V2 session", /* SNMPERR_V1_IN_V2 */ "Bad value for non-repeaters", /* SNMPERR_BAD_REPEATERS */ "Bad value for max-repetitions", /* SNMPERR_BAD_REPETITIONS */ "Error building ASN.1 representation", /* SNMPERR_BAD_ASN1_BUILD */ "Failure in sendto", /* SNMPERR_BAD_SENDTO */ "Bad parse of ASN.1 type", /* SNMPERR_BAD_PARSE */ "Bad version specified", /* SNMPERR_BAD_VERSION */ "Bad source party specified", /* SNMPERR_BAD_SRC_PARTY */ "Bad destination party specified", /* SNMPERR_BAD_DST_PARTY */ "Bad context specified", /* SNMPERR_BAD_CONTEXT */ "Bad community specified", /* SNMPERR_BAD_COMMUNITY */ "Cannot send noAuth/Priv", /* SNMPERR_NOAUTH_DESPRIV */ "Bad ACL definition", /* SNMPERR_BAD_ACL */ "Bad Party definition", /* SNMPERR_BAD_PARTY */ "Session abort failure", /* SNMPERR_ABORT */ "Unknown PDU type", /* SNMPERR_UNKNOWN_PDU */ "Timeout", /* SNMPERR_TIMEOUT */ "Failure in recvfrom", /* SNMPERR_BAD_RECVFROM */ "Unable to determine contextEngineID", /* SNMPERR_BAD_ENG_ID */ "No securityName specified", /* SNMPERR_BAD_SEC_NAME */ "Unable to determine securityLevel", /* SNMPERR_BAD_SEC_LEVEL */ "ASN.1 parse error in message", /* SNMPERR_ASN_PARSE_ERR */ "Unknown security model in message", /* SNMPERR_UNKNOWN_SEC_MODEL */ "Invalid message (e.g. msgFlags)", /* SNMPERR_INVALID_MSG */ "Unknown engine ID", /* SNMPERR_UNKNOWN_ENG_ID */ "Unknown user name", /* SNMPERR_UNKNOWN_USER_NAME */ "Unsupported security level", /* SNMPERR_UNSUPPORTED_SEC_LEVEL */ "Authentication failure (incorrect password, community or key)", /* SNMPERR_AUTHENTICATION_FAILURE */ "Not in time window", /* SNMPERR_NOT_IN_TIME_WINDOW */ "Decryption error", /* SNMPERR_DECRYPTION_ERR */ "SCAPI general failure", /* SNMPERR_SC_GENERAL_FAILURE */ "SCAPI sub-system not configured", /* SNMPERR_SC_NOT_CONFIGURED */ "Key tools not available", /* SNMPERR_KT_NOT_AVAILABLE */ "Unknown Report message", /* SNMPERR_UNKNOWN_REPORT */ "USM generic error", /* SNMPERR_USM_GENERICERROR */ "USM unknown security name (no such user exists)", /* SNMPERR_USM_UNKNOWNSECURITYNAME */ "USM unsupported security level (this user has not been configured for that level of security)", /* SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL */ "USM encryption error", /* SNMPERR_USM_ENCRYPTIONERROR */ "USM authentication failure (incorrect password or key)", /* SNMPERR_USM_AUTHENTICATIONFAILURE */ "USM parse error", /* SNMPERR_USM_PARSEERROR */ "USM unknown engineID", /* SNMPERR_USM_UNKNOWNENGINEID */ "USM not in time window", /* SNMPERR_USM_NOTINTIMEWINDOW */ "USM decryption error", /* SNMPERR_USM_DECRYPTIONERROR */ "MIB not initialized", /* SNMPERR_NOMIB */ "Value out of range", /* SNMPERR_RANGE */ "Sub-id out of range", /* SNMPERR_MAX_SUBID */ "Bad sub-id in object identifier", /* SNMPERR_BAD_SUBID */ "Object identifier too long", /* SNMPERR_LONG_OID */ "Bad value name", /* SNMPERR_BAD_NAME */ "Bad value notation", /* SNMPERR_VALUE */ "Unknown Object Identifier", /* SNMPERR_UNKNOWN_OBJID */ "No PDU in snmp_send", /* SNMPERR_NULL_PDU */ "Missing variables in PDU", /* SNMPERR_NO_VARS */ "Bad variable type", /* SNMPERR_VAR_TYPE */ "Out of memory (malloc failure)", /* SNMPERR_MALLOC */ "Kerberos related error", /* SNMPERR_KRB5 */};static const char *secLevelName[] = { "BAD_SEC_LEVEL", "noAuthNoPriv", "authNoPriv", "authPriv"};/* * Multiple threads may changes these variables. * Suggest using the Single API, which does not use Sessions. * * Reqid may need to be protected. Time will tell... * *//* * MTCRITICAL_RESOURCE *//* * use token in comments to individually protect these resources */struct session_list *Sessions = NULL; /* MT_LIB_SESSION */static long Reqid = 0; /* MT_LIB_REQUESTID */static long Msgid = 0; /* MT_LIB_MESSAGEID */static long Sessid = 0; /* MT_LIB_SESSIONID */static long Transid = 0; /* MT_LIB_TRANSID */int snmp_errno = 0;/* * END MTCRITICAL_RESOURCE *//* * global error detail storage */static char snmp_detail[192];static int snmp_detail_f = 0;/* * Prototypes. */int snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset, netsnmp_session * pss, netsnmp_pdu *pdu);static int snmp_parse(void *, netsnmp_session *, netsnmp_pdu *, u_char *, size_t);static void snmpv3_calc_msg_flags(int, int, u_char *);static int snmpv3_verify_msg(netsnmp_request_list *, netsnmp_pdu *);static int snmpv3_build_probe_pdu(netsnmp_pdu **);static int snmpv3_build(u_char ** pkt, size_t * pkt_len, size_t * offset, netsnmp_session * session, netsnmp_pdu *pdu);static int snmp_parse_version(u_char *, size_t);static int snmp_resend_request(struct session_list *slp, netsnmp_request_list *rp, int incr_retries);static void register_default_handlers(void);static struct session_list *snmp_sess_copy(netsnmp_session * pss);int snmp_get_errno(void);void snmp_synch_reset(netsnmp_session * notused);void snmp_synch_setup(netsnmp_session * notused);#ifndef HAVE_STRERRORconst char *strerror(int err){ extern const char *sys_errlist[]; extern int sys_nerr; if (err < 0 || err >= sys_nerr) return "Unknown error"; return sys_errlist[err];}#endif#define DEBUGPRINTPDUTYPE(token, type) \ switch(type) { \ case SNMP_MSG_GET: \ DEBUGDUMPSECTION(token, "PDU-GET"); \ break; \ case SNMP_MSG_GETNEXT: \ DEBUGDUMPSECTION(token, "PDU-GETNEXT"); \ break; \ case SNMP_MSG_RESPONSE: \ DEBUGDUMPSECTION(token, "PDU-RESPONSE"); \ break; \ case SNMP_MSG_SET: \ DEBUGDUMPSECTION(token, "PDU-SET"); \ break; \ case SNMP_MSG_GETBULK: \ DEBUGDUMPSECTION(token, "PDU-GETBULK"); \ break; \ case SNMP_MSG_INFORM: \ DEBUGDUMPSECTION(token, "PDU-INFORM"); \ break; \ case SNMP_MSG_TRAP2: \ DEBUGDUMPSECTION(token, "PDU-TRAP2"); \ break; \ case SNMP_MSG_REPORT: \ DEBUGDUMPSECTION(token, "PDU-REPORT"); \ break; \ default: \ DEBUGDUMPSECTION(token, "PDU-UNKNOWN"); \ break; \ }longsnmp_get_next_reqid(void){ long retVal; snmp_res_lock(MT_LIBRARY_ID, MT_LIB_REQUESTID); retVal = 1 + Reqid; /*MTCRITICAL_RESOURCE */ if (!retVal) retVal = 2; Reqid = retVal; snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_REQUESTID); return retVal;}longsnmp_get_next_msgid(void){ long retVal; snmp_res_lock(MT_LIBRARY_ID, MT_LIB_MESSAGEID); retVal = 1 + Msgid; /*MTCRITICAL_RESOURCE */ if (!retVal) retVal = 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -