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