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