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