C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[66048] Re:Re:Re:SNMP Agent를 구현하려고 합니다.
빌더 [] 1826 읽음    2012-01-26 12:32
C 로 구현된 SNMP Agent 부분 입니다. RFC 1067 문서를 참고하세요.

int
handle_snmp_packet(int operation, struct snmp_session *session, int reqid,
                   struct snmp_pdu *pdu, void *magic)
{
    struct agent_snmp_session  *asp;
    int status, allDone, i, error_index = 0;
    struct variable_list *var_ptr, *var_ptr2;

    if ( magic == NULL ) {
    asp = init_agent_snmp_session( session, pdu );
    status = SNMP_ERR_NOERROR;
    }
    else {
    asp = (struct agent_snmp_session *)magic;
        status =   asp->status;
    }

    if (asp->outstanding_requests != NULL)
    return 1;

    if ( check_access(pdu) != 0) {
        /* access control setup is incorrect */
    send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
        if (asp->pdu->version != SNMP_VERSION_1 && asp->pdu->version != SNMP_VERSION_2c) {
            asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
            asp->pdu->command = SNMP_MSG_RESPONSE;
            snmp_increment_statistic(STAT_SNMPOUTPKTS);
            if (! snmp_send( asp->session, asp->pdu ))
            snmp_free_pdu(asp->pdu);
        asp->pdu = NULL;
        free_agent_snmp_session(asp);
            return 1;
        } else {
            /* drop the request */
            free_agent_snmp_session( asp );
            return 0;
        }
    }

    switch (pdu->command) {
    case SNMP_MSG_GET:
    if ( asp->mode != RESERVE1 )
        break;            /* Single pass */
        snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
    status = handle_next_pass( asp );
    asp->mode = RESERVE2;
    break;

    case SNMP_MSG_GETNEXT:
    if ( asp->mode != RESERVE1 )
        break;            /* Single pass */
        snmp_increment_statistic(STAT_SNMPINGETNEXTS);
    asp->exact   = FALSE;
    status = handle_next_pass( asp );
    asp->mode = RESERVE2;
    break;

    case SNMP_MSG_GETBULK:
        /*
         * GETBULKS require multiple passes. The first pass handles the
         * explicitly requested varbinds, and subsequent passes append
         * to the existing var_op_list.  Each pass (after the first)
         * uses the results of the preceeding pass as the input list
         * (delimited by the start & end pointers.
         * Processing is terminated if all entries in a pass are
         * EndOfMib, or the maximum number of repetitions are made.
         */
    if ( asp->mode == RESERVE1 ) {
            snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
        asp->exact   = FALSE;
            /*
             * Limit max repetitions to something reasonable
             *    XXX: We should figure out what will fit somehow...
             */
        if ( asp->pdu->errindex > 100 )
            asp->pdu->errindex = 100;
   
            /*
             * If max-repetitions is 0, we shouldn't
             *   process the non-nonrepeaters at all
             *   so set up 'asp->end' accordingly
             */
        if ( asp->pdu->errindex == 0 ) {
        if ( asp->pdu->errstat == 0 ) {
                /* Nothing to do at all */
            snmp_free_varbind(asp->pdu->variables);
            asp->pdu->variables=NULL;
            asp->start=NULL;
        }
        else {
            asp->end   = asp->pdu->variables;
            i = asp->pdu->errstat;
            while ( --i > 0 )
            if ( asp->end )
                asp->end = asp->end->next_variable;
            snmp_free_varbind(asp->end->next_variable);
            asp->end->next_variable = NULL;
        }
        }

        status = handle_next_pass( asp );    /* First pass */
        asp->mode = RESERVE2;
        if ( status != SNMP_ERR_NOERROR )
            break;
   
        while ( asp->pdu->errstat-- > 0 )    /* Skip non-repeaters */
        {
            if ( NULL != asp->start )    /* if there are variables ... */
            asp->start = asp->start->next_variable;
        }
        asp->pdu->errindex--;           /* Handled first repetition */

        if ( asp->outstanding_requests != NULL )
        return 1;
    }

    if ( NULL != asp->start )    /* if there are variables ... */
    while ( asp->pdu->errindex-- > 0 ) {    /* Process repeaters */
        /*
        * Add new variable structures for the
        * repeating elements, ready for the next pass.
        * Also check that these are not all EndOfMib
        */
        allDone = TRUE;        /* Check for some content */
        for ( var_ptr = asp->start;
          var_ptr != asp->end->next_variable;
          var_ptr = var_ptr->next_variable ) {
                /* XXX: we don't know the size of the next
                    OID, so assume the maximum length */
        if ( var_ptr->type != SNMP_ENDOFMIBVIEW ) {
            var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN);
            for ( i=var_ptr->name_length ; i<MAX_OID_LEN ; i++)
            var_ptr2->name[i] = 0;
            var_ptr2->name_length = var_ptr->name_length;

            allDone = FALSE;
        }
        }
        if ( allDone )
        break;

        asp->start = asp->end->next_variable;
        while ( asp->end->next_variable != NULL )
        asp->end = asp->end->next_variable;
       
        status = handle_next_pass( asp );
        if ( status != SNMP_ERR_NOERROR )
        break;
        if ( asp->outstanding_requests != NULL )
        return 1;
    }
    break;

