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