Merge remote-tracking branch 'goog/tcpdump'

* goog/tcpdump: (1872 commits)
  Remove old version. Getting ready for new libpcap 1.5
  Remove commas from clauses in a comma-separated list.
  Fix typo.
  Describe all NFLOG TLV types and define structures for some of them.
  Check caplen in the NFLOG TLV loop.
  Have nflog_tlv_t include only the TLV header.
  Byte-swap the T and L in TLVs as necessary when reading an NFLOG file.
  Don't support D-Bus sniffing on OS X.
  Add post-1.5.2 bug fixes.
  Tag some changes with a bug identifier.
  Add items for 1.5.1 and 1.5.2.
  Formatting tweak.
  Count *ring buffer blocks*, not *packets* to be filtered in userland.
  Add a PACKET_COUNT_IS_UNLIMITED() to test for a packet count <= 0.
  Use HAVE_TPACKET3 rather than TPACKET_V3 to test for TPACKET_V3 support.
  Fix builds on systems without TPACKET_V3.
  tweak manpages formatting
  Fix pcap_loop() with a count of 0 and TPACKET_V3.
  Discourage the use of a zero timeout.
  We can't use TPACKET_V3 in immediate mode, so fall back on TPACKET_V2.
  ...

Change-Id: I2aa9bd87673c56aee439e1154b96a14026ca7985
diff --git a/msdos/bin2c.c b/msdos/bin2c.c
new file mode 100644
index 0000000..d82056e
--- /dev/null
+++ b/msdos/bin2c.c
@@ -0,0 +1,43 @@
+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <time.h>

+

+static void Abort (char *fmt,...)

+{

+  va_list args;

+  va_start (args, fmt);

+  vfprintf (stderr, fmt, args);

+  va_end (args);

+  exit (1);

+}

+

+int main (int argc, char **argv)

+{

+  FILE  *inFile;

+  FILE  *outFile = stdout;

+  time_t now     = time (NULL);

+  int    ch, i;

+

+  if (argc != 2)

+     Abort ("Usage: %s bin-file [> result]", argv[0]);

+

+  if ((inFile = fopen(argv[1],"rb")) == NULL)

+     Abort ("Cannot open %s\n", argv[1]);

+

+  fprintf (outFile,

+           "/* data statements for file %s at %.24s */\n"

+           "/* Generated by BIN2C, G.Vanem 1995 */\n",

+           argv[1], ctime(&now));

+

+  i = 0;

+  while ((ch = fgetc(inFile)) != EOF)

+  {

+    if (i++ % 12 == 0)

+       fputs ("\n  ", outFile);

+    fprintf (outFile, "0x%02X,", ch);

+  }

+  fputc ('\n', outFile);

+  fclose (inFile);

+  return (0);

+}

diff --git a/msdos/common.dj b/msdos/common.dj
new file mode 100644
index 0000000..3f64d14
--- /dev/null
+++ b/msdos/common.dj
@@ -0,0 +1,80 @@
+#
+# Common defines for libpcap and 16/32-bit network drivers (djgpp)
+#
+# @(#) $Header: /tcpdump/master/libpcap/msdos/common.dj,v 1.2 2004-12-19 19:36:33 guy Exp $ (LBL)
+
+.SUFFIXES: .exe .wlm .dxe .l .y
+.PHONY:    check_gcclib
+
+default: check_gcclib all
+
+GCCLIB   = /djgpp/lib/gcc-lib/djgpp/3.31
+MAKEFILE = Makefile.dj
+
+#
+# DLX 2.91+ lib. Change path to suite.
+# Not used anymore. Uses DXE3 now.
+#
+# DLX_LIB  = $(DJDIR)/contrib/dlx.291/libdlx.a
+# DLX_LINK = $(DJDIR)/bin/dlxgen.exe
+
+WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
+
+
+ifeq ($(wildcard $(GCCLIB)/libgcc.a),)
+check_gcclib:
+	@echo libgcc.a not found. Set \"$(GCCLIB)\" to \"/djgpp/lib/gcc-lib/djgpp/3.X\"
+endif
+
+
+#
+# Include 32-bit driver support
+#
+USE_32BIT_DRIVERS = 0
+
+#
+# Use loadable driver modules instead of statically linking
+# all drivers.
+#
+USE_32BIT_MODULES = 0
+
+#
+# Put interrupt sensitive code/data in locked sections
+# Do `make clean' in all affected directories after changing this.
+#
+USE_SECTION_LOCKING = 0
+
+#
+# Set to 1 to use exception handler lib (only for me)
+#
+USE_EXCEPT = 0
+
+CC   = gcc.exe
+LD   = ld.exe
+ASM  = nasm.exe -fbin -dDEBUG
+YACC = bison.exe
+LEX  = flex.exe
+
+CFLAGS = -g -gcoff -O2 -Wall -I. -I$(WATT32_ROOT)/inc
+
+ifeq ($(USE_EXCEPT),1)
+  CFLAGS += -DUSE_EXCEPT
+  EXC_LIB = d:/prog/mw/except/lib/libexc.a
+endif
+
+ifeq ($(USE_SECTION_LOCKING),1)
+  CFLAGS += -DUSE_SECTION_LOCKING
+endif
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+  CFLAGS += -DUSE_32BIT_DRIVERS
+endif
+
+%.o: %.c
+	$(CC) -c $(CFLAGS) $<
+	@echo
+
+%.o: %.s
+	$(CC) -c $(CFLAGS) -x assembler-with-cpp -o $@ $<
+	@echo
+
diff --git a/msdos/makefile b/msdos/makefile
new file mode 100644
index 0000000..cdb4e7c
--- /dev/null
+++ b/msdos/makefile
@@ -0,0 +1,184 @@
+#

+#  Makefile for dos-libpcap. NB. This makefile requires a Borland

+#  compatible make tool.

+#

+#  Targets:

+#    Borland C 4.0+      (DOS large model)

+#    Metaware HighC 3.3+ (PharLap 386|DosX)

+#

+

+.AUTODEPEND

+.SWAP

+

+!if "$(WATT_ROOT)" == ""

+!error Environment variable "WATT_ROOT" not set.

+!endif

+

+WATT_INC = $(WATT_ROOT)\inc

+

+DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \

+         -DHAVE_STRERROR -DHAVE_LIMITS_H

+

+ASM    = tasm.exe -t -l -mx -m2 -DDEBUG

+

+SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \

+         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \

+         savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \

+         missing\snprintf.c

+

+BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj

+

+HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32

+

+all:

+            @echo Usage: make pcap_bc.lib or pcap_hc.lib

+

+

+pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc

+

+

+pcap_hc.lib: hc386.arg $(HIGHC_OBJ)

+            386lib $< @&&|

+               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)

+|

+

+pcap_bc:    $(BORLAND_OBJ)

+            @tlib pcap_bc.lib /C @&&|

+               -+$(**:.obj=-+)

+|

+

+.c.obj:

+            bcc.exe @bcc.arg -o$*.obj $*.c

+

+.c.o32:

+            hc386.exe @hc386.arg -o $*.o32 $*.c

+

+.asm.obj:

+            $(ASM) $*.asm, $*.obj

+

+.asm.o32:

+            $(ASM) -DDOSX=1 $*.asm, $*.o32

+

+scanner.c: scanner.l

+            flex -Ppcap_ -7 -oscanner.c scanner.l

+

+grammar.c tokdefs.h: grammar.y

+            bison --name-prefix=pcap_ --yacc --defines grammar.y

+            - @del grammar.c

+            - @del tokdefs.h

+            ren y_tab.c grammar.c

+            ren y_tab.h tokdefs.h

+

+bcc.arg:    msdos\Makefile

+            @copy &&|

+              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-

+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym

+| $<

+

+hc386.arg:  msdos\Makefile

+            @copy &&|

+            # -DUSE_32BIT_DRIVERS

+              $(DEFS) -DDOSX=1 -w3 -c -g -O5

+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr

+              -Hsuffix=.o32

+              -Hnocopyr

+              -Hpragma=Offwarn(491,553,572)

+              -Hon=Recognize_library  # make memcpy/strlen etc. inline

+              -Hoff=Behaved           # turn off some optimiser warnings

+| $<

+

+clean:

+            @del *.obj

+            @del *.o32

+            @del *.lst

+            @del *.map

+            @del bcc.arg

+            @del hc386.arg

+            @del grammar.c

+            @del tokdefs.h

+            @del scanner.c

+            @echo Cleaned

+

+#

+# dependencies

+#             

+pkt_rx0.obj:  msdos\pkt_rx0.asm

+

+bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

+

+bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

+

+bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h

+

+etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h

+

+optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

+

+savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h

+

+pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

+

+inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h

+

+grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pf.h pcap-namedb.h

+

+scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pcap-namedb.h tokdefs.h

+

+gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \

+  arcnet.h pf.h pcap-namedb.h

+

+nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pcap-namedb.h ethertype.h

+

+pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \

+  msdos\pktdrvr.h

+

+pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \

+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

+

+ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

+  msdos\ndis2.h

+

+pkt_rx0.o32:  msdos\pkt_rx0.asm

+

+bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

+

+bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

+

+bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h

+

+etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h

+

+optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

+

+savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h

+

+pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

+

+inet.o32: inet.c pcap-int.h pcap.h pcap-bpf.h

+

+grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pf.h pcap-namedb.h

+

+scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pcap-namedb.h tokdefs.h

+

+gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \

+  arcnet.h pf.h pcap-namedb.h

+

+nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

+  pcap-namedb.h ethertype.h

+

+pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \

+  msdos\pktdrvr.h

+

+pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \

+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

+

+ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

+  msdos\ndis2.h

+

diff --git a/msdos/makefile.dj b/msdos/makefile.dj
new file mode 100644
index 0000000..7ce58b4
--- /dev/null
+++ b/msdos/makefile.dj
@@ -0,0 +1,152 @@
+#
+# GNU Makefile for DOS-libpcap. djgpp version.
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+#  c:\net\pcap> make -f msdos/makefile.dj
+#
+# @(#) $Header: /tcpdump/master/libpcap/msdos/makefile.dj,v 1.2 2004-12-19 19:41:06 guy Exp $ (LBL)
+
+VPATH = missing msdos
+
+PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc
+
+include msdos/common.dj
+
+DRIVER_DIR = ./msdos/pm_drvr
+
+CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR \
+          -D_U_='__attribute__((unused))' -DHAVE_VERSION_H
+
+# CFLAGS += -Dyylval=pcap_lval -DBDEBUG -DNDEBUG
+
+SOURCES = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c   \
+          etherent.c gencode.c nametoad.c pcap-dos.c optimize.c  \
+          savefile.c pcap.c inet.c msdos\pktdrvr.c msdos/ndis2.c \
+          missing/snprintf.c
+
+OBJECTS = $(notdir $(SOURCES:.c=.o))
+TEMPBIN = tmp.bin
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+  PM_OBJECTS = $(addprefix $(DRIVER_DIR)/, \
+                 printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \
+                 lock.o kmalloc.o quirks.o timer.o net_init.o)
+  #
+  # Static link of drivers
+  #
+  ifeq ($(USE_32BIT_MODULES),0)
+    PM_OBJECTS += $(addprefix $(DRIVER_DIR)/, \
+                    accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \
+                    3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o)
+  endif
+endif
+
+all: libpcap.a
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+$(PM_OBJECTS):
+	$(MAKE) -f Makefile.dj -C $(DRIVER_DIR) $(notdir $@)
+endif
+
+libpcap.a: version.h $(OBJECTS) $(PM_OBJECTS)
+	rm -f $@
+	ar rs $@ $^
+
+msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
+	$(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S
+	./msdos/bin2c $(TEMPBIN) > $@
+	rm -f $(TEMPBIN)
+
+grammar.c tokdefs.h: grammar.y
+	rm -f grammar.c tokdefs.h
+	$(YACC) --name-prefix=pcap_ --yacc --defines grammar.y
+	mv -f y_tab.c grammar.c
+	mv -f y_tab.h tokdefs.h
+
+version.h: ./VERSION
+	@echo '/* Generated from VERSION. Do not edit */' > $@
+	sed -e 's/.*/static char pcap_version_string[] = "libpcap (&)";/' ./VERSION >> $@
+
+scanner.c: scanner.l
+	$(LEX) -Ppcap_ -7 -t $^ > $@
+	@echo
+
+msdos/bin2c.exe: msdos/bin2c.c
+	$(CC) $*.c -o $*.exe
+
+clean:
+	$(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
+	$(MAKE) -f Makefile.dj -C libcpcap clean
+	rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak $(PREREQUISITES)
+
+vclean: clean
+	rm -f libpcap.a msdos/bin2c.exe
+
+#
+# Generated dependencies; Due to some hacks in gcc 2.95 and djgpp 2.03
+# we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing
+# included in dependency output (or else this makefile cannot be used on
+# another machine). We therefore use a special 'specs' file during
+# pre-processing.
+#
+MM_SPECS = specs.tmp
+MAKEFILE = msdos/Makefile.dj
+
+depend: $(PREREQUISITES)
+	@echo Generating dependencies..
+	@cp $(MAKEFILE) Makefile.bak
+	@echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS)
+	sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE)
+	echo "# DO NOT DELETE THIS LINE"                        >> $(MAKEFILE)
+	$(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES)       >> $(MAKEFILE)
+	rm -f $(MM_SPECS)
+
+#
+# Manually generated dependencies
+#             
+msdos/pktdrvr.c: msdos/pkt_stub.inc
+scanner.c: scanner.l
+grammar.c tokdefs.h: grammar.y
+grammar.h: grammar.y
+scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h gnuc.h
+grammar.y: pcap-int.h gencode.h pcap-namedb.h gnuc.h
+
+#
+# Automatically generated dependencies
+#
+# DO NOT DELETE THIS LINE
+grammar.o: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h pf.h \
+  pcap-namedb.h
+scanner.o: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h pcap-namedb.h \
+  tokdefs.h
+bpf_filt.o: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+bpf_imag.o: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+bpf_dump.o: bpf_dump.c pcap.h pcap-bpf.h
+etherent.o: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+gencode.o: gencode.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h \
+  ppp.h sll.h arcnet.h pf.h pcap-namedb.h
+nametoad.o: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+pcap-dos.o: pcap-dos.c msdos/pm_drvr/pmdrvr.h msdos/pm_drvr/iface.h \
+  msdos/pm_drvr/lock.h msdos/pm_drvr/ioport.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos/pm_drvr/kmalloc.h msdos/pm_drvr/bitops.h \
+  msdos/pm_drvr/timer.h msdos/pm_drvr/dma.h msdos/pm_drvr/irq.h \
+  msdos/pm_drvr/printk.h msdos/pm_drvr/pci.h msdos/pm_drvr/bios32.h \
+  msdos/pm_drvr/module.h msdos/pm_drvr/3c501.h msdos/pm_drvr/3c503.h \
+  msdos/pm_drvr/3c509.h msdos/pm_drvr/3c59x.h msdos/pm_drvr/3c515.h \
+  msdos/pm_drvr/3c90x.h msdos/pm_drvr/3c575_cb.h msdos/pm_drvr/ne.h \
+  msdos/pm_drvr/wd.h msdos/pm_drvr/accton.h msdos/pm_drvr/cs89x0.h \
+  msdos/pm_drvr/rtl8139.h msdos/pm_drvr/ne2k-pci.h msdos/pktdrvr.h
+optimize.o: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+savefile.o: savefile.c pcap-int.h pcap.h pcap-bpf.h
+pcap.o: pcap.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h
+inet.o: inet.c pcap-int.h pcap.h pcap-bpf.h
+pktdrvr.o: msdos/pktdrvr.c gnuc.h pcap-dos.h msdos/pm_drvr/lock.h \
+  pcap-int.h pcap.h pcap-bpf.h msdos/pktdrvr.h msdos/pkt_stub.inc
+ndis2.o: msdos/ndis2.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h msdos/ndis2.h
+snprintf.o: missing/snprintf.c pcap-int.h pcap.h pcap-bpf.h
diff --git a/msdos/makefile.wc b/msdos/makefile.wc
new file mode 100644
index 0000000..e0d5672
--- /dev/null
+++ b/msdos/makefile.wc
@@ -0,0 +1,131 @@
+#

+#  Watcom Makefile for dos-libpcap.

+#

+# Specify MODEL = `3r' or `3s'

+# Specify TARGET = `pharlap' or `dos4g'

+#

+# Use this makefile from the libpcap root directory.

+# E.g. like this:

+#

+#  c:\net\pcap> wmake -f msdos\makefile.wc

+#

+

+MODEL  = 3s

+TARGET = dos4g

+

+OBJDIR = msdos\$(TARGET).w$(MODEL)

+LIB    = $(OBJDIR)\pcap.lib

+

+.EXTENSIONS: .l .y

