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