⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snmp_api.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return 0;
}

static void
snmpv3_calc_msg_flags (int sec_level, int msg_command, u_char *flags)
{
  *flags = 0;
  if (sec_level == SNMP_SEC_LEVEL_AUTHNOPRIV)
    *flags = SNMP_MSG_FLAG_AUTH_BIT;
  else if (sec_level == SNMP_SEC_LEVEL_AUTHPRIV)
    *flags = SNMP_MSG_FLAG_AUTH_BIT | SNMP_MSG_FLAG_PRIV_BIT;

  if (SNMP_CMD_CONFIRMED(msg_command)) *flags |= SNMP_MSG_FLAG_RPRT_BIT;

  return;
}

static int
snmpv3_verify_msg(struct request_list *rp, struct snmp_pdu *pdu)
{
  struct snmp_pdu     *rpdu;
  
  if (!rp || !rp->pdu || !pdu) return 0;
  /* Reports don't have to match anything according to the spec */
  if (pdu->command == SNMP_MSG_REPORT) return 1;
  rpdu = rp->pdu;
  if (rp->request_id != pdu->reqid || rpdu->reqid != pdu->reqid) return 0;
  if (rpdu->version != pdu->version) return 0;
  if (rpdu->securityModel != pdu->securityModel) return 0;
  if (rpdu->securityLevel != pdu->securityLevel) return 0;

  if (rpdu->contextEngineIDLen != pdu->contextEngineIDLen || 
      memcmp(rpdu->contextEngineID, pdu->contextEngineID, 
	     pdu->contextEngineIDLen))
    return 0;
  if (rpdu->contextNameLen != pdu->contextNameLen || 
      memcmp(rpdu->contextName, pdu->contextName, pdu->contextNameLen)) 
    return 0;
  if (rpdu->securityEngineIDLen != pdu->securityEngineIDLen || 
      memcmp(rpdu->securityEngineID, pdu->securityEngineID, 
	     pdu->securityEngineIDLen))
    return 0;
  if (rpdu->securityNameLen != pdu->securityNameLen || 
      memcmp(rpdu->securityName, pdu->securityName, pdu->securityNameLen)) 
    return 0;
  return 1;
}


/* SNMPv3
 * Takes a session and a pdu and serializes the ASN PDU into the area
 * pointed to by packet.  out_length is the size of the data area available.
 * Returns the length of the completed packet in out_length.  If any errors
 * occur, -1 is returned.  If all goes well, 0 is returned.
 */
static int
snmpv3_build(struct snmp_session	*session,
             struct snmp_pdu	        *pdu,
             u_char	        	*packet,
             size_t			*out_length)
{
  int ret;

    session->s_snmp_errno = 0;
    session->s_errno = 0;

	/* do validation for PDU types */
  switch (pdu->command) {
	case SNMP_MSG_RESPONSE:
	case SNMP_MSG_TRAP2:
	case SNMP_MSG_REPORT:
	    pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE);
	    /* Fallthrough */
	case SNMP_MSG_GET:
	case SNMP_MSG_GETNEXT:
	case SNMP_MSG_SET:
	case SNMP_MSG_INFORM:
	    if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
	        pdu->errstat = 0;
	    if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
	        pdu->errindex = 0;
	    break;

	case SNMP_MSG_GETBULK:
	    if (pdu->max_repetitions < 0) {
	        session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
	        return -1;
	    }
	    if (pdu->non_repeaters < 0) {
	        session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
	        return -1;
	    }
	    break;

	case SNMP_MSG_TRAP:
	    session->s_snmp_errno = SNMPERR_V1_IN_V2;
	    return -1;
	
	default:
	    session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
	    return -1;
  }

      if (pdu->securityEngineIDLen == 0) {
	if (session->securityEngineIDLen) {
	  snmpv3_clone_engineID(&pdu->securityEngineID, 
				&pdu->securityEngineIDLen,
				session->securityEngineID,
				session->securityEngineIDLen);
	}
      }

      if (pdu->contextEngineIDLen == 0) {
	if (session->contextEngineIDLen) {
	  snmpv3_clone_engineID(&pdu->contextEngineID, 
				&pdu->contextEngineIDLen,
				session->contextEngineID,
				session->contextEngineIDLen);
	} else if (pdu->securityEngineIDLen) {
	  snmpv3_clone_engineID(&pdu->contextEngineID, 
				&pdu->contextEngineIDLen,
				pdu->securityEngineID,
				pdu->securityEngineIDLen);
	}
      }

      if (pdu->contextName == NULL) {
	if (!session->contextName){
	  session->s_snmp_errno = SNMPERR_BAD_CONTEXT;
	  return -1;
	}
	pdu->contextName = strdup(session->contextName);
	if (pdu->contextName == NULL) {
	  session->s_snmp_errno = SNMPERR_GENERR;
	  return -1;
	}
	pdu->contextNameLen = session->contextNameLen;
      }
      pdu->securityModel = SNMP_SEC_MODEL_USM;
      if (pdu->securityNameLen == 0 && pdu->securityName == 0) {
	if (session->securityNameLen == 0){
	  session->s_snmp_errno = SNMPERR_BAD_SEC_NAME;
	  return -1;
	}
	pdu->securityName = strdup(session->securityName);
	if (pdu->securityName == NULL) {
	  session->s_snmp_errno = SNMPERR_GENERR;
	  return -1;
	}
	pdu->securityNameLen = session->securityNameLen;
      }
      if (pdu->securityLevel == 0) {
	if (session->securityLevel == 0) {
	    session->s_snmp_errno = SNMPERR_BAD_SEC_LEVEL;
	    return -1;
	}
	pdu->securityLevel = session->securityLevel;
      }
      DEBUGMSGTL(("snmp_build",
                  "Building SNMPv3 message (secName:\"%s\", secLevel:%s)...\n",
                  ((session->securityName) ? (char *)session->securityName :
                   ((pdu->securityName) ? (char *)pdu->securityName : 
                    "ERROR: undefined")),
                  usmSecLevelName[pdu->securityLevel]));

  ret = snmpv3_packet_build(pdu, packet, out_length, NULL, 0);
  if (-1 != ret) {
      session->s_snmp_errno = ret;
  }

  return ret;

}  /* end snmpv3_build() */




