std::string AddressToString( const netadr_t& address, bool with_port ) { if ( address.type == netadrtype_t::NA_LOOPBACK ) { return "loopback"; } else if ( address.type == netadrtype_t::NA_BOT ) { return "bot"; } else if ( address.type == netadrtype_t::NA_IP || address.type == netadrtype_t::NA_IP6 || address.type == netadrtype_t::NA_IP_DUAL ) { char s[ NET_ADDR_STR_MAX_LEN ]; sockaddr_storage sadr = {0}; NetadrToSockadr( &address, reinterpret_cast<sockaddr*>(&sadr) ); Sys_SockaddrToString( s, sizeof(s), reinterpret_cast<sockaddr*>(&sadr) ); std::string result = s; if ( with_port ) { if ( NET_IS_IPv6( address.type ) ) { result = '[' + result + ']'; } result += ':' + std::to_string(ntohs(GetPort(address))); } return result; } return ""; }
static void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) { memset( s, 0, sizeof( struct sockaddr ) ); if ( a->type == NA_BROADCAST ) { ( ( struct sockaddr_in * ) s )->sin_family = AF_INET; ( ( struct sockaddr_in * ) s )->sin_port = a->port; ( ( struct sockaddr_in * ) s )->sin_addr.s_addr = INADDR_BROADCAST; } else if ( a->type == NA_IP ) { ( ( struct sockaddr_in * ) s )->sin_family = AF_INET; ( ( struct sockaddr_in * ) s )->sin_addr.s_addr = * ( int * ) &a->ip; ( ( struct sockaddr_in * ) s )->sin_port = ( a->type == NA_IP_DUAL ? a->port4 : a->port ); } else if ( NET_IS_IPv6( a->type ) ) { ( ( struct sockaddr_in6 * ) s )->sin6_family = AF_INET6; ( ( struct sockaddr_in6 * ) s )->sin6_addr = * ( ( struct in6_addr * ) &a->ip6 ); ( ( struct sockaddr_in6 * ) s )->sin6_port = ( a->type == NA_IP_DUAL ? a->port6 : a->port ); ( ( struct sockaddr_in6 * ) s )->sin6_scope_id = a->scope_id; } else if ( a->type == NA_MULTICAST6 ) { ( ( struct sockaddr_in6 * ) s )->sin6_family = AF_INET6; ( ( struct sockaddr_in6 * ) s )->sin6_addr = curgroup.ipv6mr_multiaddr; ( ( struct sockaddr_in6 * ) s )->sin6_port = a->port; } }
unsigned short GetPort(const netadr_t& address) { if ( address.type == netadrtype_t::NA_IP_DUAL ) { if ( NET_IS_IPv4( address.type ) ) { return address.port4; } else if ( NET_IS_IPv6( address.type ) ) { return address.port6; } } return address.port; }
const char *NET_AdrToStringwPort( netadr_t a ) { static char s[ NET_ADDR_W_PORT_STR_MAX_LEN ]; if ( a.type == NA_LOOPBACK ) { Com_sprintf( s, sizeof( s ), "loopback" ); } else if ( a.type == NA_BOT ) { Com_sprintf( s, sizeof( s ), "bot" ); } else if ( NET_IS_IPv4( a.type ) ) { Com_sprintf( s, sizeof( s ), "%s:%hu", NET_AdrToString( a ), ntohs( a.type == NA_IP_DUAL ? a.port4 : a.port ) ); } else if ( NET_IS_IPv6( a.type ) ) { Com_sprintf( s, sizeof( s ), "[%s]:%hu", NET_AdrToString( a ), ntohs( a.type == NA_IP_DUAL ? a.port6 : a.port ) ); } return s; }
/* ================== Sys_SendPacket ================== */ void Sys_SendPacket( int length, const void *data, netadr_t to ) { int ret = SOCKET_ERROR; struct sockaddr_storage addr; if ( to.type != NA_BROADCAST && to.type != NA_IP && to.type != NA_IP_DUAL && to.type != NA_IP6 && to.type != NA_MULTICAST6 ) { Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" ); } if ( ( ip_socket == INVALID_SOCKET && NET_IS_IPv4( to.type ) ) || ( ip_socket == INVALID_SOCKET && to.type == NA_BROADCAST ) || ( ip6_socket == INVALID_SOCKET && NET_IS_IPv6( to.type ) ) || ( ip6_socket == INVALID_SOCKET && to.type == NA_MULTICAST6 ) ) { return; } if ( to.type == NA_MULTICAST6 && ( net_enabled->integer & NET_DISABLEMCAST ) ) { return; } memset( &addr, 0, sizeof( addr ) ); NetadrToSockadr( &to, ( struct sockaddr * ) &addr ); if ( usingSocks && addr.ss_family == AF_INET /*to.type == NA_IP*/ ) { socksBuf[ 0 ] = 0; // reserved socksBuf[ 1 ] = 0; socksBuf[ 2 ] = 0; // fragment (not fragmented) socksBuf[ 3 ] = 1; // address type: IPV4 * ( int * ) &socksBuf[ 4 ] = ( ( struct sockaddr_in * ) &addr )->sin_addr.s_addr; * ( short * ) &socksBuf[ 8 ] = ( ( struct sockaddr_in * ) &addr )->sin_port; memcpy( &socksBuf[ 10 ], data, length ); ret = sendto( ip_socket, ( const char* )socksBuf, length + 10, 0, &socksRelayAddr, sizeof( socksRelayAddr ) ); } else { if ( addr.ss_family == AF_INET ) { ret = sendto( ip_socket, ( const char* )data, length, 0, ( struct sockaddr * ) &addr, sizeof( struct sockaddr_in ) ); } else if ( addr.ss_family == AF_INET6 ) { ret = sendto( ip6_socket, ( const char* )data, length, 0, ( struct sockaddr * ) &addr, sizeof( struct sockaddr_in6 ) ); } } if ( ret == SOCKET_ERROR ) { int err = socketError; // wouldblock is silent if ( err == EAGAIN ) { return; } // some PPP links do not allow broadcasts and return an error if ( ( err == EADDRNOTAVAIL ) && ( ( to.type == NA_BROADCAST ) ) ) { return; } if ( addr.ss_family == AF_INET ) { Com_Printf( "Sys_SendPacket (ipv4): %s\n", NET_ErrorString() ); } else if ( addr.ss_family == AF_INET6 ) { Com_Printf( "Sys_SendPacket (ipv6): %s\n", NET_ErrorString() ); } else { Com_Printf( "Sys_SendPacket (%i): %s\n", addr.ss_family , NET_ErrorString() ); } } }