+ if (mIpSec->DisabledFlag) {\r
+ //\r
+ // If IPsec is disabled, restore the original MTU\r
+ // \r
+ IpSb->MaxPacketSize = IpSb->OldMaxPacketSize;\r
+ goto ON_EXIT;\r
+ } else {\r
+ //\r
+ // If IPsec is enabled, use the MTU which reduce the IPsec header length. \r
+ //\r
+ IpSb->MaxPacketSize = IpSb->OldMaxPacketSize - IP4_MAX_IPSEC_HEADLEN; \r
+ }\r
+\r
+ //\r
+ // Rebuild fragment table from netbuf to ease IPsec process.\r
+ //\r
+ FragmentTable = AllocateZeroPool (FragmentCount * sizeof (NET_FRAGMENT));\r
+\r
+ if (FragmentTable == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount);\r
+ \r
+ //\r
+ // Record the original FragmentTable and count.\r
+ //\r
+ OriginalFragmentTable = FragmentTable;\r
+ OriginalFragmentCount = FragmentCount;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (FragmentTable);\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Convert host byte order to network byte order\r
+ //\r
+ Ip4NtohHead (*Head);\r
+ \r
+ Status = mIpSec->ProcessExt (\r
+ mIpSec,\r
+ IpSb->Controller,\r
+ IP_VERSION_4,\r
+ (VOID *) (*Head),\r
+ &(*Head)->Protocol,\r
+ (VOID **) Options,\r
+ OptionsLen,\r
+ (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable),\r
+ &FragmentCount,\r
+ Direction,\r
+ &RecycleEvent\r
+ );\r
+ //\r
+ // Convert back to host byte order\r
+ //\r
+ Ip4NtohHead (*Head);\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (OriginalFragmentTable);\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) {\r
+ //\r
+ // For ByPass Packet\r
+ //\r
+ FreePool (FragmentTable);\r
+ goto ON_EXIT;\r
+ } else {\r
+ //\r
+ // Free the FragmentTable which allocated before calling the IPsec.\r
+ //\r
+ FreePool (OriginalFragmentTable);\r
+ }\r
+\r
+ if (Direction == EfiIPsecOutBound && TxWrap != NULL) {\r
+ \r
+ TxWrap->IpSecRecycleSignal = RecycleEvent;\r
+ TxWrap->Packet = NetbufFromExt (\r
+ FragmentTable,\r
+ FragmentCount,\r
+ IP4_MAX_HEADLEN,\r
+ 0,\r
+ Ip4FreeTxToken,\r
+ TxWrap\r
+ );\r
+ if (TxWrap->Packet == NULL) {\r
+ //\r
+ // Recover the TxWrap->Packet, if meet a error, and the caller will free\r
+ // the TxWrap.\r
+ //\r
+ TxWrap->Packet = *Netbuf;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Free orginal Netbuf.\r
+ //\r
+ NetIpSecNetbufFree (*Netbuf);\r
+ *Netbuf = TxWrap->Packet;\r
+ \r
+ } else {\r
+ \r
+ IpSecWrap = AllocateZeroPool (sizeof (IP4_IPSEC_WRAP));\r
+ \r
+ if (IpSecWrap == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ gBS->SignalEvent (RecycleEvent);\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ IpSecWrap->IpSecRecycleSignal = RecycleEvent;\r
+ IpSecWrap->Packet = Packet;\r
+ Packet = NetbufFromExt (\r
+ FragmentTable, \r
+ FragmentCount, \r
+ IP4_MAX_HEADLEN, \r
+ 0, \r
+ Ip4IpSecFree, \r
+ IpSecWrap\r
+ );\r
+ \r
+ if (Packet == NULL) {\r
+ Packet = IpSecWrap->Packet;\r
+ gBS->SignalEvent (RecycleEvent);\r
+ FreePool (IpSecWrap);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (Direction == EfiIPsecInBound && 0 != CompareMem (*Head, &ZeroHead, sizeof (IP4_HEAD))) {\r
+ Ip4PrependHead (Packet, *Head, *Options, *OptionsLen);\r
+ Ip4NtohHead (Packet->Ip.Ip4);\r
+ NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE);\r
+\r
+ CopyMem (\r
+ IP4_GET_CLIP_INFO (Packet),\r
+ IP4_GET_CLIP_INFO (IpSecWrap->Packet),\r
+ sizeof (IP4_CLIP_INFO)\r
+ );\r
+ }\r
+ *Netbuf = Packet;\r