Home | History | Annotate | Download | only in IpsecConfig
      1 /** @file
      2   The implementation of dump policy entry function in IpSecConfig application.
      3 
      4   Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "IpSecConfig.h"
     17 #include "Dump.h"
     18 #include "ForEach.h"
     19 #include "Helper.h"
     20 
     21 /**
     22   Private function called to get the version infomation from an EFI_IP_ADDRESS_INFO structure.
     23 
     24   @param[in] AddressInfo    The pointer to the EFI_IP_ADDRESS_INFO structure.
     25 
     26   @return the value of version.
     27 **/
     28 UINTN
     29 GetVerFromAddrInfo (
     30   IN EFI_IP_ADDRESS_INFO    *AddressInfo
     31 )
     32 {
     33   if((AddressInfo->PrefixLength <= 32) && (AddressInfo->Address.Addr[1] == 0) &&
     34      (AddressInfo->Address.Addr[2] == 0) && (AddressInfo->Address.Addr[3] == 0)) {
     35     return IP_VERSION_4;
     36   } else {
     37     return IP_VERSION_6;
     38   }
     39 }
     40 
     41 /**
     42   Private function called to get the version information from a EFI_IP_ADDRESS structure.
     43 
     44   @param[in] Address    The pointer to the EFI_IP_ADDRESS structure.
     45 
     46   @return The value of the version.
     47 **/
     48 UINTN
     49 GetVerFromIpAddr (
     50   IN EFI_IP_ADDRESS    *Address
     51 )
     52 {
     53   if ((Address->Addr[1] == 0) && (Address->Addr[2] == 0) && (Address->Addr[3] == 0)) {
     54     return IP_VERSION_4;
     55   } else {
     56     return IP_VERSION_6;
     57   }
     58 }
     59 
     60 /**
     61   Private function called to print an ASCII string in unicode char format.
     62 
     63   @param[in] Str       The pointer to the ASCII string.
     64   @param[in] Length    The value of the ASCII string length.
     65 **/
     66 VOID
     67 DumpAsciiString (
     68   IN CHAR8    *Str,
     69   IN UINTN    Length
     70   )
     71 {
     72   UINTN    Index;
     73   Print (L"\"");
     74   for (Index = 0; Index < Length; Index++) {
     75     Print (L"%c", (CHAR16) Str[Index]);
     76   }
     77   Print (L"\"");
     78 }
     79 
     80 /**
     81   Private function called to print a buffer in Hex format.
     82 
     83   @param[in] Data      The pointer to the buffer.
     84   @param[in] Length    The size of the buffer.
     85 
     86 **/
     87 VOID
     88 DumpBuf (
     89   IN UINT8    *Data,
     90   IN UINTN    Length
     91   )
     92 {
     93   UINTN    Index;
     94   for (Index = 0; Index < Length; Index++) {
     95     Print (L"%02x ", Data[Index]);
     96   }
     97 }
     98 
     99 /**
    100   Private function called to print EFI_IP_ADDRESS_INFO content.
    101 
    102   @param[in] AddressInfo    The pointer to the EFI_IP_ADDRESS_INFO structure.
    103 **/
    104 VOID
    105 DumpAddressInfo (
    106   IN EFI_IP_ADDRESS_INFO    *AddressInfo
    107   )
    108 {
    109   if (IP_VERSION_4 == GetVerFromAddrInfo (AddressInfo)) {
    110     Print (
    111       L"%d.%d.%d.%d",
    112       (UINTN) AddressInfo->Address.v4.Addr[0],
    113       (UINTN) AddressInfo->Address.v4.Addr[1],
    114       (UINTN) AddressInfo->Address.v4.Addr[2],
    115       (UINTN) AddressInfo->Address.v4.Addr[3]
    116       );
    117     if (AddressInfo->PrefixLength != 32) {
    118       Print (L"/%d", (UINTN) AddressInfo->PrefixLength);
    119     }
    120   }
    121 
    122   if (IP_VERSION_6 == GetVerFromAddrInfo (AddressInfo)) {
    123     Print (
    124       L"%x:%x:%x:%x:%x:%x:%x:%x",
    125       (((UINT16) AddressInfo->Address.v6.Addr[0]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[1]),
    126       (((UINT16) AddressInfo->Address.v6.Addr[2]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[3]),
    127       (((UINT16) AddressInfo->Address.v6.Addr[4]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[5]),
    128       (((UINT16) AddressInfo->Address.v6.Addr[6]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[7]),
    129       (((UINT16) AddressInfo->Address.v6.Addr[8]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[9]),
    130       (((UINT16) AddressInfo->Address.v6.Addr[10]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[11]),
    131       (((UINT16) AddressInfo->Address.v6.Addr[12]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[13]),
    132       (((UINT16) AddressInfo->Address.v6.Addr[14]) << 8) | ((UINT16) AddressInfo->Address.v6.Addr[15])
    133       );
    134     if (AddressInfo->PrefixLength != 128) {
    135       Print (L"/%d", AddressInfo->PrefixLength);
    136     }
    137   }
    138 }
    139 
    140 /**
    141   Private function called to print EFI_IP_ADDRESS content.
    142 
    143   @param[in] IpAddress    The pointer to the EFI_IP_ADDRESS structure.
    144 **/
    145 VOID
    146 DumpIpAddress (
    147   IN EFI_IP_ADDRESS    *IpAddress
    148   )
    149 {
    150   if (IP_VERSION_4 == GetVerFromIpAddr (IpAddress)) {
    151     Print (
    152       L"%d.%d.%d.%d",
    153       (UINTN) IpAddress->v4.Addr[0],
    154       (UINTN) IpAddress->v4.Addr[1],
    155       (UINTN) IpAddress->v4.Addr[2],
    156       (UINTN) IpAddress->v4.Addr[3]
    157       );
    158   }
    159 
    160   if (IP_VERSION_6 == GetVerFromIpAddr (IpAddress)) {
    161     Print (
    162       L"%x:%x:%x:%x:%x:%x:%x:%x",
    163       (((UINT16) IpAddress->v6.Addr[0]) << 8) | ((UINT16) IpAddress->v6.Addr[1]),
    164       (((UINT16) IpAddress->v6.Addr[2]) << 8) | ((UINT16) IpAddress->v6.Addr[3]),
    165       (((UINT16) IpAddress->v6.Addr[4]) << 8) | ((UINT16) IpAddress->v6.Addr[5]),
    166       (((UINT16) IpAddress->v6.Addr[6]) << 8) | ((UINT16) IpAddress->v6.Addr[7]),
    167       (((UINT16) IpAddress->v6.Addr[8]) << 8) | ((UINT16) IpAddress->v6.Addr[9]),
    168       (((UINT16) IpAddress->v6.Addr[10]) << 8) | ((UINT16) IpAddress->v6.Addr[11]),
    169       (((UINT16) IpAddress->v6.Addr[12]) << 8) | ((UINT16) IpAddress->v6.Addr[13]),
    170       (((UINT16) IpAddress->v6.Addr[14]) << 8) | ((UINT16) IpAddress->v6.Addr[15])
    171       );
    172   }
    173 
    174 }
    175 
    176 /**
    177   Private function called to print EFI_IPSEC_SPD_SELECTOR content.
    178 
    179   @param[in] Selector    The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
    180 **/
    181 VOID
    182 DumpSpdSelector (
    183   IN EFI_IPSEC_SPD_SELECTOR    *Selector
    184   )
    185 {
    186   UINT32    Index;
    187   CHAR16    *Str;
    188 
    189   for (Index = 0; Index < Selector->LocalAddressCount; Index++) {
    190     if (Index > 0) {
    191       Print (L",");
    192     }
    193 
    194     DumpAddressInfo (&Selector->LocalAddress[Index]);
    195   }
    196 
    197   if (Index == 0) {
    198     Print (L"localhost");
    199   }
    200 
    201   Print (L" -> ");
    202 
    203   for (Index = 0; Index < Selector->RemoteAddressCount; Index++) {
    204     if (Index > 0) {
    205       Print (L",");
    206     }
    207 
    208     DumpAddressInfo (&Selector->RemoteAddress[Index]);
    209   }
    210 
    211   Str = MapIntegerToString (Selector->NextLayerProtocol, mMapIpProtocol);
    212   if (Str != NULL) {
    213     Print (L" %s", Str);
    214   } else {
    215     Print (L" proto:%d", (UINTN) Selector->NextLayerProtocol);
    216   }
    217 
    218   if ((Selector->NextLayerProtocol == EFI_IP4_PROTO_TCP) || (Selector->NextLayerProtocol == EFI_IP4_PROTO_UDP)) {
    219     Print (L" port:");
    220     if (Selector->LocalPort != EFI_IPSEC_ANY_PORT) {
    221       Print (L"%d", Selector->LocalPort);
    222       if (Selector->LocalPortRange != 0) {
    223         Print (L"~%d", (UINTN) Selector->LocalPort + Selector->LocalPortRange);
    224       }
    225     } else {
    226       Print (L"any");
    227     }
    228 
    229     Print (L" -> ");
    230     if (Selector->RemotePort != EFI_IPSEC_ANY_PORT) {
    231       Print (L"%d", Selector->RemotePort);
    232       if (Selector->RemotePortRange != 0) {
    233         Print (L"~%d", (UINTN) Selector->RemotePort + Selector->RemotePortRange);
    234       }
    235     } else {
    236       Print (L"any");
    237     }
    238   } else if (Selector->NextLayerProtocol == EFI_IP4_PROTO_ICMP) {
    239     Print (L" class/code:");
    240     if (Selector->LocalPort != 0) {
    241       Print (L"%d", (UINTN) (UINT8) Selector->LocalPort);
    242     } else {
    243       Print (L"any");
    244     }
    245 
    246     Print (L"/");
    247     if (Selector->RemotePort != 0) {
    248       Print (L"%d", (UINTN) (UINT8) Selector->RemotePort);
    249     } else {
    250       Print (L"any");
    251     }
    252   }
    253 }
    254 
    255 /**
    256   Print EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA content.
    257 
    258   @param[in] Selector      The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
    259   @param[in] Data          The pointer to the EFI_IPSEC_SPD_DATA structure.
    260   @param[in] EntryIndex    The pointer to the Index in SPD Database.
    261 
    262   @retval EFI_SUCCESS    Dump SPD information successfully.
    263 **/
    264 EFI_STATUS
    265 DumpSpdEntry (
    266   IN EFI_IPSEC_SPD_SELECTOR    *Selector,
    267   IN EFI_IPSEC_SPD_DATA        *Data,
    268   IN UINTN                     *EntryIndex
    269   )
    270 {
    271   BOOLEAN    HasPre;
    272   CHAR16     DataName[128];
    273   CHAR16     *String1;
    274   CHAR16     *String2;
    275   CHAR16     *String3;
    276   UINT8      Index;
    277 
    278   Print (L"%d.", (*EntryIndex)++);
    279 
    280   //
    281   // xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400
    282   // Protect  PF:0x34323423 Name:First Entry
    283   // ext-sequence sequence-overflow fragcheck life:[B0,S1024,H3600]
    284   // ESP algo1 algo2 Tunnel [xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx set]
    285   //
    286 
    287   DumpSpdSelector (Selector);
    288   Print (L"\n  ");
    289 
    290   Print (L"%s ", MapIntegerToString (Data->Action, mMapIpSecAction));
    291   Print (L"PF:%08x ", Data->PackageFlag);
    292 
    293   Index = 0;
    294   while (Data->Name[Index] != 0) {
    295     DataName[Index] = (CHAR16) Data->Name[Index];
    296     Index++;
    297     ASSERT (Index < 128);
    298   }
    299   DataName[Index] = L'\0';
    300 
    301   Print (L"Name:%s", DataName);
    302 
    303   if (Data->Action == EfiIPsecActionProtect) {
    304     Print (L"\n  ");
    305     if (Data->ProcessingPolicy->ExtSeqNum) {
    306       Print (L"ext-sequence ");
    307     }
    308 
    309     if (Data->ProcessingPolicy->SeqOverflow) {
    310       Print (L"sequence-overflow ");
    311     }
    312 
    313     if (Data->ProcessingPolicy->FragCheck) {
    314       Print (L"fragment-check ");
    315     }
    316 
    317     HasPre = FALSE;
    318     if (Data->ProcessingPolicy->SaLifetime.ByteCount != 0) {
    319       Print (HasPre ? L"," : L"life:[");
    320       Print (L"%lxB", Data->ProcessingPolicy->SaLifetime.ByteCount);
    321       HasPre = TRUE;
    322     }
    323 
    324     if (Data->ProcessingPolicy->SaLifetime.SoftLifetime != 0) {
    325       Print (HasPre ? L"," : L"life:[");
    326       Print (L"%lxs", Data->ProcessingPolicy->SaLifetime.SoftLifetime);
    327       HasPre = TRUE;
    328     }
    329 
    330     if (Data->ProcessingPolicy->SaLifetime.HardLifetime != 0) {
    331       Print (HasPre ? L"," : L"life:[");
    332       Print (L"%lxS", Data->ProcessingPolicy->SaLifetime.HardLifetime);
    333       HasPre = TRUE;
    334     }
    335 
    336     if (HasPre) {
    337       Print (L"]");
    338     }
    339 
    340     if (HasPre || Data->ProcessingPolicy->ExtSeqNum ||
    341         Data->ProcessingPolicy->SeqOverflow || Data->ProcessingPolicy->FragCheck) {
    342       Print (L"\n  ");
    343     }
    344 
    345     String1 = MapIntegerToString (Data->ProcessingPolicy->Proto, mMapIpSecProtocol);
    346     String2 = MapIntegerToString (Data->ProcessingPolicy->AuthAlgoId, mMapAuthAlgo);
    347     String3 = MapIntegerToString (Data->ProcessingPolicy->EncAlgoId, mMapEncAlgo);
    348     Print (
    349       L"%s Auth:%s Encrypt:%s ",
    350       String1,
    351       String2,
    352       String3
    353       );
    354 
    355     Print (L"%s ", MapIntegerToString (Data->ProcessingPolicy->Mode, mMapIpSecMode));
    356     if (Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
    357       Print (L"[");
    358       DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress);
    359       Print (L" -> ");
    360       DumpIpAddress (&Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress);
    361       Print (L" %s]", MapIntegerToString (Data->ProcessingPolicy->TunnelOption->DF, mMapDfOption));
    362     }
    363   }
    364 
    365   Print (L"\n");
    366 
    367   return EFI_SUCCESS;
    368 }
    369 
    370 /**
    371   Print EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA2 content.
    372 
    373   @param[in] SaId          The pointer to the EFI_IPSEC_SA_ID structure.
    374   @param[in] Data          The pointer to the EFI_IPSEC_SA_DATA2 structure.
    375   @param[in] EntryIndex    The pointer to the Index in the SAD Database.
    376 
    377   @retval EFI_SUCCESS    Dump SAD information successfully.
    378 **/
    379 EFI_STATUS
    380 DumpSadEntry (
    381   IN EFI_IPSEC_SA_ID      *SaId,
    382   IN EFI_IPSEC_SA_DATA2   *Data,
    383   IN UINTN                *EntryIndex
    384   )
    385 {
    386   BOOLEAN    HasPre;
    387   CHAR16     *AuthAlgoStr;
    388   CHAR16     *EncAlgoStr;
    389 
    390   AuthAlgoStr      = NULL;
    391   EncAlgoStr       = NULL;
    392 
    393   //
    394   // SPI:1234 ESP Destination:xxx.xxx.xxx.xxx
    395   //  Mode:Transport SeqNum:134 AntiReplayWin:64 life:[0B,1023s,3400S] PathMTU:34
    396   //  Auth:xxxx/password Encrypt:yyyy/password
    397   //  xxx.xxx.xxx.xxx/yy -> xxx.xxx.xxx.xx/yy proto:23 port:100~300 -> 300~400
    398   //
    399 
    400   Print (L"%d.", (*EntryIndex)++);
    401   Print (L"0x%x %s ", (UINTN) SaId->Spi, MapIntegerToString (SaId->Proto, mMapIpSecProtocol));
    402   if (Data->Mode == EfiIPsecTunnel) {
    403     Print (L"TunnelSourceAddress:");
    404     DumpIpAddress (&Data->TunnelSourceAddress);
    405     Print (L"\n");
    406     Print (L"  TunnelDestination:");
    407     DumpIpAddress (&Data->TunnelDestinationAddress);
    408     Print (L"\n");
    409   }
    410 
    411   Print (
    412     L"  Mode:%s SeqNum:%lx AntiReplayWin:%d ",
    413     MapIntegerToString (Data->Mode, mMapIpSecMode),
    414     Data->SNCount,
    415     (UINTN) Data->AntiReplayWindows
    416     );
    417 
    418   HasPre = FALSE;
    419   if (Data->SaLifetime.ByteCount != 0) {
    420     Print (HasPre ? L"," : L"life:[");
    421     Print (L"%lxB", Data->SaLifetime.ByteCount);
    422     HasPre = TRUE;
    423   }
    424 
    425   if (Data->SaLifetime.SoftLifetime != 0) {
    426     Print (HasPre ? L"," : L"life:[");
    427     Print (L"%lxs", Data->SaLifetime.SoftLifetime);
    428     HasPre = TRUE;
    429   }
    430 
    431   if (Data->SaLifetime.HardLifetime != 0) {
    432     Print (HasPre ? L"," : L"life:[");
    433     Print (L"%lxS", Data->SaLifetime.HardLifetime);
    434     HasPre = TRUE;
    435   }
    436 
    437   if (HasPre) {
    438     Print (L"] ");
    439   }
    440 
    441   Print (L"PathMTU:%d\n", (UINTN) Data->PathMTU);
    442 
    443   if (SaId->Proto == EfiIPsecAH) {
    444     Print (
    445       L"  Auth:%s/%s\n",
    446       MapIntegerToString (Data->AlgoInfo.AhAlgoInfo.AuthAlgoId, mMapAuthAlgo),
    447       Data->AlgoInfo.AhAlgoInfo.AuthKey
    448       );
    449   } else {
    450     AuthAlgoStr = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.AuthAlgoId, mMapAuthAlgo);
    451     EncAlgoStr  = MapIntegerToString (Data->AlgoInfo.EspAlgoInfo.EncAlgoId, mMapEncAlgo);
    452 
    453     if (Data->ManualSet) {
    454       //
    455       // if the SAD is set manually the key is a Ascii string in most of time.
    456       // Print the Key in Ascii string format.
    457       //
    458       Print (L"  Auth:%s/",AuthAlgoStr);
    459       DumpAsciiString (
    460         Data->AlgoInfo.EspAlgoInfo.AuthKey,
    461         Data->AlgoInfo.EspAlgoInfo.AuthKeyLength
    462         );
    463       Print (L"\n  Encrypt:%s/",EncAlgoStr);
    464       DumpAsciiString (
    465         Data->AlgoInfo.EspAlgoInfo.EncKey,
    466         Data->AlgoInfo.EspAlgoInfo.EncKeyLength
    467         );
    468     } else {
    469       //
    470       // if the SAD is created by IKE, the key is a set of hex value in buffer.
    471       // Print the Key in Hex format.
    472       //
    473       Print (L"  Auth:%s/",AuthAlgoStr);
    474       DumpBuf ((UINT8 *)(Data->AlgoInfo.EspAlgoInfo.AuthKey), Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);
    475 
    476       Print (L"\n  Encrypt:%s/",EncAlgoStr);
    477       DumpBuf ((UINT8 *)(Data->AlgoInfo.EspAlgoInfo.EncKey), Data->AlgoInfo.EspAlgoInfo.EncKeyLength);
    478     }
    479   }
    480   Print (L"\n");
    481   if (Data->SpdSelector != NULL) {
    482     Print (L"  ");
    483     DumpSpdSelector (Data->SpdSelector);
    484     Print (L"\n");
    485   }
    486 
    487   return EFI_SUCCESS;
    488 }
    489 
    490 /**
    491   Print EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA content.
    492 
    493   @param[in] PadId         The pointer to the EFI_IPSEC_PAD_ID structure.
    494   @param[in] Data          The pointer to the EFI_IPSEC_PAD_DATA structure.
    495   @param[in] EntryIndex    The pointer to the Index in the PAD Database.
    496 
    497   @retval EFI_SUCCESS    Dump PAD information successfully.
    498 **/
    499 EFI_STATUS
    500 DumpPadEntry (
    501   IN EFI_IPSEC_PAD_ID      *PadId,
    502   IN EFI_IPSEC_PAD_DATA    *Data,
    503   IN UINTN                 *EntryIndex
    504   )
    505 {
    506   CHAR16    *String1;
    507   CHAR16    *String2;
    508 
    509   //
    510   // ADDR:10.23.17.34/15
    511   // IDEv1 PreSharedSecret IKE-ID
    512   // password
    513   //
    514 
    515   Print (L"%d.", (*EntryIndex)++);
    516 
    517   if (PadId->PeerIdValid) {
    518     Print (L"ID:%s", PadId->Id.PeerId);
    519   } else {
    520     Print (L"ADDR:");
    521     DumpAddressInfo (&PadId->Id.IpAddress);
    522   }
    523 
    524   Print (L"\n");
    525 
    526   String1 = MapIntegerToString (Data->AuthProtocol, mMapAuthProto);
    527   String2 = MapIntegerToString (Data->AuthMethod, mMapAuthMethod);
    528   Print (
    529     L"  %s %s",
    530     String1,
    531     String2
    532     );
    533 
    534   if (Data->IkeIdFlag) {
    535     Print (L"IKE-ID");
    536   }
    537 
    538   Print (L"\n");
    539 
    540   if (Data->AuthData != NULL) {
    541     DumpAsciiString (Data->AuthData, Data->AuthDataSize);
    542     Print (L"\n");
    543   }
    544 
    545   if (Data->RevocationData != NULL) {
    546     Print (L"  %s\n", Data->RevocationData);
    547   }
    548 
    549   return EFI_SUCCESS;
    550 
    551 }
    552 
    553 VISIT_POLICY_ENTRY  mDumpPolicyEntry[] = {
    554   (VISIT_POLICY_ENTRY) DumpSpdEntry,
    555   (VISIT_POLICY_ENTRY) DumpSadEntry,
    556   (VISIT_POLICY_ENTRY) DumpPadEntry
    557 };
    558 
    559 /**
    560   Print all entry information in the database according to datatype.
    561 
    562   @param[in] DataType        The value of EFI_IPSEC_CONFIG_DATA_TYPE.
    563   @param[in] ParamPackage    The pointer to the ParamPackage list.
    564 
    565   @retval EFI_SUCCESS    Dump all information successfully.
    566   @retval Others         Some mistaken case.
    567 **/
    568 EFI_STATUS
    569 ListPolicyEntry (
    570   IN EFI_IPSEC_CONFIG_DATA_TYPE    DataType,
    571   IN LIST_ENTRY                    *ParamPackage
    572   )
    573 {
    574   UINTN  EntryIndex;
    575 
    576   EntryIndex = 0;
    577   return ForeachPolicyEntry (DataType, mDumpPolicyEntry[DataType], &EntryIndex);
    578 }
    579 
    580