EtherLib/pckt_assembler.c
Wiesner András 05288d7a3c - ARP cache auto lookup feature added
- IGMPv2 capabilities added (report membership, leave group)
- ICMP capabilities added (ping)
- Tx Message Queue added
2023-01-14 14:24:56 +01:00

67 lines
2.0 KiB
C

//
// Created by epagris on 2023.01.11..
//
#include <stddef.h>
#include "pckt_assembler.h"
#include "packet_sieve.h"
#include "dynmem.h"
#include "eth_interface.h"
#include "global_state.h"
#include "utils.h"
int pckt_assemble(RawPckt *raw, const Pckt *cooked) {
// calculate frame size
uint16_t frameSize = 0;
uint16_t headerSize = 0;
const PcktHeaderElement *hdrIter = cooked->header;
// rewind headers
while (hdrIter->prev != NULL) {
hdrIter = hdrIter->prev;
}
const PcktHeaderElement *lastHdr = hdrIter;
while (hdrIter != NULL) {
headerSize += hdrIter->props.headerSize;
lastHdr = hdrIter;
hdrIter = hdrIter->next;
}
frameSize = headerSize + cooked->payloadSize + 4; // header + payload + CRC32 checksum area
// calculate padding size
uint16_t padding = (frameSize < ETH_FRAME_MIN_SIZE) ? (ETH_FRAME_MIN_SIZE - frameSize) : 0;
// grow frame to minimum length if needed
frameSize = (frameSize < ETH_FRAME_MIN_SIZE) ? ETH_FRAME_MIN_SIZE : frameSize;
// allocate raw packet data
raw->payload = dynmem_alloc(frameSize);
raw->size = frameSize;
// insert pointer
uint8_t * payloadInsPtr = raw->payload + headerSize;
uint8_t * headerInsPtr = payloadInsPtr - lastHdr->props.headerSize;
// insert payload
memcpy(payloadInsPtr, cooked->payload, cooked->payloadSize);
// insert zero padding
memset(payloadInsPtr + cooked->payloadSize, 0, padding);
// insert reversely headers (e.g.: UDP -> IPv4 -> Ethernet)
hdrIter = lastHdr;
while (hdrIter != NULL) {
hdrIter->props.hdrInsFn(headerInsPtr, hdrIter); // insert header
hdrIter = hdrIter->prev; // step to previous header
if (hdrIter != NULL) {
headerInsPtr -= hdrIter->props.headerSize; // advance data pointer
}
}
// insert CRC32
uint32_t crc = crc32(raw->payload, frameSize - 4);
memcpy(raw->payload + frameSize - 4, (const uint8_t *)&crc, 4);
return 0;
}