mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-02 07:28:21 +00:00
ipv4: checksumming and processing
This commit is contained in:
@@ -15,12 +15,11 @@ void eth_process(netdev_t *netdev, void *buffer) {
|
|||||||
if (!(MAC_EQUAL(&dst, &netdev->mac) || MAC_EQUAL(&dst, &broadcast)))
|
if (!(MAC_EQUAL(&dst, &netdev->mac) || MAC_EQUAL(&dst, &broadcast)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("our machine!\n");
|
|
||||||
|
|
||||||
void *nextbuff = (void *)((uintptr_t)buffer + sizeof(ethframe_t));
|
void *nextbuff = (void *)((uintptr_t)buffer + sizeof(ethframe_t));
|
||||||
|
|
||||||
switch (be_to_cpu_w(frame->type)) {
|
switch (be_to_cpu_w(frame->type)) {
|
||||||
case ETH_PROTO_IP:
|
case ETH_PROTO_IP:
|
||||||
|
ipv4_process(netdev, nextbuff);
|
||||||
break;
|
break;
|
||||||
case ETH_PROTO_ARP:
|
case ETH_PROTO_ARP:
|
||||||
arp_process(netdev, nextbuff);
|
arp_process(netdev, nextbuff);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <mutex.h>
|
#include <mutex.h>
|
||||||
#include <kernel/alloc.h>
|
#include <kernel/alloc.h>
|
||||||
|
#include <kernel/abi.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
netdev_t *netdev;
|
netdev_t *netdev;
|
||||||
@@ -79,6 +80,27 @@ int ipv4_addroute(netdev_t *netdev, uint32_t addr, uint32_t gateway, uint32_t ma
|
|||||||
#define FLAG_MF 1
|
#define FLAG_MF 1
|
||||||
// offset has to be a multiple of 8
|
// offset has to be a multiple of 8
|
||||||
#define FLAGS_FRAGOFFSET(flg, offset) (((flg) << 13) | ((offset) >> 3))
|
#define FLAGS_FRAGOFFSET(flg, offset) (((flg) << 13) | ((offset) >> 3))
|
||||||
|
#define GET_FLAGS(x) (((x) >> 13) & 0x7)
|
||||||
|
#define GET_FRAGOFFSET(x) ((x) & 0x1fff)
|
||||||
|
|
||||||
|
static int checksum(void *buffer, size_t size) {
|
||||||
|
uint16_t *p = buffer;
|
||||||
|
int sum = 0;
|
||||||
|
int i;
|
||||||
|
for (int i = 0; i < (size & ~(1lu)); i += 2) {
|
||||||
|
sum += be_to_cpu_w(p[i >> 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size & 1) {
|
||||||
|
sum += ((uint8_t *)p)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
sum += sum >> 16;
|
||||||
|
|
||||||
|
uint16_t ret = ~sum;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int dispatch_fragment(netdev_t *netdev, netdesc_t fragdesc,
|
static int dispatch_fragment(netdev_t *netdev, netdesc_t fragdesc,
|
||||||
uintmax_t fragmentoffset, size_t fragmentlen, int id, uint32_t ip, mac_t mac, int proto, bool last) {
|
uintmax_t fragmentoffset, size_t fragmentlen, int id, uint32_t ip, mac_t mac, int proto, bool last) {
|
||||||
@@ -90,15 +112,50 @@ static int dispatch_fragment(netdev_t *netdev, netdesc_t fragdesc,
|
|||||||
.flags_fragoffset = cpu_to_be_w(FLAGS_FRAGOFFSET(!last ? FLAG_MF : 0, fragmentoffset)),
|
.flags_fragoffset = cpu_to_be_w(FLAGS_FRAGOFFSET(!last ? FLAG_MF : 0, fragmentoffset)),
|
||||||
.timetolive = 0xff,
|
.timetolive = 0xff,
|
||||||
.protocol = proto,
|
.protocol = proto,
|
||||||
.framechecksum = 0xfefe, // TODO checksum
|
.framechecksum = 0,
|
||||||
.srcaddr = netdev->ip, // TODO src addr
|
.srcaddr = cpu_to_be_d(netdev->ip),
|
||||||
.dstaddr = cpu_to_be_d(ip)
|
.dstaddr = cpu_to_be_d(ip)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
frame.framechecksum = cpu_to_be_w(checksum(&frame, sizeof(frame)));
|
||||||
|
|
||||||
memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset), &frame, sizeof(ipv4frame_t));
|
memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset), &frame, sizeof(ipv4frame_t));
|
||||||
return netdev->sendpacket(netdev, fragdesc, mac, ETH_PROTO_IP);
|
return netdev->sendpacket(netdev, fragdesc, mac, ETH_PROTO_IP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ipv4_process(netdev_t *netdev, void *buff) {
|
||||||
|
ipv4frame_t *frame = buff;
|
||||||
|
|
||||||
|
if (checksum(frame, sizeof(ipv4frame_t)) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->version_length != VERSION_LENGTH(4, 5))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint16_t flagsfrag = be_to_cpu_w(frame->flags_fragoffset);
|
||||||
|
if ((GET_FLAGS(flagsfrag) & FLAG_MF) || (GET_FRAGOFFSET(flagsfrag) > 0)) {
|
||||||
|
printf("ipv4: reassembly not yet supported\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dstip = be_to_cpu_d(frame->dstaddr);
|
||||||
|
uint32_t srcip = be_to_cpu_d(frame->srcaddr);
|
||||||
|
|
||||||
|
if (dstip != IPV4_BROADCAST_ADDRESS && dstip != netdev->ip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
void *nextbuff = (void *)((uintptr_t)buff + sizeof(ipv4frame_t));
|
||||||
|
|
||||||
|
switch (frame->protocol) {
|
||||||
|
case IPV4_PROTO_UDP:
|
||||||
|
udp_process(netdev, nextbuff, srcip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, netdev_t *broadcastdev) {
|
int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, netdev_t *broadcastdev) {
|
||||||
if ((packetsize + sizeof(ipv4frame_t)) > 65535)
|
if ((packetsize + sizeof(ipv4frame_t)) > 65535)
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
@@ -134,7 +191,8 @@ int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, net
|
|||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
memcpy((void *)((uintptr_t)fragdesc.address + sizeof(ipv4frame_t)), (void *)((uintptr_t)buffer + i * devfragmentsize), fragmentlen);
|
memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset + sizeof(ipv4frame_t)), (void *)((uintptr_t)buffer + i * devfragmentsize), fragmentlen);
|
||||||
|
|
||||||
e = dispatch_fragment(netdev, fragdesc, i * devfragmentsize, fragmentlen, 0x1234, ip, mac, proto, i == fragmentcount - 1);
|
e = dispatch_fragment(netdev, fragdesc, i * devfragmentsize, fragmentlen, 0x1234, ip, mac, proto, i == fragmentcount - 1);
|
||||||
// TODO unallocate desc
|
// TODO unallocate desc
|
||||||
if (e)
|
if (e)
|
||||||
|
|||||||
Reference in New Issue
Block a user