Skip to content

Commit

Permalink
Merge pull request #4 from ns1/export-validations
Browse files Browse the repository at this point in the history
Exported validation functions.
  • Loading branch information
antoniovl authored Aug 4, 2020
2 parents 07ce488 + 68be870 commit a22535a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 30 deletions.
86 changes: 59 additions & 27 deletions pkg/validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package validator

import (
"errors"
"fmt"
"net"
"strings"
Expand All @@ -25,6 +26,8 @@ import (
"go.uber.org/multierr"
)

var errUnparsableNetworkAddr = errors.New("unparsable network address")

func LoadAndValidate(filename string) (*model.RoutemapRoot, model.RoutemapSummary, error) {
var (
rmap *model.RoutemapRoot
Expand All @@ -50,15 +53,18 @@ func isAsciiOnly(s string) bool {
return true
}

func validateProperCIDR(ip net.IP, ipnet *net.IPNet) error {
// ValidateProperCIDR verifies that the IP address corresponds to the network.
func ValidateProperCIDR(ip net.IP, ipnet *net.IPNet) error {
if !ip.Equal(ipnet.IP) {
return fmt.Errorf("network address not properly masked")
}

return nil
}

func validateNetmaskLen(ipnet *net.IPNet) error {
// ValidateNetmaskLen verifies that the mask length does not exceeds the maximum
// allowed value.
func ValidateNetmaskLen(ipnet *net.IPNet) error {
numOnes, numBits := ipnet.Mask.Size()
switch {
case numOnes == 0 && numBits == 0:
Expand All @@ -72,44 +78,70 @@ func validateNetmaskLen(ipnet *net.IPNet) error {
}
}

func validateNetworks(nets []string, mapIdx int, summary *model.RoutemapSummary) error {
var allErrs error
// ValidateNetwork takes an string representing a network from the JSON source
// file and validates it.
// Returns the parsed IP and IPNet along with an error instance that can possibly
// be a multierr instance.
//
// If the network can not be parsed, only the error instance will contain values.
// The correctness of the network depends on the returned error having a nil value.
func ValidateNetwork(network string) (net.IP, *net.IPNet, error) {
var errs []error

ip, ipnet, err := net.ParseCIDR(network)
if err != nil {
return nil, nil, errUnparsableNetworkAddr
}

if err = ValidateProperCIDR(ip, ipnet); err != nil {
errs = append(errs, err)
}
if err = ValidateNetmaskLen(ipnet); err != nil {
errs = append(errs, err)
}

return ip, ipnet, multierr.Combine(errs...)
}

func ValidateNetworks(nets []string, mapIdx int, summary *model.RoutemapSummary) error {
var (
allErrs error
err error
ipnet *net.IPNet
)

summary.NumNetworks += len(nets)

for idx, n := range nets {
lg.Tracef("visiting networks at index=%d, map segment index=%d...", idx, mapIdx)

ip, ipnet, err := net.ParseCIDR(n)
_, ipnet, err = ValidateNetwork(n)
if err != nil {
multierr.AppendInto(&allErrs,
fmt.Errorf("unparsable network address (for CIDR \"%s\" at index=%d, map segment index=%d)", n, idx, mapIdx))
for _, e := range multierr.Errors(err) {
// Rehydrate the packed errors so we can set the proper individual
// error messages.
multierr.AppendInto(&allErrs,
fmt.Errorf("%v (for CIDR \"%s\" at index=%d, map segment index=%d)",
e, n, idx, mapIdx))
}
continue
}

if _, bits := ipnet.Mask.Size(); bits == 32 {
summary.NumIPv4 += 1
} else {
summary.NumIPv6 += 1
}

var errs []error

errs = append(errs, validateProperCIDR(ip, ipnet))
errs = append(errs, validateNetmaskLen(ipnet))

for _, e := range errs {
if e != nil {
multierr.AppendInto(&allErrs,
fmt.Errorf("%v (for CIDR \"%s\" at index=%d, map segment index=%d)", e, n, idx, mapIdx))
// ValidateNetwork will return a nil ipnet if the string was unparsable.
if ipnet != nil {
if _, bits := ipnet.Mask.Size(); bits == 32 {
summary.NumIPv4 += 1
} else {
summary.NumIPv6 += 1
}
}
}

return allErrs
}

func validateLabels(labels []string, mapIdx int, summary *model.RoutemapSummary) error {
// ValidateLabels validates the set of labels of the route map.
func ValidateLabels(labels []string, mapIdx int, summary *model.RoutemapSummary) error {
var allErrs error

if len(labels) == 0 {
Expand Down Expand Up @@ -147,7 +179,7 @@ func validateLabels(labels []string, mapIdx int, summary *model.RoutemapSummary)
return allErrs
}

func validateVersion(version int) error {
func ValidateVersion(version int) error {
if version < 1 {
return fmt.Errorf("invalid or missing meta/version")
} else if version != 1 {
Expand All @@ -158,7 +190,7 @@ func validateVersion(version int) error {
}

func startValidate(root *model.RoutemapRoot, summary *model.RoutemapSummary) error {
if err := validateVersion(root.MetaVersion()); err != nil {
if err := ValidateVersion(root.MetaVersion()); err != nil {
return err
}

Expand All @@ -181,8 +213,8 @@ func startValidate(root *model.RoutemapRoot, summary *model.RoutemapSummary) err
continue
}

multierr.AppendInto(&allErrs, validateNetworks(m.Networks, idx, summary))
multierr.AppendInto(&allErrs, validateLabels(m.Labels, idx, summary))
multierr.AppendInto(&allErrs, ValidateNetworks(m.Networks, idx, summary))
multierr.AppendInto(&allErrs, ValidateLabels(m.Labels, idx, summary))

if lg.EnabledFor(lg.LevelDebug) && (summary.NumNetworks-lastProgressReport) > 500000 {
numErrs := len(multierr.Errors(allErrs))
Expand Down
6 changes: 3 additions & 3 deletions pkg/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func Test_validateProperCIDR(t *testing.T) {
ip, ipnet, err := net.ParseCIDR(fx.addr)
assert.NoError(t, err, fx.addr)

err = validateProperCIDR(ip, ipnet)
err = ValidateProperCIDR(ip, ipnet)
if fx.valid {
assert.NoError(t, err, fx.addr)
} else {
Expand All @@ -64,7 +64,7 @@ func Test_validateNetmaskLen(t *testing.T) {
_, ipnet, err := net.ParseCIDR(fx.addr)
assert.NoError(t, err, fx.addr)

err = validateNetmaskLen(ipnet)
err = ValidateNetmaskLen(ipnet)
if fx.valid {
assert.NoError(t, err, fx.addr)
} else {
Expand All @@ -88,7 +88,7 @@ func Test_validateLabels(t *testing.T) {
summary := model.NewRoutemapSummary()

for _, fx := range fixtures {
err := validateLabels(fx.labels, 1, &summary)
err := ValidateLabels(fx.labels, 1, &summary)
if fx.valid {
assert.NoError(t, err, fx.labels)
} else {
Expand Down

0 comments on commit a22535a

Please sign in to comment.