Netz- und Broadcast IP-Adresse finden leicht gemacht

Nachdem nun einige Monate keine neuen Beiträge kamen, habe ich nun endlich wieder etwas Zeit, um hier einen neuen Beitrag zu veröffentlichen. Diesmal beschäftigen wir uns mit dem einfachen Finden von Netz- sowie Broadcast IP-Adressen in einem Netzwerk. Auch wenn dies sehr simpel ist, benötigt es einige Aktionen auf Bit-Ebene, um das Problem zu lösen. Damit hier eine sichere Funktionalität gewährleistet ist, möchte ich darauf hinweisen, dass die Größe der Datentypen hierbei sehr entscheidend sein kann. Kommen wir nun zum Sourcecode. 

Beginnen wir mit der Methoden- sowie die Ergebnisdatentyp-Definition. Diese sieht in meinem Beispiel wie folgt aus:

public class AnalyzedIpDataResponse 
{
	public string IpAddress { get; private set; }
	public string Subnetmask { get; private set; }
	
	public string NetAddress { get; private set; }
	public string BroadcastAddress { get; private set; }
	
	public int AvailableClients { get; private set; }
	
	public AnalyzedIpDataResponse(string ip, string mask, string net, string broadcast, int clients) 
	{
		IpAddress = ip;
		Subnetmask = mask;
		
		NetAddress = net;
		BroadcastAddress = broadcast;
		
		AvailableClients = clients;
	}
}
/// <summary>
/// Method to define network data such as net address and broadcast address.
/// </summary>
/// <param name="ipAddress">A ip address from the network. Format: 10.10.11.50/16</param>
/// <returns>A detailed response with network informations.</returns>
public AnalyzedIpDataResponse DetermineNetwork(string ipAddress)
{
    throw new NotImplementedException();
}

Nun geht es darum die Funktionalität zu implementieren. Man beachte an dieser Stelle die Kommentare im Quelltext, die Informationen zur Dateneingabe liefern. Im nächsten Schritt sollten wir die IP-Adresse sowie die Anzahl der Subnetmasken-Bits von einander trennen.

    string[] parts = ipAddress.Split(new[] { '/' });
    string ip = parts[0];
    string mask = parts[1];

Nachdem wir auch dies erledigt haben, definieren wir uns zwei zusätzliche Methoden, die im nächsten Schritt benötigt werden. Dies wäre zum einen das Umwandeln einer IP-Adresse zu einen Int32 Wert und zum anderen das genaue Gegenteil. Auch wenn diese Methoden bereits im .NET Framework definiert sind, schadet es nicht Kenntnis darüber zu haben wie diese Funktionieren aufgebaut sind, um diese auch in anderen Programmiersprachen wie z.B. Perl, C, PHP, usw. nutzen zu können.

private string ConvertIntToIpString(uint value)
{
    return string.Format("{0}.{1}.{2}.{3}", (value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF);
}

private uint ConvertIpStringToInt(string value)
{
    string[] parts = value.Split(new[] { '.' });
    return (Convert.ToUInt32(parts[0]) << 24) + (Convert.ToUInt32(parts[1]) << 16) + (Convert.ToUInt32(parts[2]) << 8) + Convert.ToUInt32(parts[3]);
}

Da wir nun auch diese Methoden haben, können wir im nächsten Schritt unsere IP-Adresse in einen Int32 wandeln und den Int32 Wert der Subnetzsmaske bestimmen. Um den Int32-Wert unserer Subnetzmaske zu bestimmen, nehmen wir einfach den uint.MaxValue (0xFFFFFFFF) und schieben hier die Bits um X, wobei X gleich der Anzahl der Bits ist, die als Subnetzmaske verwendet werden.

    uint ipValue = ConvertIpStringToInt(ip);
    uint maskValue = ~(0xFFFFFFFF >> Convert.ToInt32(mask));

    mask = ConvertIntToIpString(maskValue);

Weiter geht es damit, die Netzadresse für die gegebene IP-Adresse zu bestimmen. Dies wird einer simplen Bit-Und-Operation erledigt.

    uint netValue = ipValue & maskValue;
    string net = ConvertIntToIpString(netValue);

Nun müssen wir noch die Broadcast Adresse bestimmen. Dies kann mit einer Kombination einer Bit-Negierung oder einer Bit-Exklusiv-Oder und, in beiden Fällen, einer Bit-Oder Operation erledigt werden.

    uint invertMaskValue = maskValue ^ 0xFFFFFFFF; //Alternativ kann hier auch ~maskValue verwendet werden!
    uint broadcastValue = invertMaskValue | netValue;
    string broadcast = ConvertIntToIpString(broadcastValue);

Wenn wir auch dies erledigt haben, können wir auch ganz simpel die Anzahl der Clients, die in diesem Netzwerk möglich sind ermitteln. Hierbei gilt, dass die Anzahl der Client = invertMaskValue – 2 ist. Nun noch unsere ganzen Werte in den Rückgabetypen packen und zurückgeben. Dann sollte die ganze Methode wie folgt aussehen:

/// <summary>
/// Method to define network data such as net address and broadcast address.
/// </summary>
/// <param name="ipAddress">A ip address from the network. Format: 10.10.11.50/16</param>
/// <returns>A detailed response with network informations.</returns>
public AnalyzedIpDataResponse DetermineNetwork(string ipAddress)
{
    string[] parts = ipAddress.Split(new[] { '/' });
    string ip = parts[0];
    string mask = parts[1];

    uint ipValue = ConvertIpStringToInt(ip);
    uint maskValue = ~(0xFFFFFFFF >> Convert.ToInt32(mask));

    mask = ConvertIntToIpString(maskValue);

    uint netValue = ipValue & maskValue;
    string net = ConvertIntToIpString(netValue);

    uint invertMaskValue = maskValue ^ 0xFFFFFFFF; //Alternativ kann hier auch ~maskValue verwendet werden!
    uint broadcastValue = invertMaskValue | netValue;
    string broadcast = ConvertIntToIpString(broadcastValue);

    return new AnalyzedIpDataResponse(ip, mask, net, broadcast, Convert.ToInt32(invertMaskValue - 2));
}

Ich hoffe dies konnte einigen helfen und ich hoffe in Zukunft wieder mehr Zeit für weitere Blog-Beiträge zu finden!