From e5370ad95bb09801450854797a3b5fcef8228fb8 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Thu, 6 Aug 2009 20:42:26 +0000 Subject: [PATCH] #36, basic raw mode tunnel works --- src/iodine.c | 105 +++++++++++++++++++++++++++++--------------------- src/iodined.c | 66 +++++++++++++++++-------------- src/user.c | 6 ++- 3 files changed, 103 insertions(+), 74 deletions(-) diff --git a/src/iodine.c b/src/iodine.c index 41cb9cc..5c2e418 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -189,58 +189,77 @@ is_sending() } static int -read_dns(int fd, char *buf, int buflen) +read_dns(int dns_fd, int tun_fd, char *buf, int buflen) /* FIXME: tun_fd needed for raw handling */ { struct sockaddr_in from; char data[64*1024]; socklen_t addrlen; struct query q; - int rv; int r; addrlen = sizeof(struct sockaddr); - if ((r = recvfrom(fd, data, sizeof(data), 0, + if ((r = recvfrom(dns_fd, data, sizeof(data), 0, (struct sockaddr*)&from, &addrlen)) == -1) { warn("recvfrom"); return 0; } - rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r); + if (conn == CONN_DNS_NULL) { + int rv; - /* decode the data header, update seqno and frag before next request */ - if (rv >= 2) { - downstream_seqno = (buf[1] >> 5) & 7; - downstream_fragment = (buf[1] >> 1) & 15; - } - - - if (is_sending()) { - if (chunkid == q.id) { - /* Got ACK on sent packet */ - outpkt.offset += outpkt.sentlen; - if (outpkt.offset == outpkt.len) { - /* Packet completed */ - outpkt.offset = 0; - outpkt.len = 0; - outpkt.sentlen = 0; - - /* If the ack contains unacked frag number but no data, - * send a ping to ack the frag number and get more data*/ - if (rv == 2 && ( - downstream_seqno != down_ack_seqno || - downstream_fragment != down_ack_fragment - )) { - - send_ping(fd); - } - } else { - /* More to send */ - send_chunk(fd); - } + rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r); + /* decode the data header, update seqno and frag before next request */ + if (rv >= 2) { + downstream_seqno = (buf[1] >> 5) & 7; + downstream_fragment = (buf[1] >> 1) & 15; } + + + if (is_sending()) { + if (chunkid == q.id) { + /* Got ACK on sent packet */ + outpkt.offset += outpkt.sentlen; + if (outpkt.offset == outpkt.len) { + /* Packet completed */ + outpkt.offset = 0; + outpkt.len = 0; + outpkt.sentlen = 0; + + /* If the ack contains unacked frag number but no data, + * send a ping to ack the frag number and get more data*/ + if (rv == 2 && ( + downstream_seqno != down_ack_seqno || + downstream_fragment != down_ack_fragment + )) { + + send_ping(dns_fd); + } + } else { + /* More to send */ + send_chunk(dns_fd); + } + } + } + return rv; + } else { /* CONN_RAW_UDP */ + unsigned long datalen; + char buf[64*1024]; + int raw_user; + + /* minimum length */ + if (r < RAW_HDR_LEN) return 0; + /* should start with header */ + if (memcmp(data, raw_header, RAW_HDR_IDENT_LEN)) return 0; + /* should be data packet */ + if (RAW_HDR_GET_CMD(data) != RAW_HDR_CMD_DATA) return 0; + + raw_user = RAW_HDR_GET_USR(data); + if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) &data[RAW_HDR_LEN], r) == Z_OK) { + write_tun(tun_fd, buf, datalen); + } + return 0; } - return rv; } @@ -283,7 +302,7 @@ tunnel_dns(int tun_fd, int dns_fd) char buf[64*1024]; size_t read; - if ((read = read_dns(dns_fd, buf, sizeof(buf))) <= 2) + if ((read = read_dns(dns_fd, tun_fd, buf, sizeof(buf))) <= 2) return -1; if (downstream_seqno != inpkt.seqno) { @@ -578,7 +597,7 @@ handshake_version(int dns_fd, int *seed) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if(read <= 0) { if (read == 0) { @@ -646,7 +665,7 @@ handshake_login(int dns_fd, int seed) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if(read <= 0) { warn("read"); @@ -707,7 +726,7 @@ handshake_raw_udp(int dns_fd, int seed) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - len = read_dns(dns_fd, in, sizeof(in)); + len = read_dns(dns_fd, 0, in, sizeof(in)); if (len == 5 && in[0] == 'I') { /* Received IP address */ remoteaddr = (in[1] & 0xff); @@ -800,7 +819,7 @@ handshake_case_check(int dns_fd) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if (read > 0) { if (in[0] == 'z' || in[0] == 'Z') { @@ -864,7 +883,7 @@ handshake_switch_codec(int dns_fd) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if (read > 0) { if (strncmp("BADLEN", in, 6) == 0) { @@ -918,7 +937,7 @@ handshake_autoprobe_fragsize(int dns_fd) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if (read > 0) { /* We got a reply */ @@ -989,7 +1008,7 @@ handshake_set_fragsize(int dns_fd, int fragsize) r = select(dns_fd + 1, &fds, NULL, NULL, &tv); if(r > 0) { - read = read_dns(dns_fd, in, sizeof(in)); + read = read_dns(dns_fd, 0, in, sizeof(in)); if (read > 0) { int accepted_fragsize; diff --git a/src/iodined.c b/src/iodined.c index 60b84ca..3b7d33d 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -123,6 +123,9 @@ check_user_and_ip(int userid, struct query *q) if (!users[userid].active) { return 1; } + if (users[userid].last_pkt + 60 < time(NULL)) { + return 1; + } /* return early if IP checking is disabled */ if (!check_ip) { @@ -133,6 +136,24 @@ check_user_and_ip(int userid, struct query *q) return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); } +static void +send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q) +{ + char packet[4096]; + int len; + + len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); + + memcpy(packet, raw_header, RAW_HDR_LEN); + memcpy(&packet[RAW_HDR_LEN], buf, len); + + len += RAW_HDR_LEN; + packet[RAW_HDR_CMD] = cmd | (user & 0x0F); + + sendto(fd, packet, len, 0, &q->from, q->fromlen); +} + + static int tunnel_tun(int tun_fd, int dns_fd) { @@ -155,17 +176,22 @@ tunnel_tun(int tun_fd, int dns_fd) outlen = sizeof(out); compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9); - /* if another packet is queued, throw away this one. TODO build queue */ - if (users[userid].outpacket.len == 0) { - memcpy(users[userid].outpacket.data, out, outlen); - users[userid].outpacket.len = outlen; - users[userid].outpacket.offset = 0; - users[userid].outpacket.sentlen = 0; - users[userid].outpacket.seqno = (++users[userid].outpacket.seqno & 7); - users[userid].outpacket.fragment = 0; + if (users[userid].conn == CONN_DNS_NULL) { + /* if another packet is queued, throw away this one. TODO build queue */ + if (users[userid].outpacket.len == 0) { + memcpy(users[userid].outpacket.data, out, outlen); + users[userid].outpacket.len = outlen; + users[userid].outpacket.offset = 0; + users[userid].outpacket.sentlen = 0; + users[userid].outpacket.seqno = (++users[userid].outpacket.seqno & 7); + users[userid].outpacket.fragment = 0; + return outlen; + } else { + return 0; + } + } else { /* CONN_RAW_UDP */ + send_raw(dns_fd, out, outlen, userid, RAW_HDR_CMD_DATA, &users[userid].q); return outlen; - } else { - return 0; } } @@ -790,7 +816,7 @@ tunnel(int tun_fd, int dns_fd, int bind_fd) if (i==0) { int j; for (j = 0; j < USERS; j++) { - if (users[j].q.id != 0) { + if (users[j].q.id != 0 && users[j].conn == CONN_DNS_NULL) { send_chunk(dns_fd, j); } } @@ -848,23 +874,6 @@ handle_full_packet(int tun_fd, int userid) users[userid].inpacket.len = users[userid].inpacket.offset = 0; } -static void -send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q) -{ - char packet[4096]; - int len; - - len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); - - memcpy(packet, raw_header, RAW_HDR_LEN); - memcpy(&packet[RAW_HDR_LEN], buf, len); - - len += RAW_HDR_LEN; - packet[RAW_HDR_CMD] = cmd | (user & 0x0F); - - sendto(fd, packet, len, 0, &q->from, q->fromlen); -} - static void handle_raw_login(char *packet, int len, struct query *q, int fd, int userid) { @@ -931,7 +940,6 @@ raw_decode(char *packet, int len, struct query *q, int dns_fd, int tun_fd) if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN)) return 0; raw_user = RAW_HDR_GET_USR(packet); - printf("raw %02x\n", packet[RAW_HDR_CMD]); switch (RAW_HDR_GET_CMD(packet)) { case RAW_HDR_CMD_LOGIN: /* Login challenge */ diff --git a/src/user.c b/src/user.c index 7250251..54fcd35 100644 --- a/src/user.c +++ b/src/user.c @@ -106,7 +106,7 @@ users_waiting_on_reply() for (i = 0; i < USERS; i++) { if (users[i].active && !users[i].disabled && users[i].last_pkt + 60 > time(NULL) && - users[i].q.id != 0) { + users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) { ret++; } } @@ -144,7 +144,9 @@ all_users_waiting_to_send() for (i = 0; i < USERS; i++) { if (users[i].active && !users[i].disabled && users[i].last_pkt + 60 > now && - users[i].outpacket.len == 0) { + ((users[i].outpacket.len == 0 && users[i].conn == CONN_DNS_NULL) + || users[i].conn == CONN_RAW_UDP)) { + ret = 0; break; }