+

+DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &

+       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF

+

+CC  = wcc386.exe

+ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s

+

+OBJS = $(OBJDIR)\grammar.obj  $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &

+       $(OBJDIR)\bpf_filt.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &

+       $(OBJDIR)\etherent.obj $(OBJDIR)\gencode.obj  $(OBJDIR)\nametoad.obj &

+       $(OBJDIR)\pcap-dos.obj $(OBJDIR)\pktdrvr.obj  $(OBJDIR)\optimize.obj &

+       $(OBJDIR)\savefile.obj $(OBJDIR)\inet.obj     $(OBJDIR)\ndis2.obj

+

+CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &

+         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &

+         -oilrtf -zm

+

+TEMPBIN = tmp.bin

+

+all: $(OBJDIR) $(OBJDIR)\pcap.lib

+

+$(OBJDIR):

+          - mkdir $(OBJDIR)

+

+$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg

+          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg

+

+wlib.arg: msdos\makefile.wc

+          %create $^@

+          for %f in ($(OBJS)) do %append $^@ +- %f

+

+$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c gnuc.h &

+  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h

+          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@

+

+$(OBJDIR)\ndis2.obj: msdos\ndis2.c

+          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@

+

+.ERASE

+.c{$(OBJDIR)}.obj:

+          *$(CC) $(CFLAGS) $[@ -fo=$@

+

+grammar.c tokdefs.h: grammar.y 

+          bison --name-prefix=pcap_ --yacc --defines $[@

+          - @del grammar.c

+          - @del tokdefs.h

+          ren y_tab.c grammar.c

+          ren y_tab.h tokdefs.h

+

+scanner.c: scanner.l

+          flex -Ppcap_ -7 -o$@ $[@

+

+msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S

+          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S

+          bin2c.exe  $(TEMPBIN) > $@

+          @del $(TEMPBIN)

+

+bin2c.exe: msdos\bin2c.c

+          wcl $[@

+

+clean realclean vclean: .SYMBOLIC

+          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &

+            @del %f\*.obj

+          @del grammar.c

+          @del tokdefs.h

+          @del scanner.c

+          @del bin2c.exe

+          @del bin2c.obj

+          @del msdos\pkt_stub.inc

+          @echo Cleaned

+

+#

+# dependencies

+#                     

+$(OBJDIR)\bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

+

+$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

+

+$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h

+

+$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-nam.h

+

+$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

+

+$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h

+

+$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

+

+$(OBJDIR)\inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h

+

+$(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h &

+  pf.h pcap-nam.h

+

+$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &

+  pcap-nam.h tokdefs.h

+

+$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &

+  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &

+  arcnet.h pf.h pcap-nam.h

+

+$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &

+  pcap-nam.h ethertyp.h

+

+$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &

+  msdos\pktdrvr.h

+

+$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h &

+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

+

+$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &

+  msdos\ndis2.h

+

diff --git a/msdos/ndis2.c b/msdos/ndis2.c
new file mode 100644
index 0000000..0a5ea2a
--- /dev/null
+++ b/msdos/ndis2.c
@@ -0,0 +1,860 @@
+/* 

+ * Copyright (c) 1993,1994

+ *      Texas A&M University.  All rights reserved.

+ *

+ * 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. All advertising materials mentioning features or use of this software

+ *    must display the following acknowledgement:

+ *      This product includes software developed by Texas A&M University

+ *      and its contributors.

+ * 4. Neither the name of the University nor the names of its contributors

+ *    may be used to endorse or promote products derived from this software

+ *    without specific prior written permission.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE

+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

+ * SUCH DAMAGE.

+ *

+ * Developers:

+ *             David K. Hess, Douglas Lee Schales, David R. Safford

+ *

+ * Heavily modified for Metaware HighC + GNU C 2.8+

+ *             Gisle Vanem 1998

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <dos.h>

+#include <io.h>

+#include <fcntl.h>

+#include <malloc.h>

+#include <string.h>

+

+#include "pcap-dos.h"

+#include "pcap-int.h"

+#include "msdos/ndis2.h"

+

+#if defined(USE_NDIS2)

+

+/*

+ *  Packet buffer handling

+ */

+extern int     FreePktBuf  (PktBuf *buf);

+extern int     EnquePktBuf (PktBuf *buf);

+extern PktBuf* AllocPktBuf (void);

+

+/*

+ *  Various defines

+ */

+#define MAX_NUM_DEBUG_STRINGS 90

+#define DEBUG_STRING_LENGTH   80

+#define STACK_POOL_SIZE       6

+#define STACK_SIZE            256

+

+#define MEDIA_FDDI            1

+#define MEDIA_ETHERNET        2

+#define MEDIA_TOKEN           3

+

+static int     startDebug     = 0;

+static int     stopDebug      = 0;

+

+static DWORD   droppedPackets = 0L;

+static WORD    frameSize      = 0;

+static WORD    headerSize     = 0;

+static int     mediaType      = 0;

+static char   *lastErr        = NULL;

+

+static BYTE    debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH];

+static BYTE   *freeStacks   [STACK_POOL_SIZE];

+static int     freeStackPtr = STACK_POOL_SIZE - 1;

+

+static ProtMan protManEntry = NULL;

+static WORD    protManDS    = 0;

+static volatile int xmitPending;

+

+static struct _PktBuf        *txBufPending;

+static struct _CardHandle    *handle;

+static struct _CommonChars    common;

+static struct _ProtocolChars  protChars;

+static struct _ProtDispatch   lowerTable;

+

+static struct _FailingModules failingModules;

+static struct _BindingsList   bindings;

+

+static struct {

+         WORD  err_num;

+         char *err_text;

+       } ndis_errlist[] = {

+

+  { ERR_SUCCESS,

+    "The function completed successfully.\n"  },

+

+  { ERR_WAIT_FOR_RELEASE,

+    "The ReceiveChain completed successfully but the protocol has\n"

+    "retained control of the buffer.\n"  },

+

+  { ERR_REQUEST_QUEUED,

+    "The current request has been queued.\n"  },

+

+  { ERR_FRAME_NOT_RECOGNIZED,

+    "Frame not recognized.\n"  },

+

+  { ERR_FRAME_REJECTED,

+    "Frame was discarded.\n"  },

+

+  { ERR_FORWARD_FRAME,

+    "Protocol wishes to forward frame to another protocol.\n"  },

+

+  { ERR_OUT_OF_RESOURCE,

+    "Out of resource.\n"  },

+

+  { ERR_INVALID_PARAMETER,

+    "Invalid parameter.\n"  },

+

+  { ERR_INVALID_FUNCTION,

+    "Invalid function.\n"  },

+

+  { ERR_NOT_SUPPORTED,

+    "Not supported.\n"  },

+

+  { ERR_HARDWARE_ERROR,

+    "Hardware error.\n"  },

+

+  { ERR_TRANSMIT_ERROR,

+    "The packet was not transmitted due to an error.\n"  },

+

+  { ERR_NO_SUCH_DESTINATION,

+    "Token ring packet was not recognized when transmitted.\n"  },

+

+  { ERR_BUFFER_TOO_SMALL,

+    "Provided buffer was too small.\n"  },

+

+  { ERR_ALREADY_STARTED,

+    "Network drivers already started.\n"  },

+

+  { ERR_INCOMPLETE_BINDING,

+    "Protocol driver could not complete its bindings.\n"  },

+

+  { ERR_DRIVER_NOT_INITIALIZED,

+    "MAC did not initialize properly.\n"  },

+

+  { ERR_HARDWARE_NOT_FOUND,

+    "Hardware not found.\n"  },

+

+  { ERR_HARDWARE_FAILURE,

+    "Hardware failure.\n"  },

+

+  { ERR_CONFIGURATION_FAILURE,

+    "Configuration failure.\n"  },

+

+  { ERR_INTERRUPT_CONFLICT,

+    "Interrupt conflict.\n"  },

+

+  { ERR_INCOMPATIBLE_MAC,

+    "The MAC is not compatible with the protocol.\n"  },

+

+  { ERR_INITIALIZATION_FAILED,

+    "Initialization failed.\n"  },

+

+  { ERR_NO_BINDING,

+    "Binding did not occur.\n"  },

+

+  { ERR_NETWORK_MAY_NOT_BE_CONNECTED,

+    "The network may not be connected to the adapter.\n"  },

+

+  { ERR_INCOMPATIBLE_OS_VERSION,

+    "The version of the operating system is incompatible with the protocol.\n"  },

+

+  { ERR_ALREADY_REGISTERED,

+    "The protocol is already registered.\n"  },

+

+  { ERR_PATH_NOT_FOUND,

+    "PROTMAN.EXE could not be found.\n"  },

+

+  { ERR_INSUFFICIENT_MEMORY,

+    "Insufficient memory.\n"  },

+

+  { ERR_INFO_NOT_FOUND,

+    "Protocol Mananger info structure is lost or corrupted.\n"  },

+

+  { ERR_GENERAL_FAILURE,

+    "General failure.\n"  }

+};

+

+/*

+ *  Some handy macros

+ */       

+#define PERROR(str)    printf("%s (%d): %s\n", __FILE__,__LINE__,str)

+#define DEBUG_RING()   (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \

+                        stopDebug = 0 : ++stopDebug])

+

+/*

+ * needs rewrite for DOSX

+ */

+#define MAC_DISPATCH(hnd)  ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable)

+#define MAC_STATUS(hnd)    ((struct _MacStatusTable*)  (hnd)->common->serviceStatus)

+#define MAC_CHAR(hnd)      ((struct _MacChars*)        (hnd)->common->serviceChars)

+

+#ifdef NDIS_DEBUG

+  #define DEBUG0(str)      printf (str)

+  #define DEBUG1(fmt,a)    printf (fmt,a)

+  #define DEBUG2(fmt,a,b)  printf (fmt,a,b)

+  #define TRACE0(str)      sprintf (DEBUG_RING(),str)

+  #define TRACE1(fmt,a)    sprintf (DEBUG_RING(),fmt,a)

+#else

+  #define DEBUG0(str)      ((void)0)

+  #define DEBUG1(fmt,a)    ((void)0)

+  #define DEBUG2(fmt,a,b)  ((void)0)

+  #define TRACE0(str)      ((void)0)

+  #define TRACE1(fmt,a)    ((void)0)

+#endif

+

+/*

+ * This routine is called from both threads

+ */

+void NdisFreeStack (BYTE *aStack)

+{

+  GUARD();

+

+  if (freeStackPtr == STACK_POOL_SIZE - 1)

+     PERROR ("tried to free too many stacks");

+

+  freeStacks[++freeStackPtr] = aStack;

+

+  if (freeStackPtr == 0)

+     TRACE0 ("freeStackPtr went positive\n");

+

+  UNGUARD();

+}

+

+/*

+ * This routine is called from callbacks to allocate local data

+ */

+BYTE *NdisAllocStack (void)

+{

+  BYTE *stack;

+

+  GUARD();

+

+  if (freeStackPtr < 0)

+  {

+    /* Ran out of stack buffers. Return NULL which will start

+     * dropping packets

+     */

+    TRACE0 ("freeStackPtr went negative\n");

+    stack = 0;

+  }

+  else

+    stack = freeStacks[freeStackPtr--];

+

+  UNGUARD();

+  return (stack);

+}

+

+CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3,

+                             WORD opcode, WORD targetDS))

+{

+  static int            bindEntry = 0;

+  struct _CommonChars  *macCommon;

+  volatile WORD result;

+

+  switch (opcode)

+  {

+    case REQ_INITIATE_BIND:

+         macCommon = (struct _CommonChars*) param2;

+         if (macCommon == NULL)

+	 {

+           printf ("There is an NDIS misconfiguration.\n");

+           result = ERR_GENERAL_FAILURE;

+	   break;

+	 }

+         DEBUG2 ("module name %s\n"

+                 "module type %s\n",

+                 macCommon->moduleName,

+                 ((MacChars*) macCommon->serviceChars)->macName);

+

+         /* Binding to the MAC */

+         result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon,

+                                            0, REQ_BIND,

+                                            macCommon->moduleDS);

+

+         if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName))

+              handle->common = macCommon;

+         else PERROR ("unknown module");

+         ++bindEntry;

+	 break;

+

+    case REQ_INITIATE_UNBIND:

+         macCommon = (struct _CommonChars*) param2;

+         result = macCommon->systemRequest ((DWORD)&common, 0,

+                                            0, REQ_UNBIND,

+                                            macCommon->moduleDS);

+         break;

+

+    default:

+         result = ERR_GENERAL_FAILURE;

+	 break;

+  }

+  ARGSUSED (param1);

+  ARGSUSED (param3);

+  ARGSUSED (targetDS);

+  return (result);

+}

+

+CALLBACK (NdisRequestConfirm (WORD protId, WORD macId,   WORD reqHandle,

+                              WORD status, WORD request, WORD protDS))

+{

+  ARGSUSED (protId);    ARGSUSED (macId);

+  ARGSUSED (reqHandle); ARGSUSED (status);

+  ARGSUSED (request);   ARGSUSED (protDS);

+  return (ERR_SUCCESS);

+}

+

+CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle,

+                               WORD status, WORD protDS))

+{

+  xmitPending--;

+  FreePktBuf (txBufPending);  /* Add passed ECB back to the free list */

+

+  ARGSUSED (reqHandle);

+  ARGSUSED (status);

+  ARGSUSED (protDS);

+  return (ERR_SUCCESS);

+}

+

+

+/*

+ * The primary function for receiving packets

+ */

+CALLBACK (NdisReceiveLookahead (WORD  macId,      WORD  frameSize,

+                                WORD  bytesAvail, BYTE *buffer,

+                                BYTE *indicate,   WORD  protDS))

+{

+  int     result;

+  PktBuf *pktBuf;

+  WORD    bytesCopied;

+  struct _TDBufDescr tDBufDescr;

+

+#if 0

+  TRACE1 ("lookahead length = %d, ", bytesAvail);

+  TRACE1 ("ecb = %08lX, ",          *ecb);

+  TRACE1 ("count = %08lX\n",         count);

+  TRACE1 ("offset = %08lX, ",        offset);

+  TRACE1 ("timesAllowed = %d, ",     timesAllowed);

+  TRACE1 ("packet size = %d\n",      look->dataLookAheadLen);

+#endif

+

+  /* Allocate a buffer for the packet

+   */

+  if ((pktBuf = AllocPktBuf()) == NULL)

+  {

+    droppedPackets++;

+    return (ERR_FRAME_REJECTED);

+  }

+

+  /*

+   * Now kludge things. Note we will have to undo this later. This will

+   * make the packet contiguous after the MLID has done the requested copy.

+   */

+

+  tDBufDescr.tDDataCount = 1;

+  tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL;

+  tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer;

+  tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length;

+  tDBufDescr.tDBufDescrRec[0].dummy     = 0;

+

+  result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr,

+                                               handle->common->moduleDS);

+  pktBuf->packetLength = bytesCopied;

+

+  if (result == ERR_SUCCESS)

+       EnquePktBuf(pktBuf);

+  else FreePktBuf (pktBuf);

+

+  ARGSUSED (frameSize);

+  ARGSUSED (bytesAvail);

+  ARGSUSED (indicate);

+  ARGSUSED (protDS);

+

+  return (ERR_SUCCESS);

+}

+

+CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS))

+{

+  ARGSUSED (macId);

+  ARGSUSED (protDS);

+

+  /* We don't give a hoot about these. Just return

+   */

+  return (ERR_SUCCESS);

+}

+

+/*

+ * This is the OTHER way we may receive packets

+ */

+CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle,

+                            struct _RxBufDescr *rxBufDescr,

+                            BYTE *indicate, WORD protDS))

+{

+  struct _PktBuf *pktBuf;

+  int     i;

+

+  /*

+   * For now we copy the entire packet over to a PktBuf structure. This may be

+   * a performance hit but this routine probably isn't called very much, and

+   * it is a lot of work to do it otherwise. Also if it is a filter protocol

+   * packet we could end up sucking up MAC buffes.

+   */

+

+  if ((pktBuf = AllocPktBuf()) == NULL)

+  {

+    droppedPackets++;

+    return (ERR_FRAME_REJECTED);

+  }

+  pktBuf->packetLength = 0;

+

+  /* Copy the packet to the buffer

+   */

+  for (i = 0; i < rxBufDescr->rxDataCount; ++i)

+  {

+    struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i];

+

+    memcpy (pktBuf->buffer + pktBuf->packetLength,

+            rxDescr->rxDataPtr, rxDescr->rxDataLen);

+    pktBuf->packetLength += rxDescr->rxDataLen;

+  }

+

+  EnquePktBuf (pktBuf);

+

+  ARGSUSED (frameSize);

+  ARGSUSED (reqHandle);

+  ARGSUSED (indicate);

+  ARGSUSED (protDS);   

