public override void Decode(ByteBuffer buf) { int len = base.DecodeLength(buf); // since the linkAddr of the relay message is the interface // on which the relay itself received the message to be forwarded // we can assume that address is logically a server port IPEndPoint relayMsgLocalAddr = new IPEndPoint(relayMessage.GetLinkAddress(), DhcpConstants.V6_SERVER_PORT); // the peerAddr of the relay message is the source address of // the message which it received and is forwarding, thus the // peerAddress is either another relay or the client itself, // so we don't really know what port to logically set for the // inner message's remote port IPEndPoint relayMsgRemoteAddr = new IPEndPoint(relayMessage.GetPeerAddress(), 0); // create a new buffer that will hold just this RelayOption byte[] b = buf.getBytes(len); ByteBuffer _buf = ByteBuffer.allocate(len); _buf.put(b); // use the wrapped buffer which represents the contents of the message // contained within this relay option, but not any more, i.e. not beyond // what _this_ relay option reports its length to be dhcpMessage = DhcpV6Message.Decode(_buf, relayMsgLocalAddr.Address, relayMsgRemoteAddr); }
private static DhcpV6RelayMessage HandleRelayForward(DhcpV6RelayMessage relayMessage) { IPAddress linkAddr = relayMessage.GetLinkAddress(); _log.Info(("Handling relay forward on link address: " + linkAddr.ToString())); DhcpV6RelayOption relayOption = relayMessage.GetRelayOption(); if ((relayOption != null)) { DhcpV6Message relayOptionMessage = relayOption.GetDhcpMessage(); while ((relayOptionMessage != null)) { // check what kind of message is in the option if ((relayOptionMessage is DhcpV6RelayMessage)) { // encapsulated message is another relay message DhcpV6RelayMessage anotherRelayMessage = ((DhcpV6RelayMessage)(relayOptionMessage)); // flip this inner relay_forward into a relay_reply, // because we reuse the relay message "stack" for the reply anotherRelayMessage.SetMessageType(DhcpConstants.V6MESSAGE_TYPE_RELAY_REPL); // reset the client link reference linkAddr = anotherRelayMessage.GetLinkAddress(); // reset the current relay option reference to the // encapsulated relay message's relay option relayOption = anotherRelayMessage.GetRelayOption(); // reset the relayOptionMessage reference to recurse relayOptionMessage = relayOption.GetDhcpMessage(); } else { // we've peeled off all the layers of the relay message(s), // so now go handle the client request _log.Info(("Handling client request on remote client link address: " + linkAddr.ToString())); DhcpV6Message replyMessage = DhcpV6MessageHandler.HandleClientRequest(linkAddr, relayOptionMessage, null); if ((replyMessage != null)) { // replace the original client request message inside // the relayed message with the generated Reply message relayOption.SetDhcpMessage(replyMessage); // flip the outer-most relay_foward into a relay_reply relayMessage.SetMessageType(DhcpConstants.V6MESSAGE_TYPE_RELAY_REPL); // return the relay message we started with, // with each relay "layer" flipped from a relay_forward // to a relay_reply, and the lowest level relayOption // will contain our Reply for the client request return(relayMessage); } relayOptionMessage = null; // done with relayed messages } } } else { _log.Error("Relay message does not contain a relay option"); } // if we get here, no reply was generated return(null); }