SITA ACN support, from Fulko Hew.
diff --git a/CREDITS b/CREDITS
index 0a01153..b357383 100644
--- a/CREDITS
+++ b/CREDITS
@@ -34,6 +34,7 @@
         Erik de Castro Lopo             <erik.de.castro.lopo@sensorynetworks.com>
 	Florent Drouin			<Florent.Drouin@alcatel-lucent.fr>
 	Franz Schaefer			<schaefer@mond.at>
+	Fulko Hew			<fulko.hew@gmail.com>
 	Gianluca Varenni		<varenni@netgroup-serv.polito.it>
 	Gilbert Hoyek			<gil_hoyek@hotmail.com>
 	Gisle Vanem			<giva@bgnett.no>
diff --git a/FILES b/FILES
index bb2d6f8..307d96e 100644
--- a/FILES
+++ b/FILES
@@ -13,6 +13,7 @@
 README.linux
 README.macosx
 README.septel
+README.sita
 README.tru64
 README.Win32
 SUNOS4/nit_if.o.sparc
@@ -38,6 +39,7 @@
 fad-gifc.c
 fad-glifc.c
 fad-null.c
+fad-sita.c
 fad-win32.c
 filtertest.c
 findalldevstest.c
@@ -101,6 +103,9 @@
 pcap-pf.h
 pcap-septel.c
 pcap-septel.h
+pcap-sita.h
+pcap-sita.c
+pcap-sita.html
 pcap-stdinc.h
 pcap-snit.c
 pcap-snoop.c
diff --git a/INSTALL.txt b/INSTALL.txt
index 8876b93..d322c1c 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -1,4 +1,4 @@
-@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.21 2007-09-22 02:10:17 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.22 2007-10-20 01:15:14 guy Exp $ (LBL)
 
 To build libpcap, run "./configure" (a shell script). The configure
 script will determine your system attributes and generate an
@@ -309,6 +309,7 @@
 README.linux	- notes on using libpcap on Linux
 README.macosx	- notes on using libpcap on Mac OS X
 README.septel   - notes on using libpcap to capture on Intel/Septel devices
+README.sita	- notes on using libpcap to capture on SITA devices
 README.tru64	- notes on using libpcap on Digital/Tru64 UNIX
 README.Win32	- notes on using libpcap on Win32 systems (with WinPcap)
 SUNOS4		- pre-SunOS 4.1 replacement kernel nit modules
@@ -332,6 +333,7 @@
 fad-gifc.c	- pcap_findalldevs() for systems with only SIOCGIFLIST
 fad-glifc.c	- pcap_findalldevs() for systems with SIOCGLIFCONF
 fad-null.c	- pcap_findalldevs() for systems without capture support
+fad-sita.c	- pcap_findalldevs() for systems with SITA support
 fad-win32.c	- pcap_findalldevs() for WinPcap
 filtertest.c	- test program for BPF compiler
 findalldevstest.c - test program for pcap_findalldevs()
@@ -377,6 +379,9 @@
 pcap-pf.h	- Ultrix and Digital/Tru64 UNIX Packet Filter definitions
 pcap-septel.c   - Intel/Septel device capture support
 pcap-septel.h   - Intel/Septel device capture support
+pcap-sita.c	- SITA device capture support
+pcap-sita.h	- SITA device capture support
+pcap-sita.html	- SITA device capture documentation
 pcap-stdinc.h	- includes and #defines for compiling on Win32 systems
 pcap-snit.c	- SunOS 4.x STREAMS-based Network Interface Tap support
 pcap-snoop.c	- IRIX Snoop network monitoring support
diff --git a/README.sita b/README.sita
new file mode 100644
index 0000000..9b7e360
--- /dev/null
+++ b/README.sita
@@ -0,0 +1,61 @@
+The following instructions apply if you have a Linux platform and want
+libpcap to support the 'ACN' WAN/LAN router product from from SITA
+(http://www.sita.aero)
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+These additions/extensions have been made to PCAP to allow it to
+capture packets from a SITA ACN device (and potentially others).
+
+To enable its support you need to ensure that the distribution has
+a correct configure.in file; that can be created if neccessay by
+using the normal autoconf procedure of:
+
+aclocal
+autoconf
+autoheader
+automake
+
+Then run configure with the 'sita' option:
+
+./configure --with-sita
+
+Applications built with libpcap configured in this way will only detect SITA
+ACN interfaces and will not capture from the native OS packet stream.
+
+The SITA extension provides a remote datascope operation for capturing
+both WAN and LAN protocols.  It effectively splits the operation of
+PCAP into two halves.  The top layer performs the majority of the
+work, but interfaces via a TCP session to remote agents that
+provide the lower layer functionality of actual sniffing and
+filtering. More detailed information regarding the functions and
+inter-device protocol and naming conventions are described in detail
+in 'pcap-sita.html'.
+
+pcap_findalldevs() reads the local system's /etc/hosts file looking
+for host names that match the format of IOP type devices.  ie.  aaa_I_x_y
+and then queries each associated IP address for a list of its WAN and
+LAN devices.  The local system the aggregates the lists obtained from
+each IOP, sorts it, and provides it (to Wireshark et.al) as the
+list of monitorable interfaces.
+
+Once a valid interface has been selected, pcap_open() is called
+which opens a TCP session (to a well known port) on the target IOP
+and tells it to start monitoring.
+
+All captured packets are then forwarded across that TCP session
+back to the local 'top layer' for forwarding to the actual
+sniffing program (wireshark...)
+
+Note that the DLT_SITA protocol includes a proprietary header
+that is documented as part of the SITA dissector of Wireshark
+and is also described in 'pcap-sita.html' for posterity sake.
+
+That header provides:
+- Packet direction (in/out) (1 octet)
+- Link layer hardware signal status (1 octet)
+- Transmit/Receive error status (2 octets)
+- Encapsulated WAN protocol ID (1 octet)
+
+
diff --git a/atmuni31.h b/atmuni31.h
index b06cd39..5920e55 100644
--- a/atmuni31.h
+++ b/atmuni31.h
@@ -29,13 +29,13 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1 2002-07-11 09:06:32 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.2 2007-10-20 01:15:14 guy Exp $ (LBL)
  */
 
 /* Based on UNI3.1 standard by ATM Forum */
 
 /* ATM traffic types based on VPI=0 and (the following VCI */
-#define PPC			0x05	/* Point-to-point signal msg */
+#define ATM_PPC			0x05	/* Point-to-point signal msg */
 #define BCC			0x02	/* Broadcast signal msg */
 #define OAMF4SC			0x03	/* Segment OAM F4 flow cell */
 #define OAMF4EC			0x04	/* End-to-end OAM F4 flow cell */
diff --git a/config.h.in b/config.h.in
index 7a39758..bda5e91 100644
--- a/config.h.in
+++ b/config.h.in
@@ -182,6 +182,9 @@
 /* target host supports USB sniffing */
 #undef PCAP_SUPPORT_USB
 
+/* include ACN support */
+#undef SITA
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
diff --git a/configure b/configure
index f2a0f93..1b4556d 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.138 .
+# From configure.in Revision: 1.139 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61.
 #
@@ -1289,6 +1289,7 @@
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --without-gcc           don't use gcc
   --with-pcap=TYPE        use packet capture TYPE
+  --with-sita             include SITA support
   --with-dag[=DIR]        include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)
   --with-dag-includes=DIR   Endace DAG include directory
   --with-dag-libraries=DIR  Endace DAG library directory
@@ -6341,6 +6342,22 @@
 _ACEOF
 
    fi
+
+# Check whether --with-sita was given.
+if test "${with_sita+set}" = set; then
+  withval=$with_sita;
+
+cat >>confdefs.h <<\_ACEOF
+#define SITA 1
+_ACEOF
+
+		SSRC="pcap-sita.c"
+		{ echo "$as_me:$LINENO: Enabling SITA ACN support" >&5
+echo "$as_me: Enabling SITA ACN support" >&6;}
+		V_FINDALLDEVS=sita
+
+fi
+
 	;;
 
 dag)
diff --git a/configure.in b/configure.in
index 2e1eb8a..a95cbaa 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.138 2007-10-04 23:06:25 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.139 2007-10-20 01:15:14 guy Exp $ (LBL)
 dnl
 dnl Copyright (c) 1994, 1995, 1996, 1997
 dnl	The Regents of the University of California.  All rights reserved.
@@ -6,7 +6,7 @@
 dnl Process this file with autoconf to produce a configure script.
 dnl
 
-AC_REVISION($Revision: 1.138 $)
+AC_REVISION($Revision: 1.139 $)
 AC_PREREQ(2.50)
 AC_INIT(pcap.c)
 
@@ -371,6 +371,13 @@
 		AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
 	fi
 	AC_LBL_TPACKET_STATS
+	AC_ARG_WITH(sita, [  --with-sita             include SITA support],
+	[
+		AC_DEFINE(SITA,1,[include ACN support])
+		SSRC="pcap-sita.c"
+		AC_MSG_NOTICE(Enabling SITA ACN support)
+		V_FINDALLDEVS=sita
+	])
 	;;
 
 dag)
