From 3bcfe91769cb2cd9479dee6fe1b9ee7c9eaf7bd3 Mon Sep 17 00:00:00 2001 From: frekky Date: Tue, 27 Oct 2015 18:33:44 +0800 Subject: [PATCH] Fixed raw UDP mode + improved debugging --- src/client.c | 97 +++++++++++++++++++++++++++------------------------- src/server.c | 43 ++++++++++++++--------- 2 files changed, 78 insertions(+), 62 deletions(-) diff --git a/src/client.c b/src/client.c index fc84c6d..0ba56a9 100644 --- a/src/client.c +++ b/src/client.c @@ -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); } diff --git a/src/server.c b/src/server.c index 393f7bc..20a251f 100644 --- a/src/server.c +++ b/src/server.c @@ -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;