/** @file
  iSCSI DHCP6 related configuration routines.

Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include "IScsiImpl.h"


/**
  Extract the Root Path option and get the required target information from
  Boot File Uniform Resource Locator (URL) Option.

  @param[in]       RootPath      The RootPath string.
  @param[in]       Length        Length of the RootPath option payload.
  @param[in, out]  ConfigData    The iSCSI session configuration data read from
                                 nonvolatile device.

  @retval EFI_SUCCESS            All required information is extracted from the
                                 RootPath option.
  @retval EFI_NOT_FOUND          The RootPath is not an iSCSI RootPath.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
  @retval EFI_INVALID_PARAMETER  The RootPath is malformatted.

**/
EFI_STATUS
IScsiDhcp6ExtractRootPath (
  IN     CHAR8                        *RootPath,
  IN     UINT16                       Length,
  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData
  )
{
  EFI_STATUS                  Status;
  UINT16                      IScsiRootPathIdLen;
  CHAR8                       *TmpStr;
  ISCSI_ROOT_PATH_FIELD       Fields[RP_FIELD_IDX_MAX];
  ISCSI_ROOT_PATH_FIELD       *Field;
  UINT32                      FieldIndex;
  UINT8                       Index;
  ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;
  EFI_IP_ADDRESS              Ip;
  UINT8                       IpMode;  

  ConfigNvData = &ConfigData->SessionConfigData;

  //
  // "iscsi:"<servername>":"<protocol>":"<port>":"<LUN>":"<targetname>
  //
  IScsiRootPathIdLen = (UINT16) AsciiStrLen (ISCSI_ROOT_PATH_ID);

  if ((Length <= IScsiRootPathIdLen) ||
      (CompareMem (RootPath, ISCSI_ROOT_PATH_ID, IScsiRootPathIdLen) != 0)) {
    return EFI_NOT_FOUND;
  }
  //
  // Skip the iSCSI RootPath ID "iscsi:".
  //
  RootPath = RootPath + IScsiRootPathIdLen;
  Length   = (UINT16) (Length - IScsiRootPathIdLen);

  TmpStr   = (CHAR8 *) AllocatePool (Length + 1);
  if (TmpStr == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  CopyMem (TmpStr, RootPath, Length);
  TmpStr[Length]  = '\0';

  Index           = 0;
  FieldIndex      = 0;
  ZeroMem (&Fields[0], sizeof (Fields));

  //
  // Extract SERVERNAME field in the Root Path option.
  //
  if (TmpStr[Index] != ISCSI_ROOT_PATH_ADDR_START_DELIMITER) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  } else {
    Index++;
  }

  Fields[RP_FIELD_IDX_SERVERNAME].Str = &TmpStr[Index];

  while ((TmpStr[Index] != ISCSI_ROOT_PATH_ADDR_END_DELIMITER) && (Index < Length)) {
    Index++;
  }

  //
  // Skip ']' and ':'.
  //
  TmpStr[Index] = '\0';
  Index += 2;

  Fields[RP_FIELD_IDX_SERVERNAME].Len = (UINT8) AsciiStrLen (Fields[RP_FIELD_IDX_SERVERNAME].Str);

  //
  // Extract others fields in the Root Path option string.
  //
  for (FieldIndex = 1; (FieldIndex < RP_FIELD_IDX_MAX) && (Index < Length); FieldIndex++) {

    if (TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) {
      Fields[FieldIndex].Str = &TmpStr[Index];
    }

    while ((TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) && (Index < Length)) {
      Index++;
    }

    if (TmpStr[Index] == ISCSI_ROOT_PATH_FIELD_DELIMITER) {
      if (FieldIndex != RP_FIELD_IDX_TARGETNAME) {
        TmpStr[Index] = '\0';
        Index++;
      }

      if (Fields[FieldIndex].Str != NULL) {
        Fields[FieldIndex].Len = (UINT8) AsciiStrLen (Fields[FieldIndex].Str);
      }
    }
  }

  if (FieldIndex != RP_FIELD_IDX_MAX) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }

  if ((Fields[RP_FIELD_IDX_SERVERNAME].Str == NULL) ||
      (Fields[RP_FIELD_IDX_TARGETNAME].Str == NULL) ||
      (Fields[RP_FIELD_IDX_PROTOCOL].Len > 1)
      ) {

    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }
  //
  // Get the IP address of the target.
  //
  Field   = &Fields[RP_FIELD_IDX_SERVERNAME];  
  if (ConfigNvData->IpMode < IP_MODE_AUTOCONFIG) {
    IpMode = ConfigNvData->IpMode;
  } else {
    IpMode = ConfigData->AutoConfigureMode;
  }

  Status = IScsiAsciiStrToIp (Field->Str, IpMode, &Ip);
  CopyMem (&ConfigNvData->TargetIp, &Ip, sizeof (EFI_IP_ADDRESS));


  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }
  //
  // Check the protocol type.
  //
  Field = &Fields[RP_FIELD_IDX_PROTOCOL];
  if ((Field->Str != NULL) && ((*(Field->Str) - '0') != EFI_IP_PROTO_TCP)) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }
  //
  // Get the port of the iSCSI target.
  //
  Field = &Fields[RP_FIELD_IDX_PORT];
  if (Field->Str != NULL) {
    ConfigNvData->TargetPort = (UINT16) AsciiStrDecimalToUintn (Field->Str);
  } else {
    ConfigNvData->TargetPort = ISCSI_WELL_KNOWN_PORT;
  }
  //
  // Get the LUN.
  //
  Field = &Fields[RP_FIELD_IDX_LUN];
  if (Field->Str != NULL) {
    Status = IScsiAsciiStrToLun (Field->Str, ConfigNvData->BootLun);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }
  } else {
    ZeroMem (ConfigNvData->BootLun, sizeof (ConfigNvData->BootLun));
  }
  //
  // Get the target iSCSI Name.
  //
  Field = &Fields[RP_FIELD_IDX_TARGETNAME];

  if (AsciiStrLen (Field->Str) > ISCSI_NAME_MAX_SIZE - 1) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_EXIT;
  }
  //
  // Validate the iSCSI name.
  //
  Status = IScsiNormalizeName (Field->Str, AsciiStrLen (Field->Str));
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  AsciiStrCpy (ConfigNvData->TargetName, Field->Str);

