Skip to content

Commit

Permalink
Merge pull request #71 from maxmind/greg/typed-error
Browse files Browse the repository at this point in the history
Use typed errors for aliased and reserved inserts
  • Loading branch information
marselester authored Oct 5, 2023
2 parents 5199b97 + 4876c99 commit 0699cd0
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 13 deletions.
124 changes: 124 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package mmdbwriter

import (
"errors"
"fmt"
"net"
"net/netip"
)

// AliasedNetworkError is returned when inserting a aliased network into
// a Tree where DisableIPv4Aliasing in Options is false.
type AliasedNetworkError struct {
// AliasedNetwork is the aliased network being inserted into.
AliasedNetwork netip.Prefix
// InsertedNetwork is the network being inserted into the Tree.
InsertedNetwork netip.Prefix
}

func newAliasedNetworkError(netIP net.IP, curPrefixLen, recPrefixLen int) error {
anErr := &AliasedNetworkError{}
ip, ok := netip.AddrFromSlice(netIP)
if !ok {
return errors.Join(
fmt.Errorf("creating netip.Addr from %s", netIP),
anErr,
)
}
var err error
// We are using netip here despite using net.IP/net.IPNet internally as
// it seems quite likely that we will switch to netip throughout.
anErr.InsertedNetwork, err = ip.Prefix(recPrefixLen)
if err != nil {
return errors.Join(
fmt.Errorf(
"creating prefix from addr %s and prefix length %d: %w",
ip,
recPrefixLen,
err,
),
anErr,
)
}

anErr.AliasedNetwork, err = ip.Prefix(curPrefixLen)
if err != nil {
return errors.Join(
fmt.Errorf(
"creating prefix from addr %s and prefix length %d: %w",
ip,
curPrefixLen,
err,
),
anErr,
)
}
return anErr
}

func (r *AliasedNetworkError) Error() string {
return fmt.Sprintf(
"attempt to insert %s into %s, which is an aliased network",
r.InsertedNetwork,
r.AliasedNetwork,
)
}

// ReservedNetworkError is returned when inserting a reserved network into
// a Tree where IncludeReservedNetworks in Options is false.
type ReservedNetworkError struct {
// InsertedNetwork is the network being inserted into the Tree.
InsertedNetwork netip.Prefix
// ReservedNetwork is the reserved network being inserted into.
ReservedNetwork netip.Prefix
}

var _ error = &ReservedNetworkError{}

func newReservedNetworkError(netIP net.IP, curPrefixLen, recPrefixLen int) error {
rnErr := &ReservedNetworkError{}
ip, ok := netip.AddrFromSlice(netIP)
if !ok {
return errors.Join(
fmt.Errorf("creating netip.Addr from %s", netIP),
rnErr,
)
}
var err error
// We are using netip here despite using net.IP/net.IPNet internally as
// it seems quite likely that we will switch to netip throughout.
rnErr.InsertedNetwork, err = ip.Prefix(recPrefixLen)
if err != nil {
return errors.Join(
fmt.Errorf(
"creating prefix from addr %s and prefix length %d: %w",
ip,
recPrefixLen,
err,
),
rnErr,
)
}

rnErr.ReservedNetwork, err = ip.Prefix(curPrefixLen)
if err != nil {
return errors.Join(
fmt.Errorf(
"creating prefix from addr %s and prefix length %d: %w",
ip,
curPrefixLen,
err,
),
rnErr,
)
}
return rnErr
}

func (r *ReservedNetworkError) Error() string {
return fmt.Sprintf(
"attempt to insert %s into %s, which is a reserved network",
r.InsertedNetwork,
r.ReservedNetwork,
)
}
12 changes: 2 additions & 10 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,7 @@ func (r *record) insert(
return r.maybeMergeChildren(iRec)
case recordTypeReserved:
if iRec.prefixLen >= newDepth {
return fmt.Errorf(
"attempt to insert %s/%d, which is in a reserved network",
iRec.ip,
iRec.prefixLen,
)
return newReservedNetworkError(iRec.ip, newDepth, iRec.prefixLen)
}
// If we are inserting a network that contains a reserved network,
// we silently remove the reserved network.
Expand All @@ -133,11 +129,7 @@ func (r *record) insert(
return nil
}
// attempting to insert _into_ an aliased network
return fmt.Errorf(
"attempt to insert %s/%d, which is in an aliased network",
iRec.ip,
iRec.prefixLen,
)
return newAliasedNetworkError(iRec.ip, newDepth, iRec.prefixLen)
default:
return fmt.Errorf("inserting into record type %d is not implemented", r.recordType)
}
Expand Down
6 changes: 3 additions & 3 deletions tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,19 +341,19 @@ func TestTreeInsertAndGet(t *testing.T) {
network: "10.0.0.0/8",
start: "10.0.0.0",
end: "10.255.255.255",
expectedErrorMsg: "attempt to insert ::a00:0/104, which is in a reserved network",
expectedErrorMsg: "attempt to insert ::a00:0/104 into ::a00:0/104, which is a reserved network",
},
{
network: "10.0.0.1/32",
start: "10.0.0.1",
end: "10.0.0.1",
expectedErrorMsg: "attempt to insert ::a00:1/128, which is in a reserved network",
expectedErrorMsg: "attempt to insert ::a00:1/128 into ::a00:0/104, which is a reserved network",
},
{
network: "2002:100::/24",
start: "2002:100::",
end: "2002:1ff:ffff:ffff:ffff:ffff:ffff:ffff",
expectedErrorMsg: "attempt to insert 2002:100::/24, which is in an aliased network",
expectedErrorMsg: "attempt to insert 2002:100::/24 into 2002::/16, which is an aliased network",
},
},
gets: []testGet{
Expand Down

0 comments on commit 0699cd0

Please sign in to comment.