+

+  /* This frees up the buffer for the MAC to use

+   */

+  return (ERR_SUCCESS);

+}

+

+CALLBACK (NdisStatusProc (WORD macId,  WORD param1, BYTE *indicate,

+                          WORD opcode, WORD protDS))

+{

+  switch (opcode)

+  {

+    case STATUS_RING_STATUS:

+	 break;

+    case STATUS_ADAPTER_CHECK:

+	 break;

+    case STATUS_START_RESET:

+	 break;

+    case STATUS_INTERRUPT:

+	 break;

+    case STATUS_END_RESET:

+	 break;

+    default:

+	 break;

+  }

+  ARGSUSED (macId);

+  ARGSUSED (param1);

+  ARGSUSED (indicate);

+  ARGSUSED (opcode);

+  ARGSUSED (protDS);

+

+  /* We don't need to do anything about this stuff yet

+   */

+  return (ERR_SUCCESS);

+}

+

+/*

+ * Tell the NDIS driver to start the delivery of the packet

+ */

+int NdisSendPacket (struct _PktBuf *pktBuf, int macId)

+{ 

+  struct _TxBufDescr txBufDescr;

+  int     result;

+

+  xmitPending++;

+  txBufPending = pktBuf;    /* we only have 1 pending Tx at a time */

+

+  txBufDescr.txImmedLen  = 0;

+  txBufDescr.txImmedPtr  = NULL;

+  txBufDescr.txDataCount = 1;

+  txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL;

+  txBufDescr.txBufDescrRec[0].dummy     = 0;

+  txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength;

+  txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer;

+

+  result = MAC_DISPATCH(handle)->transmitChain (common.moduleId,

+                                                pktBuf->handle,

+                                                &txBufDescr,

+                                                handle->common->moduleDS);

+  switch (result)

+  {

+    case ERR_OUT_OF_RESOURCE:

+         /* Note that this should not happen but if it does there is not

+          * much we can do about it

+          */

+         printf ("ERROR: transmit queue overflowed\n");

+         return (0);

+

+    case ERR_SUCCESS:

+         /* Everything was hunky dory and synchronous. Free up the 

+          * packet buffer

+          */

+         xmitPending--;

+         FreePktBuf (pktBuf);

+         return (1);

+

+    case ERR_REQUEST_QUEUED:

+         /* Everything was hunky dory and asynchronous. Do nothing

+          */

+         return (1);

+

+    default:

+         printf ("Tx fail, code = %04X\n", result);

+         return (0);

+  }

+}

+

+

+

+static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]);

+

+static char *Ndis_strerror (WORD errorCode)

+{

+  static char buf[30];

+  int    i;

+

+  for (i = 0; i < ndis_nerr; i++)

+      if (errorCode == ndis_errlist[i].err_num)

+         return (ndis_errlist[i].err_text);

+

+  sprintf (buf,"unknown error %d",errorCode);

+  return (buf);

+}

+

+

+char *NdisLastError (void)

+{

+  char *errStr = lastErr;

+  lastErr = NULL;

+  return (errStr);

+}

+

+int NdisOpen (void)

+{

+  struct _ReqBlock reqBlock;

+  int     result;

+  int     ndisFd = open (NDIS_PATH, O_RDONLY);

+

+  if (ndisFd < 0)

+  {

+    printf ("Could not open NDIS Protocol Manager device.\n");

+    return (0);

+  }

+

+  memset (&reqBlock, 0, sizeof(ReqBlock));

+

+  reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE;

+

+  result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock));

+  if (result != 0)

+  {

+    printf ("Could not get Protocol Manager linkage.\n");

+    close (ndisFd);

+    return (0);

+  }

+

+  close (ndisFd);

+  protManEntry = (ProtMan) reqBlock.pointer1;

+  protManDS    = reqBlock.word1;

+

+  DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry));

+  DEBUG1 ("ProtMan DS  = %04X\n", protManDS);

+  return (1);

+}

+

+

+int NdisRegisterAndBind (int promis)

+{

+  struct _ReqBlock reqBlock;

+  WORD    result;

+

+  memset (&common,0,sizeof(common));

+

+  common.tableSize = sizeof (common);

+

+  common.majorNdisVersion   = 2;

+  common.minorNdisVersion   = 0;

+  common.majorModuleVersion = 2;

+  common.minorModuleVersion = 0;

+

+  /* Indicates binding from below and dynamically loaded

+   */

+  common.moduleFlags = 0x00000006L;

+

+  strcpy (common.moduleName, "PCAP");

+

+  common.protocolLevelUpper = 0xFF;

+  common.protocolLevelLower = 1;

+  common.interfaceLower     = 1;

+#ifdef __DJGPP__

+  common.moduleDS           = _dos_ds; /* the callback data segment */

+#else

+  common.moduleDS           = _DS;

+#endif

+

+  common.systemRequest      = (SystemRequest) systemRequestGlue;

+  common.serviceChars       = (BYTE*) &protChars;

+  common.serviceStatus      = NULL;

+  common.upperDispatchTable = NULL;

+  common.lowerDispatchTable = (BYTE*) &lowerTable;

+

+  protChars.length  = sizeof (protChars);

+  protChars.name[0] = 0;

+  protChars.type    = 0;

+

+  lowerTable.backPointer        = &common;

+  lowerTable.requestConfirm     = requestConfirmGlue;

+  lowerTable.transmitConfirm    = transmitConfirmGlue;

+  lowerTable.receiveLookahead   = receiveLookaheadGlue;

+  lowerTable.indicationComplete = indicationCompleteGlue;

+  lowerTable.receiveChain       = receiveChainGlue;

+  lowerTable.status             = statusGlue;

+  lowerTable.flags              = 3;

+  if (promis)

+     lowerTable.flags |= 4;   /* promiscous mode (receive everything) */

+

+  bindings.numBindings = 1;

+  strcpy (bindings.moduleName[0], handle->moduleName);

+

+  /* Register ourselves with NDIS

+   */

+  reqBlock.opcode   = PM_REGISTER_MODULE;

+  reqBlock.pointer1 = (BYTE FAR*) &common;

+  reqBlock.pointer2 = (BYTE FAR*) &bindings;

+

+  result = (*protManEntry) (&reqBlock, protManDS);

+  if (result)

+  {

+    printf ("Protman registering failed: %s\n", Ndis_strerror(result));

+    return (0);

+  }

+

+  /* Start the binding process

+   */

+  reqBlock.opcode   = PM_BIND_AND_START;

+  reqBlock.pointer1 = (BYTE FAR*) &failingModules;

+

+  result = (*protManEntry) (&reqBlock, protManDS);

+  if (result)

+  {

+    printf ("Start binding failed: %s\n", Ndis_strerror(result));

+    return (0);

+  }

+  return (1);

+}

+

+static int CheckMacFeatures (CardHandle *card)

+{

+  DWORD      serviceFlags;

+  BYTE _far *mediaString;

+  BYTE _far *mac_addr;

+

+  DEBUG2 ("checking card features\n"

+          "common table address = %08lX, macId = %d\n",

+          card->common, card->common->moduleId);

+

+  serviceFlags = MAC_CHAR (handle)->serviceFlags;

+

+  if ((serviceFlags & SF_PROMISCUOUS) == 0)

+  {

+    printf ("The MAC %s does not support promiscuous mode.\n",

+            card->moduleName);

+    return (0);

+  }

+

+  mediaString = MAC_CHAR (handle)->macName;

+

+  DEBUG1 ("media type = %s\n",mediaString);

+

+  /* Get the media type. And set the header size

+   */

+  if (!strncmp(mediaString,"802.3",5) ||

+      !strncmp(mediaString,"DIX",3)   ||

+      !strncmp(mediaString,"DIX+802.3",9))

+       headerSize = sizeof (EthernetIIHeader);

+

+  else if (!strncmp(mediaString,"FDDI",4))

+       headerSize = sizeof (FddiHeader) +

+                    sizeof (Ieee802Dot2SnapHeader);

+  else

+  {

+    printf ("Unsupported MAC type: `%s'\n", mediaString);

+    return (0);

+  }

+

+  frameSize = MAC_CHAR (handle)->maxFrameSize;

+  mac_addr  = MAC_CHAR (handle)->currentAddress;

+

+  printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n",

+          mac_addr[0], mac_addr[1], mac_addr[2],

+          mac_addr[3], mac_addr[4], mac_addr[5]);

+  return (1);

+}

+

+static int NdisStartMac (CardHandle *card)

+{

+  WORD result;

+

+  /* Set the lookahead length

+   */

+  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,

+                                          headerSize, 0,

+                                          REQ_SET_LOOKAHEAD,

+                                          card->common->moduleDS);

+

+  /* We assume that if we got INVALID PARAMETER then either this

+   * is not supported or will work anyway. NE2000 does this.

+   */

+  if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER)

+  {

+    DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result));

+    return (0);

+  }

+

+  /* Set the packet filter. Note that for some medias and drivers we

+   * must specify all three flags or the card(s) will not operate correctly.

+   */

+  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,

+                      /* all packets */   FILTER_PROMISCUOUS |

+                      /* packets to us */ FILTER_DIRECTED    |

+                      /* broadcasts */    FILTER_BROADCAST,

+                                          0, REQ_SET_PACKET_FILTER,

+                                          card->common->moduleDS);

+  if (result != ERR_SUCCESS)

+  {

+    DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result));

+    return (0);

+  }

+

+  /* If OPEN/CLOSE supported then open the adapter

+   */

+  if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE)

+  {

+    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL,

+                                            REQ_OPEN_ADAPTER,

+                                            card->common->moduleDS);

+    if (result != ERR_SUCCESS)

+    {

+      DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result));

+      return (0);

+    }

+  }

+  return (1);

+}

+

+void NdisShutdown (void)

+{

+  struct _ReqBlock reqBlock;

+  int     result, i;

+

+  if (!handle)

+     return;

+

+  /* If the adapters support open and are open then close them

+   */

+  if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) &&

+      (MAC_STATUS(handle)->macStatus & MAC_OPEN))

+  {

+    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0,

+                                            REQ_CLOSE_ADAPTER,

+                                            handle->common->moduleDS);

+    if (result != ERR_SUCCESS)

+    {

+      printf ("Closing the MAC failed: %s\n", Ndis_strerror(result));

+      return;

+    }

+  }

+

+  /* Tell the Protocol Manager to unbind and stop

+   */

+  reqBlock.opcode   = PM_UNBIND_AND_STOP;

+  reqBlock.pointer1 = (BYTE FAR*) &failingModules;

+  reqBlock.pointer2 = NULL;

+

+  result = (*protManEntry) (&reqBlock, protManDS);

+  if (result)

+     printf ("Unbind failed: %s\n",  Ndis_strerror(result));

+

+  for (i = 0; i < STACK_POOL_SIZE; ++i)

+     free (freeStacks[i] - STACK_SIZE);

+

+  handle = NULL;

+}

+

+int NdisInit (int promis)

+{

+  int i, result;

+

+  /* Allocate the real mode stacks used for NDIS callbacks

+   */

+  for (i = 0; i < STACK_POOL_SIZE; ++i)

+  {

+    freeStacks[i] = malloc (STACK_SIZE);

+    if (!freeStacks[i])

+       return (0);

+    freeStacks[i] += STACK_SIZE;

+  }

+

+  if (!NdisOpen())

+     return (0);

+

+  if (!NdisRegisterAndBind(promis))

+     return (0);

+

+  DEBUG1 ("My module id: %d\n", common.moduleId);

+  DEBUG1 ("Handle id;    %d\n", handle->common->moduleId);

+  DEBUG1 ("MAC card:     %-16s - ", handle->moduleName);

+

+  atexit (NdisShutdown);

+

+  if (!CheckMacFeatures(&handle))

+     return (0);

+

+  switch (mediaType)

+  {

+    case MEDIA_FDDI:

+         DEBUG0 ("Media type: FDDI");

+	 break;

+    case MEDIA_ETHERNET:

+         DEBUG0 ("Media type: ETHERNET");

+	 break;

+    default:

+         DEBUG0 ("Unsupported media.\n");

+         return (0);

+  }

+

+  DEBUG1 (" - Frame size: %d\n", frameSize);

+

+  if (!NdisStartMac(&handle))

+     return (0);

+  return (1);

+}

+#endif  /* USE_NDIS2 */

+

diff --git a/msdos/ndis2.h b/msdos/ndis2.h
new file mode 100644
index 0000000..dc72f4c
--- /dev/null
+++ b/msdos/ndis2.h
@@ -0,0 +1,559 @@
+/* 

+ * Copyright (c) 1993,1994

+ *      Texas A&M University.  All rights reserved.

+ *

+ * 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. All advertising materials mentioning features or use of this software

+ *    must display the following acknowledgement:

+ *      This product includes software developed by Texas A&M University

+ *      and its contributors.

+ * 4. Neither the name of the University nor the names of its contributors

+ *    may be used to endorse or promote products derived from this software

+ *    without specific prior written permission.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE

+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

+ * SUCH DAMAGE.

+ *

+ * Developers:

+ *             David K. Hess, Douglas Lee Schales, David R. Safford

+ *

+ * Heavily modified for Metaware HighC + GNU C 2.8+

+ *             Gisle Vanem 1998

+ */

+

+#ifndef __PCAP_NDIS_H

+#define __PCAP_NDIS_H

+

+#if defined (__HIGHC__)

+  #define pascal          _CC(_CALLEE_POPS_STACK & ~_REVERSE_PARMS) /* calling convention */

+  #define CALLBACK(foo)   pascal WORD foo

+  #define PAS_PTR(x,arg)  typedef FAR WORD pascal (*x) arg

+  #define GUARD()         _inline (0x9C,0xFA)   /* pushfd, cli */

+  #define UNGUARD()       _inline (0x9D)        /* popfd */

+  #define FAR             _far

+

+#elif defined(__GNUC__)

+  #define CALLBACK(foo)   WORD foo __attribute__((stdcall))

+  #define PAS_PTR(x,arg)  typedef WORD (*x) arg __attribute__((stdcall))

+  #define GUARD()         __asm__ __volatile__ ("pushfd; cli")

+  #define UNGUARD()       __asm__ __volatile__ ("popfd")

+  #define FAR

+

+#elif defined (__TURBOC__)

+  #define CALLBACK(foo)   WORD pascal foo

+  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg

+  #define GUARD()         _asm { pushf; cli }

+  #define UNGUARD()       _asm { popf }

+  #define FAR             _far

+

+#elif defined (__WATCOMC__)

+  #define CALLBACK(foo)   WORD pascal foo

+  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg

+  #define GUARD()         _disable()

+  #define UNGUARD()       _enable()

+  #define FAR             _far

+

+#else

+  #error Unsupported compiler

+#endif

+

+

+/*

+ *  Forwards

+ */

+struct _ReqBlock;

+struct _TxBufDescr;

+struct _TDBufDescr;

+

+/*

+ * Protocol Manager API

+ */

+PAS_PTR (ProtMan, (struct _ReqBlock FAR*, WORD));

+

+/*

+ * System request

+ */

+PAS_PTR (SystemRequest, (DWORD, DWORD, WORD, WORD, WORD));

+

+/*

+ * MAC API

+ */

+PAS_PTR (TransmitChain, (WORD, WORD, struct _TxBufDescr FAR*, WORD));

+PAS_PTR (TransferData,  (WORD*,WORD, struct _TDBufDescr FAR*, WORD));

+PAS_PTR (Request,       (WORD, WORD, WORD, DWORD, WORD, WORD));

+PAS_PTR (ReceiveRelease,(WORD, WORD));

+PAS_PTR (IndicationOn,  (WORD));

+PAS_PTR (IndicationOff, (WORD));

+

+

+typedef enum {

+        HARDWARE_NOT_INSTALLED  = 0,

+        HARDWARE_FAILED_DIAG    = 1,

+        HARDWARE_FAILED_CONFIG  = 2,

+        HARDWARE_HARD_FAULT     = 3,

+        HARDWARE_SOFT_FAULT     = 4,

+        HARDWARE_OK             = 7,

+        HARDWARE_MASK           = 0x0007,

+        MAC_BOUND               = 0x0008,

+        MAC_OPEN                = 0x0010,

+        DIAG_IN_PROGRESS        = 0x0020

+      } NdisMacStatus;

+

+typedef enum {

+        STATUS_RING_STATUS      = 1,

+        STATUS_ADAPTER_CHECK    = 2,

+        STATUS_START_RESET      = 3,

+        STATUS_INTERRUPT        = 4,

+        STATUS_END_RESET        = 5

+      } NdisStatus;

+

+typedef enum {

+        FILTER_DIRECTED         = 1,

+        FILTER_BROADCAST        = 2,

+        FILTER_PROMISCUOUS      = 4,

+        FILTER_SOURCE_ROUTE     = 8

+      } NdisPacketFilter;

