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