    case SNMP_MSG_SET:
            /*
         * SETS require 3-4 passes through the var_op_list.  The first two
         * passes verify that all types, lengths, and values are valid
         * and may reserve resources and the third does the set and a
         * fourth executes any actions.  Then the identical GET RESPONSE
         * packet is returned.
         * If either of the first two passes returns an error, another
         * pass is made so that any reserved resources can be freed.
         * If the third pass returns an error, another pass is made so that
         * any changes can be reversed.
         * If the fourth pass (or any of the error handling passes)
         * return an error, we'd rather not know about it!
         */
    if ( asp->mode == RESERVE1 ) {
            snmp_increment_statistic(STAT_SNMPINSETREQUESTS);
        asp->rw      = WRITE;

        status = handle_next_pass( asp );

            if ( status != SNMP_ERR_NOERROR ){
            asp->mode = FREE;
                error_index = asp->index;
            }
        else
            asp->mode = RESERVE2;

        if ( asp->outstanding_requests != NULL )
        return 1;
    }

    if ( asp->mode == RESERVE2 ) {
        status = handle_next_pass( asp );

        if ( status != SNMP_ERR_NOERROR ){
            asp->mode = FREE;
                error_index = asp->index;
            }
        else
            asp->mode = ACTION;

        if ( asp->outstanding_requests != NULL )
        return 1;
    }

    if ( asp->mode == ACTION ) {
        status = handle_next_pass( asp );

        if ( status != SNMP_ERR_NOERROR ){
            asp->mode = UNDO;
                error_index = asp->index;
            }
        else
            asp->mode = COMMIT;

        if ( asp->outstanding_requests != NULL )
        return 1;
    }

    if ( asp->mode == COMMIT ) {
        status = handle_next_pass( asp );

        if ( status != SNMP_ERR_NOERROR ) {
        status    = SNMP_ERR_COMMITFAILED;
            asp->mode = FINISHED_FAILURE;
                error_index = asp->index;
        }
        else
            asp->mode = FINISHED_SUCCESS;

        if ( asp->outstanding_requests != NULL )
        return 1;
    }

    if ( asp->mode == UNDO ) {
            if (handle_next_pass( asp ) != SNMP_ERR_NOERROR ) {
        status = SNMP_ERR_UNDOFAILED;
                error_index = 0;
            }

        asp->mode = FINISHED_FAILURE;
    }

    if ( asp->mode == FREE ) {
        (void) handle_next_pass( asp );
    }
        asp->index = error_index;
    break;

