| /* |
| * 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 */ |
| |