2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file host.cpp Functions related to getting host specific data (IPs). */
10 #include "../../stdafx.h"
11 #include "../../debug.h"
12 #include "../../core/alloc_func.hpp"
15 #include "../../safeguards.h"
18 * Internal implementation for finding the broadcast IPs.
19 * This function is implemented multiple times for multiple targets.
20 * @param broadcast the list of broadcasts to write into.
22 static void NetworkFindBroadcastIPsInternal(NetworkAddressList
*broadcast
);
25 static void NetworkFindBroadcastIPsInternal(NetworkAddressList
*broadcast
) // Win32 implementation
27 SOCKET sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
28 if (sock
== INVALID_SOCKET
) return;
32 INTERFACE_INFO
*ifo
= CallocT
<INTERFACE_INFO
>(num
);
35 if (WSAIoctl(sock
, SIO_GET_INTERFACE_LIST
, nullptr, 0, ifo
, num
* sizeof(*ifo
), &len
, nullptr, nullptr) == 0) break;
37 if (WSAGetLastError() != WSAEFAULT
) {
42 ifo
= CallocT
<INTERFACE_INFO
>(num
);
45 for (uint j
= 0; j
< len
/ sizeof(*ifo
); j
++) {
46 if (ifo
[j
].iiFlags
& IFF_LOOPBACK
) continue;
47 if (!(ifo
[j
].iiFlags
& IFF_BROADCAST
)) continue;
49 sockaddr_storage address
;
50 memset(&address
, 0, sizeof(address
));
51 /* iiBroadcast is unusable, because it always seems to be set to 255.255.255.255. */
52 memcpy(&address
, &ifo
[j
].iiAddress
.Address
, sizeof(sockaddr
));
53 ((sockaddr_in
*)&address
)->sin_addr
.s_addr
= ifo
[j
].iiAddress
.AddressIn
.sin_addr
.s_addr
| ~ifo
[j
].iiNetmask
.AddressIn
.sin_addr
.s_addr
;
54 NetworkAddress
addr(address
, sizeof(sockaddr
));
55 if (std::none_of(broadcast
->begin(), broadcast
->end(), [&addr
](NetworkAddress
const &elem
) -> bool { return elem
== addr
; })) broadcast
->push_back(addr
);
63 static void NetworkFindBroadcastIPsInternal(NetworkAddressList
*broadcast
)
65 struct ifaddrs
*ifap
, *ifa
;
67 if (getifaddrs(&ifap
) != 0) return;
69 for (ifa
= ifap
; ifa
!= nullptr; ifa
= ifa
->ifa_next
) {
70 if (!(ifa
->ifa_flags
& IFF_BROADCAST
)) continue;
71 if (ifa
->ifa_broadaddr
== nullptr) continue;
72 if (ifa
->ifa_broadaddr
->sa_family
!= AF_INET
) continue;
74 NetworkAddress
addr(ifa
->ifa_broadaddr
, sizeof(sockaddr
));
75 if (std::none_of(broadcast
->begin(), broadcast
->end(), [&addr
](NetworkAddress
const &elem
) -> bool { return elem
== addr
; })) broadcast
->push_back(addr
);
79 #endif /* all NetworkFindBroadcastIPsInternals */
82 * Find the IPv4 broadcast addresses; IPv6 uses a completely different
83 * strategy for broadcasting.
84 * @param broadcast the list of broadcasts to write into.
86 void NetworkFindBroadcastIPs(NetworkAddressList
*broadcast
)
88 NetworkFindBroadcastIPsInternal(broadcast
);
90 /* Now display to the debug all the detected ips */
91 Debug(net
, 3, "Detected broadcast addresses:");
93 for (NetworkAddress
&addr
: *broadcast
) {
94 addr
.SetPort(NETWORK_DEFAULT_PORT
);
95 Debug(net
, 3, " {}) {}", i
++, addr
.GetHostname());