package org.batfish.representation.host; import java.io.IOException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; import org.batfish.common.VendorConversionException; import org.batfish.common.util.BatfishObjectMapper; import org.batfish.datamodel.AbstractRoute; import org.batfish.datamodel.Configuration; import org.batfish.datamodel.ConfigurationFormat; import org.batfish.datamodel.Interface; import org.batfish.datamodel.Ip; import org.batfish.datamodel.IpAccessList; import org.batfish.datamodel.IpAccessListLine; import org.batfish.datamodel.LineAction; import org.batfish.datamodel.Prefix; import org.batfish.datamodel.StaticRoute; import org.batfish.datamodel.Vrf; import org.batfish.datamodel.collections.RoleSet; import org.batfish.common.Warnings; import org.batfish.representation.iptables.IptablesVendorConfiguration; import org.batfish.vendor.VendorConfiguration; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; public class HostConfiguration extends VendorConfiguration { private static final String FILTER_FORWARD = "filter::FORWARD"; private static final Object FILTER_INPUT = "filter::INPUT"; private static final Object FILTER_OUTPUT = "filter::OUTPUT"; private static final String HOST_INTERFACES_VAR = "hostInterfaces"; private static final String HOSTNAME_VAR = "hostname"; private static final String IPTABLES_FILE_VAR = "iptablesFile"; private static final String MANGLE_FORWARD = "mangle::FORWARD"; private static final String MANGLE_INPUT = "mangle::INPUT"; private static final String MANGLE_OUTPUT = "mangle::OUTPUT"; private static final String MANGLE_POSTROUTING = "mangle::POSTROUTING"; private static final String MANGLE_PREROUTING = "mangle::PREROUTING"; private static final String NAT_OUTPUT = "nat::OUTPUT"; private static final String NAT_PREROUTING = "nat::PREROUTING"; private static final String RAW_OUTPUT = "raw::OUTPUT"; private static final String RAW_PREROUTING = "raw::PREROUTING"; /** * */ private static final long serialVersionUID = 1L; public static HostConfiguration fromJson(String text, Warnings warnings) throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new BatfishObjectMapper(); HostConfiguration hostConfiguration = mapper.readValue(text, HostConfiguration.class); hostConfiguration._w = warnings; return hostConfiguration; } private Configuration _c; protected final Map<String, HostInterface> _hostInterfaces; private String _hostname; private String _iptablesFile; private IptablesVendorConfiguration _iptablesVendorConfig; protected final RoleSet _roles = new RoleSet(); private final Set<HostStaticRoute> _staticRoutes; // @JsonCreator // public HostConfiguration(@JsonProperty(HOSTNAME_VAR) String name) { // _hostname = name; // _interfaces = new HashMap<String, Interface>(); // _roles = new RoleSet(); // } private transient Set<String> _unimplementedFeatures; public HostConfiguration() { _hostInterfaces = new TreeMap<>(); _staticRoutes = new TreeSet<>(); } @JsonProperty(HOST_INTERFACES_VAR) public Map<String, HostInterface> getHostInterfaces() { return _hostInterfaces; } @JsonProperty(HOSTNAME_VAR) @Override public String getHostname() { return _hostname; } public Map<String, Interface> getInterfaces() { throw new UnsupportedOperationException( "no implementation for generated method"); } @JsonProperty(IPTABLES_FILE_VAR) public String getIptablesFile() { return _iptablesFile; } @JsonIgnore @Override public RoleSet getRoles() { return _roles; } @JsonIgnore @Override public Set<String> getUnimplementedFeatures() { return _unimplementedFeatures; } @Override public void setHostname(String hostname) { _hostname = hostname; } public void setIptablesConfig(IptablesVendorConfiguration config) { _iptablesVendorConfig = config; } public void setIptablesFile(String file) { _iptablesFile = file; } @Override public void setRoles(RoleSet roles) { _roles.addAll(roles); } @JsonIgnore @Override public void setVendor(ConfigurationFormat format) { throw new UnsupportedOperationException( "Cannot set vendor for host configuration"); } private boolean simple() { String[] aclsToCheck = new String[] { RAW_PREROUTING, MANGLE_PREROUTING, NAT_PREROUTING, MANGLE_INPUT, RAW_OUTPUT, MANGLE_OUTPUT, NAT_OUTPUT, MANGLE_FORWARD, FILTER_FORWARD, MANGLE_POSTROUTING }; for (String aclName : aclsToCheck) { IpAccessList acl = _c.getIpAccessLists().get(aclName); if (acl != null) { for (IpAccessListLine line : acl.getLines()) { if (line.getAction() == LineAction.REJECT) { return false; } if (!line.unrestricted()) { return false; } } } } return true; } @Override public Configuration toVendorIndependentConfiguration() throws VendorConversionException { String hostname = getHostname(); _c = new Configuration(hostname); _c.setConfigurationFormat(ConfigurationFormat.HOST); _c.setDefaultCrossZoneAction(LineAction.ACCEPT); _c.setDefaultInboundAction(LineAction.ACCEPT); _c.setRoles(_roles); _c.getVrfs().put(Configuration.DEFAULT_VRF_NAME, new Vrf(Configuration.DEFAULT_VRF_NAME)); // add interfaces _hostInterfaces.forEach((iname, hostInterface) -> { org.batfish.datamodel.Interface newIface = hostInterface .toInterface(_c, _w); _c.getInterfaces().put(iname, newIface); _c.getDefaultVrf().getInterfaces().put(iname, newIface); }); // add iptables if (_iptablesVendorConfig != null) { _iptablesVendorConfig.addAsIpAccessLists(_c, _w); } // apply acls to interfaces if (simple()) { for (Interface iface : _c.getDefaultVrf().getInterfaces().values()) { iface.setIncomingFilter(_c.getIpAccessLists().get(FILTER_INPUT)); iface.setOutgoingFilter(_c.getIpAccessLists().get(FILTER_OUTPUT)); } } else { _w.unimplemented("Do not support complicated iptables rules yet"); } _c.getDefaultVrf().getStaticRoutes().addAll(_staticRoutes.stream() .map(hsr -> hsr.toStaticRoute()).collect(Collectors.toSet())); Set<StaticRoute> staticRoutes = _c.getDefaultVrf().getStaticRoutes(); for (HostInterface iface : _hostInterfaces.values()) { Ip gateway = iface.getGateway(); if (gateway != null) { StaticRoute sr = new StaticRoute(Prefix.ZERO, gateway, iface.getName(), AbstractRoute.NO_TAG); sr.setAdministrativeCost( HostStaticRoute.DEFAULT_ADMINISTRATIVE_COST); staticRoutes.add(sr); break; } } if (_staticRoutes.isEmpty() && staticRoutes.isEmpty() && !_c.getInterfaces().isEmpty()) { String ifaceName = _c.getInterfaces().values().iterator().next() .getName(); StaticRoute sr = new StaticRoute(Prefix.ZERO, null, ifaceName, AbstractRoute.NO_TAG); sr.setAdministrativeCost(HostStaticRoute.DEFAULT_ADMINISTRATIVE_COST); _c.getDefaultVrf().getStaticRoutes().add(sr); } return _c; } }