1/** @file
2  Implement the IP4 driver support for the socket layer.
3
4  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
5  This program and the accompanying materials are licensed and made available
6  under the terms and conditions of the BSD License which accompanies this
7  distribution.  The full text of the license may be found at
8  http://opensource.org/licenses/bsd-license.php.
9
10  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12**/
13#include "Socket.h"
14
15
16/** Get the local socket address.
17
18  This routine returns the IPv4 address associated with the local
19  socket.
20
21  This routine is called by ::EslSocketGetLocalAddress to determine the
22  network address for the SOCK_RAW socket.
23
24  @param [in] pPort       Address of an ::ESL_PORT structure.
25  @param [out] pAddress   Network address to receive the local system address
26**/
27VOID
28EslIp4LocalAddressGet (
29  IN ESL_PORT * pPort,
30  OUT struct sockaddr * pAddress
31  )
32{
33  struct sockaddr_in * pLocalAddress;
34  ESL_IP4_CONTEXT * pIp4;
35
36  DBG_ENTER ( );
37
38  //  Return the local address
39  pIp4 = &pPort->Context.Ip4;
40  pLocalAddress = (struct sockaddr_in *)pAddress;
41  pLocalAddress->sin_family = AF_INET;
42  CopyMem ( &pLocalAddress->sin_addr,
43            &pIp4->ModeData.ConfigData.StationAddress.Addr[0],
44            sizeof ( pLocalAddress->sin_addr ));
45
46  DBG_EXIT ( );
47}
48
49
50/** Set the local port address.
51
52  This routine sets the local port address.
53
54  This support routine is called by ::EslSocketPortAllocate.
55
56  @param [in] pPort       Address of an ESL_PORT structure
57  @param [in] pSockAddr   Address of a sockaddr structure that contains the
58                          connection point on the local machine.  An IPv4 address
59                          of INADDR_ANY specifies that the connection is made to
60                          all of the network stacks on the platform.  Specifying a
61                          specific IPv4 address restricts the connection to the
62                          network stack supporting that address.  Specifying zero
63                          for the port causes the network layer to assign a port
64                          number from the dynamic range.  Specifying a specific
65                          port number causes the network layer to use that port.
66
67  @param [in] bBindTest   TRUE = run bind testing
68
69  @retval EFI_SUCCESS     The operation was successful
70 **/
71EFI_STATUS
72EslIp4LocalAddressSet (
73  IN ESL_PORT * pPort,
74  IN CONST struct sockaddr * pSockAddr,
75  IN BOOLEAN bBindTest
76  )
77{
78  EFI_IP4_CONFIG_DATA * pConfig;
79  CONST struct sockaddr_in * pIpAddress;
80  CONST UINT8 * pIpv4Address;
81  EFI_STATUS Status;
82
83  DBG_ENTER ( );
84
85  //  Validate the address
86  pIpAddress = (struct sockaddr_in *)pSockAddr;
87  if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
88    //  The local address must not be the broadcast address
89    Status = EFI_INVALID_PARAMETER;
90    pPort->pSocket->errno = EADDRNOTAVAIL;
91  }
92  else {
93    Status = EFI_SUCCESS;
94
95    //  Set the local address
96    pIpAddress = (struct sockaddr_in *)pSockAddr;
97    pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
98    pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
99    pConfig->StationAddress.Addr[0] = pIpv4Address[0];
100    pConfig->StationAddress.Addr[1] = pIpv4Address[1];
101    pConfig->StationAddress.Addr[2] = pIpv4Address[2];
102    pConfig->StationAddress.Addr[3] = pIpv4Address[3];
103
104    //  Determine if the default address is used
105    pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
106
107    //  Display the local address
108    DEBUG (( DEBUG_BIND,
109              "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",
110              pPort,
111              pConfig->StationAddress.Addr[0],
112              pConfig->StationAddress.Addr[1],
113              pConfig->StationAddress.Addr[2],
114              pConfig->StationAddress.Addr[3]));
115
116    //  Set the subnet mask
117    if ( pConfig->UseDefaultAddress ) {
118      pConfig->SubnetMask.Addr[0] = 0;
119      pConfig->SubnetMask.Addr[1] = 0;
120      pConfig->SubnetMask.Addr[2] = 0;
121      pConfig->SubnetMask.Addr[3] = 0;
122    }
123    else {
124      pConfig->SubnetMask.Addr[0] = 0xff;
125      pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
126      pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
127      pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
128    }
129  }
130  //  Return the operation status
131  DBG_EXIT_STATUS ( Status );
132  return Status;
133}
134
135
136/** Get the option value.
137
138  This routine handles the IPv4 level options.
139
140  The ::EslSocketOptionGet routine calls this routine to retrieve
141  the IPv4 options one at a time by name.
142
143  @param [in] pSocket           Address of an ::ESL_SOCKET structure
144  @param [in] OptionName        Name of the option
145  @param [out] ppOptionData     Buffer to receive address of option value
146  @param [out] pOptionLength    Buffer to receive the option length
147
148  @retval EFI_SUCCESS - Socket data successfully received
149 **/
150EFI_STATUS
151EslIp4OptionGet (
152  IN ESL_SOCKET * pSocket,
153  IN int OptionName,
154  OUT CONST void ** __restrict ppOptionData,
155  OUT socklen_t * __restrict pOptionLength
156  )
157{
158  EFI_STATUS Status;
159
160  DBG_ENTER ( );
161
162  //  Assume success
163  pSocket->errno = 0;
164  Status = EFI_SUCCESS;
165
166  //  Attempt to get the option
167  switch ( OptionName ) {
168  default:
169    //  Option not supported
170    pSocket->errno = ENOPROTOOPT;
171    Status = EFI_INVALID_PARAMETER;
172    break;
173
174  case IP_HDRINCL:
175    *ppOptionData = (void *)&pSocket->bIncludeHeader;
176    *pOptionLength = sizeof ( pSocket->bIncludeHeader );
177    break;
178  }
179  //  Return the operation status
180  DBG_EXIT_STATUS ( Status );
181  return Status;
182}
183
184
185/** Set the option value.
186
187  This routine handles the IPv4 level options.
188
189  The ::EslSocketOptionSet routine calls this routine to adjust
190  the IPv4 options one at a time by name.
191
192  @param [in] pSocket         Address of an ::ESL_SOCKET structure
193  @param [in] OptionName      Name of the option
194  @param [in] pOptionValue    Buffer containing the option value
195  @param [in] OptionLength    Length of the buffer in bytes
196
197  @retval EFI_SUCCESS - Option successfully set
198 **/
199EFI_STATUS
200EslIp4OptionSet (
201  IN ESL_SOCKET * pSocket,
202  IN int OptionName,
203  IN CONST void * pOptionValue,
204  IN socklen_t OptionLength
205  )
206{
207  BOOLEAN bTrueFalse;
208  //socklen_t LengthInBytes;
209  //UINT8 * pOptionData;
210  EFI_STATUS Status;
211
212  DBG_ENTER ( );
213
214  //  Assume success
215  pSocket->errno = 0;
216  Status = EFI_SUCCESS;
217
218  //  Determine if the option protocol matches
219  //LengthInBytes = 0;
220  //pOptionData = NULL;
221  switch ( OptionName ) {
222  default:
223    //  Protocol level not supported
224    DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));
225    pSocket->errno = ENOTSUP;
226    Status = EFI_UNSUPPORTED;
227    break;
228
229  case IP_HDRINCL:
230
231    //  Validate the option length
232    if ( sizeof ( UINT32 ) == OptionLength ) {
233      //  Restrict the input to TRUE or FALSE
234      bTrueFalse = TRUE;
235      if ( 0 == *(UINT32 *)pOptionValue ) {
236        bTrueFalse = FALSE;
237      }
238      pOptionValue = &bTrueFalse;
239
240      //  Set the option value
241      //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;
242      //LengthInBytes = sizeof ( pSocket->bIncludeHeader );
243    }
244    break;
245  }
246  //  Return the operation status
247  DBG_EXIT_STATUS ( Status );
248  return Status;
249}
250
251
252/**
253  Free a receive packet
254
255  This routine performs the network specific operations necessary
256  to free a receive packet.
257
258  This routine is called by ::EslSocketPortCloseTxDone to free a
259  receive packet.
260
261  @param [in] pPacket         Address of an ::ESL_PACKET structure.
262  @param [in, out] pRxBytes   Address of the count of RX bytes
263
264**/
265VOID
266EslIp4PacketFree (
267  IN ESL_PACKET * pPacket,
268  IN OUT size_t * pRxBytes
269  )
270{
271  EFI_IP4_RECEIVE_DATA * pRxData;
272  DBG_ENTER ( );
273
274  //
275  //  Account for the receive bytes
276  //
277  pRxData = pPacket->Op.Ip4Rx.pRxData;
278  *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;
279
280  //
281  //  Disconnect the buffer from the packet
282  //
283  pPacket->Op.Ip4Rx.pRxData = NULL;
284
285  //
286  //  Return the buffer to the IP4 driver
287  //
288  gBS->SignalEvent ( pRxData->RecycleSignal );
289  DBG_EXIT ( );
290}
291
292
293/**
294  Initialize the network specific portions of an ::ESL_PORT structure.
295
296  This routine initializes the network specific portions of an
297  ::ESL_PORT structure for use by the socket.
298
299  This support routine is called by ::EslSocketPortAllocate
300  to connect the socket with the underlying network adapter
301  running the IPv4 protocol.
302
303  @param [in] pPort       Address of an ESL_PORT structure
304  @param [in] DebugFlags  Flags for debug messages
305
306  @retval EFI_SUCCESS - Socket successfully created
307
308 **/
309EFI_STATUS
310EslIp4PortAllocate (
311  IN ESL_PORT * pPort,
312  IN UINTN DebugFlags
313  )
314{
315  EFI_IP4_CONFIG_DATA * pConfig;
316  ESL_SOCKET * pSocket;
317  EFI_STATUS Status;
318
319  DBG_ENTER ( );
320
321  //
322  //  Initialize the port
323  //
324  pSocket = pPort->pSocket;
325  pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );
326  pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );
327  pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );
328
329  //
330  //  Save the cancel, receive and transmit addresses
331  //
332  pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure;
333  pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;
334  pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll;
335  pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;
336  pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;
337
338  //
339  //  Set the configuration flags
340  //
341  pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
342  pConfig->AcceptIcmpErrors = FALSE;
343  pConfig->AcceptBroadcast = FALSE;
344  pConfig->AcceptPromiscuous = FALSE;
345  pConfig->TypeOfService = 0;
346  pConfig->TimeToLive = 255;
347  pConfig->DoNotFragment = FALSE;
348  pConfig->RawData = FALSE;
349  pConfig->ReceiveTimeout = 0;
350  pConfig->TransmitTimeout = 0;
351
352  //
353  //  Set the default protocol
354  //
355  pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;
356  pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );
357  Status = EFI_SUCCESS;
358
359  //
360  //  Return the operation status
361  //
362  DBG_EXIT_STATUS ( Status );
363  return Status;
364}
365
366
367/**
368  Receive data from a network connection.
369
370  This routine attempts to return buffered data to the caller.  The
371  data is removed from the urgent queue if the message flag MSG_OOB
372  is specified, otherwise data is removed from the normal queue.
373  See the \ref ReceiveEngine section.
374
375  This routine is called by ::EslSocketReceive to handle the network
376  specific receive operation to support SOCK_RAW sockets.
377
378  @param [in] pPort           Address of an ::ESL_PORT structure.
379
380  @param [in] pPacket         Address of an ::ESL_PACKET structure.
381
382  @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
383
384  @param [in] BufferLength    Length of the the buffer
385
386  @param [in] pBuffer         Address of a buffer to receive the data.
387
388  @param [in] pDataLength     Number of received data bytes in the buffer.
389
390  @param [out] pAddress       Network address to receive the remote system address
391
392  @param [out] pSkipBytes     Address to receive the number of bytes skipped
393
394  @return   Returns the address of the next free byte in the buffer.
395
396 **/
397UINT8 *
398EslIp4Receive (
399  IN ESL_PORT * pPort,
400  IN ESL_PACKET * pPacket,
401  IN BOOLEAN * pbConsumePacket,
402  IN size_t BufferLength,
403  IN UINT8 * pBuffer,
404  OUT size_t * pDataLength,
405  OUT struct sockaddr * pAddress,
406  OUT size_t * pSkipBytes
407  )
408{
409  size_t DataBytes;
410  size_t HeaderBytes;
411  size_t LengthInBytes;
412  struct sockaddr_in * pRemoteAddress;
413  EFI_IP4_RECEIVE_DATA * pRxData;
414
415  DBG_ENTER ( );
416
417  //
418  //  Return the remote system address if requested
419  //
420  pRxData = pPacket->Op.Ip4Rx.pRxData;
421  if ( NULL != pAddress ) {
422    //
423    //  Build the remote address
424    //
425    DEBUG (( DEBUG_RX,
426              "Getting packet remote address: %d.%d.%d.%d\r\n",
427              pRxData->Header->SourceAddress.Addr[0],
428              pRxData->Header->SourceAddress.Addr[1],
429              pRxData->Header->SourceAddress.Addr[2],
430              pRxData->Header->SourceAddress.Addr[3]));
431    pRemoteAddress = (struct sockaddr_in *)pAddress;
432    CopyMem ( &pRemoteAddress->sin_addr,
433              &pRxData->Header->SourceAddress.Addr[0],
434              sizeof ( pRemoteAddress->sin_addr ));
435  }
436
437  //
438  //  Copy the IP header
439  //
440  HeaderBytes = pRxData->HeaderLength;
441  if ( HeaderBytes > BufferLength ) {
442    HeaderBytes = BufferLength;
443  }
444  DEBUG (( DEBUG_RX,
445            "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
446            pRxData->Header,
447            pBuffer,
448            HeaderBytes ));
449  CopyMem ( pBuffer, pRxData->Header, HeaderBytes );
450  pBuffer += HeaderBytes;
451  LengthInBytes = HeaderBytes;
452
453  //
454  //  Copy the received data
455  //
456  if ( 0 < ( BufferLength - LengthInBytes )) {
457    pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
458                                              &pRxData->FragmentTable[0],
459                                              BufferLength - LengthInBytes,
460                                              pBuffer,
461                                              &DataBytes );
462    LengthInBytes += DataBytes;
463  }
464
465  //
466  //  Determine if the data is being read
467  //
468  if ( *pbConsumePacket ) {
469    //
470    //  Display for the bytes consumed
471    //
472    DEBUG (( DEBUG_RX,
473              "0x%08x: Port account for 0x%08x bytes\r\n",
474              pPort,
475              LengthInBytes ));
476
477    //
478    //  Account for any discarded data
479    //
480    *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;
481  }
482
483  //
484  //  Return the data length and the buffer address
485  //
486  *pDataLength = LengthInBytes;
487  DBG_EXIT_HEX ( pBuffer );
488  return pBuffer;
489}
490
491
492/**
493  Get the remote socket address
494
495  This routine returns the address of the remote connection point
496  associated with the SOCK_RAW socket.
497
498  This routine is called by ::EslSocketGetPeerAddress to detemine
499  the IPv4 address associated with the network adapter.
500
501  @param [in] pPort       Address of an ::ESL_PORT structure.
502
503  @param [out] pAddress   Network address to receive the remote system address
504
505**/
506VOID
507EslIp4RemoteAddressGet (
508  IN ESL_PORT * pPort,
509  OUT struct sockaddr * pAddress
510  )
511{
512  struct sockaddr_in * pRemoteAddress;
513  ESL_IP4_CONTEXT * pIp4;
514
515  DBG_ENTER ( );
516
517  //
518  //  Return the remote address
519  //
520  pIp4 = &pPort->Context.Ip4;
521  pRemoteAddress = (struct sockaddr_in *)pAddress;
522  pRemoteAddress->sin_family = AF_INET;
523  CopyMem ( &pRemoteAddress->sin_addr,
524            &pIp4->DestinationAddress.Addr[0],
525            sizeof ( pRemoteAddress->sin_addr ));
526
527  DBG_EXIT ( );
528}
529
530
531/**
532  Set the remote address
533
534  This routine sets the remote address in the port.
535
536  This routine is called by ::EslSocketConnect to specify the
537  remote network address.
538
539  @param [in] pPort           Address of an ::ESL_PORT structure.
540
541  @param [in] pSockAddr       Network address of the remote system.
542
543  @param [in] SockAddrLength  Length in bytes of the network address.
544
545  @retval EFI_SUCCESS     The operation was successful
546
547 **/
548EFI_STATUS
549EslIp4RemoteAddressSet (
550  IN ESL_PORT * pPort,
551  IN CONST struct sockaddr * pSockAddr,
552  IN socklen_t SockAddrLength
553  )
554{
555  ESL_IP4_CONTEXT * pIp4;
556  CONST struct sockaddr_in * pRemoteAddress;
557  EFI_STATUS Status;
558
559  DBG_ENTER ( );
560
561  //
562  //  Set the remote address
563  //
564  pIp4 = &pPort->Context.Ip4;
565  pRemoteAddress = (struct sockaddr_in *)pSockAddr;
566  pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
567  pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
568  pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
569  pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
570  pPort->pSocket->bAddressSet = TRUE;
571  Status = EFI_SUCCESS;
572
573  //
574  //  Return the operation status
575  //
576  DBG_EXIT_STATUS ( Status );
577  return Status;
578}
579
580
581/**
582  Process the receive completion
583
584  This routine keeps the IPv4 driver's buffer and queues it in
585  in FIFO order to the data queue.  The IP4 driver's buffer will
586  be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
587  See the \ref ReceiveEngine section.
588
589  This routine is called by the IPv4 driver when data is
590  received.
591
592  @param [in] Event     The receive completion event
593
594  @param [in] pIo       The address of an ::ESL_IO_MGMT structure
595
596**/
597VOID
598EslIp4RxComplete (
599  IN EFI_EVENT Event,
600  IN ESL_IO_MGMT * pIo
601  )
602{
603  size_t LengthInBytes;
604  ESL_PACKET * pPacket;
605  EFI_IP4_RECEIVE_DATA * pRxData;
606  EFI_STATUS Status;
607
608  DBG_ENTER ( );
609
610  //
611  //  Get the operation status.
612  //
613  Status = pIo->Token.Ip4Rx.Status;
614
615  //
616  //  Get the packet length
617  //
618  pRxData = pIo->Token.Ip4Rx.Packet.RxData;
619  LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;
620
621  //{{
622  //      +--------------------+   +----------------------+
623  //      | ESL_IO_MGMT        |   |      Data Buffer     |
624  //      |                    |   |     (Driver owned)   |
625  //      |    +---------------+   +----------------------+
626  //      |    | Token         |               ^
627  //      |    |      Rx Event |               |
628  //      |    |               |   +----------------------+
629  //      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |
630  //      +----+---------------+   |    (Driver owned)    |
631  //                               +----------------------+
632  //      +--------------------+               ^
633  //      | ESL_PACKET         |               .
634  //      |                    |               .
635  //      |    +---------------+               .
636  //      |    |       pRxData --> NULL  .......
637  //      +----+---------------+
638  //
639  //
640  //  Save the data in the packet
641  //}}
642  pPacket = pIo->pPacket;
643  pPacket->Op.Ip4Rx.pRxData = pRxData;
644
645  //
646  //  Complete this request
647  //
648  EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
649  DBG_EXIT ( );
650}
651
652
653/**
654  Determine if the socket is configured.
655
656  This routine uses the flag ESL_SOCKET::bConfigured to determine
657  if the network layer's configuration routine has been called.
658  This routine calls the ::EslSocketBind and configuration routines
659  if they were not already called.  After the port is configured,
660  the \ref ReceiveEngine is started.
661
662  This routine is called by EslSocketIsConfigured to verify
663  that the socket is configured.
664
665  @param [in] pSocket         Address of an ::ESL_SOCKET structure
666
667  @retval EFI_SUCCESS - The port is connected
668  @retval EFI_NOT_STARTED - The port is not connected
669
670 **/
671 EFI_STATUS
672 EslIp4SocketIsConfigured (
673  IN ESL_SOCKET * pSocket
674  )
675{
676  UINTN Index;
677  ESL_PORT * pPort;
678  ESL_PORT * pNextPort;
679  ESL_IP4_CONTEXT * pIp4;
680  EFI_IP4_PROTOCOL * pIp4Protocol;
681  EFI_STATUS Status;
682  struct sockaddr_in LocalAddress;
683
684  DBG_ENTER ( );
685
686  //
687  //  Assume success
688  //
689  Status = EFI_SUCCESS;
690
691  //
692  //  Configure the port if necessary
693  //
694  if ( !pSocket->bConfigured ) {
695    //
696    //  Fill in the port list if necessary
697    //
698    pSocket->errno = ENETDOWN;
699    if ( NULL == pSocket->pPortList ) {
700      LocalAddress.sin_len = sizeof ( LocalAddress );
701      LocalAddress.sin_family = AF_INET;
702      LocalAddress.sin_addr.s_addr = 0;
703      LocalAddress.sin_port = 0;
704      Status = EslSocketBind ( &pSocket->SocketProtocol,
705                               (struct sockaddr *)&LocalAddress,
706                               LocalAddress.sin_len,
707                               &pSocket->errno );
708    }
709
710    //
711    //  Walk the port list
712    //
713    pPort = pSocket->pPortList;
714    while ( NULL != pPort ) {
715      //
716      //  Update the raw setting
717      //
718      pIp4 = &pPort->Context.Ip4;
719      if ( pSocket->bIncludeHeader ) {
720        //
721        //  IP header will be included with the data on transmit
722        //
723        pIp4->ModeData.ConfigData.RawData = TRUE;
724      }
725
726      //
727      //  Attempt to configure the port
728      //
729      pNextPort = pPort->pLinkSocket;
730      pIp4Protocol = pPort->pProtocol.IPv4;
731      DEBUG (( DEBUG_TX,
732                "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
733                          pPort,
734                          pIp4->ModeData.ConfigData.StationAddress.Addr[0],
735                          pIp4->ModeData.ConfigData.StationAddress.Addr[1],
736                          pIp4->ModeData.ConfigData.StationAddress.Addr[2],
737                          pIp4->ModeData.ConfigData.StationAddress.Addr[3],
738                          pIp4->DestinationAddress.Addr[0],
739                          pIp4->DestinationAddress.Addr[1],
740                          pIp4->DestinationAddress.Addr[2],
741                          pIp4->DestinationAddress.Addr[3]));
742      Status = pIp4Protocol->Configure ( pIp4Protocol,
743                                          &pIp4->ModeData.ConfigData );
744      if ( !EFI_ERROR ( Status )) {
745        //
746        //  Update the configuration data
747        //
748        Status = pIp4Protocol->GetModeData ( pIp4Protocol,
749                                             &pIp4->ModeData,
750                                             NULL,
751                                             NULL );
752      }
753      if ( EFI_ERROR ( Status )) {
754        if ( !pSocket->bConfigured ) {
755          DEBUG (( DEBUG_LISTEN,
756                    "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
757                    Status ));
758          switch ( Status ) {
759          case EFI_ACCESS_DENIED:
760            pSocket->errno = EACCES;
761            break;
762
763          default:
764          case EFI_DEVICE_ERROR:
765            pSocket->errno = EIO;
766            break;
767
768          case EFI_INVALID_PARAMETER:
769            pSocket->errno = EADDRNOTAVAIL;
770            break;
771
772          case EFI_NO_MAPPING:
773            pSocket->errno = EAFNOSUPPORT;
774            break;
775
776          case EFI_OUT_OF_RESOURCES:
777            pSocket->errno = ENOBUFS;
778            break;
779
780          case EFI_UNSUPPORTED:
781            pSocket->errno = EOPNOTSUPP;
782            break;
783          }
784        }
785      }
786      else {
787        DEBUG (( DEBUG_TX,
788                  "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
789                  pPort,
790                  pIp4->ModeData.ConfigData.StationAddress.Addr[0],
791                  pIp4->ModeData.ConfigData.StationAddress.Addr[1],
792                  pIp4->ModeData.ConfigData.StationAddress.Addr[2],
793                  pIp4->ModeData.ConfigData.StationAddress.Addr[3],
794                  pIp4->DestinationAddress.Addr[0],
795                  pIp4->DestinationAddress.Addr[1],
796                  pIp4->DestinationAddress.Addr[2],
797                  pIp4->DestinationAddress.Addr[3]));
798        DEBUG (( DEBUG_TX,
799                  "Subnet Mask: %d.%d.%d.%d\r\n",
800                  pIp4->ModeData.ConfigData.SubnetMask.Addr[0],
801                  pIp4->ModeData.ConfigData.SubnetMask.Addr[1],
802                  pIp4->ModeData.ConfigData.SubnetMask.Addr[2],
803                  pIp4->ModeData.ConfigData.SubnetMask.Addr[3]));
804        DEBUG (( DEBUG_TX,
805                  "Route Count: %d\r\n",
806                  pIp4->ModeData.RouteCount ));
807        for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) {
808          if ( 0 == Index ) {
809            DEBUG (( DEBUG_TX, "Route Table:\r\n" ));
810          }
811          DEBUG (( DEBUG_TX,
812                    "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
813                    Index,
814                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0],
815                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1],
816                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2],
817                    pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3],
818                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0],
819                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1],
820                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2],
821                    pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3],
822                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0],
823                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1],
824                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2],
825                    pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3]));
826        }
827        pPort->bConfigured = TRUE;
828        pSocket->bConfigured = TRUE;
829
830        //
831        //  Start the first read on the port
832        //
833        EslSocketRxStart ( pPort );
834
835        //
836        //  The socket is connected
837        //
838        pSocket->State = SOCKET_STATE_CONNECTED;
839        pSocket->errno = 0;
840      }
841
842      //
843      //  Set the next port
844      //
845      pPort = pNextPort;
846    }
847  }
848
849  //
850  //  Determine the socket configuration status
851  //
852  Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
853
854  //
855  //  Return the port connected state.
856  //
857  DBG_EXIT_STATUS ( Status );
858  return Status;
859}
860
861
862/**
863  Buffer data for transmission over a network connection.
864
865  This routine buffers data for the transmit engine in the normal
866  data queue.  When the \ref TransmitEngine has resources, this
867  routine will start the transmission of the next buffer on the
868  network connection.
869
870  This routine is called by ::EslSocketTransmit to buffer
871  data for transmission.  The data is copied into a local buffer
872  freeing the application buffer for reuse upon return.  When
873  necessary, this routine starts the transmit engine that
874  performs the data transmission on the network connection.  The
875  transmit engine transmits the data a packet at a time over the
876  network connection.
877
878  Transmission errors are returned during the next transmission or
879  during the close operation.  Only buffering errors are returned
880  during the current transmission attempt.
881
882  @param [in] pSocket         Address of an ::ESL_SOCKET structure
883
884  @param [in] Flags           Message control flags
885
886  @param [in] BufferLength    Length of the the buffer
887
888  @param [in] pBuffer         Address of a buffer to receive the data.
889
890  @param [in] pDataLength     Number of received data bytes in the buffer.
891
892  @param [in] pAddress        Network address of the remote system address
893
894  @param [in] AddressLength   Length of the remote network address structure
895
896  @retval EFI_SUCCESS - Socket data successfully buffered
897
898**/
899EFI_STATUS
900EslIp4TxBuffer (
901  IN ESL_SOCKET * pSocket,
902  IN int Flags,
903  IN size_t BufferLength,
904  IN CONST UINT8 * pBuffer,
905  OUT size_t * pDataLength,
906  IN const struct sockaddr * pAddress,
907  IN socklen_t AddressLength
908  )
909{
910  ESL_PACKET * pPacket;
911  ESL_PACKET * pPreviousPacket;
912  ESL_PORT * pPort;
913  const struct sockaddr_in * pRemoteAddress;
914  ESL_IP4_CONTEXT * pIp4;
915  size_t * pTxBytes;
916  ESL_IP4_TX_DATA * pTxData;
917  EFI_STATUS Status;
918  EFI_TPL TplPrevious;
919
920  DBG_ENTER ( );
921
922  //
923  //  Assume failure
924  //
925  Status = EFI_UNSUPPORTED;
926  pSocket->errno = ENOTCONN;
927  *pDataLength = 0;
928
929  //
930  //  Verify that the socket is connected
931  //
932  if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
933    //
934    //  Verify that there is enough room to buffer another
935    //  transmit operation
936    //
937    pTxBytes = &pSocket->TxBytes;
938    if ( pSocket->MaxTxBuf > *pTxBytes ) {
939      //
940      //  Locate the port
941      //
942      pPort = pSocket->pPortList;
943      while ( NULL != pPort ) {
944        //
945        //  Determine the queue head
946        //
947        pIp4 = &pPort->Context.Ip4;
948
949        //
950        //  Attempt to allocate the packet
951        //
952        Status = EslSocketPacketAllocate ( &pPacket,
953                                           sizeof ( pPacket->Op.Ip4Tx )
954                                           - sizeof ( pPacket->Op.Ip4Tx.Buffer )
955                                           + BufferLength,
956                                           0,
957                                           DEBUG_TX );
958        if ( !EFI_ERROR ( Status )) {
959          //
960          //  Initialize the transmit operation
961          //
962          pTxData = &pPacket->Op.Ip4Tx;
963          pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0];
964          pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1];
965          pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2];
966          pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3];
967          pTxData->TxData.OverrideData = NULL;
968          pTxData->TxData.OptionsLength = 0;
969          pTxData->TxData.OptionsBuffer = NULL;
970          pTxData->TxData.TotalDataLength = (UINT32) BufferLength;
971          pTxData->TxData.FragmentCount = 1;
972          pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;
973          pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0];
974
975          //
976          //  Set the remote system address if necessary
977          //
978          if ( NULL != pAddress ) {
979            pRemoteAddress = (const struct sockaddr_in *)pAddress;
980            pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0];
981            pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1];
982            pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2];
983            pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3];
984            pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;
985            pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
986            pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
987            pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
988            pTxData->Override.GatewayAddress.Addr[0] = 0;
989            pTxData->Override.GatewayAddress.Addr[1] = 0;
990            pTxData->Override.GatewayAddress.Addr[2] = 0;
991            pTxData->Override.GatewayAddress.Addr[3] = 0;
992            pTxData->Override.Protocol = (UINT8)pSocket->Protocol;
993            pTxData->Override.TypeOfService = 0;
994            pTxData->Override.TimeToLive = 255;
995            pTxData->Override.DoNotFragment = FALSE;
996
997            //
998            //  Use the remote system address when sending this packet
999            //
1000            pTxData->TxData.OverrideData = &pTxData->Override;
1001          }
1002
1003          //
1004          //  Copy the data into the buffer
1005          //
1006          CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0],
1007                    pBuffer,
1008                    BufferLength );
1009
1010          //
1011          //  Synchronize with the socket layer
1012          //
1013          RAISE_TPL ( TplPrevious, TPL_SOCKETS );
1014
1015          //
1016          //  Display the request
1017          //
1018          DEBUG (( DEBUG_TX,
1019                    "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
1020                    BufferLength,
1021                    pBuffer,
1022                    pIp4->ModeData.ConfigData.StationAddress.Addr[0],
1023                    pIp4->ModeData.ConfigData.StationAddress.Addr[1],
1024                    pIp4->ModeData.ConfigData.StationAddress.Addr[2],
1025                    pIp4->ModeData.ConfigData.StationAddress.Addr[3],
1026                    pTxData->TxData.DestinationAddress.Addr[0],
1027                    pTxData->TxData.DestinationAddress.Addr[1],
1028                    pTxData->TxData.DestinationAddress.Addr[2],
1029                    pTxData->TxData.DestinationAddress.Addr[3]));
1030
1031          //
1032          //  Queue the data for transmission
1033          //
1034          pPacket->pNext = NULL;
1035          pPreviousPacket = pSocket->pTxPacketListTail;
1036          if ( NULL == pPreviousPacket ) {
1037            pSocket->pTxPacketListHead = pPacket;
1038          }
1039          else {
1040            pPreviousPacket->pNext = pPacket;
1041          }
1042          pSocket->pTxPacketListTail = pPacket;
1043          DEBUG (( DEBUG_TX,
1044                    "0x%08x: Packet on transmit list\r\n",
1045                    pPacket ));
1046
1047          //
1048          //  Account for the buffered data
1049          //
1050          *pTxBytes += BufferLength;
1051          *pDataLength = BufferLength;
1052
1053          //
1054          //  Start the transmit engine if it is idle
1055          //
1056          if ( NULL != pPort->pTxFree ) {
1057            EslSocketTxStart ( pPort,
1058                               &pSocket->pTxPacketListHead,
1059                               &pSocket->pTxPacketListTail,
1060                               &pPort->pTxActive,
1061                               &pPort->pTxFree );
1062
1063            //
1064            //  Ignore any transmit error
1065            //
1066            if ( EFI_ERROR ( pSocket->TxError )) {
1067              DEBUG (( DEBUG_TX,
1068                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
1069                       pPort,
1070                       pPacket,
1071                       pSocket->TxError ));
1072            }
1073            pSocket->TxError = EFI_SUCCESS;
1074          }
1075
1076          //
1077          //  Release the socket layer synchronization
1078          //
1079          RESTORE_TPL ( TplPrevious );
1080        }
1081        else {
1082          //
1083          //  Packet allocation failed
1084          //
1085          pSocket->errno = ENOMEM;
1086          break;
1087        }
1088
1089        //
1090        //  Set the next port
1091        //
1092        pPort = pPort->pLinkSocket;
1093      }
1094    }
1095    else {
1096      //
1097      //  Not enough buffer space available
1098      //
1099      pSocket->errno = EAGAIN;
1100      Status = EFI_NOT_READY;
1101    }
1102  }
1103
1104  //
1105  //  Return the operation status
1106  //
1107  DBG_EXIT_STATUS ( Status );
1108  return Status;
1109}
1110
1111
1112/**
1113  Process the transmit completion
1114
1115  This routine use ::EslSocketTxComplete to perform the transmit
1116  completion processing for data packets.
1117
1118  This routine is called by the IPv4 network layer when a data
1119  transmit request completes.
1120
1121  @param [in] Event     The normal transmit completion event
1122
1123  @param [in] pIo       The address of an ::ESL_IO_MGMT structure
1124
1125**/
1126VOID
1127EslIp4TxComplete (
1128  IN EFI_EVENT Event,
1129  IN ESL_IO_MGMT * pIo
1130  )
1131{
1132  UINT32 LengthInBytes;
1133  ESL_PORT * pPort;
1134  ESL_PACKET * pPacket;
1135  ESL_SOCKET * pSocket;
1136  EFI_STATUS Status;
1137
1138  DBG_ENTER ( );
1139
1140  //
1141  //  Locate the active transmit packet
1142  //
1143  pPacket = pIo->pPacket;
1144  pPort = pIo->pPort;
1145  pSocket = pPort->pSocket;
1146
1147  //
1148  //  Get the transmit length and status
1149  //
1150  LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength;
1151  pSocket->TxBytes -= LengthInBytes;
1152  Status = pIo->Token.Ip4Tx.Status;
1153
1154  //
1155  //  Ignore the transmit error
1156  //
1157  if ( EFI_ERROR ( Status )) {
1158    DEBUG (( DEBUG_TX,
1159             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1160             pPort,
1161             pPacket,
1162             Status ));
1163    Status = EFI_SUCCESS;
1164  }
1165
1166  //
1167  //  Complete the transmit operation
1168  //
1169  EslSocketTxComplete ( pIo,
1170                        LengthInBytes,
1171                        Status,
1172                        "Raw ",
1173                        &pSocket->pTxPacketListHead,
1174                        &pSocket->pTxPacketListTail,
1175                        &pPort->pTxActive,
1176                        &pPort->pTxFree );
1177  DBG_EXIT ( );
1178}
1179
1180
1181/**
1182  Verify the adapter's IP address
1183
1184  This support routine is called by EslSocketBindTest.
1185
1186  @param [in] pPort       Address of an ::ESL_PORT structure.
1187  @param [in] pConfigData Address of the configuration data
1188
1189  @retval EFI_SUCCESS - The IP address is valid
1190  @retval EFI_NOT_STARTED - The IP address is invalid
1191
1192 **/
1193EFI_STATUS
1194EslIp4VerifyLocalIpAddress (
1195  IN ESL_PORT * pPort,
1196  IN EFI_IP4_CONFIG_DATA * pConfigData
1197  )
1198{
1199  UINTN DataSize;
1200  EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;
1201  EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;
1202  ESL_SERVICE * pService;
1203  EFI_STATUS Status;
1204
1205  DBG_ENTER ( );
1206
1207  //
1208  //  Use break instead of goto
1209  //
1210  pIfInfo = NULL;
1211  for ( ; ; ) {
1212    //
1213    //  Determine if the IP address is specified
1214    //
1215    DEBUG (( DEBUG_BIND,
1216              "UseDefaultAddress: %s\r\n",
1217              pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));
1218    DEBUG (( DEBUG_BIND,
1219              "Requested IP address: %d.%d.%d.%d\r\n",
1220              pConfigData->StationAddress.Addr [ 0 ],
1221              pConfigData->StationAddress.Addr [ 1 ],
1222              pConfigData->StationAddress.Addr [ 2 ],
1223              pConfigData->StationAddress.Addr [ 3 ]));
1224    if ( pConfigData->UseDefaultAddress
1225      || (( 0 == pConfigData->StationAddress.Addr [ 0 ])
1226      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])
1227      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])
1228      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))
1229    {
1230      Status = EFI_SUCCESS;
1231      break;
1232    }
1233
1234    //
1235    //  Open the configuration protocol
1236    //
1237    pService = pPort->pService;
1238    Status = gBS->OpenProtocol (
1239                    pService->Controller,
1240                    &gEfiIp4Config2ProtocolGuid,
1241                    (VOID **)&pIpConfig2Protocol,
1242                    NULL,
1243                    NULL,
1244                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
1245                    );
1246    if ( EFI_ERROR ( Status )) {
1247      DEBUG (( DEBUG_ERROR,
1248                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1249                Status ));
1250      break;
1251    }
1252
1253    //
1254    // Get the interface information size.
1255    //
1256    DataSize = 0;
1257    Status = pIpConfig2Protocol->GetData (
1258                                   pIpConfig2Protocol,
1259                                   Ip4Config2DataTypeInterfaceInfo,
1260                                   &DataSize,
1261                                   NULL
1262                                   );
1263    if ( EFI_BUFFER_TOO_SMALL != Status ) {
1264      DEBUG (( DEBUG_ERROR,
1265                "ERROR - Failed to get the interface information size, Status: %r\r\n",
1266                Status ));
1267      break;
1268    }
1269
1270    //
1271    //  Allocate the interface information buffer
1272    //
1273    pIfInfo = AllocatePool ( DataSize );
1274    if ( NULL == pIfInfo ) {
1275      DEBUG (( DEBUG_ERROR,
1276                "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
1277      Status = EFI_OUT_OF_RESOURCES;
1278      break;
1279    }
1280
1281    //
1282    // Get the interface info.
1283    //
1284    Status = pIpConfig2Protocol->GetData (
1285                                  pIpConfig2Protocol,
1286                                  Ip4Config2DataTypeInterfaceInfo,
1287                                  &DataSize,
1288                                  pIfInfo
1289                                  );
1290    if ( EFI_ERROR ( Status )) {
1291      DEBUG (( DEBUG_ERROR,
1292                "ERROR - Failed to return the interface info, Status: %r\r\n",
1293                Status ));
1294      break;
1295    }
1296
1297    //
1298    //  Display the current configuration
1299    //
1300    DEBUG (( DEBUG_BIND,
1301              "Actual adapter IP address: %d.%d.%d.%d\r\n",
1302              pIfInfo->StationAddress.Addr [ 0 ],
1303              pIfInfo->StationAddress.Addr [ 1 ],
1304              pIfInfo->StationAddress.Addr [ 2 ],
1305              pIfInfo->StationAddress.Addr [ 3 ]));
1306
1307    //
1308    //  Assume the port is not configured
1309    //
1310    Status = EFI_SUCCESS;
1311    if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])
1312      && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])
1313      && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])
1314      && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {
1315      break;
1316    }
1317
1318    //
1319    //  The IP address did not match
1320    //
1321    Status = EFI_NOT_STARTED;
1322    break;
1323  }
1324
1325  //
1326  //  Free the buffer if necessary
1327  //
1328  if ( NULL != pIfInfo ) {
1329    FreePool ( pIfInfo );
1330  }
1331
1332  //
1333  //  Return the IP address status
1334  //
1335  DBG_EXIT_STATUS ( Status );
1336  return Status;
1337}
1338
1339
1340/**
1341  Interface between the socket layer and the network specific
1342  code that supports SOCK_RAW sockets over IPv4.
1343**/
1344CONST ESL_PROTOCOL_API cEslIp4Api = {
1345  "IPv4",
1346    IPPROTO_IP,
1347  OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ),
1348  OFFSET_OF ( ESL_LAYER, pIp4List ),
1349  OFFSET_OF ( struct sockaddr_in, sin_zero ),
1350  sizeof ( struct sockaddr_in ),
1351  AF_INET,
1352  sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
1353  sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
1354  OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),
1355  FALSE,
1356  EADDRNOTAVAIL,
1357  NULL,   //  Accept
1358  NULL,   //  ConnectPoll
1359  NULL,   //  ConnectStart
1360  EslIp4SocketIsConfigured,
1361  EslIp4LocalAddressGet,
1362  EslIp4LocalAddressSet,
1363  NULL,   //  Listen
1364  EslIp4OptionGet,
1365  EslIp4OptionSet,
1366  EslIp4PacketFree,
1367  EslIp4PortAllocate,
1368  NULL,   //  PortClose
1369  NULL,   //  PortCloseOp
1370  TRUE,
1371  EslIp4Receive,
1372  EslIp4RemoteAddressGet,
1373  EslIp4RemoteAddressSet,
1374  EslIp4RxComplete,
1375  NULL,   //  RxStart
1376  EslIp4TxBuffer,
1377  EslIp4TxComplete,
1378  NULL,   //  TxOobComplete
1379  (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress
1380};
1381