+

+typedef enum {

+        REQ_INITIATE_DIAGNOSTICS     = 1,

+        REQ_READ_ERROR_LOG           = 2,

+        REQ_SET_STATION_ADDRESS      = 3,

+        REQ_OPEN_ADAPTER             = 4,

+        REQ_CLOSE_ADAPTER            = 5,

+        REQ_RESET_MAC                = 6,

+        REQ_SET_PACKET_FILTER        = 7,

+        REQ_ADD_MULTICAST_ADDRESS    = 8,

+        REQ_DELETE_MULTICAST_ADDRESS = 9,

+        REQ_UPDATE_STATISTICS        = 10,

+        REQ_CLEAR_STATISTICS         = 11,

+        REQ_INTERRUPT_REQUEST        = 12,

+        REQ_SET_FUNCTIONAL_ADDRESS   = 13,

+        REQ_SET_LOOKAHEAD            = 14

+      } NdisGeneralRequest;

+

+typedef enum {

+        SF_BROADCAST             = 0x00000001L,

+        SF_MULTICAST             = 0x00000002L,

+        SF_FUNCTIONAL            = 0x00000004L,

+        SF_PROMISCUOUS           = 0x00000008L,

+        SF_SOFT_ADDRESS          = 0x00000010L,

+        SF_STATS_CURRENT         = 0x00000020L,

+        SF_INITIATE_DIAGS        = 0x00000040L,

+        SF_LOOPBACK              = 0x00000080L,

+        SF_RECEIVE_CHAIN         = 0x00000100L,

+        SF_SOURCE_ROUTING        = 0x00000200L,

+        SF_RESET_MAC             = 0x00000400L,

+        SF_OPEN_CLOSE            = 0x00000800L,

+        SF_INTERRUPT_REQUEST     = 0x00001000L,

+        SF_SOURCE_ROUTING_BRIDGE = 0x00002000L,

+        SF_VIRTUAL_ADDRESSES     = 0x00004000L

+      } NdisMacServiceFlags;

+

+typedef enum {

+        REQ_INITIATE_BIND        = 1,

+        REQ_BIND                 = 2,

+        REQ_INITIATE_PREBIND     = 3,

+        REQ_INITIATE_UNBIND      = 4,

+        REQ_UNBIND               = 5

+      } NdisSysRequest;

+

+typedef enum  {

+        PM_GET_PROTOCOL_MANAGER_INFO      = 1,

+        PM_REGISTER_MODULE                = 2,

+        PM_BIND_AND_START                 = 3,

+        PM_GET_PROTOCOL_MANAGER_LINKAGE   = 4,

+        PM_GET_PROTOCOL_INI_PATH          = 5,

+        PM_REGISTER_PROTOCOL_MANAGER_INFO = 6,

+        PM_INIT_AND_REGISTER              = 7,

+        PM_UNBIND_AND_STOP                = 8,

+        PM_BIND_STATUS                    = 9,

+        PM_REGISTER_STATUS                = 10

+      } NdisProtManager;

+

+

+typedef enum {

+        ERR_SUCCESS                      = 0x00,

+        ERR_WAIT_FOR_RELEASE             = 0x01,

+        ERR_REQUEST_QUEUED               = 0x02,

+        ERR_FRAME_NOT_RECOGNIZED         = 0x03,

+        ERR_FRAME_REJECTED               = 0x04,

+        ERR_FORWARD_FRAME                = 0x05,

+        ERR_OUT_OF_RESOURCE              = 0x06,

+        ERR_INVALID_PARAMETER            = 0x07,

+        ERR_INVALID_FUNCTION             = 0x08,

+        ERR_NOT_SUPPORTED                = 0x09,

+        ERR_HARDWARE_ERROR               = 0x0A,

+        ERR_TRANSMIT_ERROR               = 0x0B,

+        ERR_NO_SUCH_DESTINATION          = 0x0C,

+        ERR_BUFFER_TOO_SMALL             = 0x0D,

+        ERR_ALREADY_STARTED              = 0x20,

+        ERR_INCOMPLETE_BINDING           = 0x21,

+        ERR_DRIVER_NOT_INITIALIZED       = 0x22,

+        ERR_HARDWARE_NOT_FOUND           = 0x23,

+        ERR_HARDWARE_FAILURE             = 0x24,

+        ERR_CONFIGURATION_FAILURE        = 0x25,

+        ERR_INTERRUPT_CONFLICT           = 0x26,

+        ERR_INCOMPATIBLE_MAC             = 0x27,

+        ERR_INITIALIZATION_FAILED        = 0x28,

+        ERR_NO_BINDING                   = 0x29,

+        ERR_NETWORK_MAY_NOT_BE_CONNECTED = 0x2A,

+        ERR_INCOMPATIBLE_OS_VERSION      = 0x2B,

+        ERR_ALREADY_REGISTERED           = 0x2C,

+        ERR_PATH_NOT_FOUND               = 0x2D,

+        ERR_INSUFFICIENT_MEMORY          = 0x2E,

+        ERR_INFO_NOT_FOUND               = 0x2F,

+        ERR_GENERAL_FAILURE              = 0xFF

+      } NdisError;

+

+#define NDIS_PARAM_INTEGER   0

+#define NDIS_PARAM_STRING    1

+

+#define NDIS_TX_BUF_LENGTH   8

+#define NDIS_TD_BUF_LENGTH   1

+#define NDIS_RX_BUF_LENGTH   8

+

+#define NDIS_PTR_PHYSICAL    0

+#define NDIS_PTR_VIRTUAL     2

+

+#define NDIS_PATH    "PROTMAN$"

+

+

+typedef struct _CommonChars {

+        WORD  tableSize;

+        BYTE  majorNdisVersion;        /* 2 - Latest version */

+        BYTE  minorNdisVersion;        /* 0                  */

+        WORD  reserved1;

+        BYTE  majorModuleVersion;

+        BYTE  minorModuleVersion;

+        DWORD moduleFlags;

+        /* 0 - Binding at upper boundary supported

+         * 1 - Binding at lower boundary supported

+         * 2 - Dynamically bound.

+         * 3-31 - Reserved, must be zero.

+         */

+        BYTE  moduleName[16];

+        BYTE  protocolLevelUpper;

+        /* 1 - MAC

+         * 2 - Data Link

+         * 3 - Network

+         * 4 - Transport

+         * 5 - Session

+         * -1 - Not specified

+         */

+        BYTE  interfaceUpper;

+        BYTE  protocolLevelLower;

+        /* 0 - Physical

+         * 1 - MAC

+         * 2 - Data Link

+         * 3 - Network

+         * 4 - Transport

+         * 5 - Session

+         * -1 - Not specified

+         */

+        BYTE  interfaceLower;

+        WORD  moduleId;

+        WORD  moduleDS;

+        SystemRequest systemRequest;

+        BYTE *serviceChars;

+        BYTE *serviceStatus;

+        BYTE *upperDispatchTable;

+        BYTE *lowerDispatchTable;

+        BYTE *reserved2;            /* Must be NULL */

+        BYTE *reserved3;            /* Must be NULL */

+      } CommonChars;

+

+

+typedef struct _MulticastList {

+        WORD   maxMulticastAddresses;

+        WORD   numberMulticastAddresses;

+        BYTE   multicastAddress[16][16];

+      } MulticastList;

+

+

+typedef struct _MacChars {

+        WORD   tableSize;

+        BYTE   macName[16];

+        WORD   addressLength;

+        BYTE   permanentAddress[16];

+        BYTE   currentAddress[16];

+        DWORD  currentFunctionalAddress;

+        MulticastList *multicastList;

+        DWORD  linkSpeed;

+        DWORD  serviceFlags;

+        WORD   maxFrameSize;

+        DWORD  txBufferSize;

+        WORD   txBufferAllocSize;

+        DWORD  rxBufferSize;

+        WORD   rxBufferAllocSize;

+        BYTE   ieeeVendor[3];

+        BYTE   vendorAdapter;

+        BYTE  *vendorAdapterDescription;

+        WORD   interruptLevel;

+        WORD   txQueueDepth;

+        WORD   maxDataBlocks;

+      } MacChars;

+

+

+typedef struct _ProtocolChars {

+        WORD   length;

+        BYTE   name[16];

+        WORD   type;

+      } ProtocolChars;

+

+

+typedef struct _MacUpperDispatch {

+        CommonChars      *backPointer;

+        Request           request;

+        TransmitChain     transmitChain;

+        TransferData      transferData;

+        ReceiveRelease    receiveRelease;

+        IndicationOn      indicationOn;

+        IndicationOff     indicationOff;

+      } MacUpperDispatch;

+

+

+typedef struct _MacStatusTable {

+        WORD   tableSize;

+        DWORD  lastDiag;

+        DWORD  macStatus;

+        WORD   packetFilter;

+        BYTE  *mediaSpecificStats;

+        DWORD  lastClear;

+        DWORD  totalFramesRx;

+        DWORD  totalFramesCrc;

+        DWORD  totalBytesRx;

+        DWORD  totalDiscardBufSpaceRx;

+        DWORD  totalMulticastRx;

+        DWORD  totalBroadcastRx;

+        DWORD  obsolete1[5];

+        DWORD  totalDiscardHwErrorRx;

+        DWORD  totalFramesTx;

+        DWORD  totalBytesTx;

+        DWORD  totalMulticastTx;

+        DWORD  totalBroadcastTx;

+        DWORD  obsolete2[2];

+        DWORD  totalDiscardTimeoutTx;

+        DWORD  totalDiscardHwErrorTx;

+      } MacStatusTable;

+

+

+typedef struct _ProtDispatch {

+        CommonChars *backPointer;

+        DWORD        flags;

+        /* 0 - handles non-LLC frames

+         * 1 - handles specific-LSAP LLC frames

+         * 2 - handles specific-LSAP LLC frames

+         * 3-31 - reserved must be 0

+         */

+        void  (*requestConfirm) (void);

+        void  (*transmitConfirm) (void);

+        void  (*receiveLookahead) (void);

+        void  (*indicationComplete) (void);

+        void  (*receiveChain) (void);

+        void  (*status) (void);

+      } ProtDispatch;

+

+

+typedef struct _ReqBlock {

+        WORD      opcode;

+        WORD      status;

+        BYTE FAR *pointer1;

+        BYTE FAR *pointer2;

+        WORD      word1;

+      } ReqBlock;

+

+

+typedef struct _TxBufDescrRec {

+        BYTE   txPtrType;

+        BYTE   dummy;

+        WORD   txDataLen;

+        BYTE  *txDataPtr;

+      } TxBufDescrRec;

+

+

+typedef struct _TxBufDescr {

+        WORD          txImmedLen;

+        BYTE         *txImmedPtr;

+        WORD          txDataCount;

+        TxBufDescrRec txBufDescrRec[NDIS_TX_BUF_LENGTH];

+      } TxBufDescr;

+

+

+typedef struct _TDBufDescrRec {

+        BYTE   tDPtrType;

+        BYTE   dummy;

+        WORD   tDDataLen;

+        BYTE  *tDDataPtr;

+      } TDBufDescrRec;

+

+

+typedef struct _TDBufDescr {

+        WORD          tDDataCount;

+        TDBufDescrRec tDBufDescrRec[NDIS_TD_BUF_LENGTH];

+      } TDBufDescr;

+

+

+typedef struct _RxBufDescrRec {

+        WORD   rxDataLen;

+        BYTE  *rxDataPtr;

+      } RxBufDescrRec;

+

+

+typedef struct _RxBufDescr {

+        WORD          rxDataCount;

+        RxBufDescrRec rxBufDescrRec[NDIS_RX_BUF_LENGTH];

+      } RxBufDescr;

+

+

+typedef struct _PktBuf {

+	struct _PktBuf *nextLink;

+	struct _PktBuf *prevLink;

+        int    handle;

+        int    length;

+        int    packetLength;

+        DWORD  sequence;

+        BYTE  *buffer;

+      } PktBuf;

+

+

+typedef struct _CardHandle {

+        BYTE         moduleName[16];

+        CommonChars *common;

+      } CardHandle;

+

+

+typedef struct _BindingsList {

+        WORD  numBindings;

+        BYTE  moduleName[2][16];

+      } BindingsList;

+

+

+typedef struct _FailingModules {

+        BYTE  upperModuleName[16];

+        BYTE  lowerModuleName[16];

+      } FailingModules;

+

+

+typedef union _HardwareAddress {

+        BYTE  bytes[6];

+        WORD  words[3];

+        struct {

+          BYTE bytes[6];

+        } addr;

+      } HardwareAddress;

+

+

+typedef struct _FddiHeader {

+        BYTE             frameControl;

+        HardwareAddress  etherDestHost;

+        HardwareAddress  etherSrcHost;

+      } FddiHeader;

+

+

+typedef struct _EthernetIIHeader {

+        HardwareAddress  etherDestHost;

+        HardwareAddress  etherSrcHost;

+        WORD             etherType;

+      } EthernetIIHeader;

+

+

+typedef struct _Ieee802Dot5Header {

+        HardwareAddress  etherDestHost;

+        HardwareAddress  etherSrcHost;

+        BYTE             routeInfo[30];

+      } Ieee802Dot5Header;

+

+

+typedef struct _Ieee802Dot2SnapHeader {

+        BYTE  dsap;                      /* 0xAA */

+        BYTE  ssap;                      /* 0xAA */

+        BYTE  control;                   /* 3    */

+        BYTE protocolId[5];

+      } Ieee802Dot2SnapHeader;

+

+

+/*

+ *  Prototypes

+ */

+extern char *NdisLastError        (void);

+extern int   NdisOpen             (void);

+extern int   NdisInit             (int promis);

+extern int   NdisRegisterAndBind  (int promis);

+extern void  NdisShutdown         (void);

+extern void  NdisCheckMacFeatures (struct _CardHandle *card);

+extern int   NdisSendPacket       (struct _PktBuf *pktBuf, int macId);

+

+/*

+ *  Assembly "glue" functions

+ */

+extern int systemRequestGlue();

+extern int requestConfirmGlue();

+extern int transmitConfirmGlue();

+extern int receiveLookaheadGlue();

+extern int indicationCompleteGlue();

+extern int receiveChainGlue();

+extern int statusGlue();

+

+/*

+ *  IOCTL function

+ */

+#ifdef __SMALL__

+extern int _far NdisGetLinkage (int handle, char *data, int size);

+#else

+extern int NdisGetLinkage (int handle, char *data, int size);

+#endif

+

+/*

+ *  NDIS callback handlers

+ */

+CALLBACK (NdisSystemRequest     (DWORD,DWORD, WORD, WORD, WORD));

+CALLBACK (NdisRequestConfirm    ( WORD, WORD, WORD, WORD, WORD,WORD));

+CALLBACK (NdisTransmitConfirm   ( WORD, WORD, WORD, WORD, WORD));

+CALLBACK (NdisReceiveLookahead  ( WORD, WORD, WORD, BYTE*, BYTE*, WORD));

+CALLBACK (NdisReceiveChain      ( WORD, WORD, WORD, struct _RxBufDescr*, BYTE*, WORD));

+CALLBACK (NdisStatusProc        ( WORD, WORD, BYTE*, WORD,WORD));

+CALLBACK (NdisIndicationComplete( WORD, WORD));

+

+BYTE *NdisAllocStack (void);

+void  NdisFreeStack  (BYTE*);

+

+#ifdef __HIGHC__

+  #define RENAME_ASM_SYM(x) pragma Alias(x,"@" #x "")  /* prepend `@' */

+  #define RENAME_C_SYM(x)   pragma Alias(x,"_" #x "")  /* prepend `_' */

+

+  RENAME_ASM_SYM (systemRequestGlue);

+  RENAME_ASM_SYM (requestConfirmGlue);

+  RENAME_ASM_SYM (transmitConfirmGlue);

+  RENAME_ASM_SYM (receiveLookaheadGlue);

+  RENAME_ASM_SYM (indicationCompleteGlue);

+  RENAME_ASM_SYM (receiveChainGlue);

+  RENAME_ASM_SYM (statusGlue);

+  RENAME_ASM_SYM (NdisGetLinkage);

+  RENAME_C_SYM   (NdisSystemRequest);

+  RENAME_C_SYM   (NdisRequestConfirm);

+  RENAME_C_SYM   (NdisTransmitConfirm);

+  RENAME_C_SYM   (NdisReceiveLookahead);

+  RENAME_C_SYM   (NdisIndicationComplete);

+  RENAME_C_SYM   (NdisReceiveChain);

+  RENAME_C_SYM   (NdisStatusProc);

+  RENAME_C_SYM   (NdisAllocStack);

+  RENAME_C_SYM   (NdisFreeStack);

+#endif

+

+#endif

