netx/samples/demo_netx_snmp.c
2020-05-11 08:51:44 -06:00

424 lines
10 KiB
C

/* This is a small demo of the NetX SNMP Agent on the high-performance NetX TCP/IP stack.
This demo relies on ThreadX and NetX to show simple SNMP GET/GETNEXT/SET requests on
the SNMP MIB-2 objects. */
#include "tx_api.h"
#include "nx_api.h"
#include "nx_snmp.h"
#include "demo_snmp_helper.h"
#define DEMO_STACK_SIZE 4096
#define AGENT_PRIMARY_ADDRESS IP_ADDRESS(1,2,3,4)
/* Define the ThreadX and NetX object control blocks... */
TX_THREAD thread_0;
NX_PACKET_POOL pool_0;
NX_IP ip_0;
NX_SNMP_AGENT my_agent;
/* To use SNMPv3 features such as authentication and encryption, define NX_SNMP_DISABLE_V3. */
/* Define authentication and privacy keys. */
#ifdef AUTHENTICATION_REQUIRED
NX_SNMP_SECURITY_KEY my_authentication_key;
#endif
#ifdef PRIVACY_REQUIRED
NX_SNMP_SECURITY_KEY my_privacy_key;
#endif
/* Define an error counter variable. */
UINT error_counter = 0;
/* This binds a secondary interfaces to the primary IP network interface
if SNMP is required for required for that interface. */
/* #define MULTI_HOMED_DEVICE */
/* Define function prototypes. A generic ram driver is used in this demo. However to properly
run an SNMP agent demo, a real driver should be substituted. */
VOID thread_agent_entry(ULONG thread_input);
VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
UINT mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
UINT mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
UINT mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
UINT mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username);
VOID mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr);
UCHAR context_engine_id[] = {0x80, 0x00, 0x0d, 0xfe, 0x03, 0x00, 0x11, 0x23, 0x23, 0x44, 0x55};
UINT context_engine_size = 11;
UCHAR context_name[] = {0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c};
UINT context_name_size = 7;
/* Define main entry point. */
int main()
{
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
/* Define what the initial system looks like. */
void tx_application_define(void *first_unused_memory)
{
UCHAR *pointer;
UINT status;
/* Setup the working pointer. */
pointer = (UCHAR *) first_unused_memory;
status = tx_thread_create(&thread_0, "agent thread", thread_agent_entry, 0,
pointer, DEMO_STACK_SIZE,
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
if (status != NX_SUCCESS)
{
return;
}
pointer = pointer + DEMO_STACK_SIZE;
/* Initialize the NetX system. */
nx_system_initialize();
/* Create packet pool. */
status = nx_packet_pool_create(&pool_0, "NetX Packet Pool 0", 2048, pointer, 20000);
if (status != NX_SUCCESS)
{
return;
}
pointer = pointer + 20000;
/* Create an IP instance. */
status = nx_ip_create(&ip_0, "SNMP Agent IP Instance", AGENT_PRIMARY_ADDRESS,
0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
pointer, 4096, 1);
if (status != NX_SUCCESS)
{
return;
}
pointer = pointer + 4096;
/* Enable ARP and supply ARP cache memory for IP Instance 0. */
nx_arp_enable(&ip_0, (void *) pointer, 1024);
pointer = pointer + 1024;
/* Enable ICMP for ping. */
nx_icmp_enable(&ip_0);
/* Enable UPD processing for IP instance. */
nx_udp_enable(&ip_0);
/* Create an SNMP agent instance. */
status = nx_snmp_agent_create(&my_agent, "SNMP Agent", &ip_0, pointer, 4096, &pool_0,
mib2_username_processing, mib2_get_processing, mib2_getnext_processing,
mib2_set_processing);
if (status != NX_SUCCESS)
{
return;
}
pointer = pointer + 4096;
#ifdef NX_SNMP_DISABLE_V3
status = nx_snmp_agent_context_engine_set(&my_agent, context_engine_id, context_engine_size);
if (status != NX_SUCCESS)
{
error_counter++;
}
#endif /* NX_SNMP_DISABLE_V3 */
return;
}
VOID thread_agent_entry(ULONG thread_input)
{
UINT status;
NX_PARAMETER_NOT_USED(thread_input);
/* Allow NetX time to get initialized. */
tx_thread_sleep(NX_IP_PERIODIC_RATE);
#ifdef AUTHENTICATION_REQUIRED
/* Create an authentication key. */
status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)"authpassword", &my_authentication_key);
if (status)
error_counter++;
/* Use the authentication key. */
status = nx_snmp_agent_authenticate_key_use(&my_agent, &my_authentication_key);
if (status)
error_counter++;
#endif
#ifdef PRIVACY_REQUIRED
/* Create a privacy key. */
status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)"privpassword", &my_privacy_key);
if (status)
error_counter++;
/* Use the privacy key. */
status = nx_snmp_agent_privacy_key_use(&my_agent, &my_privacy_key);
if (status)
error_counter++;
#endif
/* Start the SNMP instance. */
status = nx_snmp_agent_start(&my_agent);
if (status)
error_counter++;
}
/* Define the application's GET processing routine. */
UINT mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
{
UINT i;
UINT status;
NX_PARAMETER_NOT_USED(agent_ptr);
/* Loop through the sample MIB to see if we have information for the supplied variable. */
i = 0;
status = NX_SNMP_ERROR;
while (mib2_mib[i].object_name)
{
/* See if we have found the matching entry. */
status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
/* Was it found? */
if (status == NX_SUCCESS)
{
/* Yes it was found. */
break;
}
/* Move to the next index. */
i++;
}
/* Determine if a not found condition is present. */
if (status != NX_SUCCESS)
{
/* The object was not found - return an error. */
return(NX_SNMP_ERROR_NOSUCHNAME);
}
/* Determine if the entry has a get function. */
if (mib2_mib[i].object_get_callback)
{
/* Yes, call the get function. */
status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
}
else
{
/* No get function, return no access. */
status = NX_SNMP_ERROR_NOACCESS;
}
/* Return the status. */
return(status);
}
/* Define the application's GETNEXT processing routine. */
UINT mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
{
UINT i;
UINT status;
NX_PARAMETER_NOT_USED(agent_ptr);
/* Loop through the sample MIB to see if we have information for the supplied variable. */
i = 0;
status = NX_SNMP_ERROR;
while (mib2_mib[i].object_name)
{
/* See if we have found the next entry. */
status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
/* Is the next entry the mib greater? */
if (status == NX_SNMP_NEXT_ENTRY)
{
/* Yes it was found. */
break;
}
/* Move to the next index. */
i++;
}
/* Determine if a not found condition is present. */
if (status != NX_SNMP_NEXT_ENTRY)
{
/* The object was not found - return an error. */
return(NX_SNMP_ERROR_NOSUCHNAME);
}
/* Copy the new name into the object. */
nx_snmp_object_copy(mib2_mib[i].object_name, object_requested);
/* Determine if the entry has a get function. */
if (mib2_mib[i].object_get_callback)
{
/* Yes, call the get function. */
status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
/* Determine if the object data indicates an end-of-mib condition. */
if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
{
/* Copy the name supplied in the mib table. */
nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
}
}
else
{
/* No get function, return no access. */
status = NX_SNMP_ERROR_NOACCESS;
}
/* Return the status. */
return(status);
}
/* Define the application's SET processing routine. */
UINT mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
{
UINT i;
UINT status;
NX_PARAMETER_NOT_USED(agent_ptr);
/* Loop through the sample MIB to see if we have information for the supplied variable. */
i = 0;
status = NX_SNMP_ERROR;
while (mib2_mib[i].object_name)
{
/* See if we have found the matching entry. */
status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
/* Was it found? */
if (status == NX_SUCCESS)
{
/* Yes it was found. */
break;
}
/* Move to the next index. */
i++;
}
/* Determine if a not found condition is present. */
if (status != NX_SUCCESS)
{
/* The object was not found - return an error. */
return(NX_SNMP_ERROR_NOSUCHNAME);
}
/* Determine if the entry has a set function. */
if (mib2_mib[i].object_set_callback)
{
/* Yes, call the set function. */
status = (mib2_mib[i].object_set_callback)(mib2_mib[i].object_value_ptr, object_data);
}
else
{
/* No get function, return no access. */
status = NX_SNMP_ERROR_NOACCESS;
}
/* Return the status. */
return(status);
}
/* Define the application's authentication routine. */
UINT mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username)
{
NX_PARAMETER_NOT_USED(agent_ptr);
NX_PARAMETER_NOT_USED(username);
/* Update MIB-2 objects. In this example, it is only the SNMP objects. */
mib2_variable_update(&ip_0, &my_agent);
/* No authentication is done, just return success! */
return(NX_SUCCESS);
}
/* Define the application's update routine. */
VOID mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr)
{
NX_PARAMETER_NOT_USED(ip_ptr);
NX_PARAMETER_NOT_USED(agent_ptr);
/* This section is for updating the snmp parameters defined in the MIB table definition files. */
}