use of org.onlab.packet.dhcp.DhcpOption in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method directlyConnected.
/**
* Check if the host is directly connected to the network or not.
*
* @param dhcpPayload the dhcp payload
* @return true if the host is directly connected to the network; false otherwise
*/
private boolean directlyConnected(DHCP dhcpPayload) {
// leasequery is always indirect
if (isDhcpPacketLeasequery(dhcpPayload)) {
return false;
}
DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) dhcpPayload.getOption(OptionCode_CircuitID);
// Doesn't contains relay option
if (relayAgentOption == null) {
return true;
}
// check circuit id, if circuit id is invalid, we say it is an indirect host
DhcpOption circuitIdOpt = relayAgentOption.getSubOption(CIRCUIT_ID.getValue());
try {
CircuitId.deserialize(circuitIdOpt.getData());
return true;
} catch (Exception e) {
// invalid circuit id
return false;
}
}
use of org.onlab.packet.dhcp.DhcpOption in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method getClientInterface.
/**
* Gets output interface of a dhcp packet.
* If option 82 exists in the dhcp packet and the option was sent by
* ONOS (circuit format is correct), use the connect
* point and vlan id from circuit id; otherwise, find host by destination
* address and use vlan id from sender (dhcp server).
*
* @param ethPacket the ethernet packet
* @param dhcpPayload the dhcp packet
* @return an interface represent the output port and vlan; empty value
* if the host or circuit id not found
*/
private Optional<Interface> getClientInterface(Ethernet ethPacket, DHCP dhcpPayload) {
VlanId originalPacketVlanId = VlanId.vlanId(ethPacket.getVlanID());
DhcpRelayAgentOption option = (DhcpRelayAgentOption) dhcpPayload.getOption(OptionCode_CircuitID);
DhcpOption circuitIdSubOption = option.getSubOption(CIRCUIT_ID.getValue());
try {
CircuitId circuitId = CircuitId.deserialize(circuitIdSubOption.getData());
ConnectPoint connectPoint = ConnectPoint.deviceConnectPoint(circuitId.connectPoint());
VlanId vlanId = circuitId.vlanId();
return interfaceService.getInterfacesByPort(connectPoint).stream().filter(iface -> interfaceContainsVlan(iface, vlanId)).findFirst();
} catch (IllegalArgumentException ex) {
// invalid circuit format, didn't sent by ONOS
log.debug("Invalid circuit {}, use information from dhcp payload", circuitIdSubOption.getData());
}
// Use Vlan Id from DHCP server if DHCP relay circuit id was not
// sent by ONOS or circuit Id can't be parsed
// TODO: remove relay store from this method
MacAddress dstMac = valueOf(dhcpPayload.getClientHardwareAddress());
VlanId filteredVlanId = getVlanIdFromDhcpRecord(dstMac, originalPacketVlanId);
// Get the vlan from the dhcp record
if (filteredVlanId == null) {
log.debug("not find the matching DHCP record for mac: {} and vlan: {}", dstMac, originalPacketVlanId);
return Optional.empty();
}
Optional<DhcpRecord> dhcpRecord = dhcpRelayStore.getDhcpRecord(HostId.hostId(dstMac, filteredVlanId));
ConnectPoint clientConnectPoint = dhcpRecord.map(DhcpRecord::locations).orElse(Collections.emptySet()).stream().reduce((hl1, hl2) -> {
// find latest host connect point
if (hl1 == null || hl2 == null) {
return hl1 == null ? hl2 : hl1;
}
return hl1.time() > hl2.time() ? hl1 : hl2;
}).orElse(null);
if (clientConnectPoint != null) {
return interfaceService.getInterfacesByPort(clientConnectPoint).stream().filter(iface -> interfaceContainsVlan(iface, filteredVlanId)).findFirst();
}
return Optional.empty();
}
use of org.onlab.packet.dhcp.DhcpOption in project onos by opennetworkinglab.
the class DhcpManagerTest method constructDhcpPacket.
/**
* Constructs an Ethernet packet containing a DHCP Payload.
* @param packetType DHCP Message Type
* @return Ethernet packet
*/
private Ethernet constructDhcpPacket(DHCP.MsgType packetType) {
// Ethernet Frame.
Ethernet ethReply = new Ethernet();
ethReply.setSourceMACAddress(CLIENT1_HOST.mac());
ethReply.setDestinationMACAddress(MacAddress.BROADCAST);
ethReply.setEtherType(Ethernet.TYPE_IPV4);
ethReply.setVlanID((short) 2);
// IP Packet
IPv4 ipv4Reply = new IPv4();
ipv4Reply.setSourceAddress(0);
ipv4Reply.setDestinationAddress(BROADCAST.toInt());
ipv4Reply.setTtl((byte) 127);
// UDP Datagram.
UDP udpReply = new UDP();
udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
// DHCP Payload.
DHCP dhcpReply = new DHCP();
dhcpReply.setOpCode(DHCP.OPCODE_REQUEST);
dhcpReply.setYourIPAddress(0);
dhcpReply.setServerIPAddress(0);
dhcpReply.setTransactionId(TRANSACTION_ID);
dhcpReply.setClientHardwareAddress(CLIENT1_HOST.mac().toBytes());
dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
dhcpReply.setHardwareAddressLength((byte) 6);
// DHCP Options.
DhcpOption option = new DhcpOption();
List<DhcpOption> optionList = new ArrayList<>();
// DHCP Message Type.
option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
option.setLength((byte) 1);
byte[] optionData = { (byte) packetType.getValue() };
option.setData(optionData);
optionList.add(option);
// DHCP Requested IP.
option = new DhcpOption();
option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
option.setLength((byte) 4);
optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
option.setData(optionData);
optionList.add(option);
// End Option.
option = new DhcpOption();
option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
option.setLength((byte) 1);
optionList.add(option);
dhcpReply.setOptions(optionList);
udpReply.setPayload(dhcpReply);
ipv4Reply.setPayload(udpReply);
ethReply.setPayload(ipv4Reply);
return ethReply;
}
use of org.onlab.packet.dhcp.DhcpOption in project onos by opennetworkinglab.
the class OpenstackSwitchingDhcpHandlerTest method constructDhcpPacket.
/**
* Constructs an Ethernet packet containing a DHCP payload.
*
* @param msgType DHCP message type
* @return Ethernet packet
*/
private Ethernet constructDhcpPacket(DHCP.MsgType msgType) {
// Ethernet frame
Ethernet ethFrame = new Ethernet();
ethFrame.setSourceMACAddress(CLIENT_HOST.mac());
ethFrame.setDestinationMACAddress(MacAddress.BROADCAST);
ethFrame.setEtherType(Ethernet.TYPE_IPV4);
ethFrame.setVlanID((short) 2);
// IP packet
IPv4 ipv4Pkt = new IPv4();
ipv4Pkt.setSourceAddress(0);
ipv4Pkt.setDestinationAddress(BROADCAST.toInt());
ipv4Pkt.setTtl((byte) 127);
// UDP datagram
UDP udpDatagram = new UDP();
udpDatagram.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
udpDatagram.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
// DHCP payload
DHCP dhcp = new DHCP();
dhcp.setOpCode(DHCP.OPCODE_REQUEST);
dhcp.setYourIPAddress(0);
dhcp.setServerIPAddress(0);
dhcp.setTransactionId(TRANSACTION_ID);
dhcp.setClientHardwareAddress(CLIENT_HOST.mac().toBytes());
dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
dhcp.setHardwareAddressLength((byte) 6);
// DHCP options start...
DhcpOption option = new DhcpOption();
List<DhcpOption> optionList = new ArrayList<>();
// DHCP message type
option.setCode(OptionCode_MessageType.getValue());
option.setLength((byte) 1);
byte[] optionData = { (byte) msgType.getValue() };
option.setData(optionData);
optionList.add(option);
// DHCP requested IP address
option = new DhcpOption();
option.setCode(OptionCode_RequestedIP.getValue());
option.setLength((byte) 4);
optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
option.setData(optionData);
optionList.add(option);
// DHCP domain server
Subnet subnet = dhcpHandler.osNetworkService.subnet("subnet");
option = new DhcpOption();
option.setCode(OptionCode_DomainServer.getValue());
option.setLength((byte) 8);
ByteBuffer dnsByteBuf = ByteBuffer.allocate(8);
dnsByteBuf.put(DEFAULT_PRIMARY_DNS.toOctets());
dnsByteBuf.put(DEFAULT_SECONDARY_DNS.toOctets());
option.setData(dnsByteBuf.array());
optionList.add(option);
// MTU
option = new DhcpOption();
option.setCode(DHCP_OPTION_MTU);
option.setLength((byte) 2);
option.setData(ByteBuffer.allocate(2).putShort(MTU).array());
optionList.add(option);
// classless static route
option = new DhcpOption();
option.setCode(OptionCode_Classless_Static_Route.getValue());
option.setLength((byte) HOST_ROUTES_SIZE);
ByteBuffer hostRouteByteBuf = ByteBuffer.allocate(HOST_ROUTES_SIZE);
subnet.getHostRoutes().forEach(h -> {
IpPrefix ipPrefix = IpPrefix.valueOf(h.getDestination());
hostRouteByteBuf.put(bytesDestinationDescriptor(ipPrefix));
hostRouteByteBuf.put(Ip4Address.valueOf(h.getNexthop()).toOctets());
});
option.setData(hostRouteByteBuf.array());
optionList.add(option);
// default router address setup
option = new DhcpOption();
option.setCode(OptionCode_RouterAddress.getValue());
option.setLength((byte) 4);
option.setData(Ip4Address.valueOf(subnet.getGateway()).toOctets());
optionList.add(option);
// DHCP options end...
option = new DhcpOption();
option.setCode(OptionCode_END.getValue());
option.setLength((byte) 1);
optionList.add(option);
dhcp.setOptions(optionList);
udpDatagram.setPayload(dhcp);
ipv4Pkt.setPayload(udpDatagram);
ethFrame.setPayload(ipv4Pkt);
return ethFrame;
}
use of org.onlab.packet.dhcp.DhcpOption in project onos by opennetworkinglab.
the class DHCP method serialize.
@Override
public byte[] serialize() {
// not guaranteed to retain length/exact format
this.resetChecksum();
// minimum size 240 including magic cookie, options generally padded to
// 300
int optionsLength = 0;
for (final DhcpOption option : this.options) {
if (option.getCode() == DHCPOptionCode.OptionCode_Pad.getValue() || option.getCode() == DHCPOptionCode.OptionCode_END.getValue()) {
optionsLength += 1;
} else {
optionsLength += 2 + (UNSIGNED_BYTE_MASK & option.getLength());
}
}
int optionsPadLength = 0;
if (optionsLength < BASE_OPTION_LEN) {
optionsPadLength = BASE_OPTION_LEN - optionsLength;
}
final byte[] data = new byte[MIN_DHCP_LEN + optionsLength + optionsPadLength];
final ByteBuffer bb = ByteBuffer.wrap(data);
bb.put(this.opCode);
bb.put(this.hardwareType);
bb.put(this.hardwareAddressLength);
bb.put(this.hops);
bb.putInt(this.transactionId);
bb.putShort(this.seconds);
bb.putShort(this.flags);
bb.putInt(this.clientIPAddress);
bb.putInt(this.yourIPAddress);
bb.putInt(this.serverIPAddress);
bb.putInt(this.gatewayIPAddress);
checkArgument(this.clientHardwareAddress.length <= BASE_HW_ADDR_LEN, "Hardware address is too long (%s bytes)", this.clientHardwareAddress.length);
bb.put(this.clientHardwareAddress);
if (this.clientHardwareAddress.length < BASE_HW_ADDR_LEN) {
for (int i = 0; i < BASE_HW_ADDR_LEN - this.clientHardwareAddress.length; ++i) {
bb.put(PAD_BYTE);
}
}
this.writeString(this.serverName, bb, BASE_SERVER_NAME_LEN);
this.writeString(this.bootFileName, bb, BASE_BOOT_FILE_NAME_LEN);
// magic cookie
bb.putInt(MAGIC_COOKIE);
for (final DhcpOption option : this.options) {
bb.put(option.serialize());
}
// assume the rest is padded out with zeroes
return data;
}
Aggregations