1 /* This NetX test concentrates on the basic SNMPv2 operation.  The 'manager' sends
2    three requests, Get, Get Next, and Get Bulk, and the SNMP agent responds.  A successful
3    result means the Agent received and sent the expected number of messages, and no
4    internal SNMP errors were encountered.
5 
6    The MIB database is defined in demo_snmp_helper.h */
7 
8 
9 #include   "tx_api.h"
10 #include   "nx_api.h"
11 #include   "nxd_snmp.h"
12 #include "small_mib_helper.h" // was demo_snmp_helper.h in the old MIB
13 
14 extern void    test_control_return(UINT);
15 
16 #if !defined(NX_DISABLE_IPV4)
17 
18 #define     DEMO_STACK_SIZE         2048
19 
20 extern MIB_ENTRY   mib2_mib[];
21 
22 static UINT    v2query_response_complete = NX_FALSE;
23 
24 static UINT    v2_mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
25 static UINT    v2_mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
26 static UINT    v2_mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
27 static UINT    v2_mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username);
28 static VOID    v2_mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr);
29 
30 #define     QUERY_COUNT             3
31 
32 /* Define the ThreadX and NetX object control blocks...  */
33 
34 static TX_THREAD               thread_agent;
35 static TX_THREAD               thread_manager;
36 static NX_SNMP_AGENT           v2_my_agent;
37 static NX_PACKET_POOL          v2_pool_0;
38 static NX_IP                   agent_ip;
39 static NX_IP                   manager_ip;
40 
41 static NX_UDP_SOCKET           snmp_manager_socket;
42 
43 #define SNMP_MANAGER_ADDRESS   IP_ADDRESS(10,0,0,1)
44 #define SNMP_AGENT_ADDRESS     IP_ADDRESS(10,0,0,10)
45 
46 
47 /* Define the counters used in the demo application...  */
48 
49 static UINT                    status;
50 static ULONG                   error_counter;
51 
52 
53 /* Define thread prototypes.  */
54 
55 static void    thread_0_entry(ULONG thread_input);
56 static void    thread_1_entry(ULONG thread_input);
57 extern void    _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
58 static void    snmp_test_initialize();
59 
60 
61 /* Send SNMP manager query.  */
62 static UINT    nx_snmp_query_packet_send(NX_UDP_SOCKET *snmp_manager_socket, UINT request_id, UINT packet_number);
63 
64 extern char simple_get_query_pkt[82];
65 extern int  simple_get_query_size;
66 extern char simple_get_next_query_pkt[82];
67 extern int  simple_get_next_query_size;
68 #if 1
69 extern char simple_get_bulk_query_pkt[76];
70 extern int  simple_get_bulk_query_size;
71 #endif
72 
73 
74 typedef struct SNMP_QUERY_STRUCT
75 {
76     char          *snmp_query_pkt_data;
77     int           snmp_query_pkt_size;
78 } SNMP_QUERY;
79 
80 
81 static SNMP_QUERY       snmp_query[QUERY_COUNT];
82 
83 
84 #ifdef CTEST
test_application_define(void * first_unused_memory)85 VOID test_application_define(void *first_unused_memory)
86 #else
87 void    netx_snmp_basic_v2_test_application_define(void *first_unused_memory)
88 #endif
89 {
90 
91 CHAR    *pointer;
92 
93     /* Setup the working pointer.  */
94     pointer =  (CHAR *) first_unused_memory;
95 
96     /* Create the SNMP agent thread.  */
97     tx_thread_create(&thread_agent, "Agent thread", thread_0_entry, 0,
98                       pointer, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
99 
100     pointer =  pointer + DEMO_STACK_SIZE;
101 
102     /* Create the SNMP Manager thread.  */
103     tx_thread_create(&thread_manager, "Manager thread", thread_1_entry, 0,
104                      pointer, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
105 
106     pointer =  pointer + DEMO_STACK_SIZE;
107 
108 
109     /* Initialize the NetX system.  */
110     nx_system_initialize();
111 
112     /* Create a packet pool.  */
113     status =  nx_packet_pool_create(&v2_pool_0, "NetX Main Packet Pool", 1000, pointer, 4096);
114     pointer = pointer + 4096;
115 
116     /* Create an IP instance.  */
117     status += nx_ip_create(&agent_ip, "Agent IP", SNMP_AGENT_ADDRESS, 0xFFFFFF00UL, &v2_pool_0, _nx_ram_network_driver_1500,
118                     pointer, 2048, 1);
119     pointer =  pointer + 2048;
120 
121     /* Create another IP instance.  */
122     status += nx_ip_create(&manager_ip, "Manager IP", SNMP_MANAGER_ADDRESS, 0xFFFFFF00UL, &v2_pool_0, _nx_ram_network_driver_1500,
123                     pointer, 2048, 1);
124     pointer =  pointer + 2048;
125 
126     /* Check for IP create errors.  */
127     if (status)
128     {
129 
130         error_counter++;
131     }
132 
133     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
134     status =  nx_arp_enable(&agent_ip, (void *) pointer, 1024);
135     pointer = pointer + 1024;
136 
137     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
138     status +=  nx_arp_enable(&manager_ip, (void *) pointer, 1024);
139     pointer = pointer + 1024;
140 
141     /* Check for ARP enable errors.  */
142     if (status)
143     {
144         error_counter++;
145     }
146 
147     /* Enable UDP traffic.  */
148     status =  nx_udp_enable(&agent_ip);
149     status += nx_udp_enable(&manager_ip);
150 
151     /* Check for UDP enable errors.  */
152     if (status)
153     {
154         error_counter++;
155     }
156 
157         /* Create an SNMP agent instance.  */
158     status = nx_snmp_agent_create(&v2_my_agent, "SNMP Agent", &agent_ip, pointer, 4096, &v2_pool_0,
159                          v2_mib2_username_processing, v2_mib2_get_processing,
160                          v2_mib2_getnext_processing, v2_mib2_set_processing);
161 
162     if (status)
163     {
164         error_counter++;
165     }
166 
167     return;
168 }
169 
170 
171 
172 /* Define the test threads.  */
173 
thread_0_entry(ULONG thread_input)174 static void    thread_0_entry(ULONG thread_input)
175 {
176 
177 UINT status;
178 
179     printf("NetX Test:   SNMP Basic V2 Test........................................");
180 
181 
182     if (error_counter)
183     {
184         printf("ERROR!\n");
185         test_control_return(1);
186     }
187 
188     /* Start the SNMP instance.  */
189     status = nx_snmp_agent_start(&v2_my_agent);
190 
191     /* Return the test result.  */
192     if (status)
193     {
194        error_counter++;
195     }
196 
197     /* Wait for the 'manager' to finish querying the Agent. */
198     while (v2query_response_complete == NX_FALSE)
199     {
200         tx_thread_sleep(100);
201     }
202 
203     /* Check for correct internal counters of SNMP processing. */
204     if ((v2_my_agent.nx_snmp_agent_get_requests != 1) ||
205         (v2_my_agent.nx_snmp_agent_getnext_requests != 1) ||
206         (v2_my_agent.nx_snmp_agent_getbulk_requests != 1) ||
207         //(v2_my_agent.nx_snmp_agent_total_get_variables != 8) ||
208         (v2_my_agent.nx_snmp_agent_packets_received != 3) ||
209         (v2_my_agent.nx_snmp_agent_packets_sent != 3) ||
210         (v2_my_agent.nx_snmp_agent_getresponse_sent != 3))
211     {
212         error_counter++;
213 
214         printf("ERROR1!\n");
215         test_control_return(1);
216     }
217 
218     /* Check for errors processing the requests. */
219     if (v2_my_agent.nx_snmp_agent_invalid_packets ||
220         v2_my_agent.nx_snmp_agent_internal_errors ||
221         v2_my_agent.nx_snmp_agent_allocation_errors  ||
222         v2_my_agent.nx_snmp_agent_request_errors  ||
223         v2_my_agent.nx_snmp_agent_too_big_errors  ||
224         v2_my_agent.nx_snmp_agent_username_errors ||
225         v2_my_agent.nx_snmp_agent_unknown_requests ||
226         v2_my_agent.nx_snmp_agent_no_such_name_errors)
227     {
228 
229         error_counter++;
230 
231         printf("ERROR2!\n");
232         test_control_return(1);
233     }
234 
235     if (error_counter)
236     {
237         printf("ERROR!\n");
238         test_control_return(1);
239     }
240     else
241     {
242         printf("SUCCESS!\n");
243         test_control_return(0);
244     }
245 
246     return;
247 
248 }
249 
250 /* SNMP Manager thread */
thread_1_entry(ULONG thread_input)251 static void    thread_1_entry(ULONG thread_input)
252 {
253 
254 NX_PACKET   *agent_packet;
255 UINT        port;
256 UINT        i;
257 USHORT      request_id = 1;
258 
259     /* Let the agent get set up first! */
260     tx_thread_sleep(50);
261 
262     /* Create a UDP socket act as the DNS server.  */
263     status = nx_udp_socket_create(&manager_ip, &snmp_manager_socket, "Manager Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
264 
265     /* Check status.  */
266     if (status)
267     {
268         error_counter++;
269         v2query_response_complete = NX_TRUE;
270     }
271 
272     /* Bind the UDP socket to the IP port.  */
273     status =  nx_udp_socket_bind(&snmp_manager_socket, 161, 200);
274 
275 
276     /* Check status.  */
277     if (status)
278     {
279         error_counter++;
280         v2query_response_complete = NX_TRUE;
281     }
282 
283     /* Load the test data up. */
284     snmp_test_initialize();
285 
286     /* Send SNMP queries to the agent.  */
287     for (i = 0; i < QUERY_COUNT; i++ )
288     {
289 
290         /* Send the SNMP manager query packet.  */
291         status = nx_snmp_query_packet_send(&snmp_manager_socket, request_id,  i);
292 
293         /* Check status.  */
294         if (status)
295         {
296 
297             error_counter++;
298             v2query_response_complete = NX_TRUE;
299             break;
300         }
301 
302         /* Receive the SNMP agent response.  */
303         status =  nx_udp_socket_receive(&snmp_manager_socket, &agent_packet, 200);
304 
305         /* Check status.  */
306         if (status)
307         {
308 
309             error_counter++;
310             v2query_response_complete = NX_TRUE;
311 
312             printf("ERROR3!\n");
313             test_control_return(1);
314             //break;
315         }
316 
317         /* Get the SNMP agent UDP port.  */
318         status = nx_udp_packet_info_extract(agent_packet, NX_NULL ,NX_NULL, &port, NX_NULL);
319 
320         /* Check status.  */
321 
322         if (status)
323         {
324 
325             error_counter++;
326             v2query_response_complete = NX_TRUE;
327 
328             printf("ERROR4!\n");
329             test_control_return(1);
330             //break;
331         }
332 
333         /* Release the packet.  */
334         nx_packet_release(agent_packet);
335 
336         request_id++;
337     }
338 
339     /* Indicate the test is complete. */
340     v2query_response_complete = NX_TRUE;
341 
342     /* Unbind the UDP socket.  */
343      nx_udp_socket_unbind(&snmp_manager_socket);
344 
345     /* Delete the UDP socket.  */
346     nx_udp_socket_delete(&snmp_manager_socket);
347 
348     return;
349 }
350 
351 
nx_snmp_query_packet_send(NX_UDP_SOCKET * snmp_manager_socket,UINT snmp_request_id,UINT packet_number)352 static UINT   nx_snmp_query_packet_send(NX_UDP_SOCKET *snmp_manager_socket, UINT snmp_request_id, UINT packet_number)
353 {
354 UINT        status;
355 NX_PACKET   *response_packet;
356 
357 
358     /* Allocate a response packet.  */
359     status =  nx_packet_allocate(&v2_pool_0, &response_packet, NX_UDP_PACKET, 200);
360 
361     /* Check status.  */
362     if (status)
363     {
364 
365         error_counter++;
366         return(1);
367     }
368 
369     memset(response_packet -> nx_packet_prepend_ptr, 0, (response_packet -> nx_packet_data_end - response_packet -> nx_packet_prepend_ptr));
370 
371     /* Write the SMTP response messages into the packet payload!  */
372     memcpy(response_packet -> nx_packet_prepend_ptr,
373            snmp_query[packet_number].snmp_query_pkt_data,
374            snmp_query[packet_number].snmp_query_pkt_size);
375 
376     /* Adjust the write pointer.  */
377     response_packet -> nx_packet_length =  snmp_query[packet_number].snmp_query_pkt_size;
378     response_packet -> nx_packet_append_ptr =  response_packet -> nx_packet_prepend_ptr + response_packet -> nx_packet_length;
379 
380     /* Send the UDP packet with the correct port.  */
381     status =  nx_udp_socket_send(snmp_manager_socket, response_packet, IP_ADDRESS(10, 0, 0, 10), 161);
382 
383     /* Check the status.  */
384     if (status)
385     {
386 
387         error_counter++;
388         nx_packet_release(response_packet);
389     }
390 
391     return status;
392 }
393 
394 
snmp_test_initialize()395 static void  snmp_test_initialize()
396 {
397 
398     snmp_query[0].snmp_query_pkt_data = &simple_get_query_pkt[0];
399     snmp_query[0].snmp_query_pkt_size = simple_get_query_size;
400 
401 
402     snmp_query[1].snmp_query_pkt_data = &simple_get_next_query_pkt[0];
403     snmp_query[1].snmp_query_pkt_size = simple_get_next_query_size;
404 #if 1
405     snmp_query[2].snmp_query_pkt_data = &simple_get_bulk_query_pkt[0];
406     snmp_query[2].snmp_query_pkt_size = simple_get_bulk_query_size;
407 #endif
408 }
409 
410 
411 /* Define the application's GET processing routine.  */
412 
v2_mib2_get_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)413 UINT    v2_mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
414 {
415 
416 UINT    i;
417 UINT    status;
418 
419 
420 
421     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
422     i =  0;
423     status =  NX_SNMP_ERROR;
424     while (mib2_mib[i].object_name)
425     {
426 
427         /* See if we have found the matching entry.  */
428         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
429 
430         /* Was it found?  */
431         if (status == NX_SUCCESS)
432         {
433 
434             /* Yes it was found.  */
435             break;
436         }
437 
438         /* Move to the next index.  */
439         i++;
440     }
441 
442     /* Determine if a not found condition is present.  */
443     if (status != NX_SUCCESS)
444     {
445 
446         /* The object was not found - return an error.  */
447         return(NX_SNMP_ERROR_NOSUCHNAME);
448     }
449 
450     if (mib2_mib[i].object_get_octet_callback)
451     {
452 
453           /* Call the get octet function (has a length input).  */
454           status =  (mib2_mib[i].object_get_octet_callback)(mib2_mib[i].object_value_ptr, object_data, mib2_mib[i].length);
455     }
456     else if (mib2_mib[i].object_get_callback)
457     {
458 
459         /* Call the get function.  */
460         status =  (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
461     }
462     else
463     {
464 
465         /* No get function, return no access.  */
466         status =  NX_SNMP_ERROR_NOACCESS;
467         error_counter++;
468 
469         printf("ERROR5!\n");
470         test_control_return(1);
471     }
472 
473     /* Return the status.  */
474     return(status);
475 }
476 
477 
478 /* Define the application's GETNEXT processing routine.  */
479 
v2_mib2_getnext_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)480 UINT    v2_mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
481 {
482 
483 UINT    i;
484 UINT    status;
485 
486 
487     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
488     i =  0;
489     status =  NX_SNMP_ERROR;
490     while (mib2_mib[i].object_name)
491     {
492 
493         /* See if we have found the next entry.  */
494         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
495 
496         /* Is the next entry the mib greater?  */
497         if (status == NX_SNMP_NEXT_ENTRY)
498         {
499 
500             /* Yes it was found.  */
501             break;
502         }
503 
504         /* Move to the next index.  */
505         i++;
506     }
507 
508     /* Determine if a not found condition is present.  */
509     if (status != NX_SNMP_NEXT_ENTRY)
510     {
511 
512         /* The object was not found - return an error.  */
513         //return(NX_SNMP_ERROR_NOSUCHNAME);
514 
515         printf("ERROR6!\n");
516         test_control_return(1);
517     }
518 
519     /* Copy the new name into the object.  */
520     nx_snmp_object_copy(mib2_mib[i].object_name, object_requested);
521 
522     /* Call either the get octet or get callback, depending what is registered in the table entry. */
523      if (mib2_mib[i].object_get_octet_callback)
524     {
525 
526           /* Call the get octet function (has a length input).  */
527           status =  (mib2_mib[i].object_get_octet_callback)(mib2_mib[i].object_value_ptr, object_data, mib2_mib[i].length);
528 
529          /* Determine if the object data indicates an end-of-mib condition.  */
530         if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
531         {
532 
533             /* Copy the name supplied in the mib table.  */
534             nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
535         }
536     }
537     else if (mib2_mib[i].object_get_callback)
538     {
539 
540         /* Call the get function.  */
541         status =  (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
542 
543          /* Determine if the object data indicates an end-of-mib condition.  */
544         if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
545         {
546 
547             /* Copy the name supplied in the mib table.  */
548             nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
549         }
550     }
551     else
552     {
553 
554         /* No get function, return no access.  */
555         status =  NX_SNMP_ERROR_NOACCESS;
556         error_counter++;
557 
558         printf("ERROR7!\n");
559         test_control_return(1);
560     }
561 
562     /* Return the status.  */
563     return(status);
564 }
565 
566 
567 /* Define the application's SET processing routine.  */
568 
v2_mib2_set_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)569 UINT    v2_mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
570 {
571 
572 UINT    i;
573 UINT    status;
574 
575 
576     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
577     i =  0;
578     status =  NX_SNMP_ERROR;
579     while (mib2_mib[i].object_name)
580     {
581 
582         /* See if we have found the matching entry.  */
583         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
584 
585         /* Was it found?  */
586         if (status == NX_SUCCESS)
587         {
588 
589             /* Yes it was found.  */
590             break;
591         }
592 
593         /* Move to the next index.  */
594         i++;
595     }
596 
597     /* Determine if a not found condition is present.  */
598     if (status != NX_SUCCESS)
599     {
600 
601         /* The object was not found - return an error.  */
602         return(NX_SNMP_ERROR_NOSUCHNAME);
603     }
604 
605 
606     /* Determine if the entry has a set function.  */
607     if (mib2_mib[i].object_set_callback)
608     {
609 
610         /* Yes, call the set function.  */
611         status =  (mib2_mib[i].object_set_callback)(mib2_mib[i].object_value_ptr, object_data);
612     }
613     else
614     {
615 
616         /* No get function, return no access.  */
617         status =  NX_SNMP_ERROR_NOACCESS;
618     }
619 
620 
621     /* Return the status.  */
622     return(status);
623 }
624 
625 /* Create an error code if matching user not found. */
626 #define USER_NOT_FOUND 1
627 
628 /* Define the username callback routine routine. Usernames should be
629    associated with permissions (public or private string) and what version
630    of SNMP the user is configured for. The username callback should verify
631    the incoming username MIB access permissions.  */
v2_mib2_username_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * username)632 UINT  v2_mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username)
633 {
634 
635     v2_mib2_variable_update(&agent_ip, &v2_my_agent);
636 
637     return NX_SUCCESS;
638 
639 }
640 
641 extern ULONG    sysUpTime;
642 /* Define the application's update routine.  */
643 
v2_mib2_variable_update(NX_IP * ip_ptr,NX_SNMP_AGENT * agent_ptr)644 VOID  v2_mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr)
645 {
646 
647     /* Update the snmp parameters.  */
648     sysUpTime =                 tx_time_get();
649 }
650 #else
651 
652 #ifdef CTEST
test_application_define(void * first_unused_memory)653 VOID test_application_define(void *first_unused_memory)
654 #else
655 void    netx_snmp_basic_v2_test_application_define(void *first_unused_memory)
656 #endif
657 {
658 
659     /* Print out test information banner.  */
660     printf("NetX Test:   SNMP Basic V2 Test........................................N/A\n");
661 
662     test_control_return(3);
663 }
664 #endif
665