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();
}
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;
}
}
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")));
}
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")));
}
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));
}
Aggregations