diff --git a/src/router.c b/src/router.c
index f145ffb..e3fc9a6 100644
--- a/src/router.c
+++ b/src/router.c
@@ -19,6 +19,8 @@
 #include <winsock2.h>
 #include <uthash.h>
 #include <time.h>
+#include <pcap.h>
+#include <Win32-Extensions.h>
 
 #include "router.h"
 #include "common.h"
@@ -453,19 +455,109 @@ static bool _do_udp_recv(int fd)
 	return true;
 }
 
+static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+{
+	ipx_interface_t *iface = (ipx_interface_t*)(user);
+	
+	if(pkt_header->caplen < sizeof(ethernet_frame_t))
+	{
+		/* Frame isn't big enough to contain a full IPX header. */
+		return;
+	}
+	
+	ethernet_frame_t *frame = (ethernet_frame_t*)(pkt_data);
+	
+	if(ntohs(frame->ethertype) != 0x8137)
+	{
+		/* The ethertype field isn't IPX. */
+		return;
+	}
+	
+	if(frame->packet.checksum != 0xFFFF)
+	{
+		/* The "checksum" field doesn't have the magic IPX value. */
+		return;
+	}
+	
+	if(ntohs(frame->packet.length) > (pkt_header->caplen - (sizeof(*frame) - sizeof(frame->packet))))
+	{
+		/* The "length" field in the IPX header is too big. */
+		return;
+	}
+	
+	{
+		addr48_t dest  = addr48_in(frame->packet.dest_node);
+		addr48_t bcast = addr48_in((unsigned char[]){0xFF,0xFF,0xFF,0xFF,0xFF,0xFF});
+		
+		if(dest != iface->mac_addr && dest != bcast)
+		{
+			/* The destination node number isn't that of the card or
+			 * the broadcast address.
+			*/
+			return;
+		}
+	}
+	
+	_deliver_packet(frame->packet.type,
+		addr32_in(frame->packet.src_net),
+		addr48_in(frame->packet.src_node),
+		frame->packet.src_socket,
+		
+		addr32_in(frame->packet.dest_net),
+		addr48_in(frame->packet.dest_node),
+		frame->packet.dest_socket,
+		
+		frame->packet.data,
+		(ntohs(frame->packet.length) - sizeof(real_ipx_packet_t)));
+}
+
 static DWORD router_main(void *arg)
 {
+	DWORD exit_status = 0;
+	
 	time_t last_at_update = 0;
 	
+	ipx_interface_t *interfaces = NULL;
+	
+	HANDLE *wait_events = &router_event;
+	int n_events = 1;
+	
+	if(ipx_use_pcap)
+	{
+		interfaces = get_ipx_interfaces();
+		ipx_interface_t *i;
+		
+		DL_FOREACH(interfaces, i)
+		{
+			++n_events;
+		}
+		
+		wait_events = malloc(n_events * sizeof(HANDLE));
+		if(!wait_events)
+		{
+			log_printf(LOG_ERROR, "Could not allocate memory!");
+			
+			free_ipx_interface_list(&interfaces);
+			return 1;
+		}
+		
+		n_events = 1;
+		wait_events[0] = router_event;
+		
+		DL_FOREACH(interfaces, i)
+		{
+			wait_events[n_events++] = pcap_getevent(i->pcap);
+		}
+	}
+	
 	while(1)
 	{
-		WaitForSingleObject(router_event, 1000);
-		
+		WaitForMultipleObjects(n_events, wait_events, FALSE, 1000);
 		WSAResetEvent(router_event);
 		
 		if(!router_running)
 		{
-			return 0;
+			break;
 		}
 		
 		if(last_at_update != time(NULL))
@@ -474,11 +566,35 @@ static DWORD router_main(void *arg)
 			last_at_update = time(NULL);
 		}
 		
-		if(!_do_udp_recv(shared_socket) || !_do_udp_recv(private_socket))
+		if(ipx_use_pcap)
 		{
-			return 1;
+			ipx_interface_t *i;
+			DL_FOREACH(interfaces, i)
+			{
+				if(pcap_dispatch(i->pcap, -1, &_handle_pcap_frame, (u_char*)(i)) == -1)
+				{
+					log_printf(LOG_ERROR, "Could not dispatch frames on WinPcap interface: %s", pcap_geterr(i->pcap));
+					log_printf(LOG_WARNING, "No more IPX packets will be received");
+					
+					exit_status = 1;
+					break;
+				}
+			}
+		}
+		else{
+			if(!_do_udp_recv(shared_socket) || !_do_udp_recv(private_socket))
+			{
+				exit_status = 1;
+				break;
+			}
 		}
 	}
 	
-	return 0;
+	if(ipx_use_pcap)
+	{
+		free(wait_events);
+		free_ipx_interface_list(&interfaces);
+	}
+	
+	return exit_status;
 }