7b1a084307e034fcbd93bb4c3ed51224a3ff57ad
[debian/iodine.git] / src / iodine.c
1 /*
2  * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <unistd.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <sys/time.h>
28 #include <sys/socket.h>
29 #include <fcntl.h>
30 #include <err.h>
31 #include <grp.h>
32 #include <pwd.h>
33 #include <arpa/inet.h>
34 #include <zlib.h>
35 #include <arpa/nameser.h>
36 #ifdef DARWIN
37 #include <arpa/nameser8_compat.h>
38 #endif
39
40 #include "common.h"
41 #include "encoding.h"
42 #include "base32.h"
43 #include "base64.h"
44 #include "dns.h"
45 #include "login.h"
46 #include "tun.h"
47 #include "version.h"
48
49 static void send_ping(int fd);
50 static void send_chunk(int fd);
51 static int build_hostname(char *buf, size_t buflen, 
52         const char *data, const size_t datalen, 
53         const char *topdomain, struct encoder *encoder);
54
55 static int running = 1;
56 static char password[33];
57
58 static struct sockaddr_in nameserv;
59 static char *topdomain;
60
61 static uint16_t rand_seed;
62 static int downstream_seqno;
63 static int downstream_fragment;
64 static int down_ack_seqno;
65 static int down_ack_fragment;
66
67 static int max_downstream_frag_size;
68 static int autodetect_frag_size;
69
70 /* Current up/downstream IP packet */
71 static struct packet outpkt;
72 static struct packet inpkt;
73
74 /* My userid at the server */
75 static char userid;
76
77 /* DNS id for next packet */
78 static uint16_t chunkid;
79
80 /* Base32 encoder used for non-data packets */
81 static struct encoder *b32;
82
83 /* The encoder used for data packets
84  * Defaults to Base32, can be changed after handshake */
85 static struct encoder *dataenc;
86
87 /* result of case preservation check done after login */
88 static int case_preserved;
89
90 #if !defined(BSD) && !defined(__GLIBC__)
91 static char *__progname;
92 #endif
93
94 static void
95 sighandler(int sig) 
96 {
97         running = 0;
98 }
99
100 static void
101 send_query(int fd, char *hostname)
102 {
103         char packet[4096];
104         struct query q;
105         size_t len;
106
107         q.id = ++chunkid;
108         q.type = T_NULL;
109
110         len = dns_encode(packet, sizeof(packet), &q, QR_QUERY, hostname, strlen(hostname));
111
112         sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv));
113 }
114
115 static void
116 send_packet(int fd, char cmd, const char *data, const size_t datalen)
117 {
118         char buf[4096];
119
120         buf[0] = cmd;
121         
122         build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32);
123         send_query(fd, buf);
124 }
125
126 static int
127 build_hostname(char *buf, size_t buflen, 
128                 const char *data, const size_t datalen, 
129                 const char *topdomain, struct encoder *encoder)
130 {
131         int encsize;
132         size_t space;
133         char *b;
134
135         space = MIN(0xFF, buflen) - strlen(topdomain) - 5;
136         if (!encoder->places_dots())
137                 space -= (space / 57); /* space for dots */
138
139         memset(buf, 0, buflen);
140         
141         encsize = encoder->encode(buf, &space, data, datalen);
142
143         if (!encoder->places_dots())
144                 inline_dotify(buf, buflen);
145
146         b = buf;
147         b += strlen(buf);
148
149         if (*b != '.') 
150                 *b++ = '.';
151
152         strncpy(b, topdomain, strlen(topdomain)+1);
153
154         return space;
155 }
156
157 static int
158 is_sending()
159 {
160         return (outpkt.len != 0);
161 }
162
163 static int
164 read_dns(int fd, char *buf, int buflen)
165 {
166         struct sockaddr_in from;
167         char data[64*1024];
168         socklen_t addrlen;
169         struct query q;
170         int rv;
171         int r;
172
173         addrlen = sizeof(struct sockaddr);
174         if ((r = recvfrom(fd, data, sizeof(data), 0, 
175                           (struct sockaddr*)&from, &addrlen)) == -1) {
176                 warn("recvfrom");
177                 return 0;
178         }
179
180         rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r);
181
182         /* decode the data header, update seqno and frag before next request */
183         if (rv >= 2) {
184                 downstream_seqno = (buf[1] >> 5) & 7;
185                 downstream_fragment = (buf[1] >> 1) & 15;
186         }
187
188
189         if (is_sending()) {
190                 if (chunkid == q.id) {
191                         /* Got ACK on sent packet */
192                         outpkt.offset += outpkt.sentlen;
193                         if (outpkt.offset == outpkt.len) {
194                                 /* Packet completed */
195                                 outpkt.offset = 0;
196                                 outpkt.len = 0;
197                                 outpkt.sentlen = 0;
198
199                                 /* If the ack contains unacked frag number but no data, 
200                                  * send a ping to ack the frag number and get more data*/
201                                 if (rv == 2 && (
202                                         downstream_seqno != down_ack_seqno ||
203                                         downstream_fragment != down_ack_fragment
204                                         )) {
205                                         
206                                         send_ping(fd);
207                                 }
208                         } else {
209                                 /* More to send */
210                                 send_chunk(fd);
211                         }
212
213                 }
214         }
215         return rv;
216 }
217
218
219 static int
220 tunnel_tun(int tun_fd, int dns_fd)
221 {
222         unsigned long outlen;
223         unsigned long inlen;
224         char out[64*1024];
225         char in[64*1024];
226         size_t read;
227
228         if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
229                 return -1;
230
231         outlen = sizeof(out);
232         inlen = read;
233         compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9);
234
235         memcpy(outpkt.data, out, MIN(outlen, sizeof(outpkt.data)));
236         outpkt.sentlen = 0;
237         outpkt.offset = 0;
238         outpkt.len = outlen;
239         outpkt.seqno++;
240         outpkt.fragment = 0;
241
242         send_chunk(dns_fd);
243
244         return read;
245 }
246
247 static int
248 tunnel_dns(int tun_fd, int dns_fd)
249 {
250         unsigned long datalen;
251         char buf[64*1024];
252         size_t read;
253
254         if ((read = read_dns(dns_fd, buf, sizeof(buf))) <= 2) 
255                 return -1;
256
257         if (downstream_seqno != inpkt.seqno) {
258                 /* New packet */
259                 inpkt.seqno = downstream_seqno;
260                 inpkt.fragment = downstream_fragment;
261                 inpkt.len = 0;
262         } else if (downstream_fragment <= inpkt.fragment) {
263                 /* Duplicate fragment */
264                 return -1;
265         }
266         inpkt.fragment = downstream_fragment;
267
268         datalen = MIN(read - 2, sizeof(inpkt.data) - inpkt.len);
269
270         /* Skip 2 byte data header and append to packet */
271         memcpy(&inpkt.data[inpkt.len], &buf[2], datalen);
272         inpkt.len += datalen;
273
274         if (buf[1] & 1) { /* If last fragment flag is set */
275                 /* Uncompress packet and send to tun */
276                 datalen = sizeof(buf);
277                 if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) inpkt.data, inpkt.len) == Z_OK) {
278                         write_tun(tun_fd, buf, datalen);
279                 }
280                 inpkt.len = 0;
281         }
282
283         /* If we have nothing to send, send a ping to get more data */
284         if (!is_sending()) 
285                 send_ping(dns_fd);
286         
287         return read;
288 }
289
290 static int
291 tunnel(int tun_fd, int dns_fd)
292 {
293         struct timeval tv;
294         fd_set fds;
295         int rv;
296         int i;
297
298         rv = 0;
299
300         while (running) {
301                 tv.tv_sec = 1;
302                 tv.tv_usec = 0;
303
304
305                 FD_ZERO(&fds);
306                 if (!is_sending()) {
307                         FD_SET(tun_fd, &fds);
308                 }
309                 FD_SET(dns_fd, &fds);
310
311                 i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv);
312                 
313                 if (running == 0)
314                         break;
315
316                 if (i < 0) 
317                         err(1, "select");
318
319                 if (i == 0) /* timeout */
320                         send_ping(dns_fd);
321                 else {
322                         if (FD_ISSET(tun_fd, &fds)) {
323                                 if (tunnel_tun(tun_fd, dns_fd) <= 0)
324                                         continue;
325                         }
326                         if (FD_ISSET(dns_fd, &fds)) {
327                                 if (tunnel_dns(tun_fd, dns_fd) <= 0)
328                                         continue;
329                         } 
330                 }
331         }
332
333         return rv;
334 }
335
336 static void
337 send_chunk(int fd)
338 {
339         char hex[] = "0123456789ABCDEF";
340         char buf[4096];
341         int avail;
342         int code;
343         char *p;
344
345         p = outpkt.data;
346         p += outpkt.offset;
347         avail = outpkt.len - outpkt.offset;
348
349         outpkt.sentlen = build_hostname(buf + 4, sizeof(buf) - 4, p, avail, topdomain, dataenc);
350
351         /* Build upstream data header (see doc/proto_xxxxxxxx.txt) */
352
353         buf[0] = hex[userid & 15]; /* First byte is 4 bits userid */
354
355         code = ((outpkt.seqno & 7) << 2) | ((outpkt.fragment & 15) >> 2);
356         buf[1] = b32_5to8(code); /* Second byte is 3 bits seqno, 2 upper bits fragment count */
357
358         code = ((outpkt.fragment & 3) << 3) | (downstream_seqno & 7);
359         buf[2] = b32_5to8(code); /* Third byte is 2 bits lower fragment count, 3 bits downstream packet seqno */
360
361         code = ((downstream_fragment & 15) << 1) | (outpkt.sentlen == avail);
362         buf[3] = b32_5to8(code); /* Fourth byte is 4 bits downstream fragment count, 1 bit last frag flag */
363
364         down_ack_seqno = downstream_seqno;
365         down_ack_fragment = downstream_fragment;
366
367         outpkt.fragment++;
368         send_query(fd, buf);
369 }
370
371 static void
372 send_login(int fd, char *login, int len)
373 {
374         char data[19];
375
376         memset(data, 0, sizeof(data));
377         data[0] = userid;
378         memcpy(&data[1], login, MIN(len, 16));
379
380         data[17] = (rand_seed >> 8) & 0xff;
381         data[18] = (rand_seed >> 0) & 0xff;
382         
383         rand_seed++;
384
385         send_packet(fd, 'L', data, sizeof(data));
386 }
387
388 static void
389 send_ping(int fd)
390 {
391         char data[4];
392         
393         if (is_sending()) {
394                 outpkt.sentlen = 0;
395                 outpkt.offset = 0;
396                 outpkt.len = 0;
397         }
398
399         data[0] = userid;
400         data[1] = ((downstream_seqno & 7) << 4) | (downstream_fragment & 15);
401         data[2] = (rand_seed >> 8) & 0xff;
402         data[3] = (rand_seed >> 0) & 0xff;
403         
404         down_ack_seqno = downstream_seqno;
405         down_ack_fragment = downstream_fragment;
406         
407         rand_seed++;
408
409         send_packet(fd, 'P', data, sizeof(data));
410 }
411
412 static void
413 send_fragsize_probe(int fd, int fragsize)
414 {
415         char probedata[256];
416         char buf[4096];
417
418         /* build a large query domain which is random and maximum size */
419         memset(probedata, MIN(1, rand_seed & 0xff), sizeof(probedata));
420         probedata[1] = MIN(1, (rand_seed >> 8) & 0xff);
421         rand_seed++;
422         build_hostname(buf + 4, sizeof(buf) - 4, probedata, sizeof(probedata), topdomain, dataenc);
423
424         fragsize &= 2047;
425
426         buf[0] = 'r'; /* Probe downstream fragsize packet */
427         buf[1] = b32_5to8((userid << 1) | (fragsize & 1024));
428         buf[2] = b32_5to8((fragsize >> 5) & 31);
429         buf[3] = b32_5to8(fragsize & 31);
430
431         send_query(fd, buf);
432 }
433
434 static void
435 send_set_downstream_fragsize(int fd, int fragsize)
436 {
437         char data[5];
438         
439         data[0] = userid;
440         data[1] = (fragsize & 0xff00) >> 8;
441         data[2] = (fragsize & 0x00ff);
442         data[3] = (rand_seed >> 8) & 0xff;
443         data[4] = (rand_seed >> 0) & 0xff;
444         
445         rand_seed++;
446
447         send_packet(fd, 'N', data, sizeof(data));
448 }
449
450 static void 
451 send_version(int fd, uint32_t version)
452 {
453         char data[6];
454
455         data[0] = (version >> 24) & 0xff;
456         data[1] = (version >> 16) & 0xff;
457         data[2] = (version >> 8) & 0xff;
458         data[3] = (version >> 0) & 0xff;
459
460         data[4] = (rand_seed >> 8) & 0xff;
461         data[5] = (rand_seed >> 0) & 0xff;
462         
463         rand_seed++;
464
465         send_packet(fd, 'V', data, sizeof(data));
466 }
467
468 static void
469 send_case_check(int fd)
470 {
471         /* The '+' plus character is not allowed according to RFC. 
472          * Expect to get SERVFAIL or similar if it is rejected.
473          */
474         char buf[512] = "zZ+-aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY1234.";
475
476         strncat(buf, topdomain, 512 - strlen(buf));
477         send_query(fd, buf);
478 }
479
480 static void
481 send_codec_switch(int fd, int userid, int bits)
482 {
483         char buf[512] = "S__.";
484         buf[1] = b32_5to8(userid);
485         buf[2] = b32_5to8(bits);
486         
487         strncat(buf, topdomain, 512 - strlen(buf));
488         send_query(fd, buf);
489 }
490
491 static int
492 handshake(int dns_fd)
493 {
494         struct timeval tv;
495         uint32_t payload;
496         char server[65];
497         char client[65];
498         char login[16];
499         char in[4096];
500         fd_set fds;
501         int read;
502         int mtu;
503         int seed;
504         int i;
505         int r;
506
507         for (i = 0; running && i < 5; i++) {
508                 tv.tv_sec = i + 1;
509                 tv.tv_usec = 0;
510
511                 send_version(dns_fd, VERSION);
512                 
513                 FD_ZERO(&fds);
514                 FD_SET(dns_fd, &fds);
515
516                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
517
518                 if(r > 0) {
519                         read = read_dns(dns_fd, in, sizeof(in));
520                         
521                         if(read <= 0) {
522                                 if (read == 0) {
523                                         warn("handshake read");
524                                 }
525                                 /* if read < 0 then warning has been printed already */
526                                 continue;
527                         }
528
529                         if (read >= 9) {
530                                 payload =  (((in[4] & 0xff) << 24) |
531                                                 ((in[5] & 0xff) << 16) |
532                                                 ((in[6] & 0xff) << 8) |
533                                                 ((in[7] & 0xff)));
534
535                                 if (strncmp("VACK", in, 4) == 0) {
536                                         seed = payload;
537                                         userid = in[8];
538
539                                         printf("Version ok, both using protocol v 0x%08x. You are user #%d\n", VERSION, userid);
540                                         goto perform_login;
541                                 } else if (strncmp("VNAK", in, 4) == 0) {
542                                         warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up", 
543                                                         VERSION, payload);
544                                         return 1;
545                                 } else if (strncmp("VFUL", in, 4) == 0) {
546                                         warnx("Server full, all %d slots are taken. Try again later", payload);
547                                         return 1;
548                                 }
549                         } else 
550                                 warnx("did not receive proper login challenge");
551                 }
552                 
553                 printf("Retrying version check...\n");
554         }
555         errx(1, "couldn't connect to server");
556         /* NOTREACHED */
557         
558 perform_login:
559         login_calculate(login, 16, password, seed);
560         
561         for (i=0; running && i<5 ;i++) {
562                 tv.tv_sec = i + 1;
563                 tv.tv_usec = 0;
564
565                 send_login(dns_fd, login, 16);
566                 
567                 FD_ZERO(&fds);
568                 FD_SET(dns_fd, &fds);
569
570                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
571
572                 if(r > 0) {
573                         read = read_dns(dns_fd, in, sizeof(in));
574                         
575                         if(read <= 0) {
576                                 warn("read");
577                                 continue;
578                         }
579
580                         if (read > 0) {
581                                 int netmask;
582                                 if (strncmp("LNAK", in, 4) == 0) {
583                                         printf("Bad password\n");
584                                         return 1;
585                                 } else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d", 
586                                         server, client, &mtu, &netmask) == 4) {
587                                         
588                                         server[64] = 0;
589                                         client[64] = 0;
590                                         if (tun_setip(client, netmask) == 0 && 
591                                                 tun_setmtu(mtu) == 0) {
592                                                 goto perform_case_check;
593                                         } else {
594                                                 warnx("Received handshake with bad data");
595                                         }
596                                 } else {
597                                         printf("Received bad handshake\n");
598                                 }
599                         }
600                 }
601
602                 printf("Retrying login...\n");
603         }
604         warnx("couldn't login to server");
605         return 1;
606
607 perform_case_check:
608         case_preserved = 0;
609         for (i=0; running && i<5 ;i++) {
610                 tv.tv_sec = i + 1;
611                 tv.tv_usec = 0;
612
613                 send_case_check(dns_fd);
614                 
615                 FD_ZERO(&fds);
616                 FD_SET(dns_fd, &fds);
617
618                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
619
620                 if(r > 0) {
621                         read = read_dns(dns_fd, in, sizeof(in));
622                         
623                         if (read > 0) {
624                                 if (in[0] == 'z' || in[0] == 'Z') {
625                                         if (read < (27 * 2)) {
626                                                 printf("Received short case check reply. Will use base32 encoder\n");
627                                                 goto switch_codec;
628                                         } else {
629                                                 int k;
630
631                                                 /* TODO enhance this, base128 is probably also possible */
632                                                 case_preserved = 1;
633                                                 for (k = 0; k < 27 && case_preserved; k += 2) {
634                                                         if (in[k] == in[k+1]) {
635                                                                 /* test string: zZ+-aAbBcCdDeE... */
636                                                                 case_preserved = 0;
637                                                         }
638                                                 }
639                                                 goto switch_codec;
640                                         }
641                                 } else {
642                                         printf("Received bad case check reply\n");
643                                 }
644                         } else {
645                                 printf("Got error on case check, will use base32\n");
646                                 goto switch_codec;
647                         }
648                 }
649
650                 printf("Retrying case check...\n");
651         }
652
653         printf("No reply on case check, continuing\n");
654 switch_codec:
655         if (!case_preserved)
656                 goto autodetect_max_fragsize;
657
658         dataenc = get_base64_encoder();
659         printf("Switching to %s codec\n", dataenc->name);
660         /* Send to server that this user will use base64 from now on */
661         for (i=0; running && i<5 ;i++) {
662                 int bits;
663                 tv.tv_sec = i + 1;
664                 tv.tv_usec = 0;
665
666                 bits = 6; /* base64 = 6 bits per byte */
667
668                 send_codec_switch(dns_fd, userid, bits);
669                 
670                 FD_ZERO(&fds);
671                 FD_SET(dns_fd, &fds);
672
673                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
674
675                 if(r > 0) {
676                         read = read_dns(dns_fd, in, sizeof(in));
677                         
678                         if (read > 0) {
679                                 if (strncmp("BADLEN", in, 6) == 0) {
680                                         printf("Server got bad message length. ");
681                                         goto codec_revert;
682                                 } else if (strncmp("BADIP", in, 5) == 0) {
683                                         printf("Server rejected sender IP address. ");
684                                         goto codec_revert;
685                                 } else if (strncmp("BADCODEC", in, 8) == 0) {
686                                         printf("Server rejected the selected codec. ");
687                                         goto codec_revert;
688                                 }
689                                 in[read] = 0; /* zero terminate */
690                                 printf("Server switched to codec %s\n", in);
691                                 goto autodetect_max_fragsize;
692                         }
693                 }
694                 printf("Retrying codec switch...\n");
695         }
696         printf("No reply from server on codec switch. ");
697 codec_revert: 
698         printf("Falling back to base32\n");
699         dataenc = get_base32_encoder();
700 autodetect_max_fragsize:
701         if (autodetect_frag_size) {
702                 int proposed_fragsize = 768;
703                 int range = 768;
704                 max_downstream_frag_size = 0;
705                 printf("Autoprobing max downstream fragment size... (skip with -m fragsize)\n"); 
706                 while (running && range > 0 && (range >= 8 || !max_downstream_frag_size)) {
707                         for (i=0; running && i<3 ;i++) {
708                                 tv.tv_sec = 1;
709                                 tv.tv_usec = 0;
710                                 send_fragsize_probe(dns_fd, proposed_fragsize);
711
712                                 FD_ZERO(&fds);
713                                 FD_SET(dns_fd, &fds);
714
715                                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
716
717                                 if(r > 0) {
718                                         read = read_dns(dns_fd, in, sizeof(in));
719                                         
720                                         if (read > 0) {
721                                                 /* We got a reply */
722                                                 int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
723                                                 if (acked_fragsize == proposed_fragsize) {
724                                                         printf("%d ok.. ", acked_fragsize);
725                                                         fflush(stdout);
726                                                         max_downstream_frag_size = acked_fragsize;
727                                                         range >>= 1;
728                                                         proposed_fragsize += range;
729                                                         continue;
730                                                 }
731                                         }
732                                 }
733                         }
734                         printf("%d not ok.. ", proposed_fragsize);
735                         fflush(stdout);
736                         range >>= 1;
737                         proposed_fragsize -= range;
738                 }
739                 if (!running) {
740                         printf("\n");
741                         warnx("stopped while autodetecting fragment size (Try probing manually with -m)");
742                         return 1;
743                 }
744                 if (range == 0) {
745                         /* Tried all the way down to 2 and found no good size */
746                         printf("\n");
747                         warnx("found no accepted fragment size. (Try probing manually with -m)");
748                         return 1;
749                 }
750                 printf("will use %d\n", max_downstream_frag_size);
751         }
752         printf("Setting downstream fragment size to max %d...\n", max_downstream_frag_size);
753         for (i=0; running && i<5 ;i++) {
754                 tv.tv_sec = i + 1;
755                 tv.tv_usec = 0;
756
757                 send_set_downstream_fragsize(dns_fd, max_downstream_frag_size);
758                 
759                 FD_ZERO(&fds);
760                 FD_SET(dns_fd, &fds);
761
762                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
763
764                 if(r > 0) {
765                         read = read_dns(dns_fd, in, sizeof(in));
766                         
767                         if (read > 0) {
768                                 int accepted_fragsize;
769
770                                 if (strncmp("BADFRAG", in, 7) == 0) {
771                                         printf("Server rejected fragsize. Keeping default.");
772                                         goto done;
773                                 } else if (strncmp("BADIP", in, 5) == 0) {
774                                         printf("Server rejected sender IP address.\n");
775                                         goto done;
776                                 }
777
778                                 accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
779                                 goto done;
780                         }
781                 }
782                 printf("Retrying set fragsize...\n");
783         }
784         printf("No reply from server when setting fragsize. Keeping default.\n");
785 done:
786         return 0;
787 }
788
789 static char *
790 get_resolvconf_addr()
791 {
792         static char addr[16];
793         char buf[80];
794         char *rv;
795         FILE *fp;
796         
797         rv = NULL;
798
799         if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) 
800                 err(1, "/etc/resolve.conf");
801         
802         while (feof(fp) == 0) {
803                 fgets(buf, sizeof(buf), fp);
804
805                 if (sscanf(buf, "nameserver %15s", addr) == 1) {
806                         rv = addr;
807                         break;
808                 }
809         }
810         
811         fclose(fp);
812
813         return rv;
814 }
815
816 static void
817 set_nameserver(const char *cp) 
818 {
819         struct in_addr addr;
820
821         if (inet_aton(cp, &addr) != 1)
822                 errx(1, "error parsing nameserver address: '%s'", cp);
823
824         memset(&nameserv, 0, sizeof(nameserv));
825         nameserv.sin_family = AF_INET;
826         nameserv.sin_port = htons(53);
827         nameserv.sin_addr = addr;
828 }
829
830 static void
831 usage() {
832         extern char *__progname;
833
834         printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
835                         "[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
836         exit(2);
837 }
838
839 static void
840 help() {
841         extern char *__progname;
842
843         printf("iodine IP over DNS tunneling client\n");
844         printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
845                         "[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
846         printf("  -v to print version info and exit\n");
847         printf("  -h to print this help and exit\n");
848         printf("  -f to keep running in foreground\n");
849         printf("  -u name to drop privileges and run as user 'name'\n");
850         printf("  -t dir to chroot to directory dir\n");
851         printf("  -d device to set tunnel device name\n");
852         printf("  -P password used for authentication (max 32 chars will be used)\n");
853         printf("  -m maxfragsize, to limit size of downstream packets\n");
854         printf("nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n");
855         printf("topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
856
857         exit(0);
858 }
859
860 static void
861 version() {
862         printf("iodine IP over DNS tunneling client\n");
863         printf("version: 0.5.0 from 2009-01-23\n");
864
865         exit(0);
866 }
867
868 int
869 main(int argc, char **argv)
870 {
871         char *nameserv_addr;
872         struct passwd *pw;
873         char *username;
874         int foreground;
875         char *newroot;
876         char *device;
877         int choice;
878         int tun_fd;
879         int dns_fd;
880
881         memset(password, 0, 33);
882         username = NULL;
883         foreground = 0;
884         newroot = NULL;
885         device = NULL;
886         chunkid = 0;
887
888         outpkt.seqno = 0;
889         inpkt.len = 0;
890
891         autodetect_frag_size = 1;
892         max_downstream_frag_size = 3072;
893
894         b32 = get_base32_encoder();
895         dataenc = get_base32_encoder();
896         
897 #if !defined(BSD) && !defined(__GLIBC__)
898         __progname = strrchr(argv[0], '/');
899         if (__progname == NULL)
900                 __progname = argv[0];
901         else
902                 __progname++;
903 #endif
904
905         while ((choice = getopt(argc, argv, "vfhu:t:d:P:m:")) != -1) {
906                 switch(choice) {
907                 case 'v':
908                         version();
909                         /* NOTREACHED */
910                         break;
911                 case 'f':
912                         foreground = 1;
913                         break;
914                 case 'h':
915                         help();
916                         /* NOTREACHED */
917                         break;
918                 case 'u':
919                         username = optarg;
920                         break;
921                 case 't':
922                         newroot = optarg;
923                         break;
924                 case 'd':
925                         device = optarg;
926                         break;
927                 case 'P':
928                         strncpy(password, optarg, sizeof(password));
929                         password[sizeof(password)-1] = 0;
930                         
931                         /* XXX: find better way of cleaning up ps(1) */
932                         memset(optarg, 0, strlen(optarg)); 
933                         break;
934                 case 'm':
935                         autodetect_frag_size = 0;
936                         max_downstream_frag_size = atoi(optarg);
937                         break;
938                 default:
939                         usage();
940                         /* NOTREACHED */
941                 }
942         }
943         
944         if (geteuid() != 0) {
945                 warnx("Run as root and you'll be happy.\n");
946                 usage();
947                 /* NOTREACHED */
948         }
949
950         argc -= optind;
951         argv += optind;
952
953         switch (argc) {
954         case 1:
955                 nameserv_addr = get_resolvconf_addr();
956                 topdomain = strdup(argv[0]);
957                 break;
958         case 2:
959                 nameserv_addr = argv[0];
960                 topdomain = strdup(argv[1]);
961                 break;
962         default:
963                 usage();
964                 /* NOTREACHED */
965         }
966
967         if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
968                 warnx("Use a max frag size between 1 and 65535 bytes.\n");
969                 usage();
970                 /* NOTREACHED */
971         }
972
973         set_nameserver(nameserv_addr);
974
975         if(strlen(topdomain) <= 128) {
976                 if(check_topdomain(topdomain)) {
977                         warnx("Topdomain contains invalid characters.\n");
978                         usage();
979                         /* NOTREACHED */
980                 }
981         } else {
982                 warnx("Use a topdomain max 128 chars long.\n");
983                 usage();
984                 /* NOTREACHED */
985         }
986
987         if (username != NULL) {
988                 if ((pw = getpwnam(username)) == NULL) {
989                         warnx("User %s does not exist!\n", username);
990                         usage();
991                         /* NOTREACHED */
992                 }
993         }
994         
995         if (strlen(password) == 0) 
996                 read_password(password, sizeof(password));
997
998         if ((tun_fd = open_tun(device)) == -1)
999                 goto cleanup1;
1000         if ((dns_fd = open_dns(0, INADDR_ANY)) == -1)
1001                 goto cleanup2;
1002
1003         signal(SIGINT, sighandler);
1004         signal(SIGTERM, sighandler);
1005
1006         if(handshake(dns_fd))
1007                 goto cleanup2;
1008         
1009         printf("Sending queries for %s to %s\n", topdomain, nameserv_addr);
1010
1011         if (foreground == 0) 
1012                 do_detach();
1013
1014         if (newroot != NULL)
1015                 do_chroot(newroot);
1016         
1017         if (username != NULL) {
1018                 gid_t gids[1];
1019                 gids[0] = pw->pw_gid;
1020                 if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
1021                         warnx("Could not switch to user %s!\n", username);
1022                         usage();
1023                         /* NOTREACHED */
1024                 }
1025         }
1026         
1027         downstream_seqno = 0;
1028         downstream_fragment = 0;
1029         down_ack_seqno = 0;
1030         down_ack_fragment = 0;
1031         
1032         tunnel(tun_fd, dns_fd);
1033
1034 cleanup2:
1035         close_dns(dns_fd);
1036         close_tun(tun_fd);
1037 cleanup1:
1038
1039         return 0;
1040 }