diff --git a/KernelLand/Modules/IPStack/icmp.c b/KernelLand/Modules/IPStack/icmp.c
index fa9927ee1adba1af8de758e15bb3df32d2335c4a..f34d790fd01751a1616f91c11857ba203de07298 100644
--- a/KernelLand/Modules/IPStack/icmp.c
+++ b/KernelLand/Modules/IPStack/icmp.c
@@ -26,7 +26,7 @@ struct {
  */
 void ICMP_Initialise()
 {
-	IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket);
+	IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket, NULL);
 }
 
 /**
@@ -64,12 +64,15 @@ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buff
 		{
 		case 3:	// Port Unreachable
 			Log_Debug("ICMPv4", "Destination Unreachable (Port Unreachable)");
+			IPv4_HandleError( Interface, IPERR_PORT_UNREACHABLE,
+				htons(Length)-sizeof(tICMPHeader), hdr->Data );
 			break;
 		default:
 			Log_Debug("ICMPv4", "Destination Unreachable (Code %i)", hdr->Code);
+			IPv4_HandleError( Interface, IPERR_MISC,
+				htons(Length)-sizeof(tICMPHeader), hdr->Data );
 			break;
 		}
-//		IPv4_Unreachable( Interface, hdr->Code, htons(hdr->Length)-sizeof(tICMPHeader), hdr->Data );
 		break;
 	
 	// -- 8: Echo Request
diff --git a/KernelLand/Modules/IPStack/ipstack.h b/KernelLand/Modules/IPStack/ipstack.h
index ddcdde9649ea22810e8a2a273809fc32281c5ddf..3833ce7b0d6c2ed345765f511a6678f2d6529383 100644
--- a/KernelLand/Modules/IPStack/ipstack.h
+++ b/KernelLand/Modules/IPStack/ipstack.h
@@ -15,7 +15,16 @@ typedef struct sAdapter	tAdapter;
 typedef struct sInterface	tInterface;
 typedef struct sSocketFile	tSocketFile;
 
-typedef void	(*tIPCallback)(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef enum eIPErrorMode
+{
+	IPERR_MISC,
+	IPERR_HOST_UNREACHABLE,
+	IPERR_PORT_UNREACHABLE,
+} tIPErrorMode;
+
+// NOTE: Non-const to allow reuse of Rx buffer for prepping Tx
+typedef void	tIPRxCallback(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef void	tIPErrorCallback(tInterface *Interface, tIPErrorMode mode, const void *Address, int Length, const void *Buffer);
 
 enum eInterfaceTypes {
 	AF_NULL,
diff --git a/KernelLand/Modules/IPStack/ipv4.c b/KernelLand/Modules/IPStack/ipv4.c
index 000fe3966381c15393074d029408a5326ce31e30..371fe4026f224502521daa03df9bc91e388c42bc 100644
--- a/KernelLand/Modules/IPStack/ipv4.c
+++ b/KernelLand/Modules/IPStack/ipv4.c
@@ -20,7 +20,7 @@ extern  int	ICMP_Ping(tInterface *Interface, tIPv4 Addr);
 
 // === PROTOTYPES ===
  int	IPv4_Initialise();
- int	IPv4_RegisterCallback(int ID, tIPCallback Callback);
+// int	IPv4_RegisterCallback(int ID, tIPRxCallback Callback, );
 void	IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface	*IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
 Uint32	IPv4_Netmask(int FixedBits);
@@ -28,7 +28,10 @@ Uint16	IPv4_Checksum(const void *Buf, size_t Length);
  int	IPv4_Ping(tInterface *Iface, tIPv4 Addr);
 
 // === GLOBALS ===
-tIPCallback	gaIPv4_Callbacks[256];
+struct {
+	tIPRxCallback*	rx_cb;
+	tIPErrorCallback*	err_cb;
+} gaIPv4_Callbacks[256];
 
 // === CODE ===
 /**
@@ -46,11 +49,12 @@ int IPv4_Initialise()
  * \param ID	8-bit packet type ID
  * \param Callback	Callback function
  */
-int IPv4_RegisterCallback(int ID, tIPCallback Callback)
+int IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback)
 {
 	if( ID < 0 || ID > 255 )	return 0;
-	if( gaIPv4_Callbacks[ID] )	return 0;
-	gaIPv4_Callbacks[ID] = Callback;
+	if( gaIPv4_Callbacks[ID].rx_cb )	return 0;
+	gaIPv4_Callbacks[ID].rx_cb = RxCallback;
+	gaIPv4_Callbacks[ID].err_cb = ErrCallback;
 	return 1;
 }
 
