mirror of
https://github.com/yarrick/iodine.git
synced 2024-12-01 05:55:12 +00:00
Cleaned up client send_packet functions, protocol changes
This commit is contained in:
parent
5ceb6312b4
commit
5233c2ab1e
305
src/client.c
305
src/client.c
@ -426,13 +426,22 @@ send_raw_data(uint8_t *data, size_t datalen)
|
||||
static int
|
||||
send_packet(char cmd, const uint8_t *data, const size_t datalen)
|
||||
/* Base32 encodes data and sends as single DNS query
|
||||
* cmd becomes first byte of query, followed by hex userid, encoded
|
||||
* data and 3 bytes base32 encoded CMC
|
||||
* Returns ID of sent query */
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
uint8_t buf[512], data_with_cmc[datalen + 2];
|
||||
|
||||
if (data)
|
||||
memcpy(data_with_cmc, data, datalen);
|
||||
*(uint16_t *) (data_with_cmc + datalen) = this.rand_seed;
|
||||
this.rand_seed++;
|
||||
|
||||
buf[0] = cmd;
|
||||
buf[1] = this.userid_char;
|
||||
|
||||
build_hostname(buf, sizeof(buf), data, datalen, this.topdomain, b32, this.hostname_maxlen, 1);
|
||||
build_hostname(buf, sizeof(buf), data_with_cmc, datalen + 2,
|
||||
this.topdomain, b32, this.hostname_maxlen, 2);
|
||||
|
||||
return send_query(buf);
|
||||
}
|
||||
@ -442,27 +451,26 @@ send_ping(int ping_response, int ack, int set_timeout)
|
||||
{
|
||||
this.num_pings++;
|
||||
if (this.conn == CONN_DNS_NULL) {
|
||||
uint8_t data[13];
|
||||
uint8_t data[12];
|
||||
int id;
|
||||
|
||||
/* Build ping header (see doc/proto_xxxxxxxx.txt) */
|
||||
data[0] = this.userid;
|
||||
data[1] = ack & 0xFF;
|
||||
data[0] = ack & 0xFF;
|
||||
|
||||
if (this.outbuf && this.inbuf) {
|
||||
data[2] = this.outbuf->windowsize & 0xff; /* Upstream window size */
|
||||
data[3] = this.inbuf->windowsize & 0xff; /* Downstream window size */
|
||||
data[4] = this.outbuf->start_seq_id & 0xff; /* Upstream window start */
|
||||
data[5] = this.inbuf->start_seq_id & 0xff; /* Downstream window start */
|
||||
data[1] = this.outbuf->windowsize & 0xff; /* Upstream window size */
|
||||
data[2] = this.inbuf->windowsize & 0xff; /* Downstream window size */
|
||||
data[3] = this.outbuf->start_seq_id & 0xff; /* Upstream window start */
|
||||
data[4] = this.inbuf->start_seq_id & 0xff; /* Downstream window start */
|
||||
}
|
||||
|
||||
*(uint16_t *) (data + 6) = htons(this.server_timeout_ms);
|
||||
*(uint16_t *) (data + 8) = htons(this.downstream_timeout_ms);
|
||||
*(uint16_t *) (data + 5) = htons(this.server_timeout_ms);
|
||||
*(uint16_t *) (data + 7) = htons(this.downstream_timeout_ms);
|
||||
|
||||
/* update server frag/lazy timeout, ack flag, respond with ping flag */
|
||||
data[10] = ((set_timeout & 1) << 4) | ((set_timeout & 1) << 3) | ((ack < 0 ? 0 : 1) << 2) | (ping_response & 1);
|
||||
data[11] = (this.rand_seed >> 8) & 0xff;
|
||||
data[12] = (this.rand_seed >> 0) & 0xff;
|
||||
data[9] = ((set_timeout & 1) << 4) | ((set_timeout & 1) << 3) | ((ack < 0 ? 0 : 1) << 2) | (ping_response & 1);
|
||||
data[10] = (this.rand_seed >> 8) & 0xff;
|
||||
data[11] = (this.rand_seed >> 0) & 0xff;
|
||||
this.rand_seed += 1;
|
||||
|
||||
DEBUG(3, " SEND PING: respond %d, ack %d, %s(server %ld ms, downfrag %ld ms), flags %02X",
|
||||
@ -1309,116 +1317,17 @@ client_tunnel()
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
send_login(char *login, int len)
|
||||
{
|
||||
uint8_t data[19];
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
data[0] = this.userid;
|
||||
memcpy(&data[1], login, MIN(len, 16));
|
||||
|
||||
data[17] = (this.rand_seed >> 8) & 0xff;
|
||||
data[18] = (this.rand_seed >> 0) & 0xff;
|
||||
|
||||
this.rand_seed++;
|
||||
|
||||
send_packet('l', data, sizeof(data));
|
||||
}
|
||||
|
||||
static void
|
||||
send_fragsize_probe(uint16_t fragsize)
|
||||
{
|
||||
uint8_t probedata[256];
|
||||
uint8_t buf[MAX_FRAGSIZE];
|
||||
uint8_t hdr[3];
|
||||
size_t hdr_len_enc = 6;
|
||||
|
||||
buf[0] = 'r'; /* Probe downstream fragsize packet */
|
||||
|
||||
hdr[0] = this.userid;
|
||||
*(uint16_t *) (hdr + 1) = htons(fragsize);
|
||||
|
||||
b32->encode(buf + 1, &hdr_len_enc, hdr, 3);
|
||||
/* build a large query domain which is random and maximum size,
|
||||
* will also take up maximum space in the return packet */
|
||||
memset(probedata, MAX(1, this.rand_seed & 0xff), sizeof(probedata));
|
||||
probedata[1] = MAX(1, (this.rand_seed >> 8) & 0xff);
|
||||
this.rand_seed++;
|
||||
|
||||
/* Note: must either be same, or larger, than send_chunk() */
|
||||
build_hostname(buf, sizeof(buf), probedata, sizeof(probedata), this.topdomain,
|
||||
this.dataenc, this.hostname_maxlen, 6);
|
||||
|
||||
send_query(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
send_set_downstream_fragsize(uint16_t fragsize)
|
||||
{
|
||||
uint8_t data[5];
|
||||
|
||||
data[0] = this.userid;
|
||||
*(uint16_t *) (data + 1) = htons(fragsize);
|
||||
data[3] = (this.rand_seed >> 8) & 0xff;
|
||||
data[4] = (this.rand_seed >> 0) & 0xff;
|
||||
|
||||
this.rand_seed++;
|
||||
|
||||
send_packet('n', data, sizeof(data));
|
||||
}
|
||||
|
||||
static void
|
||||
send_version(uint32_t version)
|
||||
{
|
||||
uint8_t data[6];
|
||||
|
||||
version = htonl(version);
|
||||
*(uint32_t *) data = version;
|
||||
|
||||
data[4] = (this.rand_seed >> 8) & 0xff;
|
||||
data[5] = (this.rand_seed >> 0) & 0xff;
|
||||
|
||||
this.rand_seed++;
|
||||
|
||||
send_packet('v', data, sizeof(data));
|
||||
}
|
||||
|
||||
static void
|
||||
send_ip_request()
|
||||
{
|
||||
uint8_t buf[512] = "i____.";
|
||||
buf[1] = b32_5to8(this.userid);
|
||||
|
||||
buf[2] = b32_5to8((this.rand_seed >> 10) & 0x1f);
|
||||
buf[3] = b32_5to8((this.rand_seed >> 5) & 0x1f);
|
||||
buf[4] = b32_5to8((this.rand_seed ) & 0x1f);
|
||||
this.rand_seed++;
|
||||
|
||||
strncat((char *)buf, this.topdomain, 512 - strlen((char *)buf));
|
||||
send_query(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
send_raw_udp_login(int seed)
|
||||
{
|
||||
char buf[16];
|
||||
login_calculate(buf, 16, this.password, seed + 1);
|
||||
|
||||
send_raw((uint8_t *) buf, sizeof(buf), RAW_HDR_CMD_LOGIN);
|
||||
}
|
||||
|
||||
static void
|
||||
send_upenctest(char *s)
|
||||
/* NOTE: String may be at most 63-4=59 chars to fit in 1 dns chunk. */
|
||||
{
|
||||
char buf[512] = "z___";
|
||||
char buf[512] = "z___.";
|
||||
size_t buf_space = 3;
|
||||
|
||||
buf[1] = b32_5to8((this.rand_seed >> 10) & 0x1f);
|
||||
buf[2] = b32_5to8((this.rand_seed >> 5) & 0x1f);
|
||||
buf[3] = b32_5to8((this.rand_seed ) & 0x1f);
|
||||
b32->encode((uint8_t *)buf + 1, &buf_space,(uint8_t *)&this.rand_seed, sizeof(this.rand_seed));
|
||||
this.rand_seed++;
|
||||
|
||||
/* Append test string without changing it */
|
||||
strncat(buf, s, 512 - strlen(buf));
|
||||
strncat(buf, ".", 512 - strlen(buf));
|
||||
strncat(buf, this.topdomain, 512 - strlen(buf));
|
||||
@ -1426,59 +1335,110 @@ send_upenctest(char *s)
|
||||
}
|
||||
|
||||
static void
|
||||
send_downenctest(char downenc, int variant, char *s, int slen)
|
||||
/* Note: content/handling of s is not defined yet. */
|
||||
send_downenctest(char downenc, int variant)
|
||||
{
|
||||
char buf[512] = "y_____.";
|
||||
uint8_t buf[512] = "y_____.", hdr[3];
|
||||
|
||||
buf[1] = tolower(downenc);
|
||||
buf[2] = b32_5to8(variant);
|
||||
|
||||
buf[3] = b32_5to8((this.rand_seed >> 10) & 0x1f);
|
||||
buf[4] = b32_5to8((this.rand_seed >> 5) & 0x1f);
|
||||
buf[5] = b32_5to8((this.rand_seed ) & 0x1f);
|
||||
hdr[0] = variant;
|
||||
*(uint16_t *) (hdr + 1) = this.rand_seed;
|
||||
this.rand_seed++;
|
||||
|
||||
strncat(buf, this.topdomain, 512 - strlen(buf));
|
||||
send_query((uint8_t *)buf);
|
||||
build_hostname(buf, sizeof(buf), hdr, sizeof(hdr),
|
||||
this.topdomain, b32, this.hostname_maxlen, 2);
|
||||
|
||||
send_query(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
send_codec_switch(int bits)
|
||||
send_version(uint32_t version)
|
||||
{
|
||||
char buf[512] = "s_____.";
|
||||
buf[1] = b32_5to8(this.userid);
|
||||
buf[2] = b32_5to8(bits);
|
||||
uint8_t data[4], buf[512];
|
||||
|
||||
buf[3] = b32_5to8((this.rand_seed >> 10) & 0x1f);
|
||||
buf[4] = b32_5to8((this.rand_seed >> 5) & 0x1f);
|
||||
buf[5] = b32_5to8((this.rand_seed ) & 0x1f);
|
||||
this.rand_seed++;
|
||||
*(uint32_t *) data = htonl(version);
|
||||
|
||||
strncat(buf, this.topdomain, 512 - strlen(buf));
|
||||
send_query((uint8_t *)buf);
|
||||
buf[0] = 'v';
|
||||
|
||||
build_hostname(buf, sizeof(buf), data, sizeof(data),
|
||||
this.topdomain, b32, this.hostname_maxlen, 1);
|
||||
|
||||
send_query(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
send_server_options(int lazy, int compression, char denc, char *options)
|
||||
/* Options must be length >=4 */
|
||||
send_login(char *login, int len)
|
||||
{
|
||||
char buf[512] = "oU3___CMC.";
|
||||
buf[1] = b32_5to8(this.userid);
|
||||
send_packet('l', (uint8_t *) login, len);
|
||||
}
|
||||
|
||||
options[0] = tolower(denc);
|
||||
options[1] = lazy ? 'l' : 'i';
|
||||
options[2] = compression ? 'c' : 'd';
|
||||
options[3] = 0;
|
||||
strncpy(buf + 3, options, 3);
|
||||
static void
|
||||
send_fragsize_probe(uint16_t fragsize)
|
||||
{
|
||||
uint8_t data[256];
|
||||
|
||||
buf[6] = b32_5to8((this.rand_seed >> 10) & 0x1f);
|
||||
buf[7] = b32_5to8((this.rand_seed >> 5) & 0x1f);
|
||||
buf[8] = b32_5to8((this.rand_seed) & 0x1f);
|
||||
/* Probe downstream fragsize packet */
|
||||
|
||||
/* build a large query domain which is random and maximum size,
|
||||
* will also take up maximum space in the return packet */
|
||||
memset(data, MAX(1, this.rand_seed & 0xff), sizeof(data));
|
||||
|
||||
*(uint16_t *) (data) = htons(fragsize);
|
||||
this.rand_seed++;
|
||||
|
||||
strncat(buf, this.topdomain, 512 - strlen(buf));
|
||||
send_query((uint8_t *)buf);
|
||||
send_packet('r', data, sizeof(data));
|
||||
}
|
||||
|
||||
static void
|
||||
send_set_downstream_fragsize(uint16_t fragsize)
|
||||
{
|
||||
uint8_t data[2];
|
||||
*(uint16_t *) data = htons(fragsize);
|
||||
|
||||
send_packet('n', data, sizeof(data));
|
||||
}
|
||||
|
||||
static void
|
||||
send_ip_request()
|
||||
{
|
||||
send_packet('i', NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
send_raw_udp_login(int seed)
|
||||
{
|
||||
char buf[16];
|
||||
login_calculate(buf, sizeof(buf), this.password, seed + 1);
|
||||
|
||||
send_raw((uint8_t *) buf, sizeof(buf), RAW_HDR_CMD_LOGIN);
|
||||
}
|
||||
|
||||
static void
|
||||
send_codec_switch(uint8_t bits)
|
||||
{
|
||||
send_packet('s', &bits, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
send_server_options(int lazy, int compression, char denc)
|
||||
{
|
||||
uint8_t optflags = 0;
|
||||
|
||||
if (denc == 'T') /* Base32 */
|
||||
optflags |= 1 << 6;
|
||||
else if (denc == 'S') /* Base64 */
|
||||
optflags |= 1 << 5;
|
||||
else if (denc == 'U') /* Base64u */
|
||||
optflags |= 1 << 4;
|
||||
else if (denc == 'V') /* Base128 */
|
||||
optflags |= 1 << 3;
|
||||
else if (denc == 'R') /* Raw */
|
||||
optflags |= 1 << 2;
|
||||
|
||||
optflags |= (compression & 1) << 1;
|
||||
optflags |= lazy & 1;
|
||||
|
||||
send_packet('o', &optflags, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1498,25 +1458,27 @@ handshake_version(int *seed)
|
||||
read = handshake_waitdns(in, sizeof(in), 'V', i+1);
|
||||
|
||||
if (read >= 9) {
|
||||
payload = (((in[4] & 0xff) << 24) |
|
||||
((in[5] & 0xff) << 16) |
|
||||
((in[6] & 0xff) << 8) |
|
||||
((in[7] & 0xff)));
|
||||
payload = ntohl(*(uint32_t *) (in + 4));
|
||||
|
||||
if (strncmp("VACK", (char *)in, 4) == 0) {
|
||||
/* Payload is login challenge */
|
||||
*seed = payload;
|
||||
this.userid = in[8];
|
||||
this.userid_char = hex[this.userid & 15];
|
||||
this.userid_char2 = hex2[this.userid & 15];
|
||||
|
||||
DEBUG(2, "Login challenge: 0x%08x", *seed);
|
||||
|
||||
fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n",
|
||||
PROTOCOL_VERSION, this.userid);
|
||||
return 0;
|
||||
} else if (strncmp("VNAK", (char *)in, 4) == 0) {
|
||||
/* Payload is server version */
|
||||
warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up",
|
||||
PROTOCOL_VERSION, payload);
|
||||
return 1;
|
||||
} else if (strncmp("VFUL", (char *)in, 4) == 0) {
|
||||
/* Payload is max number of users on server */
|
||||
warnx("Server full, all %d slots are taken. Try again later", payload);
|
||||
return 1;
|
||||
}
|
||||
@ -1547,11 +1509,12 @@ handshake_login(int seed)
|
||||
send_login(login, 16);
|
||||
|
||||
read = handshake_waitdns(in, sizeof(in), 'L', i+1);
|
||||
in[MIN(read, sizeof(in))] = 0; /* Null terminate */
|
||||
|
||||
if (read > 0) {
|
||||
int netmask;
|
||||
if (strncmp("LNAK", in, 4) == 0) {
|
||||
fprintf(stderr, "Bad this.password\n");
|
||||
fprintf(stderr, "Bad password\n");
|
||||
return 1;
|
||||
} else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d",
|
||||
server, client, &mtu, &netmask) == 4) {
|
||||
@ -1567,7 +1530,7 @@ handshake_login(int seed)
|
||||
errx(4, "Failed to set IP and MTU");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Received bad handshake\n");
|
||||
fprintf(stderr, "Received bad handshake: %.*s\n", read, in);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1682,9 +1645,7 @@ handshake_upenctest(char *s)
|
||||
char in[4096];
|
||||
unsigned char *uin = (unsigned char *) in;
|
||||
unsigned char *us = (unsigned char *) s;
|
||||
int i;
|
||||
int read;
|
||||
int slen;
|
||||
int i, read, slen;
|
||||
|
||||
slen = strlen(s);
|
||||
for (i=0; this.running && i<3 ;i++) {
|
||||
@ -1850,7 +1811,7 @@ handshake_downenctest(char trycodec)
|
||||
|
||||
for (i=0; this.running && i<3 ;i++) {
|
||||
|
||||
send_downenctest(trycodec, 1, NULL, 0);
|
||||
send_downenctest(trycodec, 1);
|
||||
|
||||
read = handshake_waitdns(in, sizeof(in), 'Y', i+1);
|
||||
|
||||
@ -1950,7 +1911,7 @@ handshake_qtypetest(int timeout)
|
||||
byte values can be returned, which is needed for NULL/PRIVATE
|
||||
to work. */
|
||||
|
||||
send_downenctest(trycodec, 1, NULL, 0);
|
||||
send_downenctest(trycodec, 1);
|
||||
|
||||
read = handshake_waitdns(in, sizeof(in), 'Y', timeout);
|
||||
|
||||
@ -2073,7 +2034,7 @@ handshake_edns0_check()
|
||||
|
||||
for (i=0; this.running && i<3 ;i++) {
|
||||
|
||||
send_downenctest(trycodec, 1, NULL, 0);
|
||||
send_downenctest(trycodec, 1);
|
||||
|
||||
read = handshake_waitdns(in, sizeof(in), 'Y', i+1);
|
||||
|
||||
@ -2162,10 +2123,9 @@ codec_revert:
|
||||
void
|
||||
handshake_switch_options(int lazy, int compression, char denc)
|
||||
{
|
||||
char in[4096];
|
||||
char in[100];
|
||||
int read;
|
||||
char *dname, *comp_status, *lazy_status;
|
||||
char opts[4];
|
||||
|
||||
comp_status = compression ? "enabled" : "disabled";
|
||||
|
||||
@ -2185,11 +2145,13 @@ handshake_switch_options(int lazy, int compression, char denc)
|
||||
lazy_status, dname, comp_status);
|
||||
for (int i = 0; this.running && i < 5; i++) {
|
||||
|
||||
send_server_options(lazy, compression, denc, opts);
|
||||
send_server_options(lazy, compression, denc);
|
||||
|
||||
read = handshake_waitdns(in, sizeof(in) - 1, 'O', i + 1);
|
||||
|
||||
if (read > 0) {
|
||||
in[read] = 0; /* zero terminate */
|
||||
|
||||
if (strncmp("BADLEN", in, 6) == 0) {
|
||||
fprintf(stderr, "Server got bad message length.\n");
|
||||
goto opt_revert;
|
||||
@ -2199,12 +2161,15 @@ handshake_switch_options(int lazy, int compression, char denc)
|
||||
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
||||
fprintf(stderr, "Server rejected the selected options.\n");
|
||||
goto opt_revert;
|
||||
} else if (strcasecmp(dname, in) == 0) {
|
||||
fprintf(stderr, "Switched server options, using downsteam codec %s.\n", in);
|
||||
this.lazymode = lazy;
|
||||
this.compression_down = compression;
|
||||
this.downenc = denc;
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "Got invalid response. ");
|
||||
}
|
||||
fprintf(stderr, "Switched server options successfully. (%s)\n", opts);
|
||||
this.lazymode = lazy;
|
||||
this.compression_down = compression;
|
||||
this.downenc = denc;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Retrying options switch...\n");
|
||||
|
Loading…
Reference in New Issue
Block a user