📄 protocol.c
字号:
free( pdu ); return(0); } if (!IS_AGENTX_VERSION( session->version )) return SNMPERR_BAD_VERSION;#ifndef SNMPERR_INCOMPLETE_PACKET /* * Ideally, "short" packets on stream connections should * be handled specially, and the driving code set up to * keep reading until the full packet is received. * * For now, lets assume that all packets are read in one go. * I've probably inflicted enough damage on the UCD library * for one week! * * I'll come back to this once Wes is speaking to me again. */#define SNMPERR_INCOMPLETE_PACKET SNMPERR_ASN_PARSE_ERR#endif /* * Handle (common) header .... */ bufp = agentx_parse_header( pdu, bufp, length ); if ( bufp == NULL ) return SNMPERR_INCOMPLETE_PACKET; /* i.e. wait for the rest */ /* Control PDU handling */ pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW; pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; pdu->flags &= (~UCD_MSG_FLAG_RESPONSE_PDU); /* * ... and (not-un-common) context */ if ( pdu->flags & AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT ) { DEBUGDUMPHEADER("dump_recv", "Parsing Context\n"); bufp = agentx_parse_string( bufp, length, buffer, &buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); if ( bufp == NULL ) return SNMPERR_ASN_PARSE_ERR; pdu->community_len = buf_len; snmp_clone_mem((void **)&pdu->community, (void *)buffer, (unsigned) buf_len); buf_len = BUFSIZ; } DEBUGDUMPHEADER("dump_recv", "Parsing PDU\n"); DEBUGINDENTMORE(); DEBUGPRINTINDENT("dump_recv"); switch ( pdu->command ) { case AGENTX_MSG_OPEN: DEBUGMSG(("dump_recv", "Open PDU\n")); pdu->time = *bufp; /* Timeout */ bufp += 4; *length -= 4; /* Store subagent OID & description in a VarBind */ DEBUGDUMPHEADER("dump_recv", "Parsing Subagent OID\n"); bufp = agentx_parse_oid( bufp, length, NULL, oid_buffer, &oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); if ( bufp == NULL ) { DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } DEBUGDUMPHEADER("dump_recv", "Parsing Subagent Description\n"); bufp = agentx_parse_string( bufp, length, buffer, &buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); if ( bufp == NULL ) { DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, ASN_OCTET_STR, buffer, buf_len); oid_buf_len = MAX_OID_LEN; buf_len = BUFSIZ; break; case AGENTX_MSG_CLOSE: DEBUGMSG(("dump_recv", "Close PDU\n")); pdu->errstat = *bufp; /* Reason */ bufp += 4; *length -= 4; break; case AGENTX_MSG_UNREGISTER: DEBUGMSG(("dump_recv", "Un")); case AGENTX_MSG_REGISTER: DEBUGMSG(("dump_recv", "Register PDU\n")); pdu->time = *bufp; /* Timeout (Register only) */ bufp++; pdu->priority = *bufp; bufp++; pdu->range_subid = *bufp; bufp++; bufp++; *length -= 4; prefix_ptr = bufp+1; DEBUGDUMPHEADER("dump_recv", "Parsing Registration OID\n"); bufp = agentx_parse_oid( bufp, length, NULL, oid_buffer, &oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); if ( bufp == NULL ) { DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } if ( pdu->range_subid ) { if ( *prefix_ptr ) { pdu->range_subid += 5; } range_bound = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); bufp += 4; *length -= 4; /* Construct the end-OID */ memmove( &end_oid_buf, oid_buffer, oid_buf_len*4 ); end_oid_buf_len = oid_buf_len*4; end_oid_buf[ pdu->range_subid-1 ] = range_bound; snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, ASN_PRIV_INCL_RANGE, (u_char *)end_oid_buf, end_oid_buf_len); } else { snmp_add_null_var( pdu, oid_buffer, oid_buf_len ); } oid_buf_len = MAX_OID_LEN; break; case AGENTX_MSG_GETBULK: DEBUGMSG(("dump_recv", "getbulk PDU\n")); DEBUGDUMPHEADER("dump_recv", "Parsing Non-repeaters\n"); pdu->non_repeaters = agentx_parse_short( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); DEBUGDUMPHEADER("dump_recv", "Parsing Max-repeaters\n"); pdu->max_repetitions = agentx_parse_short( bufp+2, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); DEBUGINDENTLESS(); bufp += 4; *length -= 4; /* Fallthrough - SearchRange handling is the same */ case AGENTX_MSG_GETNEXT: DEBUGMSG(("dump_recv", "next-")); case AGENTX_MSG_GET: DEBUGMSG(("dump_recv", "get PDU\n")); /* * SearchRange List * Keep going while we have data left */ DEBUGDUMPHEADER("dump_recv", "Parsing Search Range\n"); while ( *length > 0 ) { bufp = agentx_parse_oid( bufp, length, &inc, oid_buffer, &oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) { DEBUGINDENTLESS(); DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } bufp = agentx_parse_oid( bufp, length, NULL, end_oid_buf, &end_oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) { DEBUGINDENTLESS(); DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } end_oid_buf_len *= 4; /* 'agentx_parse_oid()' returns the number of sub_ids */ if ( inc ) snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, ASN_PRIV_INCL_RANGE, (u_char *)end_oid_buf, end_oid_buf_len); else snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, ASN_PRIV_EXCL_RANGE, (u_char *)end_oid_buf, end_oid_buf_len); } DEBUGINDENTLESS(); oid_buf_len = MAX_OID_LEN; end_oid_buf_len = MAX_OID_LEN; break; case AGENTX_MSG_RESPONSE: DEBUGMSG(("dump_recv", "response PDU\n")); pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU; /* sysUpTime */ pdu->time = agentx_parse_int( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); bufp += 4; *length -= 4; pdu->errstat = agentx_parse_short( bufp, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); pdu->errindex = agentx_parse_short( bufp+2, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); bufp += 4; *length -= 4; /* Fallthrough - VarBind handling is the same */ case AGENTX_MSG_INDEX_ALLOCATE: case AGENTX_MSG_INDEX_DEALLOCATE: case AGENTX_MSG_NOTIFY: case AGENTX_MSG_TESTSET: /* * VarBind List * Keep going while we have data left */ DEBUGDUMPHEADER("dump_recv", "Parsing VarBindList\n"); while ( *length > 0 ) { bufp = agentx_parse_varbind( bufp, length, &type, oid_buffer, &oid_buf_len, buffer, &buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) { DEBUGINDENTLESS(); DEBUGINDENTLESS(); return SNMPERR_ASN_PARSE_ERR; } snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, type, buffer, buf_len); oid_buf_len = MAX_OID_LEN; buf_len = BUFSIZ; } DEBUGINDENTLESS(); break; case AGENTX_MSG_COMMITSET: case AGENTX_MSG_UNDOSET: case AGENTX_MSG_CLEANUPSET: case AGENTX_MSG_PING: DEBUGMSG(("dump_recv", "set or ping PDU\n")); /* "Empty" packet */ break; case AGENTX_MSG_ADD_AGENT_CAPS: /* Store AgentCap OID & description in a VarBind */ DEBUGMSG(("dump_recv", "add agent caps PDU\n")); bufp = agentx_parse_oid( bufp, length, NULL, oid_buffer, &oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) return SNMPERR_ASN_PARSE_ERR; bufp = agentx_parse_string( bufp, length, buffer, &buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) return SNMPERR_ASN_PARSE_ERR; snmp_pdu_add_variable( pdu, oid_buffer, oid_buf_len, ASN_OCTET_STR, buffer, buf_len); oid_buf_len = MAX_OID_LEN; buf_len = BUFSIZ; break; case AGENTX_MSG_REMOVE_AGENT_CAPS: DEBUGMSG(("dump_recv", "remove agent caps PDU\n")); /* Store AgentCap OID & description in a VarBind */ bufp = agentx_parse_oid( bufp, length, NULL, oid_buffer, &oid_buf_len, pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER ); if ( bufp == NULL ) return SNMPERR_ASN_PARSE_ERR; snmp_add_null_var( pdu, oid_buffer, oid_buf_len ); oid_buf_len = MAX_OID_LEN; break; default: DEBUGMSG(("dump_recv", "Unrecognised PDU\n")); DEBUGINDENTLESS(); DEBUGINDENTLESS(); DEBUGMSGTL(("agentx","Unrecognised PDU type")); return SNMPERR_UNKNOWN_PDU; } DEBUGINDENTLESS(); DEBUGINDENTLESS(); return SNMP_ERR_NOERROR;} /*********************** * * Utility functions for dumping an AgentX packet * Cribbed shamelessly from the parsing code * * TODO: Properly structured indentation * ***********************/ intagentx_dump_int(u_char *data, u_int network_byte_order){ u_int value = agentx_parse_int( data, network_byte_order ); DEBUGMSGTL(("agentx","INTEGER %.2x %.2x %.2x %.2x = %d\n", *data, *(data+1), *(data+2), *(data+3), value)); return value;}intagentx_dump_short(u_char *data, u_int network_byte_order){ u_int value = agentx_parse_short( data, network_byte_order ); DEBUGMSGTL(("agentx","SHORT %.2x %.2x = %d\n", *data, *(data+1), value)); return value;}u_char *agentx_dump_oid( u_char *data, size_t *length, u_int network_byte_order){ u_int n_subid, subid; u_int prefix; int i; u_char *buf_ptr = data; if ( *length < 4 ) { DEBUGMSGTL(("agentx","Incomplete Object ID")); return NULL; } n_subid = data[0]; prefix = data[1];DEBUGMSGTL(("agentx","OBJECT ID #subids = %d, prefix = %d, inc = %d, (reserved %d)\n", data[1], data[0], data[2], data[3])); buf_ptr += 4; *length -= 4; if ( n_subid == 0 ) {DEBUGMSGTL(("agentx","\t NULL OID\n")); return buf_ptr; } if ( *length < 4*n_subid ) { DEBUGMSGTL(("agentx","Incomplete Object ID")); return NULL; } if ( prefix ) {DEBUGMSGTL(("agentx","\t [.1.3.6.1.%d]\n", prefix)); } for ( i = 0 ; i<n_subid ; i++ ) {DEBUGMSGTL(("agentx","\t ")); agentx_dump_int( buf_ptr, network_byte_order ); buf_ptr += 4; *length -= 4; } return buf_ptr;}u_char *agentx_dump_string( u_char *data, size_t *length, u_int network_byte_order){ u_int len, i; if ( *length <= 4 ) { DEBUGMSGTL(("agentx","Incomplete string")); return NULL; }DEBUGMSGTL(("agentx","STRING\n\tlength = ")); len = agentx_dump_int( data, network_byte_order ); if ( *length < len + 4 ) { DEBUGMSGTL(("agentx","Incomplete string")); return NULL; }DEBUGMSGTL(("agentx","\t DATA ")); for ( i = 0 ; i < len ; i++ ) { DEBUGMSGTL(("agentx"," %.2x", data[4+i])); }DEBUGMSGTL(("agentx","\n\t = %c", '"')); for ( i = 0 ; i < len ; i++ ) { DEBUGMSGTL(("agentx"," %c", data[4+i])); }DEBUGMSGTL(("agentx","%c\n", '"')); len += 3; /* Extend the string length to include the padding */ len >>= 2; len <<= 2; *length -= ( len+4 ); return data + ( len+4 );}u_char *agentx_dump_varbind( u_char *data, size_t *length, u_int network_byte_order){ u_char *bufp = data; u_int type; DEBUGMSGTL(("agentx","VARBIND\n\ttype = ")); type = agentx_dump_short( bufp, network_byte_order );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -