gdr / tuntox (public) (License: GPLv3) (since 2017-01-24) (hash sha1)
Tunnel TCP connections over the Tox protocol
List of commits:
Subject Hash Author Date (UTC)
Pipe mode working, yay! 99a66836911b804dce1455580cbf75dc99f23538 GDR! 2014-12-11 22:27:26
Added MSG_NOSIGNAL to send() in client c9f51df320380a537843145ebbf4ceff7ef1c561 GDR! 2014-12-11 21:33:27
Fixed a warning and printing garbage 925a7c2bdf93c3a0209552285b77e2e585a799c4 GDR! 2014-12-11 21:31:49
Fixed a warning and printing garbage f7f5170d00ee10affcacf569842207120a7ab16d GDR! 2014-12-11 21:30:51
Fixed server-side SIGPIPE 946e3fa1907217a0717978ac98b32ce1ee7c23ac GDR! 2014-12-11 21:24:16
Added handle_server_tcp_fin_frame 169a478762d6863782395acff8c9f53b733048f5 GDR! 2014-12-11 21:19:32
Added systemd and supervisord config files ea3d59d854108f28c2d2d10a5af60fe3d66e1f6f GDR! 2014-12-11 20:33:54
Removed the const qualifier from frame->data d81429c916e41958483256556dea861cb97487c4 GDR! 2014-12-11 19:57:32
Updated the IP of MVPS bootstrap node fbe7d5d1b54b0c67d644ad68ca37088f529d150f GDR! 2014-12-11 19:56:04
Got rid of some dead code a60a3712c46bcef7dbb9c56c84693d070230c91b GDR! 2014-12-11 19:47:19
Make localhost work even if regular name resolution fails eee06b7d149e00a79897c1d17b0264af99e5149e GDR! 2014-12-11 19:38:38
Readme tweaks 6bb15840b0bde8e5949e76873aec418f2b64951f GDR! 2014-12-11 18:41:19
License 0974ae043fe15596554512560f72a0a08863e282 GDR! 2014-12-11 18:37:29
mention build.md 13f31613c0a89007baef47d8e4d5d1e47c4d4ff9 GDR! 2014-12-11 18:32:25
Help on -C switch ab22ba6bcbc395527950fcb9743080c651ab5ef8 GDR! 2014-12-11 18:31:13
Bare bones documentation aada851bb2c5576ba9afb1a486ea4b01e0c05ac3 GDR! 2014-12-11 18:30:14
Initial commit 4c36e3b71adab6e9f3f08fda3b5c7bf5714ef201 GDR! 2014-12-11 13:27:41
Server state loading/saving 7cb0f811c9a573342ec390080ac67e640d0f2e30 GDR! 2014-11-26 12:55:12
Multi-connection support client-side. 16add85eb81629b07dd7bdb04fbe30be1410cc83 GDR! 2014-11-25 22:09:45
TCP works, yay c311fb3bdd2c26c347c2dd734f97003ac0538037 GDR! 2014-11-16 02:54:56
Commit 99a66836911b804dce1455580cbf75dc99f23538 - Pipe mode working, yay!
Author: GDR!
Author date (UTC): 2014-12-11 22:27
Committer name: GDR!
Committer date (UTC): 2014-12-11 22:27
Parent(s): c9f51df320380a537843145ebbf4ceff7ef1c561
Signer:
Signing key:
Signing status: N
Tree: 2eee635f310b1dd9e39dbc45e74c60168a1fdce3
File Lines added Lines deleted
client.c 64 18
client.h 1 0
main.c 17 14
util.c 22 0
File client.c changed (mode: 100644) (index 4cf6b7b..3395757)
... ... int handle_acktunnel_frame(protocol_frame *rcvd_frame)
103 103 /* Mark that we can accept() another connection */ /* Mark that we can accept() another connection */
104 104 client_tunnel.sockfd = -1; client_tunnel.sockfd = -1;
105 105
106 printf("New tunnel ID: %d\n", tun->connid);
106 // printf("New tunnel ID: %d\n", tun->connid);
107 107
108 if(client_local_port_mode)
108 if(client_local_port_mode || client_pipe_mode)
109 109 { {
110 110 update_select_nfds(tun->sockfd); update_select_nfds(tun->sockfd);
111 111 FD_SET(tun->sockfd, &client_master_fdset); FD_SET(tun->sockfd, &client_master_fdset);
112 fprintf(stderr, "Accepted a new connection on port %d\n", local_port);
112 if(client_local_port_mode)
113 {
114 fprintf(stderr, "Accepted a new connection on port %d\n", local_port);
115 }
113 116 } }
114 117 else else
115 118 { {
116 fprintf(stderr, "This tunnel mode is not supported yet");
119 fprintf(stderr, "This tunnel mode is not supported yet\n");
117 120 exit(1); exit(1);
118 121 } }
119 122 } }
 
... ... int handle_server_tcp_frame(protocol_frame *rcvd_frame)
136 139 while(offset < rcvd_frame->data_length) while(offset < rcvd_frame->data_length)
137 140 { {
138 141 int sent_bytes; int sent_bytes;
142 int write_sockfd;
143
144 if(client_pipe_mode)
145 {
146 sent_bytes = write(
147 1, /* STDOUT */
148 rcvd_frame->data + offset,
149 rcvd_frame->data_length - offset
150 );
151 }
152 else
153 {
154 sent_bytes = send(
155 tun->sockfd,
156 rcvd_frame->data + offset,
157 rcvd_frame->data_length - offset,
158 MSG_NOSIGNAL
159 );
160 }
139 161
140 sent_bytes = send(
141 tun->sockfd,
142 rcvd_frame->data + offset,
143 rcvd_frame->data_length - offset,
144 MSG_NOSIGNAL
145 );
146 162
147 163 if(sent_bytes < 0) if(sent_bytes < 0)
148 164 { {
149 165 char data[PROTOCOL_BUFFER_OFFSET]; char data[PROTOCOL_BUFFER_OFFSET];
150 166 protocol_frame frame_st, *frame; protocol_frame frame_st, *frame;
151 167
152 fprintf(stderr, "Could not write to socket %d: %s\n", tun->sockfd, strerror(errno));
168 fprintf(stderr, "Could not write to socket %d: %s\n", write_sockfd, strerror(errno));
153 169
154 170 frame = &frame_st; frame = &frame_st;
155 171 memset(frame, 0, sizeof(protocol_frame)); memset(frame, 0, sizeof(protocol_frame));
 
... ... int handle_server_tcp_frame(protocol_frame *rcvd_frame)
166 182 offset += sent_bytes; offset += sent_bytes;
167 183 } }
168 184
169 printf("Got %d bytes from server - wrote to fd %d\n", rcvd_frame->data_length, tun->sockfd);
185 // printf("Got %d bytes from server - wrote to fd %d\n", rcvd_frame->data_length, tun->sockfd);
170 186
171 187 return 0; return 0;
172 188 } }
 
