diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/network/core/address.cpp | 13 | ||||
-rw-r--r-- | src/network/core/address.h | 13 | ||||
-rw-r--r-- | src/network/core/udp.cpp | 14 | ||||
-rw-r--r-- | src/network/network_udp.cpp | 6 |
4 files changed, 39 insertions, 7 deletions
diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 14b52faa8..6045cc98b 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -16,7 +16,10 @@ const char *NetworkAddress::GetHostname() { if (StrEmpty(this->hostname)) { assert(this->address_length != 0); - getnameinfo((struct sockaddr *)&this->address, this->address_length, this->hostname, sizeof(this->hostname), NULL, 0, NI_NUMERICHOST); + char *buf = this->hostname; + if (this->address.ss_family == AF_INET6) buf = strecpy(buf, "[", lastof(this->hostname)); + getnameinfo((struct sockaddr *)&this->address, this->address_length, buf, lastof(this->hostname) - buf, NULL, 0, NI_NUMERICHOST); + if (this->address.ss_family == AF_INET6) strecat(buf, "]", lastof(this->hostname)); } return this->hostname; } @@ -92,6 +95,14 @@ const sockaddr_storage *NetworkAddress::GetAddress() return &this->address; } +bool NetworkAddress::IsFamily(int family) +{ + if (!this->IsResolved()) { + this->Resolve(family, SOCK_STREAM, AI_ADDRCONFIG, NULL, ResolveLoopProc); + } + return this->address.ss_family == family; +} + bool NetworkAddress::IsInNetmask(char *netmask) { /* Resolve it if we didn't do it already */ diff --git a/src/network/core/address.h b/src/network/core/address.h index 4c0abdf63..0d0f61f7e 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -92,7 +92,13 @@ public: NetworkAddress(const char *hostname = "0.0.0.0", uint16 port = 0, int family = AF_INET) : address_length(0) { + /* Also handle IPv6 bracket enclosed hostnames */ + if (StrEmpty(hostname)) hostname = ""; + if (*hostname == '[') hostname++; strecpy(this->hostname, StrEmpty(hostname) ? "" : hostname, lastof(this->hostname)); + char *tmp = strrchr(hostname, ']'); + if (tmp != NULL) *tmp = '\0'; + memset(&this->address, 0, sizeof(this->address)); this->address.ss_family = family; this->SetPort(port); @@ -159,6 +165,13 @@ public: } /** + * Checks of this address is of the given family. + * @param family the family to check against + * @return true if it is of the given family + */ + bool IsFamily(int family); + + /** * Checks whether this IP address is contained by the given netmask. * @param netmask the netmask in CIDR notation to test against. * @note netmask without /n assumes all bits need to match. diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 4a5570002..9fd58eb8d 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -26,6 +26,9 @@ NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind) *this->bind.Append() = *addr; } } else { + /* As hostname NULL and port 0/NULL don't go well when + * resolving it we need to add an address for each of + * the address families we support. */ *this->bind.Append() = NetworkAddress(NULL, 0, AF_INET); } } @@ -76,8 +79,12 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a if (this->sockets.Length() == 0) this->Listen(); for (SocketList::iterator s = this->sockets.Begin(); s != this->sockets.End(); s++) { + /* Make a local copy because if we resolve it we cannot + * easily unresolve it so we can resolve it later again. */ + NetworkAddress send(*recv); + /* Not the same type */ - if (s->first.GetAddress()->ss_family != recv->GetAddress()->ss_family) continue; + if (!send.IsFamily(s->first.GetAddress()->ss_family)) continue; p->PrepareToSend(); @@ -90,10 +97,11 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a #endif /* Send the buffer */ - int res = sendto(s->second, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), recv->GetAddressLength()); + int res = sendto(s->second, (const char*)p->buffer, p->size, 0, (struct sockaddr *)send.GetAddress(), send.GetAddressLength()); + DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString()); /* Check for any errors, but ignore it otherwise */ - if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", recv->GetAddressAsString(), GET_LAST_ERROR()); + if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", send.GetAddressAsString(), GET_LAST_ERROR()); if (!all) break; } diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 55988edca..15677d0fe 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -391,7 +391,7 @@ void NetworkUDPQueryMasterServer() /* packet only contains protocol version */ p.Send_uint8(NETWORK_MASTER_SERVER_VERSION); - _udp_client_socket->SendPacket(&p, &out_addr); + _udp_client_socket->SendPacket(&p, &out_addr, true); DEBUG(net, 2, "[udp] master server queried at %s", out_addr.GetAddressAsString()); } @@ -465,7 +465,7 @@ void NetworkUDPRemoveAdvertiseThread(void *pntr) p.Send_uint16(_settings_client.network.server_port); _network_udp_mutex->BeginCritical(); - if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr); + if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr, true); _network_udp_mutex->EndCritical(); } @@ -496,7 +496,7 @@ void NetworkUDPAdvertiseThread(void *pntr) p.Send_uint64(_session_key); _network_udp_mutex->BeginCritical(); - if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr); + if (_udp_master_socket != NULL) _udp_master_socket->SendPacket(&p, &out_addr, true); _network_udp_mutex->EndCritical(); } |