/*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * SPDX-License-Identifier: MIT **************************************************************************/ /**************************************************************************/ /**************************************************************************/ /** */ /** NetX Duo Component */ /** */ /** Simple Network Management Protocol (SNMP) */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SNMP_SOURCE_CODE /* Force error checking to be disabled in this module */ #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif /* Include necessary system files. */ #include "nx_api.h" #include "nxd_snmp.h" #ifndef NX_IPV6_UTIL_INLINE extern void COPY_NXD_ADDRESS(NXD_ADDRESS *copy_from, NXD_ADDRESS *copy_to); #endif /* To enable debug output, define this option. #define NX_SNMPV3_PRINT_DEBUG_MESSAGE */ #define NX_SNMP_REQUEST_AUTH_SIZE 50 #ifndef NX_SNMP_DISABLE_V3 /* Define locations in request buffer PDU in the event we need to return the message e.g. error message response. */ static UINT pdu_length; static UCHAR *pdu_buffer_ptr; static UCHAR *pdu_auth_parm_ptr; static UCHAR *pdu_privacy_ptr; #endif /* Enable or disable SNMPv3 debug message printout. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE #define NX_SNMPV3_DBG_PRINTF printf #endif /* NX_SNMPV3_PRINT_DEBUG_MESSAGE */ /* Define global SNMP variables and strings. */ /* If the array size of _nx_snmp_v2_trap_ids is changed, these upper limit MUST by updated! */ #define TRAP_ID_MAX 5 UCHAR *_nx_snmp_v2_trap_ids[] = { (UCHAR *) "1.3.6.1.6.3.1.1.5.1.0" /* (coldStart) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.2.0" /* (warmStart) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.3.0" /* (linkDown) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.4.0" /* (linkUp) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.5.0" /* (authenticationFailure) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.6.0" /* (egpNeighborLoss) */ }; #ifndef NX_SNMP_DISABLE_V3 UCHAR *_nx_snmp_v3_trap_ids[] = { (UCHAR *) "1.3.6.1.6.3.1.1.5.1.0" /* (coldStart) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.2.0" /* (warmStart) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.3.0" /* (linkDown) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.4.0" /* (linkUp) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.5.0" /* (authenticationFailure) */, (UCHAR *) "1.3.6.1.6.3.1.1.5.6.0" /* (egpNeighborLoss) */ }; /* Define the default context engine information. This will be setup when the SNMP agent is created. Note that this information isn't used for SNMP v1 and v2. Note the host application should use the nx_snmp_agent_context_engine_set() service to set its own IPv4 (or MAC address depending on format type) when creating the Engine ID. The engine size must match the total engine data including the input context engine data as well. See documentation for more details. Note that this information isn't used for SNMP v1 and v2. */ UCHAR _nx_snmp_default_context_engine[NX_SNMP_MAX_CONTEXT_STRING] = {0x80, 0x00, 0x03, 0x10, 0x01, 0xc0, 0xa8, 0x64, 0xaf}; UINT _nx_snmp_default_context_engine_size = 9; CHAR _nx_snmp_default_initial_user_name[] = "initial"; #endif /* As per RFC 3414 for SNMPv3 the discovery report must include the usmStats variables. */ #define NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC "1.3.6.1.6.3.15.1.1.1.0" #define NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM 1 #define NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME "1.3.6.1.6.3.15.1.1.2.0" #define NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME_NUM 2 #define NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME "1.3.6.1.6.3.15.1.1.3.0" #define NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME_NUM 3 #define NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID "1.3.6.1.6.3.15.1.1.4.0" #define NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM 4 /* Define the maximum difference between local time (in seconds) and browser notion of local time recommended by RFC 3413. */ #define NX_SNMP_TIME_WINDOW 150 /* Bring in externs for caller checking code. */ NX_CALLER_CHECKING_EXTERNS #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_authenticate_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP authentication key */ /* specification function call. To disable authentication, set */ /* the key pointer to null. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Authenticate key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_authenticate_key_use Actual authentication key */ /* setup function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_authenticate_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) { return(NX_PTR_ERROR); } if (key != NX_NULL) { /* Check for valid authentication type. */ if ((key -> nx_snmp_security_key_type != NX_SNMP_MD5_KEY) && (key -> nx_snmp_security_key_type != NX_SNMP_SHA_KEY)) { return NX_SNMP_UNSUPPORTED_AUTHENTICATION; } } /* Call actual service. */ status = _nx_snmp_agent_authenticate_key_use(agent_ptr, key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_authenticate_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets up the authenticate key to use for checking the */ /* digest of the request. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Authenticate key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_authenticate_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { #ifdef NX_SNMP_NO_SECURITY return NX_NOT_ENABLED; #else /* Set the authenticate pointer so authentication will use the specified key. Note this key must have been created prior to calling this routine. */ agent_ptr -> nx_snmp_agent_v3_authentication_key = key; /* Return success to the caller. */ return(NX_SUCCESS); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trap_auth_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function is the error checking service for the setting the trap*/ /* message authentication key. To disable trap key authentication, set */ /* the key pointer to null. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Authenticate key for traps */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_auth_trap_key_use Actual set trap authentication*/ /* key service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_auth_trap_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) { return(NX_PTR_ERROR); } if (key != NX_NULL) { /* Check for invalid authentication type. */ if ((key -> nx_snmp_security_key_type != NX_SNMP_MD5_KEY) && (key -> nx_snmp_security_key_type != NX_SNMP_SHA_KEY)) { return NX_SNMP_UNSUPPORTED_AUTHENTICATION; } } /* Call actual service. */ status = _nx_snmp_agent_auth_trap_key_use(agent_ptr, key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_auth_trap_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets up the authenticate key to use for creating */ /* authentication parameters in SNMPv3 trap messages. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Authenticate key for traps */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_auth_trap_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { #ifdef NX_SNMP_NO_SECURITY return NX_NOT_ENABLED; #else /* Set the authenticate pointer so authentication will use the specified key. Note this key must have been created prior to calling this routine. */ agent_ptr -> nx_snmp_agent_v3_auth_trap_key = key; /* Return success to the caller. */ return(NX_SUCCESS); #endif } #endif /* NX_SNMP_DISABLE_V3 */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_community_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP community get */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string_ptr Pointer to the community */ /* string destination */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_community_get Actual community get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_community_get(NX_SNMP_AGENT *agent_ptr, UCHAR **community_string_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community_string_ptr == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_community_get(agent_ptr, community_string_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_community_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the community string. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string_ptr Pointer to the community */ /* string destination */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_community_get(NX_SNMP_AGENT *agent_ptr, UCHAR **community_string_ptr) { /* Set a pointer to the community string for the caller. */ *community_string_ptr = agent_ptr -> nx_snmp_agent_current_community_string; /* Return successful status. */ return(NX_SUCCESS); } #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_context_engine_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP context engine set */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* context_engine Pointer to context engine */ /* context_engine_size Number of bytes in the */ /* context engine */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_context_engine_set Actual context engine set */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_context_engine_set(NX_SNMP_AGENT *agent_ptr, UCHAR *context_engine, UINT context_engine_size) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (context_engine == NX_NULL)) return(NX_PTR_ERROR); /* Check for an invalid size. */ if ((context_engine_size == 0) || (context_engine_size >= NX_SNMP_MAX_CONTEXT_STRING)) return(NX_SNMP_ERROR); /* Call actual service. */ status = _nx_snmp_agent_context_engine_set(agent_ptr, context_engine, context_engine_size); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_context_engine_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the context engine of the specified SNMP agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* context_engine Pointer to context engine */ /* context_engine_size Number of bytes in the */ /* context engine */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_context_engine_set(NX_SNMP_AGENT *agent_ptr, UCHAR *context_engine, UINT context_engine_size) { UINT i; /* Verify V3 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v3_enabled == NX_FALSE) { return NX_NOT_ENABLED; } /* Determine if the context engine is the correct size. */ if (context_engine_size > NX_SNMP_MAX_CONTEXT_STRING) { /* Return an error. */ return(NX_SNMP_ERROR); } /* Otherwise, store the context engine. */ for (i = 0; i < context_engine_size; i++) { /* Store a byte of the context engine. */ agent_ptr -> nx_snmp_agent_v3_context_engine[i] = context_engine[i]; } /* Set the context engine length. */ agent_ptr -> nx_snmp_agent_v3_context_engine_size = context_engine_size; /* Return successful completion. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_context_name_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP context name set */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* context_name Pointer to context name */ /* context_name_size Number of bytes in the */ /* context name */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_context_name_set Actual context name set */ /* function */ /* */ /* CALLED BY */ /* */ /* Initialization */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_context_name_set(NX_SNMP_AGENT *agent_ptr, UCHAR *context_name, UINT context_name_size) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (context_name == NX_NULL)) return(NX_PTR_ERROR); /* Check for an invalid size. */ if ((context_name_size == 0) || (context_name_size >= NX_SNMP_MAX_USER_NAME)) return(NX_SNMP_ERROR); /* Call actual service. */ status = _nx_snmp_agent_context_name_set(agent_ptr, context_name, context_name_size); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_context_name_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the context name of the specified SNMP agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* context_name Pointer to context name */ /* context_name_size Number of bytes in the */ /* context name */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Initialization */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_context_name_set(NX_SNMP_AGENT *agent_ptr, UCHAR *context_name, UINT context_name_size) { UINT i; /* Determine if the context name is the correct size. */ if (context_name_size > NX_SNMP_MAX_CONTEXT_STRING) { /* Return an error. */ return(NX_SNMP_ERROR); } /* Otherwise, store the context name. */ for (i = 0; i < context_name_size; i++) { /* Store a byte of the context name. */ agent_ptr -> nx_snmp_agent_v3_context_name[i] = context_name[i]; } /* Set the context name length. */ agent_ptr -> nx_snmp_agent_v3_context_name_size = context_name_size; /* Return successful completion. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_v3_context_boots_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP context boots set */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* boots Value to set agent boots to */ /* */ /* OUTPUT */ /* */ /* NX_PTR_ERROR Invalid pointer input */ /* NX_SNMP_ERROR Invalid boot count input */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_v3_context_boots_set Actual context boots set */ /* function */ /* */ /* CALLED BY */ /* */ /* Initialization */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_v3_context_boots_set(NX_SNMP_AGENT *agent_ptr, UINT boots) { UINT status; /* Check for invalid input pointer. */ if (agent_ptr == NX_NULL) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_v3_context_boots_set(agent_ptr, boots); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_v3_context_boots_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the context boot count of the specified SNMP */ /* agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* boots Value to set agent boots to */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* NX_SNMP_ERROR Invalid boot count input */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Initialization */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_v3_context_boots_set(NX_SNMP_AGENT *agent_ptr, UINT boots) { /* Set the context name length. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boots = boots; /* Return successful completion. */ return(NX_SUCCESS); } #endif /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent create */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* snmp_agent_name Name of SNMP agent */ /* ip_ptr Pointer to IP instance */ /* stack_ptr Pointer to stack for SNMP */ /* thread */ /* stack_size Size in bytes of thread stack */ /* pool_ptr Default packet pool */ /* snmp_agent_username_process Username callback routine */ /* snmp_agent_get_process Get callback routine */ /* snmp_agent_getnext_process Getnext callback routine */ /* snmp_agent_set_process Set callback routine */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_create Actual agent create function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_create(NX_SNMP_AGENT *agent_ptr, CHAR *snmp_agent_name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr, UINT (*snmp_agent_username_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *username), UINT (*snmp_agent_get_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data), UINT (*snmp_agent_getnext_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data), UINT (*snmp_agent_set_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id == NX_SNMP_ID) || (ip_ptr == NX_NULL) || (stack_ptr == NX_NULL) || (pool_ptr == NX_NULL) || (!snmp_agent_username_process) || (!snmp_agent_get_process) || (!snmp_agent_getnext_process) || (!snmp_agent_set_process)) return(NX_PTR_ERROR); /* Check for an invalid size. */ if (stack_size == 0) return(NX_SNMP_ERROR); /* Call actual service. */ status = _nx_snmp_agent_create(agent_ptr, snmp_agent_name, ip_ptr, stack_ptr, stack_size, pool_ptr, snmp_agent_username_process, snmp_agent_get_process, snmp_agent_getnext_process, snmp_agent_set_process); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function creates an SNMP agent. */ /* */ /* Note: The string length of username in snmp_agent_username_process */ /* callback is limited by NX_SNMP_MAX_USER_NAME. */ /* The string length of object_requested in snmp_agent_get_process, */ /* snmp_agent_getnext_process and snmp_agent_set_process callback is */ /* limited by NX_SNMP_MAX_OCTET_STRING. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* snmp_agent_name Name of SNMP agent */ /* ip_ptr Pointer to IP instance */ /* stack_ptr Pointer to stack for SNMP */ /* thread */ /* stack_size Size in bytes of thread stack */ /* pool_ptr Default packet pool */ /* snmp_agent_username_process Username callback routine */ /* snmp_agent_get_process Get callback routine */ /* snmp_agent_getnext_process Getnext callback routine */ /* snmp_agent_set_process Set callback routine */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* nx_udp_socket_bind Bind SNMP agent socket */ /* nx_udp_socket_create Create SNMP agent socket */ /* nx_udp_socket_delete Delete SNMP agent socket */ /* nx_udp_socket_unbind Unbind SNMP agent socket */ /* tx_thread_create Create SNMP agent thread */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_create(NX_SNMP_AGENT *agent_ptr, CHAR *snmp_agent_name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr, UINT (*snmp_agent_username_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *username), UINT (*snmp_agent_get_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data), UINT (*snmp_agent_getnext_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data), UINT (*snmp_agent_set_process)(struct NX_SNMP_AGENT_STRUCT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)) { UINT status; #ifndef NX_SNMP_DISABLE_V3 UINT i; #endif #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF( "Creating snmp agent of size %d\n\r", stack_size); #endif /* Clear the SNMP agent structure. */ memset((void *) agent_ptr, 0, sizeof(NX_SNMP_AGENT)); /* Create the agent's UDP socket. */ status = nx_udp_socket_create(ip_ptr, &(agent_ptr -> nx_snmp_agent_socket), snmp_agent_name, NX_SNMP_TYPE_OF_SERVICE, NX_SNMP_FRAGMENT_OPTION, NX_SNMP_TIME_TO_LIVE, NX_SNMP_QUEUE_DEPTH); /* Determine if an error occurred. */ if (status) { /* Yes, return error code. */ return(NX_SNMP_ERROR); } /* Now create the SNMP Server thread. */ status = tx_thread_create(&(agent_ptr -> nx_snmp_agent_thread), "SNMP Agent Thread", _nx_snmp_agent_thread_entry, (ULONG) agent_ptr, stack_ptr, stack_size, NX_SNMP_AGENT_PRIORITY, NX_SNMP_AGENT_PRIORITY, TX_NO_TIME_SLICE, TX_DONT_START); /* Determine if an error occurred creating the thread. */ if (status) { /* Delete the UDP socket. */ nx_udp_socket_delete(&(agent_ptr -> nx_snmp_agent_socket)); /* Yes, return error code. */ return(NX_SNMP_ERROR); } /* Save the Server name. */ agent_ptr -> nx_snmp_agent_name = snmp_agent_name; /* Save the IP pointer address. */ agent_ptr -> nx_snmp_agent_ip_ptr = ip_ptr; /* Save the packet pool pointer. */ agent_ptr -> nx_snmp_agent_packet_pool_ptr = pool_ptr; /* Default the SNMP network interface to the primary interface. */ agent_ptr -> nx_snmp_agent_interface_index = 0; /* Initialize the agent as configured for all versions. Note that the #define options for disabling version support override dynamic version status. For example if NX_SNMP_DISABLE_V2 is disabled, setting nx_snmp_agent_v2_enabled to NX_TRUE has no effect. If NX_SNMP_DISABLE_V2 is not disabled, then nx_snmp_agent_v2_enabled determines at run time if the SNMP is enabled for V2.*/ agent_ptr -> nx_snmp_agent_v1_enabled = NX_TRUE; agent_ptr -> nx_snmp_agent_v2_enabled = NX_TRUE; agent_ptr -> nx_snmp_agent_v3_enabled = NX_TRUE; #ifndef NX_SNMP_DISABLE_V3 /* Setup the SNMP v3 information. */ /* Setup the default context engine. */ for (i = 0; i < _nx_snmp_default_context_engine_size; i++) { /* Copy byte of default context engine. */ agent_ptr -> nx_snmp_agent_v3_context_engine[i] = _nx_snmp_default_context_engine[i]; } /* Set the default context engine size. */ agent_ptr -> nx_snmp_agent_v3_context_engine_size = _nx_snmp_default_context_engine_size; /* Start the time (in ticks) since the previous reboot. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); #endif /* NX_SNMP_DISABLE_V3 */ /* Save the application request processing callback routines. */ agent_ptr -> nx_snmp_agent_get_process = snmp_agent_get_process; agent_ptr -> nx_snmp_agent_getnext_process = snmp_agent_getnext_process; agent_ptr -> nx_snmp_agent_set_process = snmp_agent_set_process; agent_ptr -> nx_snmp_agent_username_process = snmp_agent_username_process; /* Set the agent ID to indicate the SNMP agent thread is ready. */ agent_ptr -> nx_snmp_agent_id = NX_SNMP_ID; /* Return successful completion. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_request_get_type_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent get current */ /* request type. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* is_get_type Pointer to request type */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_request_get_type_test Actual request type service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_request_get_type_test(NX_SNMP_AGENT *agent_ptr, UINT *is_get_type) { UINT status; if ((agent_ptr == NX_NULL) || (is_get_type == NX_NULL)) { return NX_PTR_ERROR; } status = _nx_snmp_agent_request_get_type_test(agent_ptr, is_get_type); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_request_get_type_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function indicates if the current request recieved from the */ /* SNMP manager is a Get type (GET, GETNEXT etc) of a SET type. It is */ /* intended for use in the username_callback for the host application */ /* to process the request for matching community string (private for */ /* set requests, public for get requests). */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* is_get_type Pointer to request type */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_request_get_type_test(NX_SNMP_AGENT *agent_ptr, UINT *is_get_type) { *is_get_type = agent_ptr -> nx_snmp_agent_request_get_type; return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_delete PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent delete */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_delete Actual agent delete function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_delete(NX_SNMP_AGENT *agent_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_delete(agent_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_delete PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function deletes the previously created SNMP agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* nx_udp_socket_delete Delete SNMP agent socket */ /* nx_udp_socket_unbind Unbind SNMP agent socket */ /* tx_thread_delete Delete SNMP agent thread */ /* tx_thread_terminate Terminate SNMP agent thread */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_delete(NX_SNMP_AGENT *agent_ptr) { /* Terminate the SNMP thread. */ tx_thread_terminate(&(agent_ptr -> nx_snmp_agent_thread)); /* Delete the SNMP thread. */ tx_thread_delete(&(agent_ptr -> nx_snmp_agent_thread)); /* Unbind the UDP socket. */ nx_udp_socket_unbind(&(agent_ptr -> nx_snmp_agent_socket)); /* Delete the UDP socket. */ nx_udp_socket_delete(&(agent_ptr -> nx_snmp_agent_socket)); /* Clear the agent ID to indicate the SNMP agent is deleted. */ agent_ptr -> nx_snmp_agent_id = 0; /* Return successful completion. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_current_version_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the get the received */ /* packet SNMP version service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* version Pointer to packet SNMP version*/ /* */ /* OUTPUT */ /* */ /* NX_PTR_ERROR Invalid pointer input */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_current_version_get Actual get version service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_current_version_get(NX_SNMP_AGENT *agent_ptr, UINT *version) { UINT status; if ((agent_ptr == NX_NULL) || (version == NX_NULL)) { return NX_PTR_ERROR; } status = _nx_snmp_agent_current_version_get(agent_ptr, version); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_current_version_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function returns the received packet's SNMP version. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* version Pointer to packet SNMP version*/ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_current_version_get(NX_SNMP_AGENT *agent_ptr, UINT *version) { *version = agent_ptr -> nx_snmp_agent_current_version; return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_set_version PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for (dis)enabling the SNMP */ /* agent for SNMPV1, SNMPV2 and SNMPV3. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* enabled_v1 V1 enable status */ /* enabled_v2 V2 enable status */ /* enabled_v3 V3 enable status */ /* Enable = 1 (NX_TRUE) */ /* */ /* OUTPUT */ /* */ /* NX_PTR_ERROR Invalid pointer input */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_version_set(NX_SNMP_AGENT *agent_ptr, UINT enabled_v1, UINT enable_v2, UINT enable_v3) { UINT status; /* Check for invalid input */ if (agent_ptr == NX_NULL) { return NX_PTR_ERROR; } /* Call the actual service. */ status = _nx_snmp_agent_version_set(agent_ptr, enabled_v1, enable_v2, enable_v3); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_version_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the SNMP agent status for SNMPV1, SNMPV2 and */ /* SNMPV3. */ /* */ /* Note that the #define options for disabling version support override*/ /* dynamic version status. */ /* */ /* For example if NX_SNMP_DISABLE_V2 is disabled, setting */ /* nx_snmp_agent_v2_enabled to NX_TRUE has no effect. If */ /* NX_SNMP_DISABLE_V2 is not disabled, then nx_snmp_agent_v2_enabled */ /* determines at run time if the SNMP is enabled for V2. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* enabled_v1 V1 enable status */ /* enabled_v2 V2 enable status */ /* enabled_v3 V3 enable status */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_version_set(NX_SNMP_AGENT *agent_ptr, UINT enabled_v1, UINT enable_v2, UINT enable_v3) { /* Set the agent status for each of the SNMP versions. */ agent_ptr -> nx_snmp_agent_v1_enabled = enabled_v1; agent_ptr -> nx_snmp_agent_v2_enabled = enable_v2; agent_ptr -> nx_snmp_agent_v3_enabled = enable_v3; return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_set_interface PORTABLE C */ /* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the SNMP network interface for the SNMP agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* if_index SNMP network interface index */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), */ /* checked the interface index,*/ /* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_set_interface(NX_SNMP_AGENT *agent_ptr, UINT if_index) { UINT status; if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) { return NX_PTR_ERROR; } /* Check for valid interface index. */ if (if_index >= NX_MAX_PHYSICAL_INTERFACES) { return(NX_INVALID_INTERFACE); } status = _nx_snmp_agent_set_interface(agent_ptr, if_index); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_set_interface PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the SNMP network interface for the SNMP agent. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* if_index SNMP network interface index */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_set_interface(NX_SNMP_AGENT *agent_ptr, UINT if_index) { agent_ptr -> nx_snmp_agent_interface_index = if_index; return NX_SUCCESS; } #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_md5_key_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP md5 key create */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the MD5 key */ /* destination_key Destination for the MD5 key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_md5_key_create Actual agent MD5 key create */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_md5_key_create(NX_SNMP_AGENT *agent_ptr, UCHAR *password, NX_SNMP_SECURITY_KEY *destination_key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (password == NX_NULL) || (destination_key == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_md5_key_create(agent_ptr, password, destination_key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_md5_key_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function creates an MD5 key. */ /* */ /* Note: new API nx_snmp_agent_md5_key_create_extended is encouraged */ /* to use. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the MD5 key */ /* destination_key Destination for the MD5 key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_utility_string_length_check Check string length */ /* _nx_snmp_agent_md5_key_create_extended Agent MD5 key create function*/ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_md5_key_create(NX_SNMP_AGENT *agent_ptr, UCHAR *password, NX_SNMP_SECURITY_KEY *destination_key) { /* Verify SNMP security is not disabled for this project. */ #ifdef NX_SNMP_NO_SECURITY /* Security is not supported, clear the key and return an error. */ destination_key -> nx_snmp_security_key_type = 0; destination_key -> nx_snmp_security_key_size = 0; /* Return an error. */ return(NX_NOT_ENABLED); #else UINT status; UINT password_length; /* Calculate the password length. */ if (_nx_utility_string_length_check((CHAR *)password, &password_length, NX_MAX_STRING_LENGTH)) { return(NX_SIZE_ERROR); } /* Check length of password. */ if (password_length == 0) { return(NX_SNMP_FAILED); } /* Call actual service. */ status = _nx_snmp_agent_md5_key_create_extended(agent_ptr, password, password_length, destination_key); /* Return status to the caller. */ return(status); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_md5_key_create_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP md5 key create */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the MD5 key */ /* password_length Length of password */ /* destination_key Destination for the MD5 key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_md5_key_create_extended */ /* Actual agent MD5 key create */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_md5_key_create_extended(NX_SNMP_AGENT *agent_ptr, UCHAR *password, UINT password_length, NX_SNMP_SECURITY_KEY *destination_key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (password == NX_NULL) || (password_length == 0) || (destination_key == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_md5_key_create_extended(agent_ptr, password, password_length, destination_key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_md5_key_create_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function creates an MD5 key. */ /* */ /* Note: The string of password must be NULL-terminated and length */ /* of string matches the length specified in the argument list. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the MD5 key */ /* password_length Length of password */ /* destination_key Destination for the MD5 key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_md5_initialize Initialize the MD5 algorithm */ /* _nx_md5_update MD5 algorithm update */ /* _nx_md5_digest_calculate Calculate the MD5 key */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_md5_key_create_extended(NX_SNMP_AGENT *agent_ptr, UCHAR *password, UINT password_length, NX_SNMP_SECURITY_KEY *destination_key) { /* Verify SNMP security is not disabled for this project. */ #ifdef NX_SNMP_NO_SECURITY /* Security is not supported, clear the key and return an error. */ destination_key -> nx_snmp_security_key_type = 0; destination_key -> nx_snmp_security_key_size = 0; /* Return an error. */ return(NX_NOT_ENABLED); #else NX_MD5 MD; UCHAR *cp, password_buf[64]; ULONG password_index = 0; ULONG count = 0, i; UINT temp_password_length; /* Get the length of password string. */ if (_nx_utility_string_length_check((CHAR *)password, &temp_password_length, password_length)) return(NX_SNMP_FAILED); /* Check the password string length. */ if (password_length != temp_password_length) return(NX_SNMP_FAILED); /* Initialize MD5. */ _nx_md5_initialize(&MD); /* Use while loop until we've done 1 Megabyte. */ while (count < 1048576) { cp = password_buf; for (i = 0; i < 64; i++) { /* Take the next octet of the password, wrapping to the beginning of the password as necessary. */ *cp++ = password[password_index++ % password_length]; } _nx_md5_update(&MD, password_buf, 64); count += 64; } _nx_md5_digest_calculate(&MD, destination_key -> nx_snmp_security_key); /* tell MD5 we're done */ /* Now localize the key with the engineID and pass through MD5 to produce final key May want to ensure that engineLength <= 32, otherwise need to use a buffer larger than 64 */ if(agent_ptr -> nx_snmp_agent_v3_context_engine_size > 32) return(NX_SNMP_FAILED); memcpy(password_buf, destination_key -> nx_snmp_security_key, 16); /* Use case of memcpy is verified. */ memcpy(password_buf+16, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size); /* Use case of memcpy is verified. */ memcpy(password_buf+16+agent_ptr -> nx_snmp_agent_v3_context_engine_size, destination_key -> nx_snmp_security_key, 16); /* Use case of memcpy is verified. */ _nx_md5_initialize(&MD); _nx_md5_update(&MD, password_buf, 32+agent_ptr -> nx_snmp_agent_v3_context_engine_size); _nx_md5_digest_calculate(&MD, destination_key -> nx_snmp_security_key); /* Setup other information in the key structure. */ destination_key -> nx_snmp_security_key_type = NX_SNMP_MD5_KEY; destination_key -> nx_snmp_security_key_size = 16; /* Return successful completion to the caller. */ return(NX_SUCCESS); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_privacy_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP privacy key */ /* specification function call. To disable encryption, set the */ /* key pointer to null. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Pointer to key to use for */ /* privacy (encryption) */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_privacy_key_use Actual privacy key setup */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_privacy_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) return(NX_PTR_ERROR); if (key != NX_NULL) { /* Check for valid privacy key type. */ if ((key -> nx_snmp_security_key_type != NX_SNMP_MD5_KEY) && (key -> nx_snmp_security_key_type != NX_SNMP_SHA_KEY)) { return NX_SNMP_INVALID_PDU_ENCRYPTION; } } /* Call actual service. */ status = _nx_snmp_agent_privacy_key_use(agent_ptr, key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_privacy_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets up the specified key to use for privacy. To */ /* disable authentication, set the key pointer to null. */ /* */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Pointer to key to use for */ /* privacy (encryption) */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_privacy_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { #ifdef NX_SNMP_NO_SECURITY return NX_NOT_ENABLED; #else /* Set the privacy pointer so encryption/decryption will use the specified key. Note this key must have been created prior to calling this routine. */ agent_ptr -> nx_snmp_agent_v3_privacy_key = key; /* Return success to the caller. */ return(NX_SUCCESS); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_priv_trap_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for setting the privacy key */ /* for SNMPv3 trap messages. To disable trap key encryption, set */ /* the key pointer to null. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Pointer to key to use for */ /* privacy (encryption) */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_priv_trap_key_use Actual set privacy key for */ /* SNMPv3 trap messages service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_priv_trap_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) { return(NX_PTR_ERROR); } if (key != NX_NULL) { /* Check for valid privacy key type. */ if ((key -> nx_snmp_security_key_type != NX_SNMP_MD5_KEY) && (key -> nx_snmp_security_key_type != NX_SNMP_SHA_KEY)) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } } /* Call actual service. */ status = _nx_snmp_agent_priv_trap_key_use(agent_ptr, key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_priv_trap_key_use PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets up the specified key to use for privacy for */ /* sending SNMPv3 trap messages. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* key Pointer to key to use for */ /* privacy (encryption) */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_priv_trap_key_use(NX_SNMP_AGENT *agent_ptr, NX_SNMP_SECURITY_KEY *key) { #ifdef NX_SNMP_NO_SECURITY return NX_NOT_ENABLED; #else /* Set the privacy pointer so encryption/decryption will use the specified key. Note this key must have been created prior to calling this routine. */ agent_ptr -> nx_snmp_agent_v3_priv_trap_key = key; /* Return success to the caller. */ return(NX_SUCCESS); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_sha_key_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP SHA key create */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the SHA key */ /* destination_key Destination for the SHA key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_sha_key_create Actual agent SHA key create */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_sha_key_create(NX_SNMP_AGENT *agent_ptr, UCHAR *password, NX_SNMP_SECURITY_KEY *destination_key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (password == NX_NULL) || (destination_key == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_sha_key_create(agent_ptr, password, destination_key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_sha_key_create PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function creates an SHA key. */ /* */ /* Note: new API nx_snmp_agent_sha_key_create_extended is encouraged */ /* to use. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the SHA key */ /* destination_key Destination for the SHA key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_utility_string_length_check Check string length */ /* _nx_snmp_agent_sha_key_create_extended Actual agent SHA key create */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_sha_key_create(NX_SNMP_AGENT *agent_ptr, UCHAR *password, NX_SNMP_SECURITY_KEY *destination_key) { /* Verify SNMP security is not disabled for this project. */ #ifdef NX_SNMP_NO_SECURITY /* Security is not supported, clear the key and return an error. */ destination_key -> nx_snmp_security_key_type = 0; destination_key -> nx_snmp_security_key_size = 0; /* Return an error. */ return(NX_NOT_ENABLED); #else UINT status; UINT password_length; /* Calculate the password length. */ if (_nx_utility_string_length_check((CHAR *)password, &password_length, NX_MAX_STRING_LENGTH)) { return(NX_SIZE_ERROR); } /* Check length of password. */ if (password_length == 0) { return(NX_SNMP_FAILED); } /* Call actual service. */ status = _nx_snmp_agent_sha_key_create_extended(agent_ptr, password, password_length, destination_key); /* Return status. */ return(status); #endif /* NX_SNMP_NO_SECURITY */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_sha_key_create_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP SHA key create */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the SHA key */ /* password_length Length of password */ /* destination_key Destination for the SHA key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_sha_key_create_extended Actual agent SHA key create */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_sha_key_create_extended(NX_SNMP_AGENT *agent_ptr, UCHAR *password, UINT password_length, NX_SNMP_SECURITY_KEY *destination_key) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (password == NX_NULL) || (password_length == 0) || (destination_key == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_sha_key_create_extended(agent_ptr, password, password_length, destination_key); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_sha_key_create_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function creates an SHA key. */ /* */ /* Note: The string of password must be NULL-terminated and length */ /* of string matches the length specified in the argument list. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* password Password for the SHA key */ /* password_length Length of password */ /* destination_key Destination for the SHA key */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_sha1_initialize Initialize the SHA algorithm */ /* _nx_sha1_update SHA algorithm update */ /* _nx_sha1_digest_calculate Calculate the SHA key */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_sha_key_create_extended(NX_SNMP_AGENT *agent_ptr, UCHAR *password, UINT password_length, NX_SNMP_SECURITY_KEY *destination_key) { /* Verify SNMP security is not disabled for this project. */ #ifdef NX_SNMP_NO_SECURITY /* Security is not supported, clear the key and return an error. */ destination_key -> nx_snmp_security_key_type = 0; destination_key -> nx_snmp_security_key_size = 0; /* Return an error. */ return(NX_NOT_ENABLED); #else NX_SHA1 SH; UCHAR *cp, password_buf[72]; ULONG password_index = 0; ULONG count = 0, i; UINT temp_password_length; /* Get the length of password string. */ if (_nx_utility_string_length_check((CHAR *)password, &temp_password_length, password_length)) return(NX_SNMP_FAILED); /* Check the password string length. */ if (password_length != temp_password_length) return(NX_SNMP_FAILED); memset(&SH, 0, sizeof(NX_SHA1)); memset(&password_buf[0], 0, 72); memset(destination_key, 0, sizeof(NX_SNMP_SECURITY_KEY)); /* Initialize SHA. */ _nx_sha1_initialize(&SH); /* Use while loop until we've done 1 Megabyte. */ while (count < 1048576) { cp = password_buf; for (i = 0; i < 64; i++) { /* Take the next octet of the password, wrapping to the beginning of the password as necessary. */ *cp++ = password[password_index++ % password_length]; } _nx_sha1_update(&SH, password_buf, 64); count += 64; } _nx_sha1_digest_calculate(&SH, destination_key -> nx_snmp_security_key); /* tell SHA we're done */ /* Now localize the key with the engineID and pass through SHA to produce final key May want to ensure that engineLength <= 32, otherwise need to use a buffer larger than 72. */ if(agent_ptr -> nx_snmp_agent_v3_context_engine_size > 32) return(NX_SNMP_FAILED); memcpy(password_buf, destination_key -> nx_snmp_security_key, 20); /* Use case of memcpy is verified. */ memcpy(password_buf+20, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size); /* Use case of memcpy is verified. */ memcpy(password_buf+20+agent_ptr -> nx_snmp_agent_v3_context_engine_size, destination_key -> nx_snmp_security_key, 20); /* Use case of memcpy is verified. */ _nx_sha1_initialize(&SH); _nx_sha1_update(&SH, password_buf, 40+agent_ptr -> nx_snmp_agent_v3_context_engine_size); _nx_sha1_digest_calculate(&SH, destination_key -> nx_snmp_security_key); /* Setup other information in the key structure. */ destination_key -> nx_snmp_security_key_type = NX_SNMP_SHA_KEY; destination_key -> nx_snmp_security_key_size = 20; /* Return successful completion to the caller. */ return(NX_SUCCESS); #endif /* NX_SNMP_NO_SECURITY */ } #endif /* NX_SNMP_DISABLE_V3 */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_public_string_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the check of community */ /* string against the agent's public community string. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to public string */ /* is_public Pointer to outcome */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agents_public_string_test Check public string service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_public_string_test(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string, UINT *is_public) { UINT status; if ((agent_ptr == NX_NULL) || (community_string == NX_NULL) || (is_public == NX_NULL)) { return NX_PTR_ERROR; } status = _nx_snmp_agent_public_string_test(agent_ptr, community_string, is_public); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_public_string_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs checks the input community string against the*/ /* agent's public community string. */ /* */ /* Note: The string length of community_string is limited by */ /* NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to public string */ /* is_public Pointer to outcome */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_public_string_test(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string, UINT *is_public) { UINT string_length1, string_length2; if (_nx_utility_string_length_check((CHAR *)community_string, &string_length1, NX_SNMP_MAX_USER_NAME)) { return(NX_SIZE_ERROR); } if (_nx_utility_string_length_check((CHAR *)agent_ptr -> nx_snmp_agent_public_community_string, &string_length2, NX_SNMP_MAX_USER_NAME)) { return(NX_SIZE_ERROR); } /* Initialize the outcome */ *is_public = NX_TRUE; if (string_length1 != string_length2) { /* Input string not the same as agent's public string. */ *is_public = NX_FALSE; return(NX_SUCCESS); } /* The string lengths match, now match the actual strings. */ if (memcmp(community_string, agent_ptr -> nx_snmp_agent_public_community_string, string_length1)) { /* Input string not the same as agent's public string. */ *is_public = NX_FALSE; } return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_private_string_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the nx_snmp_agent_receive_*/ /* _private_string service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to received string */ /* is_private Pointer to outcome */ /* NX_TRUE if strings match */ /* NX_FALSE if strings do not */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_private_string_test */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_private_string_test(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string, UINT *is_private) { UINT status; if ((agent_ptr == NX_NULL) || (community_string == NX_NULL) || (is_private == NX_NULL)) { return NX_PTR_ERROR; } status = _nx_snmp_agent_private_string_test(agent_ptr, community_string, is_private); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_private_string_test PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function determines if the community string of the received */ /* SNMP packet matches the SNMP agent's private community string. */ /* */ /* Note: The string length of community_string is limited by */ /* NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to received string */ /* is_private Pointer to outcome */ /* NX_TRUE if strings match */ /* NX_FALSE if strings do not */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_private_string_test(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string, UINT *is_private) { UINT string_length1, string_length2; if (_nx_utility_string_length_check((CHAR *)community_string, &string_length1, NX_SNMP_MAX_USER_NAME)) { return(NX_SIZE_ERROR); } if (_nx_utility_string_length_check((CHAR *)agent_ptr -> nx_snmp_agent_private_community_string, &string_length2, NX_SNMP_MAX_USER_NAME)) { return(NX_SIZE_ERROR); } /* Initialize the outcome */ *is_private = NX_TRUE; if (string_length1 != string_length2) { /* Input string not the same as agent's private string. */ *is_private = NX_FALSE; return(NX_SUCCESS); } /* The string lengths match, now match the actual strings. */ if (memcmp(community_string, agent_ptr -> nx_snmp_agent_private_community_string, string_length1)) { /* Input string not the same as agent's private string. */ *is_private = NX_FALSE; } return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_private_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the nx_snmp_agent_set_ */ /* _private_string service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to private string */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_private_string_set Set private string service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_private_string_set(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string) { UINT status; /* Check for invalid pointer input. */ if ((agent_ptr == NX_NULL) || (community_string == NX_NULL)) { return NX_PTR_ERROR; } /* Call the actual service. */ status = _nx_snmp_agent_private_string_set(agent_ptr, community_string); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_private_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the input string and size input as the Agent's */ /* private string and private string size. */ /* */ /* Note: The string length of community_string is limited by */ /* NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to private string */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_private_string_set(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string) { UINT i; UINT length; /* Verify the string is not too large, leaving room for the null terminating string. */ if (_nx_utility_string_length_check((CHAR *)community_string, &length, NX_SNMP_MAX_USER_NAME)) { return NX_SNMP_ERROR_TOOBIG; } /* Copy the string to the SNMP agent private community string. */ for (i = 0; i < length; i++) { agent_ptr -> nx_snmp_agent_private_community_string[i] = *community_string; community_string++; } /* Null terminate the string. */ agent_ptr -> nx_snmp_agent_private_community_string[i] = 0x0; return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_public_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the nx_snmp_agent_set_ */ /* _public_string service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to public string */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_public_string_set Set public string service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_public_string_set(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string) { UINT status; if ((agent_ptr == NX_NULL) || (community_string == NX_NULL)) { return NX_PTR_ERROR; } status = _nx_snmp_agent_public_string_set(agent_ptr, community_string); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_public_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sets the input string and size input as the Agent's */ /* public string and public string size. */ /* */ /* Note: The string length of community_string is limited by */ /* NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* community_string Pointer to public string */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successful completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_public_string_set(NX_SNMP_AGENT *agent_ptr, UCHAR *community_string) { UINT i; UINT length; /* Verify the string is not too large, leaving room for the null terminating character. */ if (_nx_utility_string_length_check((CHAR *)community_string, &length, NX_SNMP_MAX_USER_NAME)) { return NX_SNMP_ERROR_TOOBIG; } /* Copy the string to the SNMP agent public community string. */ for (i = 0; i < length; i++) { agent_ptr -> nx_snmp_agent_public_community_string[i] = *community_string; community_string++; } /* Null terminate the string. */ agent_ptr -> nx_snmp_agent_public_community_string[i] = 0x0; return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_start PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent start */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_start Actual agent start function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_start(NX_SNMP_AGENT *agent_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_start(agent_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_start PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function starts the SNMP agent thread. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* tx_thread_resume Resume SNMP agent thread */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_start(NX_SNMP_AGENT *agent_ptr) { UINT status; /* Bind the socket to a the well known SNMP UDP port number. */ status = nx_udp_socket_bind(&(agent_ptr -> nx_snmp_agent_socket), NX_SNMP_AGENT_PORT, NX_NO_WAIT); /* Determine if an error occurred. */ if (status) { /* Delete the UDP socket. */ nx_udp_socket_delete(&(agent_ptr -> nx_snmp_agent_socket)); /* Yes, return error code. */ return(NX_SNMP_ERROR); } /* Start the SNMP agent thread. */ tx_thread_resume(&(agent_ptr -> nx_snmp_agent_thread)); /* Return successful status. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_stop PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent stop */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_stop Actual agent stop function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_stop(NX_SNMP_AGENT *agent_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_stop(agent_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_stop PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function stops the SNMP agent thread. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* tx_thread_suspend Suspend SNMP agent thread */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_stop(NX_SNMP_AGENT *agent_ptr) { /* Stop the SNMP agent thread. */ tx_thread_suspend(&(agent_ptr -> nx_snmp_agent_thread)); /* Unbind the UDP socket. */ nx_udp_socket_unbind(&(agent_ptr -> nx_snmp_agent_socket)); /* Return successful status. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_thread_entry PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function is the entry function of the SNMP agent thread. */ /* */ /* INPUT */ /* */ /* snmp_agent_address Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* nx_packet_copy Copy SNMP packet */ /* nx_packet_release Release original SNMP packet */ /* _nx_snmp_utility_sequence_get Get sequence number in packet */ /* _nx_snmp_utility_version_get Get SNMP version number */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* nx_udp_socket_receive Receive SNMP request */ /* nx_udp_source_extract Extract source IP and port */ /* from request */ /* */ /* CALLED BY */ /* */ /* ThreadX */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ VOID _nx_snmp_agent_thread_entry(ULONG snmp_agent_address) { NX_SNMP_AGENT *agent_ptr; UCHAR *buffer_ptr; NX_PACKET *packet_ptr; UINT length; UINT version; UINT status; UINT sequence_length; INT buffer_length; #ifndef NX_DISABLE_PACKET_CHAIN NX_PACKET *new_packet_ptr; #endif /* Setup the agent pointer. */ agent_ptr = (NX_SNMP_AGENT *) snmp_agent_address; /* Loop to process SNMP Manager requests. */ while(1) { /* Wait for a SNMP Manager request. */ status = nx_udp_socket_receive(&(agent_ptr -> nx_snmp_agent_socket), &packet_ptr, NX_WAIT_FOREVER); /* Check for a successful packet reception. */ if (status) { /* If the error is other than no packet received, update the internal error count. */ if (status != NX_NO_PACKET) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; } /* Go back and wait for another packet. */ continue; } /* Pickup the source information for the packet - do this before the packet copy since the information prior to the prepend pointer is not copied! */ nxd_udp_source_extract(packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), &(agent_ptr -> nx_snmp_agent_current_manager_port)); #ifndef NX_DISABLE_PACKET_CHAIN /* Determine if we have to copy the packet into a packet from the SNMP pool. */ if (packet_ptr -> nx_packet_next) { /* Copy the packet into a packet from the SNMP pool. */ status = nx_packet_copy(packet_ptr, &new_packet_ptr, agent_ptr -> nx_snmp_agent_packet_pool_ptr, NX_SNMP_AGENT_TIMEOUT); /* Release the original packet. */ nx_packet_release(packet_ptr); /* Determine if the copy was successful. */ if (status || (new_packet_ptr -> nx_packet_next != NX_NULL)) { /* No, the packet copy was not successful. */ /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Go back and wait for another packet. */ continue; } /* Otherwise, copy the new packet pointer to the standard packet pointer. */ packet_ptr = new_packet_ptr; } #endif /*NX_DISABLE_PACKET_CHAIN */ buffer_length = (INT)(packet_ptr -> nx_packet_length); /* Setup a pointer to the buffer. */ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; /* Pickup the SEQUENCE field. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the unknown command error. */ agent_ptr -> nx_snmp_agent_unknown_requests++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Go back and wait for another packet. */ continue; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Pickup the SNMP VERSION field. */ length = _nx_snmp_utility_version_get(buffer_ptr, &version, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the unknown command error. */ agent_ptr -> nx_snmp_agent_unknown_requests++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Go back and wait for another packet. */ continue; } /* Increment the total number of packets received. */ agent_ptr -> nx_snmp_agent_packets_received++; /* We have a valid SNMP version, process relative to the type of SNMP version. */ if (version == NX_SNMP_VERSION_1) { #ifndef NX_SNMP_DISABLE_V1 /* Verify V1 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v1_enabled == NX_FALSE) { /* It is not. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); } else { /* Update the SNMP agent's version. */ agent_ptr -> nx_snmp_agent_current_version = version; /* Process SNMP Version 1 request. */ _nx_snmp_version_1_and_2_process(agent_ptr, packet_ptr); } #else /* Invalid version. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); #endif } #ifdef NX_SNMP_V2C_ONLY else if (version == NX_SNMP_VERSION_2C) #else else if ((version == NX_SNMP_VERSION_2) || (version == NX_SNMP_VERSION_2C)) #endif { #ifndef NX_SNMP_DISABLE_V2 /* Verify V2 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v2_enabled == NX_FALSE) { /* It is not. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); } else { /* Update the SNMP agent's version. */ agent_ptr -> nx_snmp_agent_current_version = version; /* Process SNMP Version 2 request. */ _nx_snmp_version_1_and_2_process(agent_ptr, packet_ptr); } #else /* Invalid version. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); #endif } else if (version == NX_SNMP_VERSION_3) { #ifndef NX_SNMP_DISABLE_V3 /* Verify V3 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v3_enabled == NX_FALSE) { /* It is not. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); } else { /* Update the SNMP agent's version. */ agent_ptr -> nx_snmp_agent_current_version = version; /* Process SNMP Version 3 request. */ _nx_snmp_version_3_process(agent_ptr, packet_ptr); } #else /* Invalid version. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); #endif } else { /* Invalid version. Increment error counter. */ agent_ptr -> nx_snmp_agent_invalid_version++; /* Release packet. */ nx_packet_release(packet_ptr); } } } #ifndef NX_SNMP_DISABLE_V1 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trap_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMPv1 trap send service. */ /* */ /* Developers are encouraged to use the nxd_snmp_agent_trap_send */ /* service which supports IPv4 and IPv6 types. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* community Community string */ /* enterprise Identifies the device that is */ /* generating the trap */ /* trap_type Type of trap */ /* trap_code Additional trap information */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_trap_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_trap_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UCHAR *enterprise, UINT trap_type, UINT trap_code, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL) || (enterprise == NX_NULL)) return(NX_PTR_ERROR); /* Check for invalid IP address. */ if (ip_address == 0) return(NX_IP_ADDRESS_ERROR); /* Call actual service. */ status = _nx_snmp_agent_trap_send(agent_ptr, ip_address, community, enterprise, trap_type, trap_code, elapsed_time, object_list_ptr); /* Return status. */ return(status); #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(enterprise); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(trap_code); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_trap_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function stores the input IPv4 destination IP address in a NetX*/ /* Duo data type that supports IPv4 and IPv6 address formats, and */ /* uses the 'dual' trap send service _nxd_snmp_agent_trap_send to build*/ /* and send the SNMPv1 trap message. */ /* */ /* Developers are encouraged to use nxd_snmp_agent_trap_send. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* community Community string */ /* enterprise Identifies the device that is */ /* generating the trap */ /* trap_type Type of trap */ /* trap_code Additional trap information */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* NX_NOT_ENABLED Agent not enabled for V1 */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trap_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_trap_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UCHAR *enterprise, UINT trap_type, UINT trap_code, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; NXD_ADDRESS ip_netxduo_address; ip_netxduo_address.nxd_ip_address.v4 = ip_address; ip_netxduo_address.nxd_ip_version = NX_IP_VERSION_V4; status = _nxd_snmp_agent_trap_send(agent_ptr, &ip_netxduo_address, community, enterprise, trap_type, trap_code, elapsed_time, object_list_ptr); return status; #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(enterprise); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(trap_code); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxde_snmp_agent_trap_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMPv1 trap send service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community string */ /* enterprise Identifies the device that is */ /* generating the trap */ /* trap_type Type of trap */ /* trap_code Additional trap information */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trap_send Actual SNMPv1 trap send */ /* service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxde_snmp_agent_trap_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *community, UCHAR *enterprise, UINT trap_type, UINT trap_code, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL) || (enterprise == NX_NULL) || (ip_address == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nxd_snmp_agent_trap_send(agent_ptr, ip_address, community, enterprise, trap_type, trap_code, elapsed_time, object_list_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trap_send PORTABLE C */ /* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v1 trap message to the input */ /* destination address. This service supports both IPv4 and IPv6 */ /* addresses. */ /* */ /* Note: The string length of community and enterprise are limited by */ /* the packet payload and NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community string */ /* enterprise Identifies the device that is */ /* generating the trap */ /* trap_type Type of trap */ /* trap_code Additional trap information */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* nx_packet_allocate Allocate SNMP trap packet */ /* nx_packet_release Release SNMP packet */ /* nx_udp_socket_send Send SNMP trap via UDP */ /* _nx_snmp_object_copy Copy object */ /* _nx_snmp_utility_community_set Set the community name */ /* _nx_snmp_utility_object_data_set Set the data value */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_sequence_set Set the ASN.1 sequence */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_version_set Set the SNMP v1 */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), */ /* checked the interface index,*/ /* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trap_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *community, UCHAR *enterprise, UINT trap_type, UINT trap_code, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; UINT trap_length; UCHAR *trap_object_ptr; NX_SNMP_OBJECT_DATA *trap_object_data_ptr = NX_NULL; NX_SNMP_OBJECT_DATA trap_object_data; NX_PACKET *trap_packet_ptr; UCHAR *trap_buffer_ptr, *trap_sequence_ptr, *trap_type_ptr, *trap_variable_list_ptr, *trap_variable_ptr; UINT trap_sequence_length, trap_type_length, trap_variable_list_length, trap_variable_length; UINT packet_type; /* Verify V1 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v1_enabled == NX_FALSE) { return NX_NOT_ENABLED; } /* Now prepare trap message so we can process the variables one by one. */ /* Determine which packet type we allocate based on the destination address type. */ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; #else packet_type = NX_IPv6_UDP_PACKET; #endif /* FEATURE_NX_IPV6 */ } else { return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; } status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &trap_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a trap packet was allocated. */ if (status) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return(NX_SNMP_ERROR); } memset(trap_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(trap_packet_ptr -> nx_packet_data_end - trap_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the trap packet. */ trap_sequence_length = 0; trap_type_length = 0; trap_variable_list_length = 0; /* Setup a pointer to the trap packet's buffer area. */ trap_buffer_ptr = trap_packet_ptr -> nx_packet_prepend_ptr; /* This is also the trap sequence pointer. Remember it since we are going to have to update it later with the actual length of the trap. */ trap_sequence_ptr = trap_buffer_ptr; /* First, write the sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Now set the Version ID in the trap message. */ trap_length = _nx_snmp_utility_version_set(trap_buffer_ptr, NX_SNMP_VERSION_1, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the community in the trap message. */ trap_length = _nx_snmp_utility_community_set(trap_buffer_ptr, community, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Remember the request type pointer, since it will need to be updated later. */ trap_type_ptr = trap_buffer_ptr; /* Now set the request type in the trap message. */ trap_length = _nx_snmp_utility_request_type_set_multibyte(trap_buffer_ptr, NX_SNMP_ANS1_TRAP_REQUEST, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the enterprise ID in the trap message. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, enterprise, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the agent's IP address. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_IP_ADDRESS; #ifndef NX_DISABLE_IPV4 /* Check if the interface index is valid. */ if (agent_ptr -> nx_snmp_agent_interface_index >= NX_MAX_PHYSICAL_INTERFACES) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } trap_object_data.nx_snmp_object_data_msw = (LONG)(agent_ptr -> nx_snmp_agent_ip_ptr) -> nx_ip_interface[agent_ptr -> nx_snmp_agent_interface_index].nx_interface_ip_address; #else trap_object_data.nx_snmp_object_data_msw = 0; #endif /* NX_DISABLE_IPV4 */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Check that we have a valid trap type requested. */ if (trap_type > TRAP_ID_MAX) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Set the trap type. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_INTEGER; trap_object_data.nx_snmp_object_data_msw = (LONG)trap_type; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the specific trap type. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_INTEGER; trap_object_data.nx_snmp_object_data_msw = (LONG)trap_code; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the specific time-stamp. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_TIME_TICS; trap_object_data.nx_snmp_object_data_msw = (LONG)elapsed_time; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the trap's variable list field. */ trap_variable_list_ptr = trap_buffer_ptr; /* Set up the variable list. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if an object is specified. */ if (object_list_ptr) { /* Setup object pointers from the supplied object list. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } /* Loop to process all the objects in the list. */ while (trap_object_ptr) { /* Clear the trap variable length. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the object into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, trap_object_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, trap_object_data_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if there are more objects to insert into the trap message. */ if (object_list_ptr) { /* Move to the next object in the list. */ object_list_ptr++; if (object_list_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Determine if there is another object. */ if (object_list_ptr -> nx_snmp_object_string_ptr) { /* Setup the object and object data pointers. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } } } /* At this point, several trap fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_variable_list_ptr, trap_variable_list_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(trap_type_ptr, NX_SNMP_ANS1_TRAP_REQUEST, trap_type_length, trap_packet_ptr -> nx_packet_data_end); /* Now the trap packet's pointers must be setup so it can be sent. */ trap_packet_ptr -> nx_packet_length = (ULONG)(trap_buffer_ptr - trap_packet_ptr -> nx_packet_prepend_ptr); trap_packet_ptr -> nx_packet_append_ptr = trap_buffer_ptr; /* Update various statistics. */ agent_ptr -> nx_snmp_agent_traps_sent++; agent_ptr -> nx_snmp_agent_packets_sent++; /* Send the trap packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), trap_packet_ptr, ip_address, NX_SNMP_MANAGER_TRAP_PORT); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(trap_packet_ptr); } /* Return completion status. */ return(status); } #endif /* NX_SNMP_DISABLE_V1 */ #ifndef NX_SNMP_DISABLE_V2 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trapv2_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMPv2 trap send service. */ /* */ /* Developers are encouraged to use the nxd_snmp_agent_trapv2_send */ /* service which supports IPv4 and IPv6 types. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* community Community name */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_trapv2_send Actual NetX (IPv4) SNMP trap */ /* send service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_trapv2_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL) || (ip_address == 0)) return(NX_PTR_ERROR); /* Call actual netx service. */ status = _nx_snmp_agent_trapv2_send(agent_ptr, ip_address, community, trap_type, elapsed_time, object_list_ptr); /* Return status. */ return(status); #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_trapv2_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function stores the input IPv4 destination IP address in a NetX*/ /* Duo data type that supports IPv4 and IPv6 address formats, and */ /* uses the 'dual' trap send service _nxd_snmp_agent_trap_send to build*/ /* and send the SNMPv2 trap message. */ /* */ /* Developers are encouraged to use nxd_snmp_agent_trapv2_send. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* community Community name */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* NX_NOT_ENABLED Agent not enabled for V2 */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv2_send Actual NetX Duo SNMP trap */ /* send service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_trapv2_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; NXD_ADDRESS ip_nxduo_address; ip_nxduo_address.nxd_ip_version = NX_IP_VERSION_V4; ip_nxduo_address.nxd_ip_address.v4 = ip_address; status = _nxd_snmp_agent_trapv2_send(agent_ptr, &ip_nxduo_address, community, trap_type, elapsed_time, object_list_ptr); return status; #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxde_snmp_agent_trapv2_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMPv2 trap send service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv2_send Actual SNMPv2 trap send */ /* service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxde_snmp_agent_trapv2_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *community, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL) || (ip_address == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nxd_snmp_agent_trapv2_send(agent_ptr, ip_address, community, trap_type, elapsed_time, object_list_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trapv2_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMPv2 trap message to the input */ /* destination address. This service supports both IPv4 and IPv6 */ /* addresses. */ /* */ /* Note: The string length of community is limited by the packet */ /* payload and NX_SNMP_MAX_USER_NAME. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* nx_packet_allocate Allocate SNMP trap packet */ /* nx_packet_release Release SNMP packet */ /* nx_udp_socket_send Send SNMP trap via UDP */ /* _nx_snmp_object_copy Copy object */ /* _nx_snmp_utility_community_set Set the community name */ /* _nx_snmp_utility_error_info_set Set error information */ /* _nx_snmp_utility_object_data_set Set the data value */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_sequence_set Set the ASN.1 sequence */ /* _nx_snmp_utility_request_id_set Set the Trap ID */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_version_set Set the SNMP v1 */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trapv2_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *community, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; UINT trap_length; UCHAR *trap_object_ptr; NX_SNMP_OBJECT_DATA trap_object_data; NX_SNMP_OBJECT_DATA *trap_object_data_ptr = NX_NULL; NX_PACKET *trap_packet_ptr; UCHAR *trap_buffer_ptr, *trap_sequence_ptr, *trap_type_ptr, *trap_variable_list_ptr, *trap_variable_ptr; UINT trap_sequence_length, trap_type_length, trap_variable_list_length, trap_variable_length; UINT packet_type; /* Verify V2 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v2_enabled == NX_FALSE) { return NX_NOT_ENABLED; } /* Determine which packet type we allocate based on the destination address type. */ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; #else packet_type = NX_IPv6_UDP_PACKET; #endif } else { return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; } /* Now prepare trap message so we can process the variables one by one. */ /* Allocate the packet for the SNMP v2 trap. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &trap_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a trap packet was allocated. */ if (status) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return(NX_SNMP_ERROR); } memset(trap_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(trap_packet_ptr -> nx_packet_data_end - trap_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the trap packet. */ trap_sequence_length = 0; trap_type_length = 0; trap_variable_list_length = 0; trap_variable_length = 0; /* Setup a pointer to the trap packet's buffer area. */ trap_buffer_ptr = trap_packet_ptr -> nx_packet_prepend_ptr; /* This is also the trap sequence pointer. Remember it since we are going to have to update it later with the actual length of the trap. */ trap_sequence_ptr = trap_buffer_ptr; /* First, write the sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Now set the Version ID in the trap message. */ trap_length = _nx_snmp_utility_version_set(trap_buffer_ptr, NX_SNMP_VERSION_2C, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the community in the trap message. */ trap_length = _nx_snmp_utility_community_set(trap_buffer_ptr, community, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Remember the request type pointer, since it will need to be updated later. */ trap_type_ptr = trap_buffer_ptr; /* Now set the request type in the trap message. */ trap_length = _nx_snmp_utility_request_type_set_multibyte(trap_buffer_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the trap ID in the trap message. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the trap error information. */ trap_length = _nx_snmp_utility_error_info_set(trap_buffer_ptr, 0, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the trap's variable list field. */ trap_variable_list_ptr = trap_buffer_ptr; /* Setup the variable list. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the sysUpTime object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.2.1.1.3.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the SysTimerTicks into the trap buffer as the first item in the variable binding list. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_TIME_TICS; trap_object_data.nx_snmp_object_data_msw = (LONG)elapsed_time; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Clear the trap variable size. */ trap_variable_length = 0; /* Check that we have a valid trap type requested. */ if ((trap_type > TRAP_ID_MAX) && (trap_type != NX_SNMP_TRAP_CUSTOM)) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Check that we have a trap list if a custom trap is requested. */ if ((object_list_ptr == NX_NULL) && (trap_type == NX_SNMP_TRAP_CUSTOM)) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Check if this is an enumerated trap event. */ if (trap_type <= TRAP_ID_MAX) { /* Set up the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the snmpTrapOID object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.6.3.1.1.4.1.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Set an Object ID for the data. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_OBJECT_ID; trap_object_data.nx_snmp_object_data_msw = 0; /* Copy the object specified by the trap_type index. */ _nx_snmp_object_copy(_nx_snmp_v2_trap_ids[trap_type], trap_object_data.nx_snmp_object_octet_string); /* Add trap object data to trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; } /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if an object is specified. */ if (object_list_ptr) { /* Setup object pointers from the supplied object list. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } /* Loop to process all the objects in the list. */ while (trap_object_ptr) { /* Clear the trap variable length. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the object into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, trap_object_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, trap_object_data_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if there are more objects to insert into the trap message. */ if (object_list_ptr) { /* Move to the next object in the list. */ object_list_ptr++; if (object_list_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Determine if there is another object. */ if (object_list_ptr -> nx_snmp_object_string_ptr) { /* Setup the object and object data pointers. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } } } /* At this point, several trap fields need to be updated with actual lengths. */ _nx_snmp_utility_request_type_set_multibyte(trap_type_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, trap_type_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_variable_list_ptr, trap_variable_list_length, trap_packet_ptr -> nx_packet_data_end); /* Update the trap packet's pointers. */ trap_packet_ptr -> nx_packet_length = (ULONG)(trap_buffer_ptr - trap_packet_ptr -> nx_packet_prepend_ptr); trap_packet_ptr -> nx_packet_append_ptr = trap_buffer_ptr; /* Update various statistics. */ agent_ptr -> nx_snmp_agent_traps_sent++; agent_ptr -> nx_snmp_agent_packets_sent++; /* Send the trap packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), trap_packet_ptr, ip_address, NX_SNMP_MANAGER_TRAP_PORT); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return an error. */ return(NX_SNMP_ERROR); } /* Return completion status. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trapv2_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent v2 trap send */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* OID OID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_trapv2_oid_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_trapv2_oid_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL)) return(NX_PTR_ERROR); /* Check for invalid IP address. */ if (ip_address == 0) return(NX_IP_ADDRESS_ERROR); /* Call actual service. */ status = _nx_snmp_agent_trapv2_oid_send(agent_ptr, ip_address, community, oid, elapsed_time, object_list_ptr); /* Return status. */ return(status); #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(oid); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_trapv2__oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v2 trap message using the OID */ /* directly from the caller. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* OID OID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv2_oid_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_trapv2_oid_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *community, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; NXD_ADDRESS ipduo_address; ipduo_address.nxd_ip_version = NX_IP_VERSION_V4; ipduo_address.nxd_ip_address.v4 = ip_address; status = _nxd_snmp_agent_trapv2_oid_send(agent_ptr, &ipduo_address, community, oid, elapsed_time, object_list_ptr); return status; #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(community); NX_PARAMETER_NOT_USED(oid); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxde_snmp_agent_trapv2_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent v2 trap send */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* OID OID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv2_oid_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxde_snmp_agent_trapv2_oid_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ipduo_address, UCHAR *community, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (community == NX_NULL) || (ipduo_address == NX_NULL)) { return(NX_PTR_ERROR); } /* Call actual service. */ status = _nxd_snmp_agent_trapv2_oid_send(agent_ptr, ipduo_address, community, oid, elapsed_time, object_list_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trapv2_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v2 trap message using the OID */ /* directly from the caller. Supports IPv6 and IPv4 connections. */ /* */ /* Note: The string length of community is limited by the packet */ /* payload and NX_SNMP_MAX_USER_NAME. The string length of oid is */ /* limited by the packet payload and NX_SNMP_MAX_OCTET_STRING. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* OID OID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* nx_packet_allocate Allocate SNMP trap packet */ /* nx_packet_release Release SNMP packet */ /* nx_udp_socket_send Send SNMP trap via UDP */ /* _nx_snmp_object_copy Copy object */ /* _nx_snmp_utility_community_set Set the community name */ /* _nx_snmp_utility_error_info_set Set error information */ /* _nx_snmp_utility_object_data_set Set the data value */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_sequence_set Set the ASN.1 sequence */ /* _nx_snmp_utility_request_id_set Set the Trap ID */ /* _nx_snmp_utility_sequence_set_1byte */ /* Set trap sequence */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_version_set Set the SNMP v1 */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trapv2_oid_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ipduo_address, UCHAR *community, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; UINT trap_length; UCHAR *trap_object_ptr; NX_SNMP_OBJECT_DATA trap_object_data; NX_SNMP_OBJECT_DATA *trap_object_data_ptr = NX_NULL; NX_PACKET *trap_packet_ptr; UCHAR *trap_buffer_ptr, *trap_sequence_ptr, *trap_type_ptr, *trap_variable_list_ptr, *trap_variable_ptr; UINT trap_sequence_length, trap_type_length, trap_variable_list_length, trap_variable_length; UINT packet_type = NX_UDP_PACKET; if (ipduo_address -> nxd_ip_version == NX_IP_VERSION_V6) { packet_type = NX_IPv6_UDP_PACKET; } else { packet_type = NX_IPv4_UDP_PACKET; } /* Allocate the packet for the SNMP v2 trap. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &trap_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a trap packet was allocated. */ if (status) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return(NX_SNMP_ERROR); } /* Now prepare trap message so we can process the variables one by one. */ /* Initialize the counters required for the length fields of the trap packet. */ trap_sequence_length = 0; trap_type_length = 0; trap_variable_list_length = 0; trap_variable_length = 0; /* Setup a pointer to the trap packet's buffer area. */ trap_buffer_ptr = trap_packet_ptr -> nx_packet_prepend_ptr; /* This is also the trap sequence pointer. Remember it since we are going to have to update it later with the actual length of the trap. */ trap_sequence_ptr = trap_buffer_ptr; /* First, write the sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Now set the Version ID in the trap message. */ trap_length = _nx_snmp_utility_version_set(trap_buffer_ptr, NX_SNMP_VERSION_2C, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the community in the trap message. */ trap_length = _nx_snmp_utility_community_set(trap_buffer_ptr, community, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Remember the request type pointer, since it will need to be updated later. */ trap_type_ptr = trap_buffer_ptr; /* Now set the request type in the trap message. */ trap_length = _nx_snmp_utility_request_type_set_multibyte(trap_buffer_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now set the trap ID in the trap message. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the trap error information. */ trap_length = _nx_snmp_utility_error_info_set(trap_buffer_ptr, 0, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the trap's variable list field. */ trap_variable_list_ptr = trap_buffer_ptr; /* Setup the variable list. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the sysUpTime object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.2.1.1.3.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_TIME_TICS; trap_object_data.nx_snmp_object_data_msw = (LONG)elapsed_time; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Clear the trap variable size. */ trap_variable_length = 0; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the snmpTrapOID object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.6.3.1.1.4.1.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Set a Object ID for the data. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_OBJECT_ID; trap_object_data.nx_snmp_object_data_msw = 0; /* Check oid length. */ if (_nx_utility_string_length_check((CHAR *)oid, NX_NULL, NX_SNMP_MAX_OCTET_STRING)) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } _nx_snmp_object_copy(oid, trap_object_data.nx_snmp_object_octet_string); trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if an object is specified. */ if (object_list_ptr) { /* Setup object pointers from the supplied object list. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } /* Loop to process all the objects in the list. */ while (trap_object_ptr) { /* Clear the trap variable length. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the object into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, trap_object_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, trap_object_data_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if there are more objects to insert into the trap message. */ if (object_list_ptr) { /* Move to the next object in the list. */ object_list_ptr++; if (object_list_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Determine if there is another object. */ if (object_list_ptr -> nx_snmp_object_string_ptr) { /* Setup the object and object data pointers. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } } } /* At this point, several trap fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_variable_list_ptr, trap_variable_list_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(trap_type_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, trap_type_length, trap_packet_ptr -> nx_packet_data_end); /* Now the trap packet's pointers must be setup so it can be sent. */ trap_packet_ptr -> nx_packet_length = (ULONG)(trap_buffer_ptr - trap_packet_ptr -> nx_packet_prepend_ptr); trap_packet_ptr -> nx_packet_append_ptr = trap_buffer_ptr; /* Update various statistics. */ agent_ptr -> nx_snmp_agent_traps_sent++; agent_ptr -> nx_snmp_agent_packets_sent++; /* Send the trap packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), trap_packet_ptr, ipduo_address, NX_SNMP_MANAGER_TRAP_PORT); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return an error. */ return(NX_SNMP_ERROR); } /* Return completion status. */ return(NX_SUCCESS); } #endif /* NX_SNMP_DISABLE_V2 */ #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trapv3_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the NetX (IPv4) SNMP agent v3 */ /* trap send service. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* username Username */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_trapv3_send Actual NetX (IPv4) SNMP agent */ /* trap send service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_trapv3_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *username, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (username == NX_NULL) || (ip_address == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_agent_trapv3_send(agent_ptr, ip_address, username, trap_type, elapsed_time, object_list_ptr); /* Return status. */ return(status); #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(username); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_trapv3_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function stores the input IPv4 destination IP address in a NetX*/ /* Duo data type that supports IPv4 and IPv6 address formats, and */ /* uses the 'dual' trap send service _nxd_snmp_agent_trap_send to build*/ /* and send the SNMPv3 trap message. */ /* */ /* Developers are encouraged to use nxd_snmp_agent_trapv3_send. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IPv4 address */ /* username Username */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* NX_NOT_ENABLED Agent not enabled for V3 */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv3_send Actual SNMPv3 trap send */ /* service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_trapv3_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *username, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; NXD_ADDRESS ip_nxduo_address; ip_nxduo_address.nxd_ip_version = NX_IP_VERSION_V4; ip_nxduo_address.nxd_ip_address.v4 = ip_address; status = _nxd_snmp_agent_trapv3_send(agent_ptr, &ip_nxduo_address, username, trap_type, elapsed_time, object_list_ptr); return status; #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(username); NX_PARAMETER_NOT_USED(trap_type); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxde_snmp_agent_trapv3_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMPv3 trap send service. */ /* */ /* Developers are encouraged to use the nxd_snmp_agent_trapv3_send */ /* service which supports IPv4 and IPv6 types. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* username Username */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv3_send Actual NetX Duo SNMP agent */ /* trap send service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxde_snmp_agent_trapv3_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *username, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (username == NX_NULL) || (ip_address == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nxd_snmp_agent_trapv3_send(agent_ptr, ip_address, username, trap_type, elapsed_time, object_list_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trapv3_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v3 trap message to the input */ /* destination address. This service supports both IPv4 and IPv6 */ /* addresses. */ /* */ /* Note: The string length of username is limited by the packet */ /* payload and NX_SNMP_MAX_OCTET_STRING. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* username Username */ /* trap_type Type of trap */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_des_key_set Setup DES encryption */ /* _nx_des_encrypt Encrypt bytes */ /* _nx_md5_digest_calculate MD5 algorithm completion */ /* _nx_md5_initialize MD5 algorithm initialization */ /* _nx_md5_update MD5 algorithm computation */ /* nx_packet_allocate Allocate SNMP trap packet */ /* nx_packet_release Release SNMP packet */ /* nx_udp_socket_send Send SNMP trap via UDP */ /* _nx_snmp_object_copy Copy object */ /* _nx_snmp_utility_error_info_set Set error information */ /* _nx_snmp_utility_octet_set Set octet string */ /* _nx_snmp_utility_object_data_set Set the data value */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_sequence_set Set the ASN.1 sequence */ /* _nx_snmp_utility_request_id_set Set the Request ID */ /* _nx_snmp_utility_request_type_set_1byte Set trap request type */ /* _nx_snmp_utility_version_set Set the SNMP v3 */ /* _nx_sha1_digest_calculate SHA algorithm completion */ /* _nx_sha1_initialize SHA algorithm initialization */ /* _nx_sha1_update SHA algorithm computation */ /* tx_time_get Get time */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trapv3_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *username, UINT trap_type, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; UINT trap_length; UCHAR *trap_object_ptr; NX_SNMP_OBJECT_DATA trap_object_data; NX_SNMP_OBJECT_DATA *trap_object_data_ptr = NX_NULL; NX_PACKET *trap_packet_ptr; UCHAR *trap_buffer_ptr, *trap_sequence_ptr, *trap_header_ptr, *trap_security_ptr, *trap_pdu_ptr, *trap_type_ptr, *trap_variable_list_ptr, *trap_variable_ptr; UINT trap_sequence_length, trap_header_length, trap_security_length, trap_pdu_length, trap_type_length, trap_variable_list_length, trap_variable_length; UCHAR temp_string[NX_SNMP_DIGEST_SIZE]; UINT i; UCHAR *temp_ptr; UINT j, padding; UCHAR *trap_encryption_size_ptr = NX_NULL; UCHAR *trap_authentication_ptr = NX_NULL, *trap_privacy_ptr = NX_NULL; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; UINT packet_type; UCHAR message_security_options = 0; UINT username_length; /* Verify V3 is currently enabled for this agent. */ if (agent_ptr -> nx_snmp_agent_v3_enabled == NX_FALSE) { return NX_NOT_ENABLED; } /* Determine which packet type we allocate based on the destination address type. */ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; #else packet_type = NX_IPv6_UDP_PACKET; #endif } else { return NX_SNMP_INVALID_IP_PROTOCOL_ERROR; } /* Allocate the packet for the SNMP response. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &trap_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a trap packet was allocated. */ if (status) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return(NX_SNMP_ERROR); } memset(trap_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(trap_packet_ptr -> nx_packet_data_end - trap_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the trap packet. */ trap_sequence_length = 0; trap_header_length = 0; trap_security_length = 0; trap_pdu_length = 0; trap_type_length = 0; trap_variable_list_length = 0; trap_variable_length = 0; /* Setup a pointer to the trap packet's buffer area. */ trap_buffer_ptr = trap_packet_ptr -> nx_packet_prepend_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap buffer response at 0x%x\n", trap_buffer_ptr); #endif /* This is also the trap sequence pointer. Remember it since we are going to have to update it later with the actual length of the response. */ trap_sequence_ptr = trap_buffer_ptr; /* First, write the sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Now set the Version ID in the trap message. */ trap_length = _nx_snmp_utility_version_set(trap_buffer_ptr, NX_SNMP_VERSION_3, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Save the pointer to the global header. */ trap_header_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap3 header header at 0x%x\n", trap_header_ptr); #endif /* Write the sequence for the global header in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /***************8 Now set the request ID. *********************8*/ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /********************* Now set the maximum message size. ***************************8*/ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, (NX_SNMP_PACKET_SIZE - NX_UDP_PACKET), trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /********************** Now set the security options e.g. Flags. ****************************/ /* Determine what the trap message security options are. These are not the same as the general get/set request PDU options. */ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { message_security_options = NX_SNMP_SECURITY_AUTHORIZE; } if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { message_security_options |= NX_SNMP_SECURITY_PRIVACY; } trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, (UCHAR *)&message_security_options, 1, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /******************* Now set the security type (always USM model). *********************/ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, NX_SNMP_USM_SECURITY_MODEL, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /* At this point, we have successfully built the security header. */ /************************** Start the security parameters field. ************************/ /* First set up the octet string field. For now just put in zeros... we will update when the actual size is known. */ trap_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; trap_buffer_ptr[1] = 0; /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + 2; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + 2; /* Remember the security header length pointer. */ trap_security_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap3 security header 0x%x\n", trap_security_ptr); #endif /* Now set the sequence of the USM security parameters. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /************************** Now set the context engine. ***************************/ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /****************** ***************** **********************/ /* Now set BOOT COUNT. */ /****************** ***************** **********************/ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boots, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /****************** ***************** **********************/ /* Now set BOOT TIME. */ /****************** ***************** **********************/ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Check username length. */ if (_nx_utility_string_length_check((CHAR *)username, &username_length, NX_SNMP_MAX_OCTET_STRING)) { return(NX_SIZE_ERROR); } /****************** ***************** **********************/ /* Now set USER NAME. */ /****************** ***************** **********************/ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, username, username_length, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Initialize the temporary string to zero. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) temp_string[i] = 0; /****************** ***************** **********************/ /* Now set AUTHENTICATION PARAMETER. */ /****************** ***************** **********************/ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { /* We have a valid authentication key, so initialize the string to zero. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string, NX_SNMP_DIGEST_SIZE, trap_packet_ptr -> nx_packet_data_end); trap_authentication_ptr = trap_buffer_ptr + 2; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap3 authentication header 0x%x\n", trap_authentication_ptr); #endif } else { /* No security enabled so set this as an empty parameter. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string,0, trap_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /****************** ***************** **********************/ /* Now set 8 char PRIVACY PARAMETER. */ /****************** ***************** **********************/ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { /* We will encrypt the message, so set to all zeros field initially. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string, 8, trap_packet_ptr -> nx_packet_data_end); trap_privacy_ptr = trap_buffer_ptr + 2; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_privacy_ptr 0x%x\n", trap_privacy_ptr); #endif } else { /* Not encrypting, so set the privacy field as an empty parameter. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string,0, trap_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* If privacy is required, set the response to have an encryption header. */ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { /* Now setup the trap buffer to encapsulate the encrypted PDU. Note that the actual encryption will be done after the complete trap has been formed. */ trap_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; trap_buffer_ptr[1] = 0x82; trap_buffer_ptr[2] = 0x00; trap_buffer_ptr[3] = 0x00; /* Save the trap encryption size pointer. This will be filled in below as we build the message. */ trap_encryption_size_ptr = trap_buffer_ptr + 2; /* Move the trap buffer forward. */ trap_buffer_ptr = trap_buffer_ptr + 4; /* Increase the length of the total trap message. */ trap_sequence_length = trap_sequence_length + 4; } /* Save the trap pdu sequence pointer. */ trap_pdu_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_pdu_ptr: 0x%x\n", trap_pdu_ptr); #endif /****************** ***************** **********************/ /* Now start the PDU SEQUENCE. */ /****************** ***************** **********************/ /* A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Increment the number of trap sequence bytes. */ trap_sequence_length = trap_sequence_length + trap_length; /****************************************************/ /* Set the PDU engine ID */ /****************************************************/ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (trap_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap pointer forward. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Increment the sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /****************************************************/ /* Set the PDU engine name */ /****************************************************/ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_name, agent_ptr -> nx_snmp_agent_v3_context_name_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (trap_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap pointer forward. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Save the pointer to the trap type. */ trap_type_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_type_ptr: 0x%x\n", trap_type_ptr); #endif /* Increment the sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /****************************************************/ /* Set the PDU request type */ /****************************************************/ trap_length = _nx_snmp_utility_request_type_set_multibyte(trap_buffer_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /****************************************************/ /* Set the PDU request ID */ /****************************************************/ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up (this assumes two bytes but we may need more) . */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /****************************************************/ /* Get the PDU error information */ /****************************************************/ /* Assume everything is okay at this point. */ trap_length = _nx_snmp_utility_error_info_set(trap_buffer_ptr, 0, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the response's variable list field. */ trap_variable_list_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_variable_list_ptr: 0x%x\n", trap_variable_list_ptr); #endif /* Setup the variable list. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_variable_ptr: 0x%x\n", trap_variable_ptr); #endif /****************************************************/ /* Start the PDU variable list length */ /****************************************************/ /* Initialize the length to zero. We will update with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /****************************************************/ /* Set the sysUpTime object ID */ /****************************************************/ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.2.1.1.3.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /****************************************************/ /* Set the sysUpTime Timer Ticks */ /****************************************************/ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_TIME_TICS; trap_object_data.nx_snmp_object_data_msw = (LONG)elapsed_time; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set_1byte(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Clear the trap variable size. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Check for valid trap type. */ if ((trap_type > TRAP_ID_MAX) && (trap_type != NX_SNMP_TRAP_CUSTOM)) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Check that we have a trap list if a custom trap is requested. */ if ((object_list_ptr == NX_NULL) && (trap_type == NX_SNMP_TRAP_CUSTOM)) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Check if this is an enumerated trap type. */ if (trap_type <= TRAP_ID_MAX) { /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the snmpTrapOID object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.6.3.1.1.4.1.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Set a Object ID for the data. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_OBJECT_ID; trap_object_data.nx_snmp_object_data_msw = 0; _nx_snmp_object_copy(_nx_snmp_v3_trap_ids[trap_type], trap_object_data.nx_snmp_object_octet_string); /* Add trap object data to trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; } /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set_1byte(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if an object is specified. */ if (object_list_ptr) { /* Setup object pointers from the supplied object list. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } /* Loop to process all the objects in the list. */ while (trap_object_ptr) { /* Clear the trap variable length. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the object into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, trap_object_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, trap_object_data_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set_1byte(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if there are more objects to insert into the trap message. */ if (object_list_ptr) { /* Move to the next object in the list. */ object_list_ptr++; if (object_list_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Determine if there is another object. */ if (object_list_ptr -> nx_snmp_object_string_ptr) { /* Setup the object and object data pointers. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Next trap3 object data at 0x%x\n", trap_object_data_ptr); #endif /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } } } #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("\nSet trap3 sequence length at 0x%x to 0x%x\n Set global sequence length at 0x%x to 0x%x\n Set trap3 security length at 0x%x to 0x%x\n Set trap3 pdu length at 0x%x to 0x%x\n Set trap3 variable list length at 0x%x to 0x%x\n Set trap3 type length at 0x%x to 0x%x\n", trap_sequence_ptr, trap_sequence_length, trap_header_ptr, trap_header_length, trap_security_ptr, trap_security_length, trap_pdu_ptr, trap_pdu_length, trap_variable_list_ptr, trap_variable_list_length, trap_type_ptr, trap_type_length); #endif /* At this point, several trap fields need to be updated with actual lengths. */ _nx_snmp_utility_request_type_set_multibyte(trap_type_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, trap_type_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_variable_list_ptr, trap_variable_list_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_pdu_ptr, trap_pdu_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set_1byte(trap_security_ptr, trap_security_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set_1byte(trap_header_ptr, trap_header_length, trap_packet_ptr -> nx_packet_data_end); /* Setup the security OCTET string length. */ /* Backup to the OCTET string for the security size. */ trap_security_ptr = trap_security_ptr - 2; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Move trap3 security pointer by 2 0x%x (length %u)\n", trap_security_ptr, trap_security_length); #endif /* Account for the 2 byte Security Sequence field. */ trap_security_length = trap_security_length + 2; /* Store the security size. */ trap_security_ptr[1] = (UCHAR) (trap_security_length & 0xFF); /* Determine if privacy is required. If so, encrypt the PDU and setup the response to have an encryption header. */ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { /* Determine if any padding needs to be applied - account for the two bytes of sequence information on the PDU. */ trap_pdu_length = trap_pdu_length + 2; padding = ((trap_pdu_length+7)/8)*8 - trap_pdu_length; /* Add the padding the trap PDU length and the trap sequence length. */ trap_pdu_length = trap_pdu_length + padding; trap_sequence_length = trap_sequence_length + padding; /* Clear the end of the trap message... just to be nice! */ for (i = 0; i < padding; i++) { /* Clear byte at the end of the response. */ *trap_buffer_ptr++ = 0; } /* Setup the size of the encrypted PDU. */ trap_encryption_size_ptr[0] = (UCHAR) ((trap_pdu_length >> 8) & 0xFF); trap_encryption_size_ptr[1] = (UCHAR) (trap_pdu_length & 0xFF); /* Update the total trap sequence length again. */ _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); /* Increment the salt counter. */ agent_ptr -> nx_snmp_agent_v3_context_salt_counter++; /* Build the salt value for the decryption. */ key1[0] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 24) & 0xFF); key1[1] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 16) & 0xFF); key1[2] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 8) & 0xFF); key1[3] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_engine_boots & 0xFF); key1[4] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 24) & 0xFF); key1[5] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 16) & 0xFF); key1[6] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 8) & 0xFF); key1[7] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_salt_counter & 0xFF); /* Loop to store the salt in the privacy field. */ for (i = 0; i < 8; i++) { /* Store a byte of the salt. */ trap_privacy_ptr[i] = key1[i]; } /* Setup pointer to the actual PDU. */ temp_ptr = trap_encryption_size_ptr + 2; /* Make the Initialization Vector (IV). */ for (i = 0; i < 8; i++) { key2[i] = (agent_ptr -> nx_snmp_agent_v3_priv_trap_key)->nx_snmp_security_key[8+i] ^ key1[i]; } /* Setup the DES. */ _nx_des_key_set(&(agent_ptr -> nx_snmp_agent_v3_des_data), (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) -> nx_snmp_security_key); /* Setup the first input block - use the IV for the first block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[i] ^ key2[i]; } /* Encrypt the first 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[0]); /* Loop to encrypt the rest of the PDU. */ j = 8; do { /* Setup the next input block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[j+i] ^ temp_ptr[(j-8)+i]; } /* Encrypt the next 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[j]); /* Move the major index forward. */ j = j + 8; } while (j < trap_pdu_length); } /* Now the trap packet's pointers must be setup so it can be sent. */ trap_packet_ptr -> nx_packet_length = (ULONG)(trap_buffer_ptr - trap_packet_ptr -> nx_packet_prepend_ptr); trap_packet_ptr -> nx_packet_append_ptr = trap_buffer_ptr; /* Determine if authentication is required. */ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { /* Yes, authentication is required. */ /* Now determine which authentication is required. */ if ((agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key_type == NX_SNMP_MD5_KEY) { /* Copy the base MD5 key into key1. */ for (i = 0; i < NX_SNMP_MD5_DIGEST_SIZE; i++) { /* Copy a byte of the base MD5 key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_MD5_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Calculate prepend Key1. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), trap_packet_ptr -> nx_packet_prepend_ptr, trap_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1); /* Prepare to calculate the final MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Prepend Key2 to the result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_MD5_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2); } else if ((agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key_type == NX_SNMP_SHA_KEY) { /* Copy the base SHA key into key1. */ for (i = 0; i < NX_SNMP_SHA_DIGEST_SIZE; i++) { /* Copy a byte of the base SHA key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_SHA_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Calculate prepend Key1. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), trap_packet_ptr -> nx_packet_prepend_ptr, trap_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1); /* Prepare to calculate the final MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Prepend Key2 to the result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_SHA_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2); } else { /* Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* At this point, key2 contains the computed digest of the message. This needs to be place in the outgoing message. */ /* Loop to setup the outgoing digest. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) { /* Copy one byte of digest. */ trap_authentication_ptr[i] = key2[i]; } } /* Update various statistics. */ agent_ptr -> nx_snmp_agent_traps_sent++; agent_ptr -> nx_snmp_agent_packets_sent++; agent_ptr -> nx_snmp_agent_total_bytes_sent += trap_packet_ptr -> nx_packet_length; /* Send the trap packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), trap_packet_ptr, ip_address, NX_SNMP_MANAGER_TRAP_PORT); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return error. */ return(NX_SNMP_ERROR); } /* Return successful completion. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_agent_trapv3_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent v3 trap send */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* username Username */ /* oid Enterprise ID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_agent_trapv3_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_trapv3_oid_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *username, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (username == NX_NULL)) return(NX_PTR_ERROR); /* Check for invalid IP address. */ if (ip_address == 0) return(NX_IP_ADDRESS_ERROR); /* Call actual service. */ status = _nx_snmp_agent_trapv3_oid_send(agent_ptr, ip_address, username, oid, elapsed_time, object_list_ptr); /* Return status. */ return(status); #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(username); NX_PARAMETER_NOT_USED(oid); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_trapv3_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v3 trap message. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* username Username */ /* OID Enterprise ID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv3_oid_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_trapv3_oid_send(NX_SNMP_AGENT *agent_ptr, ULONG ip_address, UCHAR *username, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { #ifndef NX_DISABLE_IPV4 UINT status; NXD_ADDRESS ipduo_address; ipduo_address.nxd_ip_version = NX_IP_VERSION_V4; ipduo_address.nxd_ip_address.v4 = ip_address; status = _nxd_snmp_agent_trapv3_oid_send(agent_ptr, &ipduo_address, username, oid, elapsed_time, object_list_ptr); return status; #else NX_PARAMETER_NOT_USED(agent_ptr); NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(username); NX_PARAMETER_NOT_USED(oid); NX_PARAMETER_NOT_USED(elapsed_time); NX_PARAMETER_NOT_USED(object_list_ptr); return(NX_NOT_SUPPORTED); #endif /* NX_DISABLE_IPV4 */ } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxde_snmp_agent_trapv3_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent v2 trap send */ /* function call. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* community Community name */ /* OID OID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nxd_snmp_agent_trapv3_oid_send Actual agent trap send */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxde_snmp_agent_trapv3_oid_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ipduo_address, UCHAR *username, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; /* Check for invalid input pointers. */ if ((agent_ptr == NX_NULL) || (agent_ptr -> nx_snmp_agent_id != NX_SNMP_ID) || (username == NX_NULL) || (ipduo_address == NX_NULL)) { return(NX_PTR_ERROR); } /* Call actual service. */ status = _nxd_snmp_agent_trapv3_oid_send(agent_ptr, ipduo_address, username, oid, elapsed_time, object_list_ptr); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trapv3_oid_send PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function builds and sends a SNMP v3 trap message. */ /* */ /* Note: The string length of username and oid are limited by the */ /* packet payload and NX_SNMP_MAX_OCTET_STRING. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* ip_address Destination IP address */ /* username Username */ /* OID Enterprise ID to send */ /* elapsed_time Elapsed time from last boot */ /* of the device (sysUpTime) */ /* object_list_ptr Variable list of application */ /* objects to present with the */ /* trap */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_des_key_set Setup DES encryption */ /* _nx_des_encrypt Encrypt bytes */ /* _nx_md5_digest_calculate MD5 algorithm completion */ /* _nx_md5_initialize MD5 algorithm initialization */ /* _nx_md5_update MD5 algorithm computation */ /* nx_packet_allocate Allocate SNMP trap packet */ /* nx_packet_release Release SNMP packet */ /* nx_udp_socket_send Send SNMP trap via UDP */ /* _nx_snmp_object_copy Copy object */ /* _nx_snmp_utility_error_info_set Set error information */ /* _nx_snmp_utility_octet_set Set octet string */ /* _nx_snmp_utility_object_data_set Set the data value */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_sequence_set Set the ASN.1 sequence */ /* _nx_snmp_utility_request_id_set Set the Request ID */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_version_set Set the SNMP v3 */ /* _nx_sha1_digest_calculate SHA algorithm completion */ /* _nx_sha1_initialize SHA algorithm initialization */ /* _nx_sha1_update SHA algorithm computation */ /* tx_time_get Get time */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trapv3_oid_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ipduo_address, UCHAR *username, UCHAR *oid, ULONG elapsed_time, NX_SNMP_TRAP_OBJECT *object_list_ptr) { UINT status; UINT trap_length; UCHAR *trap_object_ptr; NX_SNMP_OBJECT_DATA trap_object_data; NX_SNMP_OBJECT_DATA *trap_object_data_ptr = NX_NULL; NX_PACKET *trap_packet_ptr; UCHAR *trap_buffer_ptr, *trap_sequence_ptr, *trap_header_ptr, *trap_security_ptr, *trap_pdu_ptr, *trap_type_ptr, *trap_variable_list_ptr, *trap_variable_ptr; UINT trap_sequence_length, trap_header_length, trap_security_length, trap_pdu_length, trap_type_length, trap_variable_list_length, trap_variable_length; UCHAR temp_string[NX_SNMP_DIGEST_SIZE]; UINT i; #ifndef NX_SNMP_NO_SECURITY UINT j, padding; UCHAR *temp_ptr; UCHAR *trap_encryption_size_ptr = NX_NULL; UCHAR *trap_authentication_ptr = NX_NULL, *trap_privacy_ptr = NX_NULL; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; #endif UINT packet_type = NX_UDP_PACKET; UCHAR message_security_options; UINT username_length; if (ipduo_address -> nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else { packet_type = NX_IPv6_UDP_PACKET; } /* Allocate the packet for the SNMP response. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &trap_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a trap packet was allocated. */ if (status != NX_SUCCESS) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return(NX_SNMP_ERROR); } /* Initialize the counters required for the length fields of the trap packet. */ trap_sequence_length = 0; trap_header_length = 0; trap_security_length = 0; trap_pdu_length = 0; trap_type_length = 0; trap_variable_list_length = 0; trap_variable_length = 0; /* Setup a pointer to the trap packet's buffer area. */ trap_buffer_ptr = trap_packet_ptr -> nx_packet_prepend_ptr; /* This is also the trap sequence pointer. Remember it since we are going to have to update it later with the actual length of the response. */ trap_sequence_ptr = trap_buffer_ptr; /* First, write the sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Now set the Version ID in the trap message. */ trap_length = _nx_snmp_utility_version_set(trap_buffer_ptr, NX_SNMP_VERSION_3, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Save the pointer to the global header. */ trap_header_ptr = trap_buffer_ptr; /* Write the sequence for the global header in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now setup the request ID. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /* Now setup the maximum message size. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, (NX_SNMP_PACKET_SIZE - NX_UDP_PACKET), trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /* Now setup the security options. */ message_security_options = 0; /* Determine what the trap message security options are. These are not the same as the general get/set request PDU options. */ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { message_security_options = NX_SNMP_SECURITY_AUTHORIZE; } if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { message_security_options |= NX_SNMP_SECURITY_PRIVACY; } trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, (UCHAR *)&message_security_options, 1, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /* Now setup the security type. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, NX_SNMP_USM_SECURITY_MODEL, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the header sequence length. */ trap_header_length = trap_header_length + trap_length; /* At this point, we have successfully built the security header. Now, we need to build the security parameters field. */ /* First setup the octet string field. */ trap_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; trap_buffer_ptr[1] = 0x0; /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + 2; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + 2; /* Remember the security header length pointer. */ trap_security_ptr = trap_buffer_ptr; /* Now set the sequence of the USM security parameters. */ trap_length = _nx_snmp_utility_sequence_set_1byte(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now setup the context engine. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Now setup the number of engine boots. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boots, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Now setup the relative time since the last engine boot. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Check username length. */ if (_nx_utility_string_length_check((CHAR *)username, &username_length, NX_SNMP_MAX_OCTET_STRING)) { return(NX_SIZE_ERROR); } /* Now setup the user name, as specified by the input parameter. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, username, username_length, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Now setup the authentication parameter - it is a 12 character field set to zeros initially. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) temp_string[i] = 0; /****************** ***************** **********************/ /* Now set AUTHENTICATION PARAMETER. */ /****************** ***************** **********************/ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { /* We have a valid authentication key, so initialize the string to zero. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string, NX_SNMP_DIGEST_SIZE, trap_packet_ptr -> nx_packet_data_end); trap_authentication_ptr = trap_buffer_ptr + 2; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap3 authentication header 0x%x\n", trap_authentication_ptr); #endif } else { /* No security enabled so set this as an empty parameter. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string,0, trap_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /****************** ***************** **********************/ /* Now set 8 char PRIVACY PARAMETER. */ /****************** ***************** **********************/ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { /* We will encrypt the message, so set to all zeros field initially. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string, 8, trap_packet_ptr -> nx_packet_data_end); trap_privacy_ptr = trap_buffer_ptr + 2; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Starting trap_privacy_ptr 0x%x\n", trap_privacy_ptr); #endif } else { /* Not encrypting, so set the privacy field as an empty parameter. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, temp_string,0, trap_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Adjust the security sequence length. */ trap_security_length = trap_security_length + trap_length; /* Determine if privacy is required. If so, decrypt the source PDU and setup the response to have an encryption header. */ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { #ifndef NX_SNMP_NO_SECURITY /* Now setup the trap buffer to encapsulate the encrypted PDU. Note that the actual encryption will be done after the complete trap has been formed. */ trap_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; trap_buffer_ptr[1] = 0x82; trap_buffer_ptr[2] = 0x00; trap_buffer_ptr[3] = 0x00; /* Save the trap encryption size pointer. This will be filled in below as we build the message. */ trap_encryption_size_ptr = trap_buffer_ptr + 2; /* Move the trap buffer forward. */ trap_buffer_ptr = trap_buffer_ptr + 4; /* Increase the length of the total trap message. */ trap_sequence_length = trap_sequence_length + 4; #else /* Encryption is not supported by this agent but is specified in the request or by the agent. Simply discard the message. */ /* Increment the privacy error counter. */ agent_ptr -> nx_snmp_agent_privacy_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); #endif } /* Save the trap pdu sequence pointer. */ trap_pdu_ptr = trap_buffer_ptr; /* First, write the PDU sequence in the trap packet. A zero is written for now. This will be updated later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Increment the number of trap sequence bytes. */ trap_sequence_length = trap_sequence_length + trap_length; /* Now store the PDU context engine in the trap packet. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (trap_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap pointer forward. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Increment the sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Now store the PDU context name in the trap packet. */ trap_length = _nx_snmp_utility_octet_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_name, agent_ptr -> nx_snmp_agent_v3_context_name_size, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (trap_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap pointer forward. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Save the pointer to the trap type. */ trap_type_ptr = trap_buffer_ptr; /* Increment the sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Setup the trap request type field. */ trap_length = _nx_snmp_utility_request_type_set_multibyte(trap_buffer_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Now set the request ID in the trap message. */ trap_length = _nx_snmp_utility_request_id_set(trap_buffer_ptr, agent_ptr -> nx_snmp_agent_traps_sent, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Set the trap error information. Assume everything is okay at this point. */ trap_length = _nx_snmp_utility_error_info_set(trap_buffer_ptr, 0, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the response's variable list field. */ trap_variable_list_ptr = trap_buffer_ptr; /* Setup the variable list. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the sysUpTime object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.2.1.1.3.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_TIME_TICS; trap_object_data.nx_snmp_object_data_msw = (LONG)elapsed_time; trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Clear the trap variable size. */ trap_variable_length = 0; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the snmpTrapOID object ID into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, (UCHAR *) "1.3.6.1.6.3.1.1.4.1.0", trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Set a Object ID for the data. */ trap_object_data.nx_snmp_object_data_type = NX_SNMP_ANS1_OBJECT_ID; trap_object_data.nx_snmp_object_data_msw = 0; /* Check oid length. */ if (_nx_utility_string_length_check((CHAR *)oid, NX_NULL, NX_SNMP_MAX_OCTET_STRING)) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } _nx_snmp_object_copy(oid, trap_object_data.nx_snmp_object_octet_string); trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, &trap_object_data, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if an object is specified. */ if (object_list_ptr) { /* Setup object pointers from the supplied object list. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } /* Loop to process all the objects in the list. */ while (trap_object_ptr) { /* Clear the trap variable length. */ trap_variable_length = 0; /* Remember the start of the variable. */ trap_variable_ptr = trap_buffer_ptr; /* Setup the variable trap sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ trap_length = _nx_snmp_utility_sequence_set(trap_buffer_ptr, 0, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Place the object into the trap buffer. */ trap_length = _nx_snmp_utility_object_id_set(trap_buffer_ptr, trap_object_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Insert the object's data into the trap buffer. */ trap_length = _nx_snmp_utility_object_data_set(trap_buffer_ptr, trap_object_data_ptr, trap_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (trap_length == 0) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Move the trap buffer pointer up. */ trap_buffer_ptr = trap_buffer_ptr + trap_length; /* Adjust the trap sequence length. */ trap_sequence_length = trap_sequence_length + trap_length; /* Increment the pdu length. */ trap_pdu_length = trap_pdu_length + trap_length; /* Adjust the trap request type length. */ trap_type_length = trap_type_length + trap_length; /* Adjust the trap variable list size. */ trap_variable_list_length = trap_variable_list_length + trap_length; /* Adjust the trap variable size. */ trap_variable_length = trap_variable_length + trap_length; /* Now update the trap variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(trap_variable_ptr, trap_variable_length, trap_packet_ptr -> nx_packet_data_end); /* Default the object pointer to NULL. */ trap_object_ptr = NX_NULL; /* Determine if there are more objects to insert into the trap message. */ if (object_list_ptr) { /* Move to the next object in the list. */ object_list_ptr++; if (object_list_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } /* Determine if there is another object. */ if (object_list_ptr -> nx_snmp_object_string_ptr) { /* Setup the object and object data pointers. */ trap_object_ptr = object_list_ptr -> nx_snmp_object_string_ptr; trap_object_data_ptr = object_list_ptr -> nx_snmp_object_data; /* Check for a valid operation. */ if(trap_object_ptr != NX_NULL && trap_object_data_ptr == NX_NULL) { /* Release the trap packet. */ nx_packet_release(trap_packet_ptr); /* Done, return to caller. */ return(NX_SNMP_ERROR); } } } } /* At this point, several trap fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_header_ptr, trap_header_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set_1byte(trap_security_ptr, trap_security_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_pdu_ptr, trap_pdu_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(trap_variable_list_ptr, trap_variable_list_length, trap_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(trap_type_ptr, NX_SNMP_ANS1_TRAP2_REQUEST, trap_type_length, trap_packet_ptr -> nx_packet_data_end); /* Setup the security OCTET string length. */ /* Backup to the OCTET string for the security size. */ trap_security_ptr = trap_security_ptr - 2; /* Account for the 2 byte Security Sequence field. */ trap_security_length = trap_security_length + 2; /* Store the security size. */ trap_security_ptr[1] = (UCHAR) (trap_security_length & 0xFF); /* Determine if privacy is required. If so, encrypt the PDU and setup the response to have an encryption header. */ if (agent_ptr -> nx_snmp_agent_v3_priv_trap_key) { #ifndef NX_SNMP_NO_SECURITY /* Determine if any padding needs to be applied - account for the four bytes of header information on the PDU. */ trap_pdu_length = trap_pdu_length + 4; padding = ((trap_pdu_length+7)/8)*8 - trap_pdu_length; /* Add the padding the trap PDU length and the trap sequence length. */ trap_pdu_length = trap_pdu_length + padding; trap_sequence_length = trap_sequence_length + padding; /* Clear the end of the trap message... just to be nice! */ for (i = 0; i < padding; i++) { /* Clear byte at the end of the response. */ *trap_buffer_ptr++ = 0; } /* Setup the size of the encrypted PDU. */ trap_encryption_size_ptr[0] = (UCHAR) ((trap_pdu_length >> 8) & 0xFF); trap_encryption_size_ptr[1] = (UCHAR) (trap_pdu_length & 0xFF); /* Update the total trap sequence length again. */ _nx_snmp_utility_sequence_set(trap_sequence_ptr, trap_sequence_length, trap_packet_ptr -> nx_packet_data_end); /* Increment the salt counter. */ agent_ptr -> nx_snmp_agent_v3_context_salt_counter++; /* Build the salt value for the decryption. */ key1[0] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 24) & 0xFF); key1[1] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 16) & 0xFF); key1[2] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 8) & 0xFF); key1[3] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_engine_boots & 0xFF); key1[4] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 24) & 0xFF); key1[5] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 16) & 0xFF); key1[6] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 8) & 0xFF); key1[7] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_salt_counter & 0xFF); /* Loop to store the salt in the privacy field. */ for (i = 0; i < 8; i++) { /* Store a byte of the salt. */ trap_privacy_ptr[i] = key1[i]; } /* Setup pointer to the actual PDU. */ temp_ptr = trap_encryption_size_ptr + 2; /* Make the Initialization Vector (IV). */ for (i = 0; i < 8; i++) { key2[i] = (agent_ptr -> nx_snmp_agent_v3_priv_trap_key)->nx_snmp_security_key[8+i] ^ key1[i]; } /* Setup the DES. */ _nx_des_key_set(&(agent_ptr -> nx_snmp_agent_v3_des_data), (agent_ptr -> nx_snmp_agent_v3_priv_trap_key)->nx_snmp_security_key); /* Setup the first input block - use the IV for the first block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[i] ^ key2[i]; } /* Encrypt the first 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[0]); /* Loop to encrypt the rest of the PDU. */ j = 8; do { /* Setup the next input block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[j+i] ^ temp_ptr[(j-8)+i]; } /* Encrypt the next 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[j]); /* Move the major index forward. */ j = j + 8; } while (j < trap_pdu_length); #else /* Increment the privacy error counter. */ agent_ptr -> nx_snmp_agent_privacy_errors++; /* Release the trap packet too. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return NX_SNMP_ERROR; #endif } /* Now the trap packet's pointers must be setup so it can be sent. */ trap_packet_ptr -> nx_packet_length = (ULONG)(trap_buffer_ptr - trap_packet_ptr -> nx_packet_prepend_ptr); trap_packet_ptr -> nx_packet_append_ptr = trap_buffer_ptr; #ifndef NX_SNMP_NO_SECURITY /* Determine if authentication is required. */ if (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) { /* Yes, authentication is required. */ /* Now determine which authentication is required. */ if ((agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key_type == NX_SNMP_MD5_KEY) { /* Copy the base MD5 key into key1. */ for (i = 0; i < NX_SNMP_MD5_DIGEST_SIZE; i++) { /* Copy a byte of the base MD5 key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_MD5_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Calculate prepend Key1. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), trap_packet_ptr -> nx_packet_prepend_ptr, trap_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1); /* Prepare to calculate the final MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Prepend Key2 to the result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_MD5_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2); } else if ((agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key_type == NX_SNMP_SHA_KEY) { /* Copy the base SHA key into key1. */ for (i = 0; i < NX_SNMP_SHA_DIGEST_SIZE; i++) { /* Copy a byte of the base SHA key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_auth_trap_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_SHA_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Calculate prepend Key1. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), trap_packet_ptr -> nx_packet_prepend_ptr, trap_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1); /* Prepare to calculate the final MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Prepend Key2 to the result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_SHA_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2); } else { /* Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return to caller. */ return(NX_SNMP_ERROR); } /* At this point, key2 contains the computed digest of the message. This needs to be place in the outgoing message. */ /* Loop to setup the outgoing digest. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) { /* Copy one byte of digest. */ trap_authentication_ptr[i] = key2[i]; } } #endif /* Update various statistics. */ agent_ptr -> nx_snmp_agent_traps_sent++; agent_ptr -> nx_snmp_agent_packets_sent++; agent_ptr -> nx_snmp_agent_total_bytes_sent += trap_packet_ptr -> nx_packet_length; /* Send the trap packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), trap_packet_ptr, ipduo_address, NX_SNMP_MANAGER_TRAP_PORT); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(trap_packet_ptr); /* Return error. */ return(NX_SNMP_ERROR); } /* Return successful completion. */ return(NX_SUCCESS); } #endif /* NX_SNMP_DISABLE_V3 */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_compare PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object compare */ /* function call. */ /* */ /* INPUT */ /* */ /* requested_object Pointer to requested object */ /* actual_object Pointer to actual object */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_compare Actual agent object compare */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_compare(UCHAR *requested_object, UCHAR *actual_object) { UINT status; /* Check for invalid input pointers. */ if ((requested_object == NX_NULL) || (actual_object == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_compare(requested_object, actual_object); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_compare PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function compares two objects. */ /* */ /* Note: new API nx_snmp_object_compare_extended is encouraged to use. */ /* */ /* INPUT */ /* */ /* requested_object Pointer to requested object */ /* actual_object Pointer to actual object */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_compare_extended Call actual compare service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_compare(UCHAR *requested_object, UCHAR *actual_object) { UINT status; UINT requested_object_length; UINT actual_object_length; /* Calculate the object length. */ if ((_nx_utility_string_length_check((CHAR *)requested_object, &requested_object_length, NX_MAX_STRING_LENGTH)) || (_nx_utility_string_length_check((CHAR *)actual_object, &actual_object_length, NX_MAX_STRING_LENGTH))) { return(NX_SIZE_ERROR); } /* Call actual service. */ status = _nx_snmp_object_compare_extended(requested_object, requested_object_length, actual_object, actual_object_length); /* Return status to the caller. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_compare_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object compare */ /* function call. */ /* */ /* INPUT */ /* */ /* requested_object Pointer to requested object */ /* requested_object_length Length of object requested */ /* actual_object Pointer to actual object */ /* actual_object_length Length of object requested */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_compare_extended Actual agent object compare */ /* extended function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_compare_extended(UCHAR *requested_object, UINT requested_object_length, UCHAR *actual_object, UINT actual_object_length) { /* Check for invalid input pointers. */ if ((requested_object == NX_NULL) || (actual_object == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ return(_nx_snmp_object_compare_extended(requested_object, requested_object_length, actual_object, actual_object_length)); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_compare_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function compares two objects. */ /* */ /* Note: The strings of requested object and actual object must be */ /* NULL-terminated and length of each string matches the length */ /* */ /* INPUT */ /* */ /* requested_object Pointer to requested object */ /* requested_object_length Length of object requested */ /* actual_object Pointer to actual object */ /* actual_object_length Length of object requested */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_compare_extended(UCHAR *requested_object, UINT requested_object_length, UCHAR *actual_object, UINT actual_object_length) { UINT i, j; UINT request_value; UINT actual_value; UINT temp_requested_object_length; UINT temp_actual_object_lenght; /* Check object string and get the actual string length. */ if ((_nx_utility_string_length_check((CHAR *)requested_object, &temp_requested_object_length, requested_object_length)) || (_nx_utility_string_length_check((CHAR *)actual_object, &temp_actual_object_lenght, actual_object_length))) return(NX_SNMP_ERROR); /* Check the actual string length. */ if ((requested_object_length != temp_requested_object_length) || (actual_object_length != temp_actual_object_lenght)) return(NX_SNMP_ERROR); /* Loop to compare the first and second object name. Stop at the first NULL. */ i = 0; request_value = 0; actual_value = 0; while ((requested_object[i]) && (actual_object[i])) { /* Update the requested object value. */ if (requested_object[i] == '.') request_value = 0; else request_value = (request_value * 10) + (UINT) (requested_object[i] - '0'); /* Update the actual object value. */ if (actual_object[i] == '.') actual_value = 0; else actual_value = (actual_value * 10) + (UINT) (actual_object[i] - '0'); /* Determine if the names are different. */ if (requested_object[i] != actual_object[i]) { /* Calculate the remainder - if any - of the requested value. */ j = i; while ((requested_object[j]) && (requested_object[j] != '.')) { /* Update the request value. */ request_value = (request_value * 10) + (UINT) (requested_object[j] - '0'); /* Move to next entry. */ j++; } /* Calculate the remainder - if any - of the actual value. */ j = i; while ((actual_object[j]) && (actual_object[j] != '.')) { /* Update the actual value. */ actual_value = (actual_value * 10) + (UINT) (actual_object[j] - '0'); /* Move to next entry. */ j++; } /* Determine if the requested object name is less than the actual object name. */ if (request_value < actual_value) return(NX_SNMP_NEXT_ENTRY); else break; } /* Move to next character. */ i++; } /* Now compare the names to check for a successful match. */ if ((requested_object[i] == NX_NULL) && (actual_object[i] == NX_NULL)) return(NX_SUCCESS); /* If the actual object is NULL, that means that everything else matched exactly. */ if (actual_object[i] == NX_NULL) return(NX_SUCCESS); /* Determine if the requested object name is NULL. This case is considered the next entry. */ if (requested_object[i] == NX_NULL) return(NX_SNMP_NEXT_ENTRY); /* Return an error condition. */ return(NX_SNMP_ERROR); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_copy PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object copy */ /* function call. */ /* */ /* INPUT */ /* */ /* source_object_name Pointer to source object */ /* destination_object_name Pointer to destination object */ /* */ /* OUTPUT */ /* */ /* size If error, returns zero, else */ /* returns number of bytes */ /* copied */ /* CALLS */ /* */ /* _nx_snmp_object_copy Actual agent object copy */ /* function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_copy(UCHAR *source_object_name, UCHAR *destination_object_name) { UINT status; /* Check for invalid input pointers. */ if ((source_object_name == NX_NULL) || (destination_object_name == NX_NULL)) return(0); /* Call actual service. */ status = _nx_snmp_object_copy(source_object_name, destination_object_name); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_copy PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function copies the source object to the destination object. */ /* */ /* Note: new API nx_snmp_object_copy_extended is encouraged to use. */ /* */ /* INPUT */ /* */ /* source_object_name Pointer to source object */ /* destination_object_name Pointer to destination object */ /* */ /* OUTPUT */ /* */ /* size If error, returns zero, else */ /* returns number of bytes */ /* copied */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_copy(UCHAR *source_object_name, UCHAR *destination_object_name) { UINT i; /* Calculate the object length. */ if (_nx_utility_string_length_check((CHAR *)source_object_name, NX_NULL, NX_MAX_STRING_LENGTH)) return(0); /* Loop to copy the name. */ i = 0; while (source_object_name[i]) { /* Copy a byte of the name. */ destination_object_name[i] = source_object_name[i]; /* Move to next byte. */ i++; } /* Ensure name is null terminated. */ destination_object_name[i] = NX_NULL; /* Return the size of the name. */ return(i); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_copy_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object copy */ /* function call. */ /* */ /* INPUT */ /* */ /* source_object_name Pointer to source object */ /* source_object_name_length Length of source object */ /* destination_object_name_buffer Pointer to destination object */ /* destination_object_name_buffer_size Size of destination object */ /* */ /* OUTPUT */ /* */ /* size If error, returns zero, else */ /* returns number of bytes */ /* copied */ /* CALLS */ /* */ /* _nx_snmp_object_copy_extended Actual agent object copy */ /* extended function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_copy_extended(UCHAR *source_object_name, UINT source_object_name_length, UCHAR *destination_object_name_buffer, UINT destination_object_name_buffer_size) { /* Check for invalid input pointers. */ if ((source_object_name == NX_NULL) || (destination_object_name_buffer == NX_NULL)) return(0); /* Call actual service. */ return(_nx_snmp_object_copy_extended(source_object_name, source_object_name_length, destination_object_name_buffer, destination_object_name_buffer_size)); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_copy_extended PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function copies the source object to the destination object. */ /* */ /* Note: the object name must be NULL-terminated, the size of */ /* destination object buffer must be larger than source object length. */ /* */ /* INPUT */ /* */ /* source_object_name Pointer to source object */ /* source_object_name_length Length of source object */ /* destination_object_name_buffer Pointer to destination object */ /* destination_object_name_buffer_size Size of destination object */ /* */ /* OUTPUT */ /* */ /* size If error, returns zero, else */ /* returns number of bytes */ /* copied */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_copy_extended(UCHAR *source_object_name, UINT source_object_name_length, UCHAR *destination_object_name_buffer, UINT destination_object_name_buffer_size) { UINT temp_object_name_length; /* Check the string length, the destination oject name buffer size must be larger than source object name length. */ if ((source_object_name_length == 0) || (destination_object_name_buffer_size <= source_object_name_length)) return(0); /* Check name string. */ if (_nx_utility_string_length_check((CHAR *)source_object_name, &temp_object_name_length, source_object_name_length)) return(0); /* Check the actual string length. */ if (source_object_name_length != temp_object_name_length) return(0); /* Copy the name and null-terminator. */ memcpy(destination_object_name_buffer, source_object_name, source_object_name_length + 1); /* Use case of memcpy is verified. */ /* Return the size of the name. */ return(source_object_name_length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_counter_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object counter */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to counter source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_counter_get Actual agent object counter */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_counter_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_counter_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_counter_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object counter from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to counter source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_counter_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_COUNTER; /* Setup pointer to the value. */ value_ptr = (ULONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG)(*value_ptr); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_counter_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object counter */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to counter destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_counter_set Actual agent object counter */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_counter_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_counter_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_counter_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object counter from the object data */ /* structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to counter destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_counter_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_COUNTER) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (ULONG *) destination_ptr; /* Copy the value into the object data structure. */ *value_ptr = (ULONG)(object_data -> nx_snmp_object_data_msw); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_counter64_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent 64-bit object */ /* counter get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to counter source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_counter64_get Actual agent object counter */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_counter64_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_counter64_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_counter64_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the 64-bit object counter from the */ /* specified source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to counter source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_counter64_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_COUNTER64; /* Setup pointer to the value. */ value_ptr = (ULONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG)value_ptr[0]; object_data -> nx_snmp_object_data_lsw = (LONG)value_ptr[1]; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_counter64_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent 64-bit object */ /* counter set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to counter destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_counter64_set Actual agent object counter */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_counter64_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_counter64_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_counter64_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the 64-bit object counter from the object */ /* data structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to counter destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_counter64_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; LONG temp = 0; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_COUNTER64) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (ULONG *) destination_ptr; if (object_data -> nx_snmp_object_data_lsw == 0) { temp = object_data -> nx_snmp_object_data_msw; value_ptr[0] = 0; } if ((object_data -> nx_snmp_object_data_lsw & (LONG)0xFFFFFF00) == 0) { temp = object_data -> nx_snmp_object_data_msw << 8; value_ptr[0] = (ULONG)(((ULONG)object_data -> nx_snmp_object_data_msw >> 24) & (0x000000FF)); } else if ((object_data -> nx_snmp_object_data_lsw & (LONG)0xFFFF0000) == 0) { temp = object_data -> nx_snmp_object_data_msw << 16; value_ptr[0] = (ULONG)(((ULONG)object_data -> nx_snmp_object_data_msw >> 16) & (0x0000FFFF)); } else if ((object_data -> nx_snmp_object_data_lsw & (LONG)0xFF000000) == 0) { temp = object_data -> nx_snmp_object_data_msw << 24; value_ptr[0] = (ULONG)(((ULONG)object_data -> nx_snmp_object_data_msw >> 8) & (0x00FFFFFF)); } else { value_ptr[0] = (ULONG)(object_data -> nx_snmp_object_data_msw); } value_ptr[1] = (ULONG)(object_data -> nx_snmp_object_data_lsw + temp); /* Value_ptr udpates the MIB data but we also need to display the data correctly in object. */ /* Update the object data to make the display correct as well. */ object_data -> nx_snmp_object_data_lsw = (LONG)value_ptr[1]; object_data -> nx_snmp_object_data_msw = (LONG)value_ptr[0]; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_end_of_mib PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent end-of-mib object */ /* set function call. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_end_of_mib Actual agent object end-of-mib*/ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_end_of_mib(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointer. */ if (object_data == NX_NULL) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_end_of_mib(not_used_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_end_of_mib PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places an end-of-mib value in the object data */ /* structure. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_end_of_mib(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_END_OF_MIB_VIEW; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG) not_used_ptr; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_gauge_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object gauge */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to gauge source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_gauge_get Actual agent object gauge */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_gauge_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_gauge_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_gauge_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object gauge from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to gauge source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_gauge_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_GAUGE; /* Setup pointer to the value. */ value_ptr = (ULONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG)(*value_ptr); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_gauge_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object gauge */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to gauge destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_gauge_set Actual agent object gauge */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_gauge_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_gauge_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_gauge_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object gauge from the object data */ /* structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to gauge destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_gauge_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_GAUGE) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (ULONG *) destination_ptr; /* Copy the value into the object data structure. */ *value_ptr = (ULONG)(object_data -> nx_snmp_object_data_msw); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_id_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object ID */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to ID source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_id_get Actual agent object ID */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_id_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_id_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_id_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object ID from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to object ID source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_id_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT length; UCHAR c; CHAR *copy_source = (CHAR*)source_ptr; c = *((UCHAR *)source_ptr); /* Check if this is an empty string. */ if ((c == 0x0) || (c == '0')) { copy_source = "0.0.0"; } /* Check string length. */ if (_nx_utility_string_length_check((CHAR *)copy_source, &length, NX_SNMP_MAX_OCTET_STRING)) { /* Incoming object data is too big to fit in. */ return(NX_SNMP_ERROR); } object_data -> nx_snmp_object_data_type = NX_SNMP_OBJECT_ID; memcpy(&object_data -> nx_snmp_object_octet_string[0], copy_source, length); /* Use case of memcpy is verified. */ /* NULL-terminate the string. */ object_data -> nx_snmp_object_octet_string[length] = 0x0; /* Calculate the length. */ object_data -> nx_snmp_object_octet_string_size = length; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_id_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object ID */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to ID destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_id_set Actual agent object ID */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_id_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_id_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_id_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object ID from the object data */ /* structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to ID destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_id_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_OBJECT_ID) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Copy the object id into the destination string. */ _nx_snmp_object_copy(object_data -> nx_snmp_object_octet_string, (UCHAR *) destination_ptr); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_integer_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object integer */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to integer source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_integer_get Actual agent integer */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_integer_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_integer_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_integer_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object integer from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to integer source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_integer_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { LONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_INTEGER; /* Setup pointer to the value. */ value_ptr = (LONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = *value_ptr; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_integer_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object integer */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to integer destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_integer_set Actual agent object integer */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_integer_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_integer_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_integer_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object integer from the object data */ /* structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to integer destination*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_integer_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { LONG *value_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_INTEGER) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (LONG *) destination_ptr; /* Copy the value into the object data structure. */ *value_ptr = object_data -> nx_snmp_object_data_msw; /* Return success. */ return(NX_SUCCESS); } #ifdef FEATURE_NX_IPV6 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_ipv6_address_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the set the IPv6 address */ /* service. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to IPv6 address */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_ipv6_address_set Actual set address service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_ipv6_address_set(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Determine if the correct type is specified. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) { /* Return an invalid pointer input. */ return(NX_PTR_ERROR); } status = _nx_snmp_object_ipv6_address_set(source_ptr, object_data); return status; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ipv6_address_set PORTABLE C */ /* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object IPv6 address from the object data*/ /* structure and places it in the destination. Note that 1) the data */ /* type is really an octet string of unspecified size and format, and */ /* 2) the caller must set the nx_snmp_object_string_size before calling*/ /* this function since it supplies the length of the octet data. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to IPv6 address */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 03-02-2021 Yuxin Zhou Modified comment(s), */ /* optimized boundary check, */ /* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ipv6_address_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT i; UCHAR *string_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Determine if the string is too big. */ if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) { return NX_SNMP_ERROR_TOOBIG; } /* Setup pointer to the value. */ string_ptr = destination_ptr; /* Copy the object data structure into the destination pointer. */ /* Copy this string into the destination. */ for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_ipv6_address_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function performs error checking for the IPv6 address get */ /* service. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to IPv6 address */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_ipv6_address_get Actual get IPv6 service */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_ipv6_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_ipv6_address_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ipv6_address_get PORTABLE C */ /* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object IPv6 address from the object data*/ /* structure and places it in the destination. Note that the caller */ /* must set the length of the octet string (object -> */ /* (nx_snmp_octet_string_size) before calling this service. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to IPv6 address */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 03-02-2021 Yuxin Zhou Modified comment(s), */ /* optimized boundary check, */ /* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ipv6_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT i; UCHAR *source_string; /* Determine if the string is too big. */ if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) { return NX_SNMP_ERROR_TOOBIG; } /* Setup pointer to source string. */ source_string = (UCHAR *) source_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_IPV6_ADDRESS; /* Copy this string into the destination. */ for (i = 0; i < object_data->nx_snmp_object_octet_string_size; i++) { /* Copy character. */ object_data -> nx_snmp_object_octet_string[i] = source_string[i]; } /* Return success. */ return(NX_SUCCESS); } #endif /* FEATURE_NX_IPV6 */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_ip_address_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object IP address */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to IP address source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_ip_address_get Actual agent IP address */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_ip_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_ip_address_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ip_address_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object IP address from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to IP address source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ip_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_IP_ADDRESS; /* Setup pointer to the value. */ value_ptr = (ULONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG)(*value_ptr); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_ip_address_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object IP address */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to IP address */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_ip_address_set Actual agent object IP address*/ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_ip_address_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_ip_address_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ip_address_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object IP address from the object data */ /* structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to IP address */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ip_address_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_ANS1_IP_ADDRESS) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (ULONG *) destination_ptr; /* Copy the value into the object data structure. */ *value_ptr = (ULONG)(object_data -> nx_snmp_object_data_msw); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_no_instance PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object no-instance*/ /* set function call. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used pointer */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_no_instance Actual agent object */ /* no-instance set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_no_instance(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if (object_data == NX_NULL) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_no_instance(not_used_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_no_instance PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places a no-instance value in the object data */ /* structure. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_no_instance(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_NO_SUCH_INSTANCE; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG) not_used_ptr; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_not_found PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent object not-found */ /* set function call. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used pointer */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_not_found Actual agent object */ /* not-found set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_not_found(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if (object_data == NX_NULL) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_not_found(not_used_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_not_found PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places an not-found value in the object data */ /* structure. */ /* */ /* INPUT */ /* */ /* not_used_ptr Not used */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_not_found(VOID *not_used_ptr, NX_SNMP_OBJECT_DATA *object_data) { /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_NO_SUCH_OBJECT; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG) not_used_ptr; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_octet_string_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent octet string */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to octet string source*/ /* object_data Pointer to object data struct */ /* length Length of octet string */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_octet_string_get Actual agent octet string */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_octet_string_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data, UINT length) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_octet_string_get(source_ptr, object_data, length) ; /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_octet_string_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object octet string from the specified */ /* source location. Note that while this does have a length field */ /* the caller must set the nx_snmp_object_string_size before calling */ /* this function since it supplies the length. */ /* */ /* The length field is deprecated. It is only included for legacy code.*/ /* */ /* INPUT */ /* */ /* source_ptr Pointer to octet string source*/ /* object_data Pointer to object data struct */ /* length Length of octet string */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_octet_string_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data, UINT length) { UINT i; UCHAR *source_string; NX_PARAMETER_NOT_USED(length); /* Setup pointer to source string. */ source_string = (UCHAR *) source_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_OCTET_STRING; if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) { return NX_SNMP_ERROR_TOOBIG; } /* Copy this string into the destination. */ for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { /* Copy character. */ object_data -> nx_snmp_object_octet_string[i] = source_string[i]; } /* The length input is deprecated. The caller sets the length from the MIB table entry to the object_data instance before calling this function. */ /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_octet_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent octet string */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to octet string */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_octet_string_set Actual agent octet string */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_octet_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_octet_string_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_octet_string_set PORTABLE C */ /* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object octet string from the object */ /* data structure and places it in the destination. Note that the */ /* length of the octet string must be set in the object string size. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to octet string */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 03-02-2021 Yuxin Zhou Modified comment(s), */ /* optimized boundary check, */ /* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_octet_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT i; UCHAR *string_ptr; /* Check for the proper type. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_OCTET_STRING) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) { return NX_SNMP_ERROR_TOOBIG; } /* Setup pointer to the destination string. */ string_ptr = (UCHAR *) destination_ptr; /* Copy this string into the destination. */ for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_string_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent string */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to string source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_string_get Actual agent string */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_string_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_string_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_string_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object ASCII string from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to ASCII string source*/ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_string_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT i; UCHAR *source_string; /* Setup pointer to source string. */ source_string = (UCHAR *) source_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_OCTET_STRING; /* Copy this string into the destination. */ i = 0; while (source_string[i]) { /* Copy character. */ object_data -> nx_snmp_object_octet_string[i] = source_string[i]; /* Move to next character. */ i++; /* Check for size of source string. */ if (i >= NX_SNMP_MAX_OCTET_STRING) { /* Error, source string is too large. */ object_data -> nx_snmp_object_octet_string[0] = NX_NULL; object_data -> nx_snmp_object_octet_string_size = 0; return(NX_SNMP_ERROR); } } /* Store the length of the string in the object data area. */ object_data -> nx_snmp_object_octet_string_size = i; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_string_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent string */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to string */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_string_set Actual agent string */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_string_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_string_set PORTABLE C */ /* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object ASCII string from the object */ /* data structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to ASCII string */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 03-02-2021 Yuxin Zhou Modified comment(s), */ /* optimized boundary check, */ /* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT i; UCHAR *string_ptr; /* Check for the proper type. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_OCTET_STRING) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Determine if the string is too big. */ if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) { return NX_SNMP_ERROR_TOOBIG; } /* Setup pointer to the destination string. */ string_ptr = (UCHAR *) destination_ptr; /* Copy this string into the destination. */ for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } /* Null terminate the destination. */ string_ptr[i] = NX_NULL; /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_timetics_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent timetics */ /* get function call. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to timetics source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_timetics_get Actual agent timetics */ /* get function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_timetics_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((source_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_timetics_get(source_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_timetics_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object timetics from the specified */ /* source location. */ /* */ /* INPUT */ /* */ /* source_ptr Pointer to timetics source */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_timetics_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Setup the object data structure. */ object_data -> nx_snmp_object_data_type = NX_SNMP_TIME_TICS; /* Setup pointer to the value. */ value_ptr = (ULONG *) source_ptr; /* Copy the value into the object data structure. */ object_data -> nx_snmp_object_data_msw = (LONG)(*value_ptr); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxe_snmp_object_timetics_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks for errors in the SNMP agent timetics */ /* set function call. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to timetics */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_snmp_object_timetics_set Actual agent timetics */ /* set function */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nxe_snmp_object_timetics_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { UINT status; /* Check for invalid input pointers. */ if ((destination_ptr == NX_NULL) || (object_data == NX_NULL)) return(NX_PTR_ERROR); /* Call actual service. */ status = _nx_snmp_object_timetics_set(destination_ptr, object_data); /* Return status. */ return(status); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_timetics_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object timetics from the object */ /* data structure and places it in the destination. */ /* */ /* INPUT */ /* */ /* destination_ptr Pointer to timetics */ /* destination */ /* object_data Pointer to object data struct */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_timetics_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) { ULONG *value_ptr; /* Determine if the correct type is specified. */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_TIME_TICS) { /* Return an invalid type message. */ return(NX_SNMP_ERROR_WRONGTYPE); } /* Setup pointer to the value. */ value_ptr = (ULONG *) destination_ptr; /* Copy the value into the object data structure. */ *value_ptr = (ULONG)(object_data -> nx_snmp_object_data_msw); /* Return success. */ return(NX_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_community_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the community string from the supplied */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* community_string Pointer to place community */ /* string */ /* buffer_length Size of input buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process SNMP v1, v2 request processing*/ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_community_get(UCHAR *buffer_ptr, UCHAR *community_string, INT buffer_length) { UINT i; UINT length; UINT total; /* Buffer size must be at least 2 bytes. */ if (buffer_length < 2) { return(0); } /* Set community string to NULL. */ *community_string = NX_NULL; /* First see if the ANS1 string type is present. */ if (buffer_ptr[0] != NX_SNMP_ANS1_OCTET_STRING) { /* Return a zero length. */ return(0); } if (buffer_ptr[1] & NX_SNMP_ANS1_MULTI_BYTES) { /* Get the type of length of the string */ UINT temp = (UINT)(buffer_ptr[1] & 0x7F); if (temp == 2) { /* Check the buffer length. */ if (buffer_length < 4) { return(0); } /* Length is in the next two bytes. Example: 0x04 0x82 0x98 0x01 */ total = (((UINT) buffer_ptr[2]) << 8) | ((UINT) buffer_ptr[3]); /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 4; /* Initialize the length. */ length = 4; } else if (temp == 1) { /* Check the buffer length. */ if (buffer_length < 3) { return(0); } /* Length is in the next byte. Example: 0x04 0x81 0x98 */ total = (UINT)(buffer_ptr[2]) ; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 3; /* Initialize the length. */ length = 3; } else { /* String is either null or too big, return a zero length to indicate an error. */ return(0); } } else { /* Otherwise, assume we have one byte. Example: 0x04 0x98 */ /* Pickup the total length of the community character string. */ total = (UINT) buffer_ptr[1]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 2; /* Initialize the length. */ length = 2; } if ((INT)(length + total) > buffer_length) { /* Buffer is too small. */ return(0); } /* Determine if the length is within the maximum. */ if (total > (NX_SNMP_MAX_USER_NAME-1)) { /* String is too big, return a zero length to indicate an error. */ return(0); } /* Loop to pickup the remaining characters in the community string. */ for (i = 0; i < total; i++) { /* Move character from buffer into community string. */ *community_string++ = *buffer_ptr++; /* Adjust the length. */ length++; } /* NULL-terminate the community string. */ *community_string = NX_NULL; /* Return the length of the ANS1 string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_community_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the community string into the supplied */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* community_string Pointer to source of the */ /* community string */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send Send SNMP v1 trap */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_community_set(UCHAR *buffer_ptr, UCHAR *community_string, UCHAR *buffer_end) { UINT i; UINT header_size; UINT length; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* First, set the OCTET byte. */ *buffer_ptr++ = NX_SNMP_ANS1_OCTET_STRING; /* Calculate the length byte. */ if (_nx_utility_string_length_check((CHAR *)community_string, &length, NX_SNMP_MAX_USER_NAME)) { /* Error, community length is too large. */ return(0); } /* Check for a length greater than 128. */ if (length >= 128) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < (3 + length)) return(0); /* Indicate there are two length bytes. */ *buffer_ptr++ = (UCHAR) 0x82; /* Set the first length byte. */ *buffer_ptr++ = (UCHAR) (length >> 8); /* Set the second length byte. */ *buffer_ptr++ = (UCHAR) (length & 0xFF); /* Set the header size. */ header_size = 4; } else { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < (1 + length)) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) length; /* The header is 2 bytes. */ header_size = 2; } /* Loop to store rest of the community string. */ for (i = 0; i < length; i++) { /* Store the SNMP community string. */ *buffer_ptr++ = (UCHAR) community_string[i]; } /* Return the length of the community string. */ return(length+header_size); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_error_info_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the error information from the supplied */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* error_code Pointer to place error code */ /* error_index Pointer to place error index */ /* buffer_length Size of input buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_error_info_get(UCHAR *buffer_ptr, UINT *error_code, UINT *error_index, INT buffer_length) { /* Check for invalid input. */ if (buffer_length < 6) { /* Invalid input. */ *error_code = 0; *error_index = 0; /* Return a zero length. */ return(0); } /* Determine if the error code and error index is correct. */ if ((buffer_ptr[0] == NX_SNMP_ANS1_INTEGER) && (buffer_ptr[1] == 1) && (buffer_ptr[3] == NX_SNMP_ANS1_INTEGER) && (buffer_ptr[4] == 1)) { /* Yes, the SNMP version string is correct. */ /* Return the error code and error index. */ *error_code = (UINT) buffer_ptr[2]; *error_index = (UINT) buffer_ptr[5]; /* Return the length of the error code/index string. */ return(6); } else { /* No, the SNMP error code/index is invalid. */ /* Clear both. */ *error_code = 0; *error_index = 0; /* Return a zero length. */ return(0); } } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_error_info_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the error information into the supplied */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* error_code Error code */ /* error_index Error index */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_error_response Send error response to Manager*/ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT error_index, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 6) return(0); /* First, set the INTEGER byte. */ *buffer_ptr++ = NX_SNMP_ANS1_INTEGER; /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 1; /* Store the error code. */ *buffer_ptr++ = (UCHAR) (error_code & 0xFF); /* Set the INTEGER byte. */ *buffer_ptr++ = NX_SNMP_ANS1_INTEGER; /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 1; /* Store the error index. */ *buffer_ptr++ = (UCHAR) (error_index & 0xFF); /* Return the length of the error info. */ return(6); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_id_get PORTABLE C */ /* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object ID from the supplied buffer */ /* and converts the object ID to an ASCII format. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* object_string Pointer to place object string*/ /* buffer_length Size of input buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* _nx_utility_uint_to_string Convert number to ASCII */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_utility_object_data_get Get object data */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 08-02-2021 Yuxin Zhou Modified comment(s), */ /* improved the logic of */ /* converting number to string,*/ /* resulting in version 6.1.8 */ /* 01-31-2022 Yuxin Zhou Modified comment(s), */ /* initialized the sequence */ /* byte value, */ /* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_id_get(UCHAR *buffer_ptr, UCHAR *object_string, INT buffer_length) { UINT i; UINT length; ULONG value; ULONG temp; ULONG multiply; UINT total; UINT size; UCHAR byte; UCHAR saved_byte; UCHAR *saved_ptr; UINT string_length; /* Buffer size must be at least 4 bytes. */ if (buffer_length < 4) { return 0; } /* Set object string to NULL. */ *object_string = NX_NULL; /* Initialize the string length to 0. */ string_length = 0; /* First see if the ANS1 object type is present. */ if (buffer_ptr[0] != NX_SNMP_ANS1_OBJECT_ID) { /* Return a zero length. */ return(0); } if (buffer_ptr[1] & NX_SNMP_ANS1_MULTI_BYTES) { temp = buffer_ptr[1] & 0x7F; /* Determine if a two byte length is present. */ if (temp == 2) { /* Check the buffer length. */ if (buffer_length < 5) { return(0); } /* Pickup the total length of the object string. */ total = (((UINT) buffer_ptr[2]) << 8) | ((UINT) buffer_ptr[3]); /* Pickup the first byte. */ byte = buffer_ptr[4]; /* Save the pointer to the first byte. */ saved_ptr = &buffer_ptr[4]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 4; /* Initialize the length. */ length = 4; } else if (temp == 1) { /* Pickup the total length of the object string. */ total = buffer_ptr[2]; /* Pickup the first byte. */ byte = buffer_ptr[3]; /* Save the pointer to the first byte. */ saved_ptr = &buffer_ptr[3]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 3; /* Initialize the length. */ length = 3; } else { /* This is out of range or null. Invalid SNMP sequence. */ return(0); } } else { /* Otherwise, assume one byte. */ /* Pickup the total length of the object string. */ total = (UINT) buffer_ptr[1]; /* Check for invalid data size */ if ((INT)total > (buffer_length - 1)) { /* Indicate an invalid request is received. */ return 0; } /* Pickup the first byte. */ byte = buffer_ptr[2]; /* Save the index. */ saved_ptr = &buffer_ptr[2]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 2; /* Initialize the length. */ length = 2; } /* Save the original byte. */ saved_byte = byte; /* Calculate the first two characters of object string. */ if (byte >= 80) { /* This form starts with 2 as the first identifier. */ *object_string++ = '2'; /* Increment the string length. */ string_length++; /* Adjust the byte. */ byte = (UCHAR)(byte - 80); } else if (byte >= 40) { /* This form starts with 1 as the first identifier. */ *object_string++ = '1'; /* Increment the string length. */ string_length++; /* Adjust the byte. */ byte = (UCHAR)(byte - 40); } else { /* This form starts with 0 as the first identifier. */ *object_string++ = '0'; /* Increment the string length. */ string_length++; } /* Always place a '.'. */ *object_string++ = '.'; /* Increment the string length. */ string_length++; /* Determine if the second identifier is legal. */ if (byte & NX_SNMP_ANS1_MULTI_BYTES) { /* Second identifier too large, return a zero length. */ return(0); } /* Write the byte back. */ buffer_ptr[0] = byte; /* Loop to pickup the remaining characters in the object string. */ while (total) { /* Initialize the sequence byte value to NULL. */ value = 0; /* Move the buffer pointer forward. */ byte = *buffer_ptr++; /* Decrement the total. */ total--; /* Increment the length. */ length++; /* Determine if the next byte has the additional bytes bit set (BIT 7). */ if ((byte & NX_SNMP_ANS1_MULTI_BYTES) == 0) { /* The specified sequence value is less than 128 and is actually in this byte! */ value = (UINT) byte; } else { /* Otherwise, we have a more complicated value that we must loop through to calculate. */ /* Loop to calculate how many bytes there are representing the value. */ i = 0; multiply = 128; while (buffer_ptr[i] & NX_SNMP_ANS1_MULTI_BYTES) { /* Increment count. */ i++; /* Adjust the multiplier. */ multiply = multiply * 128; } /* Determine if the count is reasonable. */ if (i > 3) { /* Restore the saved byte. */ *saved_ptr = saved_byte; /* Nope, too big! */ return(0); } /* Loop to calculate the value. */ do { /* Pickup the number of bytes required to represent this value. */ temp = (ULONG) (byte & ~NX_SNMP_ANS1_MULTI_BYTES); /* Calculate the temporary value. */ temp = temp * multiply; /* Calculate total value. */ value = value + temp; /* Adjust the multiply value. */ multiply = multiply/128; /* Pickup next byte. */ byte = *buffer_ptr++; /* Decrement the total. */ if (total == 0) { /* Restore the saved byte. */ *saved_ptr = saved_byte; return(0); } else total--; /* Increment the length. */ length++; } while (byte & NX_SNMP_ANS1_MULTI_BYTES); /* Add in the remainder. */ temp = (ULONG) (byte & ~NX_SNMP_ANS1_MULTI_BYTES); value = value + temp; } /* Convert value into ASCII. */ size = _nx_utility_uint_to_string(value, 10, (CHAR *)object_string, NX_SNMP_MAX_OCTET_STRING + 1 - string_length); if (size == 0) { /* String is too long. */ /* Null-terminate the string. */ *object_string = NX_NULL; /* Return the length. */ return(length); } /* Adjust the object string length. */ string_length += size; /* Adjust the object string. */ object_string = object_string + size; /* Determine if there are more tokens. */ if (total) { /* Still more nodes, place a dot in the string. */ *object_string++ = '.'; /* Increment the string length. */ string_length++; /* Determine if the length is too long. */ if (string_length >= NX_SNMP_MAX_OCTET_STRING) { /* String is too long. */ /* Null-terminate the string. */ object_string--; *object_string = NX_NULL; /* Return the length. */ return(length); } } } /* Restore the saved byte. */ *saved_ptr = saved_byte; /* NULL-terminate the object string. */ *object_string = NX_NULL; /* Return the length of the ANS1 string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_id_set PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function converts the ASCII representation of the object into */ /* ASN.1 format and then places it in the ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* object_string Object string in ASCII */ /* buffer_end End of ASN.1 buffer for error */ /* checking */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send SNMP v1 trap send */ /* _nx_snmp_agent_trapv2_send SNMP v2 trap send */ /* _nx_snmp_agent_trapv3_send SNMP v3 trap send */ /* _nx_snmp_utility_object_data_set Object data set */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 10-31-2023 Bo Chen Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_id_set(UCHAR *buffer_ptr, UCHAR *object_string, UCHAR *buffer_end) { UINT length; UINT i; ULONG value; UCHAR *length_ptr; UCHAR encoding_started; UINT object_string_length; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Check object string length. */ if (_nx_utility_string_length_check((CHAR*)object_string, &object_string_length, (UINT)(buffer_end - buffer_ptr))) return(0); /* Set the OBJECT byte. */ *buffer_ptr++ = NX_SNMP_ANS1_OBJECT_ID; /* Remember length pointer. */ length_ptr = buffer_ptr; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the length byte to zero for now. */ *buffer_ptr++ = 0; /* Check object string length. */ if (object_string_length < 2) return(0); /* Determine if the object string is legal. */ if (((object_string[0] != '0') && (object_string[0] != '1') && (object_string[0] != '2')) || (object_string[1] != '.')) { /* Invalid object ID. */ return(0); } /* Calculate the value of the second identifier. */ i = 2; value = 0; while ((object_string[i] != '.') && (object_string[i] != NX_NULL)) { /* Compute the value. */ value = (value * 10) + ((ULONG) (object_string[i] - 0x30)); /* Move to the next character. */ i++; } if (object_string[i] == '.') { /* Move to the next character. */ i++; } /* The second identifier must be less that 128. */ if (value >= 128) { /* Invalid object ID. */ return(0); } /* Now determine how to set the first byte of the object ID. */ if (object_string[0] == '1') { /* Increment value by 40 per spec. */ value = value + 40; } else if (object_string[0] == '2') { /* Increment value by 40 per spec. */ value = value + 80; } /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the first byte, which is the combination of the first two bytes. */ *buffer_ptr++ = (UCHAR) value; /* Set the length. */ length = 1; /* Process all the characters in the ID. For now, the limit will be 128 characters in the ID specification string. */ while (object_string[i]) { UCHAR *value_ptr; UCHAR byte0; ULONG mod_value; /* Initialize the encoding started flag. */ encoding_started = NX_FALSE; /* Pickup the next value. */ value = 0; while ((object_string[i] != '.') && (object_string[i] != NX_NULL)) { /* Compute the value. */ value = (value * 10) + ((ULONG) (object_string[i] - 0x30)); /* Move to the next character. */ i++; } /* At this point we have a value to store in the ID string. */ /* Determine if it is simple encoding. */ if (value < 128) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Place the value directly in the buffer. */ *buffer_ptr++ = (UCHAR) value; /* Increment the length. */ length++; } else { /* Otherwise, we need to encode the numeric value such that it has more bytes to represent it. */ if (value/268435456) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/268435456; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 268435456; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value/2097152) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/2097152; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 2097152; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value / 16384) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/16384; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 16384; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value /128) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/128; /* (0x100) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 128; /* Increment the length. */ length++; } /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Place the value directly in the buffer. */ *buffer_ptr++ = (UCHAR) value; /* Increment the length. */ length++; } /* Determine if we are sitting on a dot. */ if (object_string[i] == '.') i++; } /* Update the length. */ length_ptr[0] = (UCHAR) (length & 0xFF); /* Return the length plus the header information. */ return(length + 2); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_id_set_1byte PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function converts the ASCII representation of the object into */ /* ASN.1 format and then places it in the ASN.1 buffer. */ /* */ /* The difference with _nx_snmp_utility_object_id_set is that */ /* this uses only a single byte length field e.g. 0x30 xx instead of */ /* 0x30 0x82 xx yy where xx(yy) is the sequence length (1 vs 2 bytes). */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* object_string Object string in ASCII */ /* buffer_end End of ASN.1 buffer for error */ /* checking */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_id_set_1byte(UCHAR *buffer_ptr, UCHAR *object_string, UCHAR *buffer_end) { UINT length; UINT i; ULONG value; UCHAR *length_ptr; UCHAR encoding_started; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the OBJECT byte. */ *buffer_ptr++ = NX_SNMP_ANS1_OBJECT_ID; /* Remember length pointer. */ length_ptr = buffer_ptr; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the length byte to zero for now. */ *buffer_ptr++ = 0; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Determine if the object string is legal. */ if (((object_string[0] != '0') && (object_string[0] != '1') && (object_string[0] != '2')) || (object_string[1] != '.')) { /* Invalid object ID. */ return(0); } /* Calculate the value of the second identifier. */ i = 2; value = 0; while ((object_string[i] != '.') && (object_string[i] != NX_NULL)) { /* Compute the value. */ value = (value * 10) + ((ULONG) (object_string[i] - 0x30)); /* Move to the next character. */ i++; } if (object_string[i] == '.') { /* Move to the next character. */ i++; } /* The second identifier must be less that 128. */ if (value >= 128) { /* Invalid object ID. */ return(0); } /* Now determine how to set the first byte of the object ID. */ if (object_string[0] == '1') { /* Increment value by 40 per spec. */ value = value + 40; } else if (object_string[0] == '2') { /* Increment value by 40 per spec. */ value = value + 80; } /* Set the first byte, which is the combination of the first two bytes. */ *buffer_ptr++ = (UCHAR) value; /* Set the length. */ length = 1; /* Process all the characters in the ID. For now, the limit will be 128 characters in the ID specification string. */ while (object_string[i]) { UCHAR *value_ptr; UCHAR byte0; ULONG mod_value; /* Initialize the encoding started flag. */ encoding_started = NX_FALSE; /* Pickup the next value. */ value = 0; while ((object_string[i] != '.') && (object_string[i] != NX_NULL)) { /* Compute the value. */ value = (value * 10) + ((ULONG) (object_string[i] - 0x30)); /* Move to the next character. */ i++; } /* At this point we have a value to store in the ID string. */ /* Determine if it is simple encoding. */ if (value < 128) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Place the value directly in the buffer. */ *buffer_ptr++ = (UCHAR) value; /* Increment the length. */ length++; } else { /* Otherwise, we need to encode the numeric value such that it has more bytes to represent it. */ if (value/268435456) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/268435456; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 268435456; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value/2097152) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/2097152; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 2097152; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value / 16384) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/16384; /* (0x10000000) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 16384; /* Increment the length. */ length++; /* Set the encoding started flag so that we put 0 bytes below in cases where value is less than the next 128 divisor. */ encoding_started = NX_TRUE; } if ((value /128) || (encoding_started == NX_TRUE)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* To avoid compiler warnings of casting an ULONG to a UCHAR (loss of information possible), use an intermediate ULONG pointer. */ mod_value = value/128; /* (0x100) */ value_ptr = (UCHAR *)(&mod_value); /* A UCHAR will not hold more than one byte. */ byte0 = *(value_ptr); *buffer_ptr = ((UCHAR) (byte0)) | NX_SNMP_ANS1_MULTI_BYTES; buffer_ptr++; /* Update the value. */ value = value % 128; /* Increment the length. */ length++; } /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Place the value directly in the buffer. */ *buffer_ptr++ = (UCHAR) value; /* Increment the length. */ length++; } /* Determine if we are sitting on a dot. */ if (object_string[i] == '.') i++; } /* Update the length. */ length_ptr[0] = (UCHAR) (length & 0xFF); /* Return the length plus the header information. */ return(length + 2); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_data_get PORTABLE C */ /* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object data from the supplied ASN.1 */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* object_data Pointer to place object data */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* _nx_snmp_utility_object_id_get Get object ID */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 10-31-2022 Yuxin Zhou Modified comment(s), and */ /* fixed compiler warnings, */ /* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_data_get(UCHAR *buffer_ptr, NX_SNMP_OBJECT_DATA *object_data, INT buffer_length) { UINT i; UINT length = 0; LONG data; UINT total = 0; CHAR byte; LONG temp = 0; USHORT tlv_type, tlv_tag_class; UCHAR *tlv_data; UCHAR *work_ptr; UINT status; /* Check the buffer length. */ if (buffer_length < 1) { return(0); } work_ptr = buffer_ptr; /* First, pickup the request byte. */ byte = (CHAR)(*buffer_ptr); /* Clear several value words. */ object_data -> nx_snmp_object_data_msw = 0; object_data -> nx_snmp_object_data_lsw = 0; /* Determine if a NULL is present. */ if (byte == NX_SNMP_ANS1_NULL) { /* Return NULL values in the input object, and set length to 2 (0x05 00). */ object_data -> nx_snmp_object_data_type = NX_SNMP_ANS1_NULL; object_data -> nx_snmp_object_data_msw = 0; return(2); } /* Determine if the object is a standard type. */ else if ((byte == NX_SNMP_ANS1_OCTET_STRING) || (byte == NX_SNMP_ANS1_INTEGER) || (byte == NX_SNMP_ANS1_TIME_TICS) || (byte == NX_SNMP_ANS1_GAUGE) || (byte == NX_SNMP_ANS1_COUNTER) || (byte == NX_SNMP_ANS1_COUNTER64) || (byte == NX_SNMP_IP_ADDRESS) || (byte == NX_SNMP_ANS1_NSAP_ADDRESS)) { /* Standard object type. */ /* Check the buffer length. */ if (buffer_length < 3) { return(0); } /* If this is an integer, determine if we have a negative number (msb is set). */ if ((*buffer_ptr == NX_SNMP_ANS1_INTEGER) && (*(buffer_ptr + 2) & 0x80)) { /* This only applies if short form (size of length =1), not long form (size of length field > 1 byte) */ if (((*(buffer_ptr + 1) & 0x80)== 0)) temp = -1; /* We can only check the sign for long form data after we compute the length of length field below */ } /* Update the object with the data type. */ object_data -> nx_snmp_object_data_type = (UINT)byte; /* Extract the length of the length field and tag class. This sill update the pointer past the type * and length fields to the actual data. */ status = _nx_snmp_utility_tlv_block_parse(work_ptr, buffer_length, &tlv_type, &tlv_tag_class, (ULONG *)(&total), &tlv_data, (ULONG *)(&length)); if (status) { return 0; } work_ptr = tlv_data; /* Initialize working data. */ data = temp; object_data -> nx_snmp_object_octet_string_size = 0; i = 0; /* handle the special case of a leading zero e.g. 00 DD 2F C9 CE 69 52 74 8D where total is 9 */ if ((total == 9) && (object_data -> nx_snmp_object_data_type != NX_SNMP_ANS1_OCTET_STRING)) { /* Skip the first byte and decrement total */ work_ptr++; total = total - 1; } /* Loop through the remaining request length bytes. */ while (i < total) { /* Pickup next byte. */ byte = (CHAR)(*work_ptr++); /* Determine the type of the data. */ if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_OCTET_STRING) { /* Check for string size. */ if ((i) >= NX_SNMP_MAX_OCTET_STRING) { return(0); } /* Copy byte into the string. */ object_data -> nx_snmp_object_octet_string[i] = (UCHAR)byte; /* Increment the length. */ object_data -> nx_snmp_object_octet_string_size++; } else { /* Compute the request id based on the next value. */ data = (data << 8) | ((LONG) (0x000000FF & byte)); } /* Increment the length. */ length++; i++; /* If we are dealing with a 64 bit number, store the rest (least) significant bytes in lsw. */ if ((i == 4) && (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64)) { object_data -> nx_snmp_object_data_msw = data; data = 0x0; /* Finish the rest of the data into lsw */ while(i < total) { /* Pickup next byte. */ byte = (CHAR)(*work_ptr++); /* Compute the request id based on the next value. */ data = (data << 8) | ((LONG) (0x000000FF & byte)); i++; } object_data -> nx_snmp_object_data_lsw = data; } } /* If dealing with a 32 bit data type or less, store the data to msw */ if (object_data -> nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER64) { object_data -> nx_snmp_object_data_msw = data; } else { /* Otherwise (e.g. this is a 64 bit data type) store the least significant bytes in the lsw */ object_data -> nx_snmp_object_data_lsw = data; } /* Null terminate the data string. */ if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_OCTET_STRING) { /* Null terminate string. */ if ((i > 0) && (i < NX_SNMP_MAX_OCTET_STRING)) { object_data -> nx_snmp_object_octet_string[i] = NX_NULL; } } /* Return the length of the request id string. */ return(length); } else if (byte == NX_SNMP_ANS1_OBJECT_ID) { /* Setup the data type. */ object_data -> nx_snmp_object_data_type = (UINT)byte; /* Convert the object ID to a string. */ length = _nx_snmp_utility_object_id_get(buffer_ptr, object_data -> nx_snmp_object_octet_string, buffer_length); /* Return length of the object id. */ return(length); } /* Error; return zero length. */ return(0); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_data_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the object data and then places it in the */ /* ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* object_data Object data structure */ /* buffer_end End of ASN.1 buffer for error */ /* checking */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* _nx_snmp_utility_object_id_set Set object ID */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send Send SNMP v1 Trap */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 Trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 Trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_data_set(UCHAR *buffer_ptr, NX_SNMP_OBJECT_DATA *object_data, UCHAR *buffer_end) { UINT i; UINT length; UINT data_msw; UINT data_lsw; /* Process relative to the type of request. */ /* See if the request is a NULL. */ if ((object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_NULL) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_NO_SUCH_OBJECT) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_NO_SUCH_INSTANCE) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_END_OF_MIB_VIEW)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 2) >= buffer_end) return(0); /* Set the NULL type byte. */ *buffer_ptr++ = (UCHAR) object_data -> nx_snmp_object_data_type; *buffer_ptr = 0; /* Set the length. */ length = 2; } /* See if the request is an INTEGER. */ else if ((object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_INTEGER) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_UINTEGER32) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_TIME_TICS) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_GAUGE) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64) || (object_data -> nx_snmp_object_data_type == NX_SNMP_IP_ADDRESS) || (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_NSAP_ADDRESS)) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the type byte. */ *buffer_ptr++ = (UCHAR)object_data -> nx_snmp_object_data_type; /* Pickup the data most significant word. */ data_msw = (UINT)(object_data -> nx_snmp_object_data_msw); /* Pickup the data least significant word. */ data_lsw = (UINT)(object_data -> nx_snmp_object_data_lsw); /* Determine the size of the encoding. */ if (((data_msw & 0xFF000000) || (data_msw & 0x00800000)) && (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 9) >= buffer_end) return(0); /* Four bytes are required. */ *buffer_ptr++ = ((UCHAR) 8); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_lsw & 0xFF); /* Update the length. */ length = 10; return(length); } else if (((data_msw & 0x00FF0000) || (data_msw & 0x00008000)) && (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 8) >= buffer_end) return(0); /* Three bytes are required. */ *buffer_ptr++ = ((UCHAR) 7); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_lsw & 0xFF); /* Update the length. */ length = 9; return(length); } else if (((data_msw & 0x0000FF00) || (data_msw & 0x00000080)) && (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 7) >= buffer_end) return(0); /* Two bytes are required. */ *buffer_ptr++ = ((UCHAR) 6); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_lsw & 0xFF); /* Update the length. */ length = 8; return(length); } else if (((data_msw & 0x000000FF) || (data_lsw & 0x80000000)) && (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 6) >= buffer_end) return(0); /* One byte is required. */ *buffer_ptr++ = ((UCHAR) 5); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_lsw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_lsw & 0xFF); /* Update the length. */ length = 7; return(length); } else if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_COUNTER64) { /* Make the least significant word the most significant to use the normal integer processing below. */ data_msw = data_lsw; } /* Determine the size of the encoding. */ if ((data_msw & 0xFF000000) || (data_msw & 0x00800000) || (object_data -> nx_snmp_object_data_type == NX_SNMP_IP_ADDRESS)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 5) >= buffer_end) return(0); /* Four bytes are required. */ *buffer_ptr++ = ((UCHAR) 4); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); /* Update the length. */ length = 6; } else if ((data_msw & 0x00FF0000) || (data_msw & 0x00008000)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 4) >= buffer_end) return(0); /* Three bytes are required. */ *buffer_ptr++ = ((UCHAR) 3); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); /* Update the length. */ length = 5; } else if ((data_msw & 0x0000FF00) || (data_msw & 0x00000080)) { /* Check for the end of the buffer. */ if ((buffer_ptr + 3) >= buffer_end) return(0); /* Two bytes are required. */ *buffer_ptr++ = ((UCHAR) 2); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) ((data_msw >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); /* Update the length. */ length = 4; } else { /* Check for the end of the buffer. */ if ((buffer_ptr + 2) >= buffer_end) return(0); /* One byte is required. */ *buffer_ptr++ = ((UCHAR) 1); /* Set the value in successive bytes. */ *buffer_ptr++ = (UCHAR) (data_msw & 0xFF); /* Update the length. */ length = 3; } } /* See if the request is an octet string. Note that this includes the IPv6 address type. */ else if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_OCTET_STRING) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the OCTET type byte. */ *buffer_ptr++ = NX_SNMP_ANS1_OCTET_STRING; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Determine if a two byte length is required. */ if (object_data -> nx_snmp_object_octet_string_size >= 128) { /* A two byte length is required. */ /* Set the two byte length. */ *buffer_ptr++ = 0x82; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the first byte of the length. */ *buffer_ptr++ = (UCHAR) (object_data -> nx_snmp_object_octet_string_size >> 8); /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the second byte of the length. */ *buffer_ptr++ = (UCHAR) (object_data -> nx_snmp_object_octet_string_size & 0xFF); /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the length to represent the 4 byte header. */ length = 4; } else { /* Set the length byte. */ *buffer_ptr++ = (UCHAR) (object_data -> nx_snmp_object_octet_string_size & 0xFF); /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Set the length to represent the 2 byte header. */ length = 2; } /* Loop to process the string. */ i = 0; while (i < object_data -> nx_snmp_object_octet_string_size) { /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* Place octet string into buffer. */ *buffer_ptr++ = object_data -> nx_snmp_object_octet_string[i++]; } /* Account for the leading bytes in the length. */ length = length + i; } else if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_OBJECT_ID) { /* Call the object set routine. */ length = _nx_snmp_utility_object_id_set(buffer_ptr, object_data -> nx_snmp_object_octet_string, buffer_end); } else { /* Unhandled, return an error by setting length to 0. */ length = 0; } /* Return the length. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_octet_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the octet string from the supplied ASN.1 */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* octet_string Pointer to destination for */ /* the octet string */ /* max_octet_length Size of octet string buffer */ /* octet_length Pointer to length for octet */ /* string */ /* buffer_length Size of input buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_octet_get(UCHAR *buffer_ptr, UCHAR *octet_string, UINT max_octet_length, UINT *octet_length, INT buffer_length) { UINT i; UINT length; UINT total; /* Buffer size must be at least 2 bytes. */ if (buffer_length < 2) { return(0); } /* Set the octet length to zero. */ *octet_length = 0; /* First see if the ANS1 string type is present. */ if (buffer_ptr[0] != NX_SNMP_ANS1_OCTET_STRING) { /* Return a zero length. */ return(0); } /* Determine if a two byte length is present. */ if (*(buffer_ptr + 1) & NX_SNMP_ANS1_MULTI_BYTES) { UINT temp = *(buffer_ptr + 1) & 0x7F; if (temp == 2) { /* A two byte length is present. */ /* Check the buffer length. */ if (buffer_length < 4) { return(0); } /* Pickup the length. */ total = (((UINT) buffer_ptr[2]) << 8) | ((UINT) buffer_ptr[3]); /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 4; /* Initialize the length. */ length = 4; } else if (temp == 1) { /* Check the buffer length. */ if (buffer_length < 3) { return(0); } /* Otherwise, pickup the total length of the octet string. */ total = (UINT) buffer_ptr[2]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 3; /* Initialize the length. */ length = 3; } else { /* Invalid sequence. Too big or null size type. */ return(0); } } else { /* Otherwise, assume 1 byte. Pickup the total length of the octet string. */ total = (UINT) buffer_ptr[1]; /* Move the buffer pointer forward. */ buffer_ptr = buffer_ptr + 2; /* Initialize the length. */ length = 2; } /* Check for invalid buffer size. */ if ((INT)(length + total) > buffer_length) { /* Indicate an invalid request or packet is received. */ return 0; } /* Determine if the octet string is too large. */ if (total > max_octet_length) { /* Yes, the octet string is too large. Return an error. */ return(0); } /* Loop to pickup the remaining characters in the community string. */ for (i = 0; i < total; i++) { /* Move character from buffer into community string. */ *octet_string++ = *buffer_ptr++; /* Adjust the length. */ length++; } /* return the length of the octet string. */ *octet_length = total; /* Return the length of the ANS1 string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_octet_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the supplied octet string into the ASN.1 */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* octet_string Pointer to octet string */ /* octet_length Length of the octet string */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_octet_set(UCHAR *buffer_ptr, UCHAR *octet_string, UINT octet_length, UCHAR *buffer_end) { UINT i; UINT header_size; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* First, set the OCTET byte. */ *buffer_ptr++ = NX_SNMP_ANS1_OCTET_STRING; /* Check for a length greater than the maximum. */ if (octet_length > NX_SNMP_MAX_OCTET_STRING) { /* Error, octet string is too large. */ return(0); } /* Determine if a two byte length is required. */ if (octet_length >= 128) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < (3 + octet_length)) return(0); /* Set the two byte length flag. */ *buffer_ptr++ = (UCHAR) 0x82; /* Set the first length byte. */ *buffer_ptr++ = (UCHAR) (octet_length >> 8); /* Set the second length byte. */ *buffer_ptr++ = (UCHAR) (octet_length & 0xFF); /* Set the header size. */ header_size = 4; } else { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < (1 + octet_length)) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) octet_length; /* Set the header size. */ header_size = 2; } /* Loop to store rest of the community string. */ for (i = 0; i < octet_length; i++) { /* Store the SNMP octet string. */ *buffer_ptr++ = (UCHAR) octet_string[i]; } /* Return the length of the community string. */ return(octet_length+header_size); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_sequence_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the ASN.1 sequence from the supplied ASN.1 */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* sequence_value Pointer to destination for */ /* the sequence value */ /* buffer_length Size of buffer data */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_thread_entry SNMP Agent's thread entry */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_sequence_get(UCHAR *buffer_ptr, UINT *sequence_value, INT buffer_length) { UINT i; UINT length; UINT value; UINT total; UCHAR byte; /* Buffer size must be at least 2 bytes. */ if (buffer_length < 2) { return(0); } /* First, pickup the sequence byte. */ byte = *buffer_ptr++; /* Determine if the byte is a sequence byte (0x30). */ if (byte != NX_SNMP_ANS1_SEQUENCE) { /* Error, not a sequence byte, return a NULL. */ *sequence_value = 0; return(0); } /* Otherwise, we have a valid sequence byte. */ /* Pickup next byte. */ byte = *buffer_ptr++; /* Initialize the length of the sequence field to 2. */ length = 2; /* Determine if the next byte has the additional bytes bit set (BIT 7). */ if ((byte & NX_SNMP_ANS1_MULTI_BYTES) == 0) { /* The specified sequence value is less than 128 and is actually in this byte! */ *sequence_value = (UINT) byte; /* Return the actual length of the ANS1 sequence string. */ return(length); } /* Otherwise, we have a more complicated sequence length that we must loop through to calculate the actual sequence length. */ /* Pickup the number of bytes required to represent the sequence length. */ total = (UINT) (byte & ~NX_SNMP_ANS1_MULTI_BYTES); /* Check for invalid buffer size. */ if ((INT)(length + total) > buffer_length) { /* Indicate an invalid request or packet is received. */ return 0; } value = 0; /* Loop through the remaining sequence bytes. */ for (i = 0; i < total; i++) { /* Pickup next byte. */ byte = *buffer_ptr++; /* Compute the sequence based on the next value. */ value = (value << 8) | ((UINT) byte); /* Increment the length. */ length++; } /* Return the calculated sequence value. */ *sequence_value = value; /* Return the length of the sequence string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_sequence_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the sequence number into the ASN.1 */ /* buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* sequence_value Sequence value */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send Send SNMP v1 trap */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_sequence_set(UCHAR *buffer_ptr, UINT sequence_value, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 4) return(0); /* First, set the sequence byte. */ *buffer_ptr++ = NX_SNMP_ANS1_SEQUENCE; /* Next set the continue bit to force two additional bytes for length. */ *buffer_ptr++ = ((UCHAR) 2) | NX_SNMP_ANS1_MULTI_BYTES; /* Store the MSB. */ *buffer_ptr++ = (UCHAR) ((sequence_value >> 8) & 0xFF); /* Store the LSB. */ *buffer_ptr = (UCHAR) (sequence_value & 0xFF); /* Return the length of the sequence string. */ return(4); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_sequence_set_1byte PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the sequence number into the ASN.1 */ /* buffer. The difference with _nx_snmp_utility_sequence_set is that */ /* this uses only a single byte length field e.g. 0x30 xx instead of */ /* 0x30 0x82 xx yy where xx(yy) is the sequence length (1 vs 2 bytes). */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* sequence_value Sequence value */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_sequence_set_1byte(UCHAR *buffer_ptr, UINT sequence_value, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 2) return(0); /* First, set the sequence byte. */ *buffer_ptr++ = NX_SNMP_ANS1_SEQUENCE; /* Store the value. */ *buffer_ptr = (UCHAR) (sequence_value & 0xFF); /* Return the length of the sequence string. */ return(2); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_request_id_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the ASN.1 request ID from the supplied */ /* ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* request_id Pointer to destination for */ /* the request ID */ /* buffer_length Size of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_request_id_get(UCHAR *buffer_ptr, ULONG *request_id, INT buffer_length) { UINT i; UINT length; ULONG value; UINT total; UCHAR byte; /* Buffer size must be at least 2 bytes. */ if (buffer_length < 2) { return(0); } /* First, pickup the request byte. */ byte = *buffer_ptr++; /* Determine if the byte is a valid SNMP request type. */ if (byte != NX_SNMP_ANS1_INTEGER) { /* Error, not request id, return a NULL. */ *request_id = 0; return(0); } /* Otherwise, we have a valid request id. */ /* Pickup the ANS1 length byte. */ total = (UINT) *buffer_ptr++; /* Initialize the length of the request field to 2. */ length = 2; /* Check the length specified in the buffer against buffer size. */ if ((INT)(length + total) > buffer_length) { *request_id = 0; return(0); } /* Initialize working request length. */ value = 0; /* Loop through the remaining request length bytes. */ for (i = 0; i < total; i++) { /* Pickup next byte. */ byte = *buffer_ptr++; /* Compute the request id based on the next value. */ value = (value << 8) | ((ULONG) byte); /* Increment the length. */ length++; } /* Return the calculated request id. */ *request_id = value; /* Return the length of the request id string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_request_id_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the request ID into the ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* request_id Request ID */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_request_id_set(UCHAR *buffer_ptr, ULONG request_id, UCHAR *buffer_end) { UINT length; /* Check for the end of the buffer. */ if (buffer_ptr >= buffer_end) return(0); /* First, set the INTEGER byte. */ *buffer_ptr++ = NX_SNMP_ANS1_INTEGER; /* Determine how big the ID is. */ if ((request_id & 0xFF000000UL) || (request_id & 0x00800000)) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 5) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 4; /* Set the request ID in successive bytes. */ *buffer_ptr++ = (UCHAR) ((request_id >> 24) & 0xFF); *buffer_ptr++ = (UCHAR) ((request_id >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((request_id >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (request_id & 0xFF); /* Update the length. */ length = 6; } else if ((request_id & 0x00FF0000UL) || (request_id & 0x00008000)) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 4) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 3; /* Set the request ID in successive bytes. */ *buffer_ptr++ = (UCHAR) ((request_id >> 16) & 0xFF); *buffer_ptr++ = (UCHAR) ((request_id >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (request_id & 0xFF); /* Update the length. */ length = 5; } else if ((request_id & 0x0000FF00UL) || (request_id & 0x00000080)) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 3) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 2; /* Set the request ID in successive bytes. */ *buffer_ptr++ = (UCHAR) ((request_id >> 8) & 0xFF); *buffer_ptr++ = (UCHAR) (request_id & 0xFF); /* Update the length. */ length = 4; } else { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 2) return(0); /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 1; /* Set the request ID in successive bytes. */ *buffer_ptr++ = (UCHAR) (request_id & 0xFF); /* Update the length. */ length = 3; } /* Return the length of the request ID. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_request_type_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the ASN.1 request type from the supplied */ /* ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* request_type Pointer to destination for */ /* the request type */ /* request_length Pointer to destination for */ /* the request length */ /* buffer_length Size of input buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_request_type_get(UCHAR *buffer_ptr, UINT *request_type, UINT *request_length, INT buffer_length) { UINT i; UINT length; UINT value; UINT total; UCHAR byte; /* Buffer size must be at least 2 bytes. */ if (buffer_length < 2) { return(0); } /* First, pickup the request byte. */ byte = *buffer_ptr++; /* Determine if the byte is a valid SNMP request type. */ if ((byte < NX_SNMP_ANS1_SEQUENCE) || (byte > NX_SNMP_ANS1_TRAP2_REQUEST)) { /* Error, not request, return a NULL. */ *request_type = 0; *request_length = 0; return(0); } /* Otherwise, we have a valid request. */ /* Store the request in the destination. */ *request_type = (UINT) byte; /* Pickup next byte. */ byte = *buffer_ptr++; /* Initialize the length of the request field to 2. */ length = 2; /* Determine if the next byte has the additional bytes bit set (BIT 7). */ if ((byte & NX_SNMP_ANS1_MULTI_BYTES) == 0) { /* The specified request length is less than 128 and is actually in this byte! */ *request_length = (UINT) byte; /* Return the actual length of the ANS1 request string. */ return(length); } /* Otherwise, we have a more complicated request length that we must loop through to calculate the actual length. */ /* Pickup the number of bytes required to represent the request length. */ total = (UINT) (byte & ~NX_SNMP_ANS1_MULTI_BYTES); if ((INT)(length + total) > buffer_length) { /* Error, invalid request, return a NULL. */ *request_type = 0; *request_length = 0; return(0); } /* Initialize working request length. */ value = 0; /* Loop through the remaining request length bytes. */ for (i = 0; i < total; i++) { /* Pickup next byte. */ byte = *buffer_ptr++; /* Compute the request length based on the next value. */ value = (value << 8) | ((UINT) byte); /* Increment the length. */ length++; } /* Return the calculated request length. */ *request_length = value; /* Return the length of the request string. */ return(length); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_request_type_set_1byte PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the request type into the ASN.1 buffer. It is */ /* intended for small requests whose size value can fit into one byte. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* request_type Request type */ /* request_length Request length */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send Send SNMP v1 trap */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_request_type_set_1byte(UCHAR *buffer_ptr, UINT request_type, UINT request_length, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 2) return(0); /* First, set the request type byte. */ *buffer_ptr++ = (UCHAR) request_type; /* Store the request_length. */ *buffer_ptr = (UCHAR) (request_length & 0xFF); return 2; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_request_type_set_multibyte PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the request type into the ASN.1 buffer. It is */ /* intended for large requests whose size value requires more than one */ /* byte, e.g. A2 82 xx yy. For get, getnext requests, and report and */ /* trap responses, use _nx_snmp_utility_request_type_set_1byte. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* request_type Request type */ /* request_length Request length */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_request_type_set_multibyte(UCHAR *buffer_ptr, UINT request_type, UINT request_length, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 4) return(0); /* First, set the request type byte. */ *buffer_ptr++ = (UCHAR) request_type; /* Set the continue bit to force two additional bytes for length. */ *buffer_ptr++ = ((UCHAR) 2) | NX_SNMP_ANS1_MULTI_BYTES; /* Store the MSB. */ *buffer_ptr++ = (UCHAR) ((request_length >> 8) & 0xFF); /* Store the LSB. */ *buffer_ptr = (UCHAR) (request_length & 0xFF); return 4; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_version_get PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function retrieves the SNMP version from the supplied */ /* ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* snmp_version Pointer to destination for */ /* the snmp_version */ /* buffer_length Size of buffer data */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_thread_entry SNMP Agent's thread entry */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_version_get(UCHAR *buffer_ptr, UINT *snmp_version, INT buffer_length) { if (buffer_length < 3) { /* Clear the version. */ *snmp_version = 0; /* Return a zero length. */ return(0); } /* Determine if the version string is correct. */ if ((buffer_ptr[0] == NX_SNMP_ANS1_INTEGER) && (buffer_ptr[1] == 1) && ((buffer_ptr[2] == NX_SNMP_VERSION_1) || (buffer_ptr[2] == NX_SNMP_VERSION_2) || (buffer_ptr[2] == NX_SNMP_VERSION_2C) || (buffer_ptr[2] == NX_SNMP_VERSION_3))) { /* Yes, the SNMP version string is correct. */ /* Return the version. */ *snmp_version = (UINT) buffer_ptr[2]; /* Return the length of the version string. */ return(3); } else { /* No, the SNMP version string is invalid. */ /* Clear the version. */ *snmp_version = 0; /* Return a zero length. */ return(0); } } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_version_set PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the SNMP version into the ASN.1 buffer. */ /* */ /* INPUT */ /* */ /* buffer_ptr Pointer to ASN.1 buffer */ /* snmp_version SNMP version number */ /* buffer_end End of buffer */ /* */ /* OUTPUT */ /* */ /* ASN.1 length Length of ASN.1 sequence, a */ /* value of zero implies error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_trap_send Send SNMP v1 trap */ /* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */ /* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_report_send Send SNMP v3 report */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_version_set(UCHAR *buffer_ptr, UINT snmp_version, UCHAR *buffer_end) { /* Check for the end of the buffer. */ if ((UINT)(buffer_end - buffer_ptr) < 3) return(0); /* First, set the INTEGER byte. */ *buffer_ptr++ = NX_SNMP_ANS1_INTEGER; /* Next set the length byte. */ *buffer_ptr++ = (UCHAR) 1; /* Store the SNMP version. */ *buffer_ptr = (UCHAR) (snmp_version & 0xFF); /* Return the length of the sequence string. */ return(3); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_error_response PORTABLE C */ /* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function places the error information into the SNMP Manager's */ /* request packet and returns it to the manager. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* packet_ptr Pointer to packet containing */ /* the original SNMP request */ /* request_type_ptr Pointer to place in ASN.1 */ /* buffer for the request type */ /* error_string_ptr Pointer to place in ASN.1 */ /* buffer to place error info */ /* error_code Error code */ /* error_index Error index */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* nx_packet_release Release the packet */ /* nx_udp_socket_send Send the UDP packet */ /* _nx_snmp_utility_error_info_set Set the error information */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/ /* _nx_snmp_version_3_process SNMP v3 message processing */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), improved */ /* verification of encryption, */ /* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_error_response(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr, UCHAR *request_type_ptr, UCHAR *error_string_ptr, UINT error_code, UINT error_index) { UINT status = NX_SUCCESS; #ifndef NX_SNMP_DISABLE_V3 ULONG temp; #endif /* Increment the error counter. */ agent_ptr -> nx_snmp_agent_request_errors++; /* Determine which specific error counter to increment. */ switch(error_code) { case NX_SNMP_ERROR_TOOBIG: agent_ptr -> nx_snmp_agent_too_big_errors++; break; case NX_SNMP_ERROR_BADVALUE: case NX_SNMP_ERROR_WRONGVALUE: case NX_SNMP_ERROR_WRONGENCODING: case NX_SNMP_ERROR_WRONGTYPE: case NX_SNMP_ERROR_WRONGLENGTH: case NX_SNMP_ERROR_INCONSISTENTVALUE: agent_ptr -> nx_snmp_agent_bad_value_errors++; break; case NX_SNMP_ERROR_NOSUCHNAME: case NX_SNMP_ERROR_NOACCESS: case NX_SNMP_ERROR_NOTWRITABLE: case NX_SNMP_ERROR_NOCREATION: case NX_SNMP_ERROR_INCONSISTENTNAME: case NX_SNMP_ERROR_AUTHORIZATION: agent_ptr -> nx_snmp_agent_no_such_name_errors++; break; case NX_SNMP_ERROR_GENERAL: case NX_SNMP_ERROR_RESOURCEUNAVAILABLE: case NX_SNMP_ERROR_COMMITFAILED: case NX_SNMP_ERROR_UNDOFAILED: agent_ptr -> nx_snmp_agent_general_errors++; break; } /* Set the request type to get/response. */ *request_type_ptr = (UCHAR) NX_SNMP_ANS1_GET_RESPONSE; /* Update the error string with the error code and the object index. */ _nx_snmp_utility_error_info_set(error_string_ptr, error_code, error_index, packet_ptr -> nx_packet_data_end); #ifndef NX_SNMP_DISABLE_V3 if (agent_ptr -> nx_snmp_agent_current_version == NX_SNMP_VERSION_3) { /* Is the security set to encryption? */ temp = (ULONG)agent_ptr -> nx_snmp_agent_v3_message_security_options; if (temp & NX_SNMP_SECURITY_PRIVACY) { /* Encrypt the PDU and setup the response to have an encryption header. This will also compute our privacy parameter. */ status = _nx_snmp_agent_encrypt_pdu(agent_ptr, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, pdu_privacy_ptr); /* Check status. */ if (status) { /* Release the packet. */ nx_packet_release(packet_ptr); return; } } /* Is the security set to authentication? */ if (temp & NX_SNMP_SECURITY_AUTHORIZE) { /* Compute our authentication parameter. */ status = _nx_snmp_agent_add_auth_parameter(agent_ptr, packet_ptr, pdu_auth_parm_ptr); /* Check status. */ if (status) { /* Release the packet. */ nx_packet_release(packet_ptr); return; } } } #endif /* Increment the sent packet counter. */ agent_ptr -> nx_snmp_agent_packets_sent++; /* Increment the get responses sent counter. */ agent_ptr -> nx_snmp_agent_getresponse_sent++; /* Send the response packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), agent_ptr -> nx_snmp_agent_current_manager_port); /* Check for successful call. */ if (status) { /* Release the packet. */ nx_packet_release(packet_ptr); } /* Return to caller. */ return; } #if !defined(NX_SNMP_DISABLE_V1) && !defined(NX_SNMP_DISABLE_V2) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_1_and_2_process PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function processes the SNMP v1 request from the manager. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* packet_ptr Pointer to packet containing */ /* the SNMP request */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* nx_packet_allocate Allocate response packet */ /* nx_packet_release Release the packet */ /* nx_udp_socket_send Send the UDP packet */ /* _nx_snmp_utility_community_get Get the community name */ /* _nx_snmp_utility_community_set Set the community name */ /* _nx_snmp_utility_error_info_get Get the error information */ /* _nx_snmp_utility_error_info_set Set the error information */ /* _nx_snmp_utility_object_data_get Get the object data */ /* _nx_snmp_utility_object_data_set Set the object data */ /* _nx_snmp_utility_object_id_get Get the object ID */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_request_id_get Get the request ID */ /* _nx_snmp_utility_request_id_set Set the request ID */ /* _nx_snmp_utility_request_type_get Get the request type */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_sequence_get Get the ANS.1 sequence */ /* _nx_snmp_utility_sequence_set Set the ANS.1 sequence */ /* _nx_snmp_utility_version_get Get the SNMP version */ /* _nx_snmp_utility_version_set Set the SNMP version */ /* _nx_snmp_version_error_response Send SNMP Manager error */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_thread_entry SNMP Agent thread */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 10-31-2023 Bo Chen Initial Version 6.3.0 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_1_and_2_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr) { UINT sequence_length, version, request_type, request_length; UINT non_repeaters, max_repetitions, next_object; #ifndef NX_SNMP_DISABLE_V2 UINT current_repetitions; #endif /* NX_SNMP_DISABLE_V2 */ UINT variable_list_length, variable_length; ULONG request_id; UINT status, length, objects; UCHAR *buffer_ptr; UCHAR *error_ptr, *request_type_ptr; UINT response_length; UINT total_variable_length = 0; NX_PACKET *response_packet_ptr; UCHAR *response_buffer_ptr; UINT response_sequence_length, response_type_length; UINT response_variable_list_length, response_variable_length; UCHAR *response_sequence_ptr, *response_type_ptr; UCHAR *response_variable_list_ptr, *response_variable_ptr; UINT packet_type; INT buffer_length; buffer_length = (INT)(packet_ptr -> nx_packet_length); /* Setup a pointer to the buffer. */ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; /* Pickup the SEQUENCE field. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Pickup the SNMP VERSION field. */ length = _nx_snmp_utility_version_get(buffer_ptr, &version, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Pickup the SNMP Community String field. */ length = _nx_snmp_utility_community_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_community_string, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Save the request type pointer. */ request_type_ptr = buffer_ptr; /* Pickup the SNMP Request type. */ length = _nx_snmp_utility_request_type_get(buffer_ptr, &request_type, &request_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; agent_ptr -> nx_snmp_agent_request_get_type = NX_FALSE; if ((request_type == NX_SNMP_GET_REQUEST) || (request_type == NX_SNMP_GET_NEXT_REQUEST) || (request_type == NX_SNMP_GET_BULK_REQUEST)) { agent_ptr -> nx_snmp_agent_request_get_type = NX_TRUE; } /* Pickup the SNMP Request ID. */ length = _nx_snmp_utility_request_id_get(buffer_ptr, &request_id, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Save a pointer to the error string. */ error_ptr = buffer_ptr; /* Pickup the SNMP Error information. This is actually used to derive the GETBULK information in SNMP V2 and above. */ length = _nx_snmp_utility_error_info_get(buffer_ptr, &non_repeaters, &max_repetitions, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } #ifndef NX_DISABLE_PACKET_CHAIN /* Determine if the received packet size is too big. */ if (packet_ptr -> nx_packet_next) { /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, 0); /* Done, return to caller. */ return; } #endif /* NX_DISABLE_PACKET_CHAIN */ /* Check to see if there is a username processing routine. */ if (agent_ptr -> nx_snmp_agent_username_process) { /* Yes, there is a callback routine to process the community/username. */ status = agent_ptr -> nx_snmp_agent_username_process(agent_ptr, agent_ptr -> nx_snmp_agent_current_community_string); /* Determine if the callback routine generated an error. */ if (status != NX_SUCCESS) { /* Increment the number of community/username errors. */ agent_ptr -> nx_snmp_agent_username_errors++; /* Check the version. */ if (version == NX_SNMP_VERSION_1) { #ifdef NX_SNMP_V1_AUTHORIZATION_ERROR_RESPONSE /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, 0); #else /* Authorization error response is not supported by version 1. */ /* Release the packet. */ nx_packet_release(packet_ptr); #endif } else { /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_AUTHORIZATION, 0); } /* Done, return to caller. */ return; } } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Pickup the SNMP Variable list length. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_list_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* At this point we have parsed the incoming SNMP request up to the first variable. */ /* Now prepare response message so we can process the variables one by one. */ /* Determine which packet type we allocate based on the destination address type. */ if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 /* Release the packet. */ nx_packet_release(packet_ptr); return; #else packet_type = NX_IPv6_UDP_PACKET; #endif /* FEATURE_NX_IPV6 */ } else { /* Release the packet. */ nx_packet_release(packet_ptr); return; } /* Allocate the packet for the SNMP response. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &response_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a response packet was allocated. */ if (status) { /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } memset(response_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(response_packet_ptr -> nx_packet_data_end - response_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the response packet. */ response_sequence_length = 0; response_type_length = 0; response_variable_list_length = 0; /* Setup a pointer to the response packet's buffer area. */ response_buffer_ptr = response_packet_ptr -> nx_packet_prepend_ptr; /* This is also the response sequence pointer. Remember it since we are going to have to update it later with the actual length of the response. */ response_sequence_ptr = response_buffer_ptr; /* First, write the sequence in the response packet. A zero is written for now. This will be updated later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Now set the SNMP version in the response. */ response_length = _nx_snmp_utility_version_set(response_buffer_ptr, version, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Set the SNMP community in the response message. */ response_length = _nx_snmp_utility_community_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_current_community_string, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Remember the request type pointer, since it will need to be updated later. */ response_type_ptr = response_buffer_ptr; /* Now set the request type in the response message. */ response_length = _nx_snmp_utility_request_type_set_multibyte(response_buffer_ptr, NX_SNMP_ANS1_GET_RESPONSE, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Now set the request ID in the response message. */ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, request_id, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Set the response error information. Assume everything is okay at this point. */ response_length = _nx_snmp_utility_error_info_set(response_buffer_ptr, 0, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Remember the start of the response's variable list field. */ response_variable_list_ptr = response_buffer_ptr; /* Setup the variable list response. For now, the length will be zero. We will overwrite this with the actual length later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* At this point the response buffer is setup to exactly the same position the SNMP Manager's input buffer is - right before the first variable. We can now walk through the variable list to process each request and place the result in the response buffer. */ objects = 0; next_object = NX_TRUE; #ifndef NX_SNMP_DISABLE_V2 current_repetitions = max_repetitions; #endif /* NX_SNMP_DISABLE_V2 */ do { /* Determine if the next object should be retrieved. */ if (next_object) { /* Pickup the first SNMP Variable length. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_length, buffer_length); /* Calculate the total variable size. */ total_variable_length = variable_length + length; /* Determine if this variable will fit in the remaining length of the variable list, buffer length, and if there is integer overflow. */ if ((length == 0) || (total_variable_length > variable_list_length) || (total_variable_length < variable_length) || (total_variable_length > (UINT)buffer_length)) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_SUCCESS, objects + 1); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* Update the size of the remaining buffer. */ buffer_length -= (INT)length; /* Now pickup the object ID. */ length = _nx_snmp_utility_object_id_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, buffer_length); /* Determine if the object retrieval was successful. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* Update the size of the remaining buffer. */ buffer_length -= (INT)length; /* Default the value to NULL. */ agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type = 0; /* Determine if a value is present. */ if (length != variable_length) { /* Pickup the value associated with this variable. */ length = _nx_snmp_utility_object_data_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), buffer_length); /* Determine if the object value was successful. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Send an SNMP version error response. The packet will be released in the function. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects + 1); /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } else { /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* Update the size of the remaining buffer. */ buffer_length -= (INT)length; } } } /* At this point, we are ready to call the appropriate application request handling routine. It is responsible for extracting or placing information in the object data structure. */ if (request_type == NX_SNMP_ANS1_GET_REQUEST) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Call the application's GET routine. */ status = (agent_ptr -> nx_snmp_agent_get_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Call the application's GETNEXT routine. */ status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } else if (request_type == NX_SNMP_ANS1_SET_REQUEST) { /* Increment the total number of set variables. */ agent_ptr -> nx_snmp_agent_total_set_variables++; /* Call the application's SET routine. */ status = (agent_ptr -> nx_snmp_agent_set_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } #ifndef NX_SNMP_DISABLE_V2 else if ((request_type == NX_SNMP_ANS1_GET_BULK_REQUEST) && (version != NX_SNMP_VERSION_1)) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Clear the next object flag. */ next_object = NX_FALSE; /* Call the application's GETNEXT routine. */ status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); /* Decrement the number of non-repeaters. */ if (non_repeaters) { /* Decrement the number of non-repeaters. */ non_repeaters--; /* Set the next object flag to move to the next entry of the request. */ next_object = NX_TRUE; } else { /* Decrement the repetitions. */ if (current_repetitions) current_repetitions--; /* Determine if there are more repetitions or if the end of MIB was detected. */ if ((current_repetitions == 0) || (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type == NX_SNMP_ANS1_END_OF_MIB_VIEW)) { /* Reset the current repetition. */ current_repetitions = max_repetitions; /* Set the next object flag to true. */ next_object = NX_TRUE; } } } #endif /* NX_SNMP_DISABLE_V2 */ else { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the packet. */ nx_packet_release(packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Check for an error status from the agent's request processing callback routine. */ if (status) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); #ifndef NX_SNMP_DISABLE_V1 /* Check the version. */ if (version == NX_SNMP_VERSION_1) { /* Per RFC2576 4.3 */ switch(status) { case NX_SNMP_SUCCESS: case NX_SNMP_ERROR_TOOBIG: /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects + 1); break; case NX_SNMP_ERROR_BADVALUE: case NX_SNMP_ERROR_WRONGVALUE: case NX_SNMP_ERROR_WRONGENCODING: case NX_SNMP_ERROR_WRONGTYPE: case NX_SNMP_ERROR_WRONGLENGTH: case NX_SNMP_ERROR_INCONSISTENTVALUE: /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects + 1); break; case NX_SNMP_ERROR_NOSUCHNAME: case NX_SNMP_ERROR_NOACCESS: case NX_SNMP_ERROR_NOTWRITABLE: case NX_SNMP_ERROR_NOCREATION: case NX_SNMP_ERROR_INCONSISTENTNAME: case NX_SNMP_ERROR_AUTHORIZATION: /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, objects + 1); break; case NX_SNMP_ERROR_GENERAL: case NX_SNMP_ERROR_RESOURCEUNAVAILABLE: case NX_SNMP_ERROR_COMMITFAILED: case NX_SNMP_ERROR_UNDOFAILED: /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_GENERAL, objects + 1); break; default: /* Release the packet. */ nx_packet_release(packet_ptr); } } else #endif /* NX_SNMP_DISABLE_V1 */ { /* Call the error handling response routine. This will release the packet */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects + 1); } /* Done, return to caller. */ return; } /* Determine if the returning object is valid. */ if ((agent_ptr -> nx_snmp_agent_current_octet_string[0] != '1') || (agent_ptr -> nx_snmp_agent_current_octet_string[1] != '.') || (agent_ptr -> nx_snmp_agent_current_octet_string[2] != '3') || (agent_ptr -> nx_snmp_agent_current_octet_string[3] != '.')) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the packet. */ nx_packet_release(packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Now ensure the returning object type is valid. */ if ((agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_INTEGER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OCTET_STRING) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NULL) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_TIME_TICS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_GAUGE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER64) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_IP_ADDRESS) && #ifdef FEATURE_NX_IPV6 (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) && #endif (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NSAP_ADDRESS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID) #ifndef NX_SNMP_DISABLE_V2 && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_OBJECT) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_INSTANCE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_END_OF_MIB_VIEW) #endif /* NX_SNMP_DISABLE_V2 */ ) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, objects + 1); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Everything is okay, place the object and object data into the response buffer. */ /* Remember the start of the variable response sequence. */ response_variable_ptr = response_buffer_ptr; /* Clear the response variable size. */ response_variable_length = 0; /* Determine if there is enough room in the destination for the variable sequence. */ if ((response_buffer_ptr + 4) >= response_packet_ptr -> nx_packet_data_end) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1); /* Done, return to caller. */ return; } /* Setup the variable response sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Place the object into the response buffer. */ response_length = _nx_snmp_utility_object_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Adjust the response variable size. */ response_variable_length = response_variable_length + response_length; /* Insert the object's data into the response buffer. */ response_length = _nx_snmp_utility_object_data_set(response_buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Adjust the response variable size. */ response_variable_length = response_variable_length + response_length; /* Now update the response variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(response_variable_ptr, response_variable_length, response_packet_ptr -> nx_packet_data_end); /* Only update the source object information if the next object flag is set. */ if (next_object) { /* Decrement the size of the variable list. */ variable_list_length = variable_list_length - total_variable_length; /* Increment the object counter. */ objects++; } } while ((variable_list_length) || (next_object == NX_FALSE)); /* At this point, several response fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(response_sequence_ptr, response_sequence_length, response_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(response_variable_list_ptr, response_variable_list_length, response_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(response_type_ptr, NX_SNMP_ANS1_GET_RESPONSE, response_type_length, response_packet_ptr -> nx_packet_data_end); /* Now the response packet's pointers must be setup so it can be sent. */ response_packet_ptr -> nx_packet_length = (ULONG)(response_buffer_ptr - response_packet_ptr -> nx_packet_prepend_ptr); response_packet_ptr -> nx_packet_append_ptr = response_buffer_ptr; /* Release the original request packet. */ nx_packet_release(packet_ptr); /* Update various statistics. */ agent_ptr -> nx_snmp_agent_total_bytes_received += packet_ptr -> nx_packet_length; agent_ptr -> nx_snmp_agent_total_bytes_sent += response_packet_ptr -> nx_packet_length; if (request_type == NX_SNMP_ANS1_GET_REQUEST) agent_ptr -> nx_snmp_agent_get_requests++; else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST) agent_ptr -> nx_snmp_agent_getnext_requests++; else if (request_type == NX_SNMP_ANS1_GET_BULK_REQUEST) agent_ptr -> nx_snmp_agent_getbulk_requests++; else if (request_type == NX_SNMP_ANS1_SET_REQUEST) agent_ptr -> nx_snmp_agent_set_requests++; /* Increment the sent packet counter. */ agent_ptr -> nx_snmp_agent_packets_sent++; /* Increment the get responses sent counter. */ agent_ptr -> nx_snmp_agent_getresponse_sent++; /* Send the response packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), response_packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), agent_ptr -> nx_snmp_agent_current_manager_port); /* Check for successful call. */ if (status) { /* Release the packet. */ nx_packet_release(response_packet_ptr); } } #endif /* !NX_SNMP_DISABLE_V1 && !NX_SNMP_DISABLE_V2 */ #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_3_process PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function processes the SNMP v3 request from the manager. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* packet_ptr Pointer to packet containing */ /* the SNMP request */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* _nx_des_encrypt Encrypt bytes */ /* _nx_des_decrypt Decrypt bytes */ /* _nx_des_key_set Set the DES key */ /* _nx_md5_digest_calculate Finalize MD5 calculation */ /* _nx_md5_initialize Initialize MD5 calculation */ /* _nx_md5_update Update MD5 calculation */ /* nx_packet_allocate Allocate response packet */ /* nx_packet_release Release the packet */ /* nx_udp_socket_send Send the UDP packet */ /* _nx_snmp_utility_error_info_get Get the error information */ /* _nx_snmp_utility_error_info_set Set the error information */ /* _nx_snmp_utility_object_data_get Get the object data */ /* _nx_snmp_utility_object_data_set Set the object data */ /* _nx_snmp_utility_object_id_get Get the object ID */ /* _nx_snmp_utility_object_id_set Set the object ID */ /* _nx_snmp_utility_octet_get Get octet string */ /* _nx_snmp_utility_octet_set Set octet string */ /* _nx_snmp_utility_request_id_get Get the request ID */ /* _nx_snmp_utility_request_id_set Set the request ID */ /* _nx_snmp_utility_request_type_get Get the request type */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_sequence_get Get the ANS.1 sequence */ /* _nx_snmp_utility_sequence_set Set the ANS.1 sequence */ /* _nx_snmp_utility_version_get Get the SNMP version */ /* _nx_snmp_utility_version_set Set the SNMP version */ /* _nx_snmp_version_error_response Send SNMP Manager error */ /* _nx_snmp_version_3_discovery_respond Send discovery response */ /* _nx_sha1_digest_calculate Finalize SHA calculation */ /* _nx_sha1_initialize Initialize SHA calculation */ /* _nx_sha1_update Update SHA calculation */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_agent_thread_entry SNMP Agent thread */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), and */ /* improved boundary check, */ /* checked NULL pointer, */ /* resulting in version 6.1.6 */ /* 10-31-2023 Bo Chen Modified comment(s), improved */ /* buffer length verification, */ /* fixed packet double release,*/ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_3_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr) { UINT i, sequence_length, version, request_type, request_length; UINT header_sequence_length, security_sequence_length, pdu_sequence_length; UINT non_repeaters, max_repetitions, current_repetitions, next_object; UINT variable_list_length, variable_length; ULONG request_id; UINT status, length, objects; UCHAR *buffer_ptr; UCHAR *error_ptr, *request_type_ptr, *temp_ptr; UINT response_length; UINT total_variable_length = 0; NX_PACKET *response_packet_ptr; UINT context_engine_size, context_name_size; UCHAR *response_buffer_ptr; UINT response_sequence_length, response_header_length, response_security_length, response_pdu_length, response_type_length; UINT response_variable_list_length, response_variable_length; UCHAR *response_sequence_ptr, *response_header_ptr, *response_security_ptr, *response_pdu_ptr, *response_type_ptr; UCHAR *response_variable_list_ptr, *response_variable_ptr; UCHAR temp_string[NX_SNMP_DIGEST_SIZE]; UINT packet_type; UCHAR *response_encryption_size_ptr = NX_NULL; UCHAR *response_authentication_ptr = NX_NULL, *response_privacy_ptr = NX_NULL; UCHAR *request_authentication_ptr = NX_NULL; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; UINT authenticate_message = NX_FALSE; UINT encrypt_message = NX_FALSE; UCHAR message_sec_level; UINT mask; INT buffer_length; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("\nReceived a SNMPv3 request\n\r"); #endif buffer_length = (INT)(packet_ptr -> nx_packet_length); /* Setup a pointer to the buffer. */ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; /* Pickup the SEQUENCE field. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Pickup the SNMP VERSION field. */ length = _nx_snmp_utility_version_get(buffer_ptr, &version, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /***** Now we are positioned in front of the global header. *****/ /* Pickup the sequence for the header data, which includes the message ID, maximum reply size, flags, and the security model. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &header_sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the message ID */ /********************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_message_id), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the message size */ /********************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_message_size), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the security options */ /********************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_message_security_options), sizeof(agent_ptr -> nx_snmp_agent_v3_message_security_options), &status, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Extracted security options: 0x%x\n\r", agent_ptr -> nx_snmp_agent_v3_message_security_options); #endif /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; mask = NX_SNMP_SECURITY_AUTHORIZE | NX_SNMP_SECURITY_PRIVACY ; /* We want to mask out the reportable bit. */ agent_ptr -> nx_snmp_agent_v3_message_security_options = (UCHAR)(agent_ptr -> nx_snmp_agent_v3_message_security_options & mask); /********************************************************/ /* Get the security type */ /********************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_message_security_type), buffer_length); /* Check for a valid packet. */ if ((length == 0) || (agent_ptr -> nx_snmp_agent_v3_message_security_type != NX_SNMP_USM_SECURITY_MODEL)) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /**** Now we are positioned in front of the security parameters field. ****/ /* Determine if there are security parameters. */ if ((buffer_ptr[0] == NX_SNMP_ANS1_OCTET_STRING) && (buffer_ptr[1])) { /* Position the buffer pointer past the octet string. */ buffer_ptr = buffer_ptr + 2; /* The buffer pointer is moved. Update buffer size */ buffer_length -= 2; /* Pickup the sequence for the security data. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &security_sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the authoritative engine ID */ /********************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_context_engine, sizeof(agent_ptr -> nx_snmp_agent_v3_security_context_engine), &(agent_ptr -> nx_snmp_agent_v3_security_context_engine_size), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the number of engine reboots */ /********************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_security_engine_boots), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the engine boot time */ /********************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the security username */ /********************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_user_name, sizeof(agent_ptr -> nx_snmp_agent_v3_security_user_name), &(agent_ptr -> nx_snmp_agent_v3_security_user_name_size), buffer_length); #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Security name parsed: %s Size: %d\n\r", &agent_ptr -> nx_snmp_agent_v3_security_user_name[0], agent_ptr -> nx_snmp_agent_v3_security_user_name_size); #endif /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Null terminate the User Name. */ agent_ptr -> nx_snmp_agent_v3_security_user_name[agent_ptr -> nx_snmp_agent_v3_security_user_name_size] = 0; /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /********************************************************/ /* Get the security authentication parameter */ /********************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_authentication, sizeof(agent_ptr -> nx_snmp_agent_v3_security_authentication), &(agent_ptr -> nx_snmp_agent_v3_security_authentication_size), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } #ifndef NX_SNMP_NO_SECURITY /* Remember the pointer to the actual NX_SNMP_DIGEST_SIZE byte authorization parameter. */ request_authentication_ptr = buffer_ptr + 2; #endif /* Position to the next field. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; pdu_privacy_ptr = buffer_ptr + 2; /********************************************************/ /* Get the security privacy parameter */ /********************************************************/ /* This is effectively the salt which will be used to unencrypt the PDU. */ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_privacy, sizeof(agent_ptr -> nx_snmp_agent_v3_security_privacy), &(agent_ptr -> nx_snmp_agent_v3_security_privacy_size), buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } } else { /* Check if security option is set, but the security parameter is empty.*/ if (agent_ptr -> nx_snmp_agent_v3_message_security_options) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Position past the empty security parameter field. */ length = 2; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Save the location where the request type is located (after context engine ID and name). */ temp_ptr = buffer_ptr; /********************************************************/ /* Determine if we send a report vs response */ /********************************************************/ /* Check if Engine ID is missing AND the security user name is blank. */ if ((agent_ptr -> nx_snmp_agent_v3_security_context_engine_size == 0) && (agent_ptr -> nx_snmp_agent_v3_security_user_name_size == 0)) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("No Engine ID, no user name, this is a discovery request. \n\r"); #endif agent_ptr -> nx_snmp_agent_unknown_engineid_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM, buffer_length); /* We're done ! Release the received SNMP packet. */ nx_packet_release(packet_ptr); return; } /* Check for a mismatched Engine ID. */ else if ((memcmp(&agent_ptr -> nx_snmp_agent_v3_context_engine[0], &agent_ptr -> nx_snmp_agent_v3_security_context_engine[0], agent_ptr -> nx_snmp_agent_v3_security_context_engine_size) != 0)) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Detect a mismatched (non null) engine ID\n\r"); #endif /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_unknown_engineid_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); /* We will wait for the browser to make a discovery request (blank engine ID). */ return; } /* Check for missing username in the securities header. */ else if (agent_ptr -> nx_snmp_agent_v3_security_user_name_size == 0) { /* Missing user name in the securities field. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Request is missing a securities username\n\r"); #endif /* Update the unknown or missing user name at least. */ agent_ptr -> nx_snmp_agent_unknown_username_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); return; } /* Check for valid username in the security parameters. */ else if (agent_ptr -> nx_snmp_agent_username_process) { status = (agent_ptr -> nx_snmp_agent_username_process)(agent_ptr, agent_ptr -> nx_snmp_agent_v3_security_user_name); if (status != NX_SUCCESS) { /* Unknown user name in the securities field. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Error in username callback: 0x%x\n\r", status); #endif agent_ptr -> nx_snmp_agent_unknown_username_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); return; } /* Engine ID and username appear acceptable, Not a disco request. Check the boot time. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Request has a valid Engine ID and user name. Check the boot and boot time\n\r"); #endif /* Check if both sides have authentication enabled. */ if (((agent_ptr -> nx_snmp_agent_v3_message_security_options & NX_SNMP_SECURITY_AUTHORIZE) >= 1) && (agent_ptr -> nx_snmp_agent_v3_authentication_key != NX_NULL)) { /* They do. So now we must check for mismatched boot data. */ if (agent_ptr -> nx_snmp_agent_v3_context_engine_boots != agent_ptr -> nx_snmp_agent_v3_security_engine_boots) { /* Boot count does not match. */ agent_ptr -> nx_snmp_agent_mismatched_time_count++; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Detect a %d'th mismatch in the boot count. Agent boot count: %d; Browser boot count %d\n\r", agent_ptr -> nx_snmp_agent_mismatched_time_count, agent_ptr -> nx_snmp_agent_v3_context_engine_boots, agent_ptr -> nx_snmp_agent_v3_security_engine_boots); #endif _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Determine if the browser boot time exceeds ours by more than the acceptable limit recommended by RFC 3413 of 150 seconds. */ else if ((agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time > agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time) && ((agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time - agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time) > NX_SNMP_TIME_WINDOW)) { agent_ptr -> nx_snmp_agent_mismatched_time_count++; /* Outside acceptable limits. Do not reply to this request. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Detect %d'th invalid boot time; Agent boot time %d is less than Browser boot time %d\n\r", agent_ptr -> nx_snmp_agent_mismatched_time_count, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time); #endif _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Determine if the our boot time exceeds the browser boot time by more than the acceptable limit recommended by RFC 3413 of 150 seconds. */ else if ((agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time > agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time) && ((agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time - agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time) > NX_SNMP_TIME_WINDOW)) { agent_ptr -> nx_snmp_agent_mismatched_time_count++; /* Outside acceptable limits. Do not reply to this request. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Detect %d'th invalid boot time; Agent boot time %d is greater than Browser boot time %d\n\r", agent_ptr -> nx_snmp_agent_mismatched_time_count, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, agent_ptr -> nx_snmp_agent_v3_security_engine_boot_time); #endif _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME_NUM, buffer_length); /* Release the packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } } } authenticate_message = NX_FALSE; /* Check again if the incoming request specifies authentication. */ if ((agent_ptr -> nx_snmp_agent_v3_message_security_options & NX_SNMP_SECURITY_AUTHORIZE) >= 1) { /* Check if our key is not set up or authentication is not enabled (in which case the authentication key is NULL anyway). */ if (agent_ptr -> nx_snmp_agent_v3_authentication_key == NX_NULL) { /* The request has an unsupported (as in none) authentication level requested. This is an error. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Mismatch of user security levels detected on line %d\n\r", __LINE__); #endif agent_ptr -> nx_snmp_agent_unsupported_sec_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM, buffer_length); /* We're done ! Release the received SNMP packet. */ nx_packet_release(packet_ptr); return; } else if (request_authentication_ptr) { /* Otherwise Ok to process authentication parameter. */ authenticate_message = NX_TRUE; } } /* Check if the incoming message is not requesting authentication. */ else { if (agent_ptr -> nx_snmp_agent_v3_authentication_key != NX_NULL) { /* The request has an unsupported (as in none) authentication level requested. This is an error. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Mismatch of user security levels detected on line %d\n\r", __LINE__); #endif agent_ptr -> nx_snmp_agent_unsupported_sec_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM, buffer_length); /* We're done ! Release the received SNMP packet. */ nx_packet_release(packet_ptr); return; } } /********************************************************/ /* Check Authentication Parameter */ /********************************************************/ /* Are we processing the authentication parameter? */ if (authenticate_message == NX_TRUE) { /* Yes, authentication is required. */ /* Mark the location in the request buffer. */ pdu_auth_parm_ptr = request_authentication_ptr; /* Clear the authentication field in the message. To calculate the digest this must be cleared. Also position past the string and length. */ for (i = 0; i < agent_ptr -> nx_snmp_agent_v3_security_authentication_size; i++) { /* Clear the byte. */ *request_authentication_ptr++ = 0; } /* Now determine which authentication is required. */ if (agent_ptr -> nx_snmp_agent_v3_authentication_key -> nx_snmp_security_key_type == NX_SNMP_MD5_KEY) { /* Copy the base MD5 key into key1. */ for (i = 0; i < NX_SNMP_MD5_DIGEST_SIZE; i++) { /* Copy a byte of the base MD5 key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_authentication_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_MD5_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Calculate prepend Key1. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), packet_ptr -> nx_packet_prepend_ptr, packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1); /* Prepare to calculate the final MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Prepend Key2 to the result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_MD5_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2); } else if (agent_ptr -> nx_snmp_agent_v3_authentication_key -> nx_snmp_security_key_type == NX_SNMP_SHA_KEY) { /* Copy the base SHA key into key1. */ for (i = 0; i < NX_SNMP_SHA_DIGEST_SIZE; i++) { /* Copy a byte of the base SHA key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_authentication_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_SHA_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Calculate prepend Key1. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), packet_ptr -> nx_packet_prepend_ptr, packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1); /* Prepare to calculate the final MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Prepend Key2 to the result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_SHA_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2); } else { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Authentication error. Drop the request. Line %d \n\r", __LINE__); #endif /* Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* At this point, key2 contains the computed digest of the message. If this doesn't match, then the message is invalid. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) { /* Check for a mismatch. */ if (key2[i] != agent_ptr -> nx_snmp_agent_v3_security_authentication[i]) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Authentication mismatch. Drop the request. Line %d \n\r", __LINE__); #endif /* We are not. Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } } } /* Now prepare response message so we can process the variables one by one. */ /* Determine which packet type we allocate based on the destination address type. */ if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Device not enabled for IPv6\n\r"); #endif /* NX_SNMPV3_PRINT_DEBUG_MESSAGE*/ /* Release the packet. */ nx_packet_release(packet_ptr); return; #else packet_type = NX_IPv6_UDP_PACKET; #endif /* FEATURE_NX_IPV6 */ } else { /* Release the original packet. */ nx_packet_release(packet_ptr); return; } /* Allocate the packet for the SNMP response. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &response_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a response packet was allocated. */ if (status) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Response packet allocate error. Status: 0x%x\n\r", status); #endif /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } memset(response_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(response_packet_ptr -> nx_packet_data_end - response_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the response packet. */ response_sequence_length = 0; response_header_length = 0; response_security_length = 0; response_pdu_length = 0; response_type_length = 0; response_variable_list_length = 0; /* Setup a pointer to the response packet's buffer area. */ response_buffer_ptr = response_packet_ptr -> nx_packet_prepend_ptr; /* This is also the response sequence pointer. Remember it since we are going to have to update it later with the actual length of the response. */ response_sequence_ptr = response_buffer_ptr; /* First, write the sequence in the response packet. A zero is written for now. This will be updated later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /********************************************************/ /* Set the Version ID */ /********************************************************/ response_length = _nx_snmp_utility_version_set(response_buffer_ptr, NX_SNMP_VERSION_3, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Save the pointer to the global header. */ response_header_ptr = response_buffer_ptr; /* Write the sequence for the global header in the response packet. A zero is written for now. This will be updated later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /********************************************************/ /* Set the request ID */ /********************************************************/ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_message_id, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Release the original packet. */ nx_packet_release(packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the header sequence length. */ response_header_length = response_header_length + response_length; /********************************************************/ /* Set the maximum message size */ /********************************************************/ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, (NX_SNMP_PACKET_SIZE - NX_UDP_PACKET), response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the header sequence length. */ response_header_length = response_header_length + response_length; /********************************************************/ /* Set the message security options */ /********************************************************/ message_sec_level = agent_ptr -> nx_snmp_agent_v3_message_security_options; response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, (UCHAR *)&message_sec_level, 1, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the header sequence length. */ response_header_length = response_header_length + response_length; /****************************************************/ /* Set the security type */ /****************************************************/ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, NX_SNMP_USM_SECURITY_MODEL, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the header sequence length. */ response_header_length = response_header_length + response_length; /* At this point, we have successfully built the security header. Now, we need to build the security parameters field. */ /* First setup the octet string field. */ response_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; response_buffer_ptr[1] = 0; /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + 2; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + 2; /* Remember the security header length pointer. */ response_security_ptr = response_buffer_ptr; /* Now set the sequence of the USM security parameters. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /****************************************************/ /* Set the Context Engine */ /****************************************************/ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; /****************************************************/ /* Set the Boot Count */ /****************************************************/ if (agent_ptr -> nx_snmp_agent_v3_message_security_options == 0) { /* No security, no time synching, so set boot data to zero. */ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); } else { /* Set the actual boot count. */ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boots, response_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; /****************************************************/ /* Set the Boot Time */ /****************************************************/ if (agent_ptr -> nx_snmp_agent_v3_message_security_options == 0) { /* No security, no time synching, so set boot data to zero. */ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); } else { /* Get the tick count since last boot up. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); /* Set the actual boot count. */ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, response_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; /****************************************************/ /* Set the security user name */ /****************************************************/ /* (Use the security name in the request message) */ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_user_name, agent_ptr -> nx_snmp_agent_v3_security_user_name_size, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; /* Initialize the temporary string to zero. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) temp_string[i] = 0; /****************************************************/ /* Set the security Authentication parameter */ /****************************************************/ /* Now setup the authentication parameter if authentication is enabled, and only if called for. */ if (authenticate_message == NX_TRUE) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Authenticating: initialize auth parameter to zero in response packet. (Line %d) \n\r", __LINE__); #endif /* All set to add an authentication parameter. For now, set to all zeroes. */ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, temp_string, NX_SNMP_DIGEST_SIZE, response_packet_ptr -> nx_packet_data_end); /* Remember the pointer to the actual NX_SNMP_DIGEST_SIZE byte authorization parameter. */ response_authentication_ptr = response_buffer_ptr + 2; } else { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Not Authenticating: set auth parameter to null in response packet. (Line %d) \n\r", __LINE__); #endif /* No security enabled so set this as an empty parameter. */ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, temp_string,0, response_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; encrypt_message = NX_FALSE; /* Check if the incoming request specifies authentication. A discovery request should not have the authentication (or encxryption) flags set. */ if ((agent_ptr -> nx_snmp_agent_v3_message_security_options & NX_SNMP_SECURITY_PRIVACY) >= 2) { /* Check if our key is not set up or privacy is not enabled (in which case the privacy key is NULL anyway). */ if (agent_ptr -> nx_snmp_agent_v3_privacy_key == NX_NULL) { /* The request has an unsupported (as in none) privacy level requested. This is an error. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Mismatch of user security levels (privacy) detected on line %d\n\r", __LINE__); #endif agent_ptr -> nx_snmp_agent_unsupported_sec_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM, buffer_length); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* We're done ! Release the received SNMP packet. */ nx_packet_release(packet_ptr); return; } else { /* Otherwise Ok to process encrypt/decrypt SNMPv3 data. */ encrypt_message = NX_TRUE; } } /* Check if the incoming message is not requesting privacy. */ else { if (agent_ptr -> nx_snmp_agent_v3_privacy_key != NX_NULL) { /* The request has an unsupported (as in none) privacy level requested. This is an error. */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Mismatch of user security levels (privacy) detected on line %d\n\r", __LINE__); #endif agent_ptr -> nx_snmp_agent_unsupported_sec_count++; _nx_snmp_version_3_report_send(agent_ptr, buffer_ptr, NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM, buffer_length); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* We're done ! Release the received SNMP packet. */ nx_packet_release(packet_ptr); return; } } /****************************************************/ /* Set the security Privacy parameter */ /****************************************************/ /* Are we applying encryption to our response? */ if (encrypt_message == NX_FALSE) { /* No, so set the privacy field as an empty parameter. */ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, temp_string,0, response_packet_ptr -> nx_packet_data_end); } else { /* Initialize the 8 character privacy parameter (salt) to all zeros field initially. */ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, temp_string, 8, response_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the original packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } if (encrypt_message == NX_TRUE) { /* Remember the pointer to the actual 8 byte privacy parameter. */ response_privacy_ptr = response_buffer_ptr + 2; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Adjust the security sequence length. */ response_security_length = response_security_length + response_length; /****************************************************/ /* Decrypt the privacy data */ /****************************************************/ /* Check if encryption is required */ if (encrypt_message == NX_TRUE) { response_encryption_size_ptr = 0x0; /* Save the location if we need to return an error message. */ pdu_buffer_ptr = buffer_ptr; status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, response_buffer_ptr, &response_encryption_size_ptr, &response_length, &buffer_length); if (status != NX_SUCCESS) { /* Increment the privacy error counter. */ agent_ptr -> nx_snmp_agent_privacy_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); return; } /* Check the packet length. */ if (buffer_length < 4) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); return; } UINT temp = 0; /* This is typically coded as 0x30 0x29 [or whatever length] 0x04 0x82 or [length] without the multi byte coding. This will also handle 0x81 "multi byte" coding. */ if (buffer_ptr[3] & NX_SNMP_ANS1_MULTI_BYTES) { /* Get the type of length of the string */ temp = (UINT)(buffer_ptr[3] & 0x7F); /* Check the packet length. */ if (((temp != 1) && (temp !=2)) || ((UINT)buffer_length < (4 + temp))) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); return; } if (temp == 2) { pdu_length = (UINT) (*(buffer_ptr+ 4) << 8) | ((UINT) *(buffer_ptr+5)); } else { /* temp == 1. */ pdu_length = *(buffer_ptr + 4); } } else /* Assume one byte */ { pdu_length = *(buffer_ptr + 3); } /* Check the pdu length. */ if (pdu_length > (UINT)(buffer_length - 4 - (INT)temp)) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); return; } /* Set pdu_buffer_ptr. */ pdu_buffer_ptr = buffer_ptr; response_length = 4; } /* Now we can process the request type pointer */ while (temp_ptr < packet_ptr -> nx_packet_append_ptr) { temp_ptr++; /* Check for Get request type. */ if ((*temp_ptr == NX_SNMP_ANS1_GET_REQUEST) || (*temp_ptr == NX_SNMP_ANS1_GET_BULK_REQUEST)|| (*temp_ptr == NX_SNMP_ANS1_GET_NEXT_REQUEST) || (*temp_ptr == NX_SNMP_ANS1_SET_REQUEST)) { break; } } /* Check for invalid packet. */ if (temp_ptr == packet_ptr -> nx_packet_append_ptr) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Save the request type pointer. */ request_type_ptr = temp_ptr; /* Save the response pdu sequence pointer. */ response_pdu_ptr = response_buffer_ptr; /* Move the response buffer pointer. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Increment the number of response sequence bytes. */ response_sequence_length = response_sequence_length + response_length; /****************************************************/ /* Get the PDU sequence length */ /****************************************************/ length = _nx_snmp_utility_sequence_get(buffer_ptr, &pdu_sequence_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /****************************************************/ /* Get the PDU engine ID */ /****************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, sizeof(agent_ptr -> nx_snmp_agent_current_octet_string), &context_engine_size, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /******************************************************************************/ /* SET the PDU Sequence Header if the response is encrypted. */ /******************************************************************************/ /* If the message is encrypted we have to insert an PDU "inner" sequence header. Because we will use the multibyte sequence 0x30 82 xx yy format, we have to update the enclosing sequences (total response length and pdu length and their respective pointers accordingly. */ if (encrypt_message) { /* Move the response buffer pointer. */ response_buffer_ptr = response_buffer_ptr + 4; /* Increment the number of response sequence bytes. */ response_sequence_length = response_sequence_length + 4; /* Increment the response pdu sequence pointer. */ response_pdu_ptr = response_pdu_ptr + 4; /* Increment the pdu length for this sequence header. */ response_pdu_length = response_pdu_length + 4; } /****************************************************/ /* SET the PDU engine ID */ /****************************************************/ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, response_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (response_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response pointer forward. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Increment the sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /****************************************************/ /* Get the PDU engine name */ /****************************************************/ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, sizeof(agent_ptr -> nx_snmp_agent_current_octet_string), &context_name_size, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* The browser uses the context name from the SNMP Agent to confirm the response is coming from the SNMP Agent it sent the request to. They must match. The request ID only matches the request with response. A user may have multiple requests. There may be circumstances where the SNMP Agent only responds with one context name. Don't know what that would be. */ /* Check if the SNMP agent has set a PDU engine name yet. */ if (agent_ptr -> nx_snmp_agent_v3_context_name_size == 0) { /* No it has not, so let's set it here. */ /* First verify that this is a legal length to copy. */ if (context_name_size > NX_SNMP_MAX_CONTEXT_STRING) { /* Invalid length, this will overrun the buffer. */ /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } memcpy(agent_ptr -> nx_snmp_agent_v3_context_name, agent_ptr -> nx_snmp_agent_current_octet_string, context_name_size); /* Use case of memcpy is verified. */ agent_ptr -> nx_snmp_agent_v3_context_name_size = context_name_size; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /****************************************************/ /* SET the PDU engine name */ /****************************************************/ response_length = _nx_snmp_utility_octet_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_name, agent_ptr -> nx_snmp_agent_v3_context_name_size, response_packet_ptr -> nx_packet_data_end); /* Check for a valid packet. */ if (response_length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response pointer forward. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Save the pointer to the response type. */ response_type_ptr = response_buffer_ptr; /* Increment the sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /****************************************************/ /* Get the PDU request type */ /****************************************************/ length = _nx_snmp_utility_request_type_get(buffer_ptr, &request_type, &request_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; agent_ptr -> nx_snmp_agent_request_get_type = NX_FALSE; if ((request_type == NX_SNMP_GET_REQUEST) || (request_type == NX_SNMP_GET_NEXT_REQUEST) || (request_type == NX_SNMP_GET_BULK_REQUEST)) { agent_ptr -> nx_snmp_agent_request_get_type = NX_TRUE; } /****************************************************/ /* SET the PDU request type */ /****************************************************/ response_length = _nx_snmp_utility_request_type_set_multibyte(response_buffer_ptr, NX_SNMP_ANS1_GET_RESPONSE, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /****************************************************/ /* Get the PDU request ID */ /****************************************************/ length = _nx_snmp_utility_request_id_get(buffer_ptr, &request_id, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /****************************************************/ /* SET the PDU request ID */ /****************************************************/ response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, request_id, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Save a pointer to the error string. */ error_ptr = buffer_ptr; /****************************************************/ /* Get the PDU error information */ /****************************************************/ /* This is actually used to derive the GETBULK information in SNMP V3 and above. */ length = _nx_snmp_utility_error_info_get(buffer_ptr, &non_repeaters, &max_repetitions, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } #ifndef NX_DISABLE_PACKET_CHAIN /* Determine if the received packet size is too big. */ if (packet_ptr -> nx_packet_next) { /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, 0); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Done, return to caller. */ return; } #endif /* NX_DISABLE_PACKET_CHAIN */ /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /****************************************************/ /* SET the PDU error information */ /****************************************************/ response_length = _nx_snmp_utility_error_info_set(response_buffer_ptr, 0, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /****************************************************/ /* Get the PDU variable list length */ /****************************************************/ length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_list_length, buffer_length); /* Check for a valid packet. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* At this point we have parsed the incoming SNMP request up to the first variable. */ /* Remember the start of the response's variable list field. */ response_variable_list_ptr = response_buffer_ptr; /* Setup the variable list response. For now, the length will be zero. We will overwrite this with the actual length later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Process the variable binding list, line %d \n\r", __LINE__); #endif /* At this point the response buffer is setup to exactly the same position the SNMP Manager's input buffer is - right before the first variable. We can now walk through the variable list to process each request and place the result in the response buffer. */ objects = 0; next_object = NX_TRUE; current_repetitions = max_repetitions; do { /* Determine if the next object should be retrieved. */ if (next_object) { /* Pickup the first SNMP Variable length. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_length, buffer_length); /* Calculate the total variable size. */ total_variable_length = variable_length + length; if ((length == 0) || (total_variable_length > variable_list_length) || (total_variable_length > (UINT)buffer_length)) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Now pickup the object ID. */ length = _nx_snmp_utility_object_id_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, buffer_length); /* Determine if the object retrieval was successful. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* The buffer pointer is moved by the length. Update buffer size */ buffer_length -= (INT)length; /* Default the value to NULL. */ agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type = 0; /* Determine if a value is present. */ if (length != variable_length) { /* Pickup the value associated with this variable. */ length = _nx_snmp_utility_object_data_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), buffer_length); /* Determine if the object value was successful. */ if (length == 0) { /* Increment the invalid packet error counter. */ agent_ptr -> nx_snmp_agent_invalid_packets++; /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Send an SNMP version error response. The packet will be released in the function. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects+1); /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } else { /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; /* Update the size of the remaining buffer. */ buffer_length -= (INT)length; } } } /* At this point, we are ready to call the appropriate application request handling routine. It is responsible for extracting or placing information in the object data structure. */ if (request_type == NX_SNMP_ANS1_GET_REQUEST) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Call the application's GET routine. */ status = (agent_ptr -> nx_snmp_agent_get_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Call the application's GETNEXT routine. */ status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } else if (request_type == NX_SNMP_ANS1_GET_BULK_REQUEST) { /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Clear the next object flag. */ next_object = NX_FALSE; /* Call the application's GETNEXT routine. */ status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); /* Decrement the number of non-repeaters. */ if (non_repeaters) { /* Decrement the number of non-repeaters. */ non_repeaters--; /* Set the next object flag to move to the next entry of the request. */ next_object = NX_TRUE; } else { /* Decrement the repetitions. */ if (current_repetitions) current_repetitions--; /* Determine if there are more repetitions or if the end of MIB was detected. */ if ((current_repetitions == 0) || (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type == NX_SNMP_ANS1_END_OF_MIB_VIEW)) { /* Reset the current repetition. */ current_repetitions = max_repetitions; /* Set the next object flag to true. */ next_object = NX_TRUE; } } } else if (request_type == NX_SNMP_ANS1_SET_REQUEST) { /* Increment the total number of set variables. */ agent_ptr -> nx_snmp_agent_total_set_variables++; /* Call the application's SET routine. */ status = (agent_ptr -> nx_snmp_agent_set_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data)); } else { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Error processing variable binding items (invalid request type %d). Line %d \n\r", request_type, __LINE__); #endif /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the packet. */ nx_packet_release(packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Check for an error status from the agent's request processing callback routine. */ if (status) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Error processing variable binding get request callback. Line %d \n\r", __LINE__); #endif /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects); /* Done, return to caller. */ return; } /* Determine if the returning object is valid. */ if ((agent_ptr -> nx_snmp_agent_current_octet_string[0] != '1') || (agent_ptr -> nx_snmp_agent_current_octet_string[1] != '.') || (agent_ptr -> nx_snmp_agent_current_octet_string[2] != '3') || (agent_ptr -> nx_snmp_agent_current_octet_string[3] != '.')) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Error processing variable binding. Invalid object from get request callback. Line %d \n\r", __LINE__); #endif /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the packet. */ nx_packet_release(packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Now ensure the returning object type is valid. */ if ((agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_INTEGER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OCTET_STRING) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NULL) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_TIME_TICS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_GAUGE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER64) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_IP_ADDRESS) && #ifdef FEATURE_NX_IPV6 (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) && #endif (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NSAP_ADDRESS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_OBJECT) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_INSTANCE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_END_OF_MIB_VIEW)) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Error processing variable binding (unknown object type). Line %d \n\r", __LINE__); #endif /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Release the packet. */ nx_packet_release(packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Everything is okay, place the object and object data into the response buffer. */ /* Remember the start of the variable response sequence. */ response_variable_ptr = response_buffer_ptr; /* Clear the response variable size. */ response_variable_length = 0; /* Determine if there is enough room in the destination for the variable sequence. */ if ((response_buffer_ptr + 4) >= response_packet_ptr -> nx_packet_data_end) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects); /* Done, return to caller. */ return; } /* Setup the variable response sequence. For now, the length will be zero. We will overwrite this with the actual length later. */ response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the packet. */ nx_packet_release(packet_ptr); /* Release the response packet too. */ nx_packet_release(response_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Place the object into the response buffer. */ response_length = _nx_snmp_utility_object_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Adjust the response variable size. */ response_variable_length = response_variable_length + response_length; /* Insert the object's data into the response buffer. */ response_length = _nx_snmp_utility_object_data_set(response_buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), response_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (response_length == 0) { /* Release the response packet. */ nx_packet_release(response_packet_ptr); /* Call the error handling response routine. This will release the packet */ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ response_buffer_ptr = response_buffer_ptr + response_length; /* Adjust the response sequence length. */ response_sequence_length = response_sequence_length + response_length; /* Increment the pdu length. */ response_pdu_length = response_pdu_length + response_length; /* Adjust the response request type length. */ response_type_length = response_type_length + response_length; /* Adjust the response variable list size. */ response_variable_list_length = response_variable_list_length + response_length; /* Adjust the response variable size. */ response_variable_length = response_variable_length + response_length; /* Now update the response variable sequence with the actual variable length. */ _nx_snmp_utility_sequence_set(response_variable_ptr, response_variable_length, response_packet_ptr -> nx_packet_data_end); /* Only update the source object information if the next object flag is set. */ if (next_object) { /* Decrement the size of the variable list. */ variable_list_length = variable_list_length - total_variable_length; /* Increment the object counter. */ objects++; } } while ((variable_list_length) || (next_object == NX_FALSE)); #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Variable binding processing completed\n\r"); #endif /* At this point, several response fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(response_sequence_ptr, response_sequence_length, response_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(response_header_ptr, response_header_length, response_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(response_security_ptr, response_security_length, response_packet_ptr -> nx_packet_data_end); if (encrypt_message == NX_FALSE) { _nx_snmp_utility_sequence_set_1byte(response_pdu_ptr, response_pdu_length, response_packet_ptr -> nx_packet_data_end); } _nx_snmp_utility_sequence_set(response_variable_list_ptr, response_variable_list_length, response_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(response_type_ptr, NX_SNMP_ANS1_GET_RESPONSE, response_type_length, response_packet_ptr -> nx_packet_data_end); /* Setup the security OCTET string length. */ /* Backup to the OCTET string for the security size. */ response_security_ptr = response_security_ptr - 2; /* Account for the 4 byte Security Sequence field. */ response_security_length = response_security_length + 4; /* Store the security size. */ response_security_ptr[1] = (UCHAR) (response_security_length & 0xFF); /* Determine if privacy is required. If so, encrypt the PDU and setup the response to have an encryption header. */ if (encrypt_message == NX_TRUE) { _nx_snmp_agent_encrypt_pdu(agent_ptr, &response_pdu_length, &response_sequence_length, response_encryption_size_ptr, &response_sequence_ptr, response_packet_ptr -> nx_packet_data_end, &response_buffer_ptr, response_privacy_ptr); } /* Now the response packet's pointers must be setup so it can be sent. */ response_packet_ptr -> nx_packet_length = (ULONG)(response_buffer_ptr - response_packet_ptr -> nx_packet_prepend_ptr); response_packet_ptr -> nx_packet_append_ptr = response_buffer_ptr; if (authenticate_message == NX_TRUE) { /* Yes, authentication is required. */ status = _nx_snmp_agent_add_auth_parameter(agent_ptr, response_packet_ptr, response_authentication_ptr); if (status != NX_SUCCESS) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Authentication error creating authentication parameter. Line %d \n\r", __LINE__); #endif /* Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release the report packet too. */ nx_packet_release(response_packet_ptr); /* Release the original request packet. */ nx_packet_release(packet_ptr); return; } } /* Release the original request packet. */ nx_packet_release(packet_ptr); /* Update various statistics. */ agent_ptr -> nx_snmp_agent_total_bytes_received += packet_ptr -> nx_packet_length; agent_ptr -> nx_snmp_agent_total_bytes_sent += response_packet_ptr -> nx_packet_length; if (request_type == NX_SNMP_ANS1_GET_REQUEST) agent_ptr -> nx_snmp_agent_get_requests++; else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST) agent_ptr -> nx_snmp_agent_getnext_requests++; else if (request_type == NX_SNMP_ANS1_GET_BULK_REQUEST) agent_ptr -> nx_snmp_agent_getbulk_requests++; else if (request_type == NX_SNMP_ANS1_SET_REQUEST) agent_ptr -> nx_snmp_agent_set_requests++; /* Increment the sent packet counter. */ agent_ptr -> nx_snmp_agent_packets_sent++; /* Increment the get responses sent counter. */ agent_ptr -> nx_snmp_agent_getresponse_sent++; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Sending the response to SNMPv3 request on line %d.\n\r", __LINE__); #endif /* Send the response packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), response_packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), agent_ptr -> nx_snmp_agent_current_manager_port); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(response_packet_ptr); } } #endif /* NX_SNMP_DISABLE_V3 */ #ifndef NX_SNMP_DISABLE_V3 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_3_report_send PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function sends reports to the SNMP Manager in response to */ /* received requests. These are usually discovery requests, but can */ /* also be USM violations such as unknown username, unsupported */ /* security level or invalid boot data. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* discovery_respond Reason for report */ /* buffer_length Size of buffer data */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* nx_packet_allocate Allocate response packet */ /* nx_packet_release Release the packet */ /* nx_udp_socket_send Send the UDP packet */ /* _nx_snmp_utility_error_info_set Set the error information */ /* _nx_snmp_utility_octet_set Set the octet string */ /* _nx_snmp_utility_request_id_set Set the request ID */ /* _nx_snmp_utility_request_type_set_multibyte */ /* Set trap request type */ /* _nx_snmp_utility_sequence_set Set the ANS.1 sequence */ /* _nx_snmp_utility_version_set Set the SNMP version */ /* tx_time_get Get the time */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_process Process SNMP v3 request */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* 10-31-2023 Bo Chen Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_3_report_send(NX_SNMP_AGENT *agent_ptr, UCHAR *buffer_ptr, UINT report_respond, INT buffer_length) { UINT status; UINT report_length; NX_PACKET *report_packet_ptr; UCHAR *report_buffer_ptr, *report_sequence_ptr, *report_header_ptr, *report_security_ptr; UCHAR *report_authentication_ptr = NX_NULL, *report_pdu_ptr, *report_type_ptr; UINT report_sequence_length, report_header_length, report_security_length, report_pdu_length, report_type_length; UCHAR *report_encryption_size_ptr = NX_NULL; UCHAR temp_string[NX_SNMP_DIGEST_SIZE]; UINT packet_type; UCHAR *report_variable_list_ptr = NX_NULL; UINT report_variable_length = 0; UINT report_variable_list_length = 0; UCHAR *report_variable_ptr = NX_NULL; ULONG request_id; UINT temp, i; UINT length; UINT request_type; UINT request_length; UINT authenticate, encryption, send_reply; UCHAR report_security_level; #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Processing the report...\n\r"); #endif /* Now prepare report message so we can process the report. */ /* Determine which packet type we allocate based on the destination address type. */ if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V4) { packet_type = NX_IPv4_UDP_PACKET; } else if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V6) { #ifndef FEATURE_NX_IPV6 #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Report: IPv6 not enabled on this device.\n\r"); #endif /* NX_SNMPV3_PRINT_DEBUG_MESSAGE */ return; #else packet_type = NX_IPv6_UDP_PACKET; #endif /* FEATURE_NX_IPV6 */ } else { return; } /* Allocate the packet for the SNMP report. */ status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &report_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT); /* Determine if a report packet was allocated. */ if (status) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Report: error allocating packet 0x%x.\n\r", status); #endif /* Increment the packet allocation error counter. */ agent_ptr -> nx_snmp_agent_allocation_errors++; /* Return to caller. */ return; } memset(report_packet_ptr -> nx_packet_prepend_ptr, 0, (UINT)(report_packet_ptr -> nx_packet_data_end - report_packet_ptr -> nx_packet_prepend_ptr)); /* Initialize the counters required for the length fields of the report packet. */ report_sequence_length = 0; report_header_length = 0; report_security_length = 0; report_pdu_length = 0; report_type_length = 0; /* Setup a pointer to the report packet's buffer area. */ report_buffer_ptr = report_packet_ptr -> nx_packet_prepend_ptr; _nx_snmp_agent_security_response_status(agent_ptr, &authenticate, &encryption, &send_reply); if (send_reply == NX_FALSE) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Report: received request with encryption set. Encryption not enabled on device; no report sent.\n\r"); #endif /* Release the report packet too. */ nx_packet_release(report_packet_ptr); return; } /* We need to set our own security level in case the report security settings differ from the incoming request. */ report_security_level = (UCHAR)authenticate; /* Find out if we need to decrypt this message. */ if (encryption == NX_TRUE) { /* We do. Decrypt the data. We need to get the PDU data, request id and other data. */ status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, NX_NULL, &report_encryption_size_ptr, &report_length, &buffer_length); if (status != NX_SUCCESS) { /* Release the report packet. */ nx_packet_release(report_packet_ptr); return; } } /* Get the PDU sequence location. */ length = _nx_snmp_utility_sequence_get(buffer_ptr, &temp, buffer_length); if (length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } buffer_ptr += length; buffer_length -= (INT)length; /* Get the SNMP v3 PDU context engine field location. */ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, sizeof(agent_ptr -> nx_snmp_agent_current_octet_string), &temp, buffer_length); if (length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } buffer_ptr += length; buffer_length -= (INT)length; /* Get the SNMP v3 PDU context name field location. */ length = _nx_snmp_utility_octet_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, sizeof(agent_ptr -> nx_snmp_agent_current_octet_string), &temp, buffer_length); if (length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } buffer_ptr += length; buffer_length -= (INT)length; /* Pick up the SNMP Request type and location. */ length = _nx_snmp_utility_request_type_get(buffer_ptr, &request_type, &request_length, buffer_length); if (length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } buffer_ptr += length; buffer_length -= (INT)length; /* Get the SNMP Request ID. We need this for our report. */ length = _nx_snmp_utility_request_id_get(buffer_ptr, &request_id, buffer_length); if (length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* This is also the report sequence pointer. Remember it since we are going to have to update it later with the actual length of the report. */ report_sequence_ptr = report_buffer_ptr; /* First, write the sequence in the report packet. A zero is written for now. This will be updated later. */ report_length = _nx_snmp_utility_sequence_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /********************************************************/ /* Set the version ID */ /********************************************************/ report_length = _nx_snmp_utility_version_set(report_buffer_ptr, NX_SNMP_VERSION_3, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Save the pointer to the global header. */ report_header_ptr = report_buffer_ptr; /* Write the sequence for the global header in the report packet. A zero is written for now. This will be updated later. */ report_length = _nx_snmp_utility_sequence_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /********************************************************/ /* Set the request ID */ /********************************************************/ /* This must match the request specified by the discovery request. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_message_id, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the header sequence length. */ report_header_length = report_header_length + report_length; /********************************************************/ /* Set the maximum message size */ /********************************************************/ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, (NX_SNMP_PACKET_SIZE - NX_UDP_PACKET), report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the header sequence length. */ report_header_length = report_header_length + report_length; /********************************************************/ /* Set the security options */ /********************************************************/ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, (UCHAR *)&(report_security_level), 1, report_packet_ptr -> nx_packet_data_end); #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Setting report security level to 0x%x\n\r", report_security_level); #endif /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the header sequence length. */ report_header_length = report_header_length + report_length; /********************************************************/ /* Set the security type */ /********************************************************/ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, NX_SNMP_USM_SECURITY_MODEL, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the header sequence length. */ report_header_length = report_header_length + report_length; /* At this point, we have successfully built the security header. Now, we need to build the security parameters field. */ /* First setup the octet string field. */ report_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; report_buffer_ptr[1] = 0; /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + 2; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + 2; /* Remember the security header pointer. */ report_security_ptr = report_buffer_ptr; report_length = _nx_snmp_utility_sequence_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /********************************************************/ /* Set the context engine */ /********************************************************/ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /********************************************************/ /* Set the boot count */ /********************************************************/ if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM) { /* Set boot count to zero for discovery requests. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); } else { /* Use the current SNMP boot count for all others. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boots, report_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /* Start the time (in ticks) since the previous reboot. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); /********************************************************/ /* Set the boot time */ /********************************************************/ if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM) { /* Set boot time to zero. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); } else { /* Start the time (in ticks) since the previous reboot. */ agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time = (UINT) (tx_time_get()/NX_IP_PERIODIC_RATE); /* Use the current SNMP boot time. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine_boot_time, report_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /********************************************************/ /* Set the security user name */ /********************************************************/ /* Set the security user name as specified in the request message. */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_security_user_name, agent_ptr -> nx_snmp_agent_v3_security_user_name_size, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /* Initialize the temporary string to zero. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) temp_string[i] = 0; /********************************************************/ /* Set the security authentication parameter */ /********************************************************/ if (authenticate == NX_TRUE) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Report: set authentication parameter to zero in report. (Line %d) \n\r", __LINE__); #endif /* All set to add an authentication parameter. For now, set to all zeros. */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, temp_string, NX_SNMP_DIGEST_SIZE, report_packet_ptr -> nx_packet_data_end); /* Remember the pointer to the actual NX_SNMP_DIGEST_SIZE (12) byte authorization parameter. */ report_authentication_ptr = report_buffer_ptr + 2; } else { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Report: set authentication parameter to empty. \n\r"); #endif /* No security enabled so set this as an empty parameter. */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, temp_string, 0, report_packet_ptr -> nx_packet_data_end); } /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /* Set the Privacy Parameter field to empty (encryption/privacy not used in reports). */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, temp_string, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the security sequence length. */ report_security_length = report_security_length + report_length; /* Remember the PDU sequence pointer. */ report_pdu_ptr = report_buffer_ptr; /* Now set the sequence of the PDU. We will replace this sequence type with 'opaque' if encryption is required later. */ report_length = _nx_snmp_utility_sequence_set(report_pdu_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /********************************************************/ /* Set the Context Engine ID */ /********************************************************/ /* The Context Engine ID should be the same as the msgAuthoritativeEngine ID since there is no proxy. */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, agent_ptr -> nx_snmp_agent_v3_context_engine, agent_ptr -> nx_snmp_agent_v3_context_engine_size, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /* Now setup the PDU context name field - it is a null field in the response. */ report_length = _nx_snmp_utility_octet_set(report_buffer_ptr, temp_string, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /* Remember the type field's starting address. */ report_type_ptr = report_buffer_ptr; /* Now setup the message type field. */ report_length = _nx_snmp_utility_request_type_set_multibyte(report_buffer_ptr, NX_SNMP_ANS1_REPORT_REQUEST, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /********************************************************/ /* Set PDU request ID */ /********************************************************/ /* Set the PDU request to zero instead of matching the request if the request is encrypted. Otherwise the request ID must match the request specified by the browser request. */ if (encryption) { request_id = 0; } /* Set the PDU request ID. */ report_length = _nx_snmp_utility_request_id_set(report_buffer_ptr, request_id, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the report type length. */ report_type_length = report_type_length + report_length; /********************************************************/ /* Set the error info */ /********************************************************/ report_length = _nx_snmp_utility_error_info_set(report_buffer_ptr, 0, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the report type length. */ report_type_length = report_type_length + report_length; /* Mark the beginning of the variable list. */ report_variable_list_ptr = report_buffer_ptr; /********************************************************/ /* Set up the variable list */ /********************************************************/ /* Now setup the sequence for the variable list. This is set to zero for now. */ report_length = _nx_snmp_utility_sequence_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the report buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the report sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Adjust the PDU sequence length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the report type length. */ report_type_length = report_type_length + report_length; /* Remember the start of the variable response sequence. */ report_variable_ptr = report_buffer_ptr; /* Clear the response variable size. */ report_variable_length = 0; /* Determine if there is enough room in the destination for the variable sequence. */ if ((report_buffer_ptr + 4) >= report_packet_ptr -> nx_packet_data_end) { /* Release the response packet. */ nx_packet_release(report_packet_ptr); /* Done, return to caller. */ return; } /********************************************************/ /* Initialize variable response sequence to zero */ /********************************************************/ /* We will overwrite this with the actual length later. */ report_length = _nx_snmp_utility_sequence_set(report_buffer_ptr, 0, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Move the response buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the response sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Increment the pdu length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the response request type length. */ report_type_length = report_type_length + report_length; /********************************************************/ /* Adjust the response variable list size. */ /********************************************************/ /* Adjust the response variable list size. */ report_variable_list_length = report_variable_list_length + report_length; /********************************************************/ /* Set the report OID object */ /********************************************************/ if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID_NUM) { /* This report is responding to a discovery request. */ memcpy(&agent_ptr -> nx_snmp_agent_current_octet_string[0], NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID, /* Use case of memcpy is verified. */ sizeof(NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_ENGINEID)); status = _nx_snmp_object_counter_get((VOID *)(&agent_ptr -> nx_snmp_agent_unknown_engineid_count), &agent_ptr -> nx_snmp_agent_current_object_data); } else if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC_NUM) { /* This report is responding to a mismatch ("unsupported") in security level. */ memcpy(&agent_ptr -> nx_snmp_agent_current_octet_string[0], NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC, /* Use case of memcpy is verified. */ sizeof(NX_SNMP_DISCOVERY_RESPONSE_UNSUPPORTED_SEC)); status = _nx_snmp_object_counter_get((VOID *)(&agent_ptr -> nx_snmp_agent_unsupported_sec_count), &agent_ptr -> nx_snmp_agent_current_object_data); } else if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME_NUM) { /* This report is responding to an unknown user name. */ memcpy(&agent_ptr -> nx_snmp_agent_current_octet_string[0], NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME, /* Use case of memcpy is verified. */ sizeof(NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME)); status = _nx_snmp_object_counter_get((VOID *)(&agent_ptr -> nx_snmp_agent_unknown_username_count), &agent_ptr -> nx_snmp_agent_current_object_data); } else if (report_respond == NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME_NUM) { /* This report is responding to invalid boot time or boot count data received. */ memcpy(&agent_ptr -> nx_snmp_agent_current_octet_string[0], NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME, /* Use case of memcpy is verified. */ sizeof(NX_SNMP_DISCOVERY_RESPONSE_MISMATCHED_TIME)); status = _nx_snmp_object_counter_get((VOID *)(&agent_ptr -> nx_snmp_agent_mismatched_time_count), &agent_ptr -> nx_snmp_agent_current_object_data); } else { /* Unknown report type. Abort! */ #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Unknown report parameter %d. Abort report processing. \n\r", report_respond); #endif /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); return; } /* Check for a valid operation. */ if (status != NX_SUCCESS) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the response packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* Increment the total number of get variables. */ agent_ptr -> nx_snmp_agent_total_get_variables++; /* Determine if the returning object is valid. */ if ((agent_ptr -> nx_snmp_agent_current_octet_string[0] != '1') || (agent_ptr -> nx_snmp_agent_current_octet_string[1] != '.') || (agent_ptr -> nx_snmp_agent_current_octet_string[2] != '3') || (agent_ptr -> nx_snmp_agent_current_octet_string[3] != '.')) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Invalid object from application GET routine on line %d.\n\r", __LINE__); #endif /* Release the response packet. */ nx_packet_release(report_packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Now ensure the returning object type is valid. */ if ((agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_INTEGER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OCTET_STRING) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NULL) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_TIME_TICS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_GAUGE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER64) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_IP_ADDRESS) && #ifdef FEATURE_NX_IPV6 (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) && #endif (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NSAP_ADDRESS) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_OBJECT) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_INSTANCE) && (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_END_OF_MIB_VIEW)) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Invalid object type (%d) from application GET routine on line %d.\n\r", agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type, __LINE__); #endif /* Release the response packet. */ nx_packet_release(report_packet_ptr); /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Done, return to caller. */ return; } /* Place the object into the response buffer. */ report_length = _nx_snmp_utility_object_id_set_1byte(report_buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Release the response packet. */ nx_packet_release(report_packet_ptr); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the response sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Increment the pdu length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the response request type length. */ report_type_length = report_type_length + report_length; /* Adjust the response variable list size. */ report_variable_list_length = report_variable_list_length + report_length; /* Adjust the response variable size. */ report_variable_length = report_variable_length + report_length; /* Insert the object's data into the response buffer. */ report_length = _nx_snmp_utility_object_data_set(report_buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Release the response packet. */ nx_packet_release(report_packet_ptr); /* Done, return to caller. */ return; } /* Move the response buffer pointer up. */ report_buffer_ptr = report_buffer_ptr + report_length; /* Adjust the response sequence length. */ report_sequence_length = report_sequence_length + report_length; /* Increment the pdu length. */ report_pdu_length = report_pdu_length + report_length; /* Adjust the response request type length. */ report_type_length = report_type_length + report_length; /* Adjust the response variable list size. */ report_variable_list_length = report_variable_list_length + report_length; /* Adjust the response variable size. */ report_variable_length = report_variable_length + report_length; /* Now update the response variable sequence with the actual variable length. */ report_length = _nx_snmp_utility_sequence_set(report_variable_ptr, report_variable_length, report_packet_ptr -> nx_packet_data_end); /* Check for a valid operation. */ if (report_length == 0) { /* Increment the internal error counter. */ agent_ptr -> nx_snmp_agent_internal_errors++; /* Release the report packet too. */ nx_packet_release(report_packet_ptr); /* Return to caller. */ return; } /* At this point, several report fields need to be updated with actual lengths. */ _nx_snmp_utility_sequence_set(report_sequence_ptr, report_sequence_length, report_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(report_header_ptr, report_header_length, report_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(report_security_ptr, report_security_length, report_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(report_pdu_ptr, report_pdu_length, report_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_sequence_set(report_variable_list_ptr, report_variable_list_length, report_packet_ptr -> nx_packet_data_end); _nx_snmp_utility_request_type_set_multibyte(report_type_ptr, NX_SNMP_ANS1_REPORT_REQUEST, report_type_length, report_packet_ptr -> nx_packet_data_end); /* Now the report packet's pointers must be setup so it can be sent. */ report_packet_ptr -> nx_packet_length = (ULONG)(report_buffer_ptr - report_packet_ptr -> nx_packet_prepend_ptr); report_packet_ptr -> nx_packet_append_ptr = report_buffer_ptr; /********************************************************/ /* Set the authorization parameter */ /********************************************************/ /* Also adjust the length of the security parameters field. */ report_security_ptr = report_security_ptr - 2; /* Adjust the report security length. */ report_security_length = report_security_length + 4; /* Store the security string size. */ report_security_ptr[1] = (UCHAR) (report_security_length & 0xFF); /* Update various statistics. */ agent_ptr -> nx_snmp_agent_reports_sent++; /* Increment the sent packet counter. */ agent_ptr -> nx_snmp_agent_packets_sent++; /* Set the authentication parameter if we have determined it needs to be set, and only if we have a valid user name. (Otherwise there would be no shared key for the other side to check our authentication.)*/ if ((authenticate == NX_TRUE) && (report_respond != NX_SNMP_DISCOVERY_RESPONSE_UNKNOWN_USERNAME_NUM)) { /* Fill in the authentication parameter. */ status = _nx_snmp_agent_add_auth_parameter(agent_ptr, report_packet_ptr, report_authentication_ptr); if (status != NX_SUCCESS) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Authentication error creating authentication parameter. Line %d \n\r", __LINE__); #endif /* Increment the authentication error counter. */ agent_ptr -> nx_snmp_agent_authentication_errors++; /* Release the original request packet. */ nx_packet_release(report_packet_ptr); return; } } #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Sending the report on line %d.\n\r", __LINE__); #endif /* Send the report packet back to the requesting SNMP manager. */ status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), report_packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), agent_ptr -> nx_snmp_agent_current_manager_port); /* Determine if the packet needs to be released. */ if (status) { /* Release packet. */ nx_packet_release(report_packet_ptr); } /* Return to caller. */ return; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_add_auth_parameter PORTABLE C */ /* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function updates the specified SNMPv3 response with an */ /* authentication parameter. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* response_packet_ptr Pointer to reply message data */ /* response_authentication_ptr Pointer to authentication */ /* parameter in the reply */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Successfully added */ /* authentication parameter */ /* */ /* CALLS */ /* */ /* _nx_md5_update Calculate MD5 message digest */ /* _nx_md5_digest_calculate MD5 digest calculated */ /* _nx_md5_initialize Prepare data for MD5 calc */ /* _nx_sha_update Calculate SHa message digest */ /* _nx_sha__digest_calculate SHa digest calculated */ /* _nx_sha__initialize Prepare data for SHa calc */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_process Process SNMP v3 request reply */ /* _nx_snmp_version_3_report_send Process SNMP v3 report */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), */ /* checked NULL pointer, */ /* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_add_auth_parameter(NX_SNMP_AGENT *agent_ptr, NX_PACKET *response_packet_ptr, UCHAR *response_authentication_ptr) { UINT i; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; /* Check if the pointer is NULL. */ if (!response_authentication_ptr) { return(NX_SNMP_UNSUPPORTED_AUTHENTICATION); } /* Determine which authentication is required. */ if ((agent_ptr -> nx_snmp_agent_v3_authentication_key) && ((agent_ptr -> nx_snmp_agent_v3_authentication_key) -> nx_snmp_security_key_type == NX_SNMP_MD5_KEY)) { /* Copy the base MD5 key into key1. */ for (i = 0; i < NX_SNMP_MD5_DIGEST_SIZE; i++) { /* Copy a byte of the base MD5 key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_authentication_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_MD5_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Calculate prepend Key1. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), response_packet_ptr -> nx_packet_prepend_ptr, response_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1); /* Prepare to calculate the final MAC. */ _nx_md5_initialize(&(agent_ptr -> nx_snmp_agent_v3_md5_data)); /* Prepend Key2 to the result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_md5_update(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key1, NX_SNMP_MD5_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_md5_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_md5_data), key2); } else if ((agent_ptr -> nx_snmp_agent_v3_authentication_key) && (agent_ptr -> nx_snmp_agent_v3_authentication_key -> nx_snmp_security_key_type == NX_SNMP_SHA_KEY)) { /* Copy the base SHA key into key1. */ for (i = 0; i < NX_SNMP_SHA_DIGEST_SIZE; i++) { /* Copy a byte of the base SHA key. */ key1[i] = (agent_ptr -> nx_snmp_agent_v3_authentication_key) -> nx_snmp_security_key[i]; } /* Extend key1 to 64 bytes. */ for (i = NX_SNMP_SHA_DIGEST_SIZE; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key1[i] = 0; } /* Create key1 and key2. */ for (i = 0; i < NX_SNMP_DIGEST_WORKING_SIZE; i++) { key2[i] = key1[i] ^ 0x5C; key1[i] = key1[i] ^ 0x36; } /* Calculate the MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Calculate prepend Key1. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the message. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), response_packet_ptr -> nx_packet_prepend_ptr, response_packet_ptr -> nx_packet_length); /* Final calculation of the first pass. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1); /* Prepare to calculate the final MAC. */ _nx_sha1_initialize(&(agent_ptr -> nx_snmp_agent_v3_sha_data)); /* Prepend Key2 to the result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2, NX_SNMP_DIGEST_WORKING_SIZE); /* Calculate the previous result. */ _nx_sha1_update(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key1, NX_SNMP_SHA_DIGEST_SIZE); /* Calculate the final MAC. */ _nx_sha1_digest_calculate(&(agent_ptr -> nx_snmp_agent_v3_sha_data), key2); } else { /* Return to caller. */ return NX_SNMP_UNSUPPORTED_AUTHENTICATION; } /* At this point, key2 contains the computed digest of the message. This needs to be placed in the outgoing message. */ /* Loop to setup the outgoing digest. */ for (i = 0; i < NX_SNMP_DIGEST_SIZE; i++) { /* Copy the next byte of digest into the response buffer. */ response_authentication_ptr[i] = key2[i]; } return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_encrypt_pdu PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function encrypts data pointed to by the response buffer pointer*/ /* and updates the necessary SNMPv3 header size in the header sequence */ /* data. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* [These pointers pertain to the encrypted data to send:] */ /* response_pdu_length Size of the PDU data */ /* response_sequence_length Size of the response sequence */ /* response_encryption_size_ptr Size of encryption data */ /* response_sequence_ptr Pointer to the SNMPv3 sequence*/ /* response_buffer_ptr Pointer to the SNMPv3 response*/ /* response_privacy_ptr Pointer to privacy parameter */ /* response_length Updated size of response */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Data successfully decrypted */ /* NX_SNMP_INVALID_PDU_ENCRYPTION Invalid encrypted data */ /* NX_SNMP_INVALID_ENCRYPT_LENGTH Decryption processing error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_process Process SNMP v3 request reply */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 04-02-2021 Yuxin Zhou Modified comment(s), improved */ /* verification of encryption, */ /* resulting in version 6.1.6 */ /* 10-31-2023 Bo Chen Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_encrypt_pdu(NX_SNMP_AGENT *agent_ptr, UINT *response_pdu_length, UINT *response_sequence_length, UCHAR *response_encryption_size_ptr, UCHAR **response_sequence_ptr, UCHAR *response_sequence_buffer_end, UCHAR **response_buffer_ptr, UCHAR *response_privacy_ptr) { UINT i, j; UINT padding = 0; UCHAR *temp_ptr; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; UINT pdu_sequence_length; UINT adjusted_pdu_length; if (response_pdu_length != NX_NULL) { /* Determine if any padding needs to be applied - account for the four bytes of header information on the PDU. */ padding = ((*response_pdu_length+7)/8)*8 - *response_pdu_length; /* Add the padding the response PDU length and the response sequence length. */ *response_pdu_length = *response_pdu_length + padding; *response_sequence_length = *response_sequence_length + padding; /* Check the buffer. */ if ((UINT)(response_sequence_buffer_end - (*response_buffer_ptr)) < padding) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } /* Use a work pointer to initialize the padding buffer. */ temp_ptr = *response_buffer_ptr; /* Clear the end of the response message... just to be nice! */ for (i = 0; i < padding; i++) { /* Clear byte at the end of the response. */ *temp_ptr++ = 0; } adjusted_pdu_length = *response_pdu_length; } else { /* Check if the pointer is NULL. */ if (!pdu_buffer_ptr) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } /* Set the temp ptr to where the PDU starts in the request packet. */ temp_ptr = pdu_buffer_ptr; adjusted_pdu_length = pdu_length; } /* If this is not for our outgoing response e.g. we are re-encrypting the received packet as part of an error message, use the length from that packet. */ if ((response_encryption_size_ptr == NX_NULL) || (response_pdu_length == NX_NULL)) { pdu_sequence_length = pdu_length; } else { /* We need to set the PDU "inner" sequence length; it comes just after the main PDU sequence header. */ pdu_sequence_length = *response_pdu_length - 4; /* Do not include padding in the inner pdu size! */ pdu_sequence_length = pdu_sequence_length - padding; } if ((response_encryption_size_ptr != NX_NULL) && (response_pdu_length != NX_NULL)) { /* Now we set the PDU "inner" sequence header. Use the multibyte sequence 0x30 82 xx yy format. Note that calling function has already set the pointer for writing encyrpted PDU data past this inner header. */ response_encryption_size_ptr[2] = 0x30; response_encryption_size_ptr[3] = ((UCHAR) 2) | NX_SNMP_ANS1_MULTI_BYTES; response_encryption_size_ptr[4] = (UCHAR) ((pdu_sequence_length >> 8) & 0xFF); response_encryption_size_ptr[5] = (UCHAR) (pdu_sequence_length & 0xFF); /* Update our response buffer pointer. */ *response_buffer_ptr = temp_ptr; response_encryption_size_ptr[0] = (UCHAR) ((*response_pdu_length >> 8) & 0xFF); response_encryption_size_ptr[1] = (UCHAR) (*response_pdu_length & 0xFF); /* Update the total response sequence length again. */ _nx_snmp_utility_sequence_set(*response_sequence_ptr, *response_sequence_length, response_sequence_buffer_end); } /* Increment the salt counter. */ agent_ptr -> nx_snmp_agent_v3_context_salt_counter++; /* Build the salt value for the encryption. */ key1[0] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 24) & 0xFF); key1[1] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 16) & 0xFF); key1[2] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_engine_boots >> 8) & 0xFF); key1[3] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_engine_boots & 0xFF); key1[4] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 24) & 0xFF); key1[5] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 16) & 0xFF); key1[6] = (UCHAR) ((agent_ptr -> nx_snmp_agent_v3_context_salt_counter >> 8) & 0xFF); key1[7] = (UCHAR) (agent_ptr -> nx_snmp_agent_v3_context_salt_counter & 0xFF); if (response_privacy_ptr != NX_NULL) { /* Loop to store the salt in the privacy field. */ for (i = 0; i < 8; i++) { /* Store a byte of the salt. */ response_privacy_ptr[i] = key1[i]; } } /* Setup pointer to the actual PDU. */ if (response_encryption_size_ptr) { temp_ptr = response_encryption_size_ptr + 2; } /* Make the Initialization Vector (IV). */ for (i = 0; i < 8; i++) { key2[i] = (agent_ptr -> nx_snmp_agent_v3_privacy_key)->nx_snmp_security_key[8+i] ^ key1[i]; } /* Setup the DES. */ _nx_des_key_set(&(agent_ptr -> nx_snmp_agent_v3_des_data), (agent_ptr -> nx_snmp_agent_v3_privacy_key)->nx_snmp_security_key); /* Set up the first input block - use the IV for the first block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[i] ^ key2[i]; } /* Encrypt the first 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[0]); /* Loop to encrypt the rest of the PDU. */ j = 8; do { /* Setup the next input block. */ for (i = 0; i < 8; i++) { key1[i] = temp_ptr[j+i] ^ temp_ptr[(j-8)+i]; } /* Encrypt the next 8 bytes. */ _nx_des_encrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &key1[0], &temp_ptr[j]); /* Move the major index forward. */ j = j + 8; } while (j < adjusted_pdu_length); return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_decrypt_pdu PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function decrypts the data pointed to by the buffer pointer */ /* input. If the input response buffer pointer is not null, it will set */ /* up the initial sequence header for the encrypted data around the */ /* msgData header */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* buffer_ptr Pointer to data to decrypt */ /* response_buffer_ptr Pointer to response to send */ /* [If response_buffer_ptr is null, these have no effect:] */ /* response_encryption_size_ptr Pointer to encrypted data in */ /* response */ /* response_length Size of encrypted data so far */ /* buffer_length Size of buffer data */ /* */ /* OUTPUT */ /* */ /* NX_SUCCESS Data successfully decrypted */ /* NX_SNMP_INVALID_PDU_ENCRYPTION Invalid encrypted data */ /* NX_SNMP_INVALID_ENCRYPT_LENGTH Decryption processing error */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_process Process SNMP v3 request reply */ /* _nx_snmp_version_3_report_send PRocess SNMP v3 report */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* 10-31-2023 Bo Chen Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_decrypt_pdu(NX_SNMP_AGENT *agent_ptr, UCHAR **buffer_ptr, UCHAR *response_buffer_ptr, UCHAR **response_encryption_size_ptr, UINT *response_length, INT *buffer_length) { UINT i, j, encrypted_size; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; *response_length = 0; /* Check the buffer length for tag and length. */ if (*buffer_length < 2) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } /* Decrypt the source PDU and setup the response to have an encryption header. */ if ((*buffer_ptr)[0] != NX_SNMP_ANS1_OCTET_STRING) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Encryption error (no privacy key in the request). Line %d \n\r", __LINE__); #endif /* Return to caller. */ return NX_SNMP_INVALID_PDU_ENCRYPTION; } /* Pickup the encrypted PDU size. */ if ((*buffer_ptr)[1] & NX_SNMP_ANS1_MULTI_BYTES) { UINT temp = (*buffer_ptr)[1] & 0x7F; if (temp == 2) { /* Check the buffer length. */ if (*buffer_length < 4) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } /* Two byte octet string. */ encrypted_size = (((UINT) (*buffer_ptr)[2]) << 8) | ((UINT) (*buffer_ptr)[3]); /* Move the buffer pointer up to the actual encrypted PDU contents. */ (*buffer_ptr) += 4; *buffer_length -= 4; } else if (temp == 1) { /* Check the buffer length. */ if (*buffer_length < 3) { return(NX_SNMP_INVALID_PDU_ENCRYPTION); } /* One byte octet string e.g. 0x04 0x81 0xXY */ encrypted_size = (UINT) (*buffer_ptr)[2]; /* Move the buffer pointer up to the actual encrypted PDU contents. */ (*buffer_ptr) += 3; (*buffer_length) -= 3; } else { /* Either null or too big. Invalid size type.*/ return NX_SNMP_ERROR_WRONGENCODING; } } else { /* One byte octet string. */ encrypted_size = (UINT) (*buffer_ptr)[1]; /* Move the buffer pointer up to the actual encrypted PDU contents. */ (*buffer_ptr) += 2; (*buffer_length) -= 2; } /* Check for invalid buffer size. */ if ((INT)encrypted_size > *buffer_length) { /* Invalid buffer size. */ return NX_SNMP_INVALID_PDU_ENCRYPTION; } /* Determine if the length is valid. */ if (encrypted_size % 8) { #ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE NX_SNMPV3_DBG_PRINTF("Encryption error (invalid length).Drop the request. Line %d \n\r", __LINE__); #endif /* Return to caller. */ return NX_SNMP_INVALID_ENCRYPT_LENGTH; } /* Create the Initialization Vector (IV). */ for (i = 0; i < 8; i++) { key2[i] = (agent_ptr -> nx_snmp_agent_v3_privacy_key) -> nx_snmp_security_key[8+i] ^ agent_ptr -> nx_snmp_agent_v3_security_privacy[i]; } /* Initialize the DES component. */ _nx_des_key_set(&(agent_ptr -> nx_snmp_agent_v3_des_data), (agent_ptr -> nx_snmp_agent_v3_privacy_key) -> nx_snmp_security_key); /* Decrypt the first 8 bytes. */ _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), (*buffer_ptr), key1); /* XOR with the IV. */ for (i = 0; i < 8; i++) { /* XOR a byte of the IV. */ key1[i] = key1[i] ^ key2[i]; } /* Loop to decrypt the entire PDU. */ j = 8; do { /* Decrypt the next 8-byte block. */ _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &(*buffer_ptr)[j], key2); /* XOR with the previous encrypted 8-byte block. */ for (i = 0; i < 8; i++) { /* XOR result with previous block. */ key2[i] = key2[i] ^ (*buffer_ptr)[(j-8)+i]; /* Copy a byte of the decrypted block over the source. */ (*buffer_ptr)[(j-8)+i] = key1[i]; /* Save this byte of the new decrypted block. */ key1[i] = key2[i]; } /* Move j up to the next 8 octet sequence. */ j = j + 8; } while (j < encrypted_size); /* Flush the last block out to the buffer. */ for (i = 0; i < 8; i++) { /* Copy a byte of the decrypted block over the source. */ (*buffer_ptr)[(j-8)+i] = key1[i]; } /* If the caller is going to encrypt its response it will send a non null response buffer pointer. */ if (response_buffer_ptr != NX_NULL) { /* Now setup the response buffer to encapsulate the encrypted PDU. Note that the actual encryption will be done after the complete response has been formed. */ response_buffer_ptr[0] = NX_SNMP_ANS1_OCTET_STRING; response_buffer_ptr[1] = 0x82; response_buffer_ptr[2] = 0x00; response_buffer_ptr[3] = 0x00; /* Save the response encryption size pointer. This will be filled in below as we build the message. */ *response_encryption_size_ptr = response_buffer_ptr + 2; *response_length = 4 ; } return NX_SUCCESS; } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_security_response_status PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function determines how to set authentication and privacy */ /* parameters in the USM header. */ /* */ /* INPUT */ /* */ /* agent_ptr Pointer to SNMP agent */ /* */ /* OUTPUT */ /* */ /* *authenticate If true, authentication */ /* parameter should be set */ /* *encryption If true, privacy parameter */ /* should be set */ /* *send_reply If not true, no reply or */ /* report should be sent */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_version_3_report_send PRocess SNMP v3 report */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ VOID _nx_snmp_agent_security_response_status(NX_SNMP_AGENT *agent_ptr, UINT *authenticate, UINT *encryption, UINT *send_reply) { /* Initialize the security parameters to off. */ *encryption = NX_FALSE; *authenticate = NX_FALSE; /* In all but one or two cases we always send a reply. Initialize to true. */ *send_reply = NX_TRUE; /* Check if the incoming request specifies encryption (privacy). */ if ((agent_ptr -> nx_snmp_agent_v3_message_security_options & NX_SNMP_SECURITY_PRIVACY ) >= 2) { /* It is. Check if the SNMP agent has created an encryption key. */ if (agent_ptr -> nx_snmp_agent_v3_privacy_key == NX_NULL) { /* We cannot decrypt the incoming message, (need the request ID), so we cannot send a reply. */ *send_reply = NX_FALSE; return; } /* Ok to apply privacy security level. */ *encryption = NX_TRUE; } else { /* Incoming message does not specify privacy. */ /* Check if the SNMP agent has created an encryption key. */ if (agent_ptr -> nx_snmp_agent_v3_privacy_key == NX_NULL) { /* It has not. The SNMP agent is not configured for privacy here. All good. */ } /* else Same result, indicate no privacy applied to our response. */ } /* Now if the incoming message security level is set for authentication regardless of matching privacy levels. */ if ((agent_ptr -> nx_snmp_agent_v3_message_security_options & NX_SNMP_SECURITY_AUTHORIZE) >= 1) { /* It is. Check if the SNMP agent has created an authentication key. */ if (agent_ptr -> nx_snmp_agent_v3_authentication_key != NX_NULL) { /* Ok to authenticate (even if not going apply privacy). */ *authenticate = NX_TRUE; } /*else Cannot authenticate, but we will still send a reply. */ } return; } #endif /*NX_SNMP_DISABLE_V3 */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_snmp_asn1_tlv_block_parse PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function parses an ASN.1 type-length-value (TLV) block for use */ /* by the SNMP Agent parsing data received from the browser. */ /* */ /* INPUT */ /* */ /* buffer Pointer to data to be parsed */ /* buffer_length Size of input buffer */ /* tlv_type Return block type */ /* tlv_tag_class Return class of the tag */ /* tlv_length Return parsed length */ /* tlv_data Return pointer to block data */ /* header_length Return length of block itself */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* _nx_snmp_utility_object_get Extract data from sender */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_tlv_block_parse(UCHAR *buffer, INT buffer_length, USHORT *tlv_type, USHORT *tlv_tag_class, ULONG *tlv_length, UCHAR **tlv_data, ULONG *header_length) { UINT current_index = 0; USHORT current_tag; ULONG length; ULONG length_bytes; /* Check the buffer length. */ if ((INT)current_index >= buffer_length) { return(NX_SNMP_ERROR_WRONGLENGTH); } current_tag = buffer[current_index]; /* Handle multi-byte encoded tags. */ if ((current_tag & NX_SNMP_ASN_TAG_MULTIBYTE_MASK) == NX_SNMP_ASN_TAG_MULTIBYTE_MASK) { return(NX_SNMP_MULTIBYTE_TAG_UNSUPPORTED); } else { *header_length = 1; } /* Get the class of the tag so we can return it. */ *tlv_tag_class = (USHORT)((current_tag & NX_SNMP_ASN_TAG_CLASS_MASK) >> 6); /* Make sure we have a valid tag class. */ if (*tlv_tag_class == NX_SNMP_ASN_TAG_CLASS_PRIVATE) { /* The tag class is invalid, return error. */ return(NX_SNMP_INVALID_TAG_CLASS); } /* The caller actually handles what happens based on the tag type. */ if (current_tag & NX_SNMP_ASN_TAG_CONSTRUCTED_MASK) { current_tag = current_tag & (USHORT)(~NX_SNMP_ASN_TAG_CONSTRUCTED_MASK); } /* Clear out the class and constructed bits before returning the tag value. */ *tlv_type = current_tag & NX_SNMP_ASN_TAG_MASK; current_index++; /* Check the buffer length. */ if ((INT)current_index >= buffer_length) { return(NX_SNMP_ERROR_WRONGLENGTH); } if (current_tag == NX_SNMP_ANS1_NULL) { /* If tag is NULL, there is no length byte, just a value of zero, */ *tlv_length = 1; /* Set the data pointer and return. */ *tlv_data = &buffer[current_index]; return(NX_SUCCESS); } /* Handle the length. */ length = buffer[current_index]; current_index++; *header_length = *header_length + 1; /* Check for multi-byte length by looking at the top bit of the length byte. */ if (length & 0x80) { /* Multi-byte length: > 127, high bit is set, and lower 7 bits becomes the number of following bytes of *length* so 841 bytes of Value is encoded as 0x82, 0x03, 0x49 (0x82 = 2 bytes of length, 0x0349 = 841). */ /* Mask off top bit to get the number of bytes in length. */ length_bytes = length & 0x7F; length = 0; /* Check for length too big to handle. */ if (length_bytes > 4) { return(NX_SNMP_ASN1_LENGTH_TOO_LONG); } /* Update header length. */ *header_length = *header_length + length_bytes; /* Check the buffer length. */ if ((current_index + length_bytes) < current_index || (current_index + length_bytes) > (UINT)buffer_length) { return(NX_SNMP_ERROR_WRONGLENGTH); } while (length_bytes > 0) { /* Shift length one byte up and add in next byte. */ length <<= 8; length += buffer[current_index]; /* Advance our index by one byte. */ current_index++; length_bytes--; } } else { /* Single-byte length: <= 127 (7 bits), length is the number of bytes of Value */ *tlv_length = length; } /* Set the length to return to caller. */ *tlv_length = length; /* Check the buffer length. */ if (current_index >= (UINT)buffer_length || (length + current_index) < current_index || (length + current_index) > (UINT)buffer_length) { return(NX_SNMP_ERROR_WRONGLENGTH); } /* Now, we can set the tld value */ *tlv_data = &buffer[current_index]; return(NX_SUCCESS); }