diff --git a/dns.c b/dns.c index 2fe1d7c..1861d06 100644 --- a/dns.c +++ b/dns.c @@ -32,6 +32,7 @@ #include "read.h" static int host2dns(const char *, char *, int); +static int dns_write(int, int, char *, int, char); struct sockaddr_in peer; char topdomain[256]; @@ -202,7 +203,16 @@ dns_ping(int dns_fd) } data[0] = (pingid & 0xFF00) >> 8; data[1] = (pingid & 0xFF); - dns_write(dns_fd, ++pingid, data, 2, 1); + dns_write(dns_fd, ++pingid, data, 2, 'P'); +} + +void +dns_handshake(int dns_fd) +{ + char data[2]; + data[0] = (pingid & 0xFF00) >> 8; + data[1] = (pingid & 0xFF); + dns_write(dns_fd, ++pingid, data, 2, 'H'); } void @@ -262,8 +272,8 @@ put_hex(char *p, char h) p[1] = to_hex[t]; } -int -dns_write(int fd, int id, char *buf, int len, int ping) +static int +dns_write(int fd, int id, char *buf, int len, char flag) { int avail; int i; @@ -285,8 +295,8 @@ dns_write(int fd, int id, char *buf, int len, int ping) bzero(data, sizeof(data)); d = data; - if (ping) { - *d = 'P'; + if (flag != 0) { + *d = flag; } else { // First byte is 0 for middle packet and 1 for last packet *d = '0' + final; diff --git a/dns.h b/dns.h index d332cfb..781d585 100644 --- a/dns.h +++ b/dns.h @@ -23,8 +23,8 @@ void close_dns(int); int dns_sending(); void dns_handle_tun(int, char *, int); void dns_ping(int); +void dns_handshake(int); void dns_query(int, int, char *, int); -int dns_write(int, int, char *, int, int); int dns_read(int, char *, int); extern struct sockaddr_in peer; diff --git a/iodine.c b/iodine.c index 5d9cc4a..d536c84 100644 --- a/iodine.c +++ b/iodine.c @@ -101,6 +101,52 @@ tunnel(int tun_fd, int dns_fd) return 0; } +static int +handshake(int dns_fd) +{ + int i; + int r; + char *p; + int read; + fd_set fds; + int timeout; + char in[4096]; + struct timeval tv; + + timeout = 1; + + for (i=0;i<5;i++) { + tv.tv_sec = timeout++; + tv.tv_usec = 0; + + dns_handshake(dns_fd); + + FD_ZERO(&fds); + FD_SET(dns_fd, &fds); + + r = select(dns_fd + 1, &fds, NULL, NULL, &tv); + + if(r > 0) { + read = dns_read(dns_fd, in, sizeof(in)); + + if(read <= 0) { + perror("read"); + continue; + } + + p = strchr(in, '-'); + *p++ = '\0'; + + if (tun_setip(in) == 0 && tun_setmtu(atoi(p)) == 0) + return 0; + } + + printf("Retrying...\n"); + } + + return 1; +} + extern char *__progname; static void @@ -192,6 +238,9 @@ main(int argc, char **argv) signal(SIGINT, sigint); + if(handshake(dns_fd)) + goto cleanup2; + if (newroot) { if (chroot(newroot) != 0 || chdir("/") != 0) err(1, "%s", newroot);