[CORD-2097] DHCP V6 Relay incorrect src ip and src mac set toward server
Change-Id: Ib2bd641d5be37763e83e5a056e50125c4e7e4f84
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
index 9dabfd9..754d70d 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
@@ -688,73 +688,85 @@
*/
private InternalPacket processDhcp6PacketFromClient(PacketContext context,
Ethernet clientPacket, Set<Interface> clientInterfaces) {
- Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
- MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
- if (relayAgentIp == null || relayAgentMac == null) {
- log.warn("Missing DHCP relay agent interface Ipv6 addr config for "
- + "packet from client on port: {}. Aborting packet processing",
- clientInterfaces.iterator().next().connectPoint());
- return null;
- }
+ Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
+ MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
+ if (relayAgentIp == null || relayAgentMac == null) {
+ log.warn("Missing DHCP relay agent interface Ipv6 addr config for "
+ + "packet from client on port: {}. Aborting packet processing",
+ clientInterfaces.iterator().next().connectPoint());
+ return null;
+ }
- // get dhcp6 header.
+ // get dhcp6 header.
- IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
- UDP clientUdp = (UDP) clientIpv6.getPayload();
- DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
+ IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
+ UDP clientUdp = (UDP) clientIpv6.getPayload();
+ DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
- boolean directConnFlag = directlyConnected(clientDhcp6);
+ boolean directConnFlag = directlyConnected(clientDhcp6);
+ Interface serverInterface = directConnFlag ? getServerInterface() : getIndirectServerInterface();
+ if (serverInterface == null) {
+ log.warn("Can't get {} server interface, ignore", directConnFlag ? "direct" : "indirect");
+ return null;
+ }
+ Ip6Address ipFacingServer = getFirstIpFromInterface(serverInterface);
+ MacAddress macFacingServer = serverInterface.mac();
+ if (ipFacingServer == null || macFacingServer == null) {
+ log.warn("No IP v6 address for server Interface {}", serverInterface);
+ return null;
+ }
- Ethernet etherReply = clientPacket.duplicate();
- etherReply.setSourceMACAddress(relayAgentMac);
+ Ethernet etherReply = clientPacket.duplicate();
+ etherReply.setSourceMACAddress(macFacingServer);
- if ((directConnFlag && this.dhcpConnectMac == null) ||
- !directConnFlag && this.indirectDhcpConnectMac == null && this.dhcpConnectMac == null) {
- log.warn("Packet received from {} connected client.", directConnFlag ? "directly" : "indirectly");
- log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
- + "packet processing from client on port: {}",
- (this.dhcpGatewayIp == null) ? "server IP " + this.dhcpServerIp
- : "gateway IP " + this.dhcpGatewayIp,
- clientInterfaces.iterator().next().connectPoint());
+ if ((directConnFlag && this.dhcpConnectMac == null) ||
+ !directConnFlag && this.indirectDhcpConnectMac == null && this.dhcpConnectMac == null) {
+ log.warn("Packet received from {} connected client.", directConnFlag ? "directly" : "indirectly");
+ log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
+ + "packet processing from client on port: {}",
+ (this.dhcpGatewayIp == null) ? "server IP " + this.dhcpServerIp
+ : "gateway IP " + this.dhcpGatewayIp,
+ clientInterfaces.iterator().next().connectPoint());
- return null;
- }
+ return null;
+ }
- if (this.dhcpServerConnectPoint == null) {
- log.warn("DHCP6 server connection point direct {} directConn {} indirectConn {} is not set up yet",
- directConnFlag, this.dhcpServerConnectPoint, this.indirectDhcpServerConnectPoint);
- return null;
- }
+ if (this.dhcpServerConnectPoint == null) {
+ log.warn("DHCP6 server connection point direct {} directConn {} indirectConn {} is not set up yet",
+ directConnFlag, this.dhcpServerConnectPoint, this.indirectDhcpServerConnectPoint);
+ return null;
+ }
- etherReply.setDestinationMACAddress(this.dhcpConnectMac);
- etherReply.setVlanID(this.dhcpConnectVlan.toShort());
+ etherReply.setDestinationMACAddress(this.dhcpConnectMac);
+ etherReply.setVlanID(this.dhcpConnectVlan.toShort());
- IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
- byte[] peerAddress = clientIpv6.getSourceAddress();
- ipv6Packet.setSourceAddress(relayAgentIp.toOctets());
- ipv6Packet.setDestinationAddress(this.dhcpServerIp.toOctets());
+ IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
+ byte[] peerAddress = clientIpv6.getSourceAddress();
+ ipv6Packet.setSourceAddress(ipFacingServer.toOctets());
- UDP udpPacket = (UDP) ipv6Packet.getPayload();
- udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
- DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
- byte[] dhcp6PacketByte = dhcp6Packet.serialize();
+ ipv6Packet.setDestinationAddress(this.dhcpServerIp.toOctets());
- // notify onos and quagga to release PD
- //releasePD(dhcp6Packet);
- ConnectPoint clientConnectionPoint = context.inPacket().receivedFrom();
- VlanId vlanIdInUse = VlanId.vlanId(clientPacket.getVlanID());
- Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
+ UDP udpPacket = (UDP) ipv6Packet.getPayload();
+ udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
+ byte[] dhcp6PacketByte = dhcp6Packet.serialize();
+
+ // notify onos and quagga to release PD
+ //releasePD(dhcp6Packet);
+ ConnectPoint clientConnectionPoint = context.inPacket().receivedFrom();
+ VlanId vlanIdInUse = VlanId.vlanId(clientPacket.getVlanID());
+ Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
.stream()
.filter(iface -> interfaceContainsVlan(iface, vlanIdInUse))
.findFirst()
.orElse(null);
- removeHostOrRoute(directConnFlag, dhcp6Packet, clientPacket, clientIpv6, clientInterface);
+ removeHostOrRoute(directConnFlag, dhcp6Packet, clientPacket, clientIpv6, clientInterface);
- DHCP6 dhcp6Relay = new DHCP6();
- dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
- // link address: server uses the address to identify the link on which the client
- // is located.
+ DHCP6 dhcp6Relay = new DHCP6();
+ dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
+ // link address: server uses the address to identify the link on which the client
+ // is located.
if (directConnFlag) {
dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
log.debug("direct connection: relayAgentIp obtained dynamically {}",
@@ -792,69 +804,69 @@
}
}
- // peer address: address of the client or relay agent from which
- // the message to be relayed was received.
- dhcp6Relay.setPeerAddress(peerAddress);
- List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();
+ // peer address: address of the client or relay agent from which
+ // the message to be relayed was received.
+ dhcp6Relay.setPeerAddress(peerAddress);
+ List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();
- // directly connected case, hop count is zero
- // otherwise, hop count + 1
- if (directConnFlag) {
- dhcp6Relay.setHopCount((byte) 0);
- } else {
- dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
- }
+ // directly connected case, hop count is zero
+ // otherwise, hop count + 1
+ if (directConnFlag) {
+ dhcp6Relay.setHopCount((byte) 0);
+ } else {
+ dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
+ }
- // create relay message option
- Dhcp6Option relayMessage = new Dhcp6Option();
- relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
- relayMessage.setLength((short) dhcp6PacketByte.length);
- relayMessage.setData(dhcp6PacketByte);
- options.add(relayMessage);
+ // create relay message option
+ Dhcp6Option relayMessage = new Dhcp6Option();
+ relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
+ relayMessage.setLength((short) dhcp6PacketByte.length);
+ relayMessage.setData(dhcp6PacketByte);
+ options.add(relayMessage);
- // create interfaceId option
- String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
- Dhcp6Option interfaceId = new Dhcp6Option();
- interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
- byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
- byte[] inPortStringBytes = inPortString.getBytes();
- byte[] vlanIdBytes = new byte[2];
- vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
- vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
- byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
- inPortStringBytes.length + vlanIdBytes.length];
- log.debug("Length: interfaceIdBytes {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
- interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
- vlanIdBytes.length);
+ // create interfaceId option
+ String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
+ Dhcp6Option interfaceId = new Dhcp6Option();
+ interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
+ byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
+ byte[] inPortStringBytes = inPortString.getBytes();
+ byte[] vlanIdBytes = new byte[2];
+ vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
+ vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
+ byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
+ inPortStringBytes.length + vlanIdBytes.length];
+ log.debug("Length: interfaceIdBytes {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
+ interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
+ vlanIdBytes.length);
- System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
- System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
- System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
- vlanIdBytes.length);
+ System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
+ System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
+ System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
+ vlanIdBytes.length);
- interfaceId.setData(interfaceIdBytes);
- interfaceId.setLength((short) interfaceIdBytes.length);
+ interfaceId.setData(interfaceIdBytes);
+ interfaceId.setLength((short) interfaceIdBytes.length);
- options.add(interfaceId);
+ options.add(interfaceId);
- log.debug("interfaceId write srcMac {} portString {}",
- HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
- dhcp6Relay.setOptions(options);
- udpPacket.setPayload(dhcp6Relay);
- udpPacket.resetChecksum();
- ipv6Packet.setPayload(udpPacket);
- ipv6Packet.setHopLimit((byte) 64);
- etherReply.setPayload(ipv6Packet);
+ log.debug("interfaceId write srcMac {} portString {}",
+ HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
+ dhcp6Relay.setOptions(options);
+ udpPacket.setPayload(dhcp6Relay);
+ udpPacket.resetChecksum();
+ ipv6Packet.setPayload(udpPacket);
+ ipv6Packet.setHopLimit((byte) 64);
+ etherReply.setPayload(ipv6Packet);
- if (directConnFlag) {
- return new InternalPacket(etherReply, this.dhcpServerConnectPoint);
- } else {
- if (this.indirectDhcpServerIp == null) {
- return new InternalPacket(etherReply, this.dhcpServerConnectPoint);
- } else {
- return new InternalPacket(etherReply, this.indirectDhcpServerConnectPoint);
- }
- }
+ if (directConnFlag) {
+ return new InternalPacket(etherReply, this.dhcpServerConnectPoint);
+ } else {
+ if (this.indirectDhcpServerIp == null) {
+ return new InternalPacket(etherReply, this.dhcpServerConnectPoint);
+ } else {
+ return new InternalPacket(etherReply, this.indirectDhcpServerConnectPoint);
+ }
+ }
}
/**
@@ -1271,6 +1283,57 @@
this.indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6().orElse(null);
}
}
+
+ /**
+ * Returns the first interface ip from interface.
+ *
+ * @param iface interface of one connect point
+ * @return the first interface IP; null if not exists an IP address in
+ * these interfaces
+ */
+ private Ip6Address getFirstIpFromInterface(Interface iface) {
+ checkNotNull(iface, "Interface can't be null");
+ return iface.ipAddressesList().stream()
+ .map(InterfaceIpAddress::ipAddress)
+ .filter(IpAddress::isIp6)
+ .map(IpAddress::getIp6Address)
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * Gets Interface facing to the server for default host.
+ *
+ * @return the Interface facing to the server; null if not found
+ */
+ private Interface getServerInterface() {
+ if (dhcpServerConnectPoint == null || dhcpConnectVlan == null) {
+ return null;
+ }
+ return interfaceService.getInterfacesByPort(dhcpServerConnectPoint)
+ .stream()
+ .filter(iface -> interfaceContainsVlan(iface, dhcpConnectVlan))
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * Gets Interface facing to the server for indirect hosts.
+ * Use default server Interface if indirect server not configured.
+ *
+ * @return the Interface facing to the server; null if not found
+ */
+ private Interface getIndirectServerInterface() {
+ if (indirectDhcpServerConnectPoint == null || indirectDhcpConnectVlan == null) {
+ return getServerInterface();
+ }
+ return interfaceService.getInterfacesByPort(indirectDhcpServerConnectPoint)
+ .stream()
+ .filter(iface -> interfaceContainsVlan(iface, indirectDhcpConnectVlan))
+ .findFirst()
+ .orElse(null);
+ }
+
/**
* Determind if an Interface contains a vlan id.
*