Beispiel #1
0
int snmp_msg_read(pool *p, unsigned char **buf, size_t *buflen,
    char **community, unsigned int *community_len, long *snmp_version,
    struct snmp_pdu **pdu) {
  unsigned char asn1_type;
  unsigned int asn1_len;
  int res;

  res = snmp_asn1_read_header(p, buf, buflen, &asn1_type, &asn1_len, 0);
  if (res < 0) {
    return -1;
  }

  if (asn1_type != (SNMP_ASN1_TYPE_SEQUENCE|SNMP_ASN1_CONSTRUCT)) {
    pr_trace_msg(trace_channel, 3,
      "unable to read SNMP message (tag '%s')",
      snmp_asn1_get_tagstr(p, asn1_type));

    errno = EINVAL;
    return -1;
  }

  res = snmp_asn1_read_int(p, buf, buflen, &asn1_type, snmp_version, 0);
  if (res < 0) {
    return -1;
  }

  pr_trace_msg(trace_channel, 17,
    "read SNMP message for %s", snmp_msg_get_versionstr(*snmp_version));

  /* XXX Don't support SNMPv3 yet. */

  if (*snmp_version != SNMP_PROTOCOL_VERSION_1 &&
      *snmp_version != SNMP_PROTOCOL_VERSION_2) {
    (void) pr_log_writefile(snmp_logfd, MOD_SNMP_VERSION,
      "%s messages not currently supported, dropping packet",
      snmp_msg_get_versionstr(*snmp_version));

    res = snmp_db_incr_value(p, SNMP_DB_SNMP_F_PKTS_DROPPED_TOTAL, 1);
    if (res < 0) {
      (void) pr_log_writefile(snmp_logfd, MOD_SNMP_VERSION,
        "error incrementing snmp.packetsDroppedTotal: %s", strerror(errno));
    }

    errno = ENOSYS;
    return -1;
  }

  res = snmp_asn1_read_string(p, buf, buflen, &asn1_type, community,
    community_len);
  if (res < 0) {
    return -1;
  }

  /* Check that asn1_type is a UNIVERSTAL/PRIMITIVE/OCTETSTRING. */
  if (!(asn1_type == (SNMP_ASN1_CLASS_UNIVERSAL|SNMP_ASN1_PRIMITIVE|SNMP_ASN1_TYPE_OCTETSTRING))) {
    pr_trace_msg(trace_channel, 3,
      "unable to read OCTET_STRING (received type '%s')",
      snmp_asn1_get_tagstr(p, asn1_type));
    errno = EINVAL;
    return -1;
  }

  pr_trace_msg(trace_channel, 17,
    "read %s message: community = '%s'",
    snmp_msg_get_versionstr(*snmp_version), *community);

  res = snmp_pdu_read(p, buf, buflen, pdu, *snmp_version);
  if (res < 0) {
    return -1;
  }

  return 0;
}
Beispiel #2
0
int snmp_pdu_read(pool *p, unsigned char **buf, size_t *buflen,
    struct snmp_pdu **pdu, long snmp_version) {
  unsigned char asn1_type;
  unsigned int asn1_len;
  int flags, res;

  /* Since the "type" in this header is the PDU request type, the trace logging
   * of the ASN.1 type will be wrong.  That being the case, simply tell the
   * readers to not trace log that wrong invalid ASN.1 type.  Makes the
   * trace logging confusing and incorrect.
   */
  flags = SNMP_ASN1_FL_NO_TRACE_TYPESTR;

  res = snmp_asn1_read_header(p, buf, buflen, &asn1_type, &asn1_len, flags);
  if (res < 0) {
    return -1;
  }

  pr_trace_msg(trace_channel, 19,
    "read in PDU (0x%02x), length %u bytes", asn1_type, asn1_len);

  *pdu = snmp_pdu_create(p, asn1_type);

  switch (asn1_type) {
    case SNMP_PDU_RESPONSE:
    case SNMP_PDU_TRAP_V1:
    case SNMP_PDU_TRAP_V2:
    case SNMP_PDU_INFORM:
    case SNMP_PDU_REPORT:
      pr_trace_msg(trace_channel, 1,
        "handling '%s' PDU not currently supported",
        snmp_pdu_get_request_type_desc((*pdu)->request_type));
      errno = ENOSYS;
      return -1;

    case SNMP_PDU_GETBULK:
      /* Request ID */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->request_id), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU request ID: %ld", (*pdu)->request_id);

      /* Non-repeaters */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->non_repeaters), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU non-repeaters: %ld", (*pdu)->non_repeaters);

      /* As per RFC1905, if non_repeaters is negative, it is set to zero. */
      if ((*pdu)->non_repeaters < 0) {
        (*pdu)->non_repeaters = 0;
      }

      /* Max-repetitions */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->max_repetitions), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU max-repetitions: %ld", (*pdu)->max_repetitions);

      /* As per RFC1905, if max_repetitions is negative, it is set to zero. */
      if ((*pdu)->max_repetitions < 0) {
        (*pdu)->max_repetitions = 0;
      }

      break;

    default:
      /* Request ID */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->request_id), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU request ID: %ld", (*pdu)->request_id);

      /* Error Status/Code */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->err_code), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU error status/code: %ld", (*pdu)->err_code);

      /* XXX What if err_code is non-zero? */

      /* Error Index */
      res = snmp_asn1_read_int(p, buf, buflen, &asn1_type,
        &((*pdu)->err_idx), 0);
      if (res < 0) {
        return -1;
      }
      pr_trace_msg(trace_channel, 19,
        "read PDU error index: %ld", (*pdu)->err_idx);

      /* XXX What if err_idx is non-zero? */

      break;
  }

  res = snmp_smi_read_vars(p, buf, buflen, &((*pdu)->varlist), snmp_version);
  if (res < 0) {
    return -1;
  }

  (*pdu)->varlistlen = res;

  pr_trace_msg(trace_channel, 17,
    "read %d %s from %s message", res,
    res != 1 ? "variables" : "variable",
    snmp_msg_get_versionstr(snmp_version));

  return 0;
}