- IGMP transmission reworked - IPv4: method for filling in checksum in rendered binary data added
96 lines
3.1 KiB
C
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");
|
|
}
|