From 7eb7c02e5f56d725c6a3999a26f6a7e27e922af6 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Sat, 6 Dec 2008 19:08:14 +0000 Subject: [PATCH] Updated encoding tests --- src/common.h | 19 ++++++++ src/iodine.c | 124 ++++++++++++++++++++++++++++++------------------- tests/base32.c | 10 +++- tests/base64.c | 10 +++- 4 files changed, 111 insertions(+), 52 deletions(-) diff --git a/src/common.h b/src/common.h index c87722c..be318c7 100644 --- a/src/common.h +++ b/src/common.h @@ -30,6 +30,23 @@ #define QUERY_NAME_SIZE 256 +#define MAKE_HEADER(c,u) ((((c) & 0xf) << 4) | ((u) & 0xf)) +#define HEADER_GET_COMMAND(h) (((h) & 0xf0) >> 4) +#define HEADER_GET_USERID(h) ((h) & 0x0f) + +enum header_command { + CMD_VERSION = 0, + CMD_LOGIN, + CMD_CASE_CHECK, + CMD_CODEC_SWITCH, + CMD_DATA, + CMD_PING +}; + +#define DATAHEADER_TOTLEN 3 +#define MAKE_DATAHEADER(last,compressed,fragno) \ + ((((last) & 0x1) << 7) | (((compressed) & 0x1) << 6) | ((fragno) & 0x3f)) + #if defined IP_RECVDSTADDR # define DSTADDR_SOCKOPT IP_RECVDSTADDR # define dstaddr(x) (CMSG_DATA(x)) @@ -44,6 +61,8 @@ struct packet int sentlen; /* Length of chunk currently transmitted */ int offset; /* Current offset */ char data[64*1024]; /* The data */ + char seqno; /* The packet sequence number */ + char fragment; /* Fragment index */ }; struct query { diff --git a/src/iodine.c b/src/iodine.c index a9ca24c..3910c16 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -69,10 +69,7 @@ static char userid; /* DNS id for next packet */ static uint16_t chunkid; -/* Base32 encoder used for non-data packets */ -static struct encoder *b32; - -/* The encoder used for data packets +/* The encoder used for packets * Defaults to Base32, can be changed after handshake */ static struct encoder *dataenc; @@ -105,13 +102,11 @@ send_query(int fd, char *hostname) } static void -send_packet(int fd, char cmd, const char *data, const size_t datalen) +send_packet(int fd, const char *data, const size_t datalen) { char buf[4096]; - - buf[0] = cmd; - - build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32); + /* Encode the data and add the topdomain */ + build_hostname(buf, sizeof(buf), data, datalen, topdomain, dataenc); send_query(fd, buf); } @@ -120,7 +115,6 @@ build_hostname(char *buf, size_t buflen, const char *data, const size_t datalen, const char *topdomain, struct encoder *encoder) { - int encsize; size_t space; char *b; @@ -131,7 +125,7 @@ build_hostname(char *buf, size_t buflen, memset(buf, 0, buflen); - encsize = encoder->encode(buf, &space, data, datalen); + encoder->encode(buf, &space, data, datalen); if (!encoder->places_dots()) inline_dotify(buf, buflen); @@ -209,6 +203,8 @@ tunnel_tun(int tun_fd, int dns_fd) packet.sentlen = 0; packet.offset = 0; packet.len = outlen; + packet.seqno++; + packet.fragment = 0; send_chunk(dns_fd); @@ -287,26 +283,51 @@ tunnel(int tun_fd, int dns_fd) static void send_chunk(int fd) { - char hex[] = "0123456789ABCDEF"; - char buf[4096]; + char buf[2048]; + char header[64]; + char headerenc[64]; int avail; - int code; char *p; + int rawblock; + int headerblocks; + int pkt_encoffset; + int buf_encoffset; + int sentlen; + int i; + size_t enclen; + rawblock = dataenc->blocksize_raw(); + + headerblocks = 1; + while (headerblocks * rawblock < DATAHEADER_TOTLEN) { + headerblocks++; + } + rawblock *= headerblocks; + + pkt_encoffset = rawblock - DATAHEADER_TOTLEN; + buf_encoffset = dataenc->blocksize_encoded() * headerblocks; + + /* Encode all of the message except the first headerblocks block */ p = packet.data; p += packet.offset; - avail = packet.len - packet.offset; + avail = packet.len - packet.offset + pkt_encoffset; + sentlen = build_hostname(buf + buf_encoffset, sizeof(buf) - buf_encoffset, + &p[pkt_encoffset], avail, topdomain, dataenc); - packet.sentlen = build_hostname(buf + 1, sizeof(buf) - 1, p, avail, topdomain, dataenc); - - if (packet.sentlen == avail) - code = 1; - else - code = 0; - - code |= (userid << 1); - buf[0] = hex[code]; + packet.sentlen = sentlen + pkt_encoffset; + /* Then encode the header and maybe some pkt data */ + header[0] = MAKE_HEADER(CMD_DATA, userid); + header[1] = packet.seqno; + header[2] = MAKE_DATAHEADER(avail == sentlen, 1, packet.fragment++); + for (i = 0; i < pkt_encoffset; i++) { + header[i + DATAHEADER_TOTLEN] = p[i]; + } + /* Encode the first part, copy it into the buffer */ + dataenc->encode(headerenc, &enclen, header, DATAHEADER_TOTLEN + pkt_encoffset); + for (i = 0; i < enclen; i++) { + buf[i] = headerenc[i]; + } send_query(fd, buf); } @@ -316,7 +337,7 @@ send_login(int fd, char *login, int len) char data[19]; memset(data, 0, sizeof(data)); - data[0] = userid; + data[0] = MAKE_HEADER(CMD_LOGIN, userid); memcpy(&data[1], login, MIN(len, 16)); data[17] = (rand_seed >> 8) & 0xff; @@ -324,7 +345,7 @@ send_login(int fd, char *login, int len) rand_seed++; - send_packet(fd, 'L', data, sizeof(data)); + send_packet(fd, data, sizeof(data)); } static void @@ -338,31 +359,32 @@ send_ping(int fd) packet.len = 0; } - data[0] = userid; + data[0] = MAKE_HEADER(CMD_PING, userid); data[1] = (rand_seed >> 8) & 0xff; data[2] = (rand_seed >> 0) & 0xff; rand_seed++; - send_packet(fd, 'P', data, sizeof(data)); + send_packet(fd, data, sizeof(data)); } static void send_version(int fd, uint32_t version) { - char data[6]; + char data[7]; - data[0] = (version >> 24) & 0xff; - data[1] = (version >> 16) & 0xff; - data[2] = (version >> 8) & 0xff; - data[3] = (version >> 0) & 0xff; + data[0] = MAKE_HEADER(CMD_VERSION, 0xf); + data[1] = (version >> 24) & 0xff; + data[2] = (version >> 16) & 0xff; + data[3] = (version >> 8) & 0xff; + data[4] = (version >> 0) & 0xff; - data[4] = (rand_seed >> 8) & 0xff; - data[5] = (rand_seed >> 0) & 0xff; + data[5] = (rand_seed >> 8) & 0xff; + data[6] = (rand_seed >> 0) & 0xff; rand_seed++; - send_packet(fd, 'V', data, sizeof(data)); + send_packet(fd, data, sizeof(data)); } static void @@ -371,7 +393,15 @@ send_case_check(int fd) /* The '+' plus character is not allowed according to RFC. * Expect to get SERVFAIL or similar if it is rejected. */ - char buf[512] = "zZ+-aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY1234."; + char buf[512] = "__zZ+-aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY1234."; + char header = MAKE_HEADER(CMD_CASE_CHECK, userid); + char enc[5]; + unsigned enclen; + + dataenc->encode(enc, &enclen, &header, 1); + /* Encode header into start of message */ + buf[0] = enc[0]; + buf[1] = enc[1]; strncat(buf, topdomain, 512 - strlen(buf)); send_query(fd, buf); @@ -380,16 +410,12 @@ send_case_check(int fd) static void send_codec_switch(int fd, int userid, int bits) { - char buf[512] = "S00."; - if (userid >= 0 && userid < 9) { - buf[1] += userid; - } - if (bits >= 0 && bits < 9) { - buf[2] += bits; - } - - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + char data[2]; + + data[0] = MAKE_HEADER(CMD_VERSION, 0xf); + data[1] = bits & 0xff; + + send_packet(fd, data, sizeof(data)); } static int @@ -705,8 +731,10 @@ main(int argc, char **argv) device = NULL; chunkid = 0; - b32 = get_base32_encoder(); dataenc = get_base32_encoder(); + + packet.seqno = 0; + packet.fragment = 0; #if !defined(BSD) && !defined(__GLIBC__) __progname = strrchr(argv[0], '/'); diff --git a/tests/base32.c b/tests/base32.c index 849790c..723490b 100644 --- a/tests/base32.c +++ b/tests/base32.c @@ -38,12 +38,15 @@ START_TEST(test_base32_encode) { size_t len; char buf[4096]; + struct encoder *b32; int val; int i; + b32 = get_base32_encoder(); + for (i = 0; testpairs[i].a != NULL; i++) { len = sizeof(buf); - val = base32_encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a)); + val = b32->encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a)); fail_unless(val > 0, strerror(errno)); fail_unless(strcmp(buf, testpairs[i].b) == 0, @@ -56,12 +59,15 @@ START_TEST(test_base32_decode) { size_t len; char buf[4096]; + struct encoder *b32; int val; int i; + + b32 = get_base32_encoder(); for (i = 0; testpairs[i].a != NULL; i++) { len = sizeof(buf); - val = base32_decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b)); + val = b32->decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b)); fail_unless(val > 0, strerror(errno)); fail_unless(buf != NULL, "buf == NULL"); diff --git a/tests/base64.c b/tests/base64.c index 8e8ca0f..99f629c 100644 --- a/tests/base64.c +++ b/tests/base64.c @@ -66,12 +66,15 @@ START_TEST(test_base64_encode) { size_t len; char buf[4096]; + struct encoder *b64; int val; int i; + b64 = get_base64_encoder(); + for (i = 0; testpairs[i].a != NULL; i++) { len = sizeof(buf); - val = base64_encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a)); + val = b64->encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a)); fail_unless(val > 0, strerror(errno)); fail_unless(strcmp(buf, testpairs[i].b) == 0, @@ -84,12 +87,15 @@ START_TEST(test_base64_decode) { size_t len; char buf[4096]; + struct encoder *b64; int val; int i; + b64 = get_base64_encoder(); + for (i = 0; testpairs[i].a != NULL; i++) { len = sizeof(buf); - val = base64_decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b)); + val = b64->decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b)); fail_unless(val > 0, strerror(errno)); fail_unless(buf != NULL, "buf == NULL");