@@ -2235,6 +2235,9 @@ START_TEST(test_arp_recv_request_does_not_store_self_neighbor)
22352235 wolfIP_filter_set_callback (NULL , NULL );
22362236 wolfIP_filter_set_mask (0 );
22372237
2238+ s .last_tick = 1000 ;
2239+ arp_pending_record (& s , TEST_PRIMARY_IF , sender_ip );
2240+
22382241 memset (& arp_req , 0 , sizeof (arp_req ));
22392242 arp_req .htype = ee16 (1 );
22402243 arp_req .ptype = ee16 (0x0800 );
@@ -2264,6 +2267,89 @@ START_TEST(test_arp_recv_request_does_not_store_self_neighbor)
22642267}
22652268END_TEST
22662269
2270+ /* Regression: a same-LAN attacker that floods the ARP cache by sending
2271+ * MAX_NEIGHBORS ARP requests from distinct sender IP/MAC pairs targeting our
2272+ * IP must not lock out legitimate ARP replies for outstanding requests.
2273+ * arp_store_neighbor's silent-drop-when-full behaviour, combined with
2274+ * unconditional sender caching from the request branch of arp_recv, lets a
2275+ * flood deny resolution of any new peer until ARP_AGING_TIMEOUT_MS elapses. */
2276+ START_TEST (test_arp_request_flood_does_not_lock_out_legit_reply )
2277+ {
2278+ struct wolfIP s ;
2279+ struct arp_packet arp_pkt ;
2280+ struct wolfIP_ll_dev * ll ;
2281+ struct ipconf * conf ;
2282+ const ip4 our_ip = 0x0A000001U ;
2283+ const ip4 legit_ip = 0x0A0000FEU ;
2284+ const uint8_t legit_mac [6 ] = {0x02 , 0xCA , 0xFE , 0xBA , 0xBE , 0x01 };
2285+ uint8_t mac_out [6 ];
2286+ int i ;
2287+
2288+ wolfIP_init (& s );
2289+ mock_link_init (& s );
2290+ wolfIP_ipconfig_set (& s , our_ip , 0xFFFFFF00U , 0 );
2291+ wolfIP_filter_set_callback (NULL , NULL );
2292+ wolfIP_filter_set_mask (0 );
2293+
2294+ ll = wolfIP_getdev_ex (& s , TEST_PRIMARY_IF );
2295+ conf = wolfIP_ipconf_at (& s , TEST_PRIMARY_IF );
2296+ s .last_tick = 1000 ;
2297+
2298+ /* Attacker floods MAX_NEIGHBORS ARP requests from distinct sender
2299+ * IP/MAC pairs, all targeting our IP. Each one passes the
2300+ * broadcast/multicast/zero/own-IP filter and so reaches
2301+ * arp_store_neighbor unconditionally. */
2302+ for (i = 0 ; i < MAX_NEIGHBORS ; i ++ ) {
2303+ uint8_t fake_mac [6 ] = {0xDE , 0xAD , 0xBE , 0xEF , 0x00 ,
2304+ (uint8_t )(0x10 + i )};
2305+ ip4 fake_ip = (ip4 )(0x0A000010U + (uint32_t )i );
2306+
2307+ memset (& arp_pkt , 0 , sizeof (arp_pkt ));
2308+ memcpy (arp_pkt .eth .dst , ll -> mac , 6 );
2309+ memcpy (arp_pkt .eth .src , fake_mac , 6 );
2310+ arp_pkt .eth .type = ee16 (ETH_TYPE_ARP );
2311+ arp_pkt .htype = ee16 (1 );
2312+ arp_pkt .ptype = ee16 (0x0800 );
2313+ arp_pkt .hlen = 6 ;
2314+ arp_pkt .plen = 4 ;
2315+ arp_pkt .opcode = ee16 (ARP_REQUEST );
2316+ memcpy (arp_pkt .sma , fake_mac , 6 );
2317+ arp_pkt .sip = ee32 (fake_ip );
2318+ memset (arp_pkt .tma , 0 , 6 );
2319+ arp_pkt .tip = ee32 (conf -> ip );
2320+
2321+ s .last_tick += 1 ;
2322+ arp_recv (& s , TEST_PRIMARY_IF , & arp_pkt , sizeof (arp_pkt ));
2323+ }
2324+
2325+ /* Stack issues a legitimate ARP request for legit_ip and then receives
2326+ * the matching reply. Caching this reply must succeed even with the
2327+ * neighbor table full of attacker-driven entries. */
2328+ s .last_tick += 1 ;
2329+ arp_pending_record (& s , TEST_PRIMARY_IF , legit_ip );
2330+
2331+ memset (& arp_pkt , 0 , sizeof (arp_pkt ));
2332+ memcpy (arp_pkt .eth .dst , ll -> mac , 6 );
2333+ memcpy (arp_pkt .eth .src , legit_mac , 6 );
2334+ arp_pkt .eth .type = ee16 (ETH_TYPE_ARP );
2335+ arp_pkt .htype = ee16 (1 );
2336+ arp_pkt .ptype = ee16 (0x0800 );
2337+ arp_pkt .hlen = 6 ;
2338+ arp_pkt .plen = 4 ;
2339+ arp_pkt .opcode = ee16 (ARP_REPLY );
2340+ memcpy (arp_pkt .sma , legit_mac , 6 );
2341+ arp_pkt .sip = ee32 (legit_ip );
2342+ memcpy (arp_pkt .tma , ll -> mac , 6 );
2343+ arp_pkt .tip = ee32 (conf -> ip );
2344+
2345+ s .last_tick += 1 ;
2346+ arp_recv (& s , TEST_PRIMARY_IF , & arp_pkt , sizeof (arp_pkt ));
2347+
2348+ ck_assert_int_eq (arp_lookup (& s , TEST_PRIMARY_IF , legit_ip , mac_out ), 0 );
2349+ ck_assert_mem_eq (mac_out , legit_mac , 6 );
2350+ }
2351+ END_TEST
2352+
22672353START_TEST (test_send_ttl_exceeded_filter_drop )
22682354{
22692355 struct wolfIP s ;
@@ -2690,7 +2776,6 @@ START_TEST(test_arp_recv_filter_drop)
26902776
26912777 arp_recv (& s , TEST_PRIMARY_IF , & arp_req , sizeof (arp_req ));
26922778 ck_assert_uint_eq (last_frame_sent_size , 0 );
2693- ck_assert_int_ne (s .arp .neighbors [0 ].ip , IPADDR_ANY );
26942779
26952780 wolfIP_filter_set_callback (NULL , NULL );
26962781 wolfIP_filter_set_eth_mask (0 );
0 commit comments