summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Include/Library/NetLib.h5
-rw-r--r--MdeModulePkg/Library/DxeNetLib/DxeNetLib.c13
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h2
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c119
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h5
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c2
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c11
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c26
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h9
-rw-r--r--MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c6
10 files changed, 164 insertions, 34 deletions
diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h
index ef7bc429c1..b7ef99c7b5 100644
--- a/MdeModulePkg/Include/Library/NetLib.h
+++ b/MdeModulePkg/Include/Library/NetLib.h
@@ -422,8 +422,9 @@ NetGetIpClass (
If all bits of the host address of IP are 0 or 1, IP is also not a valid unicast address,
except when the originator is one of the endpoints of a point-to-point link with a 31-bit
- mask (RFC3021).
-
+ mask (RFC3021), or a 32bit NetMask (all 0xFF) is used for special network environment (e.g.
+ PPP link).
+
@param[in] Ip The IP to check against.
@param[in] NetMask The mask of the IP.
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
index bf8f5523e6..63f4724062 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
@@ -654,8 +654,9 @@ NetGetIpClass (
If all bits of the host address of IP are 0 or 1, IP is also not a valid unicast address,
except when the originator is one of the endpoints of a point-to-point link with a 31-bit
- mask (RFC3021).
-
+ mask (RFC3021), or a 32bit NetMask (all 0xFF) is used for special network environment (e.g.
+ PPP link).
+
@param[in] Ip The IP to check against.
@param[in] NetMask The mask of the IP.
@@ -669,18 +670,20 @@ NetIp4IsUnicast (
IN IP4_ADDR NetMask
)
{
+ INTN MaskLength;
+
ASSERT (NetMask != 0);
if (Ip == 0 || IP4_IS_LOCAL_BROADCAST (Ip)) {
return FALSE;
}
- if (NetGetMaskLength (NetMask) != 31) {
+ MaskLength = NetGetMaskLength (NetMask);
+ ASSERT ((MaskLength >= 0) && (MaskLength <= IP4_MASK_NUM));
+ if (MaskLength < 31) {
if (((Ip &~NetMask) == ~NetMask) || ((Ip &~NetMask) == 0)) {
return FALSE;
}
- } else {
- return TRUE;
}
return TRUE;
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
index e0fffc9d0d..994a81f4de 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.h
@@ -55,7 +55,7 @@ typedef struct _IP4_SERVICE IP4_SERVICE;
/// Compose the fragment field to be used in the IP4 header.
///
#define IP4_HEAD_FRAGMENT_FIELD(Df, Mf, Offset) \
- ((UINT16)(((Df) ? 0x4000 : 0) | ((Mf) ? 0x2000 : 0) | (((Offset) >> 3) & 0x1fff)))
+ ((UINT16)(((Df) ? IP4_HEAD_DF_MASK : 0) | ((Mf) ? IP4_HEAD_MF_MASK : 0) | (((Offset) >> 3) & IP4_HEAD_OFFSET_MASK)))
#define IP4_LAST_FRAGMENT(FragmentField) \
(((FragmentField) & IP4_HEAD_MF_MASK) == 0)
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
index 6e0e3290c7..499a486a8b 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
@@ -138,6 +138,7 @@ Ip4CancelFrameArp (
@param[in] CallBack Call back function to execute if transmission
finished.
@param[in] Context Opaque parameter to the call back.
+ @param[in] IpSb The pointer to the IP4 service binding instance.
@retval Token The wrapped token if succeed
@retval NULL The wrapped token if NULL
@@ -149,7 +150,8 @@ Ip4WrapLinkTxToken (
IN IP4_PROTOCOL *IpInstance OPTIONAL,
IN NET_BUF *Packet,
IN IP4_FRAME_CALLBACK CallBack,
- IN VOID *Context
+ IN VOID *Context,
+ IN IP4_SERVICE *IpSb
)
{
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
@@ -170,6 +172,7 @@ Ip4WrapLinkTxToken (
Token->Interface = Interface;
Token->IpInstance = IpInstance;
+ Token->IpSb = IpSb;
Token->CallBack = CallBack;
Token->Packet = Packet;
Token->Context = Context;
@@ -792,9 +795,89 @@ Ip4FreeInterface (
return EFI_SUCCESS;
}
+/**
+ This function tries to send all the queued frames in ArpQue to the default gateway if
+ the ARP resolve for direct destination address is failed when using /32 subnet mask.
+
+ @param[in] ArpQue The ARP queue of a failed request.
+
+ @retval EFI_SUCCESS All the queued frames have been send to the default route.
+ @retval Others Failed to send the queued frames.
+
+**/
+EFI_STATUS
+Ip4SendFrameToDefaultRoute (
+ IN IP4_ARP_QUE *ArpQue
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
+ IP4_LINK_TX_TOKEN *Token;
+ IP4_ADDR Gateway;
+ EFI_STATUS Status;
+ IP4_ROUTE_ENTRY *DefaultRoute;
+
+ //
+ // ARP resolve failed when using /32 subnet mask.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
+ RemoveEntryList (Entry);
+ Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
+ ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);
+ //
+ // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
+ //
+ RtCacheEntry = NULL;
+ if (Token->IpInstance != NULL) {
+ RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
+ }
+ if (RtCacheEntry == NULL) {
+ RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
+ }
+ if (RtCacheEntry == NULL) {
+ Status= EFI_NO_MAPPING;
+ goto ON_ERROR;
+ }
+ DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;
+ if (DefaultRoute == NULL) {
+ Status= EFI_NO_MAPPING;
+ goto ON_ERROR;
+ }
+ //
+ // Try to send the frame to the default route.
+ //
+ Gateway = DefaultRoute->NextHop;
+ if (ArpQue->Ip == Gateway) {
+ //
+ // ARP resolve for the default route is failed, return error to caller.
+ //
+ Status= EFI_NO_MAPPING;
+ goto ON_ERROR;
+ }
+ RtCacheEntry->NextHop = Gateway;
+ Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);
+ if (EFI_ERROR (Status)) {
+ Status= EFI_NO_MAPPING;
+ goto ON_ERROR;
+ }
+ Ip4FreeRouteCacheEntry (RtCacheEntry);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (RtCacheEntry != NULL) {
+ Ip4FreeRouteCacheEntry (RtCacheEntry);
+ }
+ Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
+ Ip4FreeLinkTxToken (Token);
+ return Status;
+}
+
/**
- Callback function when ARP request are finished. It will cancelled
+ Callback function when ARP request are finished. It will cancel
all the queued frame if the ARP requests failed. Or transmit them
if the request succeed.
@@ -814,6 +897,7 @@ Ip4OnArpResolvedDpc (
IP4_INTERFACE *Interface;
IP4_LINK_TX_TOKEN *Token;
EFI_STATUS Status;
+ EFI_STATUS IoStatus;
ArpQue = (IP4_ARP_QUE *) Context;
NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
@@ -821,14 +905,23 @@ Ip4OnArpResolvedDpc (
RemoveEntryList (&ArpQue->Link);
//
- // ARP resolve failed for some reason. Release all the frame
- // and ARP queue itself. Ip4FreeArpQue will call the frame's
- // owner back.
+ // ARP resolve failed for some reason.
//
if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {
- Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);
-
- return ;
+ if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {
+ //
+ // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
+ // owner back.
+ //
+ IoStatus = EFI_NO_MAPPING;
+ } else {
+ //
+ // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
+ // default route.
+ //
+ IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);
+ }
+ goto ON_EXIT;
}
//
@@ -836,6 +929,7 @@ Ip4OnArpResolvedDpc (
// queue. It isn't necessary for us to cache the ARP binding because
// we always check the ARP cache first before transmit.
//
+ IoStatus = EFI_SUCCESS;
Interface = ArpQue->Interface;
NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
@@ -863,7 +957,8 @@ Ip4OnArpResolvedDpc (
}
}
- Ip4FreeArpQue (ArpQue, EFI_SUCCESS);
+ON_EXIT:
+ Ip4FreeArpQue (ArpQue, IoStatus);
}
/**
@@ -957,6 +1052,7 @@ Ip4OnFrameSent (
to.
@param[in] CallBack Function to call back when transmit finished.
@param[in] Context Opaque parameter to the call back.
+ @param[in] IpSb The pointer to the IP4 service binding instance.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
@retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
@@ -971,7 +1067,8 @@ Ip4SendFrame (
IN NET_BUF *Packet,
IN IP4_ADDR NextHop,
IN IP4_FRAME_CALLBACK CallBack,
- IN VOID *Context
+ IN VOID *Context,
+ IN IP4_SERVICE *IpSb
)
{
IP4_LINK_TX_TOKEN *Token;
@@ -982,7 +1079,7 @@ Ip4SendFrame (
ASSERT (Interface->Configured);
- Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);
+ Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);
if (Token == NULL) {
return EFI_OUT_OF_RESOURCES;
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
index 909837131e..36e4ab3f7a 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
@@ -79,6 +79,7 @@ typedef struct {
LIST_ENTRY Link;
IP4_INTERFACE *Interface;
+ IP4_SERVICE *IpSb;
IP4_PROTOCOL *IpInstance;
IP4_FRAME_CALLBACK CallBack;
@@ -262,6 +263,7 @@ Ip4FreeInterface (
to.
@param[in] CallBack Function to call back when transmit finished.
@param[in] Context Opaque parameter to the call back.
+ @param[in] IpSb The pointer to the IP4 service binding instance.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
@retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
@@ -276,7 +278,8 @@ Ip4SendFrame (
IN NET_BUF *Packet,
IN IP4_ADDR NextHop,
IN IP4_FRAME_CALLBACK CallBack,
- IN VOID *Context
+ IN VOID *Context,
+ IN IP4_SERVICE *IpSb
);
/**
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
index 6a26143e30..7c27db6753 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
@@ -1259,7 +1259,7 @@ EfiIp4Routes (
// the gateway address must be a unicast on the connected network if not zero.
//
if ((Nexthop != IP4_ALLZERO_ADDRESS) &&
- (!IP4_NET_EQUAL (Nexthop, IpIf->Ip, IpIf->SubnetMask) ||
+ ((IpIf->SubnetMask != IP4_ALLONE_ADDRESS && !IP4_NET_EQUAL (Nexthop, IpIf->Ip, IpIf->SubnetMask)) ||
IP4_IS_BROADCAST (Ip4GetNetCast (Nexthop, IpIf)))) {
Status = EFI_INVALID_PARAMETER;
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
index 1716f43576..6b759d8d10 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c
@@ -309,15 +309,15 @@ Ip4Output (
// Route the packet unless overrided, that is, GateWay isn't zero.
//
if (IpInstance == NULL) {
- CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
+ CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);
} else {
- CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);
+ CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, FALSE);
//
// If failed to route the packet by using the instance's route table,
// try to use the default route table.
//
if (CacheEntry == NULL) {
- CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);
+ CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src, IpIf->SubnetMask, TRUE);
}
}
@@ -386,7 +386,8 @@ Ip4Output (
Fragment,
GateWay,
Ip4SysPacketSent,
- Packet
+ Packet,
+ IpSb
);
if (EFI_ERROR (Status)) {
@@ -429,7 +430,7 @@ Ip4Output (
// upper layer's packets.
//
Ip4PrependHead (Packet, Head, Option, OptLen);
- Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context);
+ Status = Ip4SendFrame (IpIf, IpInstance, Packet, GateWay, Callback, Context, IpSb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
index d240d5343a..120345836b 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.c
@@ -494,6 +494,11 @@ Ip4FindRouteEntry (
@param[in] RtTable The route table to search from
@param[in] Dest The destination address to search for
@param[in] Src The source address to search for
+ @param[in] SubnetMask The subnet mask of the Src address, this field is
+ used to check if the station is using /32 subnet.
+ @param[in] AlwaysTryDestAddr Always try to use the dest address as next hop even
+ though we can't find a matching route entry. This
+ field is only valid when using /32 subnet.
@return NULL if failed to route packet, otherwise a route cache
entry that can be used to route packet.
@@ -503,7 +508,9 @@ IP4_ROUTE_CACHE_ENTRY *
Ip4Route (
IN IP4_ROUTE_TABLE *RtTable,
IN IP4_ADDR Dest,
- IN IP4_ADDR Src
+ IN IP4_ADDR Src,
+ IN IP4_ADDR SubnetMask,
+ IN BOOLEAN AlwaysTryDestAddr
)
{
LIST_ENTRY *Head;
@@ -535,7 +542,11 @@ Ip4Route (
RtEntry = Ip4FindRouteEntry (RtTable, Dest);
if (RtEntry == NULL) {
- return NULL;
+ if (SubnetMask != IP4_ALLONE_ADDRESS) {
+ return NULL;
+ } else if (!AlwaysTryDestAddr) {
+ return NULL;
+ }
}
//
@@ -544,16 +555,23 @@ Ip4Route (
// network. Otherwise, it is an indirect route, the packet will be
// sent to the next hop router.
//
- if ((RtEntry->Flag & IP4_DIRECT_ROUTE) != 0) {
+ // When using /32 subnet mask, the packet will always be sent to the direct
+ // destination first, if we can't find a matching route cache.
+ //
+ if (SubnetMask == IP4_ALLONE_ADDRESS || ((RtEntry->Flag & IP4_DIRECT_ROUTE) != 0)) {
NextHop = Dest;
} else {
NextHop = RtEntry->NextHop;
}
- Ip4FreeRouteEntry (RtEntry);
+ if (RtEntry != NULL) {
+ Ip4FreeRouteEntry (RtEntry);
+ }
//
// Create a route cache entry, and tag it as spawned from this route entry
+ // For /32 subnet mask, the default route in RtEntry will be used if failed
+ // to send the packet to driect destination address.
//
RtCacheEntry = Ip4CreateRouteCacheEntry (Dest, Src, NextHop, (UINTN) RtEntry);
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
index 6269f4ceda..764c85a70f 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Route.h
@@ -194,6 +194,11 @@ Ip4FreeRouteCacheEntry (
@param[in] RtTable The route table to search from
@param[in] Dest The destination address to search for
@param[in] Src The source address to search for
+ @param[in] SubnetMask The subnet mask of the Src address, this field is
+ used to check if the station is using /32 subnet.
+ @param[in] AlwaysTryDestAddr Always try to use the dest address as next hop even
+ though we can't find a matching route entry. This
+ field is only valid when using /32 subnet.
@return NULL if failed to route packet, otherwise a route cache
entry that can be used to route packet.
@@ -203,7 +208,9 @@ IP4_ROUTE_CACHE_ENTRY *
Ip4Route (
IN IP4_ROUTE_TABLE *RtTable,
IN IP4_ADDR Dest,
- IN IP4_ADDR Src
+ IN IP4_ADDR Src,
+ IN IP4_ADDR SubnetMask,
+ IN BOOLEAN AlwaysTryDestAddr
);
/**
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
index d5a1a8c303..03903640b8 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
@@ -509,8 +509,9 @@ Mtftp4Start (
goto ON_ERROR;
}
+ gBS->RestoreTPL(OldTpl);
+
if (Token->Event != NULL) {
- gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}
@@ -522,7 +523,6 @@ Mtftp4Start (
This->Poll (This);
}
- gBS->RestoreTPL (OldTpl);
return Token->Status;
ON_ERROR:
@@ -682,7 +682,7 @@ EfiMtftp4Configure (
}
if ((Gateway != 0) &&
- (!IP4_NET_EQUAL (Gateway, Ip, Netmask) || (Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)))) {
+ ((Netmask != 0xFFFFFFFF && !IP4_NET_EQUAL (Gateway, Ip, Netmask)) || (Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)))) {
return EFI_INVALID_PARAMETER;
}