示例#1
0
文件: msg_out.c 项目: harmv/lwip
/**
 * Sums varbind lengths from tail to head and
 * annotates lengths in varbind for second encoding pass.
 *
 * @param root points to the root of the variable binding list
 * @return the required length for encoding the variable bindings
 */
static u16_t
snmp_varbind_list_sum(struct snmp_varbind_root *root)
{
  struct snmp_varbind *vb;
  u32_t *uint_ptr;
  s32_t *sint_ptr;
  u16_t tot_len;

  tot_len = 0;
  vb = root->tail;
  while (vb != NULL) {
    /* encoded value lenght depends on type */
    switch (vb->value_type) {
    case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
      sint_ptr = (s32_t*)vb->value;
      snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen);
      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_cnt(*uint_ptr, &vb->vlen);
      break;
    case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
    case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
    case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
    case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
      vb->vlen = vb->value_len;
      break;
    case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
      sint_ptr = (s32_t*)vb->value;
      snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen);
      break;
    default:
      /* unsupported type */
      vb->vlen = 0;
      break;
    }
    /* encoding length of value length field */
    snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen);
    snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen);
    snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen);

    vb->seqlen = 1 + vb->vlenlen + vb->vlen;
    vb->seqlen += 1 + vb->olenlen + vb->olen;
    snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen);

    /* varbind seq */
    tot_len += 1 + vb->seqlenlen + vb->seqlen;

    vb = vb->prev;
  }

  /* varbind-list seq */
  root->seqlen = tot_len;
  snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen);
  tot_len += 1 + root->seqlenlen;

  return tot_len;
}
示例#2
0
/**
 * Sums trap header field lengths from tail to head and
 * returns trap_header_lengths for second encoding pass.
 *
 * @param vb_len varbind-list length
 * @param thl points to returned header lengths
 * @return the required length for encoding the trap header
 */
static u16_t
snmp_trap_header_sum(struct snmp_msg_trap *trap)
{
  u16_t tot_len;
  u16_t len;
  u8_t lenlen;

  tot_len = 0;

  snmp_asn1_enc_u32t_cnt(trap->ts, &len);
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len);
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len);
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  if(IP_IS_V6_VAL(trap->sip)) {
#if LWIP_IPV6
    len = sizeof(ip_2_ip6(&trap->sip)->addr);
#endif
  } else {
#if LWIP_IPV4
    len = sizeof(ip_2_ip4(&trap->sip)->addr);
#endif
  }
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len);
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  trap->pdulen = tot_len;
  snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen);
  tot_len += 1 + lenlen;

  trap->comlen = (u16_t)strlen(snmp_community_trap);
  snmp_asn1_enc_length_cnt(trap->comlen, &lenlen);
  tot_len += 1 + lenlen + trap->comlen;

  snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len);
  snmp_asn1_enc_length_cnt(len, &lenlen);
  tot_len += 1 + len + lenlen;

  trap->seqlen = tot_len;
  snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen);
  tot_len += 1 + lenlen;

  return tot_len;
}
示例#3
0
/**
 * Sums trap header field lengths from tail to head and
 * returns trap_header_lengths for second encoding pass.
 *
 * @param vb_len varbind-list length
 * @param thl points to returned header lengths
 * @return the required lenght for encoding the trap header
 */
static u16_t
snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len)
{
  u16_t tot_len;
  struct snmp_trap_header_lengths *thl;

  thl = &m_trap->thl;
  tot_len = vb_len;

  snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen);
  snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen);
  tot_len += 1 + thl->tslen + thl->tslenlen;

  snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen);
  snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen);
  tot_len += 1 + thl->strplen + thl->strplenlen;

  snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen);
  snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen);
  tot_len += 1 + thl->gtrplen + thl->gtrplenlen;

  thl->aaddrlen = 4;
  snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen);
  tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen;

  snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen);
  snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen);
  tot_len += 1 + thl->eidlen + thl->eidlenlen;

  thl->pdulen = tot_len;
  snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen);
  tot_len += 1 + thl->pdulenlen;

  thl->comlen = sizeof(snmp_publiccommunity) - 1;
  snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen);
  tot_len += 1 + thl->comlenlen + thl->comlen;

  snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen);
  snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen);
  tot_len += 1 + thl->verlen + thl->verlenlen;

  thl->seqlen = tot_len;
  snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen);
  tot_len += 1 + thl->seqlenlen;

  return tot_len;
}
示例#4
0
/**
 * 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);
}
示例#5
0
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;
}