1 /* This NetX test concentrates on the basic SNMPv1 operation. The 'manager' sends
2 a request for an unknown item ("oid"). The SNMP agent should not responds, but
3 set an internal error and be able to respond to the next request.
4
5 The MIB database is defined in demo_snmp_helper.h */
6
7
8 #include "tx_api.h"
9 #include "nx_api.h"
10 #include "nxd_snmp.h"
11 #include "nx_udp.h"
12 #include "small_mib_helper.h"
13
14 extern void test_control_return(UINT);
15
16 #if !defined(NX_DISABLE_IPV4) && !defined(NX_DISABLE_FRAGMENTATION)
17
18 #define DEMO_STACK_SIZE 4096
19
20 extern MIB_ENTRY mib2_mib[];
21
22 static UINT mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
23 static UINT mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
24 static UINT mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
25 static UINT mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username);
26 static VOID mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr);
27
28 /* Define the ThreadX and NetX object control blocks... */
29
30 static TX_THREAD thread_agent;
31 static NX_SNMP_AGENT my_agent;
32 static NX_PACKET_POOL pool_0;
33 static NX_IP agent_ip;
34
35 #define SNMP_AGENT_ADDRESS IP_ADDRESS(10, 128, 16, 17)
36
37
38 /* Define the counters used in the demo application... */
39
40 static UINT status;
41 static ULONG error_counter;
42 static ULONG snmp_stack[DEMO_STACK_SIZE / sizeof(ULONG)];
43
44
45 /* Define thread prototypes. */
46
47 static void thread_0_entry(ULONG thread_input);
48 static void thread_1_entry(ULONG thread_input);
49 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
50 static void snmp_test_initialize();
51
52 /* Inject SNMP manager query. */
53 static VOID packet_inject(UCHAR *data_ptr, UINT data_size);
54
55
56 extern unsigned char v1_buffer_overwrite_packet1[1514];
57 extern int v1_buffer_overwrite_packet1_size;
58 extern unsigned char v1_buffer_overwrite_packet2[54];
59 extern int v1_buffer_overwrite_packet2_size;
60 extern unsigned char v1_buffer_overwrite_packet3[54];
61 extern int v1_buffer_overwrite_packet3_size;
62 extern unsigned char v1_buffer_overwrite_packet4[];
63 extern int v1_buffer_overwrite_packet4_size;
64
65 #define QUERY_COUNT 4
66
67 typedef struct SNMP_QUERY_STRUCT
68 {
69 char *snmp_query_pkt_data;
70 int snmp_query_pkt_size;
71 } SNMP_QUERY;
72
73
74 static SNMP_QUERY snmp_query[QUERY_COUNT];
75
76
77 #ifdef CTEST
test_application_define(void * first_unused_memory)78 VOID test_application_define(void *first_unused_memory)
79 #else
80 void netx_snmp_v1_buffer_overwrite_test_application_define(void *first_unused_memory)
81 #endif
82 {
83
84 CHAR *pointer;
85
86 /* Setup the working pointer. */
87 pointer = (CHAR *) first_unused_memory;
88
89 /* Create the SNMP agent thread. */
90 tx_thread_create(&thread_agent, "Agent thread", thread_0_entry, 0,
91 pointer, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
92
93 pointer = pointer + DEMO_STACK_SIZE;
94
95 /* Initialize the NetX system. */
96 nx_system_initialize();
97
98 /* Create a packet pool. */
99 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, pointer, (sizeof(NX_PACKET) + 1536) * 10);
100 pointer = pointer + (sizeof(NX_PACKET) + 1536) * 10;
101
102 /* Create an IP instance. */
103 status += nx_ip_create(&agent_ip, "Agent IP", SNMP_AGENT_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
104 pointer, 2048, 1);
105 pointer = pointer + 2048;
106
107 /* Check for IP create errors. */
108 if (status)
109 {
110 error_counter++;
111 }
112
113 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
114 status = nx_arp_enable(&agent_ip, (void *) pointer, 1024);
115 pointer = pointer + 1024;
116
117 /* Check for ARP enable errors. */
118 if (status)
119 {
120 error_counter++;
121 }
122
123 /* Enable UDP traffic. */
124 status = nx_udp_enable(&agent_ip);
125
126 /* Check for UDP enable errors. */
127 if (status)
128 {
129 error_counter++;
130 }
131
132 status = nx_ip_fragment_enable(&agent_ip);
133 if (status)
134 {
135 error_counter++;
136 }
137 }
138
139 /* Define the test threads. */
140
thread_0_entry(ULONG thread_input)141 static void thread_0_entry(ULONG thread_input)
142 {
143
144 UINT status;
145 UINT i;
146 NX_PACKET *packet_ptr;
147
148 printf("NetX Test: SNMP V1 Buffer Overwrite Test.............................");
149
150 if (error_counter)
151 {
152 printf("ERROR!\n");
153 test_control_return(1);
154 }
155
156 /* Create an SNMP agent instance. */
157 status = nx_snmp_agent_create(&my_agent, "SNMP Agent", &agent_ip, snmp_stack, sizeof(snmp_stack), &pool_0,
158 mib2_username_processing, mib2_get_processing,
159 mib2_getnext_processing, mib2_set_processing);
160
161 if (status)
162 {
163 error_counter++;
164 }
165
166 /* Start the SNMP instance. */
167 status = nx_snmp_agent_start(&my_agent);
168
169 /* Return the test result. */
170 if (status)
171 {
172 error_counter++;
173 }
174
175 /* Load the test data up. */
176 snmp_test_initialize();
177
178 /* Send SNMP queries to the agent. */
179 for (i = 0; i < QUERY_COUNT; i++ )
180 {
181
182 /* Inject the SNMP manager query packet. */
183 packet_inject(snmp_query[i].snmp_query_pkt_data, snmp_query[i].snmp_query_pkt_size);
184 }
185
186 /* Wait for processing snmp packet. */
187 tx_thread_sleep(NX_IP_PERIODIC_RATE);
188
189 /* Make sure the packet pool is not corrupted. */
190 while (pool_0.nx_packet_pool_available)
191 {
192 if (nx_packet_allocate(&pool_0, &packet_ptr, 0, NX_NO_WAIT) ||
193 (packet_ptr -> nx_packet_pool_owner != &pool_0))
194 {
195 error_counter++;
196 break;
197 }
198 }
199
200 /* Make sure the buffer is not overwrote. */
201 if (memcmp(mib2_mib[0].object_name, "1.3.6.1.2.1.1.1.0", sizeof("1.3.6.1.2.1.1.1.0") - 1) != 0)
202 {
203 error_counter++;
204 }
205
206 if (error_counter)
207 {
208 printf("ERROR!\n");
209 test_control_return(1);
210 }
211 else
212 {
213 printf("SUCCESS!\n");
214 test_control_return(0);
215 }
216
217 }
218
packet_inject(UCHAR * data_ptr,UINT data_size)219 static VOID packet_inject(UCHAR *data_ptr, UINT data_size)
220 {
221 UINT status;
222 NX_PACKET *my_packet;
223
224 status = nx_packet_allocate(&pool_0, &my_packet, NX_RECEIVE_PACKET, NX_NO_WAIT);
225
226 /* Check status */
227 if(status)
228 error_counter ++;
229
230 /* Make sure IP header is 4-byte aligned. */
231 my_packet -> nx_packet_prepend_ptr += 2;
232 my_packet -> nx_packet_append_ptr += 2;
233
234 /* Fill in the packet with data. Skip the MAC header. */
235 status = nx_packet_data_append(my_packet, data_ptr, data_size, &pool_0, NX_NO_WAIT);
236
237 /* Check status */
238 if(status)
239 error_counter ++;
240
241 /* Skip the MAC header. */
242 my_packet -> nx_packet_length -= 14;
243 my_packet -> nx_packet_prepend_ptr += 14;
244
245 /* Directly receive the TCP packet. */
246 _nx_ip_packet_deferred_receive(&agent_ip, my_packet);
247 }
248
snmp_test_initialize()249 static void snmp_test_initialize()
250 {
251 snmp_query[0].snmp_query_pkt_data = &v1_buffer_overwrite_packet1[0];
252 snmp_query[0].snmp_query_pkt_size = v1_buffer_overwrite_packet1_size;
253
254 snmp_query[1].snmp_query_pkt_data = &v1_buffer_overwrite_packet2[0];
255 snmp_query[1].snmp_query_pkt_size = v1_buffer_overwrite_packet2_size;
256
257 snmp_query[2].snmp_query_pkt_data = &v1_buffer_overwrite_packet3[0];
258 snmp_query[2].snmp_query_pkt_size = v1_buffer_overwrite_packet3_size;
259
260 snmp_query[3].snmp_query_pkt_data = &v1_buffer_overwrite_packet4[0];
261 snmp_query[3].snmp_query_pkt_size = v1_buffer_overwrite_packet4_size;
262 }
263
264
265 /* Define the application's GET processing routine. */
266
mib2_get_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)267 UINT mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
268 {
269
270 UINT i;
271 UINT status;
272
273
274
275 /* Loop through the sample MIB to see if we have information for the supplied variable. */
276 i = 0;
277 status = NX_SNMP_ERROR;
278 while (mib2_mib[i].object_name)
279 {
280
281 /* See if we have found the matching entry. */
282 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
283
284 /* Was it found? */
285 if (status == NX_SUCCESS)
286 {
287
288 /* Yes it was found. */
289 break;
290 }
291
292 /* Move to the next index. */
293 i++;
294 }
295
296 /* Determine if a not found condition is present. */
297 if (status != NX_SUCCESS)
298 {
299
300 /* The object was not found - return an error. */
301 return(NX_SNMP_ERROR_NOSUCHNAME);
302 }
303
304 /* Determine if the entry has a get function. */
305 if (mib2_mib[i].object_get_callback)
306 {
307
308 /* Yes, call the get function. */
309 status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
310 }
311 else
312 {
313
314 /* No get function, return no access. */
315 status = NX_SNMP_ERROR_NOACCESS;
316 }
317
318 /* Return the status. */
319 return(status);
320 }
321
322
323 /* Define the application's GETNEXT processing routine. */
324
mib2_getnext_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)325 UINT mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
326 {
327
328 UINT i;
329 UINT status;
330
331
332 /* Loop through the sample MIB to see if we have information for the supplied variable. */
333 i = 0;
334 status = NX_SNMP_ERROR;
335 while (mib2_mib[i].object_name)
336 {
337
338 /* See if we have found the next entry. */
339 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
340
341 /* Is the next entry the mib greater? */
342 if (status == NX_SNMP_NEXT_ENTRY)
343 {
344
345 /* Yes it was found. */
346 break;
347 }
348
349 /* Move to the next index. */
350 i++;
351 }
352
353 /* Determine if a not found condition is present. */
354 if (status != NX_SNMP_NEXT_ENTRY)
355 {
356
357 /* The object was not found - return an error. */
358 return(NX_SNMP_ERROR_NOSUCHNAME);
359 }
360
361
362 /* Copy the new name into the object. */
363 nx_snmp_object_copy(mib2_mib[i].object_name, object_requested);
364
365 /* Determine if the entry has a get function. */
366 if (mib2_mib[i].object_get_callback)
367 {
368
369 /* Yes, call the get function. */
370 status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
371
372 /* Determine if the object data indicates an end-of-mib condition. */
373 if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
374 {
375
376 /* Copy the name supplied in the mib table. */
377 nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
378 }
379 }
380 else
381 {
382
383 /* No get function, return no access. */
384 status = NX_SNMP_ERROR_NOACCESS;
385 }
386
387 /* Return the status. */
388 return(status);
389 }
390
391
392 /* Define the application's SET processing routine. */
393
mib2_set_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)394 UINT mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
395 {
396
397 UINT i;
398 UINT status;
399
400
401 /* Loop through the sample MIB to see if we have information for the supplied variable. */
402 i = 0;
403 status = NX_SNMP_ERROR;
404 while (mib2_mib[i].object_name)
405 {
406
407 /* See if we have found the matching entry. */
408 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
409
410 /* Was it found? */
411 if (status == NX_SUCCESS)
412 {
413
414 /* Yes it was found. */
415 break;
416 }
417
418 /* Move to the next index. */
419 i++;
420 }
421
422 /* Determine if a not found condition is present. */
423 if (status != NX_SUCCESS)
424 {
425
426 /* The object was not found - return an error. */
427 return(NX_SNMP_ERROR_NOSUCHNAME);
428 }
429
430
431 /* Determine if the entry has a set function. */
432 if (mib2_mib[i].object_set_callback)
433 {
434
435 /* If the object data type is string. */
436 if (object_data -> nx_snmp_object_data_type == NX_SNMP_ANS1_OCTET_STRING)
437 {
438
439 /* Check the string length of the object value. */
440 if (object_data -> nx_snmp_object_octet_string_size > mib2_mib[i].length)
441 {
442 return(NX_SNMP_ERROR_TOOBIG);
443 }
444 }
445
446 /* Yes, call the set function. */
447 status = (mib2_mib[i].object_set_callback)(mib2_mib[i].object_value_ptr, object_data);
448 }
449 else
450 {
451
452 /* No get function, return no access. */
453 status = NX_SNMP_ERROR_NOACCESS;
454 }
455
456
457 /* Return the status. */
458 return(status);
459 }
460
461 /* Create an error code if matching user not found. */
462 #define USER_NOT_FOUND 1
463
464 /* Define the username callback routine routine. Usernames should be
465 associated with permissions (public or private string) and what version
466 of SNMP the user is configured for. The username callback should verify
467 the incoming username MIB access permissions. */
mib2_username_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * username)468 UINT mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username)
469 {
470
471 mib2_variable_update(&agent_ip, &my_agent);
472
473 return NX_SUCCESS;
474
475 }
476
477 /* Define the application's update routine. */
478
mib2_variable_update(NX_IP * ip_ptr,NX_SNMP_AGENT * agent_ptr)479 VOID mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr)
480 {
481
482 /* Update the snmp parameters. */
483 return;
484 }
485 #else
486
487 #ifdef CTEST
test_application_define(void * first_unused_memory)488 VOID test_application_define(void *first_unused_memory)
489 #else
490 void netx_snmp_v1_buffer_overwrite_test_application_define(void *first_unused_memory)
491 #endif
492 {
493
494 /* Print out test information banner. */
495 printf("NetX Test: SNMP V1 Buffer Overwrite Test.............................N/A\n");
496
497 test_control_return(3);
498 }
499 #endif
500
501