mirror of
https://github.com/caddyserver/caddy.git
synced 2025-12-08 06:09:53 +00:00
Add support for firstipv4 and firstipv6 interface binding modes with tests
This commit is contained in:
parent
d7322226c1
commit
595b404fe0
2 changed files with 23 additions and 1 deletions
10
listeners.go
10
listeners.go
|
|
@ -1049,6 +1049,8 @@ func isInterfaceName(s string) bool {
|
||||||
// Check if the last part is a valid binding mode
|
// Check if the last part is a valid binding mode
|
||||||
lastPart := parts[2]
|
lastPart := parts[2]
|
||||||
if lastPart == string(InterfaceBindingAuto) ||
|
if lastPart == string(InterfaceBindingAuto) ||
|
||||||
|
lastPart == string(InterfaceBindingFirstIPv4) ||
|
||||||
|
lastPart == string(InterfaceBindingFirstIPv6) ||
|
||||||
lastPart == string(InterfaceBindingIPv4) ||
|
lastPart == string(InterfaceBindingIPv4) ||
|
||||||
lastPart == string(InterfaceBindingIPv6) ||
|
lastPart == string(InterfaceBindingIPv6) ||
|
||||||
lastPart == string(InterfaceBindingAll) {
|
lastPart == string(InterfaceBindingAll) {
|
||||||
|
|
@ -1113,6 +1115,8 @@ func tryParseInterfaceWithModeInHost(host string) (interfaceWithMode, bool) {
|
||||||
|
|
||||||
// Check if the last part is a valid binding mode
|
// Check if the last part is a valid binding mode
|
||||||
if parts[2] != string(InterfaceBindingAuto) &&
|
if parts[2] != string(InterfaceBindingAuto) &&
|
||||||
|
parts[2] != string(InterfaceBindingFirstIPv4) &&
|
||||||
|
parts[2] != string(InterfaceBindingFirstIPv6) &&
|
||||||
parts[2] != string(InterfaceBindingIPv4) &&
|
parts[2] != string(InterfaceBindingIPv4) &&
|
||||||
parts[2] != string(InterfaceBindingIPv6) &&
|
parts[2] != string(InterfaceBindingIPv6) &&
|
||||||
parts[2] != string(InterfaceBindingAll) {
|
parts[2] != string(InterfaceBindingAll) {
|
||||||
|
|
@ -1162,6 +1166,10 @@ func parseInterfaceAddress(network, host, port string) (NetworkAddress, error) {
|
||||||
switch modeStr {
|
switch modeStr {
|
||||||
case "auto":
|
case "auto":
|
||||||
mode = InterfaceBindingAuto
|
mode = InterfaceBindingAuto
|
||||||
|
case "firstipv4":
|
||||||
|
mode = InterfaceBindingFirstIPv4
|
||||||
|
case "firstipv6":
|
||||||
|
mode = InterfaceBindingFirstIPv6
|
||||||
case "ipv4":
|
case "ipv4":
|
||||||
mode = InterfaceBindingIPv4
|
mode = InterfaceBindingIPv4
|
||||||
case "ipv6":
|
case "ipv6":
|
||||||
|
|
@ -1169,7 +1177,7 @@ func parseInterfaceAddress(network, host, port string) (NetworkAddress, error) {
|
||||||
case "all":
|
case "all":
|
||||||
mode = InterfaceBindingAll
|
mode = InterfaceBindingAll
|
||||||
default:
|
default:
|
||||||
return NetworkAddress{}, fmt.Errorf("unknown interface binding mode: %s (supported: auto, ipv4, ipv6, all)", modeStr)
|
return NetworkAddress{}, fmt.Errorf("unknown interface binding mode: %s (supported: auto, firstipv4, firstipv6, ipv4, ipv6, all)", modeStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,10 @@ func TestIsInterfaceNameWithModes(t *testing.T) {
|
||||||
{"br-901e40e4488d:3000:ipv6", true, "docker bridge with IPv6 mode"},
|
{"br-901e40e4488d:3000:ipv6", true, "docker bridge with IPv6 mode"},
|
||||||
{"veth1308dcd:8080:auto", true, "veth pair with auto mode"},
|
{"veth1308dcd:8080:auto", true, "veth pair with auto mode"},
|
||||||
{"eth0:8080:all", true, "ethernet interface with all mode"},
|
{"eth0:8080:all", true, "ethernet interface with all mode"},
|
||||||
|
{"eth0:8080:firstipv4", true, "ethernet interface with firstipv4 mode"},
|
||||||
|
{"wlan0:443:firstipv6", true, "wireless interface with firstipv6 mode"},
|
||||||
|
{"docker0:9000:firstipv4", true, "docker interface with firstipv4 mode"},
|
||||||
|
{"enp0s3:8080:firstipv6", true, "predictable interface with firstipv6 mode"},
|
||||||
|
|
||||||
// Invalid - wrong modes
|
// Invalid - wrong modes
|
||||||
{"eth0:8080:invalid", false, "interface with invalid mode"},
|
{"eth0:8080:invalid", false, "interface with invalid mode"},
|
||||||
|
|
@ -496,11 +500,17 @@ func TestParseInterfaceAddress(t *testing.T) {
|
||||||
{"tcp", "enp0s3", "9000:auto", "enp0s3" + InterfaceDelimiter + "auto", false, "valid interface with explicit auto mode"},
|
{"tcp", "enp0s3", "9000:auto", "enp0s3" + InterfaceDelimiter + "auto", false, "valid interface with explicit auto mode"},
|
||||||
{"tcp", "eth0", "443:all", "eth0" + InterfaceDelimiter + "all", false, "valid interface with all mode"},
|
{"tcp", "eth0", "443:all", "eth0" + InterfaceDelimiter + "all", false, "valid interface with all mode"},
|
||||||
{"tcp", "wlan0", "8080-8090:all", "wlan0" + InterfaceDelimiter + "all", false, "port range with all mode"},
|
{"tcp", "wlan0", "8080-8090:all", "wlan0" + InterfaceDelimiter + "all", false, "port range with all mode"},
|
||||||
|
{"tcp", "eth0", "443:firstipv4", "eth0" + InterfaceDelimiter + "firstipv4", false, "valid interface with firstipv4 mode"},
|
||||||
|
{"tcp", "wlan0", "8080:firstipv6", "wlan0" + InterfaceDelimiter + "firstipv6", false, "valid interface with firstipv6 mode"},
|
||||||
|
{"tcp", "docker0", "9000:firstipv4", "docker0" + InterfaceDelimiter + "firstipv4", false, "docker interface with firstipv4 mode"},
|
||||||
|
{"tcp", "enp0s3", "8080:firstipv6", "enp0s3" + InterfaceDelimiter + "firstipv6", false, "predictable interface with firstipv6 mode"},
|
||||||
|
|
||||||
// Valid cases - port ranges with binding modes
|
// Valid cases - port ranges with binding modes
|
||||||
{"tcp", "eth0", "8080-8090:ipv4", "eth0" + InterfaceDelimiter + "ipv4", false, "port range with IPv4 mode"},
|
{"tcp", "eth0", "8080-8090:ipv4", "eth0" + InterfaceDelimiter + "ipv4", false, "port range with IPv4 mode"},
|
||||||
{"tcp", "wlan0", "443-445:ipv6", "wlan0" + InterfaceDelimiter + "ipv6", false, "port range with IPv6 mode"},
|
{"tcp", "wlan0", "443-445:ipv6", "wlan0" + InterfaceDelimiter + "ipv6", false, "port range with IPv6 mode"},
|
||||||
{"tcp", "docker0", "3000-3010:auto", "docker0" + InterfaceDelimiter + "auto", false, "port range with auto mode"},
|
{"tcp", "docker0", "3000-3010:auto", "docker0" + InterfaceDelimiter + "auto", false, "port range with auto mode"},
|
||||||
|
{"tcp", "eth0", "8080-8090:firstipv4", "eth0" + InterfaceDelimiter + "firstipv4", false, "port range with firstipv4 mode"},
|
||||||
|
{"tcp", "wlan0", "443-445:firstipv6", "wlan0" + InterfaceDelimiter + "firstipv6", false, "port range with firstipv6 mode"},
|
||||||
|
|
||||||
// Error cases - invalid hosts
|
// Error cases - invalid hosts
|
||||||
{"tcp", "192.168.1.1", "80", "", true, "IP address should fail"},
|
{"tcp", "192.168.1.1", "80", "", true, "IP address should fail"},
|
||||||
|
|
@ -588,6 +598,10 @@ func TestTryParseInterfaceWithModeInHost(t *testing.T) {
|
||||||
{"tailscale0:8090:ipv4", "tailscale0", "8090:ipv4", true, "Tailscale interface with IPv4 mode"},
|
{"tailscale0:8090:ipv4", "tailscale0", "8090:ipv4", true, "Tailscale interface with IPv4 mode"},
|
||||||
{"docker0:3000:ipv6", "docker0", "3000:ipv6", true, "Docker bridge interface with IPv6 mode"},
|
{"docker0:3000:ipv6", "docker0", "3000:ipv6", true, "Docker bridge interface with IPv6 mode"},
|
||||||
{"wlan0:443:all", "wlan0", "443:all", true, "Wireless interface with all mode"},
|
{"wlan0:443:all", "wlan0", "443:all", true, "Wireless interface with all mode"},
|
||||||
|
{"eth0:8080:firstipv4", "eth0", "8080:firstipv4", true, "Ethernet interface with firstipv4 mode"},
|
||||||
|
{"wlan0:443:firstipv6", "wlan0", "443:firstipv6", true, "Wireless interface with firstipv6 mode"},
|
||||||
|
{"docker0:9000:firstipv4", "docker0", "9000:firstipv4", true, "Docker interface with firstipv4 mode"},
|
||||||
|
{"enp0s3:8080:firstipv6", "enp0s3", "8080:firstipv6", true, "Predictable interface with firstipv6 mode"},
|
||||||
|
|
||||||
// Invalid cases - not enough parts
|
// Invalid cases - not enough parts
|
||||||
{"eth0", "", "", false, "Interface name only"},
|
{"eth0", "", "", false, "Interface name only"},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue