#ifndef _TEST_H_
#define _TEST_H_
+#include <stddef.h>
+
#define TEST_SETNAME(name) test_setname(name)
#define TEST_ASSERT(cnd) do{if(!(cnd)) {test_assertion_fail(__FILE__,__LINE__,"%s",#cnd);return false;}}while(0)
#define TEST_ASSERT_REL(a,r,b) do{long long a_val=(a),b_val=(b);if(!(a_val r b_val)) {test_assertion_fail(__FILE__,__LINE__,"%s(0x%llx)%s%s(0x%llx)",#a,a_val,#r,#b,b_val);return false;}}while(0)
extern void test_setname(const char *name);
extern void test_message(const char *filename, int line, const char *msg, ...);
extern void test_assertion_fail(const char *filename, int line, const char *test, ...);
+extern void test_trace(const char *msg, ...);
+extern void test_trace_hexdump(const char *hdr, const void *data, size_t len);
#endif
// === CODE ===
uint16_t IP_Checksum(uint16_t Prev, size_t Length, const void *Data)
{
+ //test_trace_hexdump("IP Checksum", Data, Length);
+
const uint16_t *words = Data;
- uint32_t ret = ~Prev;
+ uint32_t ret = 0;
for( int i = 0; i < Length/2; i ++ )
{
ret += ntohs(*words);
while( ret >> 16 )
ret = (ret & 0xFFFF) + (ret >> 16);
+ //test_trace("IP Checksum = %04x + 0x%x", ret, (~Prev) & 0xFFFF);
+
+ ret += (~Prev) & 0xFFFF;
+ while( ret >> 16 )
+ ret = (ret & 0xFFFF) + (ret >> 16);
+
return ~ret;
}
TEST_ASSERT_REL(hdr.TTL, >, 1); // >1 because there's no intervening hops
TEST_ASSERT_REL(hdr.Protocol, ==, proto);
- TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 );
- TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 );
+ if(Src) TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 );
+ if(Dst) TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 );
*ofs_out = ofs + (hdr.VerLen & 0xF) * 4;
return true;
FILE *fp;
fp = fopen("stdout.txt", "w"); fclose(fp);
fp = fopen("stderr.txt", "w"); fclose(fp);
+
+ Net_Open(0, "/tmp/acess2net");
for(int i = 0; tests[i]; i ++ )
{
- Net_Open(0, "/tmp/acess2net");
-
Stack_AddDevice("/tmp/acess2net", (char[]){TEST_MAC});
Stack_AddInterface("eth0", 4, (const char[]){TEST_IP}, 24);
Stack_AddRoute(4, "\0\0\0\0", 0, (const char[]){HOST_IP});
teardown:
Stack_Kill();
- Net_Close(0);
- unlink("/tmp/acess2net");
}
+ Net_Close(0);
+ unlink("/tmp/acess2net");
return 0;
}
fprintf(stderr, "\n");
}
+void test_trace(const char *msg, ...)
+{
+ printf("TRACE: [%s] ", gsTestName);
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stdout, msg, args);
+ va_end(args);
+ printf("\n");
+}
+void test_trace_hexdump(const char *hdr, const void *data, size_t len)
+{
+ printf("TRACE: [%s] %s - %zi bytes\n", gsTestName, hdr, len);
+ const uint8_t *data8 = data;
+ while( len > 16 )
+ {
+ printf("TRACE: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ data8[0], data8[1], data8[ 2], data8[ 3], data8[ 4], data8[ 5], data8[ 6], data8[ 7],
+ data8[8], data8[9], data8[10], data8[11], data8[12], data8[13], data8[14], data8[15]
+ );
+ len -= 16;
+ data8 += 16;
+ }
+ printf("TRACE: ");
+ while( len > 8 )
+ {
+ printf("%02x %02x %02x %02x %02x %02x %02x %02x ",
+ data8[0], data8[1], data8[ 2], data8[ 3], data8[ 4], data8[ 5], data8[ 6], data8[ 7]
+ );
+ len -= 8;
+ data8 += 8;
+ }
+ while(len > 0)
+ {
+ printf("%02x ", data8[0]);
+ len --;
+ data8 ++;
+ }
+ printf("\n");
+}
+
#include <assert.h>
#include <sys/select.h>
#include "net.h"
-
+#include <stdint.h>
#define CONNECT_TIMEOUT 10*1000
#define MAX_IFS 4
typedef struct {
- int FD;
+ int FD;
socklen_t addrlen;
struct sockaddr_un addr;
+ FILE *CapFP;
} tIf;
// === PROTOTYPES ===
if(gaInterfaces[IfNum].FD != 0) return 1;
gaInterfaces[IfNum].addrlen = sizeof(gaInterfaces[IfNum].addr);
gaInterfaces[IfNum].FD = Net_int_Open(Path);
+
+ char cappath[] = "testif00.pcap";
+ sprintf(cappath, "testif%i.pcap", IfNum);
+ gaInterfaces[IfNum].CapFP = fopen(cappath, "w");
+ {
+ struct {
+ uint32_t magic_number; /* magic number */
+ uint16_t version_major; /* major version number */
+ uint16_t version_minor; /* minor version number */
+ int32_t thiszone; /* GMT to local correction */
+ uint32_t sigfigs; /* accuracy of timestamps */
+ uint32_t snaplen; /* max length of captured packets, in octets */
+ uint32_t network; /* data link type */
+ } __attribute__((packed)) hdr = {
+ 0xa1b2c3d4,
+ 2,4,
+ 0,
+ 0,
+ 65535,
+ 1
+ };
+ fwrite(&hdr, sizeof(hdr), 1, gaInterfaces[IfNum].CapFP);
+ }
return 0;
}
assert(IfNum < MAX_IFS);
close(gaInterfaces[IfNum].FD);
gaInterfaces[IfNum].FD = 0;
+ fclose(gaInterfaces[IfNum].CapFP);
}
bool WaitOnFD(int FD, bool Write, unsigned int Timeout)
return true;
}
+void Net_int_SavePacket(tIf *If, size_t size, const void *data)
+{
+ struct timeval curtime;
+ gettimeofday(&curtime, NULL);
+ struct {
+ uint32_t ts_sec;
+ uint32_t ts_usec;
+ uint32_t incl_len;
+ uint32_t orig_len;
+ } __attribute__((packed)) hdr = {
+ curtime.tv_sec, curtime.tv_usec,
+ size, size
+ };
+ fwrite(&hdr, sizeof(hdr), 1, If->CapFP);
+ fwrite(data, size, 1, If->CapFP);
+}
+
size_t Net_Receive(int IfNum, size_t MaxLen, void *DestBuf, unsigned int Timeout)
{
assert(IfNum < MAX_IFS);
if( Net_int_EnsureConnected(IfNum) && WaitOnFD(If->FD, false, Timeout) )
{
- return recvfrom(If->FD, DestBuf, MaxLen, 0, &If->addr, &If->addrlen);
+ size_t rv = recvfrom(If->FD, DestBuf, MaxLen, 0, &If->addr, &If->addrlen);
+ Net_int_SavePacket(If, rv, DestBuf);
+ return rv;
}
return 0;
}
if( !WaitOnFD(If->FD, true, CONNECT_TIMEOUT) )
return ;
+ Net_int_SavePacket(If, Length, Buf);
int rv = sendto(If->FD, Buf, Length, 0, &If->addr, If->addrlen);
if( rv < 0 )
perror("Net_Send - send");
fprintf(stderr, "posix_spawn failed: %s", strerror(rv));
return 1;
}
+
+ posix_spawn_file_actions_destroy(&fa);
return 0;
}
phdr[8] = 0;
phdr[9] = pctl;
*(uint16_t*)(phdr+10) = htons(Len);
+
+ //test_trace_hexdump("TCP IPv4 PHdr", phdr, sizeof(phdr));
+
return IP_Checksum(IP_CHECKSUM_START, 12, phdr);
}
else {
TEST_ASSERT( ARP_Pkt_IsResponse(rxlen, rxbuf, BLOB(TEST_IP), BLOB(TEST_MAC)) );
// Request host machine's IP
- ARP_SendRequest(0, HOST_IP_STR);
+ ARP_SendRequest(0, BLOB(HOST_IP));
TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) == 0 );
#if 0
/*
+ * Acess2 Network Stack Tester
+ * - By John Hodge (thePowersGang)
+ *
+ * test_tcp.c
+ * - Tests for the behavior of the "Transmission Control Protocol"
*/
#include "test.h"
#include "tests.h"
size_t rxlen, ofs;
char rxbuf[MTU];
const int ERX_TIMEOUT = 1000; // Expect RX timeout (timeout=failure)
- const int NRX_TIMEOUT = 1000; // Not expect RX timeout (timeout=success)
+ const int NRX_TIMEOUT = 250; // Not expect RX timeout (timeout=success)
const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12";
const size_t testblob_len = sizeof(testblob);
// 1.1. Send SYN packet
TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, testblob_len, testblob);
// Expect a TCP_RST|TCP_ACK with SEQ=0,ACK=SEQ+LEN
- TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) );
+ TEST_ASSERT_rx();
TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234,
0, seq_tx+testblob_len, TCP_RST|TCP_ACK) );
TEST_ASSERT_REL(ofs, ==, rxlen);
// 1.2. Send a SYN,ACK packet
TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN|TCP_ACK, 0x1000, 0, NULL);
// Expect a TCP_RST with SEQ=ACK
- TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) );
+ TEST_ASSERT_rx();
TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) );
TEST_ASSERT_REL(ofs, ==, rxlen);
// 1.3. Send a RST packet
TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST, 0x1000, 0, NULL);
// Expect nothing
- TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 );
+ TEST_ASSERT_no_rx();
// 1.3. Send a RST,ACK packet
TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST|TCP_ACK, 0x1000, 0, NULL);
TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL);
// - Expect RST
TEST_ASSERT_rx();
- TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) );
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP),
+ server_port, local_port, seq_exp, seq_tx+0, TCP_RST) );
// 2.3. Begin hanshake (SYN)
// TODO: "If the SYN bit is set, check the security."
// - Expect SYN,ACK with ACK == SEQ+1
TEST_ASSERT_rx();
TCP_SkipCheck_Seq(true);
- TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), server_port, local_port,
- 0, seq_tx+1, TCP_SYN|TCP_ACK) );
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP),
+ server_port, local_port, 0, seq_tx+1, TCP_SYN|TCP_ACK) );
seq_exp = TCP_Pkt_GetSeq(rxlen, rxbuf, 4);
// >>> STATE: SYN-RECEIVED
// TODO: Test other transitions from SYN-RECEIVED
// 2.4. Complete handshake, TCP ACK
+ seq_exp ++;
+ seq_tx ++;
TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL);
// - Expect nothing
- TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 );
+ TEST_ASSERT_no_rx();
// >>> STATE: ESTABLISHED
return true;
}
+
+bool Test_TCP_SYN_RECEIVED(void)
+{
+ // 1. Get into SYN-RECEIVED
+
+ // 2. Send various non-ACK packets
+ return false;
+}
* threads.c
* - Threads handling
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <threads.h>
#include <threads_int.h>
* POSIX Mutex/Semaphore management
* Wait state
*/
-#define DEBUG 1
+#define DEBUG 0
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>