@@ -66,14 +70,12 @@ int IPv4_RegisterCallback(int ID, tIPCallback Callback)
  */
 int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer)
 {
-	tMacAddr	to;
 	tIPv4Header	hdr;
-	 int	length;
 
-	length = IPStack_Buffer_GetLength(Buffer);
+	int length = IPStack_Buffer_GetLength(Buffer);
 	
 	// --- Resolve destination MAC address
-	to = HWCache_Resolve(Iface, &Address);
+	tMacAddr to = HWCache_Resolve(Iface, &Address);
 	if( MAC_EQU(to, cMAC_ZERO) ) {
 		// No route to host
 		Log_Notice("IPv4", "No route to host %i.%i.%i.%i",
@@ -134,7 +136,6 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPS
 void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
 {
 	tIPv4Header	*hdr = Buffer;
-	tInterface	*iface;
 	Uint8	*data;
 	 int	dataLength;
 	 int	ret;
@@ -197,7 +198,7 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
 	data = &hdr->Options[0];
 	
 	// Get Interface (allowing broadcasts)
-	iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
+	tInterface *iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
 	
 	// Firewall rules
 	if( iface ) {
@@ -255,12 +256,29 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
 	}
 	
 	// Send it on
-	if( !gaIPv4_Callbacks[hdr->Protocol] ) {
+	if( !gaIPv4_Callbacks[hdr->Protocol].rx_cb ) {
 		Log_Log("IPv4", "Unknown Protocol %i", hdr->Protocol);
 		return ;
 	}
 	
-	gaIPv4_Callbacks[hdr->Protocol]( iface, &hdr->Source, dataLength, data );
+	gaIPv4_Callbacks[hdr->Protocol].rx_cb( iface, &hdr->Source, dataLength, data );
+}
+
+/*
+ * Handles an error from the ICMPv4 code, 'Buf' contains part of an IPv4 packet
+ */
+void IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf)
+{
+	if(Length < sizeof(tIPv4Header))	return;
+	const tIPv4Header*	hdr = Buf;
+	if(hdr->Version != 4)	return;
+	
+	// Get Data and Data Length
+	size_t dataLength = MIN(Length, ntohs(hdr->TotalLength)) - sizeof(tIPv4Header);
+	const void *data = &hdr->Options[0];
+	
+	if( gaIPv4_Callbacks[hdr->Protocol].err_cb )
+		gaIPv4_Callbacks[hdr->Protocol].err_cb(Iface, Mode, &hdr->Source, dataLength, data);
 }
 
 /**
@@ -272,16 +290,14 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
  */
 tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
 {
-	tInterface	*iface = NULL, *zero_iface = NULL;
-	Uint32	netmask;
-	Uint32	addr, this;
+	tInterface	*zero_iface = NULL;
 
 	ENTER("pAdapter xAddress bBroadcast", Adapter, Address, Broadcast);	
 
-	addr = ntohl( Address.L );
+	Uint32 addr = ntohl( Address.L );
 	LOG("addr = 0x%x", addr);
 	
-	for( iface = gIP_Interfaces; iface; iface = iface->Next)
+	for( tInterface *iface = gIP_Interfaces; iface; iface = iface->Next)
 	{
 		if( iface->Adapter != Adapter )	continue;
 		if( iface->Type != 4 )	continue;
@@ -307,8 +323,8 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
 		if( !Broadcast )	continue;
 		
 		// Check for broadcast
-		this = ntohl( ((tIPv4*)iface->Address)->L );
-		netmask = IPv4_Netmask(iface->SubnetBits);
+		Uint32 this = ntohl( ((tIPv4*)iface->Address)->L );
+		Uint32 netmask = IPv4_Netmask(iface->SubnetBits);
 		LOG("iface addr = 0x%x, netmask = 0x%x (bits = %i)", this, netmask, iface->SubnetBits);
 
 		if( (addr & netmask) == (this & netmask) && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) )
diff --git a/KernelLand/Modules/IPStack/ipv4.h b/KernelLand/Modules/IPStack/ipv4.h
index dd78788f94f76e1f951245cce8fa7a33b13e5ec6..c31b751296f968649e34e47106eb765ef30aee07 100644
--- a/KernelLand/Modules/IPStack/ipv4.h
+++ b/KernelLand/Modules/IPStack/ipv4.h
@@ -47,9 +47,11 @@ struct sIPv4Header
 #define IPV4_ETHERNET_ID	0x0800
 
 // === FUNCTIONS ===
-extern int	IPv4_RegisterCallback(int ID, tIPCallback Callback);
+extern int	IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback);
 extern Uint16	IPv4_Checksum(const void *Buf, size_t Length);
 extern Uint32	IPv4_Netmask(int FixedBits);
 extern int	IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer);
 
+extern void	IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf);
+
 #endif
diff --git a/KernelLand/Modules/IPStack/ipv6.c b/KernelLand/Modules/IPStack/ipv6.c
index 2ac05747aa4f967ab21216917b7a2ed080667b63..0e6df538d51f89c0a9435698a6e90d5aeff9c3fe 100644
--- a/KernelLand/Modules/IPStack/ipv6.c
+++ b/KernelLand/Modules/IPStack/ipv6.c
@@ -14,12 +14,12 @@ extern Uint32	IPv4_Netmask(int FixedBits);
 
 // === PROTOTYPES ===
  int	IPv6_Initialise();
- int	IPv6_RegisterCallback(int ID, tIPCallback Callback);
+// int	IPv6_RegisterCallback(int ID, tIPCallback Callback);
 void	IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface	*IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
 
 // === GLOBALS ===
-tIPCallback	gaIPv6_Callbacks[256];
+tIPRxCallback*	gaIPv6_Callbacks[256];
 
 // === CODE ===
 /**
@@ -36,7 +36,7 @@ int IPv6_Initialise()
  * \param ID	8-bit packet type ID
  * \param Callback	Callback function
  */
-int IPv6_RegisterCallback(int ID, tIPCallback Callback)
+int IPv6_RegisterCallback(int ID, tIPRxCallback* Callback)
 {
 	if( ID < 0 || ID > 255 )	return 0;
 	if( gaIPv6_Callbacks[ID] )	return 0;
diff --git a/KernelLand/Modules/IPStack/ipv6.h b/KernelLand/Modules/IPStack/ipv6.h
index fec00f75fb0f8956a8ae7cd86b42a9f47f435c88..086dfbb5398914838fbb24585d3e4ef8adc667f1 100644
--- a/KernelLand/Modules/IPStack/ipv6.h
+++ b/KernelLand/Modules/IPStack/ipv6.h
@@ -37,7 +37,7 @@ struct sIPv6Header
 
 #define IPV6_ETHERNET_ID	0x86DD
 
-extern int	IPv6_RegisterCallback(int ID, tIPCallback Callback);
+extern int	IPv6_RegisterCallback(int ID, tIPRxCallback* Callback);
 extern int	IPv6_SendPacket(tInterface *Iface, tIPv6 Destination, int Protocol, tIPStackBuffer *Buffer);
 
 #endif
diff --git a/KernelLand/Modules/IPStack/tcp.c b/KernelLand/Modules/IPStack/tcp.c
index a8a059ac61dd3fc5b715743c369a305e4ee07b88..2854f30a0ee853858f05648b85be6e9537e371a1 100644
--- a/KernelLand/Modules/IPStack/tcp.c
+++ b/KernelLand/Modules/IPStack/tcp.c
@@ -28,6 +28,7 @@ void	TCP_StartConnection(tTCPConnection *Conn);
 void	TCP_SendPacket(tTCPConnection *Conn, tTCPHeader *Header, size_t DataLen, const void *Data);
 void	TCP_int_SendPacket(tInterface *Interface, const void *Dest, tTCPHeader *Header, size_t Length, const void *Data);
 void	TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
+void	TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer);
  int	TCP_INT_HandleServerPacket(tInterface *Interface, tTCPListener *Server, const void *Address, tTCPHeader *Header, size_t Length);
  int	TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
 int	TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
@@ -94,7 +95,7 @@ void TCP_Initialise(void)
 	giTCP_NextOutPort += rand()%128;
 	IPStack_AddFile(&gTCP_ServerFile);
 	IPStack_AddFile(&gTCP_ClientFile);
-	IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
+	IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket, TCP_IPError);
 	IPv6_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
 }
 
