From 72968ed85c2794171eedc532096b5f19633d720d Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Thu, 10 Jun 2021 09:09:52 +0900 Subject: [PATCH] net: arp fixups --- base/usr/include/kernel/net/eth.h | 9 +++++++++ kernel/net/arp.c | 29 ++++++++++++++++++++++------- kernel/net/eth.c | 17 ++++++++++++----- kernel/net/ipv4.c | 3 +++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/base/usr/include/kernel/net/eth.h b/base/usr/include/kernel/net/eth.h index df6cd02d..9cf7ba7e 100644 --- a/base/usr/include/kernel/net/eth.h +++ b/base/usr/include/kernel/net/eth.h @@ -3,6 +3,13 @@ #include #include +#define ETHERNET_TYPE_IPV4 0x0800 +#define ETHERNET_TYPE_ARP 0x0806 +#define ETHERNET_BROADCAST_MAC (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +#define MAC_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" +#define FORMAT_MAC(m) (m)[0], (m)[1], (m)[2], (m)[3], (m)[4], (m)[5] + void net_eth_handle(struct ethernet_packet * frame, fs_node_t * nic); struct EthernetDevice { @@ -20,3 +27,5 @@ struct EthernetDevice { fs_node_t * device_node; }; + +void net_eth_send(struct EthernetDevice *, size_t, void*, uint16_t, uint8_t*); diff --git a/kernel/net/arp.c b/kernel/net/arp.c index b711a686..dcefcd7e 100644 --- a/kernel/net/arp.c +++ b/kernel/net/arp.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -19,7 +20,7 @@ struct arp_header { struct { uint8_t arp_sha[6]; uint32_t arp_spa; - uint16_t arp_tha[6]; + uint8_t arp_tha[6]; uint32_t arp_tpa; } __attribute__((packed)) arp_eth_ipv4; } arp_data; @@ -33,14 +34,13 @@ static void ip_ntoa(const uint32_t src_addr, char * out) { (src_addr & 0xFF)); } -#define MAC_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" -#define FORMAT_MAC(m) (m)[0], (m)[1], (m)[2], (m)[3], (m)[4], (m)[5] - void net_arp_handle(struct arp_header * packet, fs_node_t * nic) { - printf("net: arp: hardware %d protocol %d operation %d\n", - ntohs(packet->arp_htype), ntohs(packet->arp_ptype), ntohs(packet->arp_oper)); + printf("net: arp: hardware %d protocol %d operation %d hlen %d plen %d\n", + ntohs(packet->arp_htype), ntohs(packet->arp_ptype), ntohs(packet->arp_oper), + packet->arp_hlen, packet->arp_plen); + struct EthernetDevice * eth_dev = nic->device; - if (ntohs(packet->arp_htype) == 1 && ntohs(packet->arp_ptype) == 0x0800) { + if (ntohs(packet->arp_htype) == 1 && ntohs(packet->arp_ptype) == ETHERNET_TYPE_IPV4) { /* Ethernet, IPv4 */ if (ntohs(packet->arp_oper) == 1) { char spa[17]; @@ -50,6 +50,21 @@ void net_arp_handle(struct arp_header * packet, fs_node_t * nic) { printf("net: arp: " MAC_FORMAT " (%s) wants to know who %s is\n", FORMAT_MAC(packet->arp_data.arp_eth_ipv4.arp_sha), spa, tpa); + if (eth_dev->ipv4_addr && packet->arp_data.arp_eth_ipv4.arp_tpa == eth_dev->ipv4_addr) { + printf("net: arp: that's us, we should reply...\n"); + + struct arp_header response = {0}; + response.arp_htype = htons(1); + response.arp_ptype = htons(ETHERNET_TYPE_IPV4); + response.arp_hlen = 6; + response.arp_plen = 4; + response.arp_oper = htons(2); + memcpy(response.arp_data.arp_eth_ipv4.arp_sha, eth_dev->mac, 6); + memcpy(response.arp_data.arp_eth_ipv4.arp_tha, packet->arp_data.arp_eth_ipv4.arp_sha, 6); + response.arp_data.arp_eth_ipv4.arp_spa = eth_dev->ipv4_addr; + response.arp_data.arp_eth_ipv4.arp_tpa = packet->arp_data.arp_eth_ipv4.arp_spa; + net_eth_send(eth_dev, sizeof(struct arp_header), &response, ETHERNET_TYPE_ARP, packet->arp_data.arp_eth_ipv4.arp_sha); + } } else if (ntohs(packet->arp_oper) == 2) { char spa[17]; ip_ntoa(ntohl(packet->arp_data.arp_eth_ipv4.arp_spa), spa); diff --git a/kernel/net/eth.c b/kernel/net/eth.c index d380de76..a11bece4 100644 --- a/kernel/net/eth.c +++ b/kernel/net/eth.c @@ -20,10 +20,6 @@ struct ethernet_packet { uint8_t payload[]; } __attribute__((packed)) __attribute__((aligned(2))); -#define ETHERNET_TYPE_IPV4 0x0800 -#define ETHERNET_TYPE_ARP 0x0806 -#define BROADCAST_MAC {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} - extern spin_lock_t net_raw_sockets_lock; extern list_t * net_raw_sockets_list; extern void net_sock_add(sock_t * sock, void * frame); @@ -42,7 +38,7 @@ void net_eth_handle(struct ethernet_packet * frame, fs_node_t * nic) { struct EthernetDevice * nic_eth = nic->device; - if (!memcmp(frame->destination, nic_eth->mac, 6) || !memcmp(frame->destination, (uint8_t[])BROADCAST_MAC, 6)) { + if (!memcmp(frame->destination, nic_eth->mac, 6) || !memcmp(frame->destination, ETHERNET_BROADCAST_MAC, 6)) { /* Now pass the frame to the appropriate handler... */ switch (ntohs(frame->type)) { case ETHERNET_TYPE_ARP: @@ -57,3 +53,14 @@ void net_eth_handle(struct ethernet_packet * frame, fs_node_t * nic) { free(frame); } + +void net_eth_send(struct EthernetDevice * nic, size_t len, void* data, uint16_t type, uint8_t * dest) { + size_t total_size = sizeof(struct ethernet_packet) + len; + struct ethernet_packet * packet = malloc(total_size); + memcpy(packet->payload, data, len); + memcpy(packet->destination, dest, 6); + memcpy(packet->source, nic->mac, 6); + packet->type = htons(type); + write_fs(nic->device_node, 0, total_size, (uint8_t*)packet); + free(packet); +} diff --git a/kernel/net/ipv4.c b/kernel/net/ipv4.c index 49841ef0..1b12a361 100644 --- a/kernel/net/ipv4.c +++ b/kernel/net/ipv4.c @@ -33,6 +33,9 @@ struct ipv4_packet { void net_ipv4_handle(struct ipv4_packet * packet, fs_node_t * nic) { switch (packet->protocol) { + case 1: + printf("net: ipv4: %s: ICMP\n", nic->name); + break; case IPV4_PROT_UDP: printf("net: ipv4: %s: udp packet\n", nic->name); break;