diff --git a/msdos/ndis_0.asm b/msdos/ndis_0.asm
new file mode 100644
index 0000000..2990985
--- /dev/null
+++ b/msdos/ndis_0.asm
@@ -0,0 +1,188 @@
+PAGE 60,132

+NAME NDIS_0

+

+ifdef DOSX

+  .386

+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'

+  _TEXT   ENDS

+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'

+  _DATA   ENDS

+  _TEXT32 SEGMENT PUBLIC BYTE  USE32 'CODE'

+  _TEXT32 ENDS

+  CB_DSEG EQU <CS>                          ; DOSX is tiny-model

+  D_SEG   EQU <_TEXT SEGMENT>

+  D_END   EQU <_TEXT ENDS>

+  ASSUME  CS:_TEXT,DS:_TEXT

+

+  PUSHREGS equ <pushad>

+  POPREGS  equ <popad>

+

+  PUBPROC macro name

+          align 4

+          public @&name

+          @&name label near

+          endm

+else

+  .286

+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'

+  _TEXT   ENDS

+  _DATA   SEGMENT PUBLIC DWORD 'DATA'

+  _DATA   ENDS

+  CB_DSEG EQU <SEG _DATA>                   ; 16bit is small/large model

+  D_SEG   EQU <_DATA SEGMENT>

+  D_END   EQU <_DATA ENDS>

+  ASSUME  CS:_TEXT,DS:_DATA

+

+  PUSHREGS equ <pusha>

+  POPREGS  equ <popa>

+

+  PUBPROC  macro name

+           public _&name

+           _&name label far

+           endm

+endif

+

+;-------------------------------------------

+

+D_SEG

+

+D_END

+

+

+_TEXT SEGMENT

+

+EXTRN _NdisSystemRequest      : near

+EXTRN _NdisRequestConfirm     : near

+EXTRN _NdisTransmitConfirm    : near

+EXTRN _NdisReceiveLookahead   : near

+EXTRN _NdisIndicationComplete : near

+EXTRN _NdisReceiveChain       : near

+EXTRN _NdisStatusProc         : near

+EXTRN _NdisAllocStack         : near

+EXTRN _NdisFreeStack          : near

+

+;

+; *ALL* interrupt threads come through this macro.

+;

+CALLBACK macro callbackProc, argsSize

+

+     pushf

+     PUSHREGS                ;; Save the registers

+

+     push es

+     push ds

+     mov  ax,CB_DSEG         ;; Load DS

+     mov  ds,ax

+     call _NdisAllocStack    ;; Get and install a stack.

+

+     mov  bx,ss              ;; Save off the old stack in other regs

+     mov  cx,sp

+     mov  ss,dx              ;; Install the new one

+     mov  sp,ax

+     push bx                 ;; Save the old one on to the new stack

+     push cx

+     sub  sp,&argsSize       ;; Allocate space for arguments on the stack

+

+     mov  ax,ss              ;; Set up the destination for the move

+     mov  es,ax

+     mov  di,sp

+     mov  ds,bx              ;; Set up the source for the move.

+     mov  si,cx

+     add  si,4+6+32

+

+     mov  cx,&argsSize       ;; Move the arguments to the stack.

+     shr  cx,1

+     cld

+     rep  movsw

+

+     mov  ax,CB_DSEG         ;; Set my data segment again.

+     mov  ds,ax

+

+     call &callbackProc      ;; Call the real callback.

+     pop  di                 ;; Pop off the old stack

+     pop  si

+     mov  bx,ss              ;; Save off the current allocated stack.

+     mov  cx,sp

+     mov  ss,si              ;; Restore the old stack

+     mov  sp,di

+     push ax                 ;; Save the return code

+     push bx                 ;; Free the stack. Push the pointer to it

+     push cx

+     call _NdisFreeStack

+     add  sp,4

+     pop  ax                 ;; Get the return code back

+     add  di,32              ;; Get a pointer to ax on the stack

+     mov  word ptr ss:[di],ax

+     pop  ds

+     pop  es

+

+     POPREGS

+     popf

+endm

+

+;

+; Define all of the callbacks for the NDIS procs.

+;

+

+PUBPROC systemRequestGlue

+CALLBACK _NdisSystemRequest,14

+RETF

+

+PUBPROC requestConfirmGlue

+CALLBACK _NdisRequestConfirm,12

+RETF

+

+PUBPROC transmitConfirmGlue

+CALLBACK _NdisTransmitConfirm,10

+RETF

+

+PUBPROC receiveLookaheadGlue

+CALLBACK _NdisReceiveLookahead,16

+RETF

+

+PUBPROC indicationCompleteGlue

+CALLBACK _NdisIndicationComplete,4

+RETF

+

+PUBPROC receiveChainGlue

+CALLBACK _NdisReceiveChain,16

+RETF

+

+PUBPROC statusGlue

+CALLBACK _NdisStatusProc,12

+RETF

+

+;

+; int FAR NdisGetLinkage (int handle, char *data, int size);

+;

+

+ifdef DOSX

+  PUBPROC NdisGetLinkage

+          push ebx

+          mov ebx, [esp+8]              ; device handle

+          mov eax, 4402h                ; IOCTRL read function

+          mov edx, [esp+12]             ; DS:EDX -> result data

+          mov ecx, [esp+16]             ; ECX = length

+          int 21h

+          pop ebx

+          jc  @fail

+          xor eax, eax

+  @fail:  ret

+

+else

+  PUBPROC NdisGetLinkage

+          enter 0, 0

+          mov bx, [bp+6]

+          mov ax, 4402h

+          mov dx, [bp+8]

+          mov cx, [bp+12]

+          int 21h

+          jc  @fail

+          xor ax, ax

+  @fail:  leave

+          retf

+endif

+

+ENDS

+

+END

diff --git a/msdos/pkt_rx0.asm b/msdos/pkt_rx0.asm
new file mode 100644
index 0000000..94f3d09
--- /dev/null
+++ b/msdos/pkt_rx0.asm
@@ -0,0 +1,197 @@
+PAGE 60,132

+NAME PKT_RX

+

+ifdef ??version        ; using TASM

+  masm

+  jumps

+endif

+

+PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp

+PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd

+

+;

+; these sizes MUST be equal to the sizes in PKTDRVR.H

+;

+

+RX_BUF_SIZE = 1500      ; max message size on Ethernet

+TX_BUF_SIZE = 1500

+

+ifdef DOSX

+ .386

+  NUM_RX_BUF = 32       ; # of RX element buffers

+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'

+  _TEXT   ENDS

+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'

+  _DATA   ENDS

+  D_SEG   EQU <_TEXT SEGMENT>

+  D_END   EQU <_TEXT ENDS>

+  ASSUME  CS:_TEXT,DS:_TEXT

+else

+ .286

+  NUM_RX_BUF = 10

+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'

+  _TEXT   ENDS

+  _DATA   SEGMENT PUBLIC DWORD 'DATA'

+  _DATA   ENDS

+  D_SEG   EQU <_DATA SEGMENT>

+  D_END   EQU <_DATA ENDS>

+  ASSUME  CS:_TEXT,DS:_DATA

+endif

+

+;-------------------------------------------

+

+D_SEG

+

+RX_ELEMENT     STRUC

+   firstCount  dw  0                          ; # of bytes on 1st call

+   secondCount dw  0                          ; # of bytes on 2nd call

+   handle      dw  0                          ; handle for upcall

+   destinAdr   db  6           dup (0)        ; packet destination address

+   sourceAdr   db  6           dup (0)        ; packet source address

+   protocol    dw  0                          ; packet protocol number

+   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer

+ENDS

+               align 4

+_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets

+_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf

+_pktDrop       dw  0,0                        ; packet drop counter

+_pktTemp       db  20                dup (0)  ; temp work area

+_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer

+_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures

+ LAST_OFS      = offset $

+

+ screenSeg     dw  0B800h

+ newInOffset   dw  0

+

+ fanChars      db  '-\|/'

+ fanIndex      dw  0

+

+D_END

+

+_TEXT SEGMENT

+

+

+SHOW_RX  MACRO

+         push es

+         push bx

+         mov bx, screenSeg

+         mov es, bx                    ;; r-mode segment of colour screen

+         mov di, 158                   ;; upper right corner - 1

+         mov bx, fanIndex

+         mov al, fanChars[bx]          ;; get write char

+         mov ah, 15                    ;;  and white colour

+         stosw                         ;; write to screen at ES:EDI

+         inc fanIndex                  ;; update next index

+         and fanIndex, 3

+         pop bx

+         pop es

+ENDM

+

+;------------------------------------------------------------------------

+;

+; This macro return ES:DI to tail of Rx queue

+

+ENQUEUE  MACRO

+         LOCAL @noWrap

+         mov ax, _rxInOfs              ;; DI = current in-offset

+         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer

+         cmp ax, LAST_OFS              ;; pointing past last ?

+         jb  @noWrap                   ;; no - jump

+         lea ax, _pktRxBuf             ;; yes, point to 1st buffer

+         align 4

+@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?

+         je  @dump                     ;; yes, queue is full

+         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input

+         mov newInOffset, ax           ;; remember new input offset

+

+   ;; NOTE. rxInOfs is updated after the packet has been copied

+   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver

+

+ENDM

+

+;------------------------------------------------------------------------

+;

+; This routine gets called by the packet driver twice:

+;   1st time (AX=0) it requests an address where to put the packet

+;

+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)

+;   BX has client handle (stored in RX_ELEMENT.handle).

+;   CX has # of bytes in packet on both call. They should be equal.

+;

+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount

+; and _pktRxBuf[n].secondCount, and CL on first call in

+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"

+; (PKTDRVR.C)

+;

+;---------------------------------------------------------------------

+

+_PktReceiver:

+         pushf

+         cli                         ; no distraction wanted !

+         push ds

+         push bx

+ifdef DOSX

+         mov bx, cs

+else

+         mov bx, SEG _DATA

+endif

+         mov ds, bx

+         mov es, bx                  ; ES = DS = CS or seg _DATA

+         pop bx                      ; restore handle

+

+         cmp ax, 0                   ; first call? (AX=0)

+         jne @post                   ; AX=1: second call, do post process

+

+ifdef DEBUG

+         SHOW_RX                     ; show that a packet is received

+endif

+         cmp cx, RX_BUF_SIZE+14      ; size OK ?

+         ja  @skip                   ; no, packet to large for us

+

+         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]

+

+         mov [di].firstCount, cx     ; remember the first count.

+         mov [di].handle, bx         ; remember the handle.

+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr

+         pop ds

+         popf

+         retf                        ; far return to driver with ES:DI

+

+         align 4

+@dump:   inc _pktDrop[0]             ; discard the packet on 1st call

+         adc _pktDrop[2], 0          ; increment packets lost

+

+@skip:   xor di, di                  ; return ES:DI = NIL pointer

+         xor ax, ax

+         mov es, ax

+         pop ds

+         popf

+         retf

+

+         align 4

+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr

+         jz @discard                 ; make sure we don't use NULL-pointer

+

+         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr

+       ;

+       ; push si

+       ; push [si].firstCount

+       ; call bpf_filter_match       ; run the filter here some day?

+       ; add sp, 4

+       ; cmp ax, 0

+       ; je  @discard

+

+         mov [si].secondCount, cx

+         mov ax, newInOffset

+         mov _rxInOfs, ax            ; update _pktRxBuf input offset

+

+         align 4

+@discard:pop ds

+         popf

+         retf

+

+_pktRxEnd  db 0                      ; marker for end of r-mode code/data

+

+_TEXT ENDS

+

+END

diff --git a/msdos/pkt_rx1.s b/msdos/pkt_rx1.s
new file mode 100644
index 0000000..b294a36
--- /dev/null
+++ b/msdos/pkt_rx1.s
@@ -0,0 +1,155 @@
+;

+; This file requires NASM 0.97+ to assemble

+;

+; Currently used only for djgpp + DOS4GW targets

+;

+; these sizes MUST be equal to the sizes in PKTDRVR.H

+;

+%define  ETH_MTU     1500                  ; max data size on Ethernet

+%define  ETH_MIN     60                    ; min/max total frame size

+%define  ETH_MAX     (ETH_MTU+2*6+2)

+%define  NUM_RX_BUF  32                    ; # of RX element buffers

+%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6

+%idefine offset

+

+struc RX_ELEMENT

+      .firstCount  resw 1                  ; # of bytes on 1st call

+      .secondCount resw 1                  ; # of bytes on 2nd call

+      .handle      resw 1                  ; handle for upcall

+    ; .timeStamp   resw 4                  ; 64-bit RDTSC value

+      .destinAdr   resb 6                  ; packet destination address

+      .sourceAdr   resb 6                  ; packet source address

+      .protocol    resw 1                  ; packet protocol number

+      .rxBuffer    resb ETH_MTU            ; RX buffer

+endstruc

+

+;-------------------------------------------

+

+[org 0]  ; assemble to .bin file

+

+_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets

+_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf

+_pktDrop    dw   0,0                       ; packet drop counter

+_pktTemp    resb 20                        ; temp work area

+_pktTxBuf   resb (ETH_MAX)                 ; TX buffer

+_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures

+ LAST_OFS   equ  $

+

+screenSeg   dw  0B800h

+newInOffset dw  0

+

+fanChars    db  '-\|/'

+fanIndex    dw  0

+

+%macro SHOW_RX 0

+       push es

+       push bx

+       mov bx, [screenSeg]

+       mov es, bx                    ;; r-mode segment of colour screen

+       mov di, 158                   ;; upper right corner - 1

+       mov bx, [fanIndex]

+       mov al, [fanChars+bx]         ;; get write char

+       mov ah, 15                    ;;  and white colour

+       cld                           ;; Needed?

+       stosw                         ;; write to screen at ES:EDI

+       inc word [fanIndex]           ;; update next index

+       and word [fanIndex], 3

+       pop bx

+       pop es

+%endmacro

+

+;PutTimeStamp

+;       rdtsc

+;       mov [si].timeStamp, eax

+;       mov [si+4].timeStamp, edx

+;       ret

+

+

+;------------------------------------------------------------------------

+;

+; This routine gets called by the packet driver twice:

+;   1st time (AX=0) it requests an address where to put the packet

+;

+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)

+;   BX has client handle (stored in RX_ELEMENT.handle).

+;   CX has # of bytes in packet on both call. They should be equal.

+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount

+; and _pktRxBuf[n].secondCount, and CL on first call in

+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"

+; (PKTDRVR.C)

+;

+;---------------------------------------------------------------------

+

+_PktReceiver:

+         pushf

+         cli                         ; no distraction wanted !

+         push ds

+         push bx

+         mov bx, cs

+         mov ds, bx

+         mov es, bx                  ; ES = DS = CS or seg _DATA

+         pop bx                      ; restore handle

+

+         cmp ax, 0                   ; first call? (AX=0)

+         jne @post                   ; AX=1: second call, do post process

+

+%ifdef DEBUG

+         SHOW_RX                     ; show that a packet is received

+%endif

+

+         cmp cx, ETH_MAX             ; size OK ?

+         ja  @skip                   ; no, too big

+

+         mov ax, [_rxInOfs]

+         add ax, RX_SIZE

+         cmp ax, LAST_OFS

+         jb  @noWrap

+         mov ax, offset _pktRxBuf

+@noWrap:

+         cmp ax, [_rxOutOfs]

+         je  @dump

+         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]

+         mov [newInOffset], ax

+

+         mov [di], cx                ; remember firstCount.

+         mov [di+4], bx              ; remember handle.

+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr

+         pop ds

+         popf

+         retf                        ; far return to driver with ES:DI

+

+@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call

+         adc word [_pktDrop+2], 0    ; increment packets lost

+

+@skip:   xor di, di                  ; return ES:DI = NIL pointer

+         xor ax, ax

+         mov es, ax

+         pop ds

+         popf

+         retf

+

+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr

+         jz @discard                 ; make sure we don't use NULL-pointer

+

+       ;

+       ; push si

+       ; call bpf_filter_match       ; run the filter here some day

+       ; pop si

+       ; cmp ax, 0

+       ; je  @discard

+

+         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount

+         mov ax, [newInOffset]

+         mov [_rxInOfs], ax          ; update _pktRxBuf input offset

+

+       ; call PutTimeStamp

+

+@discard:

+         pop ds

+         popf

+         retf

+

+_pktRxEnd  db 0                      ; marker for end of r-mode code/data

+

+END

+

