diff --git a/src/classes/public/IPConfig.ps1 b/src/classes/public/IPConfig.ps1
new file mode 100644
index 0000000..21da2f7
--- /dev/null
+++ b/src/classes/public/IPConfig.ps1
@@ -0,0 +1,73 @@
+class IPConfig {
+ # The interface name
+ [string] $InterfaceName
+
+ # The interface description
+ [string] $Description
+
+ # The interface status
+ [System.Net.NetworkInformation.OperationalStatus] $Status
+
+ # The address family
+ [string] $AddressFamily
+
+ # The IP address
+ [string] $IPAddress
+
+ # The prefix length
+ [int] $PrefixLength
+
+ # The subnet mask
+ [string] $SubnetMask
+
+ # The gateway
+ [string] $Gateway
+
+ # The DNS servers
+ [string] $DNSServers
+
+ IPConfig(
+ [System.Net.NetworkInformation.NetworkInterface] $Interface,
+ [System.Net.NetworkInformation.UnicastIPAddressInformation] $AddressInformation,
+ [System.Net.NetworkInformation.IPInterfaceProperties] $InterfaceProperties
+ ) {
+ $this.InterfaceName = $Interface.Name
+ $this.Description = $Interface.Description
+ $this.Status = $Interface.OperationalStatus
+ switch ($AddressInformation.Address.AddressFamily) {
+ ([System.Net.Sockets.AddressFamily]::InterNetwork) { $this.AddressFamily = 'IPv4'; break }
+ ([System.Net.Sockets.AddressFamily]::InterNetworkV6) { $this.AddressFamily = 'IPv6'; break }
+ default { $this.AddressFamily = $AddressInformation.Address.AddressFamily.ToString() }
+ }
+ $this.IPAddress = $AddressInformation.Address.IPAddressToString
+ $this.PrefixLength = $AddressInformation.PrefixLength
+
+ if ($AddressInformation.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork) {
+ $this.SubnetMask = [IPConfig]::ConvertPrefixToMask($AddressInformation.PrefixLength)
+ } else {
+ # IPv6 masks are represented by prefix length
+ $this.SubnetMask = $null
+ }
+
+ $this.Gateway = ($InterfaceProperties.GatewayAddresses | ForEach-Object { $_.Address.IPAddressToString }) -join ', '
+ $this.DNSServers = ($InterfaceProperties.DnsAddresses | ForEach-Object { $_.IPAddressToString }) -join ', '
+ }
+
+ hidden static [string] ConvertPrefixToMask([int] $prefixLength) {
+ if ($prefixLength -le 0) { return '0.0.0.0' }
+ if ($prefixLength -ge 32) { return '255.255.255.255' }
+
+ [int[]] $octets = 0, 0, 0, 0
+ $bits = $prefixLength
+ for ($i = 0; $i -lt 4; $i++) {
+ $take = [Math]::Min(8, $bits)
+ if ($take -le 0) {
+ $octets[$i] = 0
+ } else {
+ $octets[$i] = 255 - ([math]::Pow(2, (8 - $take)) - 1)
+ }
+ $bits -= $take
+ }
+ return ($octets -join '.')
+ }
+}
diff --git a/src/formats/IPConfig.Format.ps1xml b/src/formats/IPConfig.Format.ps1xml
new file mode 100644
index 0000000..bef5a11
--- /dev/null
+++ b/src/formats/IPConfig.Format.ps1xml
@@ -0,0 +1,57 @@
+
+
+
+
+ IPConfigTable
+
+ IPConfig
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+ Status
+
+
+ Type
+
+
+ IPAddress
+
+
+ Gateway
+
+
+ DNSServers
+
+
+
+
+
+
+
+
diff --git a/src/functions/private/Get-SubnetMaskFromPrefix.ps1 b/src/functions/private/Get-SubnetMaskFromPrefix.ps1
new file mode 100644
index 0000000..46ce559
--- /dev/null
+++ b/src/functions/private/Get-SubnetMaskFromPrefix.ps1
@@ -0,0 +1,58 @@
+function Get-SubnetMaskFromPrefix {
+ <#
+ .SYNOPSIS
+ Converts a CIDR prefix length into a subnet mask in dotted decimal notation.
+
+ .DESCRIPTION
+ The Get-SubnetMaskFromPrefix function accepts an integer prefix (e.g., 24) and converts it into a corresponding
+ subnet mask (e.g., 255.255.255.0). It supports prefix lengths from 0 through 32. If the input prefix is outside
+ this valid range, the function returns `$null`. This is useful when translating CIDR-style network definitions
+ into traditional subnet mask format.
+
+ .EXAMPLE
+ Get-SubnetMaskFromPrefix -prefix 24
+
+ Output:
+ ```powershell
+ 255.255.255.0
+ ```
+
+ Converts a /24 prefix to the subnet mask 255.255.255.0.
+
+ .OUTPUTS
+ System.String
+
+ .NOTES
+ The subnet mask string in dotted decimal format (e.g., 255.255.255.0).
+ Returns `$null` if the prefix is not within the valid range (0–32).
+
+ .LINK
+ https://psmodule.io/Net/Functions/Get-SubnetMaskFromPrefix
+ #>
+ [OutputType([string])]
+ [CmdletBinding()]
+ param(
+ # The CIDR prefix length (0–32) to convert into a subnet mask.
+ [Parameter(Mandatory)]
+ [int] $prefix
+ )
+
+ if ($prefix -lt 0 -or $prefix -gt 32) { return $null }
+
+ $bytes = [byte[]](0..3 | ForEach-Object {
+ # Calculate the number of subnet bits for this octet (max 8, min 0)
+ $bits = [Math]::Max([Math]::Min($prefix - (8 * $_), 8), 0)
+ if ($bits -le 0) {
+ # If no bits are set for this octet, value is 0
+ 0
+ } elseif ($bits -ge 8) {
+ # If all bits are set for this octet, value is 255
+ 255
+ } else {
+ # For partial octets, shift 0xFF left by (8 - $bits) to set the correct number of bits,
+ # then mask with 0xFF to ensure only 8 bits are used
+ ((0xFF -shl (8 - $bits)) -band 0xFF)
+ }
+ })
+ [System.Net.IPAddress]::new($bytes).ToString()
+}
diff --git a/src/functions/public/Get-NetIPConfiguration.ps1 b/src/functions/public/Get-NetIPConfiguration.ps1
new file mode 100644
index 0000000..d4d108c
--- /dev/null
+++ b/src/functions/public/Get-NetIPConfiguration.ps1
@@ -0,0 +1,83 @@
+function Get-NetIPConfiguration {
+ <#
+ .SYNOPSIS
+ Retrieves IP configuration details for network interfaces on the system.
+
+ .DESCRIPTION
+ This function gathers IP configuration data, including IP addresses, subnet masks, gateway addresses,
+ and DNS servers for all network interfaces. It supports optional filtering by interface operational status
+ (Up or Down) and address family (IPv4 or IPv6). The output includes detailed per-address information in
+ a structured object format for each network interface and IP address combination.
+
+ .EXAMPLE
+ Get-NetIPConfiguration
+
+ Output:
+ ```powershell
+ InterfaceName : Ethernet
+ Description : Intel(R) Ethernet Connection
+ Status : Up
+ AddressFamily : InterNetwork
+ IPAddress : 192.168.1.10
+ PrefixLength : 24
+ SubnetMask : 255.255.255.0
+ Gateway : 192.168.1.1
+ DNSServers : 8.8.8.8, 1.1.1.1
+ ```
+
+ Retrieves the IPv4 configuration for all network interfaces that are currently operational (Up).
+
+ .OUTPUTS
+ IPConfig
+
+ .LINK
+ https://psmodule.io/Net/Functions/Get-NetIPConfiguration
+ #>
+
+ [Alias('IPConfig')]
+ [OutputType([IPConfig])]
+ [CmdletBinding()]
+ param(
+ # Filters interfaces based on operational status ('Up' or 'Down')
+ [Parameter()]
+ [ValidateSet('Up', 'Down')]
+ [string] $InterfaceStatus,
+
+ # Filters IP addresses by address family ('IPv4' or 'IPv6')
+ [Parameter()]
+ [ValidateSet('IPv4', 'IPv6')]
+ [string] $AddressFamily
+ )
+
+ # Map AddressFamily parameter to .NET enum
+ $familyEnum = $null
+ if ($AddressFamily) {
+ $familyEnum = if ($AddressFamily -eq 'IPv4') {
+ [System.Net.Sockets.AddressFamily]::InterNetwork
+ } else {
+ [System.Net.Sockets.AddressFamily]::InterNetworkV6
+ }
+ }
+
+ $interfaces = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()
+
+ # Apply optional interface status filter using enum for robustness
+ if ($InterfaceStatus) {
+ $statusEnum = [System.Net.NetworkInformation.OperationalStatus]::$InterfaceStatus
+ $interfaces = $interfaces | Where-Object { $_.OperationalStatus -eq $statusEnum }
+ }
+
+ foreach ($adapter in $interfaces) {
+ $ipProps = $adapter.GetIPProperties()
+
+ # Filter unicast addresses by address family if requested
+ $unicast = $ipProps.UnicastAddresses
+ if ($familyEnum) {
+ $unicast = $unicast | Where-Object { $_.Address.AddressFamily -eq $familyEnum }
+ }
+
+ foreach ($addr in $unicast) {
+ [IPConfig]::new($adapter, $addr, $ipProps)
+ }
+ }
+}
diff --git a/src/functions/public/Test-PSModuleTest.ps1 b/src/functions/public/Test-PSModuleTest.ps1
deleted file mode 100644
index 26be2b9..0000000
--- a/src/functions/public/Test-PSModuleTest.ps1
+++ /dev/null
@@ -1,18 +0,0 @@
-function Test-PSModuleTest {
- <#
- .SYNOPSIS
- Performs tests on a module.
-
- .EXAMPLE
- Test-PSModule -Name 'World'
-
- "Hello, World!"
- #>
- [CmdletBinding()]
- param (
- # Name of the person to greet.
- [Parameter(Mandatory)]
- [string] $Name
- )
- Write-Output "Hello, $Name!"
-}
diff --git a/src/types/IPConfig.Types.ps1xml b/src/types/IPConfig.Types.ps1xml
new file mode 100644
index 0000000..41289a6
--- /dev/null
+++ b/src/types/IPConfig.Types.ps1xml
@@ -0,0 +1,20 @@
+
+
+
+ IPConfig
+
+
+ Type
+ AddressFamily
+
+
+ Name
+ InterfaceName
+
+
+ Mask
+ PrefixLength
+
+
+
+
diff --git a/tests/PSModuleTest.Tests.ps1 b/tests/Net.Tests.ps1
similarity index 57%
rename from tests/PSModuleTest.Tests.ps1
rename to tests/Net.Tests.ps1
index b28ab23..a3ffab3 100644
--- a/tests/PSModuleTest.Tests.ps1
+++ b/tests/Net.Tests.ps1
@@ -19,8 +19,22 @@
[CmdletBinding()]
param()
-Describe 'Module' {
- It 'Function: Test-PSModuleTest' {
- Test-PSModuleTest -Name 'World' | Should -Be 'Hello, World!'
+Describe 'Net' {
+ Context 'Get-NetIPConfiguration' {
+ It 'returns expected results' {
+ $results = Get-NetIPConfiguration
+ LogGroup 'Results' {
+ Write-Host "$($results | Out-String)"
+ }
+ $results | Should -BeOfType 'IPConfig'
+ }
+
+ It 'IPConfig alias works' {
+ $results = IPConfig
+ LogGroup 'Results' {
+ Write-Host "$($results | Format-List | Out-String)"
+ }
+ $results | Should -BeOfType 'IPConfig'
+ }
}
}