📄 protocol.c
字号:
/* "Empty" packet */ break; case AGENTX_MSG_ADD_AGENT_CAPS: bufp = agentx_build_oid( bufp, out_length, 0, pdu->variables->name, pdu->variables->name_length, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); if ( bufp == NULL ) return -1; bufp = agentx_build_string( bufp, out_length, pdu->variables->val.string, pdu->variables->val_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); if ( bufp == NULL ) return -1; break; case AGENTX_MSG_REMOVE_AGENT_CAPS: bufp = agentx_build_oid( bufp, out_length, 0, pdu->variables->name, pdu->variables->name_length, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); if ( bufp == NULL ) return -1; break; default: session->s_snmp_errno = SNMPERR_UNKNOWN_PDU; return -1; } /* Insert the payload length (ignoring the 20-byte header) and return the full length of the packet */ agentx_build_int( packet+16, (bufp-packet)-20, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER); *out_length = bufp-packet; return 0;}intagentx_build(struct snmp_session *session, struct snmp_pdu *pdu, register u_char *packet, size_t *out_length){ int rc; rc = _agentx_build(session,pdu,packet,out_length); if (rc) { if (0 == session->s_snmp_errno) session->s_snmp_errno = SNMPERR_BAD_ASN1_BUILD; } return (rc);} /*********************** * * Utility functions for parsing an AgentX packet * ***********************/ intagentx_parse_int(u_char *data, u_int network_byte_order){ u_int value = 0; /* * Note - this doesn't handle 'PDP_ENDIAN' systems * If anyone needs this added, contact the coders list */ DEBUGDUMPSETUP("dump_recv", data, 4); if ( network_byte_order ) { memmove( &value, data, 4);#ifndef WORDS_BIGENDIAN value = ntohl( value );#endif } else {#ifndef WORDS_BIGENDIAN memmove( &value, data, 4);#else /* The equivalent of the 'ntohl()' macro, except this macro is null on big-endian systems */ value += data[3]; value <<= 8; value += data[2]; value <<= 8; value += data[1]; value <<= 8; value += data[0];#endif } DEBUGMSG(("dump_recv", " Integer:\t%ld (0x%.2X)\n", value, value)); return value;}intagentx_parse_short(u_char *data, u_int network_byte_order){ u_short value = 0; if ( network_byte_order ) { memmove( &value, data, 2);#ifndef WORDS_BIGENDIAN value = ntohs( value );#endif } else {#ifndef WORDS_BIGENDIAN memmove( &value, data, 2);#else /* The equivalent of the 'ntohs()' macro, except this macro is null on big-endian systems */ value += data[1]; value <<= 8; value += data[0];#endif } DEBUGDUMPSETUP("dump_recv", data, 2); DEBUGMSG(("dump_recv", " Short:\t%ld (0x%.2X)\n", value, value)); return value;}u_char *agentx_parse_oid( u_char *data, size_t *length, int *inc, oid *oid_buf, size_t *oid_len, u_int network_byte_order){ u_int n_subid, subid; u_int prefix; int i; oid *oid_ptr = oid_buf; u_char *buf_ptr = data; if ( *length < 4 ) { DEBUGMSGTL(("agentx","Incomplete Object ID")); return NULL; } n_subid = data[0]; prefix = data[1]; if ( inc ) *inc = data[2]; buf_ptr += 4; *length -= 4; if ( n_subid == 0 ) { /* Null OID */ *oid_ptr = 0; oid_ptr++; *oid_ptr = 0; oid_ptr++; *oid_len = 2; DEBUGDUMPSETUP("dump_recv", data, 4); DEBUGDUMPHEADER("dump_recv", "OID Segments\n"); DEBUGMSG(("dump_recv", "OID: NULL (0.0)\n")); return buf_ptr; } if ( *length < 4*n_subid ) { DEBUGMSGTL(("agentx","Incomplete Object ID")); return NULL; } if ( prefix ) { *oid_ptr = 1; oid_ptr++; *oid_ptr = 3; oid_ptr++; *oid_ptr = 6; oid_ptr++; *oid_ptr = 1; oid_ptr++; *oid_ptr = prefix; oid_ptr++; } DEBUGDUMPHEADER("dump_recv", "OID Segments\n"); for ( i = 0 ; i<n_subid ; i++ ) { oid_ptr[i] = agentx_parse_int( buf_ptr, network_byte_order ); buf_ptr += 4; *length -= 4; } DEBUGINDENTLESS(); *oid_len = ( prefix ? n_subid + 5 : n_subid ); DEBUGDUMPSETUP("dump_recv", data, buf_ptr - data); DEBUGMSG(("dump_recv", "OID: ")); DEBUGMSGOID(("dump_recv", oid_buf, *oid_len)); DEBUGMSG(("dump_recv", "\n")); return buf_ptr;}u_char *agentx_parse_string( u_char *data, size_t *length, u_char *string, size_t *str_len, u_int network_byte_order){ u_int len; if ( *length < 4 ) { DEBUGMSGTL(("agentx","Incomplete string (too short: %d)", *length)); return NULL; } len = agentx_parse_int( data, network_byte_order ); if ( *length < len + 4 ) { DEBUGMSGTL(("agentx","Incomplete string (still too short: %d)", *length)); return NULL; } if ( len > *str_len ) { DEBUGMSGTL(("agentx","String too long (too long)")); return NULL; } memmove( string, data+4, len ); string[len] = '\0'; *str_len = len; len += 3; /* Extend the string length to include the padding */ len >>= 2; len <<= 2; *length -= ( len+4 ); DEBUGDUMPSETUP("dump_recv", data, (len+4)); DEBUGIF("dump_recv") { char *buf = (char *)malloc(1+len+4); sprint_asciistring(buf, string, len+4); DEBUGMSG(("dump_recv", "String: %s\n", buf)); free (buf); } return data + ( len+4 );}u_char *agentx_parse_varbind( u_char *data, size_t *length, int *type, oid *oid_buf, size_t *oid_len, u_char *data_buf, size_t *data_len, u_int network_byte_order){ u_char *bufp = data; u_int int_val; struct counter64 *c64 = (struct counter64 *)data_buf; size_t convert_tmp; DEBUGDUMPHEADER("dump_recv", "VarBind:\n"); DEBUGDUMPHEADER("dump_recv", "Parsing Byte Order\n"); *type = agentx_parse_short( bufp, network_byte_order ); DEBUGINDENTLESS(); bufp += 4; *length -= 4; bufp = agentx_parse_oid( bufp, length, NULL, oid_buf, oid_len, network_byte_order ); if ( bufp == NULL ) { DEBUGINDENTLESS(); return NULL; } switch ( *type ) { case ASN_INTEGER: case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: int_val = agentx_parse_int( bufp, network_byte_order ); memmove( data_buf, &int_val, 4); *data_len = 4; bufp += 4; *length -= 4; break; case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: bufp = agentx_parse_string( bufp, length, data_buf, data_len, network_byte_order ); break; case ASN_OBJECT_ID: bufp = agentx_parse_oid( bufp, length, NULL, (oid *)data_buf, data_len, network_byte_order ); *data_len *= 4; /* 'agentx_parse_oid()' returns the number of sub_ids */ break; case ASN_COUNTER64: if ( network_byte_order ) { c64->high = agentx_parse_int( bufp, network_byte_order ); c64->low = agentx_parse_int( bufp+4, network_byte_order ); } else { c64->low = agentx_parse_int( bufp, network_byte_order ); c64->high = agentx_parse_int( bufp+4, network_byte_order ); } *data_len = 8; bufp += 8; *length -= 8; break; case ASN_NULL: case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: /* No data associated with these types */ *data_len = 0; break; default: DEBUGINDENTLESS(); return NULL; } DEBUGINDENTLESS(); return bufp;}/* * AgentX header: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | h.version | h.type | h.flags | <reserved> | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | h.sessionID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | h.transactionID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | h.packetID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | h.payload_length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Total length = 20 bytes * * If we don't seem to have the full packet, return NULL * and let the driving code go back for the rest. * Don't report this as an error, as it's quite "normal" * with a connection-oriented service. * * Note that once the header has been successfully processed * (and hence we should have the full packet), any subsequent * "running out of room" is indeed an error. */u_char *agentx_parse_header(struct snmp_pdu *pdu, u_char *data, size_t *length){ register u_char *bufp = data; size_t payload; if ( *length < 20 ) { /* Incomplete header */ return NULL; } DEBUGDUMPHEADER("dump_recv", "AgentX Header\n"); DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Version\n"); DEBUGDUMPSETUP("dump_recv", bufp, 1); pdu->version = AGENTX_VERSION_BASE | *bufp; DEBUGMSG(("dump_recv", "Version:\t%d\n", *bufp)); DEBUGINDENTLESS(); bufp++; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Command\n"); DEBUGDUMPSETUP("dump_recv", bufp, 1); pdu->command = *bufp; DEBUGMSG(("dump_recv", "Command:\t%d\n", *bufp)); DEBUGINDENTLESS(); bufp++; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Flags\n"); DEBUGDUMPSETUP("dump_recv", bufp, 1); pdu->flags |= *bufp; DEBUGMSG(("dump_recv", "Flags:\t0x%x\n", *bufp)); DEBUGINDENTLESS(); bufp++; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Reserved Byte\n"); DEBUGDUMPSETUP("dump_recv", bufp, 1); DEBUGMSG(("dump_recv", "Byte:\t0x%x\n", *bufp)); DEBUGINDENTLESS(); bufp++; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Session ID\n"); pdu->sessid = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); bufp += 4; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Transaction ID\n"); pdu->transid = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); bufp += 4; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Packet ID\n"); pdu->reqid = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); bufp += 4; DEBUGDUMPHEADER("dump_recv", "Parsing AgentX Payload Length\n"); payload = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); bufp += 4; *length -= 20; DEBUGINDENTLESS(); if ( *length != payload ) { /* Short payload */ return NULL; } return bufp;}intagentx_parse(struct snmp_session *session, struct snmp_pdu *pdu, u_char *data, size_t len){ register u_char *bufp = data; u_char buffer[BUFSIZ]; u_char *prefix_ptr; oid oid_buffer[MAX_OID_LEN], end_oid_buf[MAX_OID_LEN]; size_t buf_len = BUFSIZ; size_t oid_buf_len = MAX_OID_LEN; size_t end_oid_buf_len = MAX_OID_LEN; int range_bound;/* OID-range upper bound */ int inc; /* Inclusive SearchRange flag */ int type; /* VarBind data type */ size_t *length = &len; if ( pdu == NULL ) { /* Dump the packet in a formatted style */ pdu = (struct snmp_pdu *)malloc( sizeof( struct snmp_pdu )); agentx_dump( session, pdu, data, len );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -