Search in sources :

Example 1 with SourceNat

use of org.batfish.datamodel.SourceNat in project batfish by batfish.

the class BdpEngine method applySourceNat.

/**
 * Applies the given list of source NAT rules to the given flow and returns the new transformed
 * flow. If {@code sourceNats} is null, empty, or does not contain any ACL rules matching the
 * {@link Flow}, the original flow is returned.
 *
 * <p>Each {@link SourceNat} is expected to be valid: it must have a NAT IP or pool.
 */
static Flow applySourceNat(Flow flow, @Nullable List<SourceNat> sourceNats) {
    if (CommonUtil.isNullOrEmpty(sourceNats)) {
        return flow;
    }
    Optional<SourceNat> matchingSourceNat = sourceNats.stream().filter(sourceNat -> sourceNat.getAcl() != null && sourceNat.getAcl().filter(flow).getAction() != LineAction.REJECT).findFirst();
    if (!matchingSourceNat.isPresent()) {
        // No NAT rule matched.
        return flow;
    }
    SourceNat sourceNat = matchingSourceNat.get();
    Ip natPoolStartIp = sourceNat.getPoolIpFirst();
    if (natPoolStartIp == null) {
        throw new BatfishException(String.format("Error processing Source NAT rule %s: missing NAT address or pool", sourceNat));
    }
    Flow.Builder transformedFlowBuilder = new Flow.Builder(flow);
    transformedFlowBuilder.setSrcIp(natPoolStartIp);
    return transformedFlowBuilder.build();
}
Also used : SourceNat(org.batfish.datamodel.SourceNat) SortedSet(java.util.SortedSet) BiFunction(java.util.function.BiFunction) LRUMap(org.apache.commons.collections4.map.LRUMap) FlowTrace(org.batfish.datamodel.FlowTrace) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) Edge(org.batfish.datamodel.Edge) Interface(org.batfish.datamodel.Interface) Flow(org.batfish.datamodel.Flow) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Topology(org.batfish.datamodel.Topology) CommonUtil.initRemoteBgpNeighbors(org.batfish.common.util.CommonUtil.initRemoteBgpNeighbors) Map(java.util.Map) DataPlane(org.batfish.datamodel.DataPlane) ImmutableMap(com.google.common.collect.ImmutableMap) FlowDisposition(org.batfish.datamodel.FlowDisposition) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) List(java.util.List) SourceNat(org.batfish.datamodel.SourceNat) Entry(java.util.Map.Entry) Optional(java.util.Optional) SortedMap(java.util.SortedMap) BatfishLogger(org.batfish.common.BatfishLogger) Ip(org.batfish.datamodel.Ip) RouteBuilder(org.batfish.datamodel.RouteBuilder) NodeInterfacePair(org.batfish.datamodel.collections.NodeInterfacePair) FilterResult(org.batfish.datamodel.FilterResult) RoutingProtocol(org.batfish.datamodel.RoutingProtocol) BdpAnswerElement(org.batfish.datamodel.answers.BdpAnswerElement) CommonUtil(org.batfish.common.util.CommonUtil) FlowTraceHop(org.batfish.datamodel.FlowTraceHop) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) BatfishException(org.batfish.common.BatfishException) BgpProcess(org.batfish.datamodel.BgpProcess) IpAccessList(org.batfish.datamodel.IpAccessList) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement) AbstractRoute(org.batfish.datamodel.AbstractRoute) Version(org.batfish.common.Version) FlowProcessor(org.batfish.common.plugin.FlowProcessor) Configuration(org.batfish.datamodel.Configuration) LineAction(org.batfish.datamodel.LineAction) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) Route(org.batfish.datamodel.Route) GlobalTracer(io.opentracing.util.GlobalTracer) BdpOscillationException(org.batfish.common.BdpOscillationException) TreeMap(java.util.TreeMap) ActiveSpan(io.opentracing.ActiveSpan) Collections(java.util.Collections) Prefix(org.batfish.datamodel.Prefix) BatfishException(org.batfish.common.BatfishException) Ip(org.batfish.datamodel.Ip) RouteBuilder(org.batfish.datamodel.RouteBuilder) Flow(org.batfish.datamodel.Flow)

Example 2 with SourceNat

use of org.batfish.datamodel.SourceNat in project batfish by batfish.

the class CiscoConfiguration method processSourceNat.

/**
 * Processes a {@link CiscoSourceNat} rule. This function performs two actions:
 *
 * <p>1. Record references to ACLs and NAT pools by the various parsed {@link CiscoSourceNat}
 * objects.
 *
 * <p>2. Convert to vendor-independent {@link SourceNat} objects if valid, aka, no undefined ACL
 * and valid output configuration.
 *
 * <p>Returns the vendor-independeng {@link SourceNat}, or {@code null} if the source NAT rule is
 * invalid.
 */
@Nullable
SourceNat processSourceNat(CiscoSourceNat nat, Interface iface, Map<String, IpAccessList> ipAccessLists) {
    String sourceNatAclName = nat.getAclName();
    if (sourceNatAclName == null) {
        // Source NAT rules must have an ACL; this rule is invalid.
        return null;
    }
    SourceNat convertedNat = new SourceNat();
    /* source nat acl */
    IpAccessList sourceNatAcl = ipAccessLists.get(sourceNatAclName);
    int sourceNatAclLine = nat.getAclNameLine();
    if (sourceNatAcl == null) {
        undefined(CiscoStructureType.IP_ACCESS_LIST, sourceNatAclName, CiscoStructureUsage.IP_NAT_SOURCE_ACCESS_LIST, sourceNatAclLine);
    } else {
        convertedNat.setAcl(sourceNatAcl);
        String msg = "source nat acl for interface: " + iface.getName();
        ExtendedAccessList sourceNatExtendedAccessList = _extendedAccessLists.get(sourceNatAclName);
        if (sourceNatExtendedAccessList != null) {
            sourceNatExtendedAccessList.getReferers().put(iface, msg);
        }
        StandardAccessList sourceNatStandardAccessList = _standardAccessLists.get(sourceNatAclName);
        if (sourceNatStandardAccessList != null) {
            sourceNatStandardAccessList.getReferers().put(iface, msg);
        }
    }
    /* source nat pool */
    String sourceNatPoolName = nat.getNatPool();
    if (sourceNatPoolName != null) {
        int sourceNatPoolLine = nat.getNatPoolLine();
        NatPool sourceNatPool = _natPools.get(sourceNatPoolName);
        if (sourceNatPool != null) {
            sourceNatPool.getReferers().put(iface, "source nat pool for interface: " + iface.getName());
            Ip firstIp = sourceNatPool.getFirst();
            if (firstIp != null) {
                Ip lastIp = sourceNatPool.getLast();
                convertedNat.setPoolIpFirst(firstIp);
                convertedNat.setPoolIpLast(lastIp);
            }
        } else {
            undefined(CiscoStructureType.NAT_POOL, sourceNatPoolName, CiscoStructureUsage.IP_NAT_SOURCE_POOL, sourceNatPoolLine);
        }
    }
    // The source NAT rule is valid iff it has an ACL and a pool of IPs to NAT into.
    if (convertedNat.getAcl() != null && convertedNat.getPoolIpFirst() != null) {
        return convertedNat;
    } else {
        return null;
    }
}
Also used : SourceNat(org.batfish.datamodel.SourceNat) Ip(org.batfish.datamodel.Ip) IpAccessList(org.batfish.datamodel.IpAccessList) Nullable(javax.annotation.Nullable)

Example 3 with SourceNat

use of org.batfish.datamodel.SourceNat in project batfish by batfish.

the class BdpDataPlanePluginTest method testApplySourceNatSingleAclMatch.

@Test
public void testApplySourceNatSingleAclMatch() {
    Flow flow = makeFlow();
    SourceNat nat = new SourceNat();
    nat.setAcl(makeAcl("accept", LineAction.ACCEPT));
    nat.setPoolIpFirst(new Ip("4.5.6.7"));
    Flow transformed = BdpEngine.applySourceNat(flow, singletonList(nat));
    assertThat(transformed.getSrcIp(), equalTo(new Ip("4.5.6.7")));
}
Also used : SourceNat(org.batfish.datamodel.SourceNat) Ip(org.batfish.datamodel.Ip) Flow(org.batfish.datamodel.Flow) Test(org.junit.Test)

Example 4 with SourceNat

use of org.batfish.datamodel.SourceNat in project batfish by batfish.

the class BdpDataPlanePluginTest method testApplySourceNatLateMatchWins.

@Test
public void testApplySourceNatLateMatchWins() {
    Flow flow = makeFlow();
    SourceNat nat = new SourceNat();
    nat.setAcl(makeAcl("rejectAll", LineAction.REJECT));
    nat.setPoolIpFirst(new Ip("4.5.6.7"));
    SourceNat secondNat = new SourceNat();
    secondNat.setAcl(makeAcl("acceptAnyway", LineAction.ACCEPT));
    secondNat.setPoolIpFirst(new Ip("4.5.6.8"));
    Flow transformed = BdpEngine.applySourceNat(flow, Lists.newArrayList(nat, secondNat));
    assertThat(transformed.getSrcIp(), equalTo(new Ip("4.5.6.8")));
}
Also used : SourceNat(org.batfish.datamodel.SourceNat) Ip(org.batfish.datamodel.Ip) Flow(org.batfish.datamodel.Flow) Test(org.junit.Test)

Example 5 with SourceNat

use of org.batfish.datamodel.SourceNat in project batfish by batfish.

the class BdpDataPlanePluginTest method testApplySourceNatInvalidAclThrows.

@Test
public void testApplySourceNatInvalidAclThrows() {
    Flow flow = makeFlow();
    SourceNat nat = new SourceNat();
    nat.setAcl(makeAcl("matchAll", LineAction.ACCEPT));
    _thrown.expect(BatfishException.class);
    _thrown.expectMessage("missing NAT address or pool");
    BdpEngine.applySourceNat(flow, singletonList(nat));
}
Also used : SourceNat(org.batfish.datamodel.SourceNat) Flow(org.batfish.datamodel.Flow) Test(org.junit.Test)

Aggregations

SourceNat (org.batfish.datamodel.SourceNat)13 Ip (org.batfish.datamodel.Ip)11 Test (org.junit.Test)9 Flow (org.batfish.datamodel.Flow)6 Interface (org.batfish.datamodel.Interface)6 IpAccessList (org.batfish.datamodel.IpAccessList)6 Configuration (org.batfish.datamodel.Configuration)5 Edge (org.batfish.datamodel.Edge)4 Topology (org.batfish.datamodel.Topology)4 IpWildcard (org.batfish.datamodel.IpWildcard)3 Vrf (org.batfish.datamodel.Vrf)3 Nullable (javax.annotation.Nullable)2 IpAccessListLine (org.batfish.datamodel.IpAccessListLine)2 HeaderSpaceMatchExpr (org.batfish.z3.expr.HeaderSpaceMatchExpr)2 SynthesizerInputMatchers.hasArpTrueEdge (org.batfish.z3.matchers.SynthesizerInputMatchers.hasArpTrueEdge)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSortedSet (com.google.common.collect.ImmutableSortedSet)1 ActiveSpan (io.opentracing.ActiveSpan)1 GlobalTracer (io.opentracing.util.GlobalTracer)1 ArrayList (java.util.ArrayList)1