udp4impl.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,114 行 · 第 1/4 页

C
2,114
字号

      while (Udp4FindInstanceByPort(InstanceList, StationAddress, mUdp4RandomPort)) {

        mUdp4RandomPort++;
        if (mUdp4RandomPort == 0) {
          mUdp4RandomPort = UDP4_PORT_KNOWN;
        }

        if (mUdp4RandomPort == StartPort) {
          //
          // No available port.
          //
          return EFI_OUT_OF_RESOURCES;
        }
      }

      ConfigData->StationPort = mUdp4RandomPort;
    }

    mUdp4RandomPort++;
    if (mUdp4RandomPort == 0) {
      mUdp4RandomPort = UDP4_PORT_KNOWN;
    }
  }

  return EFI_SUCCESS;
}

BOOLEAN
Udp4IsReconfigurable (
  IN EFI_UDP4_CONFIG_DATA  *OldConfigData,
  IN EFI_UDP4_CONFIG_DATA  *NewConfigData
  )
/*++

Routine Description:

  This function is used to check whether the NewConfigData has any un-reconfigurable
  parameters changed compared to the OldConfigData.

Arguments:

  OldConfigData - Pointer to the current ConfigData the udp instance uses.
  NewConfigData - Pointer to the new ConfigData.

Returns:

  The instance is reconfigurable or not according to the NewConfigData.

--*/
{
  if ((NewConfigData->AcceptAnyPort != OldConfigData->AcceptAnyPort) ||
    (NewConfigData->AcceptBroadcast != OldConfigData->AcceptBroadcast) ||
    (NewConfigData->AcceptPromiscuous != OldConfigData->AcceptPromiscuous) ||
    (NewConfigData->AllowDuplicatePort != OldConfigData->AllowDuplicatePort)) {
    //
    // The receiving filter parameters cannot be changed.
    //
    return FALSE;
  }

  if ((!NewConfigData->AcceptAnyPort) &&
    (NewConfigData->StationPort != OldConfigData->StationPort)) {
    //
    // The port is not changeable.
    //
    return FALSE;
  }

  if (!NewConfigData->AcceptPromiscuous) {
  
    if (NewConfigData->UseDefaultAddress != OldConfigData->UseDefaultAddress) {
      //
      // The NewConfigData differs to the old one on the UseDefaultAddress.
      //
      return FALSE;
    }
    
    if (!NewConfigData->UseDefaultAddress &&
      (!EFI_IP_EQUAL (NewConfigData->StationAddress, OldConfigData->StationAddress) ||
      !EFI_IP_EQUAL (NewConfigData->SubnetMask, OldConfigData->SubnetMask))) {
      //
      // If the instance doesn't use the default address, and the new address or
      // new subnet mask is different from the old values.
      //
      return FALSE;
    }
  }

  if (!EFI_IP_EQUAL (NewConfigData->RemoteAddress, OldConfigData->RemoteAddress)) {
    //
    // The remoteaddress is not the same.
    //
    return FALSE;
  }

  if ((EFI_IP4 (NewConfigData->RemoteAddress) != 0) &&
    (NewConfigData->RemotePort != OldConfigData->RemotePort)) {
    //
    // The RemotePort differs if it's designated in the configdata.
    //
    return FALSE;
  }

  //
  // All checks pass, return TRUE.
  //
  return TRUE;
}

VOID
Udp4BuildIp4ConfigData (
  IN EFI_UDP4_CONFIG_DATA  *Udp4ConfigData,
  IN EFI_IP4_CONFIG_DATA   *Ip4ConfigData
  )
/*++

Routine Description:

  This function builds the Ip4 configdata from the Udp4ConfigData.

Arguments:

  Udp4ConfigData - Pointer to the EFI_UDP4_CONFIG_DATA.
  Ip4ConfigData  - Pointer to the EFI_IP4_CONFIG_DATA.

Returns:

  None.

--*/
{
  *Ip4ConfigData                   = mIpIoDefaultIpConfigData;
  Ip4ConfigData->DefaultProtocol   = EFI_IP_PROTO_UDP;
  Ip4ConfigData->AcceptBroadcast   = Udp4ConfigData->AcceptBroadcast;
  Ip4ConfigData->AcceptPromiscuous = Udp4ConfigData->AcceptPromiscuous;
  Ip4ConfigData->UseDefaultAddress = Udp4ConfigData->UseDefaultAddress;
  Ip4ConfigData->StationAddress    = Udp4ConfigData->StationAddress;
  Ip4ConfigData->SubnetMask        = Udp4ConfigData->SubnetMask;

  //
  // use the -1 magic number to disable the receiving process of the ip instance.
  //
  Ip4ConfigData->ReceiveTimeout    = (UINT32) (-1);
}

EFI_STATUS
Udp4ValidateTxToken (
  IN UDP4_INSTANCE_DATA         *Instance,
  IN EFI_UDP4_COMPLETION_TOKEN  *TxToken
  )
/*++

Routine Description:

  This function validates the TxToken, it returns the error code according to the spec.

Arguments:

  Instance - Pointer to the udp instance context data.
  TxToken  - Pointer to the token to be checked.

Returns:

  EFI_SUCCESS           - The TxToken is valid.
  EFI_INVALID_PARAMETER - One or more of the following are TRUE:
                            This is NULL.
                            Token is NULL.
                            Token.Event is NULL.
                            Token.Packet.TxData is NULL.
                            Token.Packet.TxData.FragmentCount is zero.
                            Token.Packet.TxData.DataLength is not equal to the sum of
                            fragment lengths.
                            One or more of the Token.Packet.TxData.FragmentTable[].
                            FragmentLength fields is zero.
                            One or more of the Token.Packet.TxData.FragmentTable[].
                            FragmentBuffer fields is NULL.
                            Token.Packet.TxData. GatewayAddress is not a unicast IPv4
                            address if it is not NULL.
                            One or more IPv4 addresses in Token.Packet.TxData.
                            UdpSessionData are not valid unicast IPv4 addresses if the
                            UdpSessionData is not NULL.
  EFI_BAD_BUFFER_SIZE   - The data length is greater than the maximum UDP packet size. 

--*/
{
  EFI_UDP4_TRANSMIT_DATA  *TxData;
  UINT32                  Index;
  UINT32                  TotalLen;
  EFI_UDP4_CONFIG_DATA    *ConfigData;
  EFI_UDP4_SESSION_DATA   *UdpSessionData;
  IP4_ADDR                SourceAddress;

  if (TxToken->Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  TxData = TxToken->Packet.TxData;

  if ((TxData == NULL) || (TxData->FragmentCount == 0)) {
    return EFI_INVALID_PARAMETER;
  }

  TotalLen = 0;
  for (Index = 0; Index < TxData->FragmentCount; Index++) {

    if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||
      (TxData->FragmentTable[Index].FragmentLength == 0)) {
      //
      // if the FragmentBuffer is NULL or the FragmentLeng is zero.
      //
      return EFI_INVALID_PARAMETER;
    }

    TotalLen += TxData->FragmentTable[Index].FragmentLength;
  }

  if (TotalLen != TxData->DataLength) {
    //
    // The TotalLen calculated by adding all the FragmentLeng doesn't equal to the
    // DataLength.
    //
    return EFI_INVALID_PARAMETER;
  }

  if ((TxData->GatewayAddress != NULL) &&
    !Ip4IsUnicast(EFI_NTOHL (*(TxData->GatewayAddress)), 0)) {
    //
    // The specified GatewayAddress is not a unicast IPv4 address while it's not 0.
    //
    return EFI_INVALID_PARAMETER;
  }

  ConfigData     = &Instance->ConfigData;
  UdpSessionData = TxData->UdpSessionData;

  if (UdpSessionData != NULL) {

    SourceAddress = EFI_NTOHL (UdpSessionData->SourceAddress);

    if ((SourceAddress != 0) && !Ip4IsUnicast (SourceAddress, 0)) {
      //
      // Check whether SourceAddress is a valid IPv4 address in case it's not zero.
      // The configured station address is used if SourceAddress is zero.
      //
      return EFI_INVALID_PARAMETER;
    }

    if ((UdpSessionData->DestinationPort == 0) && (ConfigData->RemotePort == 0)) {
      //
      // Ambiguous, no avalaible DestinationPort for this token.
      //
      return EFI_INVALID_PARAMETER;
    }

    if (EFI_IP4 (UdpSessionData->DestinationAddress) == 0) {
      //
      // The DestinationAddress specified in the UdpSessionData is 0.
      //
      return EFI_INVALID_PARAMETER;
    }
  } else if (EFI_IP4 (ConfigData->RemoteAddress) == 0) {
    //
    // the configured RemoteAddress is all zero, and the user doens't override the
    // destination address.
    //
    return EFI_INVALID_PARAMETER;
  }

  if (TxData->DataLength > UDP4_MAX_DATA_SIZE) {
    return EFI_BAD_BUFFER_SIZE;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
Udp4TokenExist (
  IN NET_MAP       *Map,
  IN NET_MAP_ITEM  *Item,
  IN VOID          *Context      
  )
/*++

Routine Description:

  This function checks whether the specified Token duplicates with the one in the Map.

Arguments:

  Map     - Pointer to the NET_MAP.
  Item    - Pointer to the NET_MAP_ITEM contain the pointer to the Token.
  Context - Pointer to the Token to be checked.

Returns:

  EFI_SUCCESS       - The Token specified by Context differs from the one in the Item.
  EFI_ACCESS_DENIED - The Token duplicates with the one in the Item.

--*/
{
  EFI_UDP4_COMPLETION_TOKEN  *Token;
  EFI_UDP4_COMPLETION_TOKEN  *TokenInItem;

  Token       = (EFI_UDP4_COMPLETION_TOKEN*) Context;
  TokenInItem = (EFI_UDP4_COMPLETION_TOKEN*) Item->Key;

  if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
    //
    // The Token duplicates with the TokenInItem in case either the two pointers are the
    // same or the Events of these two tokens are the same.
    //
    return EFI_ACCESS_DENIED;
  }

  return EFI_SUCCESS;
}

UINT16
Udp4Checksum (
  IN NET_BUF *Packet,
  IN UINT16  HeadSum
  )
/*++

Routine Description:

  This function calculates the checksum for the Packet, utilizing the pre-calculated
  pseudo HeadSum to reduce some overhead.

Arguments:

  Packet  - Pointer to the NET_BUF contains the udp datagram.
  HeadSum - Checksum of the pseudo header execpt the length field.

Returns:

  The 16-bit checksum of this udp datagram.

--*/
{
  UINT16  Checksum;

  Checksum  = NetbufChecksum (Packet);
  Checksum  = NetAddChecksum (Checksum, HeadSum);

  Checksum  = NetAddChecksum (Checksum, HTONS ((UINT16) Packet->TotalSize));

  return ~Checksum;
}

EFI_STATUS
Udp4RemoveToken (
  IN NET_MAP                    *TokenMap,
  IN EFI_UDP4_COMPLETION_TOKEN  *Token
  )
/*++

Routine Description:

  This function removes the specified Token from the TokenMap.

Arguments:

  TokenMap - Pointer to the NET_MAP containing the tokens.
  Token    - Pointer to the Token to be removed.

Returns:

  EFI_SUCCESS   - The specified Token is removed from the TokenMap.
  EFI_NOT_FOUND - The specified Token is not found in the TokenMap.

--*/
{
  NET_MAP_ITEM  *Item;

  //
  // Find the Token first.
  //
  Item = NetMapFindKey (TokenMap, (VOID *) Token);

  if (Item != NULL) {
    //
    // Remove the token if it's found in the map.
    //
    NetMapRemoveItem (TokenMap, Item, NULL);

    return EFI_SUCCESS;
  }

  return EFI_NOT_FOUND;
}

STATIC
VOID
Udp4DgramSent (
  IN EFI_STATUS  Status,
  IN VOID        *Context,
  IN VOID        *Sender,
  IN VOID        *NotifyData
  )
/*++

Routine Description:

  This function is the packet transmitting notify function registered to the IpIo
  interface. It's called to signal the udp TxToken when IpIo layer completes the
  transmitting of the udp datagram.

Arguments:

  Status     - The completion status of the output udp datagram.
  Context    - Pointer to the context data.
  Sender     - Pointer to the Ip sender of the udp datagram.
  NotifyData - Pointer to the notify data.

Returns:

  None.

--*/
{
  UDP4_INSTANCE_DATA         *Instance;
  EFI_UDP4_COMPLETION_TOKEN  *Token;

  Instance = (UDP4_INSTANCE_DATA *) Context;
  Token    = (EFI_UDP4_COMPLETION_TOKEN *) NotifyData;

  if (Udp4RemoveToken (&Instance->TxTokens, Token) == EFI_SUCCESS) {
    //
    // The token may be cancelled. Only signal it if the remove operation succeeds.
    //
    Token->Status = Status;
    gBS->SignalEvent (Token->Event);
  }
}

STATIC
VOID
Udp4DgramRcvd (
  IN EFI_STATUS            Status,
  IN ICMP_ERROR            IcmpError,
  IN EFI_NET_SESSION_DATA  *NetSession,
  IN NET_BUF               *Packet,
  IN VOID                  *Context
  )
/*++

Routine Description:

  This function processes the received datagram passed up by the IpIo layer.

Arguments:

  Status     - The status of this udp datagram.
  IcmpError  - The IcmpError code, only available when Status is EFI_ICMP_ERROR.
  NetSession - Pointer to the EFI_NET_SESSION_DATA.
  Packet     - Pointer to the NET_BUF containing the received udp datagram.
  Context    - Pointer to the context data.

Returns:

  None.

--*/
{
  NET_CHECK_SIGNATURE (Packet, NET_BUF_SIGNATURE);

  //
  // IpIo only passes received packets with Status EFI_SUCCESS or EFI_ICMP_ERROR.
  //
  if (Status == EFI_SUCCESS) {
    //
    // Demultiplex the received datagram.
    //
    Udp4Demultiplex ((UDP4_SERVICE_DATA *) Context, NetSession, Packet);
  } else {
    //
    // Handle the ICMP_ERROR packet.
    //
    Udp4IcmpHandler ((UDP4_SERVICE_DATA *) Context, IcmpError, NetSession, Packet);
  }
}

EFI_STATUS
Udp4LeaveGroup (
  IN NET_MAP       *Map,
  IN NET_MAP_ITEM  *Item,
  IN VOID          *Arg OPTIONAL
  )
/*++

Routine Description:

  This function removes the multicast group specified by Arg from the Map.

Arguments:

  Map  - Pointer to the NET_MAP.
  Item - Pointer to the NET_MAP_ITEM.
  Arg  - Pointer to the Arg, it's the pointer to a multicast IPv4 Address.

Returns:

  EFI_SUCCESS - The multicast address is removed.
  EFI_ABORTED - The specified multicast address is removed and the Arg is not NULL.

--*/
{
  EFI_IPv4_ADDRESS  *McastIp;

  McastIp = Arg;

  if ((McastIp != NULL) && ((UINTN) EFI_IP4 (*McastIp) != (UINTN) (Item->Key))) {
    //
    // McastIp is not NULL and the multicast address contained in the Item 
    // is not the same as McastIp.
    //
    return EFI_SUCCESS;
  }

  //
  // Remove this Item.
  //
  NetMapRemoveItem (Map, Item, NULL);

  if (McastIp != NULL) {
    //
    // Return EFI_ABORTED in case McastIp is not NULL to terminate the iteration.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?