#include "arp_connblock.h" #include #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; 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"); }