Example #1
0
Dhcpv6StatusCode dhcpv6GetStatusCode(const uint8_t *options, size_t length)
{
   uint16_t statusCode;
   Dhcpv6Option *option;
   Dhcpv6StatusCodeOption *statusCodeOption;

   //Search for the Status Code option
   option = dhcpv6GetOption(options, length, DHCPV6_OPTION_STATUS_CODE);

   //Check whether the option has been found
   if(option != NULL && ntohs(option->length) >= sizeof(Dhcpv6StatusCodeOption))
   {
      //The option contains a status code and a status message
      statusCodeOption = (Dhcpv6StatusCodeOption *) option->value;

      //Convert the status code from network byte order
      statusCode = ntohs(statusCodeOption->statusCode);
   }
   else
   {
      //If the Status Code option does not appear in a message in which the option
      //could appear, the status of the message is assumed to be Success
      statusCode = DHCPV6_STATUS_SUCCESS;
   }

   //Return status code
   return (Dhcpv6StatusCode) statusCode;
}
Example #2
0
error_t dhcpv6ParseStatusCodeOption(const uint8_t *options, size_t length)
{
   error_t error;
   uint16_t statusCode;
   Dhcpv6Option *option;
   Dhcpv6StatusCodeOption *statusCodeOption;

   //Search for the Status Code option
   option = dhcpv6GetOption(options, length, DHCPV6_OPTION_STATUS_CODE);

   //If the Status Code option does not appear in a message in which the option
   //could appear, the status of the message is assumed to be Success
   if(!option || ntohs(option->length) < sizeof(Dhcpv6StatusCodeOption))
      return NO_ERROR;

   //The option contains a status code and a status message
   statusCodeOption = (Dhcpv6StatusCodeOption *) option->value;
   //Convert status code from network byte order
   statusCode = ntohs(statusCodeOption->statusCode);

   //Check the status code returned by the peer
   switch(statusCode)
   {
   //Success
   case DHCPV6_STATUS_SUCCESS:
      error = NO_ERROR;
      break;
   //Unspecified failure
   case DHCPV6_STATUS_UNSPEC_FAILURE:
      error = ERROR_FAILURE;
      break;
   //Server has no address available to assign to the IA
   case DHCPV6_STATUS_NO_ADDRS_AVAILABLE:
      error = ERROR_NO_ADDRESS;
      break;
   //Client record (binding) unavailable
   case DHCPV6_STATUS_NO_BINDING:
      error = ERROR_NO_BINDING;
      break;
   //The prefix for the address is not appropriate for
   //the link to which the client is attached
   case DHCPV6_STATUS_NOT_ON_LINK:
      error = ERROR_NOT_ON_LINK;
      break;
   //Sent by a server to a client to force the client to send
   //messages to the server using the multicast address
   case DHCPV6_STATUS_USE_MULTICAST:
      error = ERROR_USE_MULTICAST;
      break;
   //Any other failure...
   default:
      error = ERROR_FAILURE;
      break;
   }

   //Return the corresponding error
   return error;
}
Example #3
0
error_t dhcpv6ForwardRelayReplyMessage(Dhcpv6RelayCtx *context)
{
   error_t error;
   uint_t i;
   uint32_t interfaceId;
   size_t inputMessageLen;
   size_t outputMessageLen;
   Dhcpv6RelayMessage *inputMessage;
   Dhcpv6Message *outputMessage;
   Dhcpv6Option *option;
   IpAddr ipAddr;
   uint16_t port;

   //Point to the buffer where to store the incoming DHCPv6 message
   inputMessage = (Dhcpv6RelayMessage *) context->buffer;

   //Read incoming message
   error = socketReceiveFrom(context->serverSocket, &ipAddr, &port,
      inputMessage, DHCPV6_MAX_MSG_SIZE, &inputMessageLen, 0);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_INFO("\r\nDHCPv6 message received on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
      context->serverInterface->name, inputMessageLen);
   //Dump the contents of the message for debugging purpose
   dhcpv6DumpMessage(inputMessage, inputMessageLen);

   //Check the length of the DHCPv6 message
   if(inputMessageLen < sizeof(Dhcpv6RelayMessage))
      return ERROR_INVALID_MESSAGE;

   //Inspect the message type and only forward Relay-Reply messages.
   //Other DHCPv6 message types must be silently discarded
   if(inputMessage->msgType != DHCPV6_MSG_TYPE_RELAY_REPL)
      return ERROR_INVALID_MESSAGE;

   //Get the length of the Options field
   inputMessageLen -= sizeof(Dhcpv6Message);

   //Check whether an Interface ID option is included in the Relay-Reply
   option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_INTERFACE_ID);
   //Failed to retrieve specified option?
   if(!option || ntohs(option->length) != sizeof(interfaceId))
      return ERROR_INVALID_MESSAGE;

   //Read the Interface ID option contents
   memcpy(&interfaceId, option->value, sizeof(interfaceId));
   //Convert the 32-bit integer from network byte order
   interfaceId = ntohl(interfaceId);

   //The Relay-Reply message must include a Relay Message option
   option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_RELAY_MSG);
   //Failed to retrieve specified option?
   if(!option || ntohs(option->length) < sizeof(Dhcpv6Message))
      return ERROR_INVALID_MESSAGE;

   //Extract the message from the Relay Message option
   outputMessage = (Dhcpv6Message *) option->value;
   //Save the length of the message
   outputMessageLen = ntohs(option->length);

   //Loop through client-facing interfaces
   for(i = 0; i < context->clientInterfaceCount; i++)
   {
      //Check whether the current interface matches the Interface ID option
      if(context->clientInterface[i]->id == interfaceId)
      {
         //Debug message
         TRACE_INFO("Forwarding DHCPv6 message on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
            context->clientInterface[i]->name, outputMessageLen);
         //Dump the contents of the message for debugging purpose
         dhcpv6DumpMessage(outputMessage, outputMessageLen);

         //Copy the peer-address into the destination IP address
         ipAddr.length = sizeof(Ipv6Addr);
         ipAddr.ipv6Addr = inputMessage->peerAddress;

         //Select the relevant port number to use
          if(outputMessage->msgType == DHCPV6_MSG_TYPE_RELAY_REPL)
            port = DHCPV6_SERVER_PORT;
         else
            port = DHCPV6_CLIENT_PORT;

         //Relay the DHCPv6 message to the client on the link
         //identified by the Interface ID option
         return socketSendTo(context->clientSocket[i], &ipAddr,
            port, outputMessage, outputMessageLen, NULL, 0);
      }
   }

   //Unknown interface identifier...
   return ERROR_INVALID_OPTION;
}