... ... int do_client_loop(char *tox_id_str)
213 229 exit(1); exit(1);
214 230 } }
215 231
216 if(!ping_mode) /* TODO handle pipe mode */
232 if(!ping_mode && !client_pipe_mode)
217 233 { {
218 234 local_bind(); local_bind();
219 235 signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
 
... ... int do_client_loop(char *tox_id_str)
277 293 { {
278 294 state = CLIENT_STATE_SEND_PING; state = CLIENT_STATE_SEND_PING;
279 295 } }
296 else if(client_pipe_mode)
297 {
298 state = CLIENT_STATE_SETUP_PIPE;
299 }
280 300 else else
281 301 { {
282 302 state = CLIENT_STATE_BIND_PORT; state = CLIENT_STATE_BIND_PORT;
 
... ... int do_client_loop(char *tox_id_str)
315 335 state = CLIENT_STATE_FORWARDING; state = CLIENT_STATE_FORWARDING;
316 336 } }
317 337 break; break;
338 case CLIENT_STATE_SETUP_PIPE:
339 send_tunnel_request_packet(
340 remote_host,
341 remote_port,
342 friendnumber
343 );
344 state = CLIENT_STATE_FORWARDING;
345 break;
318 346 case CLIENT_STATE_REQUEST_TUNNEL: case CLIENT_STATE_REQUEST_TUNNEL:
319 347 send_tunnel_request_packet( send_tunnel_request_packet(
320 348 remote_host, remote_host,
 
... ... int do_client_loop(char *tox_id_str)
324 352 state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL;
325 353 break; break;
326 354 case CLIENT_STATE_WAIT_FOR_ACKTUNNEL: case CLIENT_STATE_WAIT_FOR_ACKTUNNEL:
355 client_tunnel.sockfd = 0;
356 send_tunnel_request_packet(
357 remote_host,
358 remote_port,
359 friendnumber
360 );
327 361 break; break;
328 362 case CLIENT_STATE_FORWARDING: case CLIENT_STATE_FORWARDING:
329 363 { {
 
... ... int do_client_loop(char *tox_id_str)
336 370 fds = client_master_fdset; fds = client_master_fdset;
337 371
338 372 /* Handle accepting new connections */ /* Handle accepting new connections */
339 if(client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */
373 if(!client_pipe_mode &&
374 client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */
340 375 { {
341 376 accept_fd = accept(bind_sockfd, NULL, NULL); accept_fd = accept(bind_sockfd, NULL, NULL);
342 377 if(accept_fd != -1) if(accept_fd != -1)
 
... ... int do_client_loop(char *tox_id_str)
359 394 { {
360 395 if(FD_ISSET(tun->sockfd, &fds)) if(FD_ISSET(tun->sockfd, &fds))
361 396 { {
362 int nbytes = recv(tun->sockfd,
363 tox_packet_buf + PROTOCOL_BUFFER_OFFSET,
364 READ_BUFFER_SIZE, 0);
397 int nbytes;
398 if(client_local_port_mode)
399 {
400 nbytes = recv(tun->sockfd,
401 tox_packet_buf + PROTOCOL_BUFFER_OFFSET,
402 READ_BUFFER_SIZE, 0);
403 }
404 else
405 {
406 nbytes = read(tun->sockfd,
407 tox_packet_buf + PROTOCOL_BUFFER_OFFSET,
408 READ_BUFFER_SIZE
409 );
410 }
365 411
366 412 /* Check if connection closed */ /* Check if connection closed */
367 413 if(nbytes == 0) if(nbytes == 0)
 
... ... int do_client_loop(char *tox_id_str)
392 438 frame->data_length = nbytes; frame->data_length = nbytes;
393 439 send_frame(frame, tox_packet_buf); send_frame(frame, tox_packet_buf);
394 440
395 printf("Wrote %d bytes from sock %d to tunnel %d\n", nbytes, tun->sockfd, tun->connid);
441 // printf("Wrote %d bytes from sock %d to tunnel %d\n", nbytes, tun->sockfd, tun->connid);
396 442 } }
397 443 } }
398 444 } }
File client.h changed (mode: 100644) (index d22c161..1ac5008)
12 12 #define CLIENT_STATE_FORWARDING 10 #define CLIENT_STATE_FORWARDING 10
13 13 #define CLIENT_STATE_SHUTDOWN 11 #define CLIENT_STATE_SHUTDOWN 11
14 14 #define CLIENT_STATE_BIND_PORT 12 #define CLIENT_STATE_BIND_PORT 12
15 #define CLIENT_STATE_SETUP_PIPE 13
15 16
16 17 int handle_pong_frame(protocol_frame *rcvd_frame); int handle_pong_frame(protocol_frame *rcvd_frame);
17 18 int handle_acktunnel_frame(protocol_frame *rcvd_frame); int handle_acktunnel_frame(protocol_frame *rcvd_frame);
File main.c changed (mode: 100644) (index 8cef6ce..9d3d495)
... ... tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber)
94 94
95 95 void tunnel_delete(tunnel *t) void tunnel_delete(tunnel *t)
96 96 { {
97 printf("Deleting tunnel #%d\n", t->connid);
97 fprintf(stderr, "Deleting tunnel #%d\n", t->connid);
98 98 if(t->sockfd) if(t->sockfd)
99 99 { {
100 100 close(t->sockfd); close(t->sockfd);
 
... ... int handle_request_tunnel_frame(protocol_frame *rcvd_frame)
331 331 strncpy(hostname, rcvd_frame->data, rcvd_frame->data_length); strncpy(hostname, rcvd_frame->data, rcvd_frame->data_length);
332 332 hostname[rcvd_frame->data_length] = '\0'; hostname[rcvd_frame->data_length] = '\0';
333 333
334 printf("Got a request to forward data from %s:%d\n", hostname, port);
334 fprintf(stderr, "Got a request to forward data from %s:%d\n", hostname, port);
335 335
336 336 tunnel_id = get_random_tunnel_id(); tunnel_id = get_random_tunnel_id();
337 printf("Tunnel ID: %d\n", tunnel_id);
337 fprintf(stderr, "Tunnel ID: %d\n", tunnel_id);
338 338 /* TODO make connection */ /* TODO make connection */
339 339 sockfd = get_client_socket(hostname, port); sockfd = get_client_socket(hostname, port);
340 340 if(sockfd > 0) if(sockfd > 0)
 
... ... int parse_lossless_packet(void *sender_uc, const uint8_t *data, uint32_t len)
509 509 frame->data_length = INT16_AT(data, 6); frame->data_length = INT16_AT(data, 6);
510 510 frame->data = (uint8_t *)(data + PROTOCOL_BUFFER_OFFSET); frame->data = (uint8_t *)(data + PROTOCOL_BUFFER_OFFSET);
511 511 frame->friendnumber = *((uint32_t*)sender_uc); frame->friendnumber = *((uint32_t*)sender_uc);
512 printf("Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber);
512 fprintf(stderr, "Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber);
513 513
514 514 if(len < frame->data_length + PROTOCOL_BUFFER_OFFSET) if(len < frame->data_length + PROTOCOL_BUFFER_OFFSET)
515 515 { {
 
... ... void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *d
639 639 int32_t friendnumber; int32_t friendnumber;
640 640 int32_t *friendnumber_ptr = NULL; int32_t *friendnumber_ptr = NULL;
641 641
642 printf("Got friend request\n");
642 fprintf(stderr, "Got friend request\n");
643 643
644 644 friendnumber = tox_add_friend_norequest(tox, public_key); friendnumber = tox_add_friend_norequest(tox, public_key);
645 645
646 646 memset(tox_printable_id, '\0', sizeof(tox_printable_id)); memset(tox_printable_id, '\0', sizeof(tox_printable_id));
647 647 id_to_string(tox_printable_id, public_key); id_to_string(tox_printable_id, public_key);
648 printf("Accepted friend request from %s as %d\n", tox_printable_id, friendnumber);
648 fprintf(stderr, "Accepted friend request from %s as %d\n", tox_printable_id, friendnumber);
649 649
650 650 /* TODO: this is not freed right now, we're leaking 4 bytes per contact (OMG!) */ /* TODO: this is not freed right now, we're leaking 4 bytes per contact (OMG!) */
651 651 friendnumber_ptr = malloc(sizeof(int32_t)); friendnumber_ptr = malloc(sizeof(int32_t));
 
... ... void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *d
662 662
663 663 void cleanup(int status, void *tmp) void cleanup(int status, void *tmp)
664 664 { {
665 printf("kthxbye\n");
665 fprintf(stderr, "kthxbye\n");
666 666 fflush(stdout); fflush(stdout);
667 667 tox_kill(tox); tox_kill(tox);
668 668 if(client_socket) if(client_socket)
 
... ... int do_server_loop()
726 726 char data[PROTOCOL_BUFFER_OFFSET]; char data[PROTOCOL_BUFFER_OFFSET];
727 727 protocol_frame frame_st, *frame; protocol_frame frame_st, *frame;
728 728
729 printf("conn closed!\n");
729 fprintf(stderr, "conn closed!\n");
730 730
731 731 frame = &frame_st; frame = &frame_st;
732 732 memset(frame, 0, sizeof(protocol_frame)); memset(frame, 0, sizeof(protocol_frame));
 
... ... int do_server_loop()
738 738
739 739 tunnel_delete(tun); tunnel_delete(tun);
740 740
741 /* TODO remove tunnel? resume connection? */
742 741 continue; continue;
743 742 } }
744 743 else else
 
... ... int main(int argc, char *argv[])
775 774 unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1]; unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1];
776 775 int oc; int oc;
777 776
778 while ((oc = getopt(argc, argv, "L:pi:C:")) != -1)
777 while ((oc = getopt(argc, argv, "L:pi:C:P:")) != -1)
779 778 { {
780 779 switch(oc) switch(oc)
781 780 { {
 
... ... int main(int argc, char *argv[])
794 793 /* Pipe forwarding */ /* Pipe forwarding */
795 794 client_mode = 1; client_mode = 1;
796 795 client_pipe_mode = 1; client_pipe_mode = 1;
797 remote_port = atoi(optarg);
798 fprintf(stderr, "Forwarding remote port %d\n", remote_port);
796 if(parse_pipe_port_forward(optarg, &remote_host, &remote_port) < 0)
797 {
798 fprintf(stderr, "Invalid value for -P option - use something like -P 127.0.0.1:22\n");
799 exit(1);
800 }
801 fprintf(stderr, "Forwarding remote port %d to stdin/out\n", remote_port);
799 802 break; break;
800 803 case 'p': case 'p':
801 804 /* Ping */ /* Ping */
 
... ... int main(int argc, char *argv[])
843 846 tox_get_address(tox, tox_id); tox_get_address(tox, tox_id);
844 847 id_to_string(tox_printable_id, tox_id); id_to_string(tox_printable_id, tox_id);
845 848 tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2] = '\0'; tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2] = '\0';
846 printf("Generated Tox ID: %s\n", tox_printable_id);
849 fprintf(stderr, "Generated Tox ID: %s\n", tox_printable_id);
847 850
848 851 if(!remote_tox_id) if(!remote_tox_id)
849 852 { {
 
... ... int main(int argc, char *argv[])
866 869 memset(tox_printable_id, '\0', sizeof(tox_printable_id)); memset(tox_printable_id, '\0', sizeof(tox_printable_id));
867 870 id_to_string(tox_printable_id, tox_id); id_to_string(tox_printable_id, tox_id);
868 871 tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2] = '\0'; tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2] = '\0';
869 printf("Using Tox ID: %s\n", tox_printable_id);
872 fprintf(stderr, "Using Tox ID: %s\n", tox_printable_id);
870 873
871 874 tox_callback_friend_request(tox, accept_friend_request, NULL); tox_callback_friend_request(tox, accept_friend_request, NULL);
872 875 do_server_loop(); do_server_loop();
File util.c changed (mode: 100644) (index 86d316d..b523236)
... ... int string_to_id(char_t *w, char_t *a)
81 81 return 1; return 1;
82 82 } }
83 83
84 /* Parse the -L parameter */
84 85 /* 0 = success */ /* 0 = success */
85 86 int parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port) int parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port)
86 87 { {
 
... ... int parse_local_port_forward(char *string, int *local_port, char **hostname, int
104 105 return 0; return 0;
105 106 } }
106 107
108 /* Parse the -P parameter */
109 /* 0 = success */
110 int parse_pipe_port_forward(char *string, char **hostname, int *remote_port)
111 {
112 char *host;
113 char *rport;
114
115 host = strtok(string, ":");
116 rport = strtok(NULL, ":");
117
118 if(!host || !rport)
119 {
120 return -1;
121 }
122
123 *hostname = host;
124 *remote_port = atoi(rport);
125
126 return 0;
127 }
128
107 129 void* file_raw(char *path, uint32_t *size) void* file_raw(char *path, uint32_t *size)
108 130 { {
109 131 FILE *file; FILE *file;
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/gdr/tuntox

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/gdr/tuntox

Clone this repository using git:
git clone git://git.rocketgit.com/user/gdr/tuntox

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main