diff --git a/fad-sita.c b/fad-sita.c
new file mode 100644
index 0000000..f985e31
--- /dev/null
+++ b/fad-sita.c
@@ -0,0 +1,62 @@
+/*
+ *  fad-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ *  Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ *  License: BSD
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of the authors may not be used to endorse or promote
+ *     products derived from this software without specific prior
+ *     written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: fad-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "pcap-int.h"
+
+extern pcap_if_t	*acn_if_list;								/* pcap's list of available interfaces */
+
+extern int acn_parse_hosts_file(char *errbuf);
+extern int acn_findalldevs(char *errbuf);
+
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) {
+
+	//printf("pcap_findalldevs()\n");				// fulko
+
+	*alldevsp = 0;												/* initialize the returned variables before we do anything */
+	strcpy(errbuf, "");
+	if (acn_parse_hosts_file(errbuf))							/* scan the hosts file for potential IOPs */
+		{
+		//printf("pcap_findalldevs() returning BAD after parsehosts\n");				// fulko
+		return -1;
+		}
+	//printf("pcap_findalldevs() got hostlist now finding devs\n");				// fulko
+	if (acn_findalldevs(errbuf))								/* then ask the IOPs for their monitorable devices */
+		{
+		//printf("pcap_findalldevs() returning BAD after findalldevs\n");				// fulko
+		return -1;
+		}
+	*alldevsp = acn_if_list;
+	acn_if_list = 0;											/* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+	//printf("pcap_findalldevs() returning ZERO OK\n");				// fulko
+	return 0;
+}
diff --git a/pcap-linux.c b/pcap-linux.c
index ce3ee3f..a2b198a 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -27,7 +27,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129 2007-10-05 01:40:14 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.130 2007-10-20 01:15:14 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -96,6 +96,10 @@
 #include "pcap-bt-linux.h"
 #endif
 	  
+#ifdef SITA
+#include "pcap-sita.h"
+#endif
+
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -324,6 +328,12 @@
 	 * trying both methods with the newer method preferred.
 	 */
 
+#ifdef SITA
+	live_open_ok = acn_open_live((unsigned char *)device, ebuf, &handle->linktype);
+	handle->md.clear_promisc = promisc;
+	handle->fd = live_open_ok;
+	handle->bufsize = handle->snapshot;
+#else
 	if ((err = live_open_new(handle, device, promisc, to_ms, ebuf)) == 1)
 		live_open_ok = 1;
 	else if (err == 0) {
@@ -331,6 +341,7 @@
 		if (live_open_old(handle, device, promisc, to_ms, ebuf))
 			live_open_ok = 1;
 	}
+#endif
 	if (!live_open_ok) {
 		/*
 		 * Both methods to open the packet socket failed. Tidy
@@ -344,6 +355,7 @@
 		return NULL;
 	}
 
+#ifndef SITA
 	/*
 	 * Compute the buffer size.
 	 *
@@ -426,6 +438,7 @@
 		}
 		handle->bufsize = handle->snapshot;
 	}
+#endif
 
 	/* Allocate the buffer */
 
@@ -444,16 +457,22 @@
 	 */
 	handle->selectable_fd = handle->fd;
 
-	handle->read_op = pcap_read_linux;
 	handle->inject_op = pcap_inject_linux;
 	handle->setfilter_op = pcap_setfilter_linux;
 	handle->setdirection_op = pcap_setdirection_linux;
 	handle->set_datalink_op = NULL;	/* can't change data link type */
 	handle->getnonblock_op = pcap_getnonblock_fd;
 	handle->setnonblock_op = pcap_setnonblock_fd;
-	handle->stats_op = pcap_stats_linux;
 	handle->close_op = pcap_close_linux;
 
+#ifdef SITA
+	handle->read_op = pcap_read_acn;
+	handle->stats_op = pcap_stats_acn;
+#else
+	handle->read_op = pcap_read_linux;
+	handle->stats_op = pcap_stats_linux;
+#endif
+
 	return handle;
 }
 
@@ -968,6 +987,10 @@
 		return -1;
 	}
 
+#ifdef SITA
+	return acn_setfilter(handle->fd, filter);
+#endif
+
 	/* Make our private copy of the filter */
 
 	if (install_bpf_program(handle, filter) < 0)
