- EthIntf: packet interception in both directions; DHCP automanage; config loading and storing; info printing
- utils: atoip(), lefttrim() - ARP: bunch of bugfixes - TCP, FTP: WIP - DHCP: mutex; query the FSM state
This commit is contained in:
parent
db50beb71a
commit
9532b6b274
@ -167,6 +167,7 @@ int ftps_data_recv(cbd d) {
|
||||
// accept new data connection
|
||||
int ftps_data_accept_cb(cbd d) {
|
||||
s.connData = d; // set data connection ID
|
||||
tcp_debug(d, true);
|
||||
ETHLIB_OS_SEM_POST(s.dataConnHasOpened); // release data connection semaphore
|
||||
return 0;
|
||||
}
|
||||
@ -185,10 +186,19 @@ void ftps_process_event(uint32_t event) {
|
||||
uint32_t recvLen = tcp_recv(s.connCtrl, (uint8_t *)s.lineBuffer, FTPS_LINEBUF_LEN);
|
||||
s.lineBuffer[recvLen] = '\0';
|
||||
|
||||
// if recv len is zero in dicating that the connection was closed, by the peer,
|
||||
// then reset the server state
|
||||
if (recvLen == 0) {
|
||||
s.connCtrl = 0;
|
||||
s.connState = FTPS_IDLE;
|
||||
// TODO: close data connection as well
|
||||
return;
|
||||
}
|
||||
|
||||
// right trim the line
|
||||
ftps_rtrim(s.lineBuffer);
|
||||
|
||||
MSG("%s\n", s.lineBuffer);
|
||||
// MSG("%s\n", s.lineBuffer);
|
||||
|
||||
// get first word: get pointer to first space and calculate compare length
|
||||
char *spacePos = strchr(s.lineBuffer, ' ');
|
||||
@ -285,12 +295,13 @@ void ftps_process_event(uint32_t event) {
|
||||
case LIST: { // list files
|
||||
ETHLIB_OS_SEM_WAIT(s.dataConnHasOpened); // wait for data connection to establish
|
||||
tcp_send(s.connCtrl, (const uint8_t *)ftpOpeningDataConn, strlen(ftpOpeningDataConn)); // opening data connection
|
||||
tcp_send(s.connData, (const uint8_t *)"\r\n", 2); // sending listing data
|
||||
tcp_send(s.connData, (const uint8_t *)"\r\n", 2); // sending listing data
|
||||
tcp_send(s.connCtrl, (const uint8_t *)ftpClosingDataConn, strlen(ftpClosingDataConn)); // closing data connection
|
||||
close_connection(s.connData); // actually close connection
|
||||
s.connData = 0; // clear data connection CBD
|
||||
break;
|
||||
}
|
||||
s.connData = 0;
|
||||
resp = NULL; // clear data connection CBD
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ static int arpc_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) {
|
||||
|
||||
if (weAreCalled) {
|
||||
arpc_respond(arpc, arpProps->SHA, arpProps->SPA);
|
||||
//MSG("Megy a válasz!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -67,10 +67,12 @@ EthInterface *ethintf_new(EthIODef *io) {
|
||||
ethIntf->capabilities = 0;
|
||||
|
||||
ethIntf->dhcp = NULL;
|
||||
ethIntf->manageDhcp = true; // by default, enable automatic DHCP management
|
||||
|
||||
memset(ðIntf->evtCbTable, 0, sizeof(EthIntfEventCbTable));
|
||||
|
||||
ethIntf->interceptCb = NULL;
|
||||
ethIntf->interceptTxCb = NULL;
|
||||
ethIntf->interceptRxCb = NULL;
|
||||
|
||||
ethIntf->linkState = false;
|
||||
|
||||
@ -97,8 +99,8 @@ static ThreadReturnType task_ethintf(ThreadParamType param) {
|
||||
mq_pop(intf->rxQ);
|
||||
|
||||
// packet interception, if defined
|
||||
if (intf->interceptCb != NULL) {
|
||||
intf->interceptCb(intf, &rawPckt);
|
||||
if (intf->interceptRxCb != NULL) {
|
||||
intf->interceptRxCb(intf, &rawPckt);
|
||||
}
|
||||
|
||||
// packet processing
|
||||
@ -112,10 +114,10 @@ static ThreadReturnType task_ethintf(ThreadParamType param) {
|
||||
uint16_t speed = (event_data >> 2);
|
||||
|
||||
bool prev_ls = ethinf_get_link_state(intf); // get previous link state
|
||||
ethinf_set_link_state(intf, ls); // set new link state
|
||||
ethinf_set_link_state(intf, ls); // set new link state
|
||||
|
||||
if ((intf->dhcp != NULL) && (ls != prev_ls)) { // no double start!
|
||||
if (ls) { // if link is on
|
||||
if ((intf->manageDhcp) && (intf->dhcp != NULL) && (ls != prev_ls)) { // no double start!
|
||||
if (ls) { // if link is on
|
||||
dhcp_start(intf->dhcp);
|
||||
} else { // if link is off
|
||||
dhcp_stop(intf->dhcp);
|
||||
@ -155,8 +157,13 @@ void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// packet interception, if defined
|
||||
if (intf->interceptTxCb != NULL) {
|
||||
intf->interceptTxCb(intf, rawPckt);
|
||||
}
|
||||
|
||||
// push packet onto the message queue
|
||||
if (mq_push(intf->txQ, rawPckt)) {
|
||||
if (mq_push(intf->txQ, rawPckt)) {
|
||||
ethinf_push_notification(intf, ETH_IIE_TRANSMIT_NOTIFY, 0); // notify processing thread of the peding transmit
|
||||
} else {
|
||||
ERROR("Interface TRANSMIT queue full, packet dropped!\n");
|
||||
@ -222,6 +229,55 @@ void ethinf_down(EthInterface *intf) {
|
||||
intf->up = false;
|
||||
}
|
||||
|
||||
void ethinf_set_intercept_callback(EthInterface * intf, EthIntfInterceptCb cb) {
|
||||
intf->interceptCb = cb;
|
||||
}
|
||||
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb, EthIntfInterceptDir dir) {
|
||||
if (dir & ETH_INTERCEPT_TX) {
|
||||
intf->interceptTxCb = cb;
|
||||
}
|
||||
|
||||
if (dir & ETH_INTERCEPT_RX) {
|
||||
intf->interceptRxCb = cb;
|
||||
}
|
||||
}
|
||||
|
||||
void ethinf_set_automatic_dhcp_management(EthInterface *intf, bool automg) {
|
||||
intf->manageDhcp = automg;
|
||||
}
|
||||
|
||||
void ethinf_set_config(EthInterface *intf, const EthInterfaceNetworkConfig *config) {
|
||||
intf->ip = config->ip;
|
||||
intf->router = config->router;
|
||||
intf->netmask = config->netmask;
|
||||
intf->dns = config->dns;
|
||||
|
||||
intf->manageDhcp = config->manageDhcp;
|
||||
}
|
||||
|
||||
void ethinf_get_config(EthInterface *intf, EthInterfaceNetworkConfig *config) {
|
||||
config->ip = intf->ip;
|
||||
config->router = intf->router;
|
||||
config->netmask = intf->netmask;
|
||||
config->dns = intf->dns;
|
||||
|
||||
config->manageDhcp = intf->manageDhcp;
|
||||
}
|
||||
|
||||
void ethinf_print_info(const EthInterface * intf) {
|
||||
MSG("IP: " ANSI_COLOR_BYELLOW);
|
||||
PRINT_IPv4(intf->ip);
|
||||
MSG(ANSI_COLOR_RESET "\nRouter: ");
|
||||
PRINT_IPv4(intf->router);
|
||||
MSG("\nNetmask: ");
|
||||
PRINT_IPv4(intf->netmask);
|
||||
MSG("\nDNS: ");
|
||||
PRINT_IPv4(intf->dns);
|
||||
MSG("\n\n");
|
||||
|
||||
if (intf->dhcp != NULL) {
|
||||
bool on = dhcp_get_fsm_state(intf->dhcp) != DHCP_STOPPED;
|
||||
MSG("DHCP is %s" ANSI_COLOR_RESET "%s.", on ? (ANSI_COLOR_BGREEN "ON") : (ANSI_COLOR_BRED "OFF"), intf->manageDhcp ? "[automanaged]" : "");
|
||||
} else {
|
||||
MSG ("DHCP is " ANSI_COLOR_RED "absent" ANSI_COLOR_RESET ".");
|
||||
}
|
||||
|
||||
MSG("\n");
|
||||
}
|
||||
|
@ -48,6 +48,14 @@ struct EthInterface_;
|
||||
|
||||
typedef void (*EthIntfEvtCb)(struct EthInterface_ *intf);
|
||||
|
||||
/**
|
||||
* Frame interception direction.
|
||||
*/
|
||||
typedef enum {
|
||||
ETH_INTERCEPT_TX = 1,
|
||||
ETH_INTERCEPT_RX = 2
|
||||
} EthIntfInterceptDir;
|
||||
|
||||
/**
|
||||
* Function prototype for intercepting packets on an interface.
|
||||
* @param intf pointer to corresponding Ethernet interface
|
||||
@ -77,6 +85,7 @@ typedef struct EthInterface_ {
|
||||
EthernetAddress mac; ///< Ethernet address
|
||||
uint32_t capabilities; ///< Ethernet interface capabilities
|
||||
DhcpState *dhcp; ///< DHCP control block (allocated only, if DHCP operation is initiated)
|
||||
bool manageDhcp; ///< Let the interface automatically manage the DHCP client (start/stop)
|
||||
ip4_addr ip; ///< IP address
|
||||
ip4_addr router; ///< Router IP address
|
||||
ip4_addr netmask; ///< Subnet mask
|
||||
@ -87,14 +96,23 @@ typedef struct EthInterface_ {
|
||||
MsgQueue *rxQ; ///< Receive queue
|
||||
ETHLIB_OS_QUEUE_TYPE eventQ; ///< Event queue
|
||||
// ETHLIB_OS_SEM_TYPE eventSem; ///< Event queue semaphore
|
||||
IPv4Assembler *ipra; ///< IPv4 reassembler
|
||||
EthIntfEventCbTable evtCbTable; ///< Event callback table
|
||||
bool linkState; ///< Interface link state
|
||||
bool up; ///< Is the interface up?
|
||||
EthIntfInterceptCb interceptCb; ///< Intercept callback
|
||||
IPv4Assembler *ipra; ///< IPv4 reassembler
|
||||
EthIntfEventCbTable evtCbTable; ///< Event callback table
|
||||
bool linkState; ///< Interface link state
|
||||
bool up; ///< Is the interface up?
|
||||
EthIntfInterceptCb interceptTxCb; ///< Intercept TX callback
|
||||
EthIntfInterceptCb interceptRxCb; ///< Intercept RX callback
|
||||
|
||||
} EthInterface;
|
||||
|
||||
/*
|
||||
* Ethernet interface configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
ip4_addr ip, router, netmask, dns;
|
||||
bool manageDhcp;
|
||||
} EthInterfaceNetworkConfig;
|
||||
|
||||
/**
|
||||
* Allocate a new Ethernet interface
|
||||
* @param io Low-level IO definitions
|
||||
@ -183,6 +201,33 @@ void ethinf_down(EthInterface *intf);
|
||||
* @param intf pointer to Ethernet interface
|
||||
* @param cb intercept callback pointer
|
||||
*/
|
||||
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb);
|
||||
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb, EthIntfInterceptDir dir);
|
||||
|
||||
/**
|
||||
* Turn ON/OFF automatic DHCP client management.
|
||||
* @param intf pointer to Ethernet interface
|
||||
* @param automg automanagement enabled/disabled
|
||||
*/
|
||||
void ethinf_set_automatic_dhcp_management(EthInterface *intf, bool automg);
|
||||
|
||||
/**
|
||||
* Set interface configuration.
|
||||
* @param intf pointer to Ethernet interface
|
||||
* @param config pointer to a filled config object
|
||||
*/
|
||||
void ethinf_set_config(EthInterface * intf, const EthInterfaceNetworkConfig * config);
|
||||
|
||||
/**
|
||||
* Get interface configuration.
|
||||
* @param intf pointer to Ethernet interface
|
||||
* @param config pointer to an empty config object
|
||||
*/
|
||||
void ethinf_get_config(EthInterface *intf, EthInterfaceNetworkConfig *config);
|
||||
|
||||
/**
|
||||
* Printf information on Ethernet interface.
|
||||
* @param intf pointer to Ethernet interface
|
||||
*/
|
||||
void ethinf_print_info(const EthInterface * intf);
|
||||
|
||||
#endif // ETHERLIB_ETH_INTERFACE_H
|
||||
|
@ -2,17 +2,18 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../../utils.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;
|
||||
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 arp_new_connblock(EthInterface *intf, SieveCallBackFn cb) {
|
||||
ConnBlock arpConnB; // create ARP connblock
|
||||
connb_init_defaults(&arpConnB);
|
||||
|
||||
@ -29,35 +30,35 @@ ConnBlock arp_new_connblock(EthInterface * intf, SieveCallBackFn cb) {
|
||||
return arpConnB;
|
||||
}
|
||||
|
||||
void arp_send(const ConnBlock * connBlock, const ArpProps * props) {
|
||||
void arp_send(const ConnBlock *connBlock, const ArpProps *props) {
|
||||
// allocate header chain
|
||||
PcktHeaderElement * arpHeader = ALLOC_HEADER_ELEMENT(ArpProps);
|
||||
PcktHeaderElement * ethHeader = ALLOC_HEADER_ELEMENT(EthernetProps);
|
||||
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);
|
||||
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
|
||||
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
|
||||
} 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, 60);
|
||||
uint8_t * txBuf = dynmem_alloc(txBufSize);
|
||||
uint32_t txBufSize = MAX(txHeaderSize + 4, ETH_FRAME_MIN_SIZE);
|
||||
uint8_t *txBuf = dynmem_alloc(txBufSize);
|
||||
memset(txBuf, 0, txBufSize);
|
||||
|
||||
// insert Ethernet header
|
||||
@ -71,8 +72,11 @@ void arp_send(const ConnBlock * connBlock, const ArpProps * props) {
|
||||
dynmem_free(ethHeader);
|
||||
|
||||
// append CRC at the end
|
||||
uint32_t crc = crc32(txBuf, txBufSize - 4);
|
||||
memcpy(txBuf + txBufSize - 4, &crc, 4);
|
||||
//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;
|
||||
@ -82,7 +86,7 @@ void arp_send(const ConnBlock * connBlock, const ArpProps * props) {
|
||||
ethinf_transmit(connBlock->sieve->intf, &rpckt);
|
||||
|
||||
// release transmit buffer
|
||||
//dynmem_free(txBuf);
|
||||
// dynmem_free(txBuf);
|
||||
}
|
||||
|
||||
void arp_print_report(const ConnBlock *connBlock) {
|
||||
|
@ -146,7 +146,7 @@ static inline cbd tcps_create_based_on_listening(const TcpState *source, uint16_
|
||||
target->rxAckNum = source->rxAckNum;
|
||||
target->remoteAddr = remoteAddr;
|
||||
target->remotePort = remotePort;
|
||||
target->connState = TCP_STATE_ESTAB;
|
||||
target->connState = TCP_STATE_SYN_RCVD;
|
||||
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
||||
|
||||
return d;
|
||||
@ -168,12 +168,12 @@ static bool tcp_close(TcpState *tcps) {
|
||||
// take send semaphore
|
||||
ETHLIB_OS_SEM_WAIT(tcps->txInProgress);
|
||||
|
||||
MSG("TX SEM\n");
|
||||
//MSG("TX SEM\n");
|
||||
|
||||
// wait for the TX FIFO contents to get transmitted
|
||||
osEventFlagsWait(tcps->eventFlags, EVTFLAG_ALL_ACKED, osFlagsWaitAll | osFlagsNoClear, osWaitForever); // FIXME: ez így nem lesz jó, mert, ha valamiért nem kapjuk meg az ACK-t, akkor itt ragadunk
|
||||
// osEventFlagsWait(tcps->eventFlags, EVTFLAG_ALL_ACKED, osFlagsNoClear, 1000); // FIXME: ez így nem lesz jó, mert, ha valamiért nem kapjuk meg az ACK-t, akkor itt ragadunk
|
||||
|
||||
MSG("FLAG\n");
|
||||
//MSG("FLAG\n");
|
||||
|
||||
// lock the mutex -----
|
||||
ETHLIB_OS_MTX_LOCK(tcps->processMtx);
|
||||
@ -311,21 +311,40 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
||||
// create connection based on the listening connection
|
||||
ConnBlock connB;
|
||||
cbd client_d = tcps_create_based_on_listening(tcps, tcpProps->SourcePort, ipProps->SourceIPAddr, &connB);
|
||||
TcpState *target = TCP_FETCH_STATE_FROM_CONNBLOCK(&connB);
|
||||
|
||||
ETHLIB_OS_MTX_LOCK(target->processMtx);
|
||||
|
||||
tcp_send_segment(&connB, flags, NULL, NULL, 0);
|
||||
|
||||
TcpState *target = TCP_FETCH_STATE_FROM_CONNBLOCK(&connB);
|
||||
target->txSeqNum++;
|
||||
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
||||
|
||||
if ((client_d > 0) && (tcps->acceptCb != NULL)) {
|
||||
tcps->acceptCb(client_d);
|
||||
}
|
||||
|
||||
ETHLIB_OS_MTX_UNLOCK(target->processMtx);
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case TCP_STATE_SYN_RCVD: /* SYN was received */
|
||||
{
|
||||
bool SYNAcked = (dataSize == 0) && (tcps->txSeqNum == tcpProps->AcknowledgementNumber) &&
|
||||
(tcpProps->Flags & TCP_FLAG_ACK);
|
||||
if (SYNAcked) {
|
||||
tcps->connState = TCP_STATE_ESTAB;
|
||||
osEventFlagsSet(tcps->eventFlags, EVTFLAG_ESTAB);
|
||||
}
|
||||
} break;
|
||||
|
||||
case TCP_STATE_ESTAB: /* Connection established */
|
||||
if (tcps->debug) {
|
||||
MSG("data size: %d\n", dataSize);
|
||||
}
|
||||
|
||||
// if the other end tries to close down the connection
|
||||
if (tcpProps->Flags & TCP_FLAG_FIN) {
|
||||
// send FIN, ACK
|
||||
@ -333,6 +352,11 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
||||
tcps->rxAckNum++; // advance acknowledgement number // TODO...
|
||||
tcp_send_segment(&tcps->connBlock, flags, NULL, NULL, 0);
|
||||
|
||||
// invoke stream callback to inform application, that the connection is closing
|
||||
if (tcps->streamCb != NULL) {
|
||||
tcps->streamCb(tcps->d);
|
||||
}
|
||||
|
||||
// step into next state
|
||||
tcps->connState = TCP_STATE_LAST_ACK;
|
||||
} else if ((dataSize > 0) && (tcps->rxAckNum == tcpProps->SequenceNumber)) { // incoming data segment with integrity in ack/seq
|
||||
@ -357,9 +381,16 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
||||
// release segment from retransmit window
|
||||
tcpw_acknowledge(tcps->txWin, tcpProps->AcknowledgementNumber);
|
||||
|
||||
if (tcps->debug) {
|
||||
MSG("occupied: %d\n", tcpw_get_occupied_size(tcps->txWin));
|
||||
}
|
||||
|
||||
// set or clear all ACKed flag according to TX window state
|
||||
if (tcpw_get_occupied_size(tcps->txWin) == 0) {
|
||||
osEventFlagsSet(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
||||
if (tcps->debug) {
|
||||
MSG("All ACKed %d\n", tcps->d);
|
||||
}
|
||||
} else {
|
||||
osEventFlagsClear(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
||||
}
|
||||
@ -690,10 +721,15 @@ uint32_t tcp_send(cbd d, const uint8_t *data, uint32_t size) {
|
||||
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
||||
|
||||
// can send only data if connection is ESTABLISHED
|
||||
if (tcps->connState != TCP_STATE_ESTAB) {
|
||||
if ((tcps->connState != TCP_STATE_ESTAB) && (tcps->connState != TCP_STATE_SYN_RCVD)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is the SYN_RCVD state wait for getting into the established state
|
||||
if (tcps->connState == TCP_STATE_SYN_RCVD) {
|
||||
osEventFlagsWait(tcps->eventFlags, EVTFLAG_ESTAB, osFlagsNoClear, osWaitForever);
|
||||
}
|
||||
|
||||
// connection state is established...
|
||||
|
||||
uint32_t sizeLeft = size;
|
||||
@ -751,7 +787,11 @@ uint32_t tcp_recv(unsigned char d, uint8_t *data, uint32_t size) {
|
||||
// acquire TCP state
|
||||
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
||||
|
||||
return eth_bfifo_pop(tcps->rxFifo, data, size);
|
||||
if (tcps->connState == TCP_STATE_ESTAB) {
|
||||
return eth_bfifo_pop(tcps->rxFifo, data, size);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_print_report(const ConnBlock *connBlock) {
|
||||
|
@ -244,15 +244,31 @@ void dhcp_request(DhcpState *s, ip4_addr reqAddr, ip4_addr dhcpServerAddr) {
|
||||
|
||||
static void dhcp_retry_discover(struct Timer_ *timer, AlarmUserData user) {
|
||||
DhcpState *s = (DhcpState *)user.ptr;
|
||||
if (s->state != DHCP_BOUND) { // only retransmit DISCOVER if not BOUND
|
||||
if ((s->enabled) && (s->state != DHCP_BOUND)) { // only retransmit DISCOVER if not BOUND
|
||||
dhcp_start(s);
|
||||
}
|
||||
s->retryAlarmId = 0; // clear schedule ID
|
||||
}
|
||||
|
||||
static char * dhcp_state_names[] = {
|
||||
"DHCP INIT REBOOT",
|
||||
"DHCP REBOOTING",
|
||||
"DHCP INIT",
|
||||
"DHCP REQUESTING",
|
||||
"DHCP SELECTING",
|
||||
"DHCP REBINDING",
|
||||
"DHCP BOUND",
|
||||
"DHCP RENEWING",
|
||||
"DHCP STOPPED"
|
||||
};
|
||||
|
||||
static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
||||
ETHLIB_OS_MTX_LOCK(s->procMtx); // LOCK!
|
||||
|
||||
#ifdef DHCP_STATE_DEBUG
|
||||
uint8_t oldState = s->state;
|
||||
#endif
|
||||
|
||||
switch (s->state) {
|
||||
case DHCP_INIT: {
|
||||
dhcp_discover(s); // send discover message
|
||||
@ -280,6 +296,7 @@ static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
||||
case DHCP_REQUESTING: {
|
||||
const DhcpOption *opt = dhcp_get_option(opts, DHCP_OPT_MsgType);
|
||||
uint8_t msgType = opt->value[0];
|
||||
|
||||
if (msgType == DHCPNAK) {
|
||||
// dhcp_discover();
|
||||
// s.state = DHCP_SELECTING;
|
||||
@ -325,6 +342,14 @@ static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DHCP_STATE_DEBUG
|
||||
uint8_t newState = s->state;
|
||||
|
||||
if (newState != oldState) {
|
||||
MSG("# %s -> %s\n", dhcp_state_names[oldState], dhcp_state_names[newState]);
|
||||
}
|
||||
#endif
|
||||
|
||||
ETHLIB_OS_MTX_UNLOCK(s->procMtx); // RELEASE!
|
||||
}
|
||||
|
||||
@ -342,11 +367,19 @@ static int dhcp_resp_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
||||
}
|
||||
|
||||
void dhcp_start(DhcpState *s) {
|
||||
//MSG("DHCP start!\n");
|
||||
s->enabled = true;
|
||||
s->state = DHCP_INIT;
|
||||
dhcp_process(s, NULL, NULL);
|
||||
}
|
||||
|
||||
void dhcp_stop(DhcpState *s) {
|
||||
//MSG("DHCP stop!\n");
|
||||
|
||||
ETHLIB_OS_MTX_LOCK(s->procMtx); // LOCK!
|
||||
|
||||
s->enabled = false;
|
||||
|
||||
s->state = DHCP_STOPPED;
|
||||
if (s->renewAlarmId != 0) { // unschedule renew alarm
|
||||
timer_unsched(E.tmr, s->renewAlarmId);
|
||||
@ -382,6 +415,12 @@ void dhcp_initiate(EthInterface *intf) {
|
||||
cbdt_set_tag(E.cbdt, s->desc, tag);
|
||||
s->intf = intf;
|
||||
s->renewAlarmId = 0;
|
||||
s->retryAlarmId = 0;
|
||||
s->enabled = false;
|
||||
|
||||
intf->dhcp = s;
|
||||
}
|
||||
|
||||
DhcpFSMState dhcp_get_fsm_state(const DhcpState *s) {
|
||||
return s->state;
|
||||
}
|
@ -61,6 +61,7 @@ typedef struct {
|
||||
ETHLIB_OS_MTX_TYPE procMtx; ///< Mutex protecting the state machine
|
||||
uint32_t renewAlarmId; ///< IP renew alarm ID (valid if nonzero)
|
||||
uint32_t retryAlarmId; ///< DISCOVER retry alarm ID (valid if nonzero)
|
||||
bool enabled; ///< DHCP client is enabled
|
||||
} DhcpState;
|
||||
|
||||
#define DHCP_RETRY_TIMEOUT_S (3)
|
||||
@ -83,4 +84,11 @@ void dhcp_start(DhcpState * s);
|
||||
*/
|
||||
void dhcp_stop(DhcpState * s);
|
||||
|
||||
/**
|
||||
* Get DHCP FSM state.
|
||||
* @param s pointer to DhcpState structure
|
||||
* @return DHCP FSM state
|
||||
*/
|
||||
DhcpFSMState dhcp_get_fsm_state(const DhcpState * s);
|
||||
|
||||
#endif //ETHERLIB_DHCP_H
|
||||
|
3
timer.c
3
timer.c
@ -140,6 +140,9 @@ void timer_unsched(Timer *tmr, uint32_t id) {
|
||||
memset(alarm, 0, sizeof(AlarmAssignment));
|
||||
tmr->nSched--;
|
||||
timer_update_nearest_alarm(tmr);
|
||||
//MSG("Successful unsched of alarm #%x!\n", id);
|
||||
} else {
|
||||
//MSG("Could not unsched alarm #%x!\n", id);
|
||||
}
|
||||
}
|
||||
|
||||
|
138
utils.c
138
utils.c
@ -4,53 +4,54 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
static uint32_t crc32table[] = { /* CRC polynomial */
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
#include <stdlib.h>
|
||||
|
||||
uint32_t crc32(const uint8_t * data, uint32_t size) {
|
||||
static uint32_t crc32table[] = {/* CRC polynomial */
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
|
||||
uint32_t crc32(const uint8_t *data, uint32_t size) {
|
||||
uint32_t checksum = ~0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
@ -63,14 +64,14 @@ uint32_t crc32(const uint8_t * data, uint32_t size) {
|
||||
uint16_t chksum(const uint8_t *data, uint32_t size, int swap) {
|
||||
// sum fields
|
||||
uint32_t sum = 0;
|
||||
const uint16_t *pField = (const uint16_t *) data;
|
||||
const uint16_t *pField = (const uint16_t *)data;
|
||||
for (uint16_t i = 0; i < (size / sizeof(uint16_t)); i++) {
|
||||
uint16_t field = swap ? htons(pField[i]) : pField[i];
|
||||
sum += field;
|
||||
}
|
||||
|
||||
if (size % 2) {
|
||||
sum += ((uint16_t) (data[size - 1] << 8));
|
||||
sum += ((uint16_t)(data[size - 1] << 8));
|
||||
}
|
||||
|
||||
while (sum >> 16) {
|
||||
@ -80,4 +81,43 @@ uint16_t chksum(const uint8_t *data, uint32_t size, int swap) {
|
||||
// invert result
|
||||
uint16_t sum16 = sum ^ 0xFFFF;
|
||||
return sum16;
|
||||
}
|
||||
}
|
||||
|
||||
const char *trimleft(const char *str) {
|
||||
while ((*str) <= ' ' && (*str != '\0')) {
|
||||
str++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
#define ATOIP_BUFLEN (20)
|
||||
|
||||
ip4_addr atoip(const char *str) {
|
||||
// copy to internal buffer after trimming
|
||||
char buffer[ATOIP_BUFLEN];
|
||||
strncpy(buffer, trimleft(str), ATOIP_BUFLEN);
|
||||
|
||||
// separate the four fields
|
||||
const char *parts[4];
|
||||
parts[0] = buffer;
|
||||
uint8_t partsFound = 1;
|
||||
for (uint8_t i = 0; i < ATOIP_BUFLEN; i++) {
|
||||
if (buffer[i] == '.') {
|
||||
buffer[i] = '\0';
|
||||
parts[partsFound++] = buffer + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// check that all parts have been found
|
||||
if (partsFound < 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert to binary representation
|
||||
uint32_t nums[4];
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
nums[i] = atoi(parts[i]);
|
||||
}
|
||||
|
||||
return IPv4(nums[0], nums[1], nums[2], nums[3]);
|
||||
}
|
||||
|
16
utils.h
16
utils.h
@ -11,6 +11,8 @@
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "prefab/packet_parsers/ipv4_types.h"
|
||||
|
||||
#ifndef htonl
|
||||
#define htonl(a) \
|
||||
((((a) >> 24) & 0x000000ff) | \
|
||||
@ -92,4 +94,18 @@ uint32_t crc32(const uint8_t * data, uint32_t size);
|
||||
*/
|
||||
uint16_t chksum(const uint8_t *data, uint32_t size, int swap);
|
||||
|
||||
/**
|
||||
* Rip off whitespaces from the beginning of a string.
|
||||
* @param str string to be trimmed
|
||||
* @param pointer to the trimmed string
|
||||
*/
|
||||
const char *trimleft(const char *str);
|
||||
|
||||
/**
|
||||
* Parse string representation of an IPv4 address and convert to binary form.
|
||||
* @param str string representation of an IPv4 address
|
||||
* @return IPv4 address
|
||||
*/
|
||||
ip4_addr atoip(const char * str);
|
||||
|
||||
#endif //ETHERLIB_UTILS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user