1 /** @file
2   This library is only intended to be used by UEFI network stack modules.
3   It provides the combined IpIo layer on the EFI IP4 Protocol and EFI IP6 protocol.
4 
5 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #ifndef _IP_IO_H_
11 #define _IP_IO_H_
12 
13 #include <Protocol/Ip4.h>
14 #include <Protocol/Ip6.h>
15 
16 #include <Library/NetLib.h>
17 
18 //
19 // type and code define for ICMP protocol error
20 // from IP
21 //
22 #define ICMP_TYPE_UNREACH              3
23 #define ICMP_TYPE_TIMXCEED             11
24 #define ICMP_TYPE_PARAMPROB            12
25 #define ICMP_TYPE_SOURCEQUENCH         4
26 
27 #define ICMP_CODE_UNREACH_NET          0
28 #define ICMP_CODE_UNREACH_HOST         1
29 #define ICMP_CODE_UNREACH_PROTOCOL     2
30 #define ICMP_CODE_UNREACH_PORT         3
31 #define ICMP_CODE_UNREACH_NEEDFRAG     4
32 #define ICMP_CODE_UNREACH_SRCFAIL      5
33 #define ICMP_CODE_UNREACH_NET_UNKNOWN  6
34 #define ICMP_CODE_UNREACH_HOST_UNKNOWN 7
35 #define ICMP_CODE_UNREACH_ISOLATED     8
36 #define ICMP_CODE_UNREACH_NET_PROHIB   9
37 #define ICMP_CODE_UNREACH_HOST_PROHIB  10
38 #define ICMP_CODE_UNREACH_TOSNET       11
39 #define ICMP_CODE_UNREACH_TOSHOST      12
40 
41 /**
42   Get the IP header length from the struct EFI_IP4_HEADER. HeaderLength is
43   Internet header length in 32-bit words, so HeaderLength<<2 is the real
44   length of IP header.
45 
46   @param[out] HdrPtr   A pointer to EFI_IP4_HEADER.
47 
48   @return The IP header length.
49 **/
50 #define EFI_IP4_HEADER_LEN(HdrPtr) ((HdrPtr)->HeaderLength << 2)
51 
52 /**
53   To types of ICMP error which consist of ICMP header, IP header and original
54   datagram's data, get length from sum of ICMP header length, IP header length
55   and first 64 bits of datagram's data length.
56 
57   @param[in] IpHdr   A pointer to EFI_IP4_HEADER.
58 
59   @return The ICMP error length.
60 **/
61 #define ICMP_ERRLEN(IpHdr) \
62   (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)
63 
64 /**
65   Get the packet header from NET_BUF.
66 
67   @param[out]  Buf    A pointer to NET_BUF.
68   @param[in]   Type   Header type.
69 
70   @return The pointer to packet header.
71 **/
72 #define NET_PROTO_HDR(Buf, Type)  ((Type *) ((Buf)->BlockOp[0].Head))
73 
74 
75 extern EFI_IP4_CONFIG_DATA  mIp4IoDefaultIpConfigData;
76 extern EFI_IP6_CONFIG_DATA  mIp6IoDefaultIpConfigData;
77 
78 
79 ///
80 /// This error will be delivered to the
81 /// listening transportation layer protocol
82 /// that consumes IpIO.
83 ///
84 
85 #define  ICMP_ERR_UNREACH_NET           0
86 #define  ICMP_ERR_UNREACH_HOST          1
87 #define  ICMP_ERR_UNREACH_PROTOCOL      2
88 #define  ICMP_ERR_UNREACH_PORT          3
89 #define  ICMP_ERR_MSGSIZE               4
90 #define  ICMP_ERR_UNREACH_SRCFAIL       5
91 #define  ICMP_ERR_TIMXCEED_INTRANS      6
92 #define  ICMP_ERR_TIMXCEED_REASS        7
93 #define  ICMP_ERR_QUENCH                8
94 #define  ICMP_ERR_PARAMPROB             9
95 
96 #define  ICMP6_ERR_UNREACH_NET          0
97 #define  ICMP6_ERR_UNREACH_HOST         1
98 #define  ICMP6_ERR_UNREACH_PROTOCOL     2
99 #define  ICMP6_ERR_UNREACH_PORT         3
100 #define  ICMP6_ERR_PACKAGE_TOOBIG       4
101 #define  ICMP6_ERR_TIMXCEED_HOPLIMIT    5
102 #define  ICMP6_ERR_TIMXCEED_REASS       6
103 #define  ICMP6_ERR_PARAMPROB_HEADER     7
104 #define  ICMP6_ERR_PARAMPROB_NEXHEADER  8
105 #define  ICMP6_ERR_PARAMPROB_IPV6OPTION 9
106 
107 ///
108 /// The helper struct for IpIoGetIcmpErrStatus(). It is for internal use only.
109 ///
110 typedef struct {
111   BOOLEAN                   IsHard;
112   BOOLEAN                   Notify;
113 } ICMP_ERROR_INFO;
114 
115 typedef union {
116   EFI_IP4_COMPLETION_TOKEN  Ip4Token;
117   EFI_IP6_COMPLETION_TOKEN  Ip6Token;
118 } IP_IO_IP_COMPLETION_TOKEN;
119 
120 typedef union {
121   EFI_IP4_TRANSMIT_DATA     Ip4TxData;
122   EFI_IP6_TRANSMIT_DATA     Ip6TxData;
123 } IP_IO_IP_TX_DATA;
124 
125 typedef union {
126   EFI_IP4_RECEIVE_DATA      Ip4RxData;
127   EFI_IP6_RECEIVE_DATA      Ip6RxData;
128 } IP_IO_IP_RX_DATA;
129 
130 typedef union {
131   EFI_IP4_OVERRIDE_DATA     Ip4OverrideData;
132   EFI_IP6_OVERRIDE_DATA     Ip6OverrideData;
133 } IP_IO_OVERRIDE;
134 
135 typedef union {
136   EFI_IP4_CONFIG_DATA       Ip4CfgData;
137   EFI_IP6_CONFIG_DATA       Ip6CfgData;
138 } IP_IO_IP_CONFIG_DATA;
139 
140 typedef union {
141   EFI_IP4_HEADER            *Ip4Hdr;
142   EFI_IP6_HEADER            *Ip6Hdr;
143 } IP_IO_IP_HEADER;
144 
145 typedef union {
146   IP4_ADDR                  SubnetMask;
147   UINT8                     PrefixLength;
148 } IP_IO_IP_MASK;
149 
150 typedef union {
151   EFI_IP4_PROTOCOL  *Ip4;
152   EFI_IP6_PROTOCOL  *Ip6;
153 } IP_IO_IP_PROTOCOL;
154 
155 ///
156 /// The IP session for an IP receive packet.
157 ///
158 typedef struct _EFI_NET_SESSION_DATA {
159   EFI_IP_ADDRESS        Source;     ///< Source IP of the received packet.
160   EFI_IP_ADDRESS        Dest;       ///< Destination IP of the received packet.
161   IP_IO_IP_HEADER       IpHdr;      ///< IP header of the received packet.
162   UINT32                IpHdrLen;   ///< IP header length of the received packet.
163                                     ///< For IPv6, it includes the IP6 header
164                                     ///< length and extension header length. For
165                                     ///< IPv4, it includes the IP4 header length
166                                     ///< and options length.
167   UINT8                 IpVersion;  ///< The IP version of the received packet.
168 } EFI_NET_SESSION_DATA;
169 
170 /**
171   The prototype is called back when an IP packet is received.
172 
173   @param[in] Status        The result of the receive request.
174   @param[in] IcmpErr       Valid when Status is EFI_ICMP_ERROR.
175   @param[in] NetSession    The IP session for the received packet.
176   @param[in] Pkt           The packet received.
177   @param[in] Context       The data provided by the user for the received packet when
178                            the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
179 
180 **/
181 typedef
182 VOID
183 (EFIAPI *PKT_RCVD_NOTIFY) (
184   IN EFI_STATUS           Status,
185   IN UINT8                IcmpErr,
186   IN EFI_NET_SESSION_DATA *NetSession,
187   IN NET_BUF              *Pkt,
188   IN VOID                 *Context
189   );
190 
191 /**
192   The prototype is called back when an IP packet is sent.
193 
194   @param[in] Status        Result of the IP packet being sent.
195   @param[in] Context       The data provided by user for the received packet when
196                            the callback is registered in IP_IO_OPEN_DATA::SndContext.
197   @param[in] Sender        A Union type to specify a pointer of EFI_IP4_PROTOCOL
198                            or EFI_IP6_PROTOCOL.
199   @param[in] NotifyData    The Context data specified when calling IpIoSend()
200 
201 **/
202 typedef
203 VOID
204 (EFIAPI *PKT_SENT_NOTIFY) (
205   IN EFI_STATUS        Status,
206   IN VOID              *Context,
207   IN IP_IO_IP_PROTOCOL Sender,
208   IN VOID              *NotifyData
209   );
210 
211 ///
212 /// This data structure wraps Ip4/Ip6 instances. The IpIo Library uses it for all
213 /// Ip4/Ip6 operations.
214 ///
215 typedef struct _IP_IO {
216   ///
217   /// The node used to link this IpIo to the active IpIo list.
218   ///
219   LIST_ENTRY                    Entry;
220 
221   ///
222   /// The list used to maintain the IP instance for different sending purpose.
223   ///
224   LIST_ENTRY                    IpList;
225 
226   EFI_HANDLE                    Controller;
227   EFI_HANDLE                    Image;
228   EFI_HANDLE                    ChildHandle;
229   //
230   // The IP instance consumed by this IP_IO
231   //
232   IP_IO_IP_PROTOCOL             Ip;
233   BOOLEAN                       IsConfigured;
234 
235   ///
236   /// Some ip configuration data can be changed.
237   ///
238   UINT8                         Protocol;
239 
240   ///
241   /// Token and event used to get data from IP.
242   ///
243   IP_IO_IP_COMPLETION_TOKEN     RcvToken;
244 
245   ///
246   /// List entry used to link the token passed to IP_IO.
247   ///
248   LIST_ENTRY                    PendingSndList;
249 
250   //
251   // User interface used to get notify from IP_IO
252   //
253   VOID                          *RcvdContext;    ///< See IP_IO_OPEN_DATA::RcvdContext.
254   VOID                          *SndContext;     ///< See IP_IO_OPEN_DATA::SndContext.
255   PKT_RCVD_NOTIFY               PktRcvdNotify;   ///< See IP_IO_OPEN_DATA::PktRcvdNotify.
256   PKT_SENT_NOTIFY               PktSentNotify;   ///< See IP_IO_OPEN_DATA::PktSentNotify.
257   UINT8                         IpVersion;
258   IP4_ADDR                      StationIp;
259   IP4_ADDR                      SubnetMask;
260 } IP_IO;
261 
262 ///
263 /// The struct is for the user to pass IP configuration and callbacks to IP_IO.
264 /// It is used by IpIoOpen().
265 ///
266 typedef struct _IP_IO_OPEN_DATA {
267   IP_IO_IP_CONFIG_DATA IpConfigData;    ///< Configuration of the IP instance.
268   VOID                 *RcvdContext;    ///< Context data used by receive callback.
269   VOID                 *SndContext;     ///< Context data used by send callback.
270   PKT_RCVD_NOTIFY      PktRcvdNotify;   ///< Receive callback.
271   PKT_SENT_NOTIFY      PktSentNotify;   ///< Send callback.
272 } IP_IO_OPEN_DATA;
273 
274 ///
275 /// Internal struct book-keeping send request of IP_IO.
276 ///
277 /// An IP_IO_SEND_ENTRY will be created each time a send request is issued to
278 /// IP_IO via IpIoSend().
279 ///
280 typedef struct _IP_IO_SEND_ENTRY {
281   LIST_ENTRY                Entry;
282   IP_IO                     *IpIo;
283   VOID                      *Context;
284   VOID                      *NotifyData;
285   IP_IO_IP_PROTOCOL         Ip;
286   NET_BUF                   *Pkt;
287   IP_IO_IP_COMPLETION_TOKEN SndToken;
288 } IP_IO_SEND_ENTRY;
289 
290 ///
291 /// The IP_IO_IP_INFO is used in IpIoSend() to override the default IP instance
292 /// in IP_IO.
293 ///
294 typedef struct _IP_IO_IP_INFO {
295   EFI_IP_ADDRESS            Addr;
296   IP_IO_IP_MASK             PreMask;
297   LIST_ENTRY                Entry;
298   EFI_HANDLE                ChildHandle;
299   IP_IO_IP_PROTOCOL         Ip;
300   IP_IO_IP_COMPLETION_TOKEN DummyRcvToken;
301   INTN                      RefCnt;
302   UINT8                     IpVersion;
303 } IP_IO_IP_INFO;
304 
305 /**
306   Create a new IP_IO instance.
307 
308   If IpVersion is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
309 
310   This function uses IP4/IP6 service binding protocol in Controller to create
311   an IP4/IP6 child (aka IP4/IP6 instance).
312 
313   @param[in]  Image             The image handle of the driver or application that
314                                 consumes IP_IO.
315   @param[in]  Controller        The controller handle that has IP4 or IP6 service
316                                 binding protocol installed.
317   @param[in]  IpVersion         The version of the IP protocol to use, either
318                                 IPv4 or IPv6.
319 
320   @return The pointer to a newly created IP_IO instance, or NULL if failed.
321 
322 **/
323 IP_IO *
324 EFIAPI
325 IpIoCreate (
326   IN EFI_HANDLE Image,
327   IN EFI_HANDLE Controller,
328   IN UINT8      IpVersion
329   );
330 
331 /**
332   Destroy an IP_IO instance.
333 
334   This function is paired with IpIoCreate(). The IP_IO will be closed first.
335   Resource will be freed afterwards. See IpIoClose().
336 
337   @param[in, out]  IpIo         The pointer to the IP_IO instance that needs to be
338                                 destroyed.
339 
340   @retval          EFI_SUCCESS  The IP_IO instance was destroyed successfully.
341   @retval          Others       An error condition occurred.
342 
343 **/
344 EFI_STATUS
345 EFIAPI
346 IpIoDestroy (
347   IN OUT IP_IO *IpIo
348   );
349 
350 /**
351   Stop an IP_IO instance.
352 
353   If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
354 
355   This function is paired with IpIoOpen(). The IP_IO will be unconfigured, and all
356   pending send/receive tokens will be canceled.
357 
358   @param[in, out]  IpIo            The pointer to the IP_IO instance that needs to stop.
359 
360   @retval          EFI_SUCCESS            The IP_IO instance stopped successfully.
361   @retval          EFI_INVALID_PARAMETER  Invalid input parameter.
362   @retval          Others                 Anrror condition occurred.
363 
364 **/
365 EFI_STATUS
366 EFIAPI
367 IpIoStop (
368   IN OUT IP_IO *IpIo
369   );
370 
371 /**
372   Open an IP_IO instance for use.
373 
374   If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
375 
376   This function is called after IpIoCreate(). It is used for configuring the IP
377   instance and register the callbacks and their context data for sending and
378   receiving IP packets.
379 
380   @param[in, out]  IpIo               The pointer to an IP_IO instance that needs
381                                       to open.
382   @param[in]       OpenData           The configuration data and callbacks for
383                                       the IP_IO instance.
384 
385   @retval          EFI_SUCCESS            The IP_IO instance opened with OpenData
386                                           successfully.
387   @retval          EFI_ACCESS_DENIED      The IP_IO instance is configured, avoid to
388                                           reopen it.
389   @retval          EFI_UNSUPPORTED        IPv4 RawData mode is no supported.
390   @retval          EFI_INVALID_PARAMETER  Invalid input parameter.
391   @retval          Others                 Error condition occurred.
392 
393 **/
394 EFI_STATUS
395 EFIAPI
396 IpIoOpen (
397   IN OUT IP_IO           *IpIo,
398   IN     IP_IO_OPEN_DATA *OpenData
399   );
400 
401 /**
402   Send out an IP packet.
403 
404   This function is called after IpIoOpen(). The data to be sent is wrapped in
405   Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
406   overriden by Sender. Other sending configs, like source address and gateway
407   address etc., are specified in OverrideData.
408 
409   @param[in, out]  IpIo                  Pointer to an IP_IO instance used for sending IP
410                                          packet.
411   @param[in, out]  Pkt                   Pointer to the IP packet to be sent.
412   @param[in]       Sender                The IP protocol instance used for sending.
413   @param[in]       Context               Optional context data.
414   @param[in]       NotifyData            Optional notify data.
415   @param[in]       Dest                  The destination IP address to send this packet to.
416                                          This parameter is optional when using IPv6.
417   @param[in]       OverrideData          The data to override some configuration of the IP
418                                          instance used for sending.
419 
420   @retval          EFI_SUCCESS           The operation is completed successfully.
421   @retval          EFI_INVALID_PARAMETER The input parameter is not correct.
422   @retval          EFI_NOT_STARTED       The IpIo is not configured.
423   @retval          EFI_OUT_OF_RESOURCES  Failed due to resource limit.
424   @retval          Others                Error condition occurred.
425 
426 **/
427 EFI_STATUS
428 EFIAPI
429 IpIoSend (
430   IN OUT IP_IO          *IpIo,
431   IN OUT NET_BUF        *Pkt,
432   IN     IP_IO_IP_INFO  *Sender        OPTIONAL,
433   IN     VOID           *Context       OPTIONAL,
434   IN     VOID           *NotifyData    OPTIONAL,
435   IN     EFI_IP_ADDRESS *Dest          OPTIONAL,
436   IN     IP_IO_OVERRIDE *OverrideData  OPTIONAL
437   );
438 
439 /**
440   Cancel the IP transmit token that wraps this Packet.
441 
442   If IpIo is NULL, then ASSERT().
443   If Packet is NULL, then ASSERT().
444 
445   @param[in]  IpIo                  The pointer to the IP_IO instance.
446   @param[in]  Packet                The pointer to the packet of NET_BUF to cancel.
447 
448 **/
449 VOID
450 EFIAPI
451 IpIoCancelTxToken (
452   IN IP_IO  *IpIo,
453   IN VOID   *Packet
454   );
455 
456 /**
457   Add a new IP instance for sending data.
458 
459   If IpIo is NULL, then ASSERT().
460   If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
461 
462   The function is used to add the IP_IO to the IP_IO sending list. The caller
463   can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
464   data.
465 
466   @param[in, out]  IpIo               The pointer to an IP_IO instance to add a new IP
467                                       instance for sending purposes.
468 
469   @return The pointer to the created IP_IO_IP_INFO structure; NULL if failed.
470 
471 **/
472 IP_IO_IP_INFO *
473 EFIAPI
474 IpIoAddIp (
475   IN OUT IP_IO  *IpIo
476   );
477 
478 /**
479   Configure the IP instance of this IpInfo and start the receiving if IpConfigData
480   is not NULL.
481 
482   If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
483 
484   @param[in, out]  IpInfo          The pointer to the IP_IO_IP_INFO instance.
485   @param[in, out]  IpConfigData    The IP4 or IP6 configure data used to configure
486                                    the IP instance. If NULL, the IP instance is reset.
487                                    If UseDefaultAddress is set to TRUE, and the configure
488                                    operation succeeds, the default address information
489                                    is written back in this IpConfigData.
490 
491   @retval          EFI_SUCCESS     The IP instance of this IpInfo was configured successfully,
492                                    or there is no need to reconfigure it.
493   @retval          Others          The configuration failed.
494 
495 **/
496 EFI_STATUS
497 EFIAPI
498 IpIoConfigIp (
499   IN OUT IP_IO_IP_INFO        *IpInfo,
500   IN OUT VOID                 *IpConfigData OPTIONAL
501   );
502 
503 /**
504   Destroy an IP instance maintained in IpIo->IpList for
505   sending purpose.
506 
507   If Ip version is not IP_VERSION_4 or IP_VERSION_6, then ASSERT().
508 
509   This function pairs with IpIoAddIp(). The IpInfo is previously created by
510   IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
511   will be dstroyed if the RefCnt is zero.
512 
513   @param[in]  IpIo                  The pointer to the IP_IO instance.
514   @param[in]  IpInfo                The pointer to the IpInfo to be removed.
515 
516 **/
517 VOID
518 EFIAPI
519 IpIoRemoveIp (
520   IN IP_IO            *IpIo,
521   IN IP_IO_IP_INFO    *IpInfo
522   );
523 
524 /**
525   Find the first IP protocol maintained in IpIo whose local
526   address is the same as Src.
527 
528   This function is called when the caller needs the IpIo to send data to the
529   specified Src. The IpIo was added previously by IpIoAddIp().
530 
531   @param[in, out]  IpIo              The pointer to the pointer of the IP_IO instance.
532   @param[in]       IpVersion         The version of the IP protocol to use, either
533                                      IPv4 or IPv6.
534   @param[in]       Src               The local IP address.
535 
536   @return The pointer to the IP protocol can be used for sending purpose and its local
537           address is the same with Src. NULL if failed.
538 
539 **/
540 IP_IO_IP_INFO *
541 EFIAPI
542 IpIoFindSender (
543   IN OUT IP_IO           **IpIo,
544   IN     UINT8           IpVersion,
545   IN     EFI_IP_ADDRESS  *Src
546   );
547 
548 /**
549   Get the ICMP error map information.
550 
551   The ErrorStatus will be returned. The IsHard and Notify are optional. If they
552   are not NULL, this routine will fill them.
553 
554   @param[in]   IcmpError             IcmpError Type.
555   @param[in]   IpVersion             The version of the IP protocol to use,
556                                      either IPv4 or IPv6.
557   @param[out]  IsHard                If TRUE, indicates that it is a hard error.
558   @param[out]  Notify                If TRUE, SockError needs to be notified.
559 
560   @retval EFI_UNSUPPORTED            Unrecognizable ICMP error code
561   @return The ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
562 
563 **/
564 EFI_STATUS
565 EFIAPI
566 IpIoGetIcmpErrStatus (
567   IN  UINT8       IcmpError,
568   IN  UINT8       IpVersion,
569   OUT BOOLEAN     *IsHard  OPTIONAL,
570   OUT BOOLEAN     *Notify  OPTIONAL
571   );
572 
573 /**
574   Refresh the remote peer's Neighbor Cache entries.
575 
576   This function is called when the caller needs the IpIo to refresh the existing
577   IPv6 neighbor cache entries since the neighbor is considered reachable by the
578   node has recently received a confirmation that packets sent recently to the
579   neighbor were received by its IP layer.
580 
581   @param[in]   IpIo                  The pointer to an IP_IO instance
582   @param[in]   Neighbor              The IP address of the neighbor
583   @param[in]   Timeout               The time in 100-ns units that this entry will
584                                      remain in the neighbor cache. A value of
585                                      zero means that the entry is permanent.
586                                      A value of non-zero means that the entry is
587                                      dynamic and will be deleted after Timeout.
588 
589   @retval      EFI_SUCCESS           The operation completed successfully.
590   @retval      EFI_NOT_STARTED       The IpIo is not configured.
591   @retval      EFI_INVALID_PARAMETER The Neighbor Address is invalid.
592   @retval      EFI_NOT_FOUND         The neighbor cache entry is not in the
593                                      neighbor table.
594   @retval      EFI_UNSUPPORTED       IP version is IPv4, which doesn't support neighbor cache refresh.
595   @retval      EFI_OUT_OF_RESOURCES  Failed due to resource limitations.
596 
597 **/
598 EFI_STATUS
599 EFIAPI
600 IpIoRefreshNeighbor (
601   IN IP_IO           *IpIo,
602   IN EFI_IP_ADDRESS  *Neighbor,
603   IN UINT32          Timeout
604   );
605 
606 #endif
607 
608