Refuse IPv4-mapped prefixes with an error that says so
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
715cb772e7
commit
83b97ad538
3 files changed
+36
-1
No files matched your search
@@ -162,6 +162,9 @@ All notable changes to Housecarl are documented here. The format follows
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- An IPv4-mapped prefix (`::ffff:0:0/96`) is refused with an error that
|
||||||
|
says so; it was refused as "has host bits set; the prefix is invalid
|
||||||
|
Prefix".
|
||||||
- `hc forward show` shows the forward's hits and comment, and its
|
- `hc forward show` shows the forward's hits and comment, and its
|
||||||
hairpin as `no`, `yes` or `yes, from …` (it printed `no -`).
|
hairpin as `no`, `yes` or `yes, from …` (it printed `no -`).
|
||||||
- A history entry's ruleset diff showed the object it changed as moved:
|
- A history entry's ruleset diff showed the object it changed as moved:
|
||||||
|
|||||||
@@ -84,7 +84,11 @@ func ParseAddress(s string) (Address, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Address{}, fmt.Errorf("%q is not an address or prefix", s)
|
return Address{}, fmt.Errorf("%q is not an address or prefix", s)
|
||||||
}
|
}
|
||||||
p = netip.PrefixFrom(p.Addr().Unmap(), p.Bits())
|
if p.Addr().Is4In6() {
|
||||||
|
// Unmapping would leave an IPv4 address with IPv6 bits
|
||||||
|
// (::ffff:0:0/96 as 0.0.0.0/96).
|
||||||
|
return Address{}, fmt.Errorf("%q is an IPv4-mapped prefix, which can't be used: write IPv4 prefixes as IPv4 (10.0.0.0/8)", s)
|
||||||
|
}
|
||||||
if p.Masked() != p {
|
if p.Masked() != p {
|
||||||
return Address{}, fmt.Errorf("%q has host bits set; the prefix is %s", s, p.Masked())
|
return Address{}, fmt.Errorf("%q has host bits set; the prefix is %s", s, p.Masked())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseAddress(t *testing.T) {
|
||||||
|
for _, c := range []struct{ in, want, err string }{
|
||||||
|
{in: "10.0.0.0/8", want: "10.0.0.0/8"},
|
||||||
|
{in: "2001:db8::/32", want: "2001:db8::/32"},
|
||||||
|
{in: "::ffff:10.0.0.1", want: "10.0.0.1"},
|
||||||
|
{in: "10.0.0.1/8", err: "host bits"},
|
||||||
|
{in: "::ffff:0:0/96", err: "IPv4-mapped"},
|
||||||
|
{in: "::ffff:10.0.0.0/104", err: "IPv4-mapped"},
|
||||||
|
} {
|
||||||
|
a, err := ParseAddress(c.in)
|
||||||
|
if c.err != "" {
|
||||||
|
if err == nil || !strings.Contains(err.Error(), c.err) {
|
||||||
|
t.Errorf("%s: error %v, want one saying %q", c.in, err, c.err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil || a.String() != c.want {
|
||||||
|
t.Errorf("%s: %q, %v; want %q", c.in, a.String(), err, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user