861 lines
24 KiB
C
861 lines
24 KiB
C
/*
|
|
* 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 */
|
|
|