diff --git a/src/iodine.c b/src/iodine.c index ac52e04..0be3773 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -301,7 +301,6 @@ send_chunk(int fd) avail = packet.len - packet.offset; packet.sentlen = build_hostname(buf + 4, sizeof(buf) - 4, p, avail, topdomain, dataenc); - packet.fragment++; /* Build upstream data header (see doc/proto_xxxxxxxx.txt) */ @@ -316,6 +315,7 @@ send_chunk(int fd) code = (0 << 1) | (packet.sentlen == avail); buf[3] = b32_5to8(code); /* Fourth byte is 4 bits downstream fragment count, 1 bit compression flag */ + packet.fragment++; send_query(fd, buf); } diff --git a/src/iodined.c b/src/iodined.c index 2750877..ff3804f 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -113,6 +113,8 @@ tunnel_tun(int tun_fd, int dns_fd) if (users[userid].outpacket.len == 0) { memcpy(users[userid].outpacket.data, out, outlen); users[userid].outpacket.len = outlen; + users[userid].outpacket.seqno++; + users[userid].outpacket.fragment = 0; return outlen; } else { return 0; @@ -170,7 +172,8 @@ update_downstream_seqno(int dns_fd, int userid, int down_seq, int down_frag) if (users[userid].outpacket.len > 0) { if (debug >= 1) { printf("OUT pkt seq# %d, frag %d (last=%d), fragsize %d of total %d, to user %d\n", - 0, 0, 1, users[userid].outpacket.len, users[userid].outpacket.len, userid); + users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15, + 1, users[userid].outpacket.len, users[userid].outpacket.len, userid); } write_dns(dns_fd, &users[userid].q, users[userid].outpacket.data, users[userid].outpacket.len); users[userid].outpacket.len = 0; @@ -356,6 +359,17 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len) users[userid].last_pkt = time(NULL); memcpy(&(users[userid].q), q, sizeof(struct query)); + if (up_seq == users[userid].inpacket.seqno && + up_frag <= users[userid].inpacket.fragment) { + /* Got repeated old packet, skip it */ + if (debug >= 1) { + printf("IN pkt seq# %d, frag %d, dropped duplicate\n", + up_seq, up_frag); + } + /* Update seqno and maybe send immediate response packet */ + update_downstream_seqno(dns_fd, userid, dn_seq, dn_frag); + return; + } if (up_seq != users[userid].inpacket.seqno) { /* New packet has arrived */ users[userid].inpacket.seqno = up_seq; @@ -604,9 +618,12 @@ tunnel(int tun_fd, int dns_fd, int bind_fd) int j; for (j = 0; j < USERS; j++) { if (users[j].q.id != 0) { - if (debug >= 1) { - printf("OUT pkt seq# %d, frag %d (last=%d), fragsize %d of total %d, to user %d\n", - 0, 0, 1, users[j].outpacket.len, users[j].outpacket.len, j); + if (debug >= 1 && users[j].outpacket.len > 0) { + printf("OUT pkt seq# %d, frag %d (last=%d), " + "fragsize %d of total %d, to user %d\n", + users[j].outpacket.seqno & 7, + users[j].outpacket.fragment & 15, 1, + users[j].outpacket.len, users[j].outpacket.len, j); } write_dns(dns_fd, &(users[j].q), users[j].outpacket.data, users[j].outpacket.len); users[j].outpacket.len = 0;