FreeBSD/contrib/bsnmp/lib/snmpagent.c
/*
 * Make an error response from a PDU. We do this without decoding the
 * variable bindings. This means we can sent the junk back to a caller
 * that has sent us junk in the first place. 
 */
Make an error response from a PDU. We do this without decoding the
variable bindings. This means we can sent the junk back to a caller
that has sent us junk in the first place.
Make an error response from a PDU . We do this without decoding the variable bindings . This means we can sent the junk back to a caller that has sent us junk in the first place .
enum snmp_ret
snmp_make_errresp(const struct snmp_pdu *pdu, struct asn_buf *pdu_b,
    struct asn_buf *resp_b)
{
	u_char type;
	asn_len_t len;
	struct snmp_pdu resp;
	enum asn_err err;
	enum snmp_code code;
	snmp_pdu_create_response(pdu, &resp);
	if ((code = snmp_pdu_decode_header(pdu_b, &resp)) != SNMP_CODE_OK)
		return (SNMP_RET_IGN);
	if (pdu->version == SNMP_V3) {
		if (resp.user.priv_proto != SNMP_PRIV_NOPRIV &&
		   (asn_get_header(pdu_b, &type, &resp.scoped_len) != ASN_ERR_OK
		   || type != ASN_TYPE_OCTETSTRING)) {
			snmp_error("cannot decode encrypted pdu");
			return (SNMP_RET_IGN);
		}
		if (asn_get_sequence(pdu_b, &len) != ASN_ERR_OK) {
			snmp_error("cannot decode scoped pdu header");
			return (SNMP_RET_IGN);
		}
		len = SNMP_ENGINE_ID_SIZ;
		if (asn_get_octetstring(pdu_b, (u_char *)resp.context_engine,
		    &len) != ASN_ERR_OK) {
			snmp_error("cannot decode msg context engine");
			return (SNMP_RET_IGN);
		}
		resp.context_engine_len = len;
		len = SNMP_CONTEXT_NAME_SIZ;
		if (asn_get_octetstring(pdu_b, (u_char *)resp.context_name,
		    &len) != ASN_ERR_OK) {
			snmp_error("cannot decode msg context name");
			return (SNMP_RET_IGN);
		}
		resp.context_name[len] = '\0';
	}
	if (asn_get_header(pdu_b, &type, &len) != ASN_ERR_OK) {
		snmp_error("cannot get pdu header");
		return (SNMP_RET_IGN);
	}
	if ((type & ~ASN_TYPE_MASK) !=
	    (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) {
		snmp_error("bad pdu header tag");
		return (SNMP_RET_IGN);
	}
	err = snmp_parse_pdus_hdr(pdu_b, &resp, &len);
	if (ASN_ERR_STOPPED(err))
		return (SNMP_RET_IGN);
	if (pdu_b->asn_len < len)
		return (SNMP_RET_IGN);
	pdu_b->asn_len = len;
	resp.error_status = pdu->error_status;
	resp.error_index = pdu->error_index;
	resp.type = SNMP_PDU_RESPONSE;
	code = snmp_pdu_encode_header(resp_b, &resp);
	if (code != SNMP_CODE_OK)
		return (SNMP_RET_IGN);
	if (pdu_b->asn_len > resp_b->asn_len)
		return (SNMP_RET_IGN);
	(void)memcpy(resp_b->asn_ptr, pdu_b->asn_cptr, pdu_b->asn_len);
	resp_b->asn_len -= pdu_b->asn_len;
	resp_b->asn_ptr += pdu_b->asn_len;
	code = snmp_fix_encoding(resp_b, &resp);
	if (code != SNMP_CODE_OK)
		return (SNMP_RET_IGN);
	return (SNMP_RET_OK);
}
enum snmp_ret snmp_make_errresp ( const struct snmp_pdu * pdu , struct asn_buf * pdu_b , struct asn_buf * resp_b ) { u_char type ; asn_len_t len ; struct snmp_pdu resp ; enum asn_err err ; enum snmp_code code ; snmp_pdu_create_response ( pdu , & resp ) ; if ( ( code = snmp_pdu_decode_header ( pdu_b , & resp ) ) != SNMP_CODE_OK ) return ( SNMP_RET_IGN ) ; if ( pdu -> version == SNMP_V3 ) { if ( resp . user . priv_proto != SNMP_PRIV_NOPRIV && ( asn_get_header ( pdu_b , & type , & resp . scoped_len ) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING ) ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } if ( asn_get_sequence ( pdu_b , & len ) != ASN_ERR_OK ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } len = SNMP_ENGINE_ID_SIZ ; if ( asn_get_octetstring ( pdu_b , ( u_char * ) resp . context_engine , & len ) != ASN_ERR_OK ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } resp . context_engine_len = len ; len = SNMP_CONTEXT_NAME_SIZ ; if ( asn_get_octetstring ( pdu_b , ( u_char * ) resp . context_name , & len ) != ASN_ERR_OK ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } resp . context_name [ len ] = ' \0 ' ; } if ( asn_get_header ( pdu_b , & type , & len ) != ASN_ERR_OK ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } if ( ( type & ~ ASN_TYPE_MASK ) != ( ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT ) ) { snmp_error ( " " ) ; return ( SNMP_RET_IGN ) ; } err = snmp_parse_pdus_hdr ( pdu_b , & resp , & len ) ; if ( ASN_ERR_STOPPED ( err ) ) return ( SNMP_RET_IGN ) ; if ( pdu_b -> asn_len < len ) return ( SNMP_RET_IGN ) ; pdu_b -> asn_len = len ; resp . error_status = pdu -> error_status ; resp . error_index = pdu -> error_index ; resp . type = SNMP_PDU_RESPONSE ; code = snmp_pdu_encode_header ( resp_b , & resp ) ; if ( code != SNMP_CODE_OK ) return ( SNMP_RET_IGN ) ; if ( pdu_b -> asn_len > resp_b -> asn_len ) return ( SNMP_RET_IGN ) ; ( void ) memcpy ( resp_b -> asn_ptr , pdu_b -> asn_cptr , pdu_b -> asn_len ) ; resp_b -> asn_len -= pdu_b -> asn_len ; resp_b -> asn_ptr += pdu_b -> asn_len ; code = snmp_fix_encoding ( resp_b , & resp ) ; if ( code != SNMP_CODE_OK ) return ( SNMP_RET_IGN ) ; return ( SNMP_RET_OK ) ; }
Make an error response from a PDU.
Make an error response from a PDU .
/* now we have the bindings left - construct new message */ /* too short */