Add ARP tables and reply function
This commit is contained in:
@@ -56,8 +56,10 @@ static void rtl8139_reset(struct rtl8139 *rtl) {
|
||||
while (inb(rtl->iobase + REG_CR) & CR_RST);
|
||||
}
|
||||
|
||||
static int rtl8139_netdev_send(struct netdev *net, const void *date, size_t len) {
|
||||
static int rtl8139_netdev_send(struct netdev *net, const void *data, size_t len) {
|
||||
// TODO
|
||||
kdebug("%s: send stub:\n", net->name);
|
||||
debug_dump(DEBUG_DEFAULT, data, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#define ARP_H_ETH 1
|
||||
#define ARP_P_IP 0x0800
|
||||
|
||||
#define ARP_OP_REQUEST 1
|
||||
#define ARP_OP_REPLY 2
|
||||
|
||||
struct arp_frame {
|
||||
uint16_t htype;
|
||||
uint16_t ptype;
|
||||
|
||||
@@ -11,5 +11,8 @@ struct eth_frame {
|
||||
uint16_t ethertype;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct netdev;
|
||||
struct packet;
|
||||
void eth_handle_frame(struct packet *p);
|
||||
|
||||
int eth_send_wrapped(struct netdev *src, const uint8_t *dst, uint16_t et, void *data, size_t len);
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@
|
||||
#define IF_T_ETH 1
|
||||
|
||||
struct netdev;
|
||||
struct arp_ent;
|
||||
|
||||
typedef int (*netdev_send_func_t) (struct netdev *, const void *, size_t);
|
||||
|
||||
@@ -17,7 +18,8 @@ struct netdev {
|
||||
uint32_t flags;
|
||||
int type;
|
||||
|
||||
// TODO: arp table here?
|
||||
// ARP entry list
|
||||
struct arp_ent *arp_ent_head;
|
||||
|
||||
netdev_send_func_t send;
|
||||
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
|
||||
void strmac(char *dst, const uint8_t *hw);
|
||||
|
||||
static inline uint32_t ntohl(uint32_t w) {
|
||||
uint8_t *s = (uint8_t *)&w;
|
||||
return (uint32_t) (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
|
||||
}
|
||||
|
||||
static inline uint16_t ntohs(uint16_t w) {
|
||||
return (w >> 8) | (w << 8);
|
||||
}
|
||||
static inline uint16_t htons(uint16_t w) {
|
||||
return (w >> 8) | (w << 8);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,45 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
#include "net/util.h"
|
||||
#include "net/arp.h"
|
||||
#include "net/eth.h"
|
||||
#include "net/if.h"
|
||||
|
||||
struct arp_ent {
|
||||
uint32_t inaddr;
|
||||
uint8_t hwaddr[6];
|
||||
int resolved;
|
||||
struct arp_ent *prev, *next;
|
||||
};
|
||||
|
||||
static struct arp_ent *arp_find_inaddr(struct netdev *dev, uint32_t inaddr) {
|
||||
for (struct arp_ent *ent = dev->arp_ent_head; ent; ent = ent->next) {
|
||||
if (ent->inaddr == inaddr) {
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void arp_add_entry(struct netdev *dev, uint32_t inaddr, const uint8_t *hw) {
|
||||
struct arp_ent *ent = kmalloc(sizeof(struct arp_ent));
|
||||
_assert(ent);
|
||||
|
||||
ent->inaddr = inaddr;
|
||||
memcpy(ent->hwaddr, hw, 6);
|
||||
ent->resolved = 1;
|
||||
|
||||
ent->next = dev->arp_ent_head;
|
||||
ent->prev = NULL;
|
||||
dev->arp_ent_head = ent;
|
||||
|
||||
char mac[24];
|
||||
strmac(mac, hw);
|
||||
kdebug("%s: add arp entry: " FMT_INADDR " -> %s\n", dev->name, VA_INADDR(inaddr), mac);
|
||||
}
|
||||
|
||||
/*
|
||||
?Do I have the hardware type in ar$hrd?
|
||||
@@ -31,6 +67,25 @@ Yes: (almost definitely)
|
||||
the same hardware on which the request was received.
|
||||
*/
|
||||
|
||||
static void arp_send_reply(struct netdev *src, struct arp_frame *req) {
|
||||
char reply[sizeof(struct eth_frame) + sizeof(struct arp_frame)];
|
||||
struct arp_frame *arp = (struct arp_frame *) &reply[sizeof(struct eth_frame)];
|
||||
|
||||
memcpy(arp->tha, req->sha, 6);
|
||||
memcpy(arp->sha, src->hwaddr, 6);
|
||||
|
||||
arp->spa = req->tpa;
|
||||
arp->tpa = req->spa;
|
||||
|
||||
arp->hlen = req->hlen;
|
||||
arp->plen = req->plen;
|
||||
arp->htype = req->htype;
|
||||
arp->ptype = req->ptype;
|
||||
|
||||
arp->oper = htons(ARP_OP_REPLY);
|
||||
|
||||
eth_send_wrapped(src, arp->tha, ETH_T_ARP, reply, sizeof(reply));
|
||||
}
|
||||
|
||||
void arp_handle_frame(struct packet *p, void *data, size_t len) {
|
||||
if (len < sizeof(struct arp_frame)) {
|
||||
@@ -39,6 +94,9 @@ void arp_handle_frame(struct packet *p, void *data, size_t len) {
|
||||
}
|
||||
|
||||
struct arp_frame *arp = data;
|
||||
struct arp_ent *ent;
|
||||
struct netdev *dev = p->dev;
|
||||
int merge = 0;
|
||||
|
||||
if (ntohs(arp->htype) != ARP_H_ETH) {
|
||||
kwarn("%s: dropping non-ethernet packet\n", p->dev->name);
|
||||
@@ -48,4 +106,20 @@ void arp_handle_frame(struct packet *p, void *data, size_t len) {
|
||||
kwarn("%s: dropping non-IP packet\n", p->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ent = arp_find_inaddr(dev, ntohl(arp->spa))) != NULL) {
|
||||
merge = 1;
|
||||
kinfo("Found source addr\n");
|
||||
}
|
||||
|
||||
if ((dev->flags & IF_F_HASIP) &&
|
||||
dev->inaddr == ntohl(arp->tpa)) {
|
||||
if (!merge) {
|
||||
arp_add_entry(dev, ntohl(arp->spa), arp->sha);
|
||||
}
|
||||
|
||||
if (htons(arp->oper) == ARP_OP_REQUEST) {
|
||||
arp_send_reply(dev, arp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "net/util.h"
|
||||
#include "net/eth.h"
|
||||
@@ -6,6 +8,17 @@
|
||||
|
||||
#include "net/arp.h"
|
||||
|
||||
int eth_send_wrapped(struct netdev *src, const uint8_t *hwaddr, uint16_t et, void *data, size_t len) {
|
||||
struct eth_frame *eth = data;
|
||||
|
||||
memcpy(eth->dst_hwaddr, hwaddr, 6);
|
||||
memcpy(eth->src_hwaddr, src->hwaddr, 6);
|
||||
eth->ethertype = htons(et);
|
||||
|
||||
_assert(src->send);
|
||||
return src->send(src, data, len);
|
||||
}
|
||||
|
||||
void eth_handle_frame(struct packet *p) {
|
||||
if (p->size < sizeof(struct eth_frame)) {
|
||||
kwarn("%s: dropping undersized packet: %u\n", p->dev->name, p->size);
|
||||
|
||||
Reference in New Issue
Block a user