/* * Copyright 2016 christopher.metter. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.uniwuerzburg.info3.ofcprobe.vswitch.trafficgen.arping; import java.util.ArrayList; import java.util.List; import org.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.uniwuerzburg.info3.ofcprobe.util.AddressPositions; import de.uniwuerzburg.info3.ofcprobe.util.Util; import de.uniwuerzburg.info3.ofcprobe.vswitch.main.config.Config; import de.uniwuerzburg.info3.ofcprobe.vswitch.main.config.HostMapper; import de.uniwuerzburg.info3.ofcprobe.vswitch.trafficgen.PayLoadGen; import de.uniwuerzburg.info3.ofcprobe.vswitch.connection.IOFConnection; /** * This Class is handling the generation of ARPs. Currently, every "HOST" * generates an ARP-Request for every "HOST" in the Topology. Even for the ones * on the same ofSwitch! * * @author Christopher Metter(christopher.metter@informatik.uni-wuerzburg.de) * */ public class ARPManager { /** * Logger */ private static final Logger logger = LoggerFactory.getLogger(ARPManager.class); /** * Here to save the world. */ private final byte[] arpMaster; /** * The Hostmapper */ private HostMapper hostMapper; /** * The Config */ private Config config; private PayLoadGen payloadGen; /** * Constructor, initializes the Generators */ public ARPManager(Config config, List<IOFConnection> ofSwitches) { this.config = config; this.hostMapper = new HostMapper(config, ofSwitches); this.arpMaster = preGenerateArp(); this.config.getTopology().setHasHostMapping(true); this.config.getTopology().setHostMapper(this.hostMapper); this.payloadGen = new PayLoadGen(config); logger.trace("ARPStuff has been initialized!"); } /** * Generates ARP-Requests for every "HOST" on freePorts of "ofSwitch" for * every possible Target-"Host" in the Topology * * @param ofSwitch * @return List of ARP-Requests */ public List<ArpPacket> getArpsForIOFConnection(IOFConnection ofSwitch) { List<ArpPacket> arps = new ArrayList<>(); List<Short> freePorts = this.config.getTopology().getFreePorts(ofSwitch.getDpid(), -1); for (short port : freePorts) { Device device = new Device(ofSwitch, port); String srcMac = this.hostMapper.getMacToDevice(device); String srcIP = this.hostMapper.getIpToDevice(device); if (srcMac == null || srcIP == null) { continue; } List<String> targetIPs = this.hostMapper.getTargetsForIP(srcIP, Integer.MAX_VALUE); for (String targetIP : targetIPs) { logger.trace("Generating ARP for targetIP={} from sourceIP={}", targetIP, srcIP); byte[] payload = generateARP(srcMac, srcIP, targetIP); ArpPacket arp = new ArpPacket(port, payload); arps.add(arp); } } if (logger.isTraceEnabled()) { for (int i = 0; i < arps.size(); i++) { logger.trace("{}(allarps) i={} targetIP:{} sourceIP: {}", ofSwitch.toString(), i, arps.get(i).IPDSTtoString(), arps.get(i).IPSRCtoString()); } } return arps; } public List<TCPPacket> getTCPSynsForIOFConnection(IOFConnection ofSwitch) { List<TCPPacket> tcpSyns = new ArrayList<>(); List<Short> freePorts = this.config.getTopology().getFreePorts(ofSwitch.getDpid(), -1); for (short port : freePorts) { Device device = new Device(ofSwitch, port); String srcMac = this.hostMapper.getMacToDevice(device); String srcIP = this.hostMapper.getIpToDevice(device); if (srcMac == null || srcIP == null) { continue; } List<String> targetIPs = this.hostMapper.getTargetsForIP(srcIP, config.getTrafficGenConfig().getFillThreshold()); for (String targetIP : targetIPs) { logger.trace("Generating TCPSYN for targetIP={} from sourceIP={}", targetIP, srcIP); String targetMac = this.hostMapper.getMacToIp(targetIP); byte[] payload = this.payloadGen.generateCustomTCPSynfromStrings(srcMac, targetMac, srcIP, targetIP); TCPPacket tcpSyn = new TCPPacket(port, payload); tcpSyns.add(tcpSyn); } } if (logger.isTraceEnabled()) { for (int i = 0; i < tcpSyns.size(); i++) { logger.trace("{}(alltcpsyns) i={} targetIP:{} sourceIP: {}", ofSwitch.toString(), i, tcpSyns.get(i).IPDSTtoString(), tcpSyns.get(i).IPSRCtoString()); } } return tcpSyns; } /** * Generates an ARP-Request with the provided Addresses * * @param srcMac Source MAC * @param srcIP Source IP * @param targetIP Target IP * @return ARP with the provided Addresses */ private byte[] generateARP(String srcMac, String srcIP, String targetIP) { byte[] arp = this.arpMaster; if (srcMac == null) { System.err.println("huhu"); } byte[] srcMacbytes = HexString.fromHexString(srcMac); byte[] srcIPbytes = Util.toIPv4AddressBytes(srcIP); byte[] targetIPbytes = Util.toIPv4AddressBytes(targetIP); arp = Util.insertByteArray(arp, srcMacbytes, AddressPositions.ETHER_MAC_SRC); arp = Util.insertByteArray(arp, srcMacbytes, AddressPositions.ARP_MAC_SRC); arp = Util.insertByteArray(arp, srcIPbytes, AddressPositions.ARP_IP_SRC); arp = Util.insertByteArray(arp, targetIPbytes, AddressPositions.ARP_IP_DST); return arp; } /** * Pregenerates an ARP-Request Packet. So all Fields of the Packet that are * always the same are set. * * @return a pregenarted ARP-Request */ private byte[] preGenerateArp() { byte[] packet = new byte[60]; // Inserting MAC Header Fields byte[] ethernetType = Util.toByteArray("0806"); // Type = ARP packet = Util.insertByteArray(packet, ethernetType, AddressPositions.ETHER_TYPE); byte[] macBroadcast = HexString.fromHexString("ff:ff:ff:ff:ff:ff"); byte[] macUnknow = HexString.fromHexString("00:00:00:00:00:00"); packet = Util.insertByteArray(packet, macBroadcast, AddressPositions.ETHER_MAC_DST); packet = Util.insertByteArray(packet, macUnknow, AddressPositions.ARP_MAC_DST); byte[] hardwareNprotocolTypeNhardwareNprotocolSizeNopcode = Util.toByteArray("0001080006040001"); packet = Util.insertByteArray(packet, hardwareNprotocolTypeNhardwareNprotocolSizeNopcode, 14); byte[] padding = Util.toByteArray("000000000000000000000000000000000000"); packet = Util.insertByteArray(packet, padding, AddressPositions.ARP_PADDING); logger.trace("ARP Master Data: {}", Util.asString(packet)); return packet; } }