- 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:
Wiesner András 2024-10-06 23:29:15 +02:00
parent db50beb71a
commit 9532b6b274
11 changed files with 359 additions and 96 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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(&ethIntf->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");
}

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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