summaryrefslogtreecommitdiffstats
path: root/NetworkPkg/TcpDxe/TcpIo.c
diff options
context:
space:
mode:
Diffstat (limited to 'NetworkPkg/TcpDxe/TcpIo.c')
-rw-r--r--NetworkPkg/TcpDxe/TcpIo.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/NetworkPkg/TcpDxe/TcpIo.c b/NetworkPkg/TcpDxe/TcpIo.c
new file mode 100644
index 0000000000..cecb6d19c5
--- /dev/null
+++ b/NetworkPkg/TcpDxe/TcpIo.c
@@ -0,0 +1,190 @@
+/** @file
+ Implementation of I/O interfaces between TCP and IpIoLib.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TcpMain.h"
+
+/**
+ Packet receive callback function provided to IP_IO, used to call
+ the proper function to handle the packet received by IP.
+
+ @param[in] Status Result of the receive request.
+ @param[in] IcmpErr Valid when Status is EFI_ICMP_ERROR.
+ @param[in] NetSession The IP session for the received packet.
+ @param[in] Pkt Packet received.
+ @param[in] Context The data provided by the user for the received packet when
+ the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
+ This is an optional parameter that may be NULL.
+
+**/
+VOID
+EFIAPI
+TcpRxCallback (
+ IN EFI_STATUS Status,
+ IN UINT8 IcmpErr,
+ IN EFI_NET_SESSION_DATA *NetSession,
+ IN NET_BUF *Pkt,
+ IN VOID *Context OPTIONAL
+ )
+{
+ if (EFI_SUCCESS == Status) {
+ TcpInput (Pkt, &NetSession->Source, &NetSession->Dest, NetSession->IpVersion);
+ } else {
+ TcpIcmpInput (
+ Pkt,
+ IcmpErr,
+ &NetSession->Source,
+ &NetSession->Dest,
+ NetSession->IpVersion
+ );
+ }
+}
+
+/**
+ Send the segment to IP via IpIo function.
+
+ @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
+ @param[in] Nbuf Pointer to the TCP segment to be sent.
+ @param[in] Src Source address of the TCP segment.
+ @param[in] Dest Destination address of the TCP segment.
+ @param[in] Version IP_VERSION_4 or IP_VERSION_6
+
+ @retval 0 The segment was sent out successfully.
+ @retval -1 The segment failed to send.
+
+**/
+INTN
+TcpSendIpPacket (
+ IN TCP_CB *Tcb,
+ IN NET_BUF *Nbuf,
+ IN EFI_IP_ADDRESS *Src,
+ IN EFI_IP_ADDRESS *Dest,
+ IN UINT8 Version
+ )
+{
+ EFI_STATUS Status;
+ IP_IO *IpIo;
+ IP_IO_OVERRIDE Override;
+ SOCKET *Sock;
+ VOID *IpSender;
+ TCP_PROTO_DATA *TcpProto;
+
+ if (NULL == Tcb) {
+
+ IpIo = NULL;
+ IpSender = IpIoFindSender (&IpIo, Version, Src);
+
+ if (IpSender == NULL) {
+ DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
+ return -1;
+ }
+
+ if (Version == IP_VERSION_6) {
+ //
+ // It's tricky here. EFI IPv6 Spec don't allow an instance overriding the
+ // destination address if the dest is already specified through the
+ // configuration data. Here we get the IpIo we need and use the default IP
+ // instance in this IpIo to send the packet. The dest address is configured
+ // to be the unspecified address for the default IP instance.
+ //
+ IpSender = NULL;
+ }
+ } else {
+
+ Sock = Tcb->Sk;
+ TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
+ IpIo = TcpProto->TcpService->IpIo;
+ IpSender = Tcb->IpInfo;
+
+ if (Version == IP_VERSION_6) {
+ //
+ // It's IPv6 and this TCP segment belongs to a solid TCB, in such case
+ // the destination address can't be overridden, so reset the Dest to NULL.
+ //
+ Dest = NULL;
+ }
+ }
+
+ ASSERT (Version == IpIo->IpVersion);
+
+ if (Version == IP_VERSION_4) {
+ Override.Ip4OverrideData.TypeOfService = 0;
+ Override.Ip4OverrideData.TimeToLive = 255;
+ Override.Ip4OverrideData.DoNotFragment = FALSE;
+ Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;
+ ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
+ CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
+ } else {
+ Override.Ip6OverrideData.Protocol = EFI_IP_PROTO_TCP;
+ Override.Ip6OverrideData.HopLimit = 255;
+ Override.Ip6OverrideData.FlowLabel = 0;
+ }
+
+ Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ Refresh the remote peer's Neighbor Cache State if already exists.
+
+ @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
+ @param[in] Neighbor Source address of the TCP segment.
+ @param[in] Timeout Time in 100-ns units that this entry will remain
+ in the neighbor cache. A value of zero means that
+ the entry is permanent. A value of non-zero means
+ that the entry is dynamic and will be deleted
+ after Timeout.
+
+ @retval EFI_SUCCESS Successfully updated the neighbor relationship.
+ @retval EFI_NOT_STARTED The IpIo is not configured.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
+ @retval EFI_NOT_FOUND This entry is not in the neighbor table.
+
+**/
+EFI_STATUS
+Tcp6RefreshNeighbor (
+ IN TCP_CB *Tcb,
+ IN EFI_IP_ADDRESS *Neighbor,
+ IN UINT32 Timeout
+ )
+{
+ IP_IO *IpIo;
+ SOCKET *Sock;
+ TCP_PROTO_DATA *TcpProto;
+
+ if (NULL == Tcb) {
+ IpIo = NULL;
+ IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
+
+ if (IpIo == NULL) {
+ DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
+ return EFI_NOT_STARTED;
+ }
+
+ } else {
+ Sock = Tcb->Sk;
+ TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
+ IpIo = TcpProto->TcpService->IpIo;
+ }
+
+ return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
+}
+