1 /** @file 2 Implementation of I/O interfaces between TCP and IpIoLib. 3 4 Copyright (c) 2009 - 2012, 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 "TcpMain.h" 17 18 /** 19 Packet receive callback function provided to IP_IO, used to call 20 the proper function to handle the packet received by IP. 21 22 @param[in] Status Result of the receive request. 23 @param[in] IcmpErr Valid when Status is EFI_ICMP_ERROR. 24 @param[in] NetSession The IP session for the received packet. 25 @param[in] Pkt Packet received. 26 @param[in] Context The data provided by the user for the received packet when 27 the callback is registered in IP_IO_OPEN_DATA::RcvdContext. 28 This is an optional parameter that may be NULL. 29 30 **/ 31 VOID 32 EFIAPI 33 TcpRxCallback ( 34 IN EFI_STATUS Status, 35 IN UINT8 IcmpErr, 36 IN EFI_NET_SESSION_DATA *NetSession, 37 IN NET_BUF *Pkt, 38 IN VOID *Context OPTIONAL 39 ) 40 { 41 if (EFI_SUCCESS == Status) { 42 TcpInput (Pkt, &NetSession->Source, &NetSession->Dest, NetSession->IpVersion); 43 } else { 44 TcpIcmpInput ( 45 Pkt, 46 IcmpErr, 47 &NetSession->Source, 48 &NetSession->Dest, 49 NetSession->IpVersion 50 ); 51 } 52 } 53 54 /** 55 Send the segment to IP via IpIo function. 56 57 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 58 @param[in] Nbuf Pointer to the TCP segment to be sent. 59 @param[in] Src Source address of the TCP segment. 60 @param[in] Dest Destination address of the TCP segment. 61 @param[in] Version IP_VERSION_4 or IP_VERSION_6 62 63 @retval 0 The segment was sent out successfully. 64 @retval -1 The segment failed to send. 65 66 **/ 67 INTN 68 TcpSendIpPacket ( 69 IN TCP_CB *Tcb, 70 IN NET_BUF *Nbuf, 71 IN EFI_IP_ADDRESS *Src, 72 IN EFI_IP_ADDRESS *Dest, 73 IN UINT8 Version 74 ) 75 { 76 EFI_STATUS Status; 77 IP_IO *IpIo; 78 IP_IO_OVERRIDE Override; 79 SOCKET *Sock; 80 VOID *IpSender; 81 TCP_PROTO_DATA *TcpProto; 82 83 if (NULL == Tcb) { 84 85 IpIo = NULL; 86 IpSender = IpIoFindSender (&IpIo, Version, Src); 87 88 if (IpSender == NULL) { 89 DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n")); 90 return -1; 91 } 92 93 if (Version == IP_VERSION_6) { 94 // 95 // It's tricky here. EFI IPv6 Spec don't allow an instance overriding the 96 // destination address if the dest is already specified through the 97 // configuration data. Here we get the IpIo we need and use the default IP 98 // instance in this IpIo to send the packet. The dest address is configured 99 // to be the unspecified address for the default IP instance. 100 // 101 IpSender = NULL; 102 } 103 } else { 104 105 Sock = Tcb->Sk; 106 TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved; 107 IpIo = TcpProto->TcpService->IpIo; 108 IpSender = Tcb->IpInfo; 109 110 if (Version == IP_VERSION_6) { 111 // 112 // It's IPv6 and this TCP segment belongs to a solid TCB, in such case 113 // the destination address can't be overridden, so reset the Dest to NULL. 114 // 115 if (!Tcb->RemoteIpZero) { 116 Dest = NULL; 117 } 118 } 119 } 120 121 ASSERT (Version == IpIo->IpVersion); 122 123 if (Version == IP_VERSION_4) { 124 Override.Ip4OverrideData.TypeOfService = 0; 125 Override.Ip4OverrideData.TimeToLive = 255; 126 Override.Ip4OverrideData.DoNotFragment = FALSE; 127 Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP; 128 ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS)); 129 CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS)); 130 } else { 131 Override.Ip6OverrideData.Protocol = EFI_IP_PROTO_TCP; 132 Override.Ip6OverrideData.HopLimit = 255; 133 Override.Ip6OverrideData.FlowLabel = 0; 134 } 135 136 Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override); 137 138 if (EFI_ERROR (Status)) { 139 DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status)); 140 return -1; 141 } 142 143 return 0; 144 } 145 146 /** 147 Refresh the remote peer's Neighbor Cache State if already exists. 148 149 @param[in] Tcb Pointer to the TCP_CB of this TCP instance. 150 @param[in] Neighbor Source address of the TCP segment. 151 @param[in] Timeout Time in 100-ns units that this entry will remain 152 in the neighbor cache. A value of zero means that 153 the entry is permanent. A value of non-zero means 154 that the entry is dynamic and will be deleted 155 after Timeout. 156 157 @retval EFI_SUCCESS Successfully updated the neighbor relationship. 158 @retval EFI_NOT_STARTED The IpIo is not configured. 159 @retval EFI_INVALID_PARAMETER Any input parameter is invalid. 160 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. 161 @retval EFI_NOT_FOUND This entry is not in the neighbor table. 162 163 **/ 164 EFI_STATUS 165 Tcp6RefreshNeighbor ( 166 IN TCP_CB *Tcb, 167 IN EFI_IP_ADDRESS *Neighbor, 168 IN UINT32 Timeout 169 ) 170 { 171 IP_IO *IpIo; 172 SOCKET *Sock; 173 TCP_PROTO_DATA *TcpProto; 174 175 if (NULL == Tcb) { 176 IpIo = NULL; 177 IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor); 178 179 if (IpIo == NULL) { 180 DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n")); 181 return EFI_NOT_STARTED; 182 } 183 184 } else { 185 Sock = Tcb->Sk; 186 TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved; 187 IpIo = TcpProto->TcpService->IpIo; 188 } 189 190 return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout); 191 } 192 193