示例#1
0
文件: Mtftp4Wrq.c 项目: kraxel/edk2
/**
  The input process routine for MTFTP upload.

  @param  UdpPacket             The received MTFTP packet.
  @param  EndPoint              The local/remote access point
  @param  IoStatus              The result of the packet receiving
  @param  Context               Opaque parameter for the callback, which is the
                                MTFTP session.
**/
VOID
EFIAPI
Mtftp4WrqInput (
  IN NET_BUF                *UdpPacket,
  IN UDP_END_POINT          *EndPoint,
  IN EFI_STATUS             IoStatus,
  IN VOID                   *Context
  )
{
  MTFTP4_PROTOCOL           *Instance;
  EFI_MTFTP4_PACKET         *Packet;
  BOOLEAN                   Completed;
  EFI_STATUS                Status;
  UINT32                    Len;
  UINT16                    Opcode;

  Instance = (MTFTP4_PROTOCOL *) Context;
  NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);

  Completed = FALSE;
  Packet    = NULL;
  Status    = EFI_SUCCESS;

  if (EFI_ERROR (IoStatus)) {
    Status = IoStatus;
    goto ON_EXIT;
  }

  ASSERT (UdpPacket != NULL);

  if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {
    goto ON_EXIT;
  }

  //
  // Client send initial request to server's listening port. Server
  // will select a UDP port to communicate with the client.
  //
  if (EndPoint->RemotePort != Instance->ConnectedPort) {
    if (Instance->ConnectedPort != 0) {
      goto ON_EXIT;
    } else {
      Instance->ConnectedPort = EndPoint->RemotePort;
    }
  }

  //
  // Copy the MTFTP packet to a continuous buffer if it isn't already so.
  //
  Len = UdpPacket->TotalSize;

  if (UdpPacket->BlockOpNum > 1) {
    Packet = AllocatePool (Len);

    if (Packet == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto ON_EXIT;
    }

    NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);

  } else {
    Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
    ASSERT (Packet != NULL);
  }

  Opcode = NTOHS (Packet->OpCode);

  //
  // Call the user's CheckPacket if provided. Abort the transmission
  // if CheckPacket returns an EFI_ERROR code.
  //
  if ((Instance->Token->CheckPacket != NULL) &&
      ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {

    Status = Instance->Token->CheckPacket (
                                &Instance->Mtftp4,
                                Instance->Token,
                                (UINT16) Len,
                                Packet
                                );

    if (EFI_ERROR (Status)) {
      //
      // Send an error message to the server to inform it
      //
      if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {
        Mtftp4SendError (
          Instance,
          EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
          (UINT8 *) "User aborted the transfer"
          );
      }

      Status = EFI_ABORTED;
      goto ON_EXIT;
    }
  }

  switch (Opcode) {
  case EFI_MTFTP4_OPCODE_ACK:
    if (Len != MTFTP4_OPCODE_LEN + MTFTP4_BLKNO_LEN) {
      goto ON_EXIT;
    }

    Status = Mtftp4WrqHandleAck (Instance, Packet, Len, &Completed);
    break;

  case EFI_MTFTP4_OPCODE_OACK:
    if (Len <= MTFTP4_OPCODE_LEN) {
      goto ON_EXIT;
    }

    Status = Mtftp4WrqHandleOack (Instance, Packet, Len, &Completed);
    break;

  case EFI_MTFTP4_OPCODE_ERROR:
    Status = EFI_TFTP_ERROR;
    break;
    
  default:
    break;
  }

ON_EXIT:
  //
  // Free the resources, then if !EFI_ERROR (Status) and not completed,
  // restart the receive, otherwise end the session.
  //
  if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
    FreePool (Packet);
  }

  if (UdpPacket != NULL) {
    NetbufFree (UdpPacket);
  }

  if (!EFI_ERROR (Status) && !Completed) {
    Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
  }

  //
  // Status may have been updated by UdpIoRecvDatagram
  //
  if (EFI_ERROR (Status) || Completed) {
    Mtftp4CleanOperation (Instance, Status);
  }
}
示例#2
0
/**
  The packet process callback for Mtftp6 download.

  @param[in]  UdpPacket             The pointer to the packet received.
  @param[in]  UdpEpt                The pointer to the Udp6 access point.
  @param[in]  IoStatus              The status from Udp6 instance.
  @param[in]  Context               The pointer to the context.

**/
VOID
EFIAPI
Mtftp6RrqInput (
  IN NET_BUF                *UdpPacket,
  IN UDP_END_POINT          *UdpEpt,
  IN EFI_STATUS             IoStatus,
  IN VOID                   *Context
  )
{
  MTFTP6_INSTANCE           *Instance;
  EFI_MTFTP6_PACKET         *Packet;
  BOOLEAN                   IsCompleted;
  BOOLEAN                   IsMcast;
  EFI_STATUS                Status;
  UINT16                    Opcode;
  UINT32                    TotalNum;
  UINT32                    Len;

  Instance = (MTFTP6_INSTANCE *) Context;

  NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);

  Status      = EFI_SUCCESS;
  Packet      = NULL;
  IsCompleted = FALSE;
  IsMcast     = FALSE;
  TotalNum    = 0;

  //
  // Return error status if Udp6 instance failed to receive.
  //
  if (EFI_ERROR (IoStatus)) {
    Status = IoStatus;
    goto ON_EXIT;
  }

  ASSERT (UdpPacket != NULL);

  if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
    goto ON_EXIT;
  }

  //
  // Find the port this packet is from to restart receive correctly.
  //
  if (CompareMem (
        Ip6Swap128 (&UdpEpt->LocalAddr.v6),
        &Instance->McastIp,
        sizeof (EFI_IPv6_ADDRESS)
        ) == 0) {
    IsMcast = TRUE;
  } else {
    IsMcast = FALSE;
  }

  //
  // Client send initial request to server's listening port. Server
  // will select a UDP port to communicate with the client. The server
  // is required to use the same port as RemotePort to multicast the
  // data.
  //
  if (UdpEpt->RemotePort != Instance->ServerDataPort) {
    if (Instance->ServerDataPort != 0) {
      goto ON_EXIT;
    } else {
      //
      // For the subsequent exchange of requests, reconfigure the udpio as
      // (serverip, serverport, localip, localport).
      // Ususally, the client set serverport as 0 to receive and reset it
      // once the first packet arrives to send ack.
      //
      Instance->ServerDataPort = UdpEpt->RemotePort;
    }
  }

  //
  // Copy the MTFTP packet to a continuous buffer if it isn't already so.
  //
  Len      = UdpPacket->TotalSize;
  TotalNum = UdpPacket->BlockOpNum;

  if (TotalNum > 1) {
    Packet = AllocateZeroPool (Len);

    if (Packet == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto ON_EXIT;
    }

    NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);

  } else {
    Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
    ASSERT (Packet != NULL);
  }

  Opcode = NTOHS (Packet->OpCode);

  //
  // Callback to the user's CheckPacket if provided. Abort the transmission
  // if CheckPacket returns an EFI_ERROR code.
  //
  if ((Instance->Token->CheckPacket != NULL) &&
      (Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
      ) {

    Status = Instance->Token->CheckPacket (
                                &Instance->Mtftp6,
                                Instance->Token,
                                (UINT16) Len,
                                Packet
                                );

    if (EFI_ERROR (Status)) {
      //
      // Send an error message to the server to inform it
      //
      if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
        //
        // Free the received packet before send new packet in ReceiveNotify,
        // since the udpio might need to be reconfigured.
        //
        NetbufFree (UdpPacket);
        UdpPacket = NULL;
        //
        // Send the Mtftp6 error message if user aborted the current session.
        //
        Mtftp6SendError (
          Instance,
          EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
          (UINT8 *) "User aborted the transfer"
          );
      }

      Status = EFI_ABORTED;
      goto ON_EXIT;
    }
  }

  //
  // Switch the process routines by the operation code.
  //
  switch (Opcode) {
  case EFI_MTFTP6_OPCODE_DATA:
    if ((Len > (UINT32) (MTFTP6_DATA_HEAD_LEN + Instance->BlkSize)) || (Len < (UINT32) MTFTP6_DATA_HEAD_LEN)) {
      goto ON_EXIT;
    }
    //
    // Handle the data packet of Rrq.
    //
    Status = Mtftp6RrqHandleData (
               Instance,
               Packet,
               Len,
               &UdpPacket,
               &IsCompleted
               );
    break;

  case EFI_MTFTP6_OPCODE_OACK:
    if (IsMcast || Len <= MTFTP6_OPCODE_LEN) {
      goto ON_EXIT;
    }
    //
    // Handle the Oack packet of Rrq.
    //
    Status = Mtftp6RrqHandleOack (
               Instance,
               Packet,
               Len,
               &UdpPacket,
               &IsCompleted
               );
    break;

  default:
    //
    // Drop and return eror if received error message.
    //
    Status = EFI_TFTP_ERROR;
    break;
  }

ON_EXIT:
  //
  // Free the resources, then if !EFI_ERROR (Status), restart the
  // receive, otherwise end the session.
  //
  if (Packet != NULL && TotalNum > 1) {
    FreePool (Packet);
  }
  if (UdpPacket != NULL) {
    NetbufFree (UdpPacket);
  }
  if (!EFI_ERROR (Status) && !IsCompleted) {
    if (IsMcast) {
      Status = UdpIoRecvDatagram (
                 Instance->McastUdpIo,
                 Mtftp6RrqInput,
                 Instance,
                 0
                 );
    } else {
      Status = UdpIoRecvDatagram (
                 Instance->UdpIo,
                 Mtftp6RrqInput,
                 Instance,
                 0
                 );
    }
  }
  //
  // Clean up the current session if failed to continue.
  //
  if (EFI_ERROR (Status) || IsCompleted) {
    Mtftp6OperationClean (Instance, Status);
  }
}
示例#3
0
文件: IScsiCHAP.c 项目: jeppeter/vbox
/**
  This function fills the CHAP authentication information into the login PDU
  during the security negotiation stage in the iSCSI connection login.

  @param[in]       Conn        The iSCSI connection.
  @param[in, out]  Pdu         The PDU to send out.

  @retval EFI_SUCCESS           All check passed and the phase-related CHAP
                                authentication info is filled into the iSCSI PDU.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
  @retval EFI_PROTOCOL_ERROR    Some kind of protocol error occurred.

**/
EFI_STATUS
IScsiCHAPToSendReq (
  IN      ISCSI_CONNECTION  *Conn,
  IN OUT  NET_BUF           *Pdu
  )
{
  EFI_STATUS                  Status;
  ISCSI_SESSION               *Session;
  ISCSI_LOGIN_REQUEST         *LoginReq;
  ISCSI_CHAP_AUTH_DATA        *AuthData;
  CHAR8                       *Value;
  CHAR8                       ValueStr[256];
  CHAR8                       *Response;
  UINT32                      RspLen;
  CHAR8                       *Challenge;
  UINT32                      ChallengeLen;

  ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);

  Session     = Conn->Session;
  AuthData    = &Session->AuthData.CHAP;
  LoginReq    = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, 0);
  if (LoginReq == NULL) {
    return EFI_PROTOCOL_ERROR;
  }
  Status      = EFI_SUCCESS;

  RspLen      = 2 * ISCSI_CHAP_RSP_LEN + 3;
  Response    = AllocateZeroPool (RspLen);
  if (Response == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  ChallengeLen  = 2 * ISCSI_CHAP_RSP_LEN + 3;
  Challenge     = AllocateZeroPool (ChallengeLen);
  if (Challenge == NULL) {
    FreePool (Response);
    return EFI_OUT_OF_RESOURCES;
  }

  switch (Conn->AuthStep) {
  case ISCSI_AUTH_INITIAL:
    //
    // It's the initial Login Request. Fill in the key=value pairs mandatory
    // for the initial Login Request.
    //
    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_INITIATOR_NAME, mPrivate->InitiatorName);
    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_SESSION_TYPE, "Normal");
    IScsiAddKeyValuePair (
      Pdu,
      ISCSI_KEY_TARGET_NAME,
      Session->ConfigData->SessionConfigData.TargetName
      );

    if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) {
      Value = ISCSI_KEY_VALUE_NONE;
      ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
    } else {
      Value = ISCSI_AUTH_METHOD_CHAP;
    }

    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_AUTH_METHOD, Value);

    break;

  case ISCSI_CHAP_STEP_ONE:
    //
    // First step, send the Login Request with CHAP_A=<A1,A2...> key-value pair.
    //
    AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", ISCSI_CHAP_ALGORITHM_MD5);
    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_ALGORITHM, ValueStr);

    Conn->AuthStep = ISCSI_CHAP_STEP_TWO;
    break;

  case ISCSI_CHAP_STEP_THREE:
    //
    // Third step, send the Login Request with CHAP_N=<N> CHAP_R=<R> or
    // CHAP_N=<N> CHAP_R=<R> CHAP_I=<I> CHAP_C=<C> if target authentication is
    // required too.
    //
    // CHAP_N=<N>
    //
    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->AuthConfig->CHAPName);
    //
    // CHAP_R=<R>
    //
    IScsiBinToHex ((UINT8 *) AuthData->CHAPResponse, ISCSI_CHAP_RSP_LEN, Response, &RspLen);
    IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response);

    if (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
      //
      // CHAP_I=<I>
      //
      IScsiGenRandom ((UINT8 *) &AuthData->OutIdentifier, 1);
      AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
      IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
      //
      // CHAP_C=<C>
      //
      IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN);
      AuthData->OutChallengeLength = ISCSI_CHAP_RSP_LEN;
      IScsiBinToHex ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN, Challenge, &ChallengeLen);
      IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge);

      Conn->AuthStep = ISCSI_CHAP_STEP_FOUR;
    }
    //
    // Set the stage transition flag.
    //
    ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
    break;

  default:
    Status = EFI_PROTOCOL_ERROR;
    break;
  }

  FreePool (Response);
  FreePool (Challenge);

  return Status;
}
示例#4
0
文件: Ip6Icmp.c 项目: etiago/vbox
/**
  Reply an ICMPv6 echo request.

  @param[in]  IpSb               The IP service that received the packet.
  @param[in]  Head               The IP head of the ICMPv6 informational message.
  @param[in]  Packet             The content of the ICMPv6 message with the IP head
                                 removed.

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
  @retval EFI_SUCCESS            Successfully answered the ICMPv6 Echo request.
  @retval Others                 Failed to answer the ICMPv6 Echo request.

**/
EFI_STATUS
Ip6IcmpReplyEcho (
  IN IP6_SERVICE            *IpSb,
  IN EFI_IP6_HEADER         *Head,
  IN NET_BUF                *Packet
  )
{
  IP6_ICMP_INFORMATION_HEAD *Icmp;
  NET_BUF                   *Data;
  EFI_STATUS                Status;
  EFI_IP6_HEADER            ReplyHead;

  Status = EFI_OUT_OF_RESOURCES;
  //
  // make a copy the packet, it is really a bad idea to
  // send the MNP's buffer back to MNP.
  //
  Data = NetbufDuplicate (Packet, NULL, IP6_MAX_HEADLEN);
  if (Data == NULL) {
    goto Exit;
  }

  //
  // Change the ICMP type to echo reply, exchange the source
  // and destination, then send it. The source is updated to
  // use specific destination. See RFC1122. SRR/RR option
  // update is omitted.
  //
  Icmp = (IP6_ICMP_INFORMATION_HEAD *) NetbufGetByte (Data, 0, NULL);
  if (Icmp == NULL) {
    NetbufFree (Data);
    goto Exit;
  }

  Icmp->Head.Type     = ICMP_V6_ECHO_REPLY;
  Icmp->Head.Checksum = 0;

  //
  // Generate the IPv6 basic header
  // If the Echo Reply is a response to a Echo Request sent to one of the node's unicast address,
  // the Source address of the Echo Reply must be the same address.
  //
  ZeroMem (&ReplyHead, sizeof (EFI_IP6_HEADER));

  ReplyHead.PayloadLength  = HTONS ((UINT16) (Packet->TotalSize));
  ReplyHead.NextHeader     = IP6_ICMP;
  ReplyHead.HopLimit       = IpSb->CurHopLimit;
  IP6_COPY_ADDRESS (&ReplyHead.DestinationAddress, &Head->SourceAddress);

  if (Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
    IP6_COPY_ADDRESS (&ReplyHead.SourceAddress, &Head->DestinationAddress);
  }

  //
  // If source is unspecified, Ip6Output will select a source for us
  //
  Status = Ip6Output (
             IpSb,
             NULL,
             NULL,
             Data,
             &ReplyHead,
             NULL,
             0,
             Ip6SysPacketSent,
             NULL
             );

Exit:
  NetbufFree (Packet);
  return Status;
}