#include "tcp_connblock.h" #include #include #include "../packet_parsers/packet_parsers.h" #include "../../utils.h" #include "../../dynmem.h" #include "etherlib/pckt_assembler.h" #include "etherlib/eth_interface.h" #include "ipv4_connblock.h" #include "etherlib/prefab/packet_parsers/tcp_segment.h" #include "etherlib/gen_queue.h" #include "etherlib_options.h" static bool filtTcp(const PcktSieveFilterCondition *filtCond, const PcktProps *contProps, const PcktProps *ownProps, EthInterface *intf) { IPv4Props *ipProps = (IPv4Props *) contProps; TcpProps *tcpProps = (TcpProps *) ownProps; return ipProps->Protocol == ETH_UDP_PACKET_CLASS && (TCP_PORT_FROM_FILTCOND(filtCond) == tcpProps->DestinationPort); } /** * TCP state. */ typedef struct { uint16_t localPort; uint16_t remotePort; ip4_addr remoteAddr; uint32_t sequenceNumber; uint32_t ackNumber; uint16_t window; uint8_t * txWindow; uint8_t * rxWindow; Queue * txQueue; Queue * rxQueue; } TcpState; void tcps_init(TcpState *tcps, uint16_t localPort) { tcps->sequenceNumber = (uint32_t) rand(); tcps->localPort = localPort; tcps->remotePort = 0; tcps->remoteAddr = 0; tcps->ackNumber = 0; tcps->window = 0; tcps->txWindow = dynmem_alloc(ETHLIB_DEF_TCP_WINDOW_SIZE); tcps->rxWindow = dynmem_alloc(ETHLIB_DEF_TCP_WINDOW_SIZE); /*tcps->txQueue = Q_CREATE_T(ETHLIB_DEF_TCP_QUEUE_SIZE, TcpQueueTicker); tcps->rxQueue = Q_CREATE_T(ETHLIB_DEF_TCP_QUEUE_SIZE, TcpQueueTicker);*/ } void tcp_bind(ConnBlock * connBlock, ip4_addr remoteAddr, uint16_t remotePort) { TcpState * tcps = (TcpState *) connBlock->tag; tcps->remoteAddr = remoteAddr; tcps->remotePort = remotePort; } int tcps_receive_data_segment(TcpState * tcps, const Pckt * pckt) { } ConnBlock tcp_new_connblock(EthInterface *intf, ip4_addr ipAddr, uint16_t port, SieveCallBackFn cbFn) { ConnBlock tcpConnB; ConnBlock ipConnB = ipv4_new_connblock(intf, ipAddr, NULL); // create new IPv4 connection block PcktSieveFilterCondition filtCond; packfiltcond_zero(&filtCond); TCP_PORT_TO_FILTCOND(&filtCond, port); PcktSieveLayerTag tag; // store TCP state into sieve layer's tag tag.p = dynmem_alloc(sizeof(TcpState)); memset(tag.p, 0, sizeof(TcpState)); tcpConnB.sieveLayer = packsieve_new_layer(ipConnB.sieveLayer, &filtCond, false, filtTcp, cbFn, tag, ETH_TCP_PACKET_CLASS); ASSERT_NULL(tcpConnB.sieveLayer); tcpConnB.intf = intf; SNPRINTF(tcpConnB.sieveLayer->infoTag, PCKT_SIEVE_INFOTAG_LEN, "TCP port: %d", port); return tcpConnB; } int tcp_send_segment(const struct ConnBlock_ *connBlock, const uint8_t *data, uint32_t size) { // allocate headers PcktHeaderElement *tcpHeader = ALLOC_HEADER_ELEMENT(TcpProps); PcktHeaderElement *ipHeader = ALLOC_HEADER_ELEMENT(IPv4Props); PcktHeaderElement *ethHeader = ALLOC_HEADER_ELEMENT(EthernetProps); tcpHeader->next = NULL; tcpHeader->prev = ipHeader; ipHeader->next = tcpHeader; ipHeader->prev = ethHeader; ethHeader->next = ipHeader; ethHeader->prev = NULL; // prepare headers TcpProps *tcpProps = HEADER_FETCH_PROPS(TcpProps, tcpHeader); IPv4Props *ipProps = HEADER_FETCH_PROPS(IPv4Props, ipHeader); EthernetProps *ethProps = HEADER_FETCH_PROPS(EthernetProps, ethHeader); // get TCP state PcktSieveLayer *layer = connBlock->sieveLayer; // TCP layer TcpState *tcpState = (TcpState *) layer->tag.p; // fetch sieve layers and fill transmit headers tcpProps->SourcePort = tcpState->localPort; tcpProps->DestinationPort = tcpState->remotePort; tcpProps->SequenceNumber = tcpState->sequenceNumber; tcpProps->AcknowledgementNumber = tcpState->ackNumber; tcpProps->Window = tcpState->window; tcpProps->Checksum = 0; tcpProps->UrgentPtr = 0; return 0; }