using System; using System.Data; using System.Data.SqlClient; using Microsoft.SqlServer.Server; using System.Net; using System.Collections.Generic; using System.Text; using System.Data.SqlTypes; using System.Numerics; namespace SqlCustomFunctions { public static class IPFunctions { [Microsoft.SqlServer.Server.SqlFunction()] static public byte[] ipIPV6toBIN16(SqlString IP) { BigInteger rv = new BigInteger(); try { IPAddress ipAddress = null;//IPAddress.TryParse(IPV6Address, out _); if (IPAddress.TryParse(IP.ToString(), out ipAddress) && ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { byte[] addressBytes = ipAddress.GetAddressBytes(); // flip big-endian(network order) to little-endian if (BitConverter.IsLittleEndian) Array.Reverse(addressBytes); rv = new BigInteger(addressBytes); } } catch //(Exception ex) { rv = 0; } return rv.ToByteArray(); } [Microsoft.SqlServer.Server.SqlFunction()] static public SqlString ipBIN16toIPV6(byte[] IP) { SqlString rv = string.Empty; try { byte[] paddedBytes = new byte[16]; if (IP.Length > 16) { // Truncate to 16 bytes (take the most significant bytes for IPv6) Array.Copy(IP, IP.Length - 16, paddedBytes, 0, 16); } else if (IP.Length < 16) { // Pad with leading zeros (for smaller numbers) Array.Copy(IP, 0, paddedBytes, 16 - IP.Length, IP.Length); } else { Array.Copy(IP, paddedBytes, 16); } // flip big-endian(network order) to little-endian if (BitConverter.IsLittleEndian) Array.Reverse(paddedBytes); IPAddress ipAddress = new IPAddress(paddedBytes); rv = ipAddress.ToString(); } catch //(Exception ex) { rv = string.Empty; } return rv; } [Microsoft.SqlServer.Server.SqlFunction()] static public byte[] ipIPV4toBIN4(SqlString IP) { var rv = new byte[] { 0, 0, 0, 0 }; try { IPAddress ipAddress = null; if (IPAddress.TryParse(IP.ToString(), out ipAddress) && ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { byte[] addressBytes = ipAddress.GetAddressBytes(); // flip big-endian(network order) to little-endian // -- Can't do this, because it would break legacy code! -- //if (BitConverter.IsLittleEndian) // Array.Reverse(addressBytes); rv = addressBytes; //BitConverter.ToUInt32(addressBytes, 0); } } catch //(Exception) { rv = new byte[] { 0, 0, 0, 0 }; } return rv; } [Microsoft.SqlServer.Server.SqlFunction()] static public SqlString ipBIN4toIPV4(byte[] IP) { SqlString rv = string.Empty; try { byte[] paddedBytes = new byte[4]; if (IP.Length > 4) { // Truncate to 16 bytes (take the most significant bytes for IPv6) Array.Copy(IP, IP.Length - 4, paddedBytes, 0, 4); } else if (IP.Length < 4) { // Pad with leading zeros (for smaller numbers) Array.Copy(IP, 0, paddedBytes, 4 - IP.Length, IP.Length); } else { Array.Copy(IP, paddedBytes, 4); } // flip big-endian(network order) to little-endian // -- Can't do this, because it would break legacy code! -- //if (BitConverter.IsLittleEndian) // Array.Reverse(paddedBytes); IPAddress ipAddress = new IPAddress(paddedBytes); rv = ipAddress.ToString(); } catch //(Exception ex) { rv = string.Empty; } return rv; } } }