ON_EXIT:

  FreePool (TmpStr);

  return Status;
}

/**
  EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol 
  instance to intercept events that occurs in the DHCPv6 Information Request
  exchange process.

  @param[in]  This              Pointer to the EFI_DHCP6_PROTOCOL instance that 
                                is used to configure this  callback function.
  @param[in]  Context           Pointer to the context that is initialized in
                                the EFI_DHCP6_PROTOCOL.InfoRequest().
  @param[in]  Packet            Pointer to Reply packet that has been received.
                                The EFI DHCPv6 Protocol instance is responsible
                                for freeing the buffer.

  @retval EFI_SUCCESS           Tell the EFI DHCPv6 Protocol instance to finish
                                Information Request exchange process.
  @retval EFI_NOT_READY         Tell the EFI DHCPv6 Protocol instance to continue
                                Information Request exchange process.
  @retval EFI_ABORTED           Tell the EFI DHCPv6 Protocol instance to abort
                                the Information Request exchange process.
  @retval EFI_UNSUPPORTED       Tell the EFI DHCPv6 Protocol instance to finish
                                the Information Request exchange process because some
                                request information are not received.

**/
EFI_STATUS
EFIAPI
IScsiDhcp6ParseReply (
  IN EFI_DHCP6_PROTOCOL          *This,
  IN VOID                        *Context,
  IN EFI_DHCP6_PACKET            *Packet
  )
{
  EFI_STATUS                  Status;
  UINT32                      Index;
  UINT32                      OptionCount;
  EFI_DHCP6_PACKET_OPTION     *BootFileOpt;
  EFI_DHCP6_PACKET_OPTION     **OptionList;
  ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData;
  UINT16                      ParaLen;
 
  OptionCount = 0;
  BootFileOpt = NULL;
  
  Status      = This->Parse (This, Packet, &OptionCount, NULL);
  if (Status != EFI_BUFFER_TOO_SMALL) {
    return EFI_NOT_READY;
  }

  OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *));
  if (OptionList == NULL) {
    return EFI_NOT_READY;
  }

  Status = This->Parse (This, Packet, &OptionCount, OptionList);
  if (EFI_ERROR (Status)) {
    Status = EFI_NOT_READY;
    goto Exit;
  }

  ConfigData = (ISCSI_ATTEMPT_CONFIG_NVDATA *) Context;

  for (Index = 0; Index < OptionCount; Index++) {
    OptionList[Index]->OpCode = NTOHS (OptionList[Index]->OpCode);
    OptionList[Index]->OpLen  = NTOHS (OptionList[Index]->OpLen);

    //
    // Get DNS server addresses from this reply packet.
    //
    if (OptionList[Index]->OpCode == DHCP6_OPT_DNS_SERVERS) {

      if (((OptionList[Index]->OpLen & 0xf) != 0) || (OptionList[Index]->OpLen == 0)) {
        Status = EFI_UNSUPPORTED;
        goto Exit;
      }
      //
      // Primary DNS server address.
      //
      CopyMem (&ConfigData->PrimaryDns, &OptionList[Index]->Data[0], sizeof (EFI_IPv6_ADDRESS));

      if (OptionList[Index]->OpLen > 16) {
        //
        // Secondary DNS server address
        //
        CopyMem (&ConfigData->SecondaryDns, &OptionList[Index]->Data[16], sizeof (EFI_IPv6_ADDRESS));
      }

    } else if (OptionList[Index]->OpCode == DHCP6_OPT_BOOT_FILE_URL) {
      //
      // The server sends this option to inform the client about an URL to a boot file.
      //
      BootFileOpt = OptionList[Index];
    } else if (OptionList[Index]->OpCode == DHCP6_OPT_BOOT_FILE_PARA) {
      //
      // The server sends this option to inform the client about DHCP6 server address.
      //
      if (OptionList[Index]->OpLen < 18) {
        Status = EFI_UNSUPPORTED;
        goto Exit;
      }
      //
      // Check param-len 1, should be 16 bytes.
      //
      CopyMem (&ParaLen, &OptionList[Index]->Data[0], sizeof (UINT16));
      if (NTOHS (ParaLen) != 16) {
        Status = EFI_UNSUPPORTED;
        goto Exit;
      }

      CopyMem (&ConfigData->DhcpServer, &OptionList[Index]->Data[2], sizeof (EFI_IPv6_ADDRESS));
    }
  }

  if (BootFileOpt == NULL) {
    Status = EFI_UNSUPPORTED;
    goto Exit;
  }
  
  //
  // Get iSCSI root path from Boot File Uniform Resource Locator (URL) Option
  //
  Status = IScsiDhcp6ExtractRootPath (
             (CHAR8 *) BootFileOpt->Data,
             BootFileOpt->OpLen,
             ConfigData
             );

