public boolean matches(Flow flow, Map<String, IpSpace> namedIpSpaces) { if (!_dscps.isEmpty() && !_dscps.contains(flow.getDscp())) { return false; if (!_notDscps.isEmpty() && _notDscps.contains(flow.getDscp())) { return false; if (_dstIps != null && !_dstIps.containsIp(flow.getDstIp(), namedIpSpaces)) { return false; if (_notDstIps != null && _notDstIps.containsIp(flow.getDstIp(), namedIpSpaces)) { return false; if (!_dstPorts.isEmpty() && !rangesContain(_dstPorts, flow.getDstPort())) { return false; if (!_notDstPorts.isEmpty() && rangesContain(_notDstPorts, flow.getDstPort())) { return false; boolean match = false; for (Protocol dstProtocol : _dstProtocols) { if (dstProtocol.getIpProtocol().equals(flow.getIpProtocol())) { match = true; Integer dstPort = dstProtocol.getPort(); if (dstPort != null && !dstPort.equals(flow.getDstPort())) { match = false; boolean match = false; for (Protocol notDstProtocol : _notDstProtocols) { if (notDstProtocol.getIpProtocol().equals(flow.getIpProtocol())) {
Set<FlowTrace> currentFlowTraces = flowTraces.computeIfAbsent(flow, f -> new TreeSet<>()); String ingressNodeName = flow.getIngressNode(); if (ingressNodeName == null) { throw new BatfishException( "Cannot construct flow trace since ingressNode is not specified"); Ip dstIp = flow.getDstIp(); if (dstIp == null) { throw new BatfishException( String ingressInterfaceName = flow.getIngressInterface(); if (ingressInterfaceName != null) { Edge edge = collectFlowTraces( ingressNodeName, firstNonNull(flow.getIngressVrf(), Configuration.DEFAULT_VRF_NAME), visitedEdges, hops,
/** * Creates a return {@link Flow} for the input {@param forwardFlow}. Swaps the source/destination * IPs/ports, and sets the ingress node/vrf/interface. */ static Flow returnFlow( Flow forwardFlow, String returnIngressNode, @Nullable String returnIngressVrf, @Nullable String returnIngressIface) { checkArgument( returnIngressVrf == null ^ returnIngressIface == null, "Either returnIngressVrf or returnIngressIface required, but not both"); return forwardFlow .toBuilder() .setDstIp(forwardFlow.getSrcIp()) .setDstPort(forwardFlow.getSrcPort()) .setSrcIp(forwardFlow.getDstIp()) .setSrcPort(forwardFlow.getDstPort()) .setIngressNode(returnIngressNode) .setIngressVrf(returnIngressVrf) .setIngressInterface(returnIngressIface) .build(); }
/** * Does a basic validation of input to {@link * TracerouteEngineImplContext#buildTracesAndReturnFlows()} * * @param configurations {@link Map} of {@link Configuration}s * @param flow {@link Flow} for which input validation is to be done */ static void validateInputs(Map<String, Configuration> configurations, Flow flow) { String ingressNodeName = flow.getIngressNode(); checkArgument( ingressNodeName != null, "Cannot construct flow trace since ingressNode is not specified"); Configuration ingressNode = configurations.get(ingressNodeName); checkArgument( ingressNode != null, "Node %s is not in the network, cannot perform traceroute", ingressNodeName); String ingressIfaceName = flow.getIngressInterface(); if (ingressIfaceName != null) { checkArgument( ingressNode.getAllInterfaces().get(ingressIfaceName) != null, "%s interface does not exist on the node %s", ingressIfaceName, ingressNodeName); } checkArgument( flow.getDstIp() != null, "Cannot construct flow trace since dstIp is not specified"); }
@Nullable private static Transformation sessionTransformation(Flow inputFlow, Flow currentFlow) { ImmutableList.Builder<TransformationStep> transformationStepsBuilder = ImmutableList.builder(); Ip origDstIp = inputFlow.getDstIp(); if (!origDstIp.equals(currentFlow.getDstIp())) { transformationStepsBuilder.add(assignSourceIp(origDstIp, origDstIp)); } Ip origSrcIp = inputFlow.getSrcIp(); if (!origSrcIp.equals(currentFlow.getSrcIp())) { transformationStepsBuilder.add(TransformationStep.assignDestinationIp(origSrcIp, origSrcIp)); } List<TransformationStep> transformationSteps = transformationStepsBuilder.build(); return transformationSteps.isEmpty() ? null : always().apply(transformationSteps).build(); }
/** Compute the differences between two flows */ public static SortedSet<FlowDiff> flowDiffs(@Nullable Flow flow1, @Nullable Flow flow2) { if (flow1 == null || flow2 == null || flow1.equals(flow2)) { return ImmutableSortedSet.of(); } checkArgument( flow1 .toBuilder() .setDstIp(flow2.getDstIp()) .setSrcIp(flow2.getSrcIp()) .build() .equals(flow2), "flowDiff only supports differences of src or dst Ip"); ImmutableSortedSet.Builder<FlowDiff> diffs = ImmutableSortedSet.naturalOrder(); if (!flow1.getDstIp().equals(flow2.getDstIp())) { diffs.add( new FlowDiff(PROP_DST_IP, flow1.getDstIp().toString(), flow2.getDstIp().toString())); } if (!flow1.getSrcIp().equals(flow2.getSrcIp())) { diffs.add( new FlowDiff(PROP_SRC_IP, flow1.getSrcIp().toString(), flow2.getSrcIp().toString())); } return diffs.build(); }
@Test public void testTestFilter() { String hostname = _config.getHostname(); Flow flow = Flow.builder().setIngressNode(hostname).setDstIp(IP2).setTag("tag").build(); assertThat( TestFiltersAnswerer.getRow(ACL, flow, _config), allOf( hasColumn(COL_ACTION, equalTo("DENY"), Schema.STRING), hasColumn(COL_FILTER_NAME, equalTo(ACL.getName()), Schema.STRING))); }
dstNatFlow = transformationResult.getOutputFlow(); steps.addAll(transformationResult.getTraceSteps()); } else if (inputFlow.getIngressVrf() != null) { .setDetail( OriginateStepDetail.builder() .setOriginatingVrf(inputFlow.getIngressVrf()) .build()) .setAction(StepAction.ORIGINATED) Ip dstIp = currentFlow.getDstIp(); vrfName = currentFlow.getIngressVrf(); } else { vrfName = currentConfiguration.getAllInterfaces().get(inputIfaceName).getVrfName(); .getOrDefault(currentFlow.getDstIp(), ImmutableMap.of()) .getOrDefault(currentConfiguration.getHostname(), ImmutableSet.of()) .contains(vrfName)) { firewallSessionInterfaceInfo.getSessionInterfaces(), match5Tuple( newTransformedFlow.getDstIp(), newTransformedFlow.getDstPort(), newTransformedFlow.getSrcIp(), newTransformedFlow.getSrcPort(), newTransformedFlow.getIpProtocol()), sessionTransformation(inputFlow, newTransformedFlow)));
@Test public void testFlowDiffs() { Ip dst1 = Ip.parse("1.1.1.1"); Ip src1 = Ip.parse("2.2.2.2"); Ip dst2 = Ip.parse("3.3.3.3"); Ip src2 = Ip.parse("4.4.4.4"); Flow orig = Flow.builder() .setIngressNode("ingressNode") .setTag("tag") .setDstIp(dst1) .setSrcIp(src1) .build(); Flow newDst = orig.toBuilder().setDstIp(dst2).build(); Flow newSrc = orig.toBuilder().setSrcIp(src2).build(); Flow newDstAndSrc = newDst.toBuilder().setSrcIp(src2).build(); assertThat(flowDiffs(null, orig), empty()); assertThat(flowDiffs(orig, null), empty()); assertThat(flowDiffs(orig, orig), empty()); FlowDiff dstDiff = new FlowDiff(PROP_DST_IP, dst1.toString(), dst2.toString()); FlowDiff srcDiff = new FlowDiff(PROP_SRC_IP, src1.toString(), src2.toString()); assertThat(flowDiffs(orig, newDst), contains(dstDiff)); assertThat(flowDiffs(orig, newSrc), contains(srcDiff)); assertThat(flowDiffs(orig, newDstAndSrc), containsInAnyOrder(dstDiff, srcDiff)); }
@Test public void testDefaultPacketLength() { Builder builder = Flow.builder().setIngressNode("node").setIngressInterface("iface").setTag("tag"); PacketHeaderConstraints phc = PacketHeaderConstraints.unconstrained(); setPacketLength(phc, builder); assertThat(builder.build().getPacketLength(), equalTo(DEFAULT_PACKET_LENGTH)); }
@Test public void testSetTcpFlags() { Builder builder = Flow.builder().setIngressNode("node").setIngressInterface("iface").setTag("tag"); PacketHeaderConstraints phc = PacketHeaderConstraints.builder() .setTcpFlags(Collections.singleton(TcpFlagsMatchConditions.ACK_TCP_FLAG)) .build(); setTcpFlags(phc, builder); assertThat(builder.build().getTcpFlagsAck(), equalTo(1)); }
@Test public void testSetFlowStates() { Builder builder = Flow.builder().setIngressNode("node").setIngressInterface("iface").setTag("tag"); PacketHeaderConstraints phc = PacketHeaderConstraints.builder() .setFlowStates(Collections.singleton(FlowState.ESTABLISHED)) .build(); setFlowStates(phc, builder); assertThat(builder.build().getState(), equalTo(FlowState.ESTABLISHED)); }
@Test public void testSetFragmentOffsets() { Builder builder = Flow.builder().setIngressNode("node").setIngressInterface("iface").setTag("tag"); PacketHeaderConstraints phc = PacketHeaderConstraints.builder() .setFragmentOffsets(IntegerSpace.of(new SubRange(2, 2))) .build(); setFragmentOffsets(phc, builder); assertThat(builder.build().getFragmentOffset(), equalTo(2)); }
@Test public void testSetEcnValue() { Builder builder = Flow.builder().setIngressNode("node").setIngressInterface("iface").setTag("tag"); PacketHeaderConstraints phc = PacketHeaderConstraints.builder().setEcns(IntegerSpace.of(1)).build(); setEcnValue(phc, builder); assertThat(builder.build().getEcn(), equalTo(1)); }
@Override protected Ip featureValueOf(Flow flow) { return flow.getDstIp(); } }
traces.computeIfAbsent(flow, k -> new ArrayList<>()); validateInputs(_configurations, flow); String ingressNodeName = flow.getIngressNode(); List<Hop> hops = new ArrayList<>(); Stack<Breadcrumb> breadcrumbs = new Stack<>(); String ingressInterfaceName = flow.getIngressInterface(); if (ingressInterfaceName != null) { TransmissionContext transmissionContext = new TransmissionContext( Maps.newHashMap(), new Node(flow.getIngressNode()), currentTraces, hops,
Flow originalFlow, Flow transformedFlow) { Ip dstIp = transformedFlow.getDstIp(); Configuration currentConfiguration = _configurations.get(currentNodeName); if (currentConfiguration == null) { String srcInterfaceName; if (hopsSoFar.isEmpty()) { vrfName = transformedFlow.getIngressVrf(); srcInterfaceName = null; } else {
@Override protected String featureValueOf(Flow flow) { return flow.getIngressInterface(); } }
@Override protected IpProtocol featureValueOf(Flow flow) { return flow.getIpProtocol(); } }