📄 protocol.c
字号:
#include <config.h>#include <stdio.h>#include <errno.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 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_DMALLOC_H#include <dmalloc.h>#endif#if HAVE_WINSOCK_H#include <winsock.h>#endif#include "asn1.h"#include "snmp_api.h"#include "snmp_impl.h"#include "snmp.h"#include "snmp_client.h"#include "snmp_debug.h"#include "mib.h"#include "agentx/protocol.h"const char *agentx_cmd( u_char code ){ switch (code) { case AGENTX_MSG_OPEN: return "Open"; case AGENTX_MSG_CLOSE: return "Close"; case AGENTX_MSG_REGISTER: return "Register"; case AGENTX_MSG_UNREGISTER: return "Unregister"; case AGENTX_MSG_GET: return "Get"; case AGENTX_MSG_GETNEXT: return "Get Next"; case AGENTX_MSG_GETBULK: return "Get Bulk"; case AGENTX_MSG_TESTSET: return "Test Set"; case AGENTX_MSG_COMMITSET: return "Commit Set"; case AGENTX_MSG_UNDOSET: return "Undo Set"; case AGENTX_MSG_CLEANUPSET: return "Cleanup Set"; case AGENTX_MSG_NOTIFY: return "Notify"; case AGENTX_MSG_PING: return "Ping"; case AGENTX_MSG_INDEX_ALLOCATE: return "Index Allocate"; case AGENTX_MSG_INDEX_DEALLOCATE: return "Index Deallocate"; case AGENTX_MSG_ADD_AGENT_CAPS: return "Add Agent Caps"; case AGENTX_MSG_REMOVE_AGENT_CAPS: return "Remove Agent Caps"; case AGENTX_MSG_RESPONSE: return "Response"; default: return "Unknown"; }}voidagentx_build_int(u_char *bufp, u_int value, int network_byte_order){ u_char *orig_bufp = bufp; u_int orig_val = value; if ( network_byte_order ) {#ifndef WORDS_BIGENDIAN value = ntohl( value );#endif memmove( bufp, &value, 4); } else {#ifndef WORDS_BIGENDIAN memmove( bufp, &value, 4);#else *bufp = (u_char)value & 0xff; value >>=8; bufp++; *bufp = (u_char)value & 0xff; value >>=8; bufp++; *bufp = (u_char)value & 0xff; value >>=8; bufp++; *bufp = (u_char)value & 0xff;#endif } DEBUGDUMPSETUP("send", orig_bufp, 4); DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", orig_val, orig_val));}voidagentx_build_short(u_char *bufp, int in_value, int network_byte_order){ u_char *orig_bufp = bufp; u_short value = (u_short)in_value; if ( network_byte_order ) {#ifndef WORDS_BIGENDIAN value = ntohs( value );#endif memmove( bufp, &value, 2); } else {#ifndef WORDS_BIGENDIAN memmove( bufp, &value, 2);#else *bufp = (u_char)value & 0xff; value >>=8; bufp++; *bufp = (u_char)value & 0xff;#endif } DEBUGDUMPSETUP("send", orig_bufp, 2); DEBUGMSG(("dumpv_send", " Short:\t%ld (0x%.2X)\n", in_value, in_value));}u_char*agentx_build_oid(u_char *bufp, size_t *out_length, int inc, oid *name, size_t name_len, int network_byte_order){ u_char *orig_bufp = bufp; int prefix = 0; size_t i; DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", "OID: ")); DEBUGMSGOID(("dumpv_send", name, name_len)); DEBUGMSG(("dumpv_send", "\n")); if ( name_len == 2 && name[0] == 0 && name[1] == 0 ) { name_len = 0; /* Null OID */ } /* 'Compact' internet OIDs */ if ( name_len >= 5 && name[0] == 1 && name[1] == 3 && name[2] == 6 && name[3] == 1 ) { prefix = name[4]; name += 5; name_len -= 5; } if ( *out_length < 4 + 4*name_len ) return NULL; *bufp = (u_char)name_len; bufp++; *bufp = (u_char)prefix; bufp++; *bufp = (u_char)inc; bufp++; *bufp = 0; bufp++; *out_length -= 4; DEBUGDUMPHEADER("send", "OID Header"); DEBUGDUMPSETUP("send", orig_bufp, 4); DEBUGMSG(("dumpv_send", " # subids:\t%d (0x%.2X)\n", orig_bufp[0], orig_bufp[0])); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " prefix:\t%d (0x%.2X)\n", orig_bufp[1], orig_bufp[1])); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " inclusive:\t%d (0x%.2X)\n", orig_bufp[2], orig_bufp[2])); DEBUGINDENTLESS(); DEBUGDUMPHEADER("send", "OID Segments"); for ( i = 0 ; i < name_len ; i++ ) { agentx_build_int( bufp, name[i], network_byte_order ); bufp += 4; *out_length -= 4; } DEBUGINDENTLESS(); return bufp;}u_char*agentx_build_string(u_char *bufp, size_t *out_length, u_char *name, size_t name_len, int network_byte_order){ u_char *orig_bufp = bufp; if ( *out_length < 4 + name_len ) { return NULL; } DEBUGDUMPHEADER("send", "Build String"); DEBUGDUMPHEADER("send", "length"); agentx_build_int( bufp, (u_int)name_len, network_byte_order ); bufp += 4; *out_length -= 4; if ( name_len == 0 ) { DEBUGMSG(("dumpv_send", " String: <empty>\n")); DEBUGINDENTLESS(); DEBUGINDENTLESS(); return bufp; } orig_bufp += 4; memmove( bufp, name, name_len ); bufp += name_len; *out_length -= name_len; /* Pad to a multiple of 4 bytes */ name_len &= 0x3; if ( name_len ) name_len = 4-name_len; for ( ; name_len ; name_len-- ) { *bufp = 0; bufp++; (*out_length)--; } DEBUGDUMPSETUP("send", orig_bufp, bufp - orig_bufp); DEBUGMSG(("dumpv_send", " String:\t%s\n", name)); DEBUGINDENTLESS(); DEBUGINDENTLESS(); return bufp;}#ifdef OPAQUE_SPECIAL_TYPESu_char*agentx_build_double(u_char *bufp, size_t *out_length, double double_val, int network_byte_order){ union { double doubleVal; int intVal[2]; char c[sizeof(double)]; } du; int tmp; u_char buf[BUFSIZ]; if ( *out_length < 4 + 3 + sizeof(double) ) { return NULL; } buf[0] = ASN_OPAQUE_TAG1; buf[1] = ASN_OPAQUE_DOUBLE; buf[2] = sizeof(double); du.doubleVal = double_val; tmp = htonl(du.intVal[0]); du.intVal[0] = htonl(du.intVal[1]); du.intVal[1] = tmp; memcpy( &buf[3], &du.c[0], sizeof(double) ); return agentx_build_string( bufp, out_length, buf, 3 + sizeof(double), network_byte_order);}u_char*agentx_build_float(u_char *bufp, size_t *out_length, float float_val, int network_byte_order){ union { float floatVal; int intVal; char c[sizeof(float)]; } fu; u_char buf[BUFSIZ]; if ( *out_length < 4 + 3 + sizeof(float) ) { return NULL; } buf[0] = ASN_OPAQUE_TAG1; buf[1] = ASN_OPAQUE_FLOAT; buf[2] = sizeof(float); fu.floatVal = float_val; fu.intVal = htonl(fu.intVal); memcpy( &buf[3], &fu.c[0], sizeof(float) ); return agentx_build_string( bufp, out_length, buf, 3 + sizeof(float), network_byte_order);}#endifu_char*agentx_build_varbind(u_char *bufp, size_t *out_length, struct variable_list *vp, int network_byte_order){ if ( *out_length < 4 ) return NULL; DEBUGDUMPHEADER("send", "VarBind"); DEBUGDUMPHEADER("send", "type");#ifdef OPAQUE_SPECIAL_TYPES if (( vp->type == ASN_OPAQUE_FLOAT ) || ( vp->type == ASN_OPAQUE_DOUBLE ) || ( vp->type == ASN_OPAQUE_I64 ) || ( vp->type == ASN_OPAQUE_U64 ) || ( vp->type == ASN_OPAQUE_COUNTER64 )) agentx_build_short( bufp, ASN_OPAQUE, network_byte_order); else#endif agentx_build_short( bufp, (u_int)vp->type, network_byte_order); bufp +=2; *bufp = 0; bufp++; *bufp = 0; bufp++; /* <reserved> */ *out_length -=4; DEBUGINDENTLESS(); DEBUGDUMPHEADER("send", "name"); bufp = agentx_build_oid( bufp, out_length, 0, vp->name, vp->name_length, network_byte_order); if ( bufp == NULL ) return NULL; DEBUGINDENTLESS(); DEBUGDUMPHEADER("send", "value"); switch ( (short)vp->type ) { case ASN_INTEGER: case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: if ( *out_length < 4 ) return NULL; agentx_build_int( bufp, *(vp->val.integer), network_byte_order); bufp += 4; *out_length -= 4; break;#ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: DEBUGDUMPHEADER("send", "Build Opaque Float"); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " Float:\t%f\n", *(vp->val.floatVal))); bufp = agentx_build_float( bufp, out_length, *(vp->val.floatVal), network_byte_order); DEBUGINDENTLESS(); break; case ASN_OPAQUE_DOUBLE: DEBUGDUMPHEADER("send", "Build Opaque Double"); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " Double:\t%lf\n", *(vp->val.doubleVal))); bufp = agentx_build_double( bufp, out_length, *(vp->val.doubleVal), network_byte_order); DEBUGINDENTLESS(); break; case ASN_OPAQUE_I64: case ASN_OPAQUE_U64: case ASN_OPAQUE_COUNTER64: /* XXX - ToDo - encode as raw OPAQUE for now */#endif case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: bufp = agentx_build_string( bufp, out_length, vp->val.string, vp->val_len, network_byte_order); break; case ASN_OBJECT_ID: bufp = agentx_build_oid( bufp, out_length, 0, vp->val.objid, vp->val_len/4, network_byte_order); break; case ASN_COUNTER64: if ( *out_length < 8 ) return NULL; if ( network_byte_order ) { DEBUGDUMPHEADER("send", "Build Counter64 (high, low)"); agentx_build_int( bufp, vp->val.counter64->high, network_byte_order); agentx_build_int( bufp+4, vp->val.counter64->low, network_byte_order); DEBUGINDENTLESS(); } else { DEBUGDUMPHEADER("send", "Build Counter64 (low, high)"); agentx_build_int( bufp, vp->val.counter64->low, network_byte_order); agentx_build_int( bufp+4, vp->val.counter64->high, network_byte_order); DEBUGINDENTLESS(); } bufp += 8; *out_length -= 8; break; case ASN_NULL: case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: break; default: return NULL; } DEBUGINDENTLESS(); DEBUGINDENTLESS(); return bufp;}u_char*agentx_build_header(struct snmp_pdu *pdu, u_char *bufp, size_t *out_length){ u_char *orig_bufp = bufp; *bufp = 1; bufp++; /* version */ *bufp = pdu->command; bufp++; /* type */ *bufp = (u_char)(pdu->flags & AGENTX_MSG_FLAGS_MASK); bufp++; /* AgentX flags */ *bufp = 0; bufp++; /* <reserved> */ *out_length -=4; DEBUGDUMPHEADER("send", "AgentX Header"); DEBUGDUMPSETUP("send", orig_bufp, 4); DEBUGMSG(("dumpv_send", " Version:\t%d\n", *orig_bufp )); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " Command:\t%d (%s)\n", *(orig_bufp+1), agentx_cmd(*(orig_bufp+1)))); DEBUGPRINTINDENT("dumpv_send"); DEBUGMSG(("dumpv_send", " Flags:\t%x\n", *(orig_bufp+2) )); DEBUGDUMPHEADER("send", "Session ID"); agentx_build_int( bufp, pdu->sessid, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); *out_length -=4; bufp +=4; DEBUGDUMPHEADER("send", "Transaction ID"); agentx_build_int( bufp, pdu->transid, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); *out_length -=4; bufp +=4; DEBUGDUMPHEADER("send", "Request ID"); agentx_build_int( bufp, pdu->reqid, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); *out_length -=4; bufp +=4; DEBUGDUMPHEADER("send", "Dummy Length :-("); agentx_build_int( bufp, 0, 0 ); /* dummy payload length */ DEBUGINDENTLESS(); *out_length -=4; bufp +=4; if ( pdu->flags & AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT ) { DEBUGDUMPHEADER("send", "Community"); bufp = agentx_build_string( bufp, out_length, pdu->community, pdu->community_len, pdu->flags & AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); } DEBUGINDENTLESS(); return bufp;}static int_agentx_build(struct snmp_session *session, struct snmp_pdu *pdu, register u_char *packet, size_t *out_length){ u_char *bufp = packet; u_char *prefix_ptr, *range_ptr; struct variable_list *vp; int inc; session->s_snmp_errno = 0; session->s_errno = 0; /* Build the header (and context if appropriate) */ if ( *out_length < 20 ) return -1; /* Various PDU types shouldn't include context information */ switch ( pdu->command ) { case AGENTX_MSG_OPEN: case AGENTX_MSG_CLOSE: case AGENTX_MSG_RESPONSE: case AGENTX_MSG_COMMITSET: case AGENTX_MSG_UNDOSET: case AGENTX_MSG_CLEANUPSET: pdu->flags &= ~(AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT); } bufp = agentx_build_header( pdu, bufp, out_length ); if ( bufp == NULL ) return -1; DEBUGDUMPHEADER("send", "AgentX Payload"); switch ( pdu->command ) { case AGENTX_MSG_OPEN: /* Timeout */ if ( *out_length < 4 ) return -1; *bufp = (u_char)pdu->time; bufp++; *bufp = 0; bufp++; *bufp = 0; bufp++; *bufp = 0; bufp++; *out_length -= 4; DEBUGDUMPHEADER("send", "Open Timeout"); DEBUGDUMPSETUP("send", bufp-4, 4); DEBUGMSG(("dumpv_send", " Timeout:\t%d\n", *(bufp-4) )); DEBUGINDENTLESS(); DEBUGDUMPHEADER("send", "Open ID"); bufp = agentx_build_oid( bufp, out_length, 0, pdu->variables->name, pdu->variables->name_length, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); DEBUGINDENTLESS(); if ( bufp == NULL ) return -1; DEBUGDUMPHEADER("send", "Open Description"); bufp = agentx_build_string( bufp, out_length, pdu->variables->val.string, pdu->variables->val_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); DEBUGINDENTLESS(); if ( bufp == NULL ) return -1; break; case AGENTX_MSG_CLOSE: /* Reason */ if ( *out_length < 4 ) return -1; *bufp = (u_char)pdu->errstat; bufp++; *bufp = 0; bufp++; *bufp = 0; bufp++; *bufp = 0; bufp++; *out_length -= 4; DEBUGDUMPHEADER("send", "Close Reason"); DEBUGDUMPSETUP("send", bufp-4, 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -