diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 163 |
1 files changed, 75 insertions, 88 deletions
@@ -3,6 +3,8 @@ | |||
3 | #include "tox_bootstrap.h" | 3 | #include "tox_bootstrap.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | 5 | ||
6 | #define LOG_IP_ADDRESS | ||
7 | |||
6 | #ifdef __MACH__ | 8 | #ifdef __MACH__ |
7 | #include "mach.h" | 9 | #include "mach.h" |
8 | #endif | 10 | #endif |
@@ -14,19 +16,12 @@ TOX_CONNECTION connection_status = TOX_CONNECTION_NONE; | |||
14 | TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; | 16 | TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; |
15 | /** CONFIGURATION OPTIONS **/ | 17 | /** CONFIGURATION OPTIONS **/ |
16 | /* Whether we're a client */ | 18 | /* Whether we're a client */ |
17 | int client_mode = 0; | 19 | |
18 | 20 | ||
19 | /* Don't bootstrap nodes */ | 21 | /* Don't bootstrap nodes */ |
20 | int skip_bootstrap = 1; | 22 | int skip_bootstrap = 1; |
21 | 23 | ||
22 | /* Just send a ping and exit */ | 24 | enum Mode program_mode = Mode_Unspecified; |
23 | int ping_mode = 0; | ||
24 | |||
25 | /* Open a local port and forward it */ | ||
26 | int client_local_port_mode = 0; | ||
27 | |||
28 | /* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ | ||
29 | int client_pipe_mode = 0; | ||
30 | 25 | ||
31 | /* Remote Tox ID in client mode */ | 26 | /* Remote Tox ID in client mode */ |
32 | uint8_t *remote_tox_id = NULL; | 27 | uint8_t *remote_tox_id = NULL; |
@@ -39,7 +34,7 @@ long int udp_start_port = 0; | |||
39 | long int udp_end_port = 0; | 34 | long int udp_end_port = 0; |
40 | 35 | ||
41 | /* Directory with config and tox save */ | 36 | /* Directory with config and tox save */ |
42 | char config_path[500] = "/etc/tuntox/"; | 37 | char *config_path = "/etc/tuntox/"; |
43 | 38 | ||
44 | /* Limit hostname and port in server */ | 39 | /* Limit hostname and port in server */ |
45 | int tunnel_target_whitelist_size = 0; | 40 | int tunnel_target_whitelist_size = 0; |
@@ -68,7 +63,7 @@ char shared_secret[TOX_MAX_FRIEND_REQUEST_LENGTH]; | |||
68 | int server_whitelist_mode = 0; | 63 | int server_whitelist_mode = 0; |
69 | allowed_toxid *allowed_toxids = NULL; | 64 | allowed_toxid *allowed_toxids = NULL; |
70 | 65 | ||
71 | int load_saved_toxid_in_client_mode = 0; | 66 | bool config_path_modified = false; |
72 | 67 | ||
73 | fd_set master_server_fds; | 68 | fd_set master_server_fds; |
74 | 69 | ||
@@ -452,9 +447,9 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) | |||
452 | int sockfd = 0; | 447 | int sockfd = 0; |
453 | uint16_t tunnel_id; | 448 | uint16_t tunnel_id; |
454 | 449 | ||
455 | if(client_mode) | 450 | if(program_mode != Mode_Server) |
456 | { | 451 | { |
457 | log_printf(L_WARNING, "Got tunnel request frame from friend #%d when in client mode\n", rcvd_frame->friendnumber); | 452 | log_printf(L_WARNING, "Got tunnel request frame from friend #%d but not in server mode\n", rcvd_frame->friendnumber); |
458 | return -1; | 453 | return -1; |
459 | } | 454 | } |
460 | 455 | ||
@@ -592,15 +587,9 @@ int handle_frame(protocol_frame *frame) | |||
592 | return handle_pong_frame(frame); | 587 | return handle_pong_frame(frame); |
593 | break; | 588 | break; |
594 | case PACKET_TYPE_TCP: | 589 | case PACKET_TYPE_TCP: |
595 | if(client_mode) | 590 | return program_mode != Mode_Server |
596 | { | 591 | ? handle_server_tcp_frame(frame) |
597 | return handle_server_tcp_frame(frame); | 592 | : handle_client_tcp_frame(frame); |
598 | } | ||
599 | else | ||
600 | { | ||
601 | return handle_client_tcp_frame(frame); | ||
602 | } | ||
603 | break; | ||
604 | case PACKET_TYPE_REQUESTTUNNEL: | 593 | case PACKET_TYPE_REQUESTTUNNEL: |
605 | handle_request_tunnel_frame(frame); | 594 | handle_request_tunnel_frame(frame); |
606 | break; | 595 | break; |
@@ -608,15 +597,9 @@ int handle_frame(protocol_frame *frame) | |||
608 | handle_acktunnel_frame(frame); | 597 | handle_acktunnel_frame(frame); |
609 | break; | 598 | break; |
610 | case PACKET_TYPE_TCP_FIN: | 599 | case PACKET_TYPE_TCP_FIN: |
611 | if(client_mode) | 600 | return program_mode != Mode_Server |
612 | { | 601 | ? handle_server_tcp_fin_frame(frame) |
613 | return handle_server_tcp_fin_frame(frame); | 602 | : handle_client_tcp_fin_frame(frame); |
614 | } | ||
615 | else | ||
616 | { | ||
617 | return handle_client_tcp_fin_frame(frame); | ||
618 | } | ||
619 | break; | ||
620 | default: | 603 | default: |
621 | log_printf(L_DEBUG, "Got unknown packet type 0x%x from friend %d\n", | 604 | log_printf(L_DEBUG, "Got unknown packet type 0x%x from friend %d\n", |
622 | frame->packet_type, | 605 | frame->packet_type, |
@@ -672,14 +655,16 @@ void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, | |||
672 | 655 | ||
673 | if(len < (size_t)frame->data_length + PROTOCOL_BUFFER_OFFSET) | 656 | if(len < (size_t)frame->data_length + PROTOCOL_BUFFER_OFFSET) |
674 | { | 657 | { |
675 | log_printf(L_WARNING, "Received frame too small (attempted buffer overflow?): %d bytes, excepted at least %d bytes\n", len, frame->data_length + PROTOCOL_BUFFER_OFFSET); | 658 | log_printf(L_WARNING, "Received frame too small (attempted buffer overflow?): %d bytes, excepted at least %d bytes\n", |
659 | len, frame->data_length + PROTOCOL_BUFFER_OFFSET); | ||
676 | free(frame); | 660 | free(frame); |
677 | return; | 661 | return; |
678 | } | 662 | } |
679 | 663 | ||
680 | if(frame->data_length > (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)) | 664 | if(frame->data_length > (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)) |
681 | { | 665 | { |
682 | log_printf(L_WARNING, "Declared data length too big (attempted buffer overflow?): %d bytes, excepted at most %d bytes\n", frame->data_length, (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)); | 666 | log_printf(L_WARNING, "Declared data length too big (attempted buffer overflow?): %d bytes, excepted at most %d bytes\n", |
667 | frame->data_length, (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)); | ||
683 | free(frame); | 668 | free(frame); |
684 | return; | 669 | return; |
685 | } | 670 | } |
@@ -772,12 +757,13 @@ static size_t load_save(uint8_t **out_data) | |||
772 | { | 757 | { |
773 | void *data; | 758 | void *data; |
774 | uint32_t size; | 759 | uint32_t size; |
775 | uint8_t path_real[512], *p; | 760 | uint8_t path_real[PATH_MAX], *p; |
776 | 761 | ||
777 | strncpy((char *)path_real, config_path, sizeof(path_real)); | 762 | strncpy((char *)path_real, config_path, sizeof(path_real)); |
778 | 763 | ||
779 | p = path_real + strlen((char *)path_real); | 764 | p = path_real + strlen((char *)path_real); |
780 | memcpy(p, "tox_save", sizeof("tox_save")); | 765 | char basename[] = "/tox_save"; |
766 | memcpy(p, "/tox_save", sizeof(basename)); | ||
781 | 767 | ||
782 | data = file_raw((char *)path_real, &size); | 768 | data = file_raw((char *)path_real, &size); |
783 | 769 | ||
@@ -857,7 +843,7 @@ void tunnel_target_whitelist_load() | |||
857 | } | 843 | } |
858 | fclose(file); | 844 | fclose(file); |
859 | 845 | ||
860 | log_printf(L_INFO, "Loaded %d rules\n", tunnel_target_whitelist_size); | 846 | log_printf(L_INFO, "Loaded %d rule%s\n", tunnel_target_whitelist_size, tunnel_target_whitelist_size == 1 ? "" : "s"); |
861 | if (tunnel_target_whitelist_size == 0 && tunnel_target_whitelist_enforced){ | 847 | if (tunnel_target_whitelist_size == 0 && tunnel_target_whitelist_enforced){ |
862 | log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); | 848 | log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); |
863 | } | 849 | } |
@@ -969,7 +955,7 @@ void handle_friend_connection_status(Tox *tox, uint32_t friend_number, TOX_CONNE | |||
969 | if(connection_status == TOX_CONNECTION_UDP) | 955 | if(connection_status == TOX_CONNECTION_UDP) |
970 | log_friend_ip_address(tox, friend_number); | 956 | log_friend_ip_address(tox, friend_number); |
971 | #endif | 957 | #endif |
972 | if(client_mode) | 958 | if(program_mode != Mode_Server) |
973 | { | 959 | { |
974 | friend_connection_status = connection_status; | 960 | friend_connection_status = connection_status; |
975 | } | 961 | } |
@@ -1306,29 +1292,22 @@ int main(int argc, char *argv[]) | |||
1306 | 1292 | ||
1307 | log_init(); | 1293 | log_init(); |
1308 | 1294 | ||
1309 | while ((oc = getopt(argc, argv, "L:pi:C:s:f:W:dqhSF:DU:t:u:")) != -1) | 1295 | while ((oc = getopt(argc, argv, "L:pi:C:s:f:W:vdqhSF:DU:t:u:")) != -1) |
1310 | { | 1296 | { |
1311 | switch(oc) | 1297 | switch(oc) |
1312 | { | 1298 | { |
1313 | case 'L': | 1299 | case 'L': |
1314 | /* Local port forwarding */ | 1300 | /* Local port forwarding */ |
1315 | client_mode = 1; | 1301 | program_mode = Mode_Client_Local_Port_Forward; |
1316 | client_local_port_mode = 1; | ||
1317 | if(!parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port)) | 1302 | if(!parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port)) |
1318 | { | 1303 | { |
1319 | log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); | 1304 | log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); |
1320 | exit(1); | 1305 | exit(1); |
1321 | } | 1306 | } |
1322 | if(min_log_level == L_UNSET) | ||
1323 | { | ||
1324 | min_log_level = L_INFO; | ||
1325 | } | ||
1326 | log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); | ||
1327 | break; | 1307 | break; |
1328 | case 'W': | 1308 | case 'W': |
1329 | /* Pipe forwarding */ | 1309 | /* Pipe forwarding */ |
1330 | client_mode = 1; | 1310 | program_mode = Mode_Client_Pipe; |
1331 | client_pipe_mode = 1; | ||
1332 | if(!parse_pipe_port_forward(optarg, &remote_host, &remote_port) || remote_port == 0) | 1311 | if(!parse_pipe_port_forward(optarg, &remote_host, &remote_port) || remote_port == 0) |
1333 | { | 1312 | { |
1334 | log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); | 1313 | log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); |
@@ -1338,12 +1317,10 @@ int main(int argc, char *argv[]) | |||
1338 | { | 1317 | { |
1339 | min_log_level = L_ERROR; | 1318 | min_log_level = L_ERROR; |
1340 | } | 1319 | } |
1341 | log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); | ||
1342 | break; | 1320 | break; |
1343 | case 'p': | 1321 | case 'p': |
1344 | /* Ping */ | 1322 | /* Ping */ |
1345 | client_mode = 1; | 1323 | program_mode = Mode_Client_Ping; |
1346 | ping_mode = 1; | ||
1347 | if(min_log_level == L_UNSET) | 1324 | if(min_log_level == L_UNSET) |
1348 | { | 1325 | { |
1349 | min_log_level = L_INFO; | 1326 | min_log_level = L_INFO; |
@@ -1368,20 +1345,12 @@ int main(int argc, char *argv[]) | |||
1368 | break; | 1345 | break; |
1369 | case 'C': | 1346 | case 'C': |
1370 | /* Config directory */ | 1347 | /* Config directory */ |
1371 | strncpy(config_path, optarg, sizeof(config_path) - 1); | 1348 | config_path = strdup(optarg); |
1372 | if(optarg[strlen(optarg) - 1] != '/') | 1349 | config_path_modified = 1; |
1373 | { | ||
1374 | int optarg_len = strlen(optarg); | ||
1375 | |||
1376 | config_path[optarg_len] = '/'; | ||
1377 | config_path[optarg_len + 1] = '\0'; | ||
1378 | } | ||
1379 | load_saved_toxid_in_client_mode = 1; | ||
1380 | break; | 1350 | break; |
1381 | case 'f': | 1351 | case 'f': |
1382 | tunnel_target_whitelist_file = strdup(optarg); | 1352 | tunnel_target_whitelist_file = strdup(optarg); |
1383 | tunnel_target_whitelist_enforced = true; | 1353 | tunnel_target_whitelist_enforced = true; |
1384 | log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n"); | ||
1385 | break; | 1354 | break; |
1386 | case 's': | 1355 | case 's': |
1387 | /* Shared secret */ | 1356 | /* Shared secret */ |
@@ -1389,6 +1358,7 @@ int main(int argc, char *argv[]) | |||
1389 | memset(shared_secret, 0, TOX_MAX_FRIEND_REQUEST_LENGTH); | 1358 | memset(shared_secret, 0, TOX_MAX_FRIEND_REQUEST_LENGTH); |
1390 | strncpy(shared_secret, optarg, TOX_MAX_FRIEND_REQUEST_LENGTH-1); | 1359 | strncpy(shared_secret, optarg, TOX_MAX_FRIEND_REQUEST_LENGTH-1); |
1391 | break; | 1360 | break; |
1361 | case 'v': | ||
1392 | case 'd': | 1362 | case 'd': |
1393 | switch(++verbosity) | 1363 | switch(++verbosity) |
1394 | { | 1364 | { |
@@ -1425,8 +1395,8 @@ int main(int argc, char *argv[]) | |||
1425 | tcp_relay_port = strtol(optarg, NULL, 10); | 1395 | tcp_relay_port = strtol(optarg, NULL, 10); |
1426 | if(errno != 0 || tcp_relay_port < 0 || tcp_relay_port > 65535) | 1396 | if(errno != 0 || tcp_relay_port < 0 || tcp_relay_port > 65535) |
1427 | { | 1397 | { |
1428 | tcp_relay_port = 1024 + (rand() % 64511); | 1398 | tcp_relay_port = 1024 + (rand() % 64511); |
1429 | log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); | 1399 | log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); |
1430 | } | 1400 | } |
1431 | break; | 1401 | break; |
1432 | case 'u': | 1402 | case 'u': |
@@ -1465,25 +1435,44 @@ int main(int argc, char *argv[]) | |||
1465 | } | 1435 | } |
1466 | } | 1436 | } |
1467 | 1437 | ||
1468 | if(!client_mode && min_log_level == L_UNSET) | 1438 | switch (program_mode) { |
1469 | { | 1439 | case Mode_Client_Local_Port_Forward: |
1470 | min_log_level = L_INFO; | 1440 | case Mode_Client_Pipe: |
1471 | } | 1441 | case Mode_Client_Ping: |
1472 | 1442 | if(!remote_tox_id) | |
1473 | if(client_mode && !remote_tox_id) | 1443 | { |
1474 | { | 1444 | log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); |
1475 | log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); | 1445 | exit(1); |
1476 | exit(1); | 1446 | } |
1477 | } | 1447 | break; |
1478 | 1448 | case Mode_Unspecified: | |
1479 | if(!client_mode && server_whitelist_mode) | 1449 | program_mode = Mode_Server; |
1480 | { | 1450 | case Mode_Server: |
1481 | log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); | 1451 | break; |
1482 | } | 1452 | } |
1483 | 1453 | ||
1484 | if(!client_mode && tunnel_target_whitelist_enforced) | 1454 | switch (program_mode) { |
1485 | { | 1455 | case Mode_Client_Local_Port_Forward: |
1486 | tunnel_target_whitelist_load(); | 1456 | log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); |
1457 | break; | ||
1458 | case Mode_Client_Pipe: | ||
1459 | log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); | ||
1460 | break; | ||
1461 | case Mode_Server: | ||
1462 | if(min_log_level == L_UNSET) | ||
1463 | { | ||
1464 | min_log_level = L_INFO; | ||
1465 | } | ||
1466 | if(tunnel_target_whitelist_enforced) | ||
1467 | { | ||
1468 | log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n"); | ||
1469 | tunnel_target_whitelist_load(); | ||
1470 | } | ||
1471 | if(server_whitelist_mode) | ||
1472 | { | ||
1473 | log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); | ||
1474 | } | ||
1475 | default:; | ||
1487 | } | 1476 | } |
1488 | 1477 | ||
1489 | /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ | 1478 | /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ |
@@ -1525,7 +1514,7 @@ int main(int argc, char *argv[]) | |||
1525 | tox_options.end_port | 1514 | tox_options.end_port |
1526 | ); | 1515 | ); |
1527 | 1516 | ||
1528 | if((!client_mode) || load_saved_toxid_in_client_mode) | 1517 | if(program_mode == Mode_Server || config_path_modified) |
1529 | { | 1518 | { |
1530 | save_size = load_save(&save_data); | 1519 | save_size = load_save(&save_data); |
1531 | if(save_data && save_size) | 1520 | if(save_data && save_size) |
@@ -1564,10 +1553,10 @@ int main(int argc, char *argv[]) | |||
1564 | tox_callback_self_connection_status(tox, handle_connection_status_change); | 1553 | tox_callback_self_connection_status(tox, handle_connection_status_change); |
1565 | tox_callback_friend_connection_status(tox, handle_friend_connection_status); | 1554 | tox_callback_friend_connection_status(tox, handle_friend_connection_status); |
1566 | 1555 | ||
1567 | if (!skip_bootstrap) | 1556 | if(!skip_bootstrap) |
1568 | do_bootstrap(tox); | 1557 | do_bootstrap(tox); |
1569 | 1558 | ||
1570 | if((!client_mode) || load_saved_toxid_in_client_mode) | 1559 | if(program_mode == Mode_Server || config_path_modified) |
1571 | { | 1560 | { |
1572 | write_save(tox); | 1561 | write_save(tox); |
1573 | } | 1562 | } |
@@ -1591,16 +1580,14 @@ int main(int argc, char *argv[]) | |||
1591 | to_hex(readable_dht_key, dht_key, TOX_PUBLIC_KEY_SIZE); | 1580 | to_hex(readable_dht_key, dht_key, TOX_PUBLIC_KEY_SIZE); |
1592 | log_printf(L_DEBUG, "DHT key: %s\n", readable_dht_key); | 1581 | log_printf(L_DEBUG, "DHT key: %s\n", readable_dht_key); |
1593 | 1582 | ||
1594 | if (client_mode) | 1583 | if (program_mode == Mode_Server) |
1595 | { | 1584 | { |
1596 | do_client_loop(remote_tox_id); | 1585 | tox_callback_friend_request(tox, accept_friend_request); |
1586 | return do_server_loop(); | ||
1597 | } | 1587 | } |
1598 | else | 1588 | else |
1599 | { | 1589 | { |
1600 | tox_callback_friend_request(tox, accept_friend_request); | 1590 | return do_client_loop(remote_tox_id); |
1601 | do_server_loop(); | ||
1602 | } | 1591 | } |
1603 | } | 1592 | } |
1604 | |||
1605 | return 0; | ||
1606 | } | 1593 | } |