diff --git a/msdos/pktdrvr.c b/msdos/pktdrvr.c
new file mode 100644
index 0000000..cd22ee6
--- /dev/null
+++ b/msdos/pktdrvr.c
@@ -0,0 +1,1436 @@
+/*

+ *  File.........: pktdrvr.c

+ *

+ *  Responsible..: Gisle Vanem,  giva@bgnett.no

+ *

+ *  Created......: 26.Sept 1995

+ *

+ *  Description..: Packet-driver interface for 16/32-bit C :

+ *                 Borland C/C++ 3.0+ small/large model

+ *                 Watcom C/C++ 11+, DOS4GW flat model

+ *                 Metaware HighC 3.1+ and PharLap 386|DosX

+ *                 GNU C/C++ 2.7+ and djgpp 2.x extender

+ *

+ *  References...: PC/TCP Packet driver Specification. rev 1.09

+ *                 FTP Software Inc.

+ *

+ */

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <dos.h>

+

+#include "pcap-dos.h"

+#include "pcap-int.h"

+#include "msdos/pktdrvr.h"

+

+#if (DOSX)

+#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */

+#else

+#define NUM_RX_BUF  10

+#endif

+

+#define DIM(x)   (sizeof((x)) / sizeof(x[0]))

+#define PUTS(s)  do {                                           \

+                   if (!pktInfo.quiet)                          \

+                      pktInfo.error ?                           \

+                        printf ("%s: %s\n", s, pktInfo.error) : \

+                        printf ("%s\n", pktInfo.error = s);     \

+                 } while (0)

+

+#if defined(__HIGHC__)

+  extern UINT _mwenv;

+

+#elif defined(__DJGPP__)

+  #include <stddef.h>

+  #include <dpmi.h>

+  #include <go32.h>

+  #include <pc.h>

+  #include <sys/farptr.h>

+

+#elif defined(__WATCOMC__)

+  #include <i86.h>

+  #include <stddef.h>

+  extern char _Extender;

+

+#else

+  extern void far PktReceiver (void);

+#endif

+

+

+#if (DOSX & (DJGPP|DOS4GW))

+  #include <sys/pack_on.h>

+

+  struct DPMI_regs {

+         DWORD  r_di;

+         DWORD  r_si;

+         DWORD  r_bp;

+         DWORD  reserved;

+         DWORD  r_bx;

+         DWORD  r_dx;

+         DWORD  r_cx;

+         DWORD  r_ax;

+         WORD   r_flags;

+         WORD   r_es, r_ds, r_fs, r_gs;

+         WORD   r_ip, r_cs, r_sp, r_ss;

+       };

+

+  /* Data located in a real-mode segment. This becomes far at runtime

+   */

+  typedef struct  {          /* must match data/code in pkt_rx1.s */

+          WORD       _rxOutOfs;

+          WORD       _rxInOfs;

+          DWORD      _pktDrop;

+          BYTE       _pktTemp [20];

+          TX_ELEMENT _pktTxBuf[1];

+          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];

+          WORD       _dummy[2];        /* screenSeg,newInOffset */

+          BYTE       _fanChars[4];

+          WORD       _fanIndex;

+          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */

+        } PktRealStub;

+  #include <sys/pack_off.h>

+

+  static BYTE real_stub_array [] = {

+         #include "pkt_stub.inc"       /* generated opcode array */

+       };

+

+  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)

+  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)

+  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])

+  #define pktDrop       offsetof (PktRealStub,_pktDrop)

+  #define pktTemp       offsetof (PktRealStub,_pktTemp)

+  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)

+  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])

+  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])

+

+#else

+  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */

+  extern WORD       rxInOfs;

+  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */

+  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */

+

+  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */

+  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */

+  extern char       pktTemp[20];                 /* PktDrvr temp area  */

+

+  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]

+  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]

+#endif

+

+

+#ifdef __BORLANDC__           /* Use Borland's inline functions */

+  #define memcpy  __memcpy__

+  #define memcmp  __memcmp__

+  #define memset  __memset__

+#endif

+

+

+#if (DOSX & PHARLAP)

+  extern void PktReceiver (void);     /* in pkt_rx0.asm */

+  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);

+

+  #undef  FP_SEG

+  #undef  FP_OFF

+  #define FP_OFF(x)     ((WORD)(x))

+  #define FP_SEG(x)     ((WORD)(realBase >> 16))

+  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))

+  #define r_ax          eax

+  #define r_bx          ebx

+  #define r_dx          edx

+  #define r_cx          ecx

+  #define r_si          esi

+  #define r_di          edi

+  #define r_ds          ds

+  #define r_es          es

+  LOCAL FARPTR          protBase;

+  LOCAL REALPTR         realBase;

+  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */

+  LOCAL SWI_REGS        reg;

+

+  static WORD _far *rxOutOfsFp, *rxInOfsFp;

+

+#elif (DOSX & DJGPP)

+  static _go32_dpmi_seginfo rm_mem;

+  static __dpmi_regs        reg;

+  static DWORD              realBase;

+  static int                para_skip = 0;

+

+  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))

+  #define r_ax              x.ax

+  #define r_bx              x.bx

+  #define r_dx              x.dx

+  #define r_cx              x.cx

+  #define r_si              x.si

+  #define r_di              x.di

+  #define r_ds              x.ds

+  #define r_es              x.es

+

+#elif (DOSX & DOS4GW)

+  LOCAL struct DPMI_regs    reg;

+  LOCAL WORD                rm_base_seg, rm_base_sel;

+  LOCAL DWORD               realBase;

+  LOCAL int                 para_skip = 0;

+

+  LOCAL DWORD dpmi_get_real_vector (int intr);

+  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);

+  LOCAL void  dpmi_real_free       (WORD selector);

+  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))

+

+#else              /* real-mode Borland etc. */

+  static struct  {

+         WORD r_ax, r_bx, r_cx, r_dx, r_bp;

+         WORD r_si, r_di, r_ds, r_es, r_flags;

+       } reg;

+#endif

+

+#ifdef __HIGHC__

+  #pragma Alias (pktDrop,    "_pktDrop")

+  #pragma Alias (pktRxBuf,   "_pktRxBuf")

+  #pragma Alias (pktTxBuf,   "_pktTxBuf")

+  #pragma Alias (pktTemp,    "_pktTemp")

+  #pragma Alias (rxOutOfs,   "_rxOutOfs")

+  #pragma Alias (rxInOfs,    "_rxInOfs")

+  #pragma Alias (pktRxEnd,   "_pktRxEnd")

+  #pragma Alias (PktReceiver,"_PktReceiver")

+#endif

+

+

+PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */

+PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */

+

+PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;

+PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };

+PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };

+

+LOCAL  struct {             /* internal statistics */

+       DWORD  tooSmall;     /* size < ETH_MIN */

+       DWORD  tooLarge;     /* size > ETH_MAX */

+       DWORD  badSync;      /* count_1 != count_2 */

+       DWORD  wrongHandle;  /* upcall to wrong handle */

+     } intStat;  

+

+/***************************************************************************/

+

+PUBLIC const char *PktGetErrorStr (int errNum)

+{

+  static const char *errStr[] = {

+                    "",

+                    "Invalid handle number",

+                    "No interfaces of specified class found",

+                    "No interfaces of specified type found",

+                    "No interfaces of specified number found",

+                    "Bad packet type specified",

+                    "Interface does not support multicast",

+                    "Packet driver cannot terminate",

+                    "Invalid receiver mode specified",

+                    "Insufficient memory space",

+                    "Type previously accessed, and not released",

+                    "Command out of range, or not implemented",

+                    "Cannot send packet (usually hardware error)",

+                    "Cannot change hardware address ( > 1 handle open)",

+                    "Hardware address has bad length or format",

+                    "Cannot reset interface (more than 1 handle open)",

+                    "Bad Check-sum",

+                    "Bad size",

+                    "Bad sync" ,

+                    "Source hit"

+                  };

+

+  if (errNum < 0 || errNum >= DIM(errStr))

+     return ("Unknown driver error.");

+  return (errStr [errNum]);

+}

+

+/**************************************************************************/

+

+PUBLIC const char *PktGetClassName (WORD class)

+{

+  switch (class)

+  { 

+    case PD_ETHER:

+         return ("DIX-Ether");

+    case PD_PRONET10:

+         return ("ProNET-10");

+    case PD_IEEE8025:

+         return ("IEEE 802.5");

+    case PD_OMNINET:

+         return ("OmniNet");

+    case PD_APPLETALK:

+         return ("AppleTalk");

+    case PD_SLIP:

+         return ("SLIP");

+    case PD_STARTLAN:

+         return ("StartLAN");

+    case PD_ARCNET:

+         return ("ArcNet");

+    case PD_AX25:

+         return ("AX.25");

+    case PD_KISS:

+         return ("KISS");

+    case PD_IEEE8023_2:

+         return ("IEEE 802.3 w/802.2 hdr");

+    case PD_FDDI8022:

+         return ("FDDI w/802.2 hdr");

+    case PD_X25:

+         return ("X.25");

+    case PD_LANstar:

+         return ("LANstar");

+    case PD_PPP:

+         return ("PPP");

+    default:

+         return ("unknown");

+  }

+}

+

+/**************************************************************************/

+

+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)

+{

+  static const char *modeStr [] = {

+                    "Receiver turned off",

+                    "Receive only directly addressed packets",

+                    "Receive direct & broadcast packets",

+                    "Receive direct,broadcast and limited multicast packets",

+                    "Receive direct,broadcast and all multicast packets",

+                    "Receive all packets (promiscuouos mode)"

+                  };

+

+  if (mode > DIM(modeStr))

+     return ("??");

+  return (modeStr [mode-1]);

+}

+

+/**************************************************************************/

+

+LOCAL __inline BOOL PktInterrupt (void)

+{

+  BOOL okay;

+

+#if (DOSX & PHARLAP)

+  _dx_real_int ((UINT)pktInfo.intr, &reg);

+  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */

+

+#elif (DOSX & DJGPP)

+  __dpmi_int ((int)pktInfo.intr, &reg);

+  okay = ((reg.x.flags & 1) == 0);

+

+#elif (DOSX & DOS4GW)

+  union  REGS  r;

+  struct SREGS s;

+

+  memset (&r, 0, sizeof(r));

+  segread (&s);

+  r.w.ax  = 0x300;

+  r.x.ebx = pktInfo.intr;

+  r.w.cx  = 0;

+  s.es    = FP_SEG (&reg);

+  r.x.edi = FP_OFF (&reg);

+  reg.r_flags = 0;

+  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */

+

+  int386x (0x31, &r, &r, &s);

+  okay = (!r.w.cflag);

+

+#else

+  reg.r_flags = 0;

+  intr (pktInfo.intr, (struct REGPACK*)&reg);

+  okay = ((reg.r_flags & 1) == 0);

+#endif

+

+  if (okay)

+       pktInfo.error = NULL;

+  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);

+  return (okay);

+}

+

+/**************************************************************************/

+

+/*

+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ

+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return

+ * interrupt number, else return zero in pktInfo.intr

+ */

+PUBLIC BOOL PktSearchDriver (void)

+{

+  BYTE intr  = 0x20;

+  BOOL found = FALSE;

+

+  while (!found && intr < 0xFF)

+  {

+    static char str[12];                 /* 3 + strlen("PKT DRVR") */

+    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */

+    DWORD  rp;                           /* in interrupt  routine  */

+

+#if (DOSX & PHARLAP)

+    _dx_rmiv_get (intr, &rp);

+    ReadRealMem (&str, (REALPTR)rp, sizeof(str));

+

+#elif (DOSX & DJGPP)

+    __dpmi_raddr realAdr;

+    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);

+    rp = (realAdr.segment << 4) + realAdr.offset16;

+    dosmemget (rp, sizeof(str), &str);

+

+#elif (DOSX & DOS4GW)

+    rp = dpmi_get_real_vector (intr);

+    memcpy (&str, (void*)rp, sizeof(str));

+

+#else

+    _fmemcpy (&str, getvect(intr), sizeof(str));

+#endif

+

+    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;

+    intr++;

+  }

+  pktInfo.intr = (found ? intr-1 : 0);

+  return (found);

+}

+

+

+/**************************************************************************/

+

+static BOOL PktSetAccess (void)

+{

+  reg.r_ax = 0x0200 + pktInfo.class;

+  reg.r_bx = 0xFFFF;

+  reg.r_dx = 0;

+  reg.r_cx = 0;

+

+#if (DOSX & PHARLAP)

+  reg.ds  = 0;

+  reg.esi = 0;

+  reg.es  = RP_SEG (realBase);

+  reg.edi = (WORD) &PktReceiver;

+

+#elif (DOSX & DJGPP)

+  reg.x.ds = 0;

+  reg.x.si = 0;

+  reg.x.es = rm_mem.rm_segment;

+  reg.x.di = PktReceiver;

+

+#elif (DOSX & DOS4GW)

+  reg.r_ds = 0;

+  reg.r_si = 0;

+  reg.r_es = rm_base_seg;

+  reg.r_di = PktReceiver;

+

+#else

+  reg.r_ds = 0;

+  reg.r_si = 0;

+  reg.r_es = FP_SEG (&PktReceiver);

+  reg.r_di = FP_OFF (&PktReceiver);

+#endif

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+  pktInfo.handle = reg.r_ax;

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktReleaseHandle (WORD handle)

+{

+  reg.r_ax = 0x0300;

+  reg.r_bx = handle;

+  return PktInterrupt();

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktTransmit (const void *eth, int len)

+{

+  if (len > ETH_MTU)

+     return (FALSE);

+

+  reg.r_ax = 0x0400;             /* Function 4, send pkt */

+  reg.r_cx = len;                /* total size of frame  */

+

+#if (DOSX & DJGPP)

+  dosmemput (eth, len, realBase+pktTxBuf);

+  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */

+  reg.x.si = pktTxBuf;           /* DOS offset to buffer */

+

+#elif (DOSX & DOS4GW)

+  memcpy ((void*)(realBase+pktTxBuf), eth, len);

+  reg.r_ds = rm_base_seg;

+  reg.r_si = pktTxBuf;

+

+#elif (DOSX & PHARLAP)

+  memcpy (&pktTxBuf, eth, len);

+  reg.r_ds = FP_SEG (&pktTxBuf);

+  reg.r_si = FP_OFF (&pktTxBuf);

+

+#else

+  reg.r_ds = FP_SEG (eth);

+  reg.r_si = FP_OFF (eth);

+#endif

+

+  return PktInterrupt();

+}

+

+/**************************************************************************/

+

+#if (DOSX & (DJGPP|DOS4GW))

+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)

+#else

+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)

+#endif

+{

+  WORD count_1, count_2;

+

+  /*

+   * We got an upcall to the same RMCB with wrong handle.

+   * This can happen if we failed to release handle at program exit

+   */

+  if (rx->handle != pktInfo.handle)

+  {

+    pktInfo.error = "Wrong handle";

+    intStat.wrongHandle++;

+    PktReleaseHandle (rx->handle);

+    return (FALSE);

+  }

+  count_1 = rx->firstCount;

+  count_2 = rx->secondCount;

+

+  if (count_1 != count_2)

+  {

+    pktInfo.error = "Bad sync";

+    intStat.badSync++;

+    return (FALSE);

+  }

+  if (count_1 > ETH_MAX)

+  {

+    pktInfo.error = "Large esize";

+    intStat.tooLarge++;

+    return (FALSE);

+  }

+#if 0

+  if (count_1 < ETH_MIN)

+  {

+    pktInfo.error = "Small esize";

+    intStat.tooSmall++;

+    return (FALSE);

+  }

+#endif

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktTerminHandle (WORD handle)

+{

+  reg.r_ax = 0x0500;

+  reg.r_bx = handle;

+  return PktInterrupt();

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktResetInterface (WORD handle)

+{

+  reg.r_ax = 0x0700;

+  reg.r_bx = handle;

+  return PktInterrupt();

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)

+{

+  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)

+     return (TRUE);

+

+  reg.r_ax = 0x1400;

+  reg.r_bx = pktInfo.handle;

+  reg.r_cx = (WORD)mode;

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+  receiveMode = mode;

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)

+{

+  reg.r_ax = 0x1500;

+  reg.r_bx = pktInfo.handle;

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+  *mode = reg.r_ax;

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+static PKT_STAT initialStat;         /* statistics at startup */

+static BOOL     resetStat = FALSE;   /* statistics reset ? */

+

+PUBLIC BOOL PktGetStatistics (WORD handle)

+{

+  reg.r_ax = 0x1800;

+  reg.r_bx = handle;

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+#if (DOSX & PHARLAP)

+  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));

+

+#elif (DOSX & DJGPP)

+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);

+

+#elif (DOSX & DOS4GW)

+  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));

+

+#else

+  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));

+#endif

+

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktSessStatistics (WORD handle)

