@@ -22,8 +22,19 @@ uint32_t dns_addr = 0, gateway_addr = 0, netmask = 0;
2222struct hashmap * frag_map = NULL ;
2323static size_t frag_mem_total = 0 ;
2424
25- void get_ip_str (char * ip_str , const uint8_t * ip )
26- {
25+ /* Loopback helpers */
26+ static const uint8_t loopback_addr [4 ] = {127 , 0 , 0 , 1 };
27+ static uint8_t ip_scratch_a [TCP_MAX_PACKET_SIZE + 1 ];
28+ static uint8_t ip_scratch_b [TCP_MAX_PACKET_SIZE + 1 ];
29+ static int ip_scratch_sel = 0 ; /* 0 => A, 1 => B */
30+
31+ void ip_handle_packet (ip_packet_t * packet , [[maybe_unused ]] int n_len );
32+
33+ static inline bool ip_is_loopback (const uint8_t * ip ) {
34+ return ip [0 ] == 127 ; /* 127.0.0.0/8 */
35+ }
36+
37+ void get_ip_str (char * ip_str , const uint8_t * ip ) {
2738 snprintf (ip_str , 16 , "%d.%d.%d.%d" , ip [0 ], ip [1 ], ip [2 ], ip [3 ]);
2839}
2940
@@ -263,14 +274,7 @@ void ip_send_packet(uint8_t* dst_ip, void* data, uint16_t len, uint8_t protocol)
263274 uint64_t flags ;
264275 lock_spinlock_irq (& tcp_send_spinlock , & flags );
265276 uint8_t dst_hardware_addr [6 ] = { 0 , 0 , 0 , 0 , 0 , 0 };
266- static ip_packet_t * packet = NULL ;
267- if (packet == NULL ) {
268- packet = kmalloc (TCP_MAX_PACKET_SIZE + 1 );
269- }
270- if (!packet ) {
271- unlock_spinlock_irq (& tcp_send_spinlock , flags );
272- return ;
273- }
277+ ip_packet_t * packet = (ip_packet_t * )(ip_scratch_sel ? ip_scratch_b : ip_scratch_a );
274278 memset (packet , 0 , sizeof (ip_packet_t ));
275279 packet -> version = IP_IPV4 ;
276280 packet -> ihl = sizeof (ip_packet_t ) / sizeof (uint32_t ); // header length is in 32 bit words
@@ -283,7 +287,6 @@ void ip_send_packet(uint8_t* dst_ip, void* data, uint16_t len, uint8_t protocol)
283287 packet -> frag .fragment_offset_high = 0 ;
284288 packet -> frag .fragment_offset_low = 0 ;
285289 packet -> ttl = 64 ;
286- // XXX: This is hard coded until other protocols are supported.
287290 packet -> protocol = protocol ;
288291
289292 gethostaddr (my_ip );
@@ -295,6 +298,12 @@ void ip_send_packet(uint8_t* dst_ip, void* data, uint16_t len, uint8_t protocol)
295298
296299 memcpy (packet -> src_ip , my_ip , 4 );
297300 memcpy (packet -> dst_ip , dst_ip , 4 );
301+
302+ /* Force localhost source before checksum if 127/8 */
303+ if (ip_is_loopback (dst_ip )) {
304+ memcpy (packet -> src_ip , loopback_addr , 4 );
305+ }
306+
298307 void * packet_data = (void * )packet + packet -> ihl * 4 ;
299308 memcpy (packet_data , data , len );
300309 * ((uint8_t * )(& packet -> version_ihl_ptr )) = htonb (* ((uint8_t * )(& packet -> version_ihl_ptr )), 4 );
@@ -304,12 +313,25 @@ void ip_send_packet(uint8_t* dst_ip, void* data, uint16_t len, uint8_t protocol)
304313 packet -> header_checksum = htons (ip_calculate_checksum (packet ));
305314 // Attempt to resolve ARP or find in arp cache table
306315
316+ if (ip_is_loopback (dst_ip )) {
317+ ip_scratch_sel ^= 1 ;
318+
319+ uint16_t pkt_len = ntohs (packet -> length );
320+ unlock_spinlock_irq (& tcp_send_spinlock , flags );
321+
322+ ip_handle_packet (packet , pkt_len );
323+ return ;
324+ }
325+
307326 if (netmask != 0 && our_ip != 0 && target_ip != 0 && ((our_ip & netmask ) != (target_ip & netmask ))) {
308327 /* We need to redirect this packet to the router's MAC address */
309328 if (!arp_lookup (dst_hardware_addr , (uint8_t * )& our_gateway )) {
310- queue_packet (dst_ip , packet , packet -> length );
329+ ip_packet_t * heap_copy = kmalloc (ntohs (packet -> length ));
330+ if (heap_copy ) {
331+ memcpy (heap_copy , packet , ntohs (packet -> length ));
332+ queue_packet (dst_ip , heap_copy , heap_copy -> length );
333+ }
311334 arp_send_packet (zero_hardware_addr , (uint8_t * )& our_gateway );
312- packet = NULL ; // ensures another is allocated next time we enter the function
313335 unlock_spinlock_irq (& tcp_send_spinlock , flags );
314336 return ;
315337 }
@@ -318,9 +340,12 @@ void ip_send_packet(uint8_t* dst_ip, void* data, uint16_t len, uint8_t protocol)
318340
319341 if (!redirected && !arp_lookup (dst_hardware_addr , dst_ip )) {
320342 /* Send ARP packet, and add to queue for this mac address */
321- queue_packet (dst_ip , packet , packet -> length );
343+ ip_packet_t * heap_copy = kmalloc (ntohs (packet -> length ));
344+ if (heap_copy ) {
345+ memcpy (heap_copy , packet , ntohs (packet -> length ));
346+ queue_packet (dst_ip , heap_copy , heap_copy -> length );
347+ }
322348 arp_send_packet (zero_hardware_addr , dst_ip );
323- packet = NULL ; // ensures another is allocated next time we enter the function
324349 unlock_spinlock_irq (& tcp_send_spinlock , flags );
325350 return ;
326351 }
@@ -408,6 +433,11 @@ void ip_handle_packet(ip_packet_t* packet, [[maybe_unused]] int n_len) {
408433 * ((uint8_t * )(packet -> flags_fragment_ptr )) = ntohb (* ((uint8_t * )(packet -> flags_fragment_ptr )), 3 );
409434 add_random_entropy (packet -> header_checksum ^ (* (uint32_t * )packet -> src_ip ));
410435 if (packet -> version == IP_IPV4 ) {
436+ /* Drop illegal on-wire 127/8 traffic (RFC 1122) */
437+ if (packet -> dst_ip [0 ] == 127 || packet -> src_ip [0 ] == 127 ) {
438+ return ;
439+ }
440+
411441 get_ip_str (src_ip , packet -> src_ip );
412442 void * data_ptr = (void * )packet + packet -> ihl * 4 ;
413443 size_t data_len = ntohs (packet -> length ) - (packet -> ihl * 4 );
0 commit comments