Updated encoding tests
This commit is contained in:
parent
e5f8b28813
commit
7eb7c02e5f
19
src/common.h
19
src/common.h
|
@ -30,6 +30,23 @@
|
||||||
|
|
||||||
#define QUERY_NAME_SIZE 256
|
#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
|
#if defined IP_RECVDSTADDR
|
||||||
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
|
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
|
||||||
# define dstaddr(x) (CMSG_DATA(x))
|
# define dstaddr(x) (CMSG_DATA(x))
|
||||||
|
@ -44,6 +61,8 @@ struct packet
|
||||||
int sentlen; /* Length of chunk currently transmitted */
|
int sentlen; /* Length of chunk currently transmitted */
|
||||||
int offset; /* Current offset */
|
int offset; /* Current offset */
|
||||||
char data[64*1024]; /* The data */
|
char data[64*1024]; /* The data */
|
||||||
|
char seqno; /* The packet sequence number */
|
||||||
|
char fragment; /* Fragment index */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct query {
|
struct query {
|
||||||
|
|
124
src/iodine.c
124
src/iodine.c
|
@ -69,10 +69,7 @@ static char userid;
|
||||||
/* DNS id for next packet */
|
/* DNS id for next packet */
|
||||||
static uint16_t chunkid;
|
static uint16_t chunkid;
|
||||||
|
|
||||||
/* Base32 encoder used for non-data packets */
|
/* The encoder used for packets
|
||||||
static struct encoder *b32;
|
|
||||||
|
|
||||||
/* The encoder used for data packets
|
|
||||||
* Defaults to Base32, can be changed after handshake */
|
* Defaults to Base32, can be changed after handshake */
|
||||||
static struct encoder *dataenc;
|
static struct encoder *dataenc;
|
||||||
|
|
||||||
|
@ -105,13 +102,11 @@ send_query(int fd, char *hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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];
|
char buf[4096];
|
||||||
|
/* Encode the data and add the topdomain */
|
||||||
buf[0] = cmd;
|
build_hostname(buf, sizeof(buf), data, datalen, topdomain, dataenc);
|
||||||
|
|
||||||
build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32);
|
|
||||||
send_query(fd, buf);
|
send_query(fd, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +115,6 @@ build_hostname(char *buf, size_t buflen,
|
||||||
const char *data, const size_t datalen,
|
const char *data, const size_t datalen,
|
||||||
const char *topdomain, struct encoder *encoder)
|
const char *topdomain, struct encoder *encoder)
|
||||||
{
|
{
|
||||||
int encsize;
|
|
||||||
size_t space;
|
size_t space;
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
|
@ -131,7 +125,7 @@ build_hostname(char *buf, size_t buflen,
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
encsize = encoder->encode(buf, &space, data, datalen);
|
encoder->encode(buf, &space, data, datalen);
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots())
|
||||||
inline_dotify(buf, buflen);
|
inline_dotify(buf, buflen);
|
||||||
|
@ -209,6 +203,8 @@ tunnel_tun(int tun_fd, int dns_fd)
|
||||||
packet.sentlen = 0;
|
packet.sentlen = 0;
|
||||||
packet.offset = 0;
|
packet.offset = 0;
|
||||||
packet.len = outlen;
|
packet.len = outlen;
|
||||||
|
packet.seqno++;
|
||||||
|
packet.fragment = 0;
|
||||||
|
|
||||||
send_chunk(dns_fd);
|
send_chunk(dns_fd);
|
||||||
|
|
||||||
|
@ -287,26 +283,51 @@ tunnel(int tun_fd, int dns_fd)
|
||||||
static void
|
static void
|
||||||
send_chunk(int fd)
|
send_chunk(int fd)
|
||||||
{
|
{
|
||||||
char hex[] = "0123456789ABCDEF";
|
char buf[2048];
|
||||||
char buf[4096];
|
char header[64];
|
||||||
|
char headerenc[64];
|
||||||
int avail;
|
int avail;
|
||||||
int code;
|
|
||||||
char *p;
|
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.data;
|
||||||
p += packet.offset;
|
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);
|
packet.sentlen = sentlen + pkt_encoffset;
|
||||||
|
|
||||||
if (packet.sentlen == avail)
|
|
||||||
code = 1;
|
|
||||||
else
|
|
||||||
code = 0;
|
|
||||||
|
|
||||||
code |= (userid << 1);
|
|
||||||
buf[0] = hex[code];
|
|
||||||
|
|
||||||
|
/* 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);
|
send_query(fd, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +337,7 @@ send_login(int fd, char *login, int len)
|
||||||
char data[19];
|
char data[19];
|
||||||
|
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
data[0] = userid;
|
data[0] = MAKE_HEADER(CMD_LOGIN, userid);
|
||||||
memcpy(&data[1], login, MIN(len, 16));
|
memcpy(&data[1], login, MIN(len, 16));
|
||||||
|
|
||||||
data[17] = (rand_seed >> 8) & 0xff;
|
data[17] = (rand_seed >> 8) & 0xff;
|
||||||
|
@ -324,7 +345,7 @@ send_login(int fd, char *login, int len)
|
||||||
|
|
||||||
rand_seed++;
|
rand_seed++;
|
||||||
|
|
||||||
send_packet(fd, 'L', data, sizeof(data));
|
send_packet(fd, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -338,31 +359,32 @@ send_ping(int fd)
|
||||||
packet.len = 0;
|
packet.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
data[0] = userid;
|
data[0] = MAKE_HEADER(CMD_PING, userid);
|
||||||
data[1] = (rand_seed >> 8) & 0xff;
|
data[1] = (rand_seed >> 8) & 0xff;
|
||||||
data[2] = (rand_seed >> 0) & 0xff;
|
data[2] = (rand_seed >> 0) & 0xff;
|
||||||
|
|
||||||
rand_seed++;
|
rand_seed++;
|
||||||
|
|
||||||
send_packet(fd, 'P', data, sizeof(data));
|
send_packet(fd, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_version(int fd, uint32_t version)
|
send_version(int fd, uint32_t version)
|
||||||
{
|
{
|
||||||
char data[6];
|
char data[7];
|
||||||
|
|
||||||
data[0] = (version >> 24) & 0xff;
|
data[0] = MAKE_HEADER(CMD_VERSION, 0xf);
|
||||||
data[1] = (version >> 16) & 0xff;
|
data[1] = (version >> 24) & 0xff;
|
||||||
data[2] = (version >> 8) & 0xff;
|
data[2] = (version >> 16) & 0xff;
|
||||||
data[3] = (version >> 0) & 0xff;
|
data[3] = (version >> 8) & 0xff;
|
||||||
|
data[4] = (version >> 0) & 0xff;
|
||||||
|
|
||||||
data[4] = (rand_seed >> 8) & 0xff;
|
data[5] = (rand_seed >> 8) & 0xff;
|
||||||
data[5] = (rand_seed >> 0) & 0xff;
|
data[6] = (rand_seed >> 0) & 0xff;
|
||||||
|
|
||||||
rand_seed++;
|
rand_seed++;
|
||||||
|
|
||||||
send_packet(fd, 'V', data, sizeof(data));
|
send_packet(fd, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -371,7 +393,15 @@ send_case_check(int fd)
|
||||||
/* The '+' plus character is not allowed according to RFC.
|
/* The '+' plus character is not allowed according to RFC.
|
||||||
* Expect to get SERVFAIL or similar if it is rejected.
|
* 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));
|
strncat(buf, topdomain, 512 - strlen(buf));
|
||||||
send_query(fd, buf);
|
send_query(fd, buf);
|
||||||
|
@ -380,16 +410,12 @@ send_case_check(int fd)
|
||||||
static void
|
static void
|
||||||
send_codec_switch(int fd, int userid, int bits)
|
send_codec_switch(int fd, int userid, int bits)
|
||||||
{
|
{
|
||||||
char buf[512] = "S00.";
|
char data[2];
|
||||||
if (userid >= 0 && userid < 9) {
|
|
||||||
buf[1] += userid;
|
data[0] = MAKE_HEADER(CMD_VERSION, 0xf);
|
||||||
}
|
data[1] = bits & 0xff;
|
||||||
if (bits >= 0 && bits < 9) {
|
|
||||||
buf[2] += bits;
|
send_packet(fd, data, sizeof(data));
|
||||||
}
|
|
||||||
|
|
||||||
strncat(buf, topdomain, 512 - strlen(buf));
|
|
||||||
send_query(fd, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -705,8 +731,10 @@ main(int argc, char **argv)
|
||||||
device = NULL;
|
device = NULL;
|
||||||
chunkid = 0;
|
chunkid = 0;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
|
||||||
dataenc = get_base32_encoder();
|
dataenc = get_base32_encoder();
|
||||||
|
|
||||||
|
packet.seqno = 0;
|
||||||
|
packet.fragment = 0;
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
|
|
|
@ -38,12 +38,15 @@ START_TEST(test_base32_encode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
for (i = 0; testpairs[i].a != NULL; i++) {
|
||||||
len = sizeof(buf);
|
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(val > 0, strerror(errno));
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
||||||
|
@ -56,12 +59,15 @@ START_TEST(test_base32_decode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
for (i = 0; testpairs[i].a != NULL; i++) {
|
||||||
len = sizeof(buf);
|
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(val > 0, strerror(errno));
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
fail_unless(buf != NULL, "buf == NULL");
|
||||||
|
|
|
@ -66,12 +66,15 @@ START_TEST(test_base64_encode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
for (i = 0; testpairs[i].a != NULL; i++) {
|
||||||
len = sizeof(buf);
|
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(val > 0, strerror(errno));
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
||||||
|
@ -84,12 +87,15 @@ START_TEST(test_base64_decode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
for (i = 0; testpairs[i].a != NULL; i++) {
|
||||||
len = sizeof(buf);
|
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(val > 0, strerror(errno));
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
fail_unless(buf != NULL, "buf == NULL");
|
||||||
|
|
Loading…
Reference in New Issue