Skip to content

Commit ed1d689

Browse files
loopback support for IPv4
1 parent 3753d40 commit ed1d689

3 files changed

Lines changed: 58 additions & 19 deletions

File tree

include/ip.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,18 @@ enum ip_type_t {
2121
* @brief Sub-protocols, TCP and UDP
2222
*/
2323
enum ip_proto_t {
24-
PROTOCOL_ICMP = 1,
25-
PROTOCOL_TCP = 6,
26-
PROTOCOL_UDP = 17,
24+
PROTOCOL_ICMP = 1, /* Internet Control Message Protocol */
25+
PROTOCOL_IGMP = 2, /* Internet Group Management Protocol */
26+
PROTOCOL_TCP = 6, /* Transmission Control Protocol */
27+
PROTOCOL_UDP = 17, /* User Datagram Protocol */
28+
PROTOCOL_GRE = 47, /* Generic Routing Encapsulation */
29+
PROTOCOL_ESP = 50, /* Encapsulating Security Payload (IPsec) */
30+
PROTOCOL_AH = 51, /* Authentication Header (IPsec) */
31+
PROTOCOL_IPV6 = 41, /* IPv6 encapsulation */
32+
PROTOCOL_OSPF = 89, /* Open Shortest Path First */
33+
PROTOCOL_PIM = 103, /* Protocol Independent Multicast */
34+
PROTOCOL_SCTP = 132, /* Stream Control Transmission Protocol */
35+
PROTOCOL_VRRP = 112, /* Virtual Router Redundancy Protocol */
2736
};
2837

2938
/**

src/basic/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const char *auto_number(const char *program, uint64_t line, uint64_t increment)
110110
strlcat(newprog, "\n", new_size_max);
111111
const char *corrected = strdup(newprog);
112112
kfree_null(&newprog);
113-
dprintf("*** AUTO NUMBERED ***\n%s\n***********\n", corrected);
113+
basic_debug("*** AUTO NUMBERED ***\n%s\n***********\n", corrected);
114114
return corrected;
115115
}
116116

src/net/ip.c

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,19 @@ uint32_t dns_addr = 0, gateway_addr = 0, netmask = 0;
2222
struct hashmap *frag_map = NULL;
2323
static 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

Comments
 (0)