EtherLib/prefab/conn_blocks/arp_connblock.c
Epagris 8044d8a8b6 - RawPckt: force FCS computation feature added
- IGMP transmission reworked
- IPv4: method for filling in checksum in rendered binary data added
2024-10-20 15:38:36 +02:00

96 lines
3.1 KiB
C

#include "arp_connblock.h"
#include <stddef.h>
#include "../../dynmem.h"
#include "../../utils.h"
#include "../../pckt_assembler.h"
static bool filtArp(const PcktSieveFilterCondition *filtCond, const PcktProps *contProps, const PcktProps *ownProps, EthInterface *intf) {
EthernetProps *ethProps = (EthernetProps *)contProps;
ArpProps *arpProps = (ArpProps *)ownProps;
return ethProps->length_type == ETH_ARP_PACKET_CLASS;
}
ConnBlock arp_new_connblock(EthInterface *intf, SieveCallBackFn cb) {
ConnBlock arpConnB; // create ARP connblock
connb_init_defaults(&arpConnB);
PcktSieveFilterCondition filtCond;
packfiltcond_zero(&filtCond);
PcktSieveLayerTag tag;
tag.p = intf;
arpConnB.sieveLayer = packsieve_new_layer(&intf->sieve.layer0, &filtCond, false, filtArp, cb, tag, ETH_ARP_PACKET_CLASS);
ASSERT_NULL(arpConnB.sieveLayer);
arpConnB.sieve = &intf->sieve;
arpConnB.sieveLayer->connBReportFn = arp_print_report;
return arpConnB;
}
void arp_send(const ConnBlock *connBlock, const ArpProps *props) {
// allocate header chain
PcktHeaderElement *arpHeader = ALLOC_HEADER_ELEMENT(ArpProps);
PcktHeaderElement *ethHeader = ALLOC_HEADER_ELEMENT(EthernetProps);
arpHeader->next = NULL;
arpHeader->prev = ethHeader;
ethHeader->next = arpHeader;
ethHeader->prev = NULL;
// fetch props
ArpProps *arpProps = HEADER_FETCH_PROPS(ArpProps, arpHeader);
EthernetProps *ethProps = HEADER_FETCH_PROPS(EthernetProps, ethHeader);
// ARP
*arpProps = *props;
// Ethernet
ethProps->length_type = ETH_ARP_PACKET_CLASS;
if (arpProps->OPER == ARPOP_REP) { // respond in unicast
memcpy(ethProps->destAddr, arpProps->THA, ETH_HW_ADDR_LEN); // unicast destination
} else if (arpProps->OPER == ARPOP_REQ) { // request in broadcast
memset(ethProps->destAddr, 0xFF, ETH_HW_ADDR_LEN); // broadcast destination
}
memcpy(ethProps->sourceAddr, connBlock->sieve->intf->mac, ETH_HW_ADDR_LEN); // source
// allocate transmit buffer
uint32_t txHeaderSize = ETH_ETHERNET_HEADER_SIZE + ETH_ARP_HEADER_SIZE;
uint32_t txBufSize = MAX(txHeaderSize + 4, ETH_FRAME_MIN_SIZE);
uint8_t *txBuf = dynmem_alloc(txBufSize);
memset(txBuf, 0, txBufSize);
// insert Ethernet header
insert_ethernet_header(txBuf, ethHeader, NULL);
// insert ARP header
insert_arp_header(txBuf + ETH_ETHERNET_HEADER_SIZE, arpHeader, NULL);
// release headers
dynmem_free(arpHeader);
dynmem_free(ethHeader);
// append CRC at the end
//bool computeCRC = !(connBlock->sieve->intf->capabilities & ETHINF_CAP_TX_CRC_OFFLOAD);
//if (computeCRC) {
uint32_t crc = crc32(txBuf, txBufSize - 4);
memcpy(txBuf + txBufSize - 4, &crc, 4);
//}
// send packet
RawPckt rpckt;
memset(&rpckt, 0, sizeof(RawPckt));
rpckt.size = txBufSize;
rpckt.payload = txBuf;
rpckt.ext.tx.txTsCb = NULL;
ethinf_transmit(connBlock->sieve->intf, &rpckt);
// release transmit buffer
// dynmem_free(txBuf);
}
void arp_print_report(const ConnBlock *connBlock) {
INFO("ARP");
}