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