Add ARP stub

This commit is contained in:
Mark
2020-03-20 11:11:14 +02:00
parent 8c6a8beeaf
commit 8d6ecc7134
9 changed files with 155 additions and 12 deletions
+4 -1
View File
@@ -95,7 +95,10 @@ DIRS+=$(O)/drivers/pci \
OBJS+=$(O)/drivers/net/rtl8139.o
DIRS+=$(O)/drivers/net
OBJS+=$(O)/net/net.o
OBJS+=$(O)/net/net.o \
$(O)/net/eth.o \
$(O)/net/arp.o \
$(O)/net/util.o
DIRS+=$(O)/net
ifeq ($(DEBUG_COUNTERS),1)
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "sys/types.h"
#define ARP_H_ETH 1
#define ARP_P_IP 0x0800
struct arp_frame {
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t oper;
// INET only
uint8_t sha[6];
uint32_t spa;
uint8_t tha[6];
uint32_t tpa;
} __attribute__((packed));
struct packet;
void arp_handle_frame(struct packet *packet, void *data, size_t len);
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "sys/types.h"
#define ETH_T_IP 0x0800
#define ETH_T_IPv6 0x86DD
#define ETH_T_ARP 0x0806
struct eth_frame {
uint8_t dst_hwaddr[6];
uint8_t src_hwaddr[6];
uint16_t ethertype;
} __attribute__((packed));
struct packet;
void eth_handle_frame(struct packet *p);
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "sys/types.h"
// Takes up a single page
#define PACKET_DATA_MAX (4064)
struct packet {
size_t size;
struct packet *prev, *next;
void *source_if;
char data[PACKET_DATA_MAX];
};
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "sys/types.h"
void strmac(char *dst, const uint8_t *hw);
static inline uint16_t ntohs(uint16_t w) {
return (w >> 8) | (w << 8);
}
+50
View File
@@ -0,0 +1,50 @@
#include "sys/debug.h"
#include "net/util.h"
#include "net/arp.h"
/*
?Do I have the hardware type in ar$hrd?
Yes: (almost definitely)
[optionally check the hardware length ar$hln]
?Do I speak the protocol in ar$pro?
Yes:
[optionally check the protocol length ar$pln]
Merge_flag := false
If the pair <protocol type, sender protocol address> is
already in my translation table, update the sender
hardware address field of the entry with the new
information in the packet and set Merge_flag to true.
?Am I the target protocol address?
Yes:
If Merge_flag is false, add the triplet <protocol type,
sender protocol address, sender hardware address> to
the translation table.
?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!)
Yes:
Swap hardware and protocol fields, putting the local
hardware and protocol addresses in the sender fields.
Set the ar$op field to ares_op$REPLY
Send the packet to the (new) target hardware address on
the same hardware on which the request was received.
*/
void arp_handle_frame(struct packet *p, void *data, size_t len) {
if (len < sizeof(struct arp_frame)) {
kwarn("Dropping undersized frame: %u\n", len);
return;
}
struct arp_frame *arp = data;
if (ntohs(arp->htype) != ARP_H_ETH) {
kwarn("Dropping non-ethernet packet\n");
return;
}
if (ntohs(arp->ptype) != ARP_P_IP) {
kwarn("Dropping non-IP packet\n");
return;
}
}
+28
View File
@@ -0,0 +1,28 @@
#include "net/packet.h"
#include "sys/debug.h"
#include "net/util.h"
#include "net/eth.h"
#include "net/arp.h"
void eth_handle_frame(struct packet *p) {
struct eth_frame *eth = (struct eth_frame *) p->data;
if (p->size < sizeof(struct eth_frame)) {
kwarn("Dropping undersized packet: %u\n", p->size);
return;
}
switch (ntohs(eth->ethertype)) {
case ETH_T_ARP:
arp_handle_frame(p, p->data + sizeof(struct eth_frame), p->size - sizeof(struct eth_frame));
break;
case ETH_T_IP:
case ETH_T_IPv6:
// Silently drop
break;
default:
kwarn("Dropping unknown packet: %04x\n", ntohs(eth->ethertype));
break;
}
}
+7 -11
View File
@@ -8,14 +8,8 @@
#include "sys/debug.h"
#include "sys/spin.h"
// Takes up a single page
#define PACKET_DATA_MAX (4064)
struct packet {
size_t size;
struct packet *prev, *next;
void *source_if;
char data[PACKET_DATA_MAX];
};
#include "net/packet.h"
#include "net/eth.h"
static struct thread netd_thread = {0};
static spin_t g_rxq_lock = 0;
@@ -24,9 +18,9 @@ static struct packet *g_rxq_head, *g_rxq_tail;
static struct packet *packet_create(void);
static void packet_free(struct packet *p);
static void net_handle_packet(struct packet *p) {
kdebug("Packet:\n");
debug_dump(DEBUG_DEFAULT, p->data, p->size);
static inline void net_handle_packet(struct packet *p) {
// TODO: check if interface sends packet not in ethernet format
eth_handle_frame(p);
}
static void net_daemon(void) {
@@ -80,6 +74,8 @@ int net_receive(/* TODO: replace with struct netdev * */ void *ctx, const void *
}
struct packet *p = packet_create();
// TODO: maybe information like "Physical match", "Multicast" or "Broadcast"
// would be useful to store in packet
memcpy(p->data, data, len);
p->size = len;
p->source_if = ctx;
+11
View File
@@ -0,0 +1,11 @@
#include "net/util.h"
void strmac(char *dst, const uint8_t *hw) {
static const char hex_digits[] = "0123456789abcdef";
// I don't have snprintf, lol
for (size_t i = 0; i < 6; ++i) {
dst[i * 3 + 0] = hex_digits[hw[i] >> 4];
dst[i * 3 + 1] = hex_digits[hw[i] & 0xF];
dst[i * 3 + 2] = i == 5 ? 0 : ':';
}
}