static u_char *
snmpv3_header_build(struct snmp_pdu *pdu, u_char *packet,
                    size_t *out_length, size_t length, u_char **msg_hdr_e)

{
    u_char			*global_hdr, *global_hdr_e;
    u_char 			*cp;
    u_char			 msg_flags;
    long			 max_size;
    long			 sec_model;
    u_char			*pb, *pb0e;

    /* Save current location and build SEQUENCE tag and length placeholder
     * for SNMP message sequence (actual length inserted later)
     */
    cp = asn_build_sequence(packet, out_length,
			    (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), length);
    if (cp == NULL) return NULL;
    if (msg_hdr_e != NULL)
      *msg_hdr_e = cp;
    pb0e = cp;


    /* store the version field - msgVersion
     */
    cp = asn_build_int(cp, out_length,
		       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
		       (long *) &pdu->version, sizeof(pdu->version));
    if (cp == NULL) return NULL;

    global_hdr = cp;
    /* msgGlobalData HeaderData */
    cp = asn_build_sequence(cp, out_length,
			    (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
    if (cp == NULL) return NULL;
    global_hdr_e = cp;


    /* msgID */
    cp = asn_build_int(cp, out_length,
		       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
		       &pdu->msgid, sizeof(pdu->msgid));
    if (cp == NULL) return NULL;

    							/* msgMaxSize */
    max_size = SNMP_MAX_MSG_SIZE;
    cp = asn_build_int(cp, out_length,
		       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
		       &max_size, sizeof(max_size));
    if (cp == NULL) return NULL;

    /* msgFlags */
    snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
    cp = asn_build_string(cp, out_length,
			  (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
			  &msg_flags, sizeof(msg_flags));
    if (cp == NULL) return NULL;

    							/* msgSecurityModel */
    sec_model = SNMP_SEC_MODEL_USM;
    cp = asn_build_int(cp, out_length,
		       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
		       &sec_model, sizeof(sec_model));
    if (cp == NULL) return NULL;


    /* insert actual length of globalData
     */
    pb = asn_build_sequence(global_hdr, out_length,
                            (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
                            cp - global_hdr_e);
    if (pb == NULL) return NULL;


    /* insert the actual length of the entire packet
     */
    pb = asn_build_sequence(packet, out_length,
			    (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
                            length + (cp - pb0e));
    if (pb == NULL) return NULL;

    return cp;

}  /* end snmpv3_header_build() */



static u_char *
snmpv3_scopedPDU_header_build(struct snmp_pdu *pdu,
                              u_char *packet, size_t *out_length,
                              u_char **spdu_e)

{
  size_t	 init_length;
  u_char	*scopedPdu, *pb;


  init_length = *out_length;

  pb = scopedPdu = packet;
  pb = asn_build_sequence(pb, out_length,
                          (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
  if (pb == NULL) return NULL;
  if (spdu_e)
    *spdu_e = pb;

  pb = asn_build_string(pb, out_length,
                        (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
                        pdu->contextEngineID, pdu->contextEngineIDLen);
  if (pb == NULL) return NULL;

  pb = asn_build_string(pb, out_length,
                        (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
                        (u_char *)pdu->contextName, pdu->contextNameLen);
  if (pb == NULL) return NULL;

  return pb;

}  /* end snmpv3_scopedPDU_header_build() */


/* returns 0 if success, -1 if fail, not 0 if USM build failure */
int
snmpv3_packet_build(struct snmp_pdu *pdu, u_char *packet, size_t *out_length,
		    u_char *pdu_data, size_t pdu_data_len)
{
    u_char	*global_data,		*sec_params,	*spdu_hdr_e;
    size_t	 global_data_len,	 sec_params_len;
    u_char	 spdu_buf[SNMP_MAX_MSG_SIZE];
    size_t	 spdu_buf_len, spdu_len;
    u_char	*cp;
    int      result;

    global_data = packet;

    /* 
     * build the headers for the packet, returned addr = start of secParams
     */
    sec_params = snmpv3_header_build(pdu, global_data, out_length, 0, NULL);
    if (sec_params == NULL) return -1;
    global_data_len = sec_params - global_data;
    sec_params_len = *out_length; /* length left in packet buf for sec_params */


    /* 
     * build a scopedPDU structure into spdu_buf
     */
    spdu_buf_len = SNMP_MAX_MSG_SIZE;
    cp = snmpv3_scopedPDU_header_build(pdu,spdu_buf,&spdu_buf_len,&spdu_hdr_e);
    if (cp == NULL) return -1;

    /* build the PDU structure onto the end of spdu_buf 
     */
    if (pdu_data) {
      memcpy(cp, pdu_data, pdu_data_len);
      cp += pdu_data_len;
    } else {
      cp = snmp_pdu_build(pdu, cp, &spdu_buf_len);
      if (cp == NULL) return -1;
    }


    /* 
     * re-encode the actual ASN.1 length of the scopedPdu
     */
    spdu_len = cp - spdu_hdr_e; /* length of scopedPdu minus ASN.1 headers */
    spdu_buf_len = SNMP_MAX_MSG_SIZE;
    if (asn_build_sequence(spdu_buf, &spdu_buf_len,
                           (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
                           spdu_len) == NULL)
      return -1;
    spdu_len = cp - spdu_buf;	/* the length of the entire scopedPdu */


    /* 
     * call the security module to possibly encrypt and authenticate the
     * message - the entire message to transmitted on the wire is returned
     */
    cp = NULL; *out_length = SNMP_MAX_MSG_SIZE;
    result =
     	usm_generate_out_msg(
			SNMP_VERSION_3,		
			global_data,		global_data_len,
                        SNMP_MAX_MSG_SIZE,	
			SNMP_SEC_MODEL_USM,
                        pdu->securityEngineID,	pdu->securityEngineIDLen,
                        pdu->securityName,	pdu->securityNameLen,
                        pdu->securityLevel,	
			spdu_buf,		spdu_len, 
			pdu->securityStateRef,
			sec_params,		&sec_params_len,
                        &cp,			out_length);

    return result;

}  /* end snmpv3_packet_build() */
#endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */


/*
 * Takes a session and a pdu and serializes the ASN PDU into the area
 * pointed to by packet.  out_length is the size of the data area available.
 * Returns the length of the completed packet in out_length.  If any errors
 * occur, -1 is returned.  If all goes well, 0 is returned.
 */
static int
_snmp_build(struct snmp_session *session,
	   struct snmp_pdu *pdu,
	   u_char *packet,
	   size_t *out_length)
{
    u_char *h0, *h0e = 0, *h1;
    u_char  *cp;
    size_t length;
    long version;

    session->s_snmp_errno = 0;
    session->s_errno = 0;

#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
    if (pdu->version == SNMP_VERSION_3)
      return snmpv3_build(session, pdu, packet, out_length);
#endif

    switch

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -