0
votes

I'm writing an app that will store the IP Addresses of where requests are coming from. Those IP Addresses will be stored as a varbinary(16) in my database. Its become apparent that a varbinary(16) is not the proper size. Currently, I'm using the following code to get the IP Address of a request into a byte[];

HttpRequestMessage request = GetRequestMessage();

string ipAddress = string.Empty;
if (request.Properties.ContainsKey("MS_HttpContext"))
{
  ipAddress = ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
}
else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
  RemoteEndpointMessageProperty property = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
  ipAddress = property.Address;
}

byte[] bytes = new byte[ipAddress.Length * sizeof(char)];
System.Buffer.BlockCopy(ipAddress.ToCharArray(), 0, bytes, 0, bytes.Length);

// What is the maximum size of bytes?

I've noticed that bytes has a length of 26. My question is, what is the largest size that bytes can be if I need to support IPv6 addresses? I need to know to change the size of my varbinary(16) to the appropriate length.

Thank you!

2
Just a side note - everyone's saying varbinary(16), but since you know you want to store exactly 16 bytes, you can use binary(16) instead and lose the overhead of the variable length. Or as @PhonicUK stated, uniqueidentifier works as well.Joe Enos
Except a varbinary(16) can store IPv4 addresses efficiently too.tomfanning
@tomfanning Good point. You'd have to look at the size of the data every single time you retrieve it, to see if it's 4 bytes or 16 before you can use it, but it would save space if you have a lot of records and a significant percentage of them are v4.Joe Enos
@JoeEnos If you just take the byte array from the database and pass it to the constructor of System.Net.IPAddress, an instance of the correct family will be produced. From the docs: "If the length of address is 4, IPAddress(Byte[]) constructs an IPv4 address; otherwise, an IPv6 address with a scope of 0 is constructed." Writing code that uses IPAddress helps with writing code that works fine with both IPv4 and IPv6.tomfanning
@tomfanning Cool, didn't know that was all built in.Joe Enos

2 Answers

4
votes
byte[] bytes = new byte[ipAddress.Length * sizeof(char)];

This looks like something written by a C programmer, you don't need to do any of this.

All you need is ipAddress.GetAddressBytes() and shove that in a binary(16)

As a side note, you can also use a uniqueidentifier to store IPv6 addresses since they are the same length. These are much faster to search with than a varbinary

4
votes

The IPv6 address space is 128 bits. Therefore, any IPv6 address can be represented using 16 bytes. Therefore, varbinary(16) is correct.

However, the way you are extracting the bytes is, with respect, odd.

Please see the documentation for IPAddress.GetAddressBytes()

(Looks like you might also need IPAddress.Parse())