Fixed raw UDP mode + improved debugging

This commit is contained in:
frekky 2015-10-27 18:33:44 +08:00
parent c633173fea
commit 3bcfe91769
2 changed files with 78 additions and 62 deletions

View File

@ -1123,14 +1123,7 @@ tunnel_tun(int tun_fd, int dns_fd)
if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
return -1;
/* Check if outgoing buffer can hold data */
if (window_buffer_available(outbuf) < (read / MAX_FRAGSIZE) + 1) {
DEBUG(1, " Outgoing buffer full (%lu/%lu), not adding data!",
outbuf->numitems, outbuf->length);
return -1;
}
DEBUG(2, " IN: %lu bytes on tunnel, compression %d", read, compression_up);
DEBUG(2, " IN: %lu bytes on tunnel, to be compressed: %d", read, compression_up);
if (conn != CONN_DNS_NULL || compression_up) {
datalen = sizeof(out);
@ -1142,6 +1135,13 @@ tunnel_tun(int tun_fd, int dns_fd)
}
if (conn == CONN_DNS_NULL) {
/* Check if outgoing buffer can hold data */
if (window_buffer_available(outbuf) < (read / MAX_FRAGSIZE) + 1) {
DEBUG(1, " Outgoing buffer full (%lu/%lu), not adding data!",
outbuf->numitems, outbuf->length);
return -1;
}
window_add_outgoing_data(outbuf, data, datalen, compression_up);
/* Don't send anything here to respect min. send interval */
} else {
@ -1353,40 +1353,43 @@ client_tunnel(int tun_fd, int dns_fd)
/* TODO: detect DNS servers which drop frequent requests
* TODO: adjust number of pending queries based on current data rate */
sending = window_sending(outbuf);
total = sending;
check_pending_queries();
if (num_pending < windowsize_down && lazymode)
total = MAX(total, windowsize_down - num_pending);
else if (num_pending < 1 && !lazymode)
total = MAX(total, 1);
if (conn == CONN_DNS_NULL) {
sending = window_sending(outbuf);
total = sending;
check_pending_queries();
if (num_pending < windowsize_down && lazymode)
total = MAX(total, windowsize_down - num_pending);
else if (num_pending < 1 && !lazymode)
total = MAX(total, 1);
if (sending > 0 || total > 0 || next_downstream_ack >= 0) {
if (sending > 0 || total > 0 || next_downstream_ack >= 0) {
/* Upstream traffic - this is where all ping/data queries are sent */
if (sending > 0) {
/* More to send - next fragment */
send_next_frag(dns_fd);
} else {
/* Send ping if we didn't send anything yet */
send_ping(dns_fd, 0, next_downstream_ack, (num_pings > 20 && num_pings % 50 == 0));
next_downstream_ack = -1;
/* Upstream traffic - this is where all ping/data queries are sent */
if (sending > 0) {
/* More to send - next fragment */
send_next_frag(dns_fd);
} else {
/* Send ping if we didn't send anything yet */
send_ping(dns_fd, 0, next_downstream_ack, (num_pings > 20 && num_pings % 50 == 0));
next_downstream_ack = -1;
}
sending--;
total--;
QTRACK_DEBUG(3, "Sent a query to fill server lazy buffer to %lu, will send another %d",
lazymode ? windowsize_down : 1, total);
if (sending > 0 || (total > 0 && lazymode)) {
/* TODO: enforce min send interval even if we get new data */
tv = ms_to_timeval(min_send_interval_ms);
tv.tv_usec += 1;
} else if (total > 0 && !lazymode) {
/* use immediate mode send interval if nothing pending */
tv = ms_to_timeval(send_interval_ms);
}
send_ping_soon = 0;
}
sending--;
total--;
QTRACK_DEBUG(3, "Sent a query to fill server lazy buffer to %lu, will send another %d",
lazymode ? windowsize_down : 1, total);
if (sending > 0 || (total > 0 && lazymode)) {
tv = ms_to_timeval(min_send_interval_ms);
tv.tv_usec += 1;
} else if (total > 0 && !lazymode) {
/* use immediate mode send interval if nothing pending */
tv = ms_to_timeval(send_interval_ms);
}
send_ping_soon = 0;
}
if (stats) {
@ -1404,11 +1407,12 @@ client_tunnel(int tun_fd, int dns_fd)
min_send_interval_ms, rtt_total_ms / num_immediate, server_timeout_ms);
fprintf(stderr, " Queries immediate: %5lu, timed out: %4lu target: %4ld ms\n",
num_immediate, num_timeouts, max_timeout_ms);
fprintf(stderr, " Frags resent: %4u, OOS: %4u down frag: %4ld ms\n",
outbuf->resends, inbuf->oos, downstream_timeout_ms);
fprintf(stderr, " TX fragments: %8lu" ", RX: %8lu" ", pings: %8lu" "\n\n",
num_frags_sent, num_frags_recv, num_pings);
if (conn == CONN_DNS_NULL) {
fprintf(stderr, " Frags resent: %4u, OOS: %4u down frag: %4ld ms\n",
outbuf->resends, inbuf->oos, downstream_timeout_ms);
fprintf(stderr, " TX fragments: %8lu" ", RX: %8lu" ", pings: %8lu" "\n\n",
num_frags_sent, num_frags_recv, num_pings);
}
/* update since-last-report stats */
sent_since_report = num_sent;
recv_since_report = num_recv;
@ -1420,11 +1424,12 @@ client_tunnel(int tun_fd, int dns_fd)
if (send_ping_soon) {
tv.tv_sec = 0;
tv.tv_usec = send_ping_soon * 1000;
send_ping_soon = 0;
}
FD_ZERO(&fds);
if (window_buffer_available(outbuf) > 16) {
/* Fill up outgoing buffer with available data
if (conn != CONN_DNS_NULL || window_buffer_available(outbuf) > 16) {
/* Fill up outgoing buffer with available data if it has enough space
* The windowing protocol manages data retransmits, timeouts etc. */
FD_SET(tun_fd, &fds);
}

View File

@ -853,14 +853,18 @@ handle_raw_login(uint8_t *packet, size_t len, struct query *q, int fd, int useri
{
char myhash[16];
if (len < 16) return;
if (len < 16) {
DEBUG(2, "Invalid raw login packet: length %lu < 16 bytes!", len);
return;
}
/* can't use check_authenticated_user_and_ip() since IP address will be different,
so duplicate here except IP address */
if (userid < 0 || userid >= created_users) return;
if (!check_authenticated_user_and_ip(userid, q)) return;
if (userid < 0 || userid >= created_users ||
check_authenticated_user_and_ip(userid, q) != 0) {
DEBUG(2, "User %d not authenticated, ignoring raw login!", userid);
return;
}
DEBUG(1, "IN login raw, len %lu, from user %d", len, userid);
DEBUG(1, "RX-raw: login, len %lu, from user %d", len, userid);
/* User sends hash of seed + 1 */
login_calculate(myhash, 16, password, users[userid].seed + 1);
@ -892,9 +896,9 @@ handle_raw_data(uint8_t *packet, size_t len, struct query *q, struct dnsfd *dns_
/* Update time info for user */
users[userid].last_pkt = time(NULL);
/* copy to packet buffer, update length TODO fix the raw UDP protocol */
/* copy to packet buffer, update length */
DEBUG(3, "IN pkt raw, total %lu, from user %d", len, userid);
DEBUG(3, "RX-raw: full pkt raw, length %lu, from user %d", len, userid);
handle_full_packet(tun_fd, dns_fds, userid, packet, len, 1);
}
@ -910,7 +914,7 @@ handle_raw_ping(struct query *q, int dns_fd, int userid)
/* Update time info for user */
users[userid].last_pkt = time(NULL);
DEBUG(3, "IN ping raw, from user %d", userid);
DEBUG(3, "RX-raw: ping from user %d", userid);
/* Send ping reply */
send_raw(dns_fd, NULL, 0, userid, RAW_HDR_CMD_PING, &q->from, q->fromlen);
@ -920,30 +924,37 @@ static int
raw_decode(uint8_t *packet, size_t len, struct query *q, int dns_fd, struct dnsfd *dns_fds, int tun_fd)
{
int raw_user;
uint8_t raw_cmd;
/* minimum length */
if (len < RAW_HDR_LEN) return 0;
/* should start with header */
if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN)) return 0;
if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN))
return 0;
raw_cmd = RAW_HDR_GET_CMD(packet);
raw_user = RAW_HDR_GET_USR(packet);
DEBUG(3, "TX-raw: client %s, user %d, raw command '%c' length %lu",
format_addr(&q->from, q->fromlen), raw_user, RAW_HDR_GET_CMD(packet), len);
switch (RAW_HDR_GET_CMD(packet)) {
DEBUG(3, "RX-raw: client %s, user %d, raw command 0x%02X, length %lu",
format_addr(&q->from, q->fromlen), raw_user, raw_cmd, len);
packet += RAW_HDR_LEN;
len -= RAW_HDR_LEN;
switch (raw_cmd) {
case RAW_HDR_CMD_LOGIN:
/* Login challenge */
handle_raw_login(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fd, raw_user);
handle_raw_login(packet, len, q, dns_fd, raw_user);
break;
case RAW_HDR_CMD_DATA:
/* Data packet */
handle_raw_data(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fds, tun_fd, raw_user);
handle_raw_data(packet, len, q, dns_fds, tun_fd, raw_user);
break;
case RAW_HDR_CMD_PING:
/* Keepalive packet */
handle_raw_ping(q, dns_fd, raw_user);
break;
default:
DEBUG(1, "Unhandled raw command %02X from user %d", RAW_HDR_GET_CMD(packet), raw_user);
DEBUG(1, "Unhandled raw command %02X from user %d", raw_cmd, raw_user);
break;
}
return 1;