package org.batfish.grammar; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.batfish.datamodel.ConfigurationFormat; public final class VendorConfigurationFormatDetector { public static final String BATFISH_FLATTENED_JUNIPER_HEADER = "####BATFISH FLATTENED JUNIPER CONFIG####\n"; public static final String BATFISH_FLATTENED_VYOS_HEADER = "####BATFISH FLATTENED VYOS CONFIG####\n"; public static ConfigurationFormat identifyConfigurationFormat( String fileText) { return new VendorConfigurationFormatDetector(fileText) .identifyConfigurationFormat(); } private String _fileText; private char _firstChar; private boolean _notJuniper; private VendorConfigurationFormatDetector(String fileText) { _fileText = fileText; } private void blacklist() { Matcher bannerMatcher = Pattern.compile("(?m)^banner ") .matcher(_fileText); if (bannerMatcher.find()) { _notJuniper = true; } } private ConfigurationFormat checkAlcatelAos() { Matcher alcatelAosMatcher = Pattern.compile("(?m)^system name") .matcher(_fileText); if (alcatelAosMatcher.find()) { return ConfigurationFormat.ALCATEL_AOS; } return null; } private ConfigurationFormat checkArista() { Matcher aristaMatcher = Pattern .compile("(?m)^.*boot system flash.*\\.swi").matcher(_fileText); if (aristaMatcher.find()) { return ConfigurationFormat.ARISTA; } return null; } private ConfigurationFormat checkBlade() { Matcher bladeNetworkMatcher = Pattern.compile("(?m)^switch-type") .matcher(_fileText); if (bladeNetworkMatcher.find()) { return ConfigurationFormat.BLADENETWORK; } return null; } private ConfigurationFormat checkCisco() { Matcher ciscoLike = Pattern .compile("(?m)(^boot system flash.*$)|(^interface .*$)") .matcher(_fileText); Matcher ciscoStyleAcl = Pattern.compile("(?m)(^(ip )?access-list.*$)") .matcher(_fileText); Matcher nexusCommitLine = Pattern.compile("(?m)^ *commit *$") .matcher(_fileText); Matcher neighborActivateMatcher = Pattern .compile("(?m)^ *neighbor.*activate$").matcher(_fileText); Matcher neighborPeerGroupMatcher = Pattern .compile("(?m)^ *neighbor.*peer-group$").matcher(_fileText); if (ciscoLike.find() || _firstChar == '!' || ciscoStyleAcl.find()) { if (_fileText.contains("exit-address-family") || neighborActivateMatcher.find() || neighborPeerGroupMatcher.find()) { return ConfigurationFormat.CISCO_IOS; } else { return ConfigurationFormat.CISCO_NX; } } else if (nexusCommitLine.find()) { return ConfigurationFormat.CISCO_NX; } return null; } private ConfigurationFormat checkCiscoXr() { if (_fileText.contains("IOS XR")) { return ConfigurationFormat.CISCO_IOS_XR; } return null; } private ConfigurationFormat checkEmpty() { String trimmedText = _fileText.trim(); if (trimmedText.length() == 0) { return ConfigurationFormat.EMPTY; } _firstChar = trimmedText.charAt(0); return null; } private ConfigurationFormat checkF5() { Matcher configurationHostname = Pattern.compile("(?m)^tmsh .*$") .matcher(_fileText); if (configurationHostname.find()) { return ConfigurationFormat.F5; } return null; } private ConfigurationFormat checkFlatVyos() { if (_fileText.contains("set system config-management commit-revisions")) { return ConfigurationFormat.FLAT_VYOS; } return null; } private ConfigurationFormat checkIpTables() { if (_fileText.contains("INPUT") && _fileText.contains("OUTPUT") && _fileText.contains("FORWARD")) { return ConfigurationFormat.IPTABLES; } return null; } private ConfigurationFormat checkJuniper() { if (_notJuniper) { return null; } Matcher setMatcher = Pattern.compile("(?m)^set ").matcher(_fileText); Matcher flattenedJuniperMatcher = Pattern .compile(Pattern.quote(BATFISH_FLATTENED_JUNIPER_HEADER)) .matcher(_fileText); Matcher flatJuniperHostnameDeclarationMatcher = Pattern .compile("(?m)^set (groups [^ ][^ ]* )?system host-name ") .matcher(_fileText); Matcher juniperAclMatcher = Pattern.compile("(?m)^firewall *\\{") .matcher(_fileText); Matcher juniperPolicyOptionsMatcher = Pattern .compile("(?m)^policy-options *\\{").matcher(_fileText); Matcher juniperSnmpMatcher = Pattern.compile("(?m)^snmp *\\{") .matcher(_fileText); if (_fileText.contains("set hostname")) { return ConfigurationFormat.JUNIPER_SWITCH; } else if (flattenedJuniperMatcher.find(0) || flatJuniperHostnameDeclarationMatcher.find(0) || (_fileText.contains("apply-groups") && setMatcher.find(0))) { return ConfigurationFormat.FLAT_JUNIPER; } else if (_firstChar == '#' || (_fileText.contains("version") && _fileText.contains("system") && _fileText.contains("{") && _fileText.contains("}") && _fileText.contains("host-name") && _fileText.contains("interfaces")) || juniperAclMatcher.find() || juniperPolicyOptionsMatcher.find() || juniperSnmpMatcher.find()) { return ConfigurationFormat.JUNIPER; } return null; } private ConfigurationFormat checkMrv() { if (_fileText.contains("System.SystemName")) { return ConfigurationFormat.MRV; } return null; } private ConfigurationFormat checkMrvCommands() { Matcher configurationHostname = Pattern .compile("(?m)^configuration hostname .*$").matcher(_fileText); if (configurationHostname.find()) { return ConfigurationFormat.MRV_COMMANDS; } return null; } private ConfigurationFormat checkMss() { Matcher mssMatcher = Pattern.compile("(?m)^set system name") .matcher(_fileText); if (mssMatcher.find()) { return ConfigurationFormat.MSS; } return null; } private ConfigurationFormat checkRancid() { Matcher rancidCisco = Pattern.compile("(?m)^!RANCID-CONTENT-TYPE: cisco$") .matcher(_fileText); Matcher rancidCiscoNx = Pattern .compile("(?m)^!RANCID-CONTENT-TYPE: cisco-nx$").matcher(_fileText); Matcher rancidForce10 = Pattern .compile("(?m)^!RANCID-CONTENT-TYPE: force10$").matcher(_fileText); Matcher rancidFoundry = Pattern .compile("(?m)^!RANCID-CONTENT-TYPE: foundry$").matcher(_fileText); Matcher rancidJuniper = Pattern .compile("(?m)^!RANCID-CONTENT-TYPE: juniper$").matcher(_fileText); Matcher rancidMrv = Pattern.compile("(?m)^!RANCID-CONTENT-TYPE: mrv$") .matcher(_fileText); if (rancidCisco.find()) { return checkCisco(); // unfortunately, old RANCID cannot distinguish // subtypes } else if (rancidCiscoNx.find()) { return ConfigurationFormat.CISCO_NX; } else if (rancidForce10.find()) { return ConfigurationFormat.FORCE10; } else if (rancidFoundry.find()) { return ConfigurationFormat.FOUNDRY; } else if (rancidJuniper.find()) { return checkJuniper(); } else if (rancidMrv.find()) { return ConfigurationFormat.MRV; } return null; } private ConfigurationFormat checkVxWorks() { if (_firstChar == '!' && _fileText.contains("set prompt")) { return ConfigurationFormat.VXWORKS; } return null; } private ConfigurationFormat checkVyos() { if (_fileText.contains("system") && _fileText.contains("{") && _fileText.contains("}") && _fileText.contains("config-management") && _fileText.contains("commit-revisions")) { return ConfigurationFormat.VYOS; } return null; } private ConfigurationFormat identifyConfigurationFormat() { ConfigurationFormat format; format = checkEmpty(); if (format != null) { return format; } format = checkRancid(); if (format != null) { return format; } blacklist(); format = checkF5(); if (format != null) { return format; } format = checkCiscoXr(); if (format != null) { return format; } format = checkFlatVyos(); if (format != null) { return format; } format = checkIpTables(); if (format != null) { return format; } format = checkMrv(); if (format != null) { return format; } format = checkMrvCommands(); if (format != null) { return format; } format = checkVyos(); if (format != null) { return format; } format = checkArista(); if (format != null) { return format; } format = checkBlade(); if (format != null) { return format; } format = checkVxWorks(); if (format != null) { return format; } format = checkJuniper(); if (format != null) { return format; } format = checkAlcatelAos(); if (format != null) { return format; } format = checkMss(); if (format != null) { return format; } format = checkCisco(); if (format != null) { return format; } return ConfigurationFormat.UNKNOWN; } }