@@ -304,6 +305,29 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
 	}
 }
 
+void TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer)
+{
+	if( Length < sizeof(tTCPHeader) )	return ;
+	
+	const tTCPHeader	*hdr = Buffer;
+	
+	// TODO: Handle errors for server connections
+	
+	for( tTCPConnection *conn = gTCP_OutbountCons; conn; conn = conn->Next )
+	{
+		if(conn->Interface != Interface)
+			continue;
+		if(conn->RemotePort != ntohs(hdr->SourcePort))
+			continue;
+		if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
+			continue ;
+		
+		// Mark an error on the interface
+		VFS_MarkError(&conn->Node, 1);
+		return ;
+	}
+}
+
 /*
  * Handle packets in LISTEN state
  */
diff --git a/KernelLand/Modules/IPStack/udp.c b/KernelLand/Modules/IPStack/udp.c
index b9dd3231442851e934daf8e0086bf8b21f00a54c..9037439cf80023b273974d12ae2c5a512ee9fa51 100644
--- a/KernelLand/Modules/IPStack/udp.c
+++ b/KernelLand/Modules/IPStack/udp.c
@@ -15,7 +15,7 @@
 // === PROTOTYPES ===
 void	UDP_Initialise();
 void	UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
-void	UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer);
+void	UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer);
 void	UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, Uint16 Port, const void *Data, size_t Length);
 // --- Client Channels
 tVFS_Node	*UDP_Channel_Init(tInterface *Interface);
@@ -56,8 +56,7 @@ tSocketFile	gUDP_SocketFile = {NULL, "udp", UDP_Channel_Init};
 void UDP_Initialise()
 {
 	IPStack_AddFile(&gUDP_SocketFile);
-	//IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_Unreachable);
-	IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
+	IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_IPError);
 }
 
 /**
@@ -146,7 +145,7 @@ void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
 /**
  * \brief Handle an ICMP Unrechable Error
  */
-void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
+void UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer)
 {
 	
 }