mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-26 23:16:05 +03:00
#36, basic raw mode tunnel works
This commit is contained in:
parent
5d3b502ec6
commit
186ba79bd1
105
src/iodine.c
105
src/iodine.c
@ -189,58 +189,77 @@ is_sending()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
struct sockaddr_in from;
|
||||||
char data[64*1024];
|
char data[64*1024];
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
struct query q;
|
struct query q;
|
||||||
int rv;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
addrlen = sizeof(struct sockaddr);
|
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) {
|
(struct sockaddr*)&from, &addrlen)) == -1) {
|
||||||
warn("recvfrom");
|
warn("recvfrom");
|
||||||
return 0;
|
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 */
|
rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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];
|
char buf[64*1024];
|
||||||
size_t read;
|
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;
|
return -1;
|
||||||
|
|
||||||
if (downstream_seqno != inpkt.seqno) {
|
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);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
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);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
warn("read");
|
warn("read");
|
||||||
@ -707,7 +726,7 @@ handshake_raw_udp(int dns_fd, int seed)
|
|||||||
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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') {
|
if (len == 5 && in[0] == 'I') {
|
||||||
/* Received IP address */
|
/* Received IP address */
|
||||||
remoteaddr = (in[1] & 0xff);
|
remoteaddr = (in[1] & 0xff);
|
||||||
@ -800,7 +819,7 @@ handshake_case_check(int dns_fd)
|
|||||||
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
if (in[0] == 'z' || in[0] == 'Z') {
|
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);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
if (strncmp("BADLEN", in, 6) == 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);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
/* We got a reply */
|
/* 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);
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(r > 0) {
|
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) {
|
||||||
int accepted_fragsize;
|
int accepted_fragsize;
|
||||||
|
@ -123,6 +123,9 @@ check_user_and_ip(int userid, struct query *q)
|
|||||||
if (!users[userid].active) {
|
if (!users[userid].active) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (users[userid].last_pkt + 60 < time(NULL)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* return early if IP checking is disabled */
|
/* return early if IP checking is disabled */
|
||||||
if (!check_ip) {
|
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));
|
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
|
static int
|
||||||
tunnel_tun(int tun_fd, int dns_fd)
|
tunnel_tun(int tun_fd, int dns_fd)
|
||||||
{
|
{
|
||||||
@ -155,17 +176,22 @@ tunnel_tun(int tun_fd, int dns_fd)
|
|||||||
outlen = sizeof(out);
|
outlen = sizeof(out);
|
||||||
compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
|
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].conn == CONN_DNS_NULL) {
|
||||||
if (users[userid].outpacket.len == 0) {
|
/* if another packet is queued, throw away this one. TODO build queue */
|
||||||
memcpy(users[userid].outpacket.data, out, outlen);
|
if (users[userid].outpacket.len == 0) {
|
||||||
users[userid].outpacket.len = outlen;
|
memcpy(users[userid].outpacket.data, out, outlen);
|
||||||
users[userid].outpacket.offset = 0;
|
users[userid].outpacket.len = outlen;
|
||||||
users[userid].outpacket.sentlen = 0;
|
users[userid].outpacket.offset = 0;
|
||||||
users[userid].outpacket.seqno = (++users[userid].outpacket.seqno & 7);
|
users[userid].outpacket.sentlen = 0;
|
||||||
users[userid].outpacket.fragment = 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;
|
return outlen;
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,7 +816,7 @@ tunnel(int tun_fd, int dns_fd, int bind_fd)
|
|||||||
if (i==0) {
|
if (i==0) {
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < USERS; 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);
|
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;
|
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
|
static void
|
||||||
handle_raw_login(char *packet, int len, struct query *q, int fd, int userid)
|
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;
|
if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN)) return 0;
|
||||||
|
|
||||||
raw_user = RAW_HDR_GET_USR(packet);
|
raw_user = RAW_HDR_GET_USR(packet);
|
||||||
printf("raw %02x\n", packet[RAW_HDR_CMD]);
|
|
||||||
switch (RAW_HDR_GET_CMD(packet)) {
|
switch (RAW_HDR_GET_CMD(packet)) {
|
||||||
case RAW_HDR_CMD_LOGIN:
|
case RAW_HDR_CMD_LOGIN:
|
||||||
/* Login challenge */
|
/* Login challenge */
|
||||||
|
@ -106,7 +106,7 @@ users_waiting_on_reply()
|
|||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active && !users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
users[i].last_pkt + 60 > time(NULL) &&
|
||||||
users[i].q.id != 0) {
|
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,9 @@ all_users_waiting_to_send()
|
|||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active && !users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > now &&
|
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;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user