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