Skip to content

Commit

Permalink
Added IPs/routes validation
Browse files Browse the repository at this point in the history
Signed-off-by: Oleg Solodkov <oleg.solodkov@xored.com>
  • Loading branch information
sol-0 committed Dec 16, 2021
1 parent d31e64f commit fed2486
Show file tree
Hide file tree
Showing 7 changed files with 526 additions and 82 deletions.
105 changes: 87 additions & 18 deletions pkg/networkservice/common/excludedprefixes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ package excludedprefixes

import (
"context"
"net"

"github.com/edwarnicke/serialize"
"github.com/golang/protobuf/ptypes/empty"
"github.com/networkservicemesh/api/pkg/api/networkservice"
"github.com/pkg/errors"
"google.golang.org/grpc"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/tools/ippool"
"github.com/networkservicemesh/sdk/pkg/tools/log"
"github.com/networkservicemesh/sdk/pkg/tools/postpone"
)

type excludedPrefixesClient struct {
Expand Down Expand Up @@ -53,36 +57,58 @@ func (epc *excludedPrefixesClient) Request(ctx context.Context, request *network
logger := log.FromContext(ctx).WithField("ExcludedPrefixesClient", "Request")
ipCtx := conn.GetContext().GetIpContext()

var newExcludedPrefixes []string
oldExcludedPrefixes := ipCtx.GetExcludedPrefixes()
if len(epc.excludedPrefixes) > 0 {
<-epc.executor.AsyncExec(func() {
logger.Debugf("Adding new excluded IPs to the request: %+v", epc.excludedPrefixes)
excludedPrefixes := ipCtx.GetExcludedPrefixes()
excludedPrefixes = append(excludedPrefixes, epc.excludedPrefixes...)
excludedPrefixes = removeDuplicates(excludedPrefixes)
newExcludedPrefixes = ipCtx.GetExcludedPrefixes()
newExcludedPrefixes = append(newExcludedPrefixes, epc.excludedPrefixes...)
newExcludedPrefixes = RemoveDuplicates(newExcludedPrefixes)

logger.Debugf("Excluded prefixes from request - %+v", excludedPrefixes)
ipCtx.ExcludedPrefixes = excludedPrefixes
// excluding IPs for current request/connection before calling next client for the refresh use-case
newExcludedPrefixes = Exclude(newExcludedPrefixes, append(ipCtx.GetSrcIpAddrs(), ipCtx.GetDstIpAddrs()...))

logger.Debugf("Excluded prefixes from request - %+v", newExcludedPrefixes)
ipCtx.ExcludedPrefixes = newExcludedPrefixes
})
}

postponeCtxFunc := postpone.ContextWithValues(ctx)

resp, err := next.Client(ctx).Request(ctx, request, opts...)
if err != nil {
if oldExcludedPrefixes != nil {
ipCtx.ExcludedPrefixes = oldExcludedPrefixes
}
ipCtx.ExcludedPrefixes = oldExcludedPrefixes
return resp, err
}

respIpContext := resp.GetContext().GetIpContext()
logger.Debugf("Request excluded IPs - srcIPs: %v, dstIPs: %v, excluded prefixes: %v", respIpContext.GetSrcIpAddrs(),
respIpContext.GetDstIpAddrs(), respIpContext.GetExcludedPrefixes())
respIPContext := resp.GetContext().GetIpContext()

err = validateIPs(respIPContext, newExcludedPrefixes)
if err != nil {
closeCtx, cancelFunc := postponeCtxFunc()
defer cancelFunc()

logger.Errorf("Source or destination IPs are overlapping with excluded prefixes, srcIPs: %+v, dstIPs: %+v, excluded prefixes: %+v, error: %s",
respIPContext.GetSrcIpAddrs(), respIPContext.GetDstIpAddrs(), newExcludedPrefixes, err.Error())

if _, closeErr := next.Client(ctx).Close(closeCtx, conn, opts...); closeErr != nil {
err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error())
}

return nil, err
}

logger.Debugf("Request excluded IPs - srcIPs: %v, dstIPs: %v, excluded prefixes: %v", respIPContext.GetSrcIpAddrs(),
respIPContext.GetDstIpAddrs(), respIPContext.GetExcludedPrefixes())

<-epc.executor.AsyncExec(func() {
epc.excludedPrefixes = append(epc.excludedPrefixes, respIpContext.GetSrcIpAddrs()...)
epc.excludedPrefixes = append(epc.excludedPrefixes, respIpContext.GetDstIpAddrs()...)
epc.excludedPrefixes = append(epc.excludedPrefixes, respIpContext.GetExcludedPrefixes()...)
epc.excludedPrefixes = removeDuplicates(epc.excludedPrefixes)
epc.excludedPrefixes = append(epc.excludedPrefixes, respIPContext.GetSrcIpAddrs()...)
epc.excludedPrefixes = append(epc.excludedPrefixes, respIPContext.GetDstIpAddrs()...)
epc.excludedPrefixes = append(epc.excludedPrefixes, getRoutePrefixes(respIPContext.GetSrcRoutes())...)
epc.excludedPrefixes = append(epc.excludedPrefixes, getRoutePrefixes(respIPContext.GetDstRoutes())...)
epc.excludedPrefixes = append(epc.excludedPrefixes, respIPContext.GetExcludedPrefixes()...)
epc.excludedPrefixes = RemoveDuplicates(epc.excludedPrefixes)
logger.Debugf("Added excluded prefixes: %+v", epc.excludedPrefixes)
})

Expand All @@ -94,11 +120,54 @@ func (epc *excludedPrefixesClient) Close(ctx context.Context, conn *networkservi
ipCtx := conn.GetContext().GetIpContext()

<-epc.executor.AsyncExec(func() {
epc.excludedPrefixes = exclude(epc.excludedPrefixes, ipCtx.GetSrcIpAddrs())
epc.excludedPrefixes = exclude(epc.excludedPrefixes, ipCtx.GetDstIpAddrs())
epc.excludedPrefixes = exclude(epc.excludedPrefixes, ipCtx.GetExcludedPrefixes())
epc.excludedPrefixes = Exclude(epc.excludedPrefixes, ipCtx.GetSrcIpAddrs())
epc.excludedPrefixes = Exclude(epc.excludedPrefixes, ipCtx.GetDstIpAddrs())
epc.excludedPrefixes = Exclude(epc.excludedPrefixes, getRoutePrefixes(ipCtx.GetSrcRoutes()))
epc.excludedPrefixes = Exclude(epc.excludedPrefixes, getRoutePrefixes(ipCtx.GetDstRoutes()))
epc.excludedPrefixes = Exclude(epc.excludedPrefixes, ipCtx.GetExcludedPrefixes())
logger.Debugf("Excluded prefixes after closing connection: %+v", epc.excludedPrefixes)
})

return next.Client(ctx).Close(ctx, conn, opts...)
}

func getRoutePrefixes(routes []*networkservice.Route) []string {
var rv []string
for _, route := range routes {
rv = append(rv, route.GetPrefix())
}

return rv
}

func validateIPs(ipContext *networkservice.IPContext, excludedPrefixes []string) error {
ip4Pool := ippool.New(net.IPv4len)
ip6Pool := ippool.New(net.IPv6len)

for _, prefix := range excludedPrefixes {
_, ipNet, err := net.ParseCIDR(prefix)
if err != nil {
return err
}

ip4Pool.AddNet(ipNet)
ip6Pool.AddNet(ipNet)
}

prefixes := make([]string, 0, len(ipContext.GetSrcIpAddrs())+len(ipContext.GetDstIpAddrs()))
prefixes = append(prefixes, ipContext.GetSrcIpAddrs()...)
prefixes = append(prefixes, ipContext.GetDstIpAddrs()...)

for _, prefix := range prefixes {
ip, _, err := net.ParseCIDR(prefix)
if err != nil {
return err
}

if ip4Pool.Contains(ip) || ip6Pool.Contains(ip) {
return errors.Errorf("IP %v is excluded, but it was found in response IPs", ip)
}
}

return nil
}
Loading

0 comments on commit fed2486

Please sign in to comment.