blob: 72c80ae2133329aedf28defe14db5a02225ff710 [file] [log] [blame]
#include <multiboot.h>
#include <arch/frontend.h>
#include <net/nic_common.h>
#include <kmalloc.h>
#define debug(...) printk(__VA_ARGS__)
int handle_appserver_packet(const char* p, size_t size)
{
// Subtract off the crc because we just don't care...
size-=4;
appserver_packet_t* packet = (appserver_packet_t*)p;
if(size < sizeof(packet->header))
goto fail;
uint8_t cmd = packet->header.cmd;
if(cmd != APPSERVER_CMD_LOAD && cmd != APPSERVER_CMD_STORE)
goto fail;
uintptr_t paddr = ntohl(packet->header.addr);
size_t copy_size = ntohl(packet->header.payload_size);
if(paddr % 4 || paddr >= max_paddr)
goto fail;
if(copy_size % 4 || copy_size > APPSERVER_MAX_PAYLOAD_SIZE)
goto fail;
size_t paysize = copy_size;
size_t response_paysize = 0;
if(cmd == APPSERVER_CMD_LOAD)
{
response_paysize = copy_size;
paysize = 0;
}
if(size != sizeof(packet->header) + paysize &&
!(size == MIN_FRAME_SIZE && sizeof(packet->header) + paysize <= MIN_FRAME_SIZE))
goto fail;
// construct response packet
size_t response_size = sizeof(packet->header)+response_paysize;
appserver_packet_t* response_packet = kmalloc(response_size,0);
memcpy(response_packet->header.dst_mac,packet->header.src_mac,6);
memcpy(response_packet->header.src_mac,packet->header.dst_mac,6);
response_packet->header.ethertype = packet->header.ethertype;
response_packet->header.cmd = APPSERVER_CMD_ACK;
response_packet->header.seqno = packet->header.seqno;
response_packet->header.payload_size = htonl(response_paysize);
response_packet->header.addr = packet->header.addr;
// determine src/dest for copy
const uint32_t* copy_src = (const uint32_t*)packet->payload;
uint32_t* copy_dst = (uint32_t*)KADDR(paddr);
if(cmd == APPSERVER_CMD_LOAD)
{
copy_src = copy_dst;
copy_dst = (uint32_t*)response_packet->payload;
}
// manual word-by-word copy for word-atomicity
for(int i = 0; i < copy_size/sizeof(uint32_t); i++)
copy_dst[i] = copy_src[i];
// fire the response
if(send_frame((char*)response_packet,response_size) != response_size)
panic("couldn't send appserver packet!");
kfree(response_packet);
return 0;
fail:
panic("bad appserver packet!");
}