Exit:

  FreePool (OptionList);
  return Status;
}


/**
  Parse the DHCP ACK to get the address configuration and DNS information.

  @param[in]       Image         The handle of the driver image.
  @param[in]       Controller    The handle of the controller;
  @param[in, out]  ConfigData    The attempt configuration data.

  @retval EFI_SUCCESS            The DNS information is got from the DHCP ACK.
  @retval EFI_NO_MAPPING         DHCP failed to acquire address and other
                                 information.
  @retval EFI_INVALID_PARAMETER  The DHCP ACK's DNS option is malformatted.
  @retval EFI_DEVICE_ERROR       Some unexpected error occurred.
  @retval EFI_OUT_OF_RESOURCES   There is no sufficient resource to finish the
                                 operation.
  @retval EFI_NO_MEDIA           There was a media error.

**/
EFI_STATUS
IScsiDoDhcp6 (
  IN     EFI_HANDLE                  Image,
  IN     EFI_HANDLE                  Controller,
  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData
  )
{
  EFI_HANDLE                Dhcp6Handle;
  EFI_DHCP6_PROTOCOL        *Dhcp6;
  EFI_STATUS                Status;
  EFI_STATUS                TimerStatus;
  EFI_DHCP6_PACKET_OPTION   *Oro;
  EFI_DHCP6_RETRANSMISSION  InfoReqReXmit;
  EFI_EVENT                 Timer;
  BOOLEAN                   MediaPresent;

  //
  // Check media status before doing DHCP.
  //
  MediaPresent = TRUE;
  NetLibDetectMedia (Controller, &MediaPresent);
  if (!MediaPresent) {
    return EFI_NO_MEDIA;
  }

  //
  // iSCSI will only request target info from DHCPv6 server.
  //
  if (!ConfigData->SessionConfigData.TargetInfoFromDhcp) {
    return EFI_SUCCESS;
  }

  Dhcp6Handle = NULL;
  Dhcp6       = NULL;
  Oro         = NULL;
  Timer       = NULL;

  //
  // Create a DHCP6 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiDhcp6ServiceBindingProtocolGuid,
             &Dhcp6Handle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  Dhcp6Handle,
                  &gEfiDhcp6ProtocolGuid,
                  (VOID **) &Dhcp6,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 5);
  if (Oro == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Ask the server to reply with DNS and Boot File URL options by info request.
  // All members in EFI_DHCP6_PACKET_OPTION are in network order.
  //
  Oro->OpCode  = HTONS (DHCP6_OPT_REQUEST_OPTION);
  Oro->OpLen   = HTONS (2 * 3);
  Oro->Data[1] = DHCP6_OPT_DNS_SERVERS;
  Oro->Data[3] = DHCP6_OPT_BOOT_FILE_URL;
  Oro->Data[5] = DHCP6_OPT_BOOT_FILE_PARA;

  InfoReqReXmit.Irt = 4;
  InfoReqReXmit.Mrc = 1;
  InfoReqReXmit.Mrt = 10;
  InfoReqReXmit.Mrd = 30;

  Status = Dhcp6->InfoRequest (
                    Dhcp6,
                    TRUE,
                    Oro,
                    0,
                    NULL,
                    &InfoReqReXmit,
                    NULL,
                    IScsiDhcp6ParseReply,
                    ConfigData
                    );
  if (Status == EFI_NO_MAPPING) {
    Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    Status = gBS->SetTimer (
                    Timer,
                    TimerRelative,
                    ISCSI_GET_MAPPING_TIMEOUT
                    );

    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    do {

      TimerStatus = gBS->CheckEvent (Timer);

      if (!EFI_ERROR (TimerStatus)) {
        Status = Dhcp6->InfoRequest (
                          Dhcp6,
                          TRUE,
                          Oro,
                          0,
                          NULL,
                          &InfoReqReXmit,
                          NULL,
                          IScsiDhcp6ParseReply,
                          ConfigData
                          );
      }

    } while (TimerStatus == EFI_NOT_READY);

  }

ON_EXIT:

  if (Oro != NULL) {
    FreePool (Oro);
  }  

  if (Timer != NULL) {
    gBS->CloseEvent (Timer);
  }

  if (Dhcp6 != NULL) {
    gBS->CloseProtocol (
           Dhcp6Handle,
           &gEfiDhcp6ProtocolGuid,
           Image,
           Controller
           );
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiDhcp6ServiceBindingProtocolGuid,
    Dhcp6Handle
    );

  return Status;
}

