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