/* Initiate a TCP connection with host:port */ int net_connect(int *fd, char *host, int port) { struct sockaddr_in server_addr; struct hostent *server_host; #if WINDOWS || WINCE WSADATA wsaData; if (!wsa_init_done) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) == SOCKET_ERROR) { return EST_ERR_NET_SOCKET_FAILED; } wsa_init_done = 1; } #else signal(SIGPIPE, SIG_IGN); #endif if ((server_host = gethostbyname(host)) == NULL) { return EST_ERR_NET_UNKNOWN_HOST; } if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) { return EST_ERR_NET_SOCKET_FAILED; } memcpy((void *)&server_addr.sin_addr, (void *)server_host->h_addr, server_host->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons(port); if (connect(*fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) { closesocket(*fd); return EST_ERR_NET_CONNECT_FAILED; } return 0; }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, bool priority) { if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { return -1; } bool sendpriority = 1; if (send_pending_data(con) == -1) { if (priority) { sendpriority = 0; } else { return 0; } } VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); memcpy(packet, &c_length, sizeof(uint16_t)); int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { return -1; } if (priority) { len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0; if (len <= 0) { len = 0; } increment_nonce(con->sent_nonce); if ((unsigned int)len == SIZEOF_VLA(packet)) { return 1; } return add_priority(con, packet, SIZEOF_VLA(packet), len); } len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL); if (len <= 0) { return 0; } increment_nonce(con->sent_nonce); if ((unsigned int)len == SIZEOF_VLA(packet)) { return 1; } memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); con->last_packet_length = SIZEOF_VLA(packet); con->last_packet_sent = len; return 1; }
/* * Initiate a TCP connection with host:port */ int net_connect( int *fd, const char *host, int port ) { struct sockaddr_in server_addr; #if LWIP_DNS == 1 struct hostent *server_host; #endif #if defined(_WIN32) || defined(_WIN32_WCE) WSADATA wsaData; if( wsa_init_done == 0 ) { if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); wsa_init_done = 1; } #else #if (!defined(__ICCARM__)) && (!defined(__CC_ARM)) && (!defined(__GNUC__)) && (!defined(__TASKING__)) signal( SIGPIPE, SIG_IGN ); #endif #endif #if LWIP_DNS == 1 if( ( server_host = gethostbyname( host ) ) == NULL ) { printf( "SSL: ! gethostbyname ERROR :" ); printf(host); printf( "\n" ); return( POLARSSL_ERR_NET_UNKNOWN_HOST ); } printf ( "SSL: gethostbyname OK\n" ); memcpy( (void *) &server_addr.sin_addr, (void *) server_host->h_addr, server_host->h_length ); #else printf( "SSL: no DNS mode\n" ); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_len = sizeof(server_addr); server_addr.sin_addr.s_addr = inet_addr(host); #endif if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons( port ); if( connect( *fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) < 0 ) { close( *fd ); return( POLARSSL_ERR_NET_CONNECT_FAILED ); } return( 0 ); }
/* * Create a listening socket on bind_ip:port */ int net_bind(int *fd, char *bind_ip, int port) { int n, c[4]; struct sockaddr_in server_addr; #if defined(WIN32) || defined(_WIN32_WCE) WSADATA wsaData; if (wsa_init_done == 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) == SOCKET_ERROR) return (TROPICSSL_ERR_NET_SOCKET_FAILED); wsa_init_done = 1; } #else signal(SIGPIPE, SIG_IGN); #endif if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) return (TROPICSSL_ERR_NET_SOCKET_FAILED); n = 1; setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&n, sizeof(n)); server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons(port); if (bind_ip != NULL) { memset(c, 0, sizeof(c)); sscanf(bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3]); for (n = 0; n < 4; n++) if (c[n] < 0 || c[n] > 255) break; if (n == 4) server_addr.sin_addr.s_addr = ((unsigned long)c[0] << 24) | ((unsigned long)c[1] << 16) | ((unsigned long)c[2] << 8) | ((unsigned long)c[3]); } if (bind(*fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { close(*fd); return (TROPICSSL_ERR_NET_BIND_FAILED); } if (listen(*fd, 10) != 0) { close(*fd); return (TROPICSSL_ERR_NET_LISTEN_FAILED); } return (0); }
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ static void lan_discovery(Friend_Connections *fr_c) { if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < mono_time_get(fr_c->mono_time)) { const uint16_t first = fr_c->next_lan_port; uint16_t last = first + PORTS_PER_DISCOVERY; last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last; // Always send to default port lan_discovery_send(net_htons(TOX_PORT_DEFAULT), fr_c->dht); // And check some extra ports for (uint16_t port = first; port < last; ++port) { lan_discovery_send(net_htons(port), fr_c->dht); } // Don't include default port in port range fr_c->next_lan_port = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1; fr_c->last_lan_discovery = mono_time_get(fr_c->mono_time); } }
/* * Initiate a TCP connection with host:port */ int net_connect( int *fd, const char *host, int port ) { struct sockaddr_in server_addr; struct hostent *server_host; #if defined(_WIN32) || defined(_WIN32_WCE) WSADATA wsaData; if( wsa_init_done == 0 ) { if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); wsa_init_done = 1; } #else signal( SIGPIPE, SIG_IGN ); #endif memset( &server_addr, 0, sizeof(server_addr) ); server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons (port); if( ( server_host = gethostbyname( host ) ) == NULL ){ server_addr.sin_addr.s_addr = inet_addr( host ); if ( server_addr.sin_addr.s_addr == INADDR_NONE ) return( POLARSSL_ERR_NET_UNKNOWN_HOST ); }else{ memcpy( (void *) &server_addr.sin_addr, (void *) server_host->h_addr, server_host->h_length ); } if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); if( connect( *fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) < 0 ) { close( *fd ); return( POLARSSL_ERR_NET_CONNECT_FAILED ); } return( 0 ); }
/* * Create a listening socket on bind_ip:port */ int net_bind( int *fd, const char *bind_ip, int port, int proto ) { #if defined(POLARSSL_HAVE_IPV6) int n, ret; struct addrinfo hints, *addr_list, *cur; char port_str[6]; if( ( ret = net_prepare() ) != 0 ) return( ret ); /* getaddrinfo expects port as a string */ memset( port_str, 0, sizeof( port_str ) ); polarssl_snprintf( port_str, sizeof( port_str ), "%d", port ); /* Bind to IPv6 and/or IPv4, but only in TCP */ memset( &hints, 0, sizeof( hints ) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if( bind_ip == NULL ) hints.ai_flags = AI_PASSIVE; if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 ) return( POLARSSL_ERR_NET_UNKNOWN_HOST ); /* Try the sockaddrs until a binding succeeds */ ret = POLARSSL_ERR_NET_UNKNOWN_HOST; for( cur = addr_list; cur != NULL; cur = cur->ai_next ) { *fd = (int) socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); if( *fd < 0 ) { ret = POLARSSL_ERR_NET_SOCKET_FAILED; continue; } n = 1; if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof( n ) ) != 0 ) { close( *fd ); ret = POLARSSL_ERR_NET_SOCKET_FAILED; continue; } if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 ) { close( *fd ); ret = POLARSSL_ERR_NET_BIND_FAILED; continue; } /* Listen only makes sense for TCP */ if( proto == NET_PROTO_TCP ) { if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) { close( *fd ); ret = POLARSSL_ERR_NET_LISTEN_FAILED; continue; } } /* I we ever get there, it's a success */ ret = 0; break; } freeaddrinfo( addr_list ); return( ret ); #else /* Legacy IPv4-only version */ int ret, n, c[4]; struct sockaddr_in server_addr; if( ( ret = net_prepare() ) != 0 ) return( ret ); if( ( *fd = (int) socket( AF_INET, proto == NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, proto == NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP ) ) < 0 ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); n = 1; setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof( n ) ); server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY ); server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons( port ); if( bind_ip != NULL ) { memset( c, 0, sizeof( c ) ); sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] ); for( n = 0; n < 4; n++ ) if( c[n] < 0 || c[n] > 255 ) break; if( n == 4 ) server_addr.sin_addr.s_addr = net_htonl( ( (uint32_t) c[0] << 24 ) | ( (uint32_t) c[1] << 16 ) | ( (uint32_t) c[2] << 8 ) | ( (uint32_t) c[3] ) ); } if( bind( *fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) < 0 ) { close( *fd ); return( POLARSSL_ERR_NET_BIND_FAILED ); } /* Listen only makes sense for TCP */ if( proto == NET_PROTO_TCP ) { if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) { close( *fd ); return( POLARSSL_ERR_NET_LISTEN_FAILED ); } } return( 0 ); #endif /* POLARSSL_HAVE_IPV6 */ }
/* * Initiate a TCP connection with host:port and the given protocol */ int net_connect( int *fd, const char *host, int port, int proto ) { #if defined(POLARSSL_HAVE_IPV6) int ret; struct addrinfo hints, *addr_list, *cur; char port_str[6]; if( ( ret = net_prepare() ) != 0 ) return( ret ); /* getaddrinfo expects port as a string */ memset( port_str, 0, sizeof( port_str ) ); polarssl_snprintf( port_str, sizeof( port_str ), "%d", port ); /* Do name resolution with both IPv6 and IPv4 */ memset( &hints, 0, sizeof( hints ) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 ) return( POLARSSL_ERR_NET_UNKNOWN_HOST ); /* Try the sockaddrs until a connection succeeds */ ret = POLARSSL_ERR_NET_UNKNOWN_HOST; for( cur = addr_list; cur != NULL; cur = cur->ai_next ) { *fd = (int) socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); if( *fd < 0 ) { ret = POLARSSL_ERR_NET_SOCKET_FAILED; continue; } if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) { ret = 0; break; } close( *fd ); ret = POLARSSL_ERR_NET_CONNECT_FAILED; } freeaddrinfo( addr_list ); return( ret ); #else /* Legacy IPv4-only version */ int ret; struct sockaddr_in server_addr; struct hostent *server_host; if( ( ret = net_prepare() ) != 0 ) return( ret ); if( ( server_host = gethostbyname( host ) ) == NULL ) return( POLARSSL_ERR_NET_UNKNOWN_HOST ); if( ( *fd = (int) socket( AF_INET, proto == NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, proto == NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP ) ) < 0 ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); memcpy( (void *) &server_addr.sin_addr, (void *) server_host->h_addr, server_host->h_length ); server_addr.sin_family = AF_INET; server_addr.sin_port = net_htons( port ); if( connect( *fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) < 0 ) { close( *fd ); return( POLARSSL_ERR_NET_CONNECT_FAILED ); } return( 0 ); #endif /* POLARSSL_HAVE_IPV6 */ }
int main(int argc, char *argv[]) { if (argc == 2 && !tox_strncasecmp(argv[1], "-h", 3)) { printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]); printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]); exit(0); } /* let user override default by cmdline */ bool ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); if (argvoffset < 0) { exit(1); } /* Initialize networking - Bind to ip 0.0.0.0 / [::] : PORT */ IP ip; ip_init(&ip, ipv6enabled); Logger *logger = logger_new(); if (MIN_LOGGER_LEVEL == LOGGER_LEVEL_TRACE || MIN_LOGGER_LEVEL == LOGGER_LEVEL_DEBUG) { logger_callback_log(logger, print_log, nullptr, nullptr); } Mono_Time *mono_time = mono_time_new(); DHT *dht = new_dht(logger, mono_time, new_networking(logger, ip, PORT), true); Onion *onion = new_onion(mono_time, dht); Onion_Announce *onion_a = new_onion_announce(mono_time, dht); #ifdef DHT_NODE_EXTRA_PACKETS bootstrap_set_callbacks(dht_get_net(dht), DHT_VERSION_NUMBER, DHT_MOTD, sizeof(DHT_MOTD)); #endif if (!(onion && onion_a)) { printf("Something failed to initialize.\n"); exit(1); } perror("Initialization"); manage_keys(dht); printf("Public key: "); uint32_t i; #ifdef TCP_RELAY_ENABLED #define NUM_PORTS 3 uint16_t ports[NUM_PORTS] = {443, 3389, PORT}; TCP_Server *tcp_s = new_TCP_server(ipv6enabled, NUM_PORTS, ports, dht_get_self_secret_key(dht), onion); if (tcp_s == nullptr) { printf("TCP server failed to initialize.\n"); exit(1); } #endif const char *const public_id_filename = "PUBLIC_ID.txt"; FILE *file = fopen(public_id_filename, "w"); if (file == nullptr) { printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename); exit(1); } for (i = 0; i < 32; i++) { const uint8_t *const self_public_key = dht_get_self_public_key(dht); printf("%02X", self_public_key[i]); fprintf(file, "%02X", self_public_key[i]); } fclose(file); printf("\n"); printf("Port: %u\n", net_ntohs(net_port(dht_get_net(dht)))); if (argc > argvoffset + 3) { printf("Trying to bootstrap into the network...\n"); uint16_t port = net_htons(atoi(argv[argvoffset + 2])); uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); int res = dht_bootstrap_from_address(dht, argv[argvoffset + 1], ipv6enabled, port, bootstrap_key); free(bootstrap_key); if (!res) { printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]); exit(1); } } int is_waiting_for_dht_connection = 1; uint64_t last_LANdiscovery = 0; lan_discovery_init(dht); while (1) { mono_time_update(mono_time); if (is_waiting_for_dht_connection && dht_isconnected(dht)) { printf("Connected to other bootstrap node successfully.\n"); is_waiting_for_dht_connection = 0; } do_dht(dht); if (mono_time_is_timeout(mono_time, last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { lan_discovery_send(net_htons(PORT), dht); last_LANdiscovery = mono_time_get(mono_time); } #ifdef TCP_RELAY_ENABLED do_TCP_server(tcp_s, mono_time); #endif networking_poll(dht_get_net(dht), nullptr); c_sleep(1); } }