/// <summary>Enumerates through the siblings of an <see cref="T:System.Net.IPAddress"/> in a network.</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
/// <param name="options">Options which addresses to include an which not</param>
public static IEnumerable <IPAddress> GetSiblings(this IPAddress address, NetMask mask, SiblingOptions options)
{
if (address == null)
{
throw new ArgumentNullException(nameof(address));
}
if (mask == null)
{
throw new ArgumentNullException(nameof(mask));
}
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
{
throw new NotSupportedException(OnlyIPv4Supported);
}
bool includeSelf = BitHelper.IsOptionSet(options, SiblingOptions.IncludeSelf);
bool includeBroadcast = BitHelper.IsOptionSet(options, SiblingOptions.IncludeBroadcast);
bool includeNetworkIdentifier = BitHelper.IsOptionSet(options, SiblingOptions.IncludeNetworkIdentifier);
bool alreadyReturnedSelf = false;
var netPrefix = address.GetNetworkPrefix(mask);
if (includeNetworkIdentifier)
{
netPrefix = address.GetNetworkPrefix(mask);
if (netPrefix.Equals(address))
{
alreadyReturnedSelf = true;
}
yield return(netPrefix);
}
var selfAddressBytes = address.GetAddressBytes();
var netPrefixBytes = netPrefix.GetAddressBytes();
int cidr = mask.Cidr;
uint maxHosts = 0xFFFFFFFF;
if (cidr > 0)
{
maxHosts = (uint)(1 << (8 * NetMask.MaskLength - cidr)) - 1;
}
var hostBytes = new byte[NetMask.MaskLength];
for (int hostPart = 1; hostPart < maxHosts; ++hostPart)
{
unchecked
{
hostBytes[0] = (byte)(hostPart >> 24);
hostBytes[1] = (byte)(hostPart >> 16);
hostBytes[2] = (byte)(hostPart >> 8);
hostBytes[3] = (byte)(hostPart >> 0);
}
Debug.WriteLine("HostPart: " + hostPart.ToString("X2").PadLeft(8, '0') + " (" + BitConverter.ToString(hostBytes) + ")");
var nextIpBytes = netPrefixBytes.Or(hostBytes);
var nextIp = new IPAddress(nextIpBytes);
if (!alreadyReturnedSelf)
{
if (includeSelf)
{
if (nextIpBytes[0] == selfAddressBytes[0] &&
nextIpBytes[1] == selfAddressBytes[1] &&
nextIpBytes[2] == selfAddressBytes[2] &&
nextIpBytes[3] == selfAddressBytes[3])
{
alreadyReturnedSelf = true;
}
yield return(nextIp);
}
else if (nextIpBytes[0] != selfAddressBytes[0] ||
nextIpBytes[1] != selfAddressBytes[1] ||
nextIpBytes[2] != selfAddressBytes[2] ||
nextIpBytes[3] != selfAddressBytes[3])
{
yield return(nextIp);
}
}
else
{
yield return(nextIp);
}
}
if (includeBroadcast)
{
var broadcastAddress = address.GetBroadcastAddress(mask);
if (!address.Equals(broadcastAddress) || (address.Equals(broadcastAddress) && !alreadyReturnedSelf))
{
yield return(broadcastAddress);
}
}
}