FreeBSD/contrib/bsnmp/snmpd/main.c
/*
 * SNMP input. Start: decode the PDU, find the user or community.
 */
SNMP input. Start: decode the PDU, find the user or community.
SNMP input . Start : decode the PDU find the user or community .
enum snmpd_input_err
snmp_input_start(const u_char *buf, size_t len, const char *source,
    struct snmp_pdu *pdu, int32_t *ip, size_t *pdulen)
{
	struct asn_buf b;
	enum snmp_code code;
	enum snmpd_input_err ret;
	int sret;
	this_tick = get_ticks();
	b.asn_cptr = buf;
	b.asn_len = len;
	switch (sret = snmp_pdu_snoop(&b)) {
	  case 0:
		return (SNMPD_INPUT_TRUNC);
	  case -1:
		snmpd_stats.inASNParseErrs++;
		return (SNMPD_INPUT_FAILED);
	}
	b.asn_len = *pdulen = (size_t)sret;
	memset(pdu, 0, sizeof(*pdu));
	if ((code = snmp_pdu_decode_header(&b, pdu)) != SNMP_CODE_OK)
		goto decoded;
	if (pdu->version == SNMP_V3) {
		if (pdu->security_model != SNMP_SECMODEL_USM) {
			code = SNMP_CODE_FAILED;
			goto decoded;
		}
		if ((code = snmp_pdu_auth_user(pdu)) != SNMP_CODE_OK)
		    	goto decoded;
		if ((code =  snmp_pdu_decode_secmode(&b, pdu)) != SNMP_CODE_OK)
			goto decoded;
	}
	code = snmp_pdu_decode_scoped(&b, pdu, ip);
	ret = SNMPD_INPUT_OK;
decoded:
	snmpd_stats.inPkts++;
	switch (code) {
	  case SNMP_CODE_FAILED:
		snmpd_stats.inASNParseErrs++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_BADVERS:
	  bad_vers:
		snmpd_stats.inBadVersions++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_BADLEN:
		if (pdu->type == SNMP_OP_SET)
			ret = SNMPD_INPUT_VALBADLEN;
		break;
	  case SNMP_CODE_OORANGE:
		if (pdu->type == SNMP_OP_SET)
			ret = SNMPD_INPUT_VALRANGE;
		break;
	  case SNMP_CODE_BADENC:
		if (pdu->type == SNMP_OP_SET)
			ret = SNMPD_INPUT_VALBADENC;
		break;
	  case SNMP_CODE_BADSECLEVEL:
		snmpd_usmstats.unsupported_seclevels++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_NOTINTIME:
		snmpd_usmstats.not_in_time_windows++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_BADUSER:
		snmpd_usmstats.unknown_users++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_BADENGINE:
		snmpd_usmstats.unknown_engine_ids++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_BADDIGEST:
		snmpd_usmstats.wrong_digests++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_EDECRYPT:
		snmpd_usmstats.decrypt_errors++;
		return (SNMPD_INPUT_FAILED);
	  case SNMP_CODE_OK:
		switch (pdu->version) {
		  case SNMP_V1:
			if (!(snmpd.version_enable & VERS_ENABLE_V1))
				goto bad_vers;
			break;
		  case SNMP_V2c:
			if (!(snmpd.version_enable & VERS_ENABLE_V2C))
				goto bad_vers;
			break;
		  case SNMP_V3:
		  	if (!(snmpd.version_enable & VERS_ENABLE_V3))
				goto bad_vers;
			break;
		  case SNMP_Verr:
			goto bad_vers;
		}
		break;
	}
	if (debug.dump_pdus) {
		snmp_printf("%s -> ", source);
		snmp_pdu_dump(pdu);
	}
	if (pdu->version != SNMP_V3) {
		TAILQ_FOREACH(comm, &community_list, link)
			if (comm->string != NULL &&
			    strcmp(comm->string, pdu->community) == 0)
				break;
		if (comm == NULL) {
			snmpd_stats.inBadCommunityNames++;
			snmp_pdu_free(pdu);
			if (snmpd.auth_traps)
				snmp_send_trap(&oid_authenticationFailure,
				    (struct snmp_value *)NULL);
			ret = SNMPD_INPUT_BAD_COMM;
		} else
			community = comm->value;
	} else if (pdu->nbindings == 0) {
		if (strlen(pdu->user.sec_name) == 0) {
			asn_append_oid(&(pdu->bindings[pdu->nbindings++].var),
			    &oid_usmUnknownEngineIDs);
			pdu->context_engine_len = snmpd_engine.engine_len;
			memcpy(pdu->context_engine, snmpd_engine.engine_id,
			    snmpd_engine.engine_len);
		} else if (pdu->engine.engine_boots == 0 &&
		    pdu->engine.engine_time == 0) {
			asn_append_oid(&(pdu->bindings[pdu->nbindings++].var),
			    &oid_usmNotInTimeWindows);
			pdu->engine.engine_boots = snmpd_engine.engine_boots;
			pdu->engine.engine_time = snmpd_engine.engine_time;
		}
	} else if (usm_user->suser.auth_proto != SNMP_AUTH_NOAUTH &&
	     (pdu->engine.engine_boots == 0 || pdu->engine.engine_time == 0)) {
		snmpd_usmstats.not_in_time_windows++;
		ret = SNMPD_INPUT_FAILED;
	}
	if ((code = snmp_pdu_auth_access(pdu, ip)) != SNMP_CODE_OK)
		ret = SNMPD_INPUT_FAILED;
	return (ret);
}
enum snmpd_input_err snmp_input_start ( const u_char * buf , size_t len , const char * source , struct snmp_pdu * pdu , int32_t * ip , size_t * pdulen ) { struct asn_buf b ; enum snmp_code code ; enum snmpd_input_err ret ; int sret ; this_tick = get_ticks ( ) ; b . asn_cptr = buf ; b . asn_len = len ; switch ( sret = snmp_pdu_snoop ( & b ) ) { case 0 : return ( SNMPD_INPUT_TRUNC ) ; case -1 : snmpd_stats . inASNParseErrs ++ ; return ( SNMPD_INPUT_FAILED ) ; } b . asn_len = * pdulen = ( size_t ) sret ; memset ( pdu , 0 , sizeof ( * pdu ) ) ; if ( ( code = snmp_pdu_decode_header ( & b , pdu ) ) != SNMP_CODE_OK ) goto decoded ; if ( pdu -> version == SNMP_V3 ) { if ( pdu -> security_model != SNMP_SECMODEL_USM ) { code = SNMP_CODE_FAILED ; goto decoded ; } if ( ( code = snmp_pdu_auth_user ( pdu ) ) != SNMP_CODE_OK ) goto decoded ; if ( ( code = snmp_pdu_decode_secmode ( & b , pdu ) ) != SNMP_CODE_OK ) goto decoded ; } code = snmp_pdu_decode_scoped ( & b , pdu , ip ) ; ret = SNMPD_INPUT_OK ; decoded : snmpd_stats . inPkts ++ ; switch ( code ) { case SNMP_CODE_FAILED : snmpd_stats . inASNParseErrs ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_BADVERS : bad_vers : snmpd_stats . inBadVersions ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_BADLEN : if ( pdu -> type == SNMP_OP_SET ) ret = SNMPD_INPUT_VALBADLEN ; break ; case SNMP_CODE_OORANGE : if ( pdu -> type == SNMP_OP_SET ) ret = SNMPD_INPUT_VALRANGE ; break ; case SNMP_CODE_BADENC : if ( pdu -> type == SNMP_OP_SET ) ret = SNMPD_INPUT_VALBADENC ; break ; case SNMP_CODE_BADSECLEVEL : snmpd_usmstats . unsupported_seclevels ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_NOTINTIME : snmpd_usmstats . not_in_time_windows ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_BADUSER : snmpd_usmstats . unknown_users ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_BADENGINE : snmpd_usmstats . unknown_engine_ids ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_BADDIGEST : snmpd_usmstats . wrong_digests ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_EDECRYPT : snmpd_usmstats . decrypt_errors ++ ; return ( SNMPD_INPUT_FAILED ) ; case SNMP_CODE_OK : switch ( pdu -> version ) { case SNMP_V1 : if ( ! ( snmpd . version_enable & VERS_ENABLE_V1 ) ) goto bad_vers ; break ; case SNMP_V2c : if ( ! ( snmpd . version_enable & VERS_ENABLE_V2C ) ) goto bad_vers ; break ; case SNMP_V3 : if ( ! ( snmpd . version_enable & VERS_ENABLE_V3 ) ) goto bad_vers ; break ; case SNMP_Verr : goto bad_vers ; } break ; } if ( debug . dump_pdus ) { snmp_printf ( " " , source ) ; snmp_pdu_dump ( pdu ) ; } if ( pdu -> version != SNMP_V3 ) { TAILQ_FOREACH ( comm , & community_list , link ) if ( comm -> string != NULL && strcmp ( comm -> string , pdu -> community ) == 0 ) break ; if ( comm == NULL ) { snmpd_stats . inBadCommunityNames ++ ; snmp_pdu_free ( pdu ) ; if ( snmpd . auth_traps ) snmp_send_trap ( & oid_authenticationFailure , ( struct snmp_value * ) NULL ) ; ret = SNMPD_INPUT_BAD_COMM ; } else community = comm -> value ; } else if ( pdu -> nbindings == 0 ) { if ( strlen ( pdu -> user . sec_name ) == 0 ) { asn_append_oid ( & ( pdu -> bindings [ pdu -> nbindings ++ ] . var ) , & oid_usmUnknownEngineIDs ) ; pdu -> context_engine_len = snmpd_engine . engine_len ; memcpy ( pdu -> context_engine , snmpd_engine . engine_id , snmpd_engine . engine_len ) ; } else if ( pdu -> engine . engine_boots == 0 && pdu -> engine . engine_time == 0 ) { asn_append_oid ( & ( pdu -> bindings [ pdu -> nbindings ++ ] . var ) , & oid_usmNotInTimeWindows ) ; pdu -> engine . engine_boots = snmpd_engine . engine_boots ; pdu -> engine . engine_time = snmpd_engine . engine_time ; } } else if ( usm_user -> suser . auth_proto != SNMP_AUTH_NOAUTH && ( pdu -> engine . engine_boots == 0 || pdu -> engine . engine_time == 0 ) ) { snmpd_usmstats . not_in_time_windows ++ ; ret = SNMPD_INPUT_FAILED ; } if ( ( code = snmp_pdu_auth_access ( pdu , ip ) ) != SNMP_CODE_OK ) ret = SNMPD_INPUT_FAILED ; return ( ret ) ; }
SNMP input.
SNMP input .
/* update uptime */ /* look whether we have enough bytes for the entire PDU. */ /*
	 * Look, whether we know the community or user
	 */ /* RFC 3414 - snmpEngineID Discovery */