コード例 #1
0
ファイル: snmp_msg.c プロジェクト: geliang201201/lwip
static err_t
snmp_prepare_outbound_frame(struct snmp_request *request)
{
  struct snmp_asn1_tlv tlv;
  struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream);

  /* try allocating pbuf(s) for maximum response size */
  request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM);
  if (request->outbound_pbuf == NULL) {
    return ERR_MEM;
  }

  snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len);

  /* 'Message' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );

  /* version */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) );

  /* community */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) );

  /* 'PDU' sequence */
  request->outbound_pdu_offset = pbuf_stream->offset;
  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );

  /* request ID */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) );

  /* error status */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  request->outbound_error_status_offset = pbuf_stream->offset;
  snmp_pbuf_stream_write(pbuf_stream, 0);

  /* error index */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
  request->outbound_error_index_offset = pbuf_stream->offset;
  snmp_pbuf_stream_write(pbuf_stream, 0);

  /* 'VarBindList' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );

  request->outbound_varbind_offset = pbuf_stream->offset;

  return ERR_OK;
}
コード例 #2
0
ファイル: msg_out.c プロジェクト: harmv/lwip
/**
 * Encodes response header from head to tail.
 */
static u16_t
snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p)
{
  u16_t ofs;
  s32_t snmp_req_ver;

  ofs = 0;
  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen);
  ofs += m_stat->rhl.seqlenlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen);
  ofs += m_stat->rhl.verlenlen;
  snmp_req_ver = m_stat->version;
  snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_req_ver);
  ofs += m_stat->rhl.verlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen);
  ofs += m_stat->rhl.comlenlen;
  snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community);
  ofs += m_stat->rhl.comlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen);
  ofs += m_stat->rhl.pdulenlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen);
  ofs += m_stat->rhl.ridlenlen;
  snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid);
  ofs += m_stat->rhl.ridlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen);
  ofs += m_stat->rhl.errstatlenlen;
  snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status);
  ofs += m_stat->rhl.errstatlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen);
  ofs += m_stat->rhl.erridxlenlen;
  snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index);
  ofs += m_stat->rhl.erridxlen;

  return ofs;
}
コード例 #3
0
ファイル: snmp_traps.c プロジェクト: MorgothCreator/mSdk
/**
 * Encodes trap header from head to tail.
 */
static void
snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream)
{
  struct snmp_asn1_tlv tlv;

  /* 'Message' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);

  /* version */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version);

  /* community */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_raw(pbuf_stream,  (const u8_t *)snmp_community_trap, trap->comlen);

  /* 'PDU' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);

  /* object ID */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0);
  snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len);

  /* IP addr */
  if(IP_IS_V6_VAL(trap->sip)) {
#if LWIP_IPV6
    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr));
    snmp_ans1_enc_tlv(pbuf_stream, &tlv);
    snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr));
#endif
  } else {
#if LWIP_IPV4
    SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr));
    snmp_ans1_enc_tlv(pbuf_stream, &tlv);
    snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr));
#endif
  }

  /* trap length */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap);

  /* specific trap */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
  snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap);

  /* timestamp */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0);
  snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len);
  snmp_ans1_enc_tlv(pbuf_stream, &tlv);
  snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts);
}
コード例 #4
0
ファイル: msg_out.c プロジェクト: comrid1987/jb3500
/**
 * Encodes varbind list from head to tail.
 */
static u16_t
snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs)
{
  struct snmp_varbind *vb;
  s32_t *sint_ptr;
  u32_t *uint_ptr;
  u8_t *raw_ptr;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, root->seqlen);
  ofs += root->seqlenlen;

  vb = root->head;
  while ( vb != NULL )
  {
    snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
    ofs += 1;
    snmp_asn1_enc_length(p, ofs, vb->seqlen);
    ofs += vb->seqlenlen;

    snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));
    ofs += 1;
    snmp_asn1_enc_length(p, ofs, vb->olen);
    ofs += vb->olenlen;
    snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]);
    ofs += vb->olen;

    snmp_asn1_enc_type(p, ofs, vb->value_type);
    ofs += 1;
    snmp_asn1_enc_length(p, ofs, vb->vlen);
    ofs += vb->vlenlen;

    switch (vb->value_type)
    {
      case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
        sint_ptr = (s32_t*)vb->value;
        snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr);
        break;
      case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
      case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
      case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
        uint_ptr = (u32_t*)vb->value;
        snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr);
        break;
      case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
      case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
      case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
        raw_ptr = (u8_t*)vb->value;
        snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr);
        break;
      case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
        break;
      case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
        sint_ptr = (s32_t*)vb->value;
        snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr);
        break;
      default:
        /* unsupported type */
        break;
    };
    ofs += vb->vlen;
    vb = vb->next;
  }
  return ofs;
}
コード例 #5
0
ファイル: msg_out.c プロジェクト: comrid1987/jb3500
/**
 * Encodes trap header from head to tail.
 */
static u16_t
snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p)
{
  u16_t ofs;

  ofs = 0;
  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen);
  ofs += m_trap->thl.seqlenlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen);
  ofs += m_trap->thl.verlenlen;
  snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version);
  ofs += m_trap->thl.verlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen);
  ofs += m_trap->thl.comlenlen;
  snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]);
  ofs += m_trap->thl.comlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen);
  ofs += m_trap->thl.pdulenlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen);
  ofs += m_trap->thl.eidlenlen;
  snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]);
  ofs += m_trap->thl.eidlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen);
  ofs += m_trap->thl.aaddrlenlen;
  snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]);
  ofs += m_trap->thl.aaddrlen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen);
  ofs += m_trap->thl.gtrplenlen;
  snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap);
  ofs += m_trap->thl.gtrplen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen);
  ofs += m_trap->thl.strplenlen;
  snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap);
  ofs += m_trap->thl.strplen;

  snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS));
  ofs += 1;
  snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen);
  ofs += m_trap->thl.tslenlen;
  snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts);
  ofs += m_trap->thl.tslen;

  return ofs;
}
コード例 #6
0
ファイル: snmp_msg.c プロジェクト: geliang201201/lwip
static err_t
snmp_complete_outbound_frame(struct snmp_request *request)
{
  struct snmp_asn1_tlv tlv;
  u16_t frame_size;

  if (request->version == SNMP_VERSION_1) {
    if (request->error_status != SNMP_ERR_NOERROR) {
      /* map v2c error codes to v1 compliant error code (according to RFC 2089) */
      switch (request->error_status) {
        /* mapping of implementation specific "virtual" error codes 
         * (during processing of frame we already stored them in error_status field, 
         * so no need to check all varbinds here for those exceptions as suggested by RFC) */
        case SNMP_ERR_NOSUCHINSTANCE:
        case SNMP_ERR_NOSUCHOBJECT:
        case SNMP_ERR_ENDOFMIBVIEW:
          request->error_status = SNMP_ERR_NOSUCHNAME; break;
        /* mapping according to RFC */
        case SNMP_ERR_WRONGVALUE:
        case SNMP_ERR_WRONGENCODING:
        case SNMP_ERR_WRONGTYPE:
        case SNMP_ERR_WRONGLENGTH:
        case SNMP_ERR_INCONSISTENTVALUE:
          request->error_status = SNMP_ERR_BADVALUE; break;
        case SNMP_ERR_NOACCESS:
        case SNMP_ERR_NOTWRITABLE:
        case SNMP_ERR_NOCREATION:
        case SNMP_ERR_INCONSISTENTNAME:
        case SNMP_ERR_AUTHORIZATIONERROR:
          request->error_status = SNMP_ERR_NOSUCHNAME; break;
        case SNMP_ERR_RESOURCEUNAVAILABLE:
        case SNMP_ERR_COMMITFAILED:
        case SNMP_ERR_UNDOFAILED:
        default:
          request->error_status = SNMP_ERR_GENERROR; break;
       }
    }
  } else {
    if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
      /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */
      LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
      return ERR_ABRT;
    }
  }

  if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) {
    /* all inbound vars are returned in response without any modification for error responses and successful set requests*/
    struct snmp_pbuf_stream inbound_stream;
    OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) );
    OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) );
    snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0);
  }

  frame_size = request->outbound_pbuf_stream.offset;

  /* complete mssing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) );
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );

  /* complete mssing length in 'PDU' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) );
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );

  /* process and encode final error status */
  if (request->error_status != 0) {
    u16_t len;
    snmp_asn1_enc_s32t_cnt(request->error_status, &len);
    if (len != 1) {
      /* error, we only reserved one byte for it */
      return ERR_ABRT;
    }
    OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) );
    OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) );

    /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */
    switch (request->error_status) {
      case SNMP_ERR_TOOBIG:
        snmp_stats.outtoobigs++;
        break;
      case SNMP_ERR_NOSUCHNAME:
        snmp_stats.outnosuchnames++;
        break;
      case SNMP_ERR_BADVALUE:
        snmp_stats.outbadvalues++;
        break;
      case SNMP_ERR_GENERROR:
      default:
        snmp_stats.outgenerrs++;
        break;
    }

    if (request->error_status == SNMP_ERR_TOOBIG) {
      request->error_index = 0; /* defined by RFC 1157 */
    } else if (request->error_index == 0) {
      /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */
      request->error_index = request->inbound_varbind_enumerator.varbind_count;
    }
  } else {
    if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
      snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count;
    } else {
      snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count;
    }
  }

  /* encode final error index*/
  if (request->error_index != 0) {
    u16_t len;
    snmp_asn1_enc_s32t_cnt(request->error_index, &len);
    if (len != 1) {
      /* error, we only reserved one byte for it */
      return ERR_VAL;
    }
    OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) );
    OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) );
  }

  /* complete mssing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset);
  OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
  OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );

  pbuf_realloc(request->outbound_pbuf, frame_size);

  snmp_stats.outgetresponses++;
  snmp_stats.outpkts++;

  return ERR_OK;
}
コード例 #7
0
ファイル: snmp_msg.c プロジェクト: geliang201201/lwip
static err_t
snmp_append_outbound_varbind(struct snmp_request *request, struct snmp_varbind* varbind)
{
  struct snmp_asn1_tlv tlv;
  u8_t  vb_len_len,   oid_len_len,   value_len_len;
  u16_t vb_value_len, oid_value_len, value_value_len;

  /* calculate required lengths */
  snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &oid_value_len);
  snmp_asn1_enc_length_cnt(oid_value_len, &oid_len_len);

  if (varbind->value_len == 0) {
    value_value_len = 0;
  } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
    value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA);
  } else {
    switch (varbind->type)
    {
      case SNMP_ASN1_TYPE_INTEGER:
        if (varbind->value_len != sizeof(s32_t)) {
          return ERR_VAL;
        }
        snmp_asn1_enc_s32t_cnt(*((s32_t*)varbind->value) , &value_value_len);
        break;
      case SNMP_ASN1_TYPE_COUNTER:
      case SNMP_ASN1_TYPE_GAUGE:
      case SNMP_ASN1_TYPE_TIMETICKS:
        if (varbind->value_len != sizeof(u32_t)) {
          return ERR_VAL;
        }
        snmp_asn1_enc_u32t_cnt(*((u32_t*)varbind->value) , &value_value_len);
        break;
      case SNMP_ASN1_TYPE_OCTET_STRING:
      case SNMP_ASN1_TYPE_IPADDR:
      case SNMP_ASN1_TYPE_OPAQUE:
        value_value_len = varbind->value_len;
        break;
      case SNMP_ASN1_TYPE_NULL:
        if (varbind->value_len != 0) {
          return ERR_VAL;
        }
        value_value_len = 0;
        break;
      case SNMP_ASN1_TYPE_OBJECT_ID:
        if ((varbind->value_len % sizeof(u32_t)) != 0) {
          return ERR_VAL;
        }
        snmp_asn1_enc_oid_cnt((u32_t*)varbind->value, varbind->value_len / sizeof(u32_t), &value_value_len);
        break;
      case SNMP_ASN1_TYPE_COUNTER64:
        if (varbind->value_len != (2 * sizeof(u32_t))) {
          return ERR_VAL;
        }
        snmp_asn1_enc_u64t_cnt((u32_t*)varbind->value , &value_value_len);
        break;
      default:
        /* unsupported type */
        return ERR_VAL;
    }
  }
  snmp_asn1_enc_length_cnt(value_value_len, &value_len_len);
  
  vb_value_len = 1 + oid_len_len + oid_value_len + 1 + value_len_len + value_value_len;
  snmp_asn1_enc_length_cnt(vb_value_len, &vb_len_len);

  /* check length already before adding first data because in case of GetBulk,
   *  data added so far is returned and therefore no partial data shall be added
   */
  if ((1 + vb_len_len + vb_value_len) > request->outbound_pbuf_stream.length) {
    return ERR_BUF;
  }

  /* 'VarBind' sequence */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, vb_len_len, vb_value_len);
  OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );

  /* VarBind OID */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, oid_len_len, oid_value_len);
  OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
  OVB_BUILD_EXEC( snmp_asn1_enc_oid(&(request->outbound_pbuf_stream), varbind->oid.id, varbind->oid.len) );
  
  /* VarBind value */
  SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, value_len_len, value_value_len);
  OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );

  if (value_value_len > 0) {
    if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
      OVB_BUILD_EXEC( snmp_asn1_enc_raw(&(request->outbound_pbuf_stream), (u8_t*)varbind->value, value_value_len) );
    } else {
      switch (varbind->type)
      {
        case SNMP_ASN1_TYPE_INTEGER:
          OVB_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), value_value_len, *((s32_t*)varbind->value)) );
          break;
        case SNMP_ASN1_TYPE_COUNTER:
        case SNMP_ASN1_TYPE_GAUGE:
        case SNMP_ASN1_TYPE_TIMETICKS:
          OVB_BUILD_EXEC( snmp_asn1_enc_u32t(&(request->outbound_pbuf_stream), value_value_len, *((u32_t*)varbind->value)) );
          break;
        case SNMP_ASN1_TYPE_OCTET_STRING:
        case SNMP_ASN1_TYPE_IPADDR:
        case SNMP_ASN1_TYPE_OPAQUE:
          OVB_BUILD_EXEC( snmp_asn1_enc_raw(&(request->outbound_pbuf_stream), (u8_t*)varbind->value, value_value_len) );
          value_value_len = varbind->value_len;
          break;
        case SNMP_ASN1_TYPE_OBJECT_ID:
          OVB_BUILD_EXEC( snmp_asn1_enc_oid(&(request->outbound_pbuf_stream), (u32_t*)varbind->value, varbind->value_len / sizeof(u32_t)) );
          break;
        case SNMP_ASN1_TYPE_COUNTER64:
          OVB_BUILD_EXEC( snmp_asn1_enc_u64t(&(request->outbound_pbuf_stream), value_value_len, (u32_t*)varbind->value) );
          break;
        default:
          LWIP_ASSERT("Unknown variable type", 0);
          break;
      }
    }
  }

  return ERR_OK;
}