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