    case SNMP_MSG_RESPONSE:
        snmp_increment_statistic(STAT_SNMPINGETRESPONSES);
    free_agent_snmp_session( asp );
    return 0;
    case SNMP_MSG_TRAP:
    case SNMP_MSG_TRAP2:
        snmp_increment_statistic(STAT_SNMPINTRAPS);
    free_agent_snmp_session( asp );
    return 0;
    default:
        snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
    free_agent_snmp_session( asp );
    return 0;
    }

    if ( asp->outstanding_requests != NULL ) {
    asp->status = status;
    asp->next = agent_session_list;
    agent_session_list = asp;
    }
    else {
        /*
        * May need to "dumb down" a SET error status for a
        *  v1 query.  See RFC2576 - section 4.3
        */
    if (( asp->pdu                          ) &&
        ( asp->pdu->command == SNMP_MSG_SET ) &&
        ( asp->pdu->version == SNMP_VERSION_1 )) {
        switch ( status ) {
        case SNMP_ERR_WRONGVALUE:
        case SNMP_ERR_WRONGENCODING:
        case SNMP_ERR_WRONGTYPE:
        case SNMP_ERR_WRONGLENGTH:
        case SNMP_ERR_INCONSISTENTVALUE:
            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:
            status = SNMP_ERR_NOSUCHNAME;
            break;
        case SNMP_ERR_RESOURCEUNAVAILABLE:
        case SNMP_ERR_COMMITFAILED:
        case SNMP_ERR_UNDOFAILED:
            status = SNMP_ERR_GENERR;
            break;
        }
    }
        /*
        * Similarly we may need to "dumb down" v2 exception
        *  types to throw an error for a v1 query.
        *  See RFC2576 - section 4.1.2.3
        */
    if (( asp->pdu                          ) &&
        ( asp->pdu->command != SNMP_MSG_SET ) &&
        ( asp->pdu->version == SNMP_VERSION_1 )) {
        for ( var_ptr = asp->pdu->variables, i=1 ;
            var_ptr != NULL ;
            var_ptr = var_ptr->next_variable, i++ ) {
                switch ( var_ptr->type ) {
            case SNMP_NOSUCHOBJECT:
            case SNMP_NOSUCHINSTANCE:
            case SNMP_ENDOFMIBVIEW:
            case ASN_COUNTER64:
                status = SNMP_ERR_NOSUCHNAME;
                asp->index=i;
                break;
            }
        }
    }

        /*
             * Update the snmp error-count statistics
             *   XXX - should we include the V2 errors in this or not?
             */
#define INCLUDE_V2ERRORS_IN_V1STATS

    switch ( status ) {
#ifdef INCLUDE_V2ERRORS_IN_V1STATS
        case SNMP_ERR_WRONGVALUE:
        case SNMP_ERR_WRONGENCODING:
        case SNMP_ERR_WRONGTYPE:
        case SNMP_ERR_WRONGLENGTH:
        case SNMP_ERR_INCONSISTENTVALUE:
#endif
        case SNMP_ERR_BADVALUE:
                snmp_increment_statistic(STAT_SNMPOUTBADVALUES);
            break;
#ifdef INCLUDE_V2ERRORS_IN_V1STATS
        case SNMP_ERR_NOACCESS:
        case SNMP_ERR_NOTWRITABLE:
        case SNMP_ERR_NOCREATION:
        case SNMP_ERR_INCONSISTENTNAME:
        case SNMP_ERR_AUTHORIZATIONERROR:
#endif
        case SNMP_ERR_NOSUCHNAME:
                snmp_increment_statistic(STAT_SNMPOUTNOSUCHNAMES);
            break;
#ifdef INCLUDE_V2ERRORS_IN_V1STATS
        case SNMP_ERR_RESOURCEUNAVAILABLE:
        case SNMP_ERR_COMMITFAILED:
        case SNMP_ERR_UNDOFAILED:
#endif
        case SNMP_ERR_GENERR:
                snmp_increment_statistic(STAT_SNMPOUTGENERRS);
            break;

        case SNMP_ERR_TOOBIG:
                snmp_increment_statistic(STAT_SNMPOUTTOOBIGS);
            break;
    }

    if (( status == SNMP_ERR_NOERROR ) && ( asp->pdu )) {
        snmp_increment_statistic_by(
        (asp->pdu->command == SNMP_MSG_SET ?
            STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ),
            count_varbinds( asp->pdu ));
    }
    else {
        /*
        * Use a copy of the original request
        *   to report failures.
        */
        snmp_free_pdu( asp->pdu );
        asp->pdu = asp->orig_pdu;
        asp->orig_pdu = NULL;
    }
    if ( asp->pdu ) {
        asp->pdu->command  = SNMP_MSG_RESPONSE;
        asp->pdu->errstat  = status;
        if (status == SNMP_ERR_NOERROR) {
        asp->pdu->errindex = 0;
        } else {
        asp->pdu->errindex = asp->index;
        }
        if (! snmp_send( asp->session, asp->pdu ))
            snmp_free_pdu(asp->pdu);
        snmp_increment_statistic(STAT_SNMPOUTPKTS);
        snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
        asp->pdu = NULL;
        free_agent_snmp_session( asp );
    }
    }

    return 1;
}

+ -

관련 글 리스트
66043 SNMP Agent를 구현하려고 합니다. ksih 2856 2012/01/26
66046     Re:SNMP Agent를 구현하려고 합니다. kylix 1988 2012/01/26
66047         Re:Re:SNMP Agent를 구현하려고 합니다. ksih 1983 2012/01/26
66048             Re:Re:Re:SNMP Agent를 구현하려고 합니다. 빌더 1826 2012/01/26
66056                 Re:Re:Re:Re:SNMP Agent를 구현하려고 합니다. ksih 1940 2012/01/26
66061                     Re:Re:Re:Re:Re:SNMP Agent를 구현하려고 합니다. kylix 1758 2012/01/26
66062                         Re:Re:Re:Re:Re:Re:SNMP Agent를 구현하려고 합니다. 빌더 2093 2012/01/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.