mirror of
https://github.com/yarrick/iodine.git
synced 2024-12-27 07:13:33 +02:00
#36, basic raw mode tunnel works
This commit is contained in:
parent
5d3b502ec6
commit
186ba79bd1
3 changed files with 103 additions and 74 deletions
105
src/iodine.c
105
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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue