SnpMcastIpToMac.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /** @file
  2. Implementation of the SNP.McastIpToMac() function and its private helpers if
  3. any.
  4. Copyright (C) 2013, Red Hat, Inc.
  5. Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include <Library/UefiBootServicesTableLib.h>
  9. #include "VirtioNet.h"
  10. /**
  11. Converts a multicast IP address to a multicast HW MAC address.
  12. @param This The protocol instance pointer.
  13. @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set
  14. to FALSE if the multicast IP address is IPv4 [RFC 791].
  15. @param IP The multicast IP address that is to be converted to a multicast
  16. HW MAC address.
  17. @param MAC The multicast HW MAC address that is to be generated from IP.
  18. @retval EFI_SUCCESS The multicast IP address was mapped to the
  19. multicast HW MAC address.
  20. @retval EFI_NOT_STARTED The network interface has not been started.
  21. @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The
  22. current buffer size needed to hold the
  23. statistics is returned in StatisticsSize.
  24. @retval EFI_INVALID_PARAMETER One or more of the parameters has an
  25. unsupported value.
  26. @retval EFI_DEVICE_ERROR The command could not be sent to the network
  27. interface.
  28. @retval EFI_UNSUPPORTED This function is not supported by the network
  29. interface.
  30. **/
  31. EFI_STATUS
  32. EFIAPI
  33. VirtioNetMcastIpToMac (
  34. IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
  35. IN BOOLEAN IPv6,
  36. IN EFI_IP_ADDRESS *Ip,
  37. OUT EFI_MAC_ADDRESS *Mac
  38. )
  39. {
  40. VNET_DEV *Dev;
  41. EFI_TPL OldTpl;
  42. EFI_STATUS Status;
  43. //
  44. // http://en.wikipedia.org/wiki/Multicast_address
  45. //
  46. if ((This == NULL) || (Ip == NULL) || (Mac == NULL) ||
  47. (IPv6 && ((Ip->v6.Addr[0]) != 0xFF)) || // invalid IPv6 mcast addr
  48. (!IPv6 && ((Ip->v4.Addr[0] & 0xF0) != 0xE0)) // invalid IPv4 mcast addr
  49. )
  50. {
  51. return EFI_INVALID_PARAMETER;
  52. }
  53. Dev = VIRTIO_NET_FROM_SNP (This);
  54. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  55. switch (Dev->Snm.State) {
  56. case EfiSimpleNetworkStopped:
  57. Status = EFI_NOT_STARTED;
  58. goto Exit;
  59. case EfiSimpleNetworkStarted:
  60. Status = EFI_DEVICE_ERROR;
  61. goto Exit;
  62. default:
  63. break;
  64. }
  65. //
  66. // http://en.wikipedia.org/wiki/IP_multicast#Layer_2_delivery
  67. //
  68. if (IPv6) {
  69. Mac->Addr[0] = 0x33;
  70. Mac->Addr[1] = 0x33;
  71. Mac->Addr[2] = Ip->v6.Addr[12];
  72. Mac->Addr[3] = Ip->v6.Addr[13];
  73. Mac->Addr[4] = Ip->v6.Addr[14];
  74. Mac->Addr[5] = Ip->v6.Addr[15];
  75. } else {
  76. Mac->Addr[0] = 0x01;
  77. Mac->Addr[1] = 0x00;
  78. Mac->Addr[2] = 0x5E;
  79. Mac->Addr[3] = Ip->v4.Addr[1] & 0x7F;
  80. Mac->Addr[4] = Ip->v4.Addr[2];
  81. Mac->Addr[5] = Ip->v4.Addr[3];
  82. }
  83. Status = EFI_SUCCESS;
  84. Exit:
  85. gBS->RestoreTPL (OldTpl);
  86. return Status;
  87. }