+{

+  if (!PktGetStatistics(pktInfo.handle))

+     return (FALSE);

+

+  if (resetStat)

+  {

+    pktStat.inPackets  -= initialStat.inPackets;

+    pktStat.outPackets -= initialStat.outPackets;

+    pktStat.inBytes    -= initialStat.inBytes;

+    pktStat.outBytes   -= initialStat.outBytes;

+    pktStat.inErrors   -= initialStat.inErrors;

+    pktStat.outErrors  -= initialStat.outErrors;

+    pktStat.outErrors  -= initialStat.outErrors;

+    pktStat.lost       -= initialStat.lost;

+  }

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktResetStatistics (WORD handle)

+{

+  if (!PktGetStatistics(pktInfo.handle))

+     return (FALSE);

+

+  memcpy (&initialStat, &pktStat, sizeof(initialStat));

+  resetStat = TRUE;

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktGetAddress (ETHER *addr)

+{

+  reg.r_ax = 0x0600;

+  reg.r_bx = pktInfo.handle;

+  reg.r_cx = sizeof (*addr);

+

+#if (DOSX & DJGPP)

+  reg.x.es = rm_mem.rm_segment;

+  reg.x.di = pktTemp;

+#elif (DOSX & DOS4GW)

+  reg.r_es = rm_base_seg;

+  reg.r_di = pktTemp;

+#else

+  reg.r_es = FP_SEG (&pktTemp);

+  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */

+#endif

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+#if (DOSX & PHARLAP)

+  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));

+

+#elif (DOSX & DJGPP)

+  dosmemget (realBase+pktTemp, sizeof(*addr), addr);

+

+#elif (DOSX & DOS4GW)

+  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));

+

+#else

+  memcpy ((void*)addr, &pktTemp, sizeof(*addr));

+#endif

+

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktSetAddress (const ETHER *addr)

+{

+  /* copy addr to real-mode scrath area */

+

+#if (DOSX & PHARLAP)

+  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));

+

+#elif (DOSX & DJGPP)

+  dosmemput (addr, sizeof(*addr), realBase+pktTemp);

+

+#elif (DOSX & DOS4GW)

+  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));

+

+#else

+  memcpy (&pktTemp, (void*)addr, sizeof(*addr));

+#endif

+

+  reg.r_ax = 0x1900;

+  reg.r_cx = sizeof (*addr);      /* address length       */

+

+#if (DOSX & DJGPP)

+  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */

+  reg.x.di = pktTemp;             /* DOS segment to param */

+#elif (DOSX & DOS4GW)

+  reg.r_es = rm_base_seg;

+  reg.r_di = pktTemp;

+#else

+  reg.r_es = FP_SEG (&pktTemp);

+  reg.r_di = FP_OFF (&pktTemp);

+#endif

+

+  return PktInterrupt();

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktGetDriverInfo (void)

+{

+  pktInfo.majVer = 0;

+  pktInfo.minVer = 0;

+  memset (&pktInfo.name, 0, sizeof(pktInfo.name));

+  reg.r_ax = 0x01FF;

+  reg.r_bx = 0;

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+  pktInfo.number = reg.r_cx & 0xFF;

+  pktInfo.class  = reg.r_cx >> 8;

+#if 0

+  pktInfo.minVer = reg.r_bx % 10;

+  pktInfo.majVer = reg.r_bx / 10;

+#else

+  pktInfo.majVer = reg.r_bx;  // !!

+#endif

+  pktInfo.funcs  = reg.r_ax & 0xFF;

+  pktInfo.type   = reg.r_dx & 0xFF;

+

+#if (DOSX & PHARLAP)

+  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));

+

+#elif (DOSX & DJGPP)

+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);

+

+#elif (DOSX & DOS4GW)

+  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));

+

+#else

+  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));

+#endif

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktGetDriverParam (void)

+{

+  reg.r_ax = 0x0A00;

+

+  if (!PktInterrupt())

+     return (FALSE);

+

+#if (DOSX & PHARLAP)

+  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);

+

+#elif (DOSX & DJGPP)

+  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);

+

+#elif (DOSX & DOS4GW)

+  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);

+

+#else

+  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);

+#endif

+  return (TRUE);

+}

+

+/**************************************************************************/

+

+#if (DOSX & PHARLAP)

+  PUBLIC int PktReceive (BYTE *buf, int max)

+  {

+    WORD inOfs  = *rxInOfsFp;

+    WORD outOfs = *rxOutOfsFp;

+

+    if (outOfs != inOfs)

+    {

+      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);

+      int size, len = max;

+

+      if (CheckElement(head))

+      {

+        size = min (head->firstCount, sizeof(RX_ELEMENT));

+        len  = min (size, max);

+        _fmemcpy (buf, &head->destin, len);

+      }

+      else

+        size = -1;

+

+      outOfs += sizeof (RX_ELEMENT);

+      if (outOfs > LAST_RX_BUF)

+          outOfs = FIRST_RX_BUF;

+      *rxOutOfsFp = outOfs;

+      return (size);

+    }

+    return (0);

+  }

+

+  PUBLIC void PktQueueBusy (BOOL busy)

+  {

+    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;

+    if (*rxOutOfsFp > LAST_RX_BUF)

+        *rxOutOfsFp = FIRST_RX_BUF;

+    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;

+  }

+

+  PUBLIC WORD PktBuffersUsed (void)

+  {

+    WORD inOfs  = *rxInOfsFp;

+    WORD outOfs = *rxOutOfsFp;

+

+    if (inOfs >= outOfs)

+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

+  }

+

+  PUBLIC DWORD PktRxDropped (void)

+  {

+    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));

+  }

+

+#elif (DOSX & DJGPP)

+  PUBLIC int PktReceive (BYTE *buf, int max)

+  {

+    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);

+

+    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))

+    {

+      RX_ELEMENT head;

+      int  size, len = max;

+

+      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);

+      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);

+      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);

+

+      if (CheckElement(&head))

+      {

+        size = min (head.firstCount, sizeof(RX_ELEMENT));

+        len  = min (size, max);

+        dosmemget (realBase+ofs+6, len, buf);

+      }

+      else

+        size = -1;

+

+      ofs += sizeof (RX_ELEMENT);

+      if (ofs > LAST_RX_BUF)

+           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

+      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);

+      return (size);

+    }

+    return (0);

+  }

+

+  PUBLIC void PktQueueBusy (BOOL busy)

+  {

+    WORD ofs;

+

+    disable();

+    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);

+    if (busy)

+       ofs += sizeof (RX_ELEMENT);

+

+    if (ofs > LAST_RX_BUF)

+         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

+    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);

+    _farpokel (_dos_ds, realBase+pktDrop, 0UL);

+    enable();

+  }

+

+  PUBLIC WORD PktBuffersUsed (void)

+  {

+    WORD inOfs, outOfs;

+

+    disable();

+    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);

+    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);

+    enable();

+    if (inOfs >= outOfs)

+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

+  }

+

+  PUBLIC DWORD PktRxDropped (void)

+  {

+    return _farpeekl (_dos_ds, realBase+pktDrop);

+  }

+

+#elif (DOSX & DOS4GW)

+  PUBLIC int PktReceive (BYTE *buf, int max)

+  {

+    WORD ofs = *(WORD*) (realBase+rxOutOfs);

+

+    if (ofs != *(WORD*) (realBase+rxInOfs))

+    {

+      RX_ELEMENT head;

+      int  size, len = max;

+

+      head.firstCount  = *(WORD*) (realBase+ofs);

+      head.secondCount = *(WORD*) (realBase+ofs+2);

+      head.handle      = *(WORD*) (realBase+ofs+4);

+

+      if (CheckElement(&head))

+      {

+        size = min (head.firstCount, sizeof(RX_ELEMENT));

+        len  = min (size, max);

+        memcpy (buf, (const void*)(realBase+ofs+6), len);

+      }

+      else

+        size = -1;

+

+      ofs += sizeof (RX_ELEMENT);

+      if (ofs > LAST_RX_BUF)

+           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

+      else *(WORD*) (realBase+rxOutOfs) = ofs;

+      return (size);

+    }

+    return (0);

+  }

+

+  PUBLIC void PktQueueBusy (BOOL busy)

+  {

+    WORD ofs;

+

+    _disable();

+    ofs = *(WORD*) (realBase+rxInOfs);

+    if (busy)

+       ofs += sizeof (RX_ELEMENT);

+

+    if (ofs > LAST_RX_BUF)

+         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

+    else *(WORD*) (realBase+rxOutOfs) = ofs;

+    *(DWORD*) (realBase+pktDrop) = 0UL;

+    _enable();

+  }

+

+  PUBLIC WORD PktBuffersUsed (void)

+  {

+    WORD inOfs, outOfs;

+

+    _disable();

+    inOfs  = *(WORD*) (realBase+rxInOfs);

+    outOfs = *(WORD*) (realBase+rxOutOfs);

+    _enable();

+    if (inOfs >= outOfs)

+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

+  }

+

+  PUBLIC DWORD PktRxDropped (void)

+  {

+    return *(DWORD*) (realBase+pktDrop);

+  }

+

+#else     /* real-mode small/large model */

+

+  PUBLIC int PktReceive (BYTE *buf, int max)

+  {

+    if (rxOutOfs != rxInOfs)

+    {

+      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);

+      int  size, len = max;

+

+      if (CheckElement(head))

+      {

+        size = min (head->firstCount, sizeof(RX_ELEMENT));

+        len  = min (size, max);

+        _fmemcpy (buf, &head->destin, len);

+      }

+      else

+        size = -1;

+

+      rxOutOfs += sizeof (RX_ELEMENT);

+      if (rxOutOfs > LAST_RX_BUF)

+          rxOutOfs = FIRST_RX_BUF;

+      return (size);

+    }

+    return (0);

+  }

+

+  PUBLIC void PktQueueBusy (BOOL busy)

+  {

+    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;

+    if (rxOutOfs > LAST_RX_BUF)

+        rxOutOfs = FIRST_RX_BUF;

+    pktDrop = 0L;

+  }

+

+  PUBLIC WORD PktBuffersUsed (void)

+  {

+    WORD inOfs  = rxInOfs;

+    WORD outOfs = rxOutOfs;

+

+    if (inOfs >= outOfs)

+       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));

+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

+  }

+

+  PUBLIC DWORD PktRxDropped (void)

+  {

+    return (pktDrop);

+  }

+#endif

+

+/**************************************************************************/

+

+LOCAL __inline void PktFreeMem (void)

+{

+#if (DOSX & PHARLAP)

+  if (realSeg)

+  {

+    _dx_real_free (realSeg);

+    realSeg = 0;

+  }

+#elif (DOSX & DJGPP)

+  if (rm_mem.rm_segment)

+  {

+    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */

+

+    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)

+       _farpokel (_dos_ds, realBase + ofs, 0);

+    _go32_dpmi_free_dos_memory (&rm_mem);

+    rm_mem.rm_segment = 0;

+  }

+#elif (DOSX & DOS4GW)

+  if (rm_base_sel)

+  {

+    dpmi_real_free (rm_base_sel);

+    rm_base_sel = 0;

+  }

+#endif

+}

+

+/**************************************************************************/

+

+PUBLIC BOOL PktExitDriver (void)

+{           

+  if (pktInfo.handle)

+  {

+    if (!PktSetReceiverMode(PDRX_BROADCAST))

+       PUTS ("Error restoring receiver mode.");

+

+    if (!PktReleaseHandle(pktInfo.handle))

+       PUTS ("Error releasing PKT-DRVR handle.");

+

+    PktFreeMem();

+    pktInfo.handle = 0;

+  }

+

+  if (pcap_pkt_debug >= 1)

+     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "

+             "wrong-handle %lu\n",

+             intStat.tooSmall, intStat.tooLarge,

+             intStat.badSync, intStat.wrongHandle);

+  return (TRUE);

+}

+

+#if (DOSX & (DJGPP|DOS4GW))

+static void dump_pkt_stub (void)

+{

+  int i;

+

+  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",

+           PktReceiver);

+  for (i = 0; i < 15; i++)

+      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);

+  fputs ("\n", stderr);

+}

+#endif

+

+/*

+ * Front end initialization routine

+ */

+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)

+{

+  PKT_RX_MODE rxMode;

+  BOOL   writeInfo = (pcap_pkt_debug >= 3);

+

+  pktInfo.quiet = (pcap_pkt_debug < 3);

+

+#if (DOSX & PHARLAP) && defined(__HIGHC__)

+  if (_mwenv != 2)

+  {

+    fprintf (stderr, "Only Pharlap DOS extender supported.\n");

+    return (FALSE);

+  }

+#endif

+

+#if (DOSX & PHARLAP) && defined(__WATCOMC__)

+  if (_Extender != 1)

+  {

+    fprintf (stderr, "Only DOS4GW style extenders supported.\n");

+    return (FALSE);

+  }

+#endif

+

+  if (!PktSearchDriver())

+  {

+    PUTS ("Packet driver not found.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+  if (!PktGetDriverInfo())

+  {

+    PUTS ("Error getting pkt-drvr information.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+#if (DOSX & PHARLAP)

+  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,

+               &realBase, &protBase, (USHORT*)&realSeg))

+  {

+    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);

+    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);

+    *rxOutOfsFp = FIRST_RX_BUF;

+    *rxInOfsFp  = FIRST_RX_BUF;

+  }

+  else

+  {

+    PUTS ("Cannot allocate real-mode stub.");

+    return (FALSE);

+  }

+

+#elif (DOSX & (DJGPP|DOS4GW))

+  if (sizeof(real_stub_array) > 0xFFFF)

+  {

+    fprintf (stderr, "`real_stub_array[]' too big.\n");

+    return (FALSE);

+  }

+#if (DOSX & DJGPP)

+  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;

+

+  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)

+  {

+    PUTS ("real-mode init failed.");

+    return (FALSE);

+  }

+  realBase = (rm_mem.rm_segment << 4);

+  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);

+  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

+  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);

+

+#elif (DOSX & DOS4GW)

+  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);

+  if (!rm_base_seg)

+  {

+    PUTS ("real-mode init failed.");

+    return (FALSE);

+  }

+  realBase = (rm_base_seg << 4);

+  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));

+  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

+  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;

+

+#endif

+  {

+    int pushf = PktReceiver;

+

+    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */

+           real_stub_array[pushf]   != 0xFA)      /* cli   */

+    {

+      if (++para_skip > 16)

+      {

+        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");

+        para_skip = 0;

+        dump_pkt_stub();

+        return (FALSE);

+      }

+    }

+    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)

+    {

+      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");

+      return (FALSE);

+    }

+  }

+

+  if (pcap_pkt_debug > 2)

+      dump_pkt_stub();

+

+#else

+  rxOutOfs = FIRST_RX_BUF;

+  rxInOfs  = FIRST_RX_BUF;

+#endif

+

+  if (!PktSetAccess())

+  {

+    PUTS ("Error setting pkt-drvr access.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+  if (!PktGetAddress(&myAddress))

+  {

+    PUTS ("Error fetching adapter address.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+  if (!PktSetReceiverMode(mode))

+  {

+    PUTS ("Error setting receiver mode.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+  if (!PktGetReceiverMode(&rxMode))

+  {

+    PUTS ("Error getting receiver mode.");

+    PktFreeMem();

+    return (FALSE);

+  }

+

+  if (writeInfo)

+     printf ("Pkt-driver information:\n"

+             "  Version  : %d.%d\n"

+             "  Name     : %.15s\n"

+             "  Class    : %u (%s)\n"

+             "  Type     : %u\n"

+             "  Number   : %u\n"

+             "  Funcs    : %u\n"

+             "  Intr     : %Xh\n"

+             "  Handle   : %u\n"

+             "  Extended : %s\n"

+             "  Hi-perf  : %s\n"

+             "  RX mode  : %s\n"

+             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",

+

+             pktInfo.majVer, pktInfo.minVer, pktInfo.name,

+             pktInfo.class,  PktGetClassName(pktInfo.class),

+             pktInfo.type,   pktInfo.number,

+             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,

+             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",

+             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",

+             PktRXmodeStr(rxMode),

+             myAddress[0], myAddress[1], myAddress[2],

+             myAddress[3], myAddress[4], myAddress[5]);

+

+#if defined(DEBUG) && (DOSX & PHARLAP)

+  if (writeInfo)

+  {

+    DWORD    rAdr = realBase + (WORD)&PktReceiver;

+    unsigned sel, ofs;

+

+    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));

+    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));

+

+    sel = _FP_SEG (protBase);

+    ofs = _FP_OFF (protBase);

+    printf ("Protbase    = %04X:%08X\n", sel,ofs);

+    printf ("RealSeg     = %04X\n", realSeg);

+

+    sel = _FP_SEG (rxOutOfsFp);

+    ofs = _FP_OFF (rxOutOfsFp);

+    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);

+

+    sel = _FP_SEG (rxInOfsFp);

+    ofs = _FP_OFF (rxInOfsFp);

+    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);

+

+    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",

+            *rxOutOfsFp, *rxInOfsFp);

+

+    PktQueueBusy (TRUE);

+    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",

+            *rxOutOfsFp, *rxInOfsFp);