@@ -1729,6 +1752,11 @@
 
 static void	pcap_close_linux( pcap_t *handle )
 {
+#ifdef SITA
+	pcap_close_acn(handle);
+	return;
+#endif
+
 	struct pcap	*p, *prevp;
 	struct ifreq	ifr;
 
diff --git a/pcap-sita.c b/pcap-sita.c
new file mode 100644
index 0000000..d892d11
--- /dev/null
+++ b/pcap-sita.c
@@ -0,0 +1,905 @@
+/*
+ *  pcap-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ *  Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ *  License: BSD
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of the authors may not be used to endorse or promote
+ *     products derived from this software without specific prior
+ *     written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: pcap-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "pcap-int.h"
+
+	/* non-configureable manifests follow */
+
+#define IOP_SNIFFER_PORT	49152			/* TCP port on the IOP used for 'distributed pcap' usage */
+#define MAX_LINE_SIZE		255				/* max size of a buffer/line in /etc/hosts we allow */
+#define MAX_CHASSIS			8				/* number of chassis in an ACN site */
+#define MAX_GEOSLOT			8				/* max number of access units in an ACN site */
+
+#define FIND			0
+#define LIVE			1
+
+typedef struct iface {
+	struct iface	*next;					/* a pointer to the next interface */
+	char			*name;					/* this interface's name on Wireshark */
+	char			*IOPname;				/* this interface's name on an IOP */
+	uint32_t		iftype;					/* the type of interface (DLT values) */
+} iface_t;
+
+typedef struct unit {
+	char				*ip;				/* this unit's IP address (as extracted from /etc/hosts) */
+	int					fd;					/* the connection to this unit (if it exists) */
+	int					find_fd;			/* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
+	int					first_time;			/* 0 = just opened via acn_open_live(),  ie. the first time, NZ = nth time */
+	struct sockaddr_in	*serv_addr;			/* the address control block for comms to this unit */
+	int					chassis;
+	int					geoslot;
+	iface_t				*iface;				/* a pointer to a linked list of interface structures */
+	char				*imsg;				/* a pointer to an inbound message */
+	int					len;				/* the current size of the inbound message */
+} unit_t;
+
+static char			*errorString;
+static unit_t		units[MAX_CHASSIS+1][MAX_GEOSLOT+1];	/* we use indexes of 1 through 8, but we reserve/waste index 0 */
+static fd_set		readfds;								/* a place to store the file descriptors for the connections to the IOPs */
+static fd_set		working_set;
+static int			max_fs;
+static char			static_buf[32];
+
+pcap_if_t			*acn_if_list;							/* pcap's list of available interfaces */
+
+static void dump_interface_list() {
+	pcap_if_t		*iff;
+	pcap_addr_t		*addr;
+	int				longest_name_len = 0;
+	char			*n, *d, *f;
+	int				if_number = 0;
+
+	iff = acn_if_list;
+	while (iff) {
+		if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name);
+		iff = iff->next;
+	}
+	iff = acn_if_list;
+	printf("Interface List:\n");
+	while (iff) {
+		n = (iff->name)							? iff->name			: "";
+		d = (iff->description)					? iff->description	: "";
+		f = (iff->flags == PCAP_IF_LOOPBACK)	? "L"				: "";
+		printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d);
+		addr = iff->addresses;
+		while (addr) {
+			printf("%*s ", (5 + longest_name_len), "");		/* add some indentation */
+			printf("%15s  ", (addr->addr)		? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr)		: "");
+			printf("%15s  ", (addr->netmask)	? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr)	: "");
+			printf("%15s  ", (addr->broadaddr)	? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr)	: "");
+			printf("%15s  ", (addr->dstaddr)	? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr)	: "");
+			printf("\n");
+			addr = addr->next;
+		}
+		iff = iff->next;
+	}
+}
+
+static dump(unsigned char *ptr, int i, int indent) {
+	fprintf(stderr, "%*s", indent, " ");
+	for (; i > 0; i--) {
+		fprintf(stderr, "%2.2x ", *ptr++);
+	}
+	fprintf(stderr, "\n");
+}
+
+static void dump_interface_list_p() {
+	pcap_if_t		*iff;
+	pcap_addr_t		*addr;
+	int				longest_name_len = 0;
+	char			*n, *d, *f;
+	int				if_number = 0;
+
+	iff = acn_if_list;
+	printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff);
+	while (iff) {
+		printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next);
+		dump((unsigned char *)iff, sizeof(pcap_if_t), 5);
+		addr = iff->addresses;
+		while (addr) {
+			printf("          %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next);
+			dump((unsigned char *)addr, sizeof(pcap_addr_t), 10);
+			addr = addr->next;
+		}
+		iff = iff->next;
+	}
+}
+
+static void dump_unit_table() {
+	int		chassis, geoslot;
+	iface_t	*p;
+
+	printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address");
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+			if (units[chassis][geoslot].ip != NULL)
+				printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip);
+			p = units[chassis][geoslot].iface;
+			while (p) {
+				char *n = (p->name)			? p->name			: "";
+				char *i = (p->IOPname)		? p->IOPname		: "";
+				p = p->next;
+				printf("   %12s    -> %12s\n", i, n);
+			}
+		}
+	}
+}
+
+static int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) {
+	int		c, s;
+
+	for (c = 0; c <= MAX_CHASSIS; c++) {
+		for (s = 0; s <= MAX_GEOSLOT; s++) {
+			if (units[c][s].fd == fd || units[c][s].find_fd == fd) {
+				if (chassis)	*chassis = c;
+				if (geoslot)	*geoslot = s;
+				if (unit_ptr)	*unit_ptr = &units[c][s];
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+static int read_client_nbytes(int fd, int count, unsigned char *buf) {
+	unit_t			*u;
+	int				chassis, geoslot;
+	int				len;
+
+	find_unit_by_fd(fd, &chassis, &geoslot, &u);
+	while (count) {
+		if ((len = recv(fd, buf, count, 0)) <= 0)	return -1;	/* read in whatever data was sent to us */
+		count -= len;	
+		buf += len;
+	}															/* till we have everything we are looking for */
+	return 0;
+}
+
+static void empty_unit_iface(unit_t *u) {
+	iface_t	*p, *cur;
+
+	cur = u->iface;
+	while (cur) {											/* loop over all the interface entries */
+		if (cur->name)			free(cur->name);			/* throwing away the contents if they exist */
+		if (cur->IOPname)		free(cur->IOPname);
+		p = cur->next;
+		free(cur);											/* then throw away the structure itself */
+		cur = p;
+	}
+	u->iface = 0;											/* and finally remember that there are no remaining structure */
+}
+
+static void empty_unit(int chassis, int geoslot) {
+	iface_t	*p, *cur;
+	unit_t	*u = &units[chassis][geoslot];
+
+	empty_unit_iface(u);
+	if (u->imsg) {											/* then if an inbound message buffer exists */
+		u->imsg = (char *)realloc(u->imsg, 1);				/* and re-allocate the old large buffer into a new small one */
+	}
+}
+
+static void empty_unit_table() {
+	int		chassis, geoslot;
+
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+			if (units[chassis][geoslot].ip != NULL) {
+				free(units[chassis][geoslot].ip);			/* get rid of the malloc'ed space that holds the IP address */
+				units[chassis][geoslot].ip = 0;				/* then set the pointer to NULL */
+			}
+			empty_unit(chassis, geoslot);
+		}
+	}
+}
+
+static char *find_nth_interface_name(int n) {
+	int		chassis, geoslot;
+	iface_t	*p;
+	char	*last_name = 0;
+
+	if (n < 0) n = 0;												/* ensure we are working with a valid number */
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {			/* scan the table... */
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+			if (units[chassis][geoslot].ip != NULL) {
+				p = units[chassis][geoslot].iface;
+				while (p) {											/* and all interfaces... */
+					if (p->IOPname) last_name = p->name;			/* remembering the last name found */
+					if (n-- == 0) return last_name;					/* and if we hit the instance requested */
+					p = p->next;
+				}
+			}
+		}
+	}
+											/* if we couldn't fine the selected entry */
+	if (last_name)	return last_name;		/* ... but we did have at least one entry... return the last entry found */
+	return "";								/* ... but if there wasn't any entry... return an empty string instead */
+}
+
+int acn_parse_hosts_file(char *errbuf) {				/* returns: -1 = error, 0 = OK */
+	FILE	*fp;
+	char	buf[MAX_LINE_SIZE];
+	char	*ptr, *ptr2;
+	int		pos;
+	int		chassis, geoslot;
+	unit_t	*u;
+
+	empty_unit_table();
+	if ((fp = fopen("/etc/hosts", "r")) == NULL) {										/* try to open the hosts file and if it fails */
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading.");	/* return the nohostsfile error response */
+		return -1;
+	}
+	while (fgets(buf, MAX_LINE_SIZE-1, fp)) {			/* while looping over the file */
+
+		pos = strcspn(buf, "#\n\r");					/* find the first comment character or EOL */
+		*(buf + pos) = '\0';							/* and clobber it and anything that follows it */
+
+		pos = strspn(buf, " \t");						/* then find the first non-white space */
+		if (pos == strlen(buf))							/* if there is nothing but white space on the line */
+			continue;									/* ignore that empty line */
+		ptr = buf + pos;								/* and skip over any of that leading whitespace */
+
+		if ((ptr2 = strstr(ptr, "_I_")) == NULL)		/* skip any lines that don't have names that look like they belong to IOPs */
+			continue;
+		if (*(ptr2 + 4) != '_')							/* and skip other lines that have names that don't look like ACN components */
+			continue;
+		*(ptr + strcspn(ptr, " \t")) = '\0';			/* null terminate the IP address so its a standalone string */
+
+		chassis = *(ptr2 + 3) - '0';					/* extract the chassis number */
+		geoslot = *(ptr2 + 5) - '0';					/* and geo-slot number */
+		if (chassis < 1 || chassis > MAX_CHASSIS ||
+			geoslot < 1 || geoslot > MAX_GEOSLOT) {		/* if the chassis and/or slot numbers appear to be bad... */
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'.");	/* warn the user */
+			continue;																	/* and ignore the entry */
+		}
+		if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+			continue;
+		}
+		strcpy(ptr2, ptr);								/* copy the IP address into our malloc'ed memory */
+		u = &units[chassis][geoslot];
+		u->ip = ptr2;									/* and remember the whole shebang */
+		u->chassis = chassis;
+		u->geoslot = geoslot;
+	}
+	fclose(fp);
+	if (*errbuf)	return -1;
+	else			return 0;
+}
+
+static int open_with_IOP(unit_t  *u, int flag) {
+	int					sockfd;
+	char				*ip;
+
+	if (u->serv_addr == NULL) {
+		u->serv_addr = malloc(sizeof(struct sockaddr_in));
+	}
+	ip = u->ip;
+	bzero((char *)u->serv_addr, sizeof(struct sockaddr_in));
+	u->serv_addr->sin_family		= AF_INET;
+	u->serv_addr->sin_addr.s_addr	= inet_addr(ip);
+	u->serv_addr->sin_port			= htons(IOP_SNIFFER_PORT);
+
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip);
+		return 0;
+	}
+	if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) {
+		fprintf(stderr, "pcap can't connect to IOP at %s\n", ip);
+		return 0;
+	}
+	if (flag == LIVE)	u->fd = sockfd;
+	else				u->find_fd = sockfd;
+	u->first_time = 0;
+	return sockfd;			/* return the non-zero file descriptor as a 'success' indicator */
+}
+
+static void close_with_IOP(int chassis, int geoslot, int flag) {
+	int		*id;
+
+	if (flag == LIVE)	id = &units[chassis][geoslot].fd;
+	else				id = &units[chassis][geoslot].find_fd;
+
+	if (*id) {										/* this was the last time, so... if we are connected... */
+		close(*id);									/* disconnect us */
+		*id = 0;									/* and forget that the descriptor exists because we are not open */
+	}
+}
+
+void pcap_close_acn(pcap_t *handle) {
+	int		chassis, geoslot;
+	unit_t	*u;
+
+	if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0)
+		return;
+	close_with_IOP(chassis, geoslot, LIVE);
+	if (u)
+		u->first_time = 0;
+}
+
+static void send_to_fd(int fd, int len, unsigned char *str) {
+	int		nwritten;
+	int		chassis, geoslot;
+
+	while (len > 0) {
+		if ((nwritten = write(fd, str, len)) <= 0) {
+			find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+			if (units[chassis][geoslot].fd == fd)			close_with_IOP(chassis, geoslot, LIVE);
+			else if (units[chassis][geoslot].find_fd == fd)	close_with_IOP(chassis, geoslot, FIND);
+			empty_unit(chassis, geoslot);
+			return;
+		}
+		len -= nwritten;
+		str += nwritten;
+	}
+}
+
+static void acn_freealldevs() {
+
+	pcap_if_t	*iff, *next_iff;
+	pcap_addr_t	*addr, *next_addr;
+
+	for (iff = acn_if_list; iff != NULL; iff = next_iff) {
+		next_iff = iff->next;
+		for (addr = iff->addresses; addr != NULL; addr = next_addr) {
+			next_addr = addr->next;
+			if (addr->addr)			free(addr->addr);
+			if (addr->netmask)		free(addr->netmask);
+			if (addr->broadaddr)	free(addr->broadaddr);
+			if (addr->dstaddr)		free(addr->dstaddr);
+			free(addr);
+		}
+		if (iff->name)			free(iff->name);
+		if (iff->description)	free(iff->description);
+		free(iff);
+	}
+}
+
+static char *nonUnified_port_num(unit_t *u, int IOPportnum) {
+
+	sprintf(static_buf, "%d_%d", u->chassis, u->geoslot);
+	return static_buf;
+}
+
+static char *unified_port_num(unit_t *u, int IOPportnum) {
+	int			portnum;
+
+	portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
+	sprintf(static_buf, "%d", portnum);
+	return static_buf;
+}
+
+static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, ulong iftype) {
+	iface_t		*iface_ptr, *iface;
+	char		*name;
+	char		buf[32];
+	char		*proto;
+	char		*port;
+	int			IOPportnum = 0;
+
+	iface = malloc(sizeof(iface_t));		/* get memory for a structure */
+	bzero((char *)iface, sizeof(iface_t));
+
+	iface->iftype = iftype;					/* remember the interface type of this interface */
+
+	name = malloc(strlen(IOPname) + 1);		/* get memory for the IOP's name */
+	strcpy(name, IOPname);					/* and copy it in */
+	iface->IOPname = name;					/* and stick it into the structure */
+
+	if (strncmp(IOPname, "lo", 2) == 0) {
+		IOPportnum = atoi(&IOPname[2]);
+		switch (iftype) {
+			case DLT_EN10MB:	proto = "lo";		port = nonUnified_port_num(u, IOPportnum);	break;
+			default:			proto = "???";		port = unified_port_num(u, IOPportnum);		break;
+		}
+	} else if (strncmp(IOPname, "eth", 3) == 0) {
+		IOPportnum = atoi(&IOPname[3]);
+		switch (iftype) {
+			case DLT_EN10MB:	proto = "eth";		port = nonUnified_port_num(u, IOPportnum);	break;
+			default:			proto = "???";		port = unified_port_num(u, IOPportnum);		break;
+		}
+	} else if (strncmp(IOPname, "wan", 3) == 0) {
+		IOPportnum = atoi(&IOPname[3]);
+		switch (iftype) {
+			case DLT_SITA:		proto = "wan";		port = unified_port_num(u, IOPportnum);		break;
+			default:			proto = "???";		port = unified_port_num(u, IOPportnum);		break;
+		}
+	}
+
+	sprintf(buf, "%s_%s", proto, port);		/* compose the user's name for that IOP port name */
+	name = malloc(strlen(buf) + 1);			/* get memory for that name */
+	strcpy(name, buf);						/* and copy it in */
+	iface->name = name;						/* and stick it into the structure */
+
+	if (u->iface == 0) {					/* if this is the first name */
+		u->iface = iface;					/* stick this entry at the head of the list */
+	} else {
+		iface_ptr = u->iface;
+		while (iface_ptr->next) {			/* othewise scan the list */
+			iface_ptr = iface_ptr->next;	/* till we're at the last entry */
+		}
+		iface_ptr->next = iface;			/* then tack this entry on the end of the list */
+	}
+	return iface->name;
+}
+
+static int if_sort(char *s1, char *s2) {
+	char	*s1_p2, *s2_p2;
+	char	str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE];
+	int		s1_p1_len, s2_p1_len;
+	int		retval;
+
+	if ((s1_p2 = strchr(s1, '_'))) {	/* if an underscore is found... */
+		s1_p1_len = s1_p2 - s1;			/* the prefix length is the difference in pointers */
+		s1_p2++;						/* the suffix actually starts _after_ the underscore */
+	} else {							/* otherwise... */
+		s1_p1_len = strlen(s1);			/* the prefix length is the length of the string itself */
+		s1_p2 = 0;						/* and there is no suffix */
+	}
+	if ((s2_p2 = strchr(s2, '_'))) {	/* now do the same for the second string */
+		s2_p1_len = s2_p2 - s2;
+		s2_p2++;
+	} else {
+		s2_p1_len = strlen(s2);
+		s2_p2 = 0;
+	}
+	strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1));   *(str1 + s1_p1_len) = 0;
+	strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2));   *(str2 + s2_p1_len) = 0;
+	retval = strcmp(str1, str2);
+	if (retval != 0) return retval;		/* if they are not identical, then we can quit now and return the indication */
+	return strcmp(s1_p2, s2_p2);		/* otherwise we return the result of comparing the 2nd half of the string */
+}
+
+static void sort_if_table() {
+	pcap_if_t	*p1, *p2, *prev, *temp;
+	int			has_swapped;
+
+	if (!acn_if_list) return;				/* nothing to do if the list is empty */
+
+	while (1) {
+		p1 = acn_if_list;					/* start at the head of the list */
+		prev = 0;
+		has_swapped = 0;
+		while ((p2 = p1->next)) {
+			if (if_sort(p1->name, p2->name) > 0) {
+				if (prev) {					/* we are swapping things that are _not_ at the head of the list */
+					temp = p2->next;
+					prev->next = p2;
+					p2->next = p1;
+					p1->next = temp;
+				} else {					/* special treatment if we are swapping with the head of the list */
+					temp = p2->next;
+					acn_if_list= p2;
+					p2->next = p1;
+					p1->next = temp;
+				}
+				p1 = p2;
+				prev = p1;
+				has_swapped = 1;
+			}
+			prev = p1;
+			p1 = p1->next;
+		}
+		if (has_swapped == 0)
+			return;
+	}	
+	return;
+}
+	
+static int process_client_data (char *errbuf) {								/* returns: -1 = error, 0 = OK */
+	int					chassis, geoslot;
+	unit_t				*u;
+	pcap_if_t			*iff, *prev_iff;
+	pcap_addr_t			*addr, *prev_addr;
+	char				*ptr;
+	int					address_count;
+	struct sockaddr_in	*s;
+	char				*newname;
+	ulong				interfaceType;
+	unsigned char		flags;
+
+	prev_iff = 0;
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {				/* now loop over all the devices */
+			u = &units[chassis][geoslot];
+			empty_unit_iface(u);
+			ptr = u->imsg;													/* point to the start of the msg for this IOP */
+			while (ptr < (u->imsg + u->len)) {
+				if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
+					snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+					return -1;
+				}
+				bzero((char *)iff, sizeof(pcap_if_t));
+				if (acn_if_list == 0)	acn_if_list = iff;					/* remember the head of the list */
+				if (prev_iff)			prev_iff->next = iff;				/* insert a forward link */
+
+				if (*ptr) {													/* if there is a count for the name */
+					if ((iff->name = malloc(*ptr + 1)) == NULL) {			/* get that amount of space */
+						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						return -1;
+					}
+					memcpy(iff->name, (ptr + 1), *ptr);						/* copy the name into the malloc'ed space */
+					*(iff->name + *ptr) = 0;								/* and null terminate the string */
+					ptr += *ptr;											/* now move the pointer forwards by the length of the count plus the length of the string */
+				}
+				ptr++;
+
+				if (*ptr) {													/* if there is a count for the description */
+					if ((iff->description = malloc(*ptr + 1)) == NULL) {	/* get that amount of space */
+						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						return -1;
+					}
+					memcpy(iff->description, (ptr + 1), *ptr);				/* copy the name into the malloc'ed space */
+					*(iff->description + *ptr) = 0;							/* and null terminate the string */
+					ptr += *ptr;											/* now move the pointer forwards by the length of the count plus the length of the string */
+				}
+				ptr++;
+
+				interfaceType = ntohl(*(ulong *)ptr);
+				ptr += 4;													/* skip over the interface type */
+
+				flags = *ptr++;
+				if (flags) iff->flags = PCAP_IF_LOOPBACK;					/* if this is a loopback style interface, lets mark it as such */
+
+				address_count = *ptr++;
+
+				prev_addr = 0;
+				while (address_count--) {
+					if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
+						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						return -1;
+					}
+					bzero((char *)addr, sizeof(pcap_addr_t));
+					if (iff->addresses == 0) iff->addresses = addr;
+					if (prev_addr) prev_addr->next = addr;							/* insert a forward link */
+					if (*ptr) {														/* if there is a count for the address */
+						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {		/* get that amount of space */
+							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							return -1;
+						}
+						bzero((char *)s, sizeof(struct sockaddr_in));
+						addr->addr = (struct sockaddr *)s;
+						s->sin_family		= AF_INET;
+						s->sin_addr.s_addr	= *(ulong *)(ptr + 1);			/* copy the address in */
+						ptr += *ptr;										/* now move the pointer forwards according to the specified length of the address */
+					}
+					ptr++;													/* then forwards one more for the 'length of the address' field */
+					if (*ptr) {												/* process any netmask */
+						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							return -1;
+						}
+						bzero((char *)s, sizeof(struct sockaddr_in));
+						addr->netmask = (struct sockaddr *)s;
+						s->sin_family		= AF_INET;
+						s->sin_addr.s_addr	= *(ulong*)(ptr + 1);
+						ptr += *ptr;
+					}
+					ptr++;
+					if (*ptr) {												/* process any broadcast address */
+						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							return -1;
+						}
+						bzero((char *)s, sizeof(struct sockaddr_in));
+						addr->broadaddr = (struct sockaddr *)s;
+						s->sin_family		= AF_INET;
+						s->sin_addr.s_addr	= *(ulong*)(ptr + 1);
+						ptr += *ptr;
+					}
+					ptr++;
+					if (*ptr) {												/* process any destination address */
+						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							return -1;
+						}
+						bzero((char *)s, sizeof(struct sockaddr_in));
+						addr->dstaddr = (struct sockaddr *)s;
+						s->sin_family		= AF_INET;
+						s->sin_addr.s_addr	= *(ulong*)(ptr + 1);
+						ptr += *ptr;
+					}
+					ptr++;
+					prev_addr = addr;
+				}
+				prev_iff = iff;
+
+				newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType);		/* add a translation entry and get a point to the mangled name */
+				if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) {	/* we now re-write the name stored in the interface list */
+					snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+					return -1;
+				}
+				strcpy(iff->name, newname);												/* to this new name */
+			}
+		}
+	}
+	return 0;
+}
+
+static int read_client_data (int fd) {
+	unsigned char	buf[256];
+	int				chassis, geoslot;
+	unit_t			*u;
+	int				len;
+
+	find_unit_by_fd(fd, &chassis, &geoslot, &u);
+
+	if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0)	return 0;	/* read in whatever data was sent to us */
+
+	if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL)	/* extend the buffer for the new data */
+		return 0;
+	memcpy((u->imsg + u->len), buf, len);						/* append the new data */
+	u->len += len;
+	return 1;
+}
+
+static void wait_for_all_answers() {
+	int		retval;
+	struct	timeval tv;
+	int		fd;
+	int		chassis, geoslot;
+
+	tv.tv_sec = 2;
+	tv.tv_usec = 0;
+
+	while (1) {
+		int flag = 0;
+		for (fd = 0; fd <= max_fs; fd++) {								/* scan the list of descriptors we may be listening to */
+			if (FD_ISSET(fd, &readfds)) flag = 1;						/* and see if there are any still set */
+		}
+		if (flag == 0) return;											/* we are done, when they are all gone */
+
+		memcpy(&working_set, &readfds, sizeof(readfds));				/* otherwise, we still have to listen for more stuff, till we timeout */
+		retval = select(max_fs + 1, &working_set, NULL, NULL, &tv);
+		if (retval == -1) {												/* an error occured !!!!! */
+			return;
+		} else if (retval == 0) {										/* timeout occured, so process what we've got sofar and return */
+			printf("timeout\n");
+			return;
+		} else {
+			for (fd = 0; fd <= max_fs; fd++) {							/* scan the list of things to do, and do them */
+				if (FD_ISSET(fd, &working_set)) {
+					if (read_client_data(fd) == 0) {					/* if the socket has closed */
+						FD_CLR(fd, &readfds);							/* and descriptors we listen to for errors */
+						find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+						close_with_IOP(chassis, geoslot, FIND);			/* and close out connection to him */
+					}
+				}
+			}
+		}
+	}
+}
+
+static char *get_error_response(int fd, char *errbuf) {		/* return a pointer on error, NULL on no error */
+	char	byte;
+	int		len = 0;
+
+	while (1) {
+		recv(fd, &byte, 1, 0);							/* read another byte in */
+		if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) {		/* and if there is still room in the buffer */
+			*errbuf++ = byte;							/* stick it in */
+			*errbuf = '\0';								/* ensure the string is null terminated just in case we might exceed the buffer's size */
+		}
+		if (byte == '\0')
+			if (len > 1)	{ return errbuf;	}
+			else			{ return NULL;		}
+	}
+}
+
+int acn_findalldevs(char *errbuf) {								/* returns: -1 = error, 0 = OK */
+	int		chassis, geoslot;
+	unit_t	*u;
+
+	FD_ZERO(&readfds);
+	max_fs = 0;
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+			u = &units[chassis][geoslot];
+			if (u->ip && (open_with_IOP(u, FIND))) {			/* connect to the remote IOP */
+				send_to_fd(u->find_fd, 1, (unsigned char *)"\0");
+				if (get_error_response(u->find_fd, errbuf))
+					close_with_IOP(chassis, geoslot, FIND);
+				else {
+					if (u->find_fd > max_fs)
+						max_fs = u->find_fd;								/* remember the highest number currently in use */
+					FD_SET(u->find_fd, &readfds);						/* we are going to want to read this guy's response to */
+					u->len = 0;
+					send_to_fd(u->find_fd, 1, (unsigned char *)"Q");		/* this interface query request */
+				}
+			}
+		}
+	}
+	wait_for_all_answers();
+	if (process_client_data(errbuf))
+		return -1;
+	sort_if_table();
+	return 0;
+}
+
+int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) {
+	unsigned char	buf[12];
+
+	send_to_fd(handle->fd, 1, (unsigned char *)"S");						/* send the get_stats command to the IOP */
+
+	if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1;	/* try reading the required bytes */
+
+	ps->ps_recv		= ntohl(*(uint32_t *)&buf[0]);							/* break the buffer into its three 32 bit components */
+	ps->ps_drop		= ntohl(*(uint32_t *)&buf[4]);
+	ps->ps_ifdrop	= ntohl(*(uint32_t *)&buf[8]);
+
+	return 0;
+}
+
+int acn_open_live(char *name, char *errbuf, int *linktype) {		/* returns 0 on error, else returns the file descriptor */
+	int			chassis, geoslot;
+	unit_t		*u;
+	iface_t		*p;
+	pcap_if_t	*alldevsp;
+
+	pcap_findalldevs(&alldevsp, errbuf);
+	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {										/* scan the table... */
+		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+			u = &units[chassis][geoslot];
+			if (u->ip != NULL) {
+				p = u->iface;
+				while (p) {																		/* and all interfaces... */
+					if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) {				/* and if we found the interface we want... */
+						*linktype = p->iftype;
+						open_with_IOP(u, LIVE);													/* start a connection with that IOP */
+						send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname);	/* send the IOP's interface name, and a terminating null */
+						if (get_error_response(u->fd, errbuf)) {
+							return 0;
+						}
+						return u->fd;															/* and return that open descriptor */
+					}
+					p = p->next;
+				}
+			}
+		}
+	}
+	return 0;																				/* if the interface wasn't found, return an error */
+}
+
+void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) {
+	unsigned char	buf[8];
+	unit_t			*u;
+
+	//printf("acn_start_monitor()\n");				// fulko
+	find_unit_by_fd(fd, NULL, NULL, &u);
+	if (u->first_time == 0) {
+		buf[0]					= 'M';
+		*(uint32_t *)&buf[1]	= htonl(snaplen);
+		buf[5]					= timeout;
+		buf[6]					= promiscuous;
+		buf[7]					= direction;
+	//printf("acn_start_monitor() first time\n");				// fulko
+		send_to_fd(fd, 8, buf);								/* send the start monitor command with its parameters to the IOP */
+		u->first_time = 1;
+	}
+	//printf("acn_start_monitor() complete\n");				// fulko
+}
+
+int acn_setfilter(int fd, struct bpf_program *bpf) {
+	int				count;
+	struct bpf_insn	*p;
+	uint16_t		shortInt;
+	uint32_t		longInt;
+
+	send_to_fd(fd, 1, (unsigned char *)"F");			/* BPF filter follows command */
+	count = bpf->bf_len;
+	longInt = htonl(count);
+	send_to_fd(fd, 4, (unsigned char *)&longInt);		/* send the instruction sequence count */
+	p = bpf->bf_insns;
+	while (count--) {									/* followed by the list of instructions */
+		shortInt = htons(p->code);
+		longInt = htonl(p->k);
+		send_to_fd(fd, 2, (unsigned char *)&shortInt);
+		send_to_fd(fd, 1, (unsigned char *)&p->jt);
+		send_to_fd(fd, 1, (unsigned char *)&p->jf);
+		send_to_fd(fd, 4, (unsigned char *)&longInt);
+		p++;
+	}
+	if (get_error_response(fd, NULL))
+		return -1;
+	return 0;
+}
+
+int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) {
+	struct		timeval tv;
+	int			retval, fd;
+	fd_set		r_fds;
+	fd_set		w_fds;
+	u_char		*bp;
+	int			len = 0;
+	int			offset = 0;
+
+	tv.tv_sec = 5;
+	tv.tv_usec = 0;
+
+	fd = handle->fd;
+	FD_ZERO(&r_fds);
+	FD_SET(fd, &r_fds);
+	memcpy(&w_fds, &r_fds, sizeof(r_fds));
+	bp = handle->bp;
+	while (count) {
+		retval = select(fd + 1, &w_fds, NULL, NULL, &tv);
+		if (retval == -1) {											/* an error occured !!!!! */
+//			fprintf(stderr, "error during packet data read\n");
+			return -1;												/* but we need to return a good indication to prevent unneccessary popups */
+		} else if (retval == 0) {									/* timeout occured, so process what we've got sofar and return */
+//			fprintf(stderr, "timeout during packet data read\n");
+			return -1;
+		} else {
+			if ((len = recv(fd, (bp + offset), count, 0)) <= 0) {
+//				fprintf(stderr, "premature exit during packet data rx\n");
+				return -1;
+			}
+			count -= len;
+			offset += len;
+		}
+	}
+	return 0;
+}
+
+int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) {
+	#define HEADER_SIZE (4 * 4)
+	unsigned char		packet_header[HEADER_SIZE];
+	struct pcap_pkthdr	pcap_header;
+
+	//printf("pcap_read_acn()\n");			// fulko
+	acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction);	/* maybe tell him to start monitoring */
+	//printf("pcap_read_acn() after start monitor\n");			// fulko
+
+	handle->bp = packet_header;
+	if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0;			/* try to read a packet header in so we can get the sizeof the packet data */
+
+	pcap_header.ts.tv_sec	= ntohl(*(uint32_t *)&packet_header[0]);				/* tv_sec */
+	pcap_header.ts.tv_usec	= ntohl(*(uint32_t *)&packet_header[4]);				/* tv_usec */
+	pcap_header.caplen		= ntohl(*(uint32_t *)&packet_header[8]);				/* caplen */
+	pcap_header.len			= ntohl(*(uint32_t *)&packet_header[12]);				/* len */
+
+	handle->bp = handle->buffer + handle->offset;									/* start off the receive pointer at the right spot */
+	if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0;	/* then try to read in the rest of the data */
+
+	callback(user, &pcap_header, handle->bp);										/* call the user supplied callback function */
+	return 1;
+}
diff --git a/pcap-sita.h b/pcap-sita.h
new file mode 100644
index 0000000..8c50066
--- /dev/null
+++ b/pcap-sita.h
@@ -0,0 +1,12 @@
+/*
+ * pcap-sita.h: Packet capture interface for SITA WAN devices
+ *
+ * Authors: Fulko Hew (fulko.hew@sita.aero) (+1 905 6815570);
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-sita.h
+ */
+
+void pcap_close_acn(pcap_t *handle);
+int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps);
+int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user);
+
diff --git a/pcap-sita.html b/pcap-sita.html
new file mode 100644
index 0000000..5f7884f
--- /dev/null
+++ b/pcap-sita.html
@@ -0,0 +1,943 @@
+<HTML><HEAD>
+<STYLE type="text/css">
+<!--
+A { text-decoration:none }
+-->
+</STYLE>
+</HEAD>
+<BODY>
+
+<TABLE WIDTH=100%><TR>
+	<TD ALIGN=LEFT VALIGN=TOP>
+		<FONT SIZE=+0 FACE="COURIER"><B>A "Distributed Pcap" for<BR>Remote Monitoring LANs & WANs</B><BR>
+										(Design Notes for the SITA ACN device)</FONT>
+	</TD>
+	<TD ALIGN=RIGHT VALIGN=TOP>
+		Fulko Hew<BR>SITA INC Canada, Inc.<BR>Revised: October 2, 2007
+	</TD>
+</TR></TABLE>
+
+
+<H3>SUMMARY</H3>
+<UL>
+	<STRONG>Note:</STRONG> This document is part of the libpcap CVS and was derived from 'pcap.3' (circa Aug/07).
+	<P>
+	The ACN provides a customized/distributed version of this library that alows SMPs to
+	interact with the various IOPs within the site providing a standard mechanism
+	to capture LAN and WAN message traffic.
+	<P>
+	<CENTER>
+		<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3 WIDTH=75%>
+			<TR>
+				<TH VALIGN=TOP>SMP</TH>
+				<TD VALIGN=TOP>The Supervisory Management Processor where Wireshark (or equivalent)
+								runs in conjuction with a libpcap front-end.</TD>
+			</TR>
+			<TR>
+				<TH VALIGN=TOP>IOP</TH>
+				<TD VALIGN=TOP>I/O Processors where the monitored ports exist in conjunction
+								with a custom device driver/libpcap back-end.</TD>
+			</TR>
+		</TABLE>
+	</CENTER>
+	<P>
+	Each IOP will be capable of supporting multiple connections from an SMP
+	enabling monitoring of more than one interface at a time, each through
+	its own seperate connection.  The IOP is responsible to ensure and report
+	an error if any attempt is made to monitor the same interface more than once.
+	<P>
+	There are three applications that will be supported by the ACN version of libpcap.
+	They each use a slightly different mode for looping/capturing and termination
+	as summarized in the following table:
+	<P>
+	<CENTER>
+	<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+    	<TR><TH>Application</TH>	<TH>Capture</TH>	<TH>Termination</TH></TR>
+    	<TR><TH VALIGN=TOP NOWRAP>wireshark</TH>
+			<TD VALIGN=TOP>pcap_dispatch(all packets in one buffer of capture only)</TD>
+			<TD VALIGN=TOP>pcap_breakloop()</TD>
+		</TR>
+    	<TR><TH VALIGN=TOP NOWRAP>tshark</TH>
+			<TD VALIGN=TOP>pcap_dispatch(one buffer of capture only)</TD>
+			<TD VALIGN=TOP>Since a CTRL-C was used to terminate the application, pcap_breakloop() is never called.</TD>
+		</TR>
+    	<TR><TH VALIGN=TOP NOWRAP>tcpdump</TH>
+			<TD VALIGN=TOP>pcap_loop(all packets in the next buffer, and loop forever)</TD>
+			<TD VALIGN=TOP>pcap_breakloop()</TD>
+		</TR>
+	</TABLE>
+	</CENTER>
+	<P>
+	<B>Note: </B>In all cases, the termination of capturing is always (apparently) followed by
+	pcap_close().  Pcap_breakloop() is only used to stop/suspend looping/processing,
+	and upon close interpretation of the function definitions, it is possible to resume
+	capturing following a pcap_breakloop() without any re-initialization.
+	<P>
+	<H4>ACN Limitations</H4>
+	<OL>
+		<LI>Monitoring of backup IOPs is not currently supported.
+		<LI>Ethernet interfaces cannot be monitored in promiscuous mode.
+	</OL>
+
+</UL>
+
+<H3>ROUTINES</H3>
+<UL>
+		The following list of functions is the sub-set of Pcap functions that have been
+		altered/enhanced to support the ACN remote monitoring facility.  The remainder of the Pcap
+		functions continue to perform their duties un-altered.  Libpcap only supports this
+		mode of operation if it has been configured/compiled for SITA/ACN support.
+		<P>
+		<UL><FONT FACE=COURIER>
+			pcap_findalldevs<BR>
+			pcap_freealldevs<BR>
+			pcap_open_live<BR>
+			pcap_close<BR>
+			pcap_setfilter<BR>
+			pcap_dispatch<BR>
+			pcap_loop<BR>
+			pcap_next<BR>
+			pcap_next_ex<BR>
+			pcap_stats<BR>
+		</FONT></UL>
+
+	These subroutines have been modified for the ACN specific distributed and remote monitoring
+	ability perform the following basic functions.  More detail is provided in the
+	"SMP/IOP Inter-Process Communication Protocol" section.
+	<P>
+<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_open_live()</B></TD>
+		<TD VALIGN=TOP>Used to obtain a packet capture descriptor to look at packets on the network.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP will open a connection to the selected IOP on its 'sniffer' port
+			to ensure it is available.  It sends a null terminated string identifying
+			the interface to be monitored.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			After any required processing is complete, the IOP will return a
+			null terminated string containing an error message if one occured.
+			If no error occured, a empty string is still returned.
+			Errors are:
+			<UL>
+			<LI>"Interface (xxx) does not exist."
+			<LI>"Interface (xxx) not configured."
+			<LI>"Interface (xxx) already being monitored."
+			</UL>
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_findalldevs()</B></TD>
+		<TD VALIGN=TOP>It constructs a list of network devices that can be opened with pcap_open_live().</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			It obtains a list of IOPs currently available (via /etc/hosts).
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure
+			the IOP is available.
+			It sends a null terminated empty interface ID followed by the query request command.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>The IOP returns an error response and its list of devices.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP closes the TCP connection with each IOP.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP adds the received information to its internal structure.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_freealldevs()</B></TD>
+		<TD VALIGN=TOP>Used to free a list allocated by pcap_findalldevs().</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP frees the structure it built as a result of the previous
+			invocation of pcap_findalldevs().
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_dispatch()</B></TD>
+		<TD VALIGN=TOP>Used to collect and process packets.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+			the SMP will pass down the monitor start command and various parameters the IOP should use.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP now sends a stream of captured data.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP will read the reverse channel of the connection between the SMP and the
+			IOP that provides the captured data (via 'p->read_op' which is 'pcap_read_linux()'
+			until the select() call returns a 'no more data' indication.
+			It will the process (at most) the next 'cnt' packets and invoke the specified
+			callback function for each packet processed.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+			<TD>
+			The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_loop()</B></TD>
+		<TD VALIGN=TOP>
+				Is similar to pcap_dispatch() except it keeps reading packets until
+				the requested number of packets are processed or an error occurs.
+		</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+			the SMP will pass down the monitor start command and various parameters the IOP should use.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP now sends a stream of captured data.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP continuously reads the next packet from the reverse channel of the connection
+			between the SMP and the IOP that provides the captured data (via 'p->read_op'
+			which is 'pcap_read_linux()' until 'cnt' packets have been received.
+			The specified callback function will be invoked for each packet received.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+			<TD>
+			The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_next()</B></TD>
+		<TD VALIGN=TOP>
+			It reads the next packet (by calling pcap_dispatch() with a count of 1)
+			and returns a pointer to the data in that packet.
+		</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+			the SMP will pass down the monitor start command and various parameters the IOP should use.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP now sends a stream of captured data.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP reads only the next packet from the reverse channel of the connection
+			between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+			with a count of 1) and returns a pointer to that data by invoking an internal callback.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+			<TD>
+			The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_next_ex()</B></TD>
+		<TD VALIGN=TOP>Reads the next packet and returns a success/failure indication.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+			the SMP will pass down the monitor start command and various parameters the IOP should use.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP now sends a stream of captured data.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP reads only the next packet from the reverse channel of the connection
+			between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+			with a count of 1) and returns seperate pointers to both the
+			packet header and packet data by invoking an internal callback.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+			<TD>
+			The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_setfilter()</B></TD>
+        <TD VALIGN=TOP>Used to specify a filter program.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP sends a 'set filter' command followed by the BPF commands.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP returns a null terminated error string if it failed to accept the filter.
+			If no error occured, then a NULL terminated empty string is returned instead.
+			Errors are:
+			<UL>
+			<LI>"Invalid BPF."
+			<LI>"Insufficient resources for BPF."
+			</UL>
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_stats()</B></TD>
+        <TD VALIGN=TOP>Fills in a pcap_stat struct with packet statistics.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP sends a message to the IOP requesting its statistics.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+			<TD>
+			The IOP returns the statistics.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+			<TD>
+			The SMP fills in the structure provided with the information retrieved from the IOP.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+
+	<TR>
+		<TD VALIGN=TOP ROWSPAN=2><B>pcap_close()</B></TD>
+        <TD VALIGN=TOP>Closes the file and deallocates resources.</TD>
+	</TR>
+	<TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+			<TD>
+			The SMP closes the file descriptor, and if the descriptor is that of
+			the comminucation session with an IOP, it too is terminated.
+			</TD>
+		</TR>
+		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+			<TD>
+			If the IOP detects that its communication session with an SMP
+			has closed, it will terminate any monitoring in progress,
+			release any resources and close its end of the session.
+			It will not maintain persistance of any information or prior mode of operation.
+			</TD>
+		</TR>
+	</TABLE></TD></TR>
+</TABLE>
+</UL>
+
+<P>
+<H3>SMP/IOP Inter-Process Communication Protocol</H3>
+
+<UL>
+	<LI><P>Communications between an SMP and an IOP consists of a TCP session
+			between an ephemeral port on the SMP and the well known port of 49152
+			(which is the first available port in the 'dynamic and/or private port'
+			range) on an IOP.
+	<LI><P>Following a TCP open operation the IOP receives a null terminated
+			'interface ID' string to determine the type of operation that follows:
+	<LI><P>Every command received by an IOP implies a 'stop trace/stop forwarding' operation must
+			occur before executing the received command.
+	<LI><P>A session is closed when the SMP closes the TCP session with the IOP.
+			Obviously monitoring and forwarding is also stopped at that time.
+
+	<B>Note: </B>All multi-octet entities are sent in network neutral order.
+	<P>
+
+	<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP ROWSPAN=6>pcap_findalldevs()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>Open socket (to each IOP), and sends:
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>Interface ID</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>A NULL to indicate an an empty 'interface ID'.</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>Send its (possibly empty) NULL terminated error response string.</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>Sends the 'interface query request':
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>Interface ID</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>A 'Q' (indicating 'interface query request').</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>The IOP returns a list of sequences of information as
+				defined by the return parameter of this function call (as shown in the following table).
+				Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+				<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Notes:</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+				</TR>
+				<TR>
+					<TD ROWSPAN=7>&nbsp;</TD>
+					<TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the name field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Name</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+					<TD VALIGN=TOP>The name of the interface. The format of the name is an alphabetic string (indicating
+									the type of interface) followed by an optional numeric string (indicating the interface's
+									sequence number).
+									Sequence numbers (if needed) will begin at zero and progress monotonically upwards.
+									(i.e. 'eth0', 'lo', 'wan0', etc.)
+									<P>
+									For an IOP, the alphabetic string will be one of: 'eth', 'wan', and 'lo'
+									for Ethernet, WAN ports and the IP loopback device respectively.
+									An IOP currently supports: 'eth0', 'eth1', 'lo', 'wan0' ... 'wan7'.
+									<P>
+						<B>Note:</B> IOPs and ACNs will not currently support the concept of 'any' interface.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the interface description field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Interface Description</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+					<TD VALIGN=TOP>A description of the interface or it may be an empty string. (i.e. 'ALC')</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Interface Type</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+					<TD VALIGN=TOP>The type of interface as defined in the description for pcap_datalink() (in network neutral order).</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Loopback Flag</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>1 = if the interface is a loopback interface, zero = otherwise.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=RIGHT>count</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP># of address entries that follow.
+						Each entry is a series of bytes in network neutral order.
+						See the parameter definition above for more details.</TD>
+				</TR>
+				<TR>
+					<TD ALIGN=CENTER ROWSPAN=8 WIDTH=1%>Repeated 'count' number of times.</TD>
+					<TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the address field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Address</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+					<TD VALIGN=TOP>The address of this interface (in network neutral order).</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the netmask field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Network Mask</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+					<TD VALIGN=TOP>The network mask used on this interface (if applicable) (in network neutral order).</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the broadcast address field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Broadcast Address</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+					<TD VALIGN=TOP>The broadcast address of this interface (if applicable) (in network neutral order).</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+					<TD VALIGN=TOP>The number of octets in the destination address field that follows.</TD>
+				</TR>
+				<TR><TD VALIGN=TOP ALIGN=LEFT>Destination Address</TD>
+					<TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+					<TD VALIGN=TOP>The destination address of this interface (if applicable) (in network neutral order).</TD>
+				</TR>
+				</TABLE>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>Close the socket.</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>Close the socket.</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP ROWSPAN=2>pcap_open_live()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>Open socket, and sends:
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>Interface ID</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+						<TD VALIGN=TOP>'n' octets containing a NULL terminated interface name string.</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>Send its NULL terminated error response string.</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP NOWRAP ROWSPAN=2>pcap_dispatch()<BR>pcap_loop()<BR>pcap_next()<BR>pcap_next_ex()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>On the first invocation following a pcap_open_live() or pcap_breakloop() additional information is sent:
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>command</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>'M' (indicating 'monitor start')</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>snaplen</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+						<TD VALIGN=TOP>snaplen</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>timeout</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>timeout value (in milliseconds)</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>promiscuous</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>A flag indicating that the interface being monitored show operate
+							in promiscuous mode. [off(0) / on(NZ)]</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>direction</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>A flag indicating the direction of traffic that should be captuted [both(0) / in(1) / out(2)]</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>Sends captured packets.</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP ROWSPAN=2>pcap_setfilter()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>At any time, the SMP can issue a set filter command which contains
+							an indicator, a count of the number of statements in the filter,
+							followed by the sequence of filter commands represented as a sequence
+							of C-style structures.
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>command</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>'F' (indicating 'filter')</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>count</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+						<TD VALIGN=TOP>The number of command in the Berkeley Packet Filter that follow.</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>BPF program</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+						<TD VALIGN=TOP>8 bytes of each command (repeated 'n' times).<BR>
+								 	Each command consists of that C-style structure which contains:
+							<P>
+							<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+								<TR>
+								<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+								<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+								<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+								</TR>
+								<TR>
+									<TD VALIGN=TOP>opcode</TD>
+									<TD VALIGN=TOP ALIGN=CENTER>2</TD>
+									<TD VALIGN=TOP>The command's opcode.</TD>
+								</TR>
+								<TR>
+									<TD VALIGN=TOP>'jt'</TD>
+									<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+									<TD VALIGN=TOP>The 'jump if true' program counter offset.</TD>
+								</TR>
+								<TR>
+									<TD VALIGN=TOP>'jf'</TD>
+									<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+									<TD VALIGN=TOP>The 'jump if false' program counter offset.</TD>
+								</TR>
+								<TR>
+									<TD VALIGN=TOP>'k'</TD>
+									<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+									<TD VALIGN=TOP>The 'other' data field.</TD>
+								</TR>
+							</TABLE>
+							<P>
+							Refer to the bpf(4) man page for more details.
+						</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>In return the IOP will send its (possibly empty) NULL terminated error response string.</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP ROWSPAN=2>pcap_stats()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>At any time, the SMP can issue a 'retrieve statistics' command which contains:<BR>
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>command</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
+						<TD VALIGN=TOP>'S' (indicating 'request statistics')</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+			<TD VALIGN=TOP>In return the IOP will send:
+				<P>
+				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+					<TR>
+					<TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+					<TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+					<TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>ps_recv</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+						<TD VALIGN=TOP>The number of packets that passed the filter.</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>ps_drop</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+						<TD VALIGN=TOP>The number of packets that were dropped because the input queue was full,
+							regardless of whether they passed the filter.</TD>
+					</TR>
+					<TR>
+						<TD VALIGN=TOP>ps_ifdrop</TD>
+						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
+						<TD VALIGN=TOP>The number of packets dropped by the network inteface
+							(regardless of whether they would have passed the input filter).</TD>
+					</TR>
+				</TABLE>
+			</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+		<TR>
+			<TD VALIGN=TOP ROWSPAN=1>pcap_close()</TD>
+			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+			<TD VALIGN=TOP>At any time, the SMP can close the TCP session with the IOP.</TD>
+		</TR>
+		<TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+	</TABLE>
+</UL>
+
+<H3>Interface ID Naming Convention</H3>
+<UL>
+	Each interface within an IOP will be referred to uniquely.  Since an currently contains
+	8 monitorable WAN ports and a monitorable Ethernet port, the naming convention is:
+	<P>
+	<CENTER>
+	<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+		<TR><TH>Interface #</TH>		<TH>Type</TH>					<TH>Name</TH></TR>
+		<TR><TD ALIGN=CENTER>1</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan0</TD></TR>
+		<TR><TD ALIGN=CENTER>2</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan1</TD></TR>
+		<TR><TD ALIGN=CENTER>3</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan2</TD></TR>
+		<TR><TD ALIGN=CENTER>4</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan3</TD></TR>
+		<TR><TD ALIGN=CENTER>5</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan4</TD></TR>
+		<TR><TD ALIGN=CENTER>6</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan5</TD></TR>
+		<TR><TD ALIGN=CENTER>7</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan6</TD></TR>
+		<TR><TD ALIGN=CENTER>8</TD>		<TD ALIGN=CENTER>WAN</TD>		<TD ALIGN=CENTER>wan7</TD></TR>
+		<TR><TD ALIGN=CENTER>9</TD>		<TD ALIGN=CENTER>Ethernet</TD>	<TD ALIGN=CENTER>eth0</TD></TR>
+		<TR><TD ALIGN=CENTER>10</TD>	<TD ALIGN=CENTER>Ethernet</TD>	<TD ALIGN=CENTER>eth1</TD></TR>
+	</TABLE>
+	</CENTER>
+</UL>
+
+<H3>Packet Trace Data Format</H3>
+<UL>
+	The format of the trace data that is sent to the SMP follows a portion of the libpcap file format
+	and is summarized here.  This format specifies the generic requirements needed to
+	be able to decode packets, but does not cover ACN specifics such as custom MAC addressing
+	and WAN protocol support.
+	<P>
+
+	Although a libpcap file begins with a global header followed by zero or
+	more records for each captured packet, trace data sent to the SMP does NOT begin with a global header.
+	A trace sequence looks like this:
+	<P>
+	<TABLE>
+		<TR>
+  			<TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Header]&nbsp;</TD>
+  			<TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Data]&nbsp;</TD>
+  			<TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Header]&nbsp;</TD>
+  			<TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Data]&nbsp;</TD>
+  			<TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Header]&nbsp;</TD>
+  			<TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Data]&nbsp;</TD>
+  			<TD>...</TD>
+		</TR>
+	</TABLE>
+
+<H4>Packet Header</H4>
+	<UL>
+		Each captured packet starts with a header that contains the following values
+		(in network neutral order):
+
+		<FONT SIZE=-1>
+		<PRE>
+ uint32 tv_sec;  /* timestamp seconds */
+ uint32 tv_usec; /* timestamp microseconds */
+ uint32 caplen;  /* number of octets in the following packet */
+ uint32 len;     /* original length of packet on the wire */
+		</PRE>
+		</FONT>
+
+		<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+			<TR>
+				<TD VALIGN=TOP>tv_sec</TD>
+				<TD>The date and time when this packet was captured.
+					This value is in seconds since January 1, 1970 00:00:00 GMT;
+					this is also known as a UN*X time_t. You can use the ANSI C
+					<em>time()</em> function from <em>time.h</em> to get this value,
+					but you might use a more optimized way to get this timestamp value.
+					If this timestamp isn't based on GMT (UTC), use <em>thiszone</em>
+					from the global header for adjustments.</TD>
+			</TR>
+			<TR>
+				<TD VALIGN=TOP>tv_usec</TD>
+				<TD>The microseconds when this packet was captured, as an offset to <em>ts_sec</em>.
+					<B>Beware: </B>this value must never reach 1 second (1,000,000),
+					in this case <em>ts_sec</em> must be increased instead!</TD>
+			</TR>
+			<TR>
+				<TD VALIGN=TOP>caplen</TD>
+				<TD>The number of bytes actually provided in the capture record.
+					This value should never become larger than <em>len</em> or the
+					<em>snaplen</em> value specified during the capture.</TD>
+			</TR>
+			<TR>
+				<TD VALIGN=TOP>len</TD>
+				<TD>The length of the packet "on the wire" when it was captured.
+					If <em>caplen</em> and <em>len</em> differ, the actually
+					saved packet size was limited by the value of <em>snaplen</em> specified
+					during one of the capture directives such as pcap_dispatch().</TD>
+			</TR>
+		</TABLE>
+	</UL>
+
+<H4>Packet Data</H4>
+	<UL>
+	The actual packet data will immediately follow the packet header as a sequence of <em>caplen</em> octets.
+	Depending on the DLT encoding number assigned to the interface, the packet data will contain an additional
+	custom header used to convey WAN port related information.
+	</UL>
+
+<H4>ACN Custom Packet Header</H4>
+	<UL>
+	PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support
+	monitoring of its ports, however each of these facilities were focused on capturing
+	and displaying traffic from LAN interfaces.  The SITA extentions to these facilities
+	are used to also provide the ability to capture, filter, and display information from
+	an ACN's WAN ports.
+	<P>
+	Although each packet follows the standard libpcap format, since there are
+	two types of interfaces that can be monitored, the format of the data
+	packet varies slightly.
+	<P>
+	<UL TYPE=DISC>
+		<LI>For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format.
+		<LI>For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data
+			described by the following table:
+	</UL>
+	<P>
+	<CENTER>
+	<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+	<TR>	<TH>Octet</TH>
+			<TH>Name</TH>
+			<TH>Mask/Value</TH>
+			<TH COLSPAN=2>Definition</TH>		</TR>
+
+	<TR>	<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>0</TH>
+			<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>Control / Status</TH>
+
+			<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx0</FONT></TD>
+			<TD>Transmitted by capture device</TD>
+			<TD ROWSPAN=2 ALIGN=CENTER>(see 'Errors' octets)</TD>							</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>
+			<TD>Received by capture device</TD>												</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>
+			<TD COLSPAN=2>No buffer was available during capture of previous packet.</TD>	</TR>
+
+	<TR>	<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>1</TH>
+			<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>Signals</TH>
+
+			<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>	<TD COLSPAN=2>DSR asserted</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>	<TD COLSPAN=2>DTR asserted</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>	<TD COLSPAN=2>CTS asserted</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>	<TD COLSPAN=2>RTS asserted</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>	<TD COLSPAN=2>DCD asserted</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>	<TD COLSPAN=2>Undefined</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>	<TD COLSPAN=2>Undefined</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>	<TD COLSPAN=2>Undefined</TD>		</TR>
+
+	<TR>	<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>2</TH>
+			<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 1)</TH>
+
+			<TH>&nbsp;</TH>															<TH>Tx</TH>						<TH>Rx</TH>				</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>	<TD>Underrun</TD>				<TD>Framing</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>	<TD>CTS Lost</TD>				<TD>Parity</TD>			</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>	<TD>UART Error</TD>				<TD>Collision</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>	<TD>Re-Tx Limit Reached</TD>	<TD>Long Frame</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>	<TD>Undefined</TD>				<TD>Short Frame</TD>	</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>	<TD>Undefined</TD>				<TD>Undefined</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>	<TD>Undefined</TD>				<TD>Undefined</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>	<TD>Undefined</TD>				<TD>Undefined</TD>		</TR>
+
+	<TR>	<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>3</TH>
+			<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 2)</TH>
+
+			<TH>&nbsp;</TH>															<TH>Tx</TH>			<TH>Rx</TH>						</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>	<TD>Undefined</TD>	<TD>Non-Octet Aligned</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>	<TD>Undefined</TD>	<TD>Abort Received</TD>			</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>	<TD>Undefined</TD>	<TD>CD Lost</TD>				</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>	<TD>Undefined</TD>	<TD>Digital PLL Error</TD>		</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>	<TD>Undefined</TD>	<TD>Overrun</TD>				</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>	<TD>Undefined</TD>	<TD>Frame Length Violation</TD>	</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>	<TD>Undefined</TD>	<TD>CRC Error</TD>				</TR>
+	<TR>	<TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>	<TD>Undefined</TD>	<TD>Break Received</TD>			</TR>
+
+	<TR>	<TH VALIGN=TOP ALIGN=CENTER ROWSPAN=12>4</TH>
+			<TH VALIGN=TOP ALIGN=CENTER>Protocol</TH>
+
+			<TD COLSPAN=3>
+				<CENTER>
+				<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x01</TD>	<TD>-</TD>	<TD>LAPB (BOP)				<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x02</TD>	<TD>-</TD>	<TD>Ethernet				<SUP>1</SUP>		</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x03</TD>	<TD>-</TD>	<TD>Async (Interrupt IO)	<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x04</TD>	<TD>-</TD>	<TD>Async (Block IO)		<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x05</TD>	<TD>-</TD>	<TD>IPARS					<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x06</TD>	<TD>-</TD>	<TD>UTS						<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x07</TD>	<TD>-</TD>	<TD>PPP (HDLC)				<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x08</TD>	<TD>-</TD>	<TD>SDLC					<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x09</TD>	<TD>-</TD>	<TD>Token Ring				<SUP>1</SUP>		</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x10</TD>	<TD>-</TD>	<TD>I2C						<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x11</TD>	<TD>-</TD>	<TD>DPM Link				<SUP>&nbsp;</SUP>	</TD>	</TR>
+					<TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x12</TD>	<TD>-</TD>	<TD>Frame Relay (BOP)		<SUP>&nbsp;</SUP>	</TD>	</TR>
+				</TABLE>
+				</CENTER>
+				<P>
+				<STRONG>Note 1:</STRONG>
+				Ethernet and Token Ring frames will never be sent as DLT_SITA (with the 5 octet header),
+				but will be sent as their corresponding DLT types instead.
+			</TD>
+	</TR>
+	</TABLE>
+	</CENTER>
+</UL>
+<P>
+</UL>
+</UL>