1

I am in need to find out how I can find out if a provided subnet mask example (255.255.192.0) is a valid subnet mask and return true if it is valid and false if not, I already am checking if the value is over 255. A wrong subnet would be (255.64.0.0)

It makes a lot of sense in binary (11111111.01000000.00000000.00000000) A subnet can not stop having 1's, and then start having them again. My current idea involves using bitshift, but am unsure how to do it.

I am not using any libaries and am not allowed for this project

The code I am using goes something like

    Console.WriteLine("Enter a subnet mask");
    input = Console.ReadLine(); //Enters example of 255.64.0.0 which is invalid

Thanks in advance, ask questions if needed

  • 1
    Does this answer your question? [How to check if an IP address is within a particular subnet](https://stackoverflow.com/questions/1499269/how-to-check-if-an-ip-address-is-within-a-particular-subnet) – Deniz Nov 23 '21 at 23:38
  • 1
    If I was writing it myself. Convert the value to an int (in machine byte order). XOR to flip `111000` into `000111` Add 1 so you should now have `001000`. If the address is valid, you should have at most 1 bit set. Now AND the last two values together. If the answer is zero, the address is a valid mask. – Jeremy Lakeman Nov 24 '21 at 00:08
  • Not really, the code you linked showed how to find a subnet and check if it was the right length, I need to check that even if is the wrong length, that it is still valid or not – Fredrick Xtz Nov 24 '21 at 00:08
  • @JeremyLakeman amazing answer, I understand what you mean, but I am not that good of turning words into code if you get what I mean, if you ever have the time, could you maybe write an example – Fredrick Xtz Nov 24 '21 at 01:13

2 Answers2

3

I looked for a library method, but couldn't find one. Here's how I would write it for IPv4 addresses only;

public static bool IsValidMask(string mask)
{
    // 1) convert the address to an int32
    if (!IPAddress.TryParse(mask, out var addr))
        return false;
    var byteVal = addr.GetAddressBytes();
    if (byteVal.Length != 4)
        return false;
    var intVal = BitConverter.ToInt32(byteVal);
    intVal = IPAddress.NetworkToHostOrder(intVal);

    // A valid mask should start with ones, and end with zeros 0b111...111000...000

    // 2) XOR to flip all the bits (0b000...000111...111)
    var uintVal = (uint)intVal ^ uint.MaxValue;

    // 3) Add 1, causing all those 1's to become 0's. (0b000...001000...000)
    // An invalid address will have leading 1's that are untouched by this step. (0b101...001000...000)
    var addOne = uintVal + 1;

    // 4) AND the two values together, to detect if any leading 1's remain
    var ret = addOne & uintVal;

    return ret == 0;
}
Jeremy Lakeman
  • 9,515
  • 25
  • 29
0

You can try this way:

using System;
using System.Runtime.InteropServices;

namespace Example
{
    public class Program
    {   
        [StructLayout(LayoutKind.Explicit)]
        public struct byte_array
        {
            [FieldOffset(0)]
            public byte byte0;
            [FieldOffset(1)]
            public byte byte1;
            [FieldOffset(2)]
            public byte byte2;
            [FieldOffset(3)]
            public byte byte3;

            [FieldOffset(0)]
            public UInt32 Addr;
        }
        
        public static void Main(string[] args)
        {
            byte_array b_array = new byte_array();
            int i;
            
            b_array.byte3 = 255;
            b_array.byte2 = 64;
            b_array.byte1 = 0;
            b_array.byte0 = 0;
            
            Console.WriteLine(String.Format("{0:X4}", b_array.Addr));
            
            for(i = 31; i >= 0; i--)
                if(((1 << i) & b_array.Addr) == 0)
                    break;
            for(; i >= 0; i--)
                if(((1 << i) & b_array.Addr) != 0)
                {
                    Console.WriteLine("Bad Mask!");
                    break;
                }
        }
    }
}