+  }

+#endif

+

+  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */

+  PktQueueBusy (TRUE);

+  return (TRUE);

+}

+

+

+/*

+ * DPMI functions only for Watcom + DOS4GW extenders

+ */

+#if (DOSX & DOS4GW)

+LOCAL DWORD dpmi_get_real_vector (int intr)

+{

+  union REGS r;

+

+  r.x.eax = 0x200;

+  r.x.ebx = (DWORD) intr;

+  int386 (0x31, &r, &r);

+  return ((r.w.cx << 4) + r.w.dx);

+}

+

+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)

+{

+  union REGS r;

+

+  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */

+  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */

+  int386 (0x31, &r, &r);

+  if (r.w.cflag & 1)

+     return (0);

+

+  *selector = r.w.dx;

+  return (r.w.ax);              /* Return segment address */

+}

+

+LOCAL void dpmi_real_free (WORD selector)

+{

+  union REGS r;

+

+  r.x.eax = 0x101;              /* DPMI free DOS memory */

+  r.x.ebx = selector;           /* Selector to free */

+  int386 (0x31, &r, &r);

+}

+#endif

+

+

+#if defined(DOSX) && (DOSX & PHARLAP)

+/*

+ * Description:

+ *     This routine allocates conventional memory for the specified block

+ *     of code (which must be within the first 64K of the protected mode

+ *     program segment) and copies the code to it.

+ *

+ *     The caller should free up the conventional memory block when it

+ *     is done with the conventional memory.

+ *

+ *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.

+ *

+ * Calling arguments:

+ *     start_offs      start of real mode code in program segment

+ *     end_offs        1 byte past end of real mode code in program segment

+ *     real_basep      returned;  real mode ptr to use as a base for the

+ *                        real mode code (eg, to get the real mode FAR

+ *                        addr of a function foo(), take

+ *                        real_basep + (ULONG) foo).

+ *                        This pointer is constructed such that

+ *                        offsets within the real mode segment are

+ *                        the same as the link-time offsets in the

+ *                        protected mode program segment

+ *     prot_basep      returned;  prot mode ptr to use as a base for getting

+ *                        to the conventional memory, also constructed

+ *                        so that adding the prot mode offset of a

+ *                        function or variable to the base gets you a

+ *                        ptr to the function or variable in the

+ *                        conventional memory block.

+ *     rmem_adrp       returned;  real mode para addr of allocated

+ *                        conventional memory block, to be used to free

+ *                        up the conventional memory when done.  DO NOT

+ *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE

+ *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT

+ *                        CORRECTLY.

+ *

+ * Returned values:

+ *     0      if error

+ *     1      if success

+ */

+int RealCopy (ULONG    start_offs,

+              ULONG    end_offs,

+              REALPTR *real_basep,

+              FARPTR  *prot_basep,

+              USHORT  *rmem_adrp)

+{

+  ULONG   rm_base;    /* base real mode para addr for accessing */

+                      /* allocated conventional memory          */

+  UCHAR  *source;     /* source pointer for copy                */

+  FARPTR  destin;     /* destination pointer for copy           */

+  ULONG   len;        /* number of bytes to copy                */

+  ULONG   temp;

+  USHORT  stemp;

+

+  /* First check for valid inputs

+   */

+  if (start_offs >= end_offs || end_offs > 0x10000)

+     return (FALSE);

+

+  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up

+   * the real mode pointer easily. Round up end_offs to make sure we allocate

+   * enough paragraphs

+   */

+  start_offs &= ~15;

+  end_offs = (15 + (end_offs << 4)) >> 4;

+

+  /* Allocate the conventional memory for our real mode code.  Remember to

+   * round byte count UP to 16-byte paragraph size.  We alloc it

+   * above the DOS data buffer so both the DOS data buffer and the appl

+   * conventional mem block can still be resized.

+   *

+   * First just try to alloc it;  if we can't get it, shrink the appl mem

+   * block down to the minimum, try to alloc the memory again, then grow the

+   * appl mem block back to the maximum.  (Don't try to shrink the DOS data

+   * buffer to free conventional memory;  it wouldn't be good for this routine

+   * to have the possible side effect of making file I/O run slower.)

+   */

+  len = ((end_offs - start_offs) + 15) >> 4;

+  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)

+  {

+    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)

+       return (FALSE);

+

+    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)

+       *rmem_adrp = 0;

+

+    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)

+    {

+      if (*rmem_adrp != 0)

+         _dx_real_free (*rmem_adrp);

+      return (FALSE);

+    }

+

+    if (*rmem_adrp == 0)

+       return (FALSE);

+  }

+

+  /* Construct real mode & protected mode pointers to access the allocated

+   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)

+   * boundary, because we rounded it down.

+   *

+   * We make the offsets come out rights by backing off the real mode selector

+   * by start_offs.

+   */

+  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);

+  RP_SET (*real_basep, 0, rm_base);

+  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);

+

+  /* Copy the real mode code/data to the allocated memory

+   */

+  source = (UCHAR *) start_offs;

+  destin = *prot_basep;

+  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));

+  len = end_offs - start_offs;

+  WriteFarMem (destin, source, len);

+

+  return (TRUE);

+}

+#endif /* DOSX && (DOSX & PHARLAP) */

diff --git a/msdos/pktdrvr.h b/msdos/pktdrvr.h
new file mode 100644
index 0000000..08898ae
--- /dev/null
+++ b/msdos/pktdrvr.h
@@ -0,0 +1,153 @@
+#ifndef __PKTDRVR_H

+#define __PKTDRVR_H

+

+#define PUBLIC

+#define LOCAL        static

+

+#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */

+#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */

+

+#ifdef __HIGHC__

+#pragma Off(Align_members)

+#else

+#pragma pack(1)

+#endif

+

+typedef enum  {                /* Packet-driver classes */

+        PD_ETHER      = 1,

+        PD_PRONET10   = 2,

+        PD_IEEE8025   = 3,

+        PD_OMNINET    = 4,

+        PD_APPLETALK  = 5,

+        PD_SLIP       = 6,

+        PD_STARTLAN   = 7,

+        PD_ARCNET     = 8,

+        PD_AX25       = 9,

+        PD_KISS       = 10,

+        PD_IEEE8023_2 = 11,

+        PD_FDDI8022   = 12,

+        PD_X25        = 13,

+        PD_LANstar    = 14,

+        PD_PPP        = 18

+      } PKT_CLASS;

+

+typedef enum  {             /* Packet-driver receive modes    */

+        PDRX_OFF    = 1,    /* turn off receiver              */

+        PDRX_DIRECT,        /* receive only to this interface */

+        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */

+        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */

+        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */

+        PDRX_ALL_PACKETS,   /* receive all packets on network */

+      } PKT_RX_MODE;

+

+typedef struct {

+        char type[8];

+        char len;

+      } PKT_FRAME;

+

+

+typedef struct {

+        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */

+        BYTE  number;       /* = 0 for single LAN adapter        */

+        WORD  type;         /* = 13 for 3C523                    */

+        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */

+        WORD  intr;         /* user interrupt vector number      */

+        WORD  handle;       /* Handle associated with session    */

+        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/

+        BOOL  quiet;        /* (don't) print errors to stdout    */

+        const char *error;  /* address of error string           */

+        BYTE  majVer;       /* Major driver implementation ver.  */

+        BYTE  minVer;       /* Minor driver implementation ver.  */

+        BYTE  dummyLen;     /* length of following data          */

+        WORD  MAClength;    /* HiPerformance data, N/A           */

+        WORD  MTU;          /* HiPerformance data, N/A           */

+        WORD  multicast;    /* HiPerformance data, N/A           */

+        WORD  rcvrBuffers;  /* valid for                         */

+        WORD  UMTbufs;      /*   High Performance drivers only   */

+        WORD  postEOIintr;  /*                  Usage ??         */

+      } PKT_INFO;

+

+#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */

+

+

+typedef struct {

+        DWORD inPackets;          /* # of packets received    */

+        DWORD outPackets;         /* # of packets transmitted */

+        DWORD inBytes;            /* # of bytes received      */

+        DWORD outBytes;           /* # of bytes transmitted   */

+        DWORD inErrors;           /* # of reception errors    */

+        DWORD outErrors;          /* # of transmission errors */

+        DWORD lost;               /* # of packets lost (RX)   */

+      } PKT_STAT;

+                   

+

+typedef struct {

+        ETHER destin;

+        ETHER source;

+        WORD  proto;

+        BYTE  data [TX_BUF_SIZE];

+      } TX_ELEMENT;

+

+typedef struct {

+        WORD  firstCount;         /* # of bytes on 1st         */

+        WORD  secondCount;        /* and 2nd upcall            */

+        WORD  handle;             /* instance that upcalled    */

+        ETHER destin;             /* E-net destination address */

+        ETHER source;             /* E-net source address      */

+        WORD  proto;              /* protocol number           */

+        BYTE  data [RX_BUF_SIZE];

+      } RX_ELEMENT;

+

+

+#ifdef __HIGHC__

+#pragma pop(Align_members)

+#else

+#pragma pack()

+#endif

+

+

+/*

+ * Prototypes for publics

+ */

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+extern PKT_STAT    pktStat;     /* statistics for packets */

+extern PKT_INFO    pktInfo;     /* packet-driver information */

+

+extern PKT_RX_MODE receiveMode;

+extern ETHER       myAddress, ethBroadcast;

+

+extern BOOL  PktInitDriver (PKT_RX_MODE mode);

+extern BOOL  PktExitDriver (void);

+

+extern const char *PktGetErrorStr    (int errNum);

+extern const char *PktGetClassName   (WORD class);

+extern const char *PktRXmodeStr      (PKT_RX_MODE mode);

+extern BOOL        PktSearchDriver   (void);

+extern int         PktReceive        (BYTE *buf, int max);

+extern BOOL        PktTransmit       (const void *eth, int len);

+extern DWORD       PktRxDropped      (void);

+extern BOOL        PktReleaseHandle  (WORD handle);

+extern BOOL        PktTerminHandle   (WORD handle);

+extern BOOL        PktResetInterface (WORD handle);

+extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);

+extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);

+extern BOOL        PktGetStatistics  (WORD handle);

+extern BOOL        PktSessStatistics (WORD handle);

+extern BOOL        PktResetStatistics(WORD handle);

+extern BOOL        PktGetAddress     (ETHER *addr);

+extern BOOL        PktSetAddress     (const ETHER *addr);

+extern BOOL        PktGetDriverInfo  (void);

+extern BOOL        PktGetDriverParam (void);

+extern void        PktQueueBusy      (BOOL busy);

+extern WORD        PktBuffersUsed    (void);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif /* __PKTDRVR_H */

+

diff --git a/msdos/readme.dos b/msdos/readme.dos
new file mode 100644
index 0000000..02ef1f7
--- /dev/null
+++ b/msdos/readme.dos
@@ -0,0 +1,162 @@
+@(#) $Header: /tcpdump/master/libpcap/msdos/readme.dos,v 1.3 2004-12-19 19:47:01 guy Exp $ (LBL)
+
+libpcap for DOS
+---------------
+
+This file contains some notes on building and using libpcap for MS-DOS.
+Look in `README' and `pcap.man' for usage and details. These targets are
+supported:
+
+ - Borland C 4.0+ small or large model.
+ - Metaware HighC 3.1+ with PharLap DOS-extender
+ - GNU C 2.7+ with djgpp 2.01+ DOS extender
+ - Watcom C 11.x with DOS4GW extender
+
+Note: the files in the libpcap.zip contains short trucated filenames.
+  So for djgpp to work with these, disable the use of long file names by
+  setting "LFN=n" in the environment.
+
+Files specific to DOS are pcap-dos.[ch] and the assembly and C files in
+the MSDOS sub-directory. Remember to built lipcap libraries from the top
+install directory. And not from the MSDOS sub-directory.
+
+Note for djgpp users:
+  If you got the libpcap from the official site www.tcpdump, then that
+  distribution does NOT contain any sources for building 32-bit drivers.
+  Instead get the full version at
+     http://www.bgnett.no/~giva/pcap/libpcap.zip
+
+  and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
+
+
+
+Requirements
+------------
+
+DOS-libpcap currently only works reliably with a real-mode Ethernet packet-
+driver. This driver must be installed prior to using any program (e.g.
+tcpdump) compiled with libpcap. Work is underway to implement protected-
+mode drivers for 32-bit targets (djgpp only). The 3Com 3c509 driver is
+working almost perfectly. Due to lack of LAN-cards, I've not had the
+opportunity to test other drivers. These 32-bit drivers are modified
+Linux drivers.
+
+
+Required packages
+-----------------
+
+The following packages and tools must be present for all targets.
+
+1. Watt-32 tcp/ip library. This library is *not* used to send or
+   receive network data. It's mostly used to access the 'hosts'
+   file and other <netdb.h> features. Get 'watt32s*.zip' at:
+
+     http://www.bgnett.no/~giva/
+
+2. Exception handler and disassember library (libexc.a) is needed if
+   "USE_EXCEPT = 1" in common.dj. Available at:
+
+     http://www.bgnett.no/~giva/misc/exc_dx07.zip
+
+3. Flex & Bison is used to generate parser for the filter handler
+   pcap_compile:
+
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/flx254b.zip
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsn128b.zip
+
+4. NASM assembler v 0.98 or later is required when building djgpp and
+   Watcom targets:
+
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/nasm098p.zip
+
+5. sed (Stream Editor) is required for doing `make depend'.
+   It's available at
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed*.zip
+
+   A touch tool to update the time-stamp of a file. E.g.
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/grep*.zip
+
+6. For djgpp rm.exe and cp.exe are required. These should already be
+   part of your djgpp installation. Also required (experimental at the
+   time) for djgpp is DLX 2.91 or later. This tool is for the generation
+   of dynamically loadable modules.
+
+
+Compiling libpcap
+-----------------
+
+Follow these steps in building libpcap:
+
+1. Make sure you've installed Watt-32 properly (see it's `INSTALL' file).
+   During that installation a environment variable `WATT_ROOT' is set.
+   This variable is used for building libpcap also (`WATT_INC' is
+   deducted from `WATT_ROOT'). djgpp users should also define environment
+   variables `C_INCLUDE_PATH' and `LIBRARY_PATH' to point to the include
+   directory and library directory respectively.  E.g. put this in your
+   AUTOEXEC.BAT:
+     set C_INCLUDE_PATH=c:/net/watt/inc
+     set LIBRARY_PATH=c:/net/watt/lib
+
+2. Revise the msdos/common.dj file for your djgpp/gcc installation;
+   - change the value of `GCCLIB' to match location of libgcc.a.
+   - set `USE_32BIT_DRIVERS = 1' to build 32-bit driver objects.
+
+
+3. Build pcap by using appropriate makefile. For djgpp, use:
+     `make -f msdos/makefile.dj'  (i.e. GNU `make')
+
+   For a Watcom target say:
+     `wmake -f msdos\makefile.wc'
+
+   For a Borland target say:
+     `maker -f msdos\Makefile pcap_bc.lib'  (Borland's `maker.exe')
+
+   And for a HighC/Pharlap target say:
+     `maker -f msdos\Makefile pcap_hc.lib'  (Borland's `maker.exe')
+
+   You might like to change some `CFLAGS' -- only `DEBUG' define currently
+   have any effect. It shows a rotating "fan" in upper right corner of
+   screen.  Remove `DEBUG' if you don't like it. You could add
+   `-fomit-frame-pointer' to `CFLAGS' to speed up the generated code.
+   But note, this makes debugging and crash-traceback difficult. Only
+   add it if you're fully confident your application is 100% stable.
+
+   Note: Code in `USE_NDIS2' does not work at the moment.
+
+4. The resulting libraries are put in current directory. There's no
+   test-program for `libpcap'. Linking the library with `tcpdump' is
+   the ultimate test anyway.
+
+
+
+Extensions to libpcap
+---------------------
+
+I've included some extra functions to DOS-libpcap:
+
+  `pcap_config_hook (const char *name, const char *value)' 
+
+    Allows an application to set values of internal libpcap variables.
+    `name' is typically a left-side keyword with an associated `value'
+    that is called from application's configure process (see tcpdump's
+    config.c file). libpcap keeps a set of tables that are searched for
+    a name/value match. Currently only used to set debug-levels and
+    parameters for the 32-bit network drivers.
+
+  `pcap_set_wait (pcap_t *, void (*)(void), int)' :
+
+    Only effective when reading offline traffic from dump-files.
+    Function `pcap_offline_read()' will wait (and optionally yield)
+    before printing next packet. This will simulate the pace the packets
+    where actually recorded.
+
+
+
+Happy sniffing !
+
+
+Gisle Vanem <giva@bgnett.no>
+            <gvanem@broadpark.no>
+
+October 1999, 2004
+