Add ARP stub
This commit is contained in:
+4
-1
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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];
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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 : ':';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user