Updated encoding tests

This commit is contained in:
Erik Ekman 2008-12-06 19:08:14 +00:00 committed by Erik Ekman
parent e5f8b28813
commit 7eb7c02e5f
4 changed files with 111 additions and 52 deletions

View file

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

View file

@ -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], '/');

View file

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

View file

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