2132 lines
60 KiB
C
2132 lines
60 KiB
C
/*++
|
||
|
||
Copyright (c) 1991-1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
servencb.c
|
||
|
||
Abstract:
|
||
|
||
Routines to service completed NCB's. This file contains the following
|
||
functions:
|
||
|
||
MsgCallNetBios
|
||
MsgDeleteName
|
||
MsgGetMachineName
|
||
MsgHangupService
|
||
MsgListenService
|
||
Msgmblockbeg
|
||
Msgmblockend
|
||
Msgmblocktxt
|
||
MsgNetBiosError
|
||
MsgRecBcastService
|
||
MsgReceiveService
|
||
MsgRestart
|
||
Msgsblockmes
|
||
MsgSendAck
|
||
MsgSendService
|
||
MsgServeNCBs
|
||
MsgSesFullService
|
||
MsgStartListen
|
||
MsgStartRecBcast
|
||
MsgVerifySmb
|
||
|
||
Author:
|
||
|
||
Dan Lafferty (danl) 15-Jul-1991
|
||
|
||
Environment:
|
||
|
||
User Mode -Win32
|
||
|
||
Revision History:
|
||
|
||
19-Aug-1997 wlees
|
||
Add PNP support for lana's
|
||
|
||
27-Jul-1994 danl
|
||
MsgServeNCBs: This function now returns FALSE when the service
|
||
is to shut down.
|
||
|
||
29-May-1992 danl
|
||
MsgListenService: reset the NRC_NORES error count when a good
|
||
return code accompanies the Listen completion.
|
||
|
||
18-Feb-1992 ritaw
|
||
Convert to Win32 service control APIs.
|
||
|
||
15-Jul-1991 danl
|
||
Ported from LM2.0
|
||
|
||
--*/
|
||
|
||
//
|
||
// SMB translation
|
||
//
|
||
//
|
||
// OLD NEW
|
||
// SMB SMB_HEADER or PSMB_HEADER
|
||
// -------- -------------------------
|
||
// smb_idf Protocol
|
||
// smb_com Command
|
||
// smb_rcls ErrorClass
|
||
// smb_reh Reserved
|
||
// smb_err Error
|
||
// smb_flg Flags
|
||
// smb_flag2 Flags2
|
||
// smb_res Reserved2
|
||
// smb_gid Tid
|
||
// smb_tid Pid
|
||
// smb_pid Uid
|
||
// smb_uid Mid
|
||
// smb_mid Kludge
|
||
|
||
//
|
||
// Includes
|
||
//
|
||
|
||
#include "msrv.h"
|
||
|
||
#include <tstring.h> // Unicode string macros
|
||
#include <string.h> // memcpy
|
||
#include <netdebug.h> // NetpAssert
|
||
#include <lmerrlog.h> // NELOG_ messages
|
||
|
||
#include <netlib.h> // UNUSED macro
|
||
#include <smbtypes.h> // needed for smb.h
|
||
#include <smb.h> // Server Message Block definitions
|
||
#include <smbgtpt.h> // SMB field manipulation macros
|
||
//#include <msgrutil.h> // NetpNetBiosReset
|
||
#include <nb30.h> // NRC_GOODRET, ASYNC
|
||
|
||
#include "msgdbg.h" // MSG_LOG
|
||
#include "heap.h"
|
||
#include "msgdata.h"
|
||
#include "apiutil.h" // MsgMapNetError
|
||
|
||
|
||
#define MAX_RETRIES 10
|
||
|
||
//
|
||
// Local Functions
|
||
//
|
||
|
||
STATIC NET_API_STATUS
|
||
MsgCallNetBios(
|
||
DWORD net,
|
||
PNCB ncb,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgDeleteName(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgGetMachineName(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgHangupService(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
CHAR retval
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgListenService(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
CHAR retval
|
||
);
|
||
|
||
STATIC VOID
|
||
Msgmblockbeg(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
Msgmblockend(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
Msgmblocktxt(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC DWORD
|
||
MsgNetBiosError(
|
||
DWORD net,
|
||
PNCB ncb,
|
||
char retval,
|
||
DWORD ncbi
|
||
);
|
||
|
||
|
||
STATIC VOID
|
||
MsgReceiveService(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
char retval
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgRestart(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
Msgsblockmes(
|
||
DWORD net,
|
||
DWORD ncbi
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgSendAck(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
UCHAR smbrclass,
|
||
USHORT smbrcode
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgSendService(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
CHAR retval
|
||
);
|
||
|
||
STATIC VOID
|
||
MsgSesFullService(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
char retval
|
||
);
|
||
|
||
|
||
STATIC int
|
||
MsgVerifySmb(
|
||
DWORD net,
|
||
DWORD ncbi,
|
||
UCHAR func,
|
||
int parms,
|
||
char *buffers
|
||
);
|
||
|
||
|
||
#if DBG
|
||
|
||
VOID
|
||
MsgDumpNcb(
|
||
IN PNCB pNcb
|
||
);
|
||
|
||
#endif //DBG
|
||
|
||
|
||
/*
|
||
* MsgCallNetBios - issue a net bios call
|
||
*
|
||
* This function issues a net bios call and calls the
|
||
* error handler if that call results in an error.
|
||
*
|
||
* MsgCallNetBios (net, ncb, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncb - pointer to a Network Control Block
|
||
* ncbi - index of ncb in ncb array
|
||
*
|
||
* RETURN
|
||
* state of the Messenger: Either RUNNING or STOPPING.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls NetBios() to actually issue the net bios call.
|
||
* Calls MsgNetBiosError() if there is an error.
|
||
*/
|
||
|
||
STATIC NET_API_STATUS
|
||
MsgCallNetBios(
|
||
DWORD net, // Which network?
|
||
PNCB ncb, // Pointer to Network Control Block
|
||
DWORD ncbi
|
||
)
|
||
{
|
||
int retval;
|
||
PNCB_DATA pNcbData;
|
||
|
||
retval = Msgsendncb(ncb, net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
if (retval == NRC_GOODRET) {
|
||
|
||
//
|
||
// Clear err on success
|
||
//
|
||
pNcbData->Status.last_immediate = 0;
|
||
pNcbData->Status.this_immediate = 0;
|
||
}
|
||
else {
|
||
//
|
||
// NEW (11-4-91):
|
||
// --------------
|
||
// It is ok to get a Session Closed error if the state is STOP.
|
||
//
|
||
if ( (pNcbData->State == MESSTOP) &&
|
||
(retval == NRC_SCLOSED) ) {
|
||
|
||
MSG_LOG(TRACE,"CallNetBios: At end of msg, Session is closed for NET %d\n",
|
||
net);
|
||
pNcbData->Status.last_immediate = 0;
|
||
pNcbData->Status.this_immediate = 0;
|
||
}
|
||
else {
|
||
//
|
||
// Else mark error
|
||
//
|
||
pNcbData->Status.this_immediate = retval;
|
||
//
|
||
// Call the error handler if err
|
||
//
|
||
MSG_LOG(TRACE,"CallNetBios: net bios call failed 0x%x\n",retval);
|
||
MsgNetBiosError(net,ncb,(char)retval,ncbi);
|
||
return(MsgMapNetError((UCHAR)retval));
|
||
}
|
||
//
|
||
// Make sure the event for this thread is in the signaled state
|
||
// so that we can wake up and properly handle the error.
|
||
//
|
||
if (SetEvent(ncb->ncb_event) != TRUE) {
|
||
MSG_LOG(ERROR,"CallNetBios: SetEvent Failed\n",0);
|
||
}
|
||
}
|
||
return(NERR_Success);
|
||
}
|
||
|
||
/*
|
||
* MsgDeleteName - Delete a name from the Message Server's name table
|
||
*
|
||
* This function is called when a LISTEN, a RECEIVE BROADCAST DATAGRAM,
|
||
* or a RECEIVE ANY completes with the error code specifying that the
|
||
* name in question has been deleted. This function marks the appropriate
|
||
* entry in the flag table in the shared data area and sets the NCB_CPLT
|
||
* field of the appropriate NCB to 0xFF (so that FindCompletedNCB() will
|
||
* never find it).
|
||
*
|
||
* MsgDeleteName (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Modifies an NCB and the shared data area.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgDeleteName(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Network Control Block index
|
||
)
|
||
{
|
||
NCB ncb;
|
||
PNCB pNcb;
|
||
NET_API_STATUS status;
|
||
|
||
MSG_LOG(TRACE,"In MsgDeleteName %d\n",net);
|
||
|
||
if( SD_NAMEFLAGS(net,ncbi) & NFMACHNAME) {
|
||
//
|
||
// Name is the machine name. It may have been removed from the
|
||
// card by a board reset, so try to re-add it.
|
||
//
|
||
// NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
|
||
//
|
||
// First reset the adapter
|
||
//
|
||
MSG_LOG1(TRACE,"Calling NetBiosReset for lana #%d\n",GETNETLANANUM(net));
|
||
status = MsgsvcGlobalData->NetBiosReset(GETNETLANANUM(net));
|
||
|
||
if (status != NERR_Success) {
|
||
MSG_LOG(ERROR,"MsgDeleteName: NetBiosReset failed %d\n",
|
||
status);
|
||
MSG_LOG(ERROR,"MsgDeleteName: AdapterNum %d\n",net);
|
||
//
|
||
// I'm not sure what to do if this fails.
|
||
//
|
||
}
|
||
//
|
||
//
|
||
// NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
|
||
|
||
memcpy((char far *) ncb.ncb_name, SD_NAMES(net,ncbi),NCBNAMSZ);
|
||
ncb.ncb_command = NCBADDNAME; // Add name (wait)
|
||
ncb.ncb_lana_num = GETNETLANANUM(net); // Use the LANMAN adapter
|
||
Msgsendncb( &ncb, net);
|
||
MsgStartListen(net,ncbi);
|
||
}
|
||
else {
|
||
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"MsgDeleteName"); // Wait for write access
|
||
SD_NAMEFLAGS(net,ncbi) = NFDEL; // Name is deleted
|
||
MsgDatabaseLock(MSG_RELEASE,"MsgDeleteName"); // Free lock on share table
|
||
pNcb = GETNCB(net,ncbi);
|
||
pNcb->ncb_cmd_cplt = 0xff; // Simulate command in progress
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgGetMachineName - process a Get Machine Name Server Message Block
|
||
*
|
||
* This function sends to the caller the local machine name in
|
||
* response to a Get Machine Name Server Message Block.
|
||
*
|
||
* MsgGetMachineName (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - Network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* Globals used as input:
|
||
*
|
||
* machineName - Unicode version of the machine name.
|
||
*
|
||
* machineNameLen - The number of unicode characters in the machine
|
||
* name.
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* MsgGetMachineName() is called by MsgReceiveService (RecAnyService()).
|
||
* After verifying that the request is valid, this function builds
|
||
* an SMB containing the local machine name and sends it back to the
|
||
* caller.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgVerifySmb() and MsgCallNetBios(). Sets MsgSendService() to be the
|
||
* next service routine to be executed for the ncbi'th NCB.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgGetMachineName(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
LPBYTE buffer; // Pointer to SMB buffer
|
||
LPBYTE cp; // Save pointer
|
||
PSHORT bufLen; // Pointer to buffer length field in SMB;
|
||
|
||
NTSTATUS ntStatus;
|
||
OEM_STRING ansiString;
|
||
UNICODE_STRING unicodeString;
|
||
|
||
MSG_LOG(TRACE,"In MsgGetMachineName %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
|
||
if(pNcbData->State != MESSTART) {
|
||
//
|
||
// If wrong time for this block
|
||
//
|
||
// Hang up and start a new listen,
|
||
// log an error if mpncbistate[net][ncbi] == MESCONT;
|
||
// otherwise, do not log the error.
|
||
//
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// Log error if message in progress
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
//
|
||
// HANGUP and LISTEN again
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
return;
|
||
}
|
||
|
||
pNcbData->State = MESSTOP; // End of message state
|
||
|
||
//
|
||
// Check if SMB is malformed
|
||
//
|
||
if(MsgVerifySmb(net,ncbi,SMB_COM_GET_MACHINE_NAME,0,"") != 0) {
|
||
return;
|
||
}
|
||
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
cp = &buffer[sizeof(SMB_HEADER)]; // Skip to end of header
|
||
*cp++ = '\0'; // Return no parameters
|
||
|
||
//
|
||
// Length of name plus two
|
||
//
|
||
bufLen = (PSHORT)&cp[0];
|
||
*bufLen = MachineNameLen + (SHORT)2;
|
||
|
||
cp += sizeof(MachineNameLen); // Skip over buffer length field
|
||
|
||
*cp++ = '\004'; // Null-terminated string next
|
||
|
||
#ifdef UNICODE
|
||
//
|
||
// Translate the machineName from Unicode to Ansi and place it into
|
||
// the buffer at the temp pointer location.
|
||
//
|
||
unicodeString.Length = (USHORT)(STRLEN(machineName)*sizeof(WCHAR));
|
||
unicodeString.MaximumLength = (USHORT)((STRLEN(machineName)+1) * sizeof(WCHAR));
|
||
unicodeString.Buffer = machineName;
|
||
|
||
ansiString.Length = MachineNameLen;
|
||
ansiString.MaximumLength = *bufLen;
|
||
ansiString.Buffer = cp;
|
||
|
||
ntStatus = RtlUnicodeStringToOemString(
|
||
&ansiString,
|
||
&unicodeString,
|
||
FALSE); // Don't Allocate the ansiString Buffer
|
||
|
||
if (!NT_SUCCESS(ntStatus)) {
|
||
MSG_LOG(ERROR,
|
||
"MsgGetMachineName:RtlUnicodeStringToOemString Failed rc=%X\n",
|
||
ntStatus);
|
||
return; // They return for other errors, so I will here too.
|
||
}
|
||
|
||
*(cp + ansiString.Length) = '\0';
|
||
|
||
#else
|
||
UNUSED(unicodeString);
|
||
UNUSED(ansiString);
|
||
UNUSED(ntStatus);
|
||
strcpy( cp, (LPSTR)machineName); // Copy machine name
|
||
#endif
|
||
|
||
cp += MachineNameLen + 1; // Skip over machine name
|
||
|
||
//
|
||
// Set length of buffer
|
||
//
|
||
ncb->ncb_length = (USHORT)(cp - buffer);
|
||
|
||
ncb->ncb_command = NCBSEND | ASYNCH; // Send (no wait)
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgSendService; // Set function pointer
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
}
|
||
|
||
/*
|
||
* MsgHangupService - Service completed HANGUP net bios calls
|
||
*
|
||
* This function is invoked by NCBService() to process completed
|
||
* HANGUP net bios calls. In response to a completed HANGUP,
|
||
* this function issues a new LISTEN net bios call.
|
||
*
|
||
* MsgHangupService (net, ncbi, retval)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
* retval - value returned from net bios call
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgStartListen() to issue a new LISTEN net bios call. Calls
|
||
* MsgNetBiosError() on errors it does not know how to deal with.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgHangupService(
|
||
DWORD net, // Which network
|
||
DWORD ncbi, // Index of completed NCB
|
||
CHAR retval // HANGUP return value
|
||
)
|
||
{
|
||
PNCB pNcb;
|
||
MSG_LOG(TRACE,"In MsgHangupService %d\n",net);
|
||
|
||
switch(retval) { // Switch on return value
|
||
case NRC_GOODRET: // Success
|
||
case NRC_CMDTMO: // Command timed out
|
||
case NRC_SCLOSED: // Session closed
|
||
case NRC_SABORT: // Session ended abnormally
|
||
|
||
//
|
||
// BBSP - check if the name for this NCB ends in 0x3. If so,
|
||
// add the 0x5 version and don't reissue the listen on the 0x03.
|
||
// No need to worry about doing it on all nets, since on a machine
|
||
// with more than one the 0x05 name will never leave home, and
|
||
// the 0x03 version will never get a message.
|
||
//
|
||
|
||
MSG_LOG(TRACE," MsgHangupService: Issue a new LISTEN\n",0);
|
||
MsgStartListen(net,ncbi); // Issue a new LISTEN net bios call
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// Invoke error handler
|
||
//
|
||
MSG_LOG(TRACE," MsgHangupService: Unknown return value %x\n",retval);
|
||
pNcb = GETNCB(net,ncbi);
|
||
MsgNetBiosError(net,pNcb,retval,ncbi);
|
||
|
||
//
|
||
// BBSP - check if the name for this NCB ends in 0x3. If so,
|
||
// add the 0x5 version and don't reissue the listen on the 0x03.
|
||
// See note above.
|
||
//
|
||
|
||
MSG_LOG(TRACE," MsgHangupService: Issue a new LISTEN\n",0);
|
||
MsgStartListen(net,ncbi); // Issue a new LISTEN net bios call
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgListenService - service completed LISTEN net bios calls
|
||
*
|
||
* This function is called when a LISTEN net bios call completes
|
||
* either due to an error or due to the establishment of a
|
||
* session. In the latter case, it initiates message reception.
|
||
*
|
||
* MsgListenService (net, ncbi, retval)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
* retval - value returned from NCB call
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* If a session is established, this function issues a RECEIVE ANY
|
||
* net bios call to initiate reception of a message. If the function
|
||
* is invoked because the net bios call has failed due to the deletion
|
||
* of a name from the local network adapter's name table, then this
|
||
* function calls the routine responsible for deleting names from the
|
||
* Message Server's data area. This is the mechanism by which the
|
||
* NETNAME command notofies the Message Server of a deletion.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgCallNetBios() to issue a RECEIVE ANY net bios call. Calls
|
||
* MsgDeleteName() if it is informed of the deletion of a name. Calls
|
||
* MsgNetBiosError() on errors it does not know how to deal with. Sets
|
||
* mpncbifun[ncbi] according to the net bios call it issues.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgListenService(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi, // Index of completed NCB
|
||
CHAR retval // LISTEN return value
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to completed NCB
|
||
PNCB_DATA pNcbData; // Corresponding NCB data
|
||
|
||
static DWORD SaveCount = 0;
|
||
|
||
|
||
MSG_LOG(TRACE,"In MsgListenService %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to completed NCB
|
||
|
||
switch(retval) {
|
||
case NRC_GOODRET:
|
||
//
|
||
// Success
|
||
//
|
||
|
||
//
|
||
// Reset the No Resources error count if a good return code comes
|
||
// in for this name.
|
||
//
|
||
|
||
SaveCount = 0;
|
||
|
||
pNcbData->State = MESSTART; // Message start state
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgReceiveService;
|
||
//
|
||
// Set function pointer
|
||
//
|
||
ncb->ncb_command = NCBRECV | ASYNCH;
|
||
|
||
//
|
||
// Receive any (no wait)
|
||
//
|
||
ncb->ncb_length = BUFLEN; // Reset length of buffer
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
break;
|
||
|
||
case NRC_LOCTFUL:
|
||
//
|
||
// Session Table Full
|
||
// Log error in system error log file
|
||
//
|
||
MSG_LOG(TRACE,"[%d]MsgListenService: Session Table is full\n",net);
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgSesFullService; // Set function pointer
|
||
ncb->ncb_command = NCBDELNAME | ASYNCH; // Delete name (no wait)
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
break;
|
||
|
||
case NRC_NOWILD: // Name not found
|
||
// Name not found
|
||
// Name deleted between end of one session and start of next
|
||
|
||
case NRC_NAMERR:
|
||
//
|
||
// Name was deleted
|
||
//
|
||
MSG_LOG(TRACE,"[%d]MsgListenService: Name was deleted for some reason\n",net);
|
||
MsgDeleteName(net,ncbi); // Handle the deletion
|
||
break;
|
||
|
||
case NRC_NORES:
|
||
|
||
//
|
||
// We need to cover the case where we are adding a new name and
|
||
// starting a new listen. In this case, the thread that is adding
|
||
// the names will hangup and delete the name.
|
||
//
|
||
// So here we will sleep for a moment and then check to see if the
|
||
// name is still there. If not we just return without setting
|
||
// up to handle the NCB anymore. If the name is still there, then
|
||
// we travel down the default path and try again.
|
||
//
|
||
|
||
MSG_LOG(TRACE,"[%d]No Net Resources. SLEEP FOR A WHILE\n",net);
|
||
Sleep(1000);
|
||
MSG_LOG(TRACE,"[%d]No Net Resources. WAKEUP\n",net);
|
||
|
||
if (pNcbData->NameFlags == NFDEL)
|
||
{
|
||
MSG_LOG(TRACE,"[%d]MsgListenService: No Net Resources & Name Deleted\n",net);
|
||
ncb->ncb_cmd_cplt = 0xff;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If a session goes away and we can't gain the resources for
|
||
// it again, then we will attempt to re-connect MAX_RETRIES
|
||
// times. If we still cannot connect, then the name will be
|
||
// deleted.
|
||
//
|
||
// Don't deal with retries per net/ncbi -- if we've had
|
||
// "out of resources" failures MAX_RETRIES times, odds are
|
||
// the situation's not getting better even if we sleep/retry
|
||
// for each individual net/ncbi combo.
|
||
//
|
||
|
||
if (SaveCount >= MAX_RETRIES)
|
||
{
|
||
//
|
||
// Delete the Name
|
||
//
|
||
|
||
MSG_LOG(ERROR,
|
||
"Out of Resources, Deleting %s\n",
|
||
SD_NAMES(net,ncbi));
|
||
|
||
MsgDeleteName(net,ncbi);
|
||
|
||
//
|
||
// Mark this as 0xff now to avoid another callback call the
|
||
// next time this net/ncbi combo is hit in the loop (since that
|
||
// call will simply set this value.
|
||
//
|
||
|
||
ncb->ncb_cmd_cplt = 0xff;
|
||
|
||
//
|
||
// Don't roll SaveCount back to zero until we have an NCB
|
||
// completed with NRC_GOODRET in the future. This lets us
|
||
// avoid rewaiting MAX_RETRIES times for every net/ncbi
|
||
// combo as long as we keep getting NRC_NORES.
|
||
//
|
||
}
|
||
else
|
||
{
|
||
SaveCount++;
|
||
|
||
MSG_LOG(TRACE,
|
||
"MsgListenService: new SaveCount = %d\n",
|
||
SaveCount);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case NRC_BRIDGE:
|
||
//
|
||
// Lana number no longer valid (network interface went away)
|
||
//
|
||
MSG_LOG(TRACE,"[%d] lana has become invalid\n", net);
|
||
MsgNetBiosError(net, ncb, retval, ncbi);
|
||
|
||
//
|
||
// Indicate lana is now invalid
|
||
//
|
||
GETNETLANANUM(net) = 0xff;
|
||
|
||
//
|
||
// Mark current operation as deleted
|
||
//
|
||
ncb->ncb_cmd_cplt = 0xff;
|
||
ncb->ncb_retcode = 0;
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// Other failure
|
||
//
|
||
MSG_LOG(TRACE,"MsgListenService: Unrecognized retval %x\n",retval);
|
||
|
||
MsgNetBiosError(net,ncb,retval,ncbi);
|
||
|
||
// The listen error has been logged. Now as much as possible to
|
||
// get another listen staterd. This involves performing
|
||
// a HangUp for this name (which should fail but might help
|
||
// to clear out the err) and then re-issuing the listen. If the
|
||
// same error occurs SHUTDOWN_THRESHOLD consecutive times then
|
||
// MsgNetBiosError will shut down the message server.
|
||
//
|
||
|
||
MsgRestart(net,ncbi); // Attempt to restart the Listen
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Msgmblockbeg - process the header of a multi-block message
|
||
*
|
||
* This function acknowledges receipt of the header of a multi-block
|
||
* message and initiates logging of that message.
|
||
*
|
||
* Msgmblockbeg (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function is called from ReceivePost() (RecAnyPost()).
|
||
* It first check to see if it is appropriate for the ncbi'th
|
||
* name to have received a begin-multi-block-message SMB at the
|
||
* current time. It verifies the correctness of the SMB in the
|
||
* ncbi'th buffer. It initiates logging of the multi-block message,
|
||
* and it sends an acknowledgement to the sender of the message.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgRestart() to terminate the session if the SMB has arrived
|
||
* at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
|
||
* Calls logmbb() to begin logging. Calls MsgSendAck() to send an
|
||
* acknowledgement to the sender of the message.
|
||
*/
|
||
|
||
STATIC VOID
|
||
Msgmblockbeg(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
LPBYTE buffer; // Pointer to SMB buffer
|
||
LPSTR cp; // Save pointer
|
||
LPSTR from; // From-name
|
||
LPSTR to; // To-name
|
||
|
||
MSG_LOG(TRACE,"In Msgmblockbeg %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
if(pNcbData->State != MESSTART) { // If wrong time for this block
|
||
|
||
//
|
||
// Hang up and start a new listen,
|
||
// log an error if mpncbistate[net][ncbi] == MESCONT;
|
||
// otherwise, do not log the error.
|
||
//
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// Log error if message in progress
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
|
||
//
|
||
// HANGUP and LISTEN again
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
return;
|
||
}
|
||
pNcbData->State = MESCONT; // Processing multi-block message
|
||
if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_START_MB_MESSAGE,0,"ss") != 0) {
|
||
//
|
||
// Check for malformed SMB
|
||
//
|
||
return;
|
||
}
|
||
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
from = &buffer[sizeof(SMB_HEADER) + 4]; // Save pointer to from-name
|
||
to = &from[strlen(from) + 2]; // Save pointer to to-name
|
||
|
||
if(Msglogmbb(from,to,net,ncbi)) { // If attempt to log header fails
|
||
pNcbData->State = MESERR; // Enter error state
|
||
//
|
||
// Send negative acknowledgement
|
||
//
|
||
MsgSendAck(net,ncbi,'\002',SMB_ERR_NO_ROOM);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Indicate message received
|
||
//
|
||
SmbPutUshort(&(((PSMB_HEADER)buffer)->Error), (USHORT)SMB_ERR_SUCCESS);
|
||
|
||
// ((PSMB_HEADER)buffer)->Error = (USHORT)SMB_ERR_SUCCESS;
|
||
|
||
cp = &buffer[sizeof(SMB_HEADER)]; // Point just past header
|
||
*cp++ = '\001'; // One parameter
|
||
((short UNALIGNED far *) cp)[0] = ++mgid; // Message group ID
|
||
pNcbData->mgid = mgid; // Save message group i.d.
|
||
((short UNALIGNED far *) cp)[1] = 0; // No buffer
|
||
ncb->ncb_length = sizeof(SMB_HEADER) + 5; // Set length of buffer
|
||
ncb->ncb_command = NCBSEND | ASYNCH; // Send(no wait)
|
||
|
||
//
|
||
// Set function pointer & issue the net bios call
|
||
//
|
||
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgSendService;
|
||
|
||
MsgCallNetBios(net,ncb,ncbi);
|
||
}
|
||
|
||
/*
|
||
* Msgmblockend - process end of a multi-block message
|
||
*
|
||
* This function acknowledges receipt of the end of a
|
||
* multi-block message and terminates logging of the message.
|
||
*
|
||
* Msgmblockend (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function is called from ReceivePost() (RecAnyPost()).
|
||
* It first check to see if it is appropriate for the ncbi'th
|
||
* name to have received an end-multi-block-message SMB at the
|
||
* current time. It verifies the correctness of the SMB in the
|
||
* ncbi'th buffer. It terminates logging, and it sends an
|
||
* acknowledgement to the sender of the message.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgRestart() to terminate the session if the SMB has arrived
|
||
* at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
|
||
* Calls logmbe() to terminate logging. Calls MsgSendAck() to send an
|
||
* acknowledgement to the sender of the message.
|
||
*/
|
||
|
||
STATIC VOID
|
||
Msgmblockend(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
LPBYTE buffer; // Pointer to SMB buffer
|
||
int error; // Error flag
|
||
char smbrclass; // SMB return class
|
||
unsigned short smbrcode; // SMB return code
|
||
|
||
MSG_LOG(TRACE,"In Msgmblockend %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
if(pNcbData->State != MESCONT) { // If wrong time for this block
|
||
//
|
||
// Hang up and start a new listen,
|
||
// no error to log since no message in progress.
|
||
// HANGUP and LISTEN again
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
return;
|
||
}
|
||
pNcbData->State = MESSTOP; // End of message state
|
||
if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_END_MB_MESSAGE,1,"") != 0) {
|
||
//
|
||
// If SMB is malformed, log error and return
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
return;
|
||
}
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
|
||
if(*((short UNALIGNED far *) &buffer[sizeof(SMB_HEADER) + 1]) != pNcbData->mgid) {
|
||
|
||
//
|
||
// If i.d. does not match
|
||
//
|
||
error = 1; // Error found
|
||
smbrclass = '\002'; // Error return
|
||
smbrcode = SMB_ERR_ERROR; // Non-specific error
|
||
}
|
||
else {
|
||
//
|
||
// Else if message group i.d. okay
|
||
//
|
||
error = 0; // No error found
|
||
smbrclass = '\0'; // Good return
|
||
smbrcode = (USHORT)SMB_ERR_SUCCESS; // Message received
|
||
}
|
||
MsgSendAck(net,ncbi,smbrclass,smbrcode); // Send acknowledgement
|
||
if(!error) Msglogmbe(MESSTOP,net,ncbi); // Log end of message
|
||
}
|
||
|
||
/*
|
||
* Msgmblocktxt - process text of a multi-block message
|
||
*
|
||
* This function acknowledges receipt of a block of text of a
|
||
* multi-block message and logs that block.
|
||
*
|
||
* Msgmblocktxt (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - Network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function is called from ReceivePost() (RecAnyPost()).
|
||
* It first check to see if it is appropriate for the ncbi'th
|
||
* name to have received a multi-block-message-text SMB at the
|
||
* current time. It verifies the correctness of the SMB in the
|
||
* ncbi'th buffer. It logs the text block, and it sends an
|
||
* acknowledgement to the sender of the message.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgRestart() to terminate the session if the SMB has arrived
|
||
* at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
|
||
* Calls logmbt() to log the text block. Calls MsgSendAck() to send an
|
||
* acknowledgement to the sender of the message.
|
||
*/
|
||
|
||
STATIC VOID
|
||
Msgmblocktxt(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
LPBYTE buffer; // Pointer to SMB buffer
|
||
LPSTR cp; // Save pointer
|
||
char smbrclass; // SMB return class
|
||
unsigned short smbrcode; // SMB return code
|
||
|
||
MSG_LOG(TRACE,"In Msgmblocktxt %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
if(pNcbData->State != MESCONT) { // If wrong time for this block
|
||
//
|
||
// HANGUP and start a new LISTEN.
|
||
// no error to log since no message in progress.
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
return;
|
||
}
|
||
if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_TEXT_MB_MESSAGE,1,"b") != 0) {
|
||
//
|
||
// If SMB is malformed
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi); // Log error
|
||
return;
|
||
}
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
cp = &buffer[sizeof(SMB_HEADER) + 1]; // Skip to message group i.d.
|
||
|
||
if(*((short UNALIGNED far *) cp) != pNcbData->mgid) {
|
||
//
|
||
// If i.d. does not match
|
||
//
|
||
smbrclass = '\002'; // Error return
|
||
smbrcode = SMB_ERR_ERROR; // Non-specific error
|
||
}
|
||
else if(Msglogmbt(&buffer[sizeof(SMB_HEADER) + 6], net, ncbi)) {
|
||
//
|
||
// Else if text cannot be logged
|
||
//
|
||
pNcbData->State = MESERR; // Enter error state
|
||
smbrclass = '\002'; // Error return
|
||
smbrcode = SMB_ERR_NO_ROOM; // No room in buffer
|
||
}
|
||
else {
|
||
//
|
||
// Else if message logged okay
|
||
//
|
||
smbrclass = '\0'; // Good return
|
||
smbrcode = (USHORT)SMB_ERR_SUCCESS; // Message received
|
||
}
|
||
|
||
MsgSendAck(net,ncbi,smbrclass,smbrcode); // Send acknowledgement
|
||
}
|
||
|
||
/*
|
||
* MsgNetBiosError - process an error returned by a net bios call
|
||
*
|
||
* This function performs generic error handling for
|
||
* failed net bios calls. If the error is a fatal one because the error
|
||
* counted exceeded the SHUTDOWN_THRESHOLD, this routine begins a forced
|
||
* shutdown of the messenger. This shutdown will not complete until all
|
||
* threads have woken up and returned to the main loop where the
|
||
* messenger status is examined.
|
||
*
|
||
* MsgNetBiosError (net, ncb, retval, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - Network index
|
||
* ncb - Network Control Block pointer
|
||
* retval - value returned from the net bios call
|
||
* ncbi - ncb array index of ncb which resulted in this error
|
||
*
|
||
* RETURN
|
||
* state of the Messenger: Either RUNNING or STOPPING.
|
||
*
|
||
* Chcks in ncbStatus array that this is not a repeated error
|
||
* that has already been entered in the error log, and logs
|
||
* the error.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgErrorLogWrite() to log errors in the Network System Error Log.
|
||
* If this is a new error, the error status in the ncbStatus array for this
|
||
* ncb is updated so that the same error will not be reported if it is
|
||
* repeated.
|
||
*/
|
||
|
||
STATIC DWORD
|
||
MsgNetBiosError(
|
||
DWORD net, // Which network?
|
||
PNCB ncb, // Pointer to NCB
|
||
char retval, // Error code
|
||
DWORD ncbi // Index of array causing the error
|
||
)
|
||
{
|
||
PNCB_DATA pNcbData;
|
||
//
|
||
// First check the immediate status for this ncb. If it is in error
|
||
// then this must be the error, else it is a final error code.
|
||
//
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
if (pNcbData->Status.this_immediate != 0) {
|
||
|
||
if(pNcbData->Status.this_immediate ==
|
||
pNcbData->Status.last_immediate) {
|
||
|
||
if (++(pNcbData->Status.rep_count) >= SHUTDOWN_THRESHOLD) {
|
||
|
||
//
|
||
// The same error has occured SHUTDOWN_THRESHOLD times in
|
||
// a row. Write to the event log and shutdown the messenger.
|
||
//
|
||
|
||
MsgErrorLogWrite(
|
||
NELOG_Msg_Shutdown,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE) ncb,
|
||
sizeof(NCB),
|
||
NULL,
|
||
0);
|
||
|
||
MSG_LOG(ERROR,"MsgNetBiosError1:repeated MsgNetBiosError(ncb error) - shutting down\n",0);
|
||
return(MsgBeginForcedShutdown(
|
||
PENDING,
|
||
NERR_InternalError));
|
||
}
|
||
return(RUNNING); // Same as last error so don't report it
|
||
}
|
||
else {
|
||
//
|
||
// This error was not the same as the last error. So just
|
||
// update the last error place holder.
|
||
//
|
||
pNcbData->Status.last_immediate =
|
||
pNcbData->Status.this_immediate;
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// Must have been a final ret code (ncb completion code) that was
|
||
// in error.
|
||
//
|
||
if(pNcbData->Status.this_final == pNcbData->Status.last_final) {
|
||
|
||
if (++(pNcbData->Status.rep_count) >= SHUTDOWN_THRESHOLD) {
|
||
|
||
MsgErrorLogWrite(
|
||
NELOG_Msg_Shutdown,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE) ncb,
|
||
sizeof(NCB),
|
||
NULL,
|
||
0);
|
||
|
||
MSG_LOG(ERROR,"MsgNetBiosError2:repeated MsgNetBiosError (final ret code) - shutting down\n",0);
|
||
return(MsgBeginForcedShutdown(
|
||
PENDING,
|
||
NERR_InternalError));
|
||
}
|
||
return(RUNNING); // Same as last error so don't report it
|
||
}
|
||
else {
|
||
pNcbData->Status.last_final = pNcbData->Status.this_final;
|
||
}
|
||
}
|
||
//
|
||
// Here if a new error has occured so log it in the error log.
|
||
//
|
||
|
||
MsgErrorLogWrite(
|
||
NELOG_Ncb_Error,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE) ncb,
|
||
sizeof(NCB),
|
||
NULL,
|
||
0); // Enter error in system error log
|
||
|
||
|
||
MSG_LOG(ERROR,"MsgNetBiosError3:An unexpected NCB was received 0x%x\n",retval);
|
||
|
||
UNUSED(retval);
|
||
|
||
#if DBG
|
||
MsgDumpNcb(ncb);
|
||
#endif
|
||
|
||
return (RUNNING);
|
||
}
|
||
|
||
/*
|
||
* MsgReceiveService - service a completed RECEIVE net bios call
|
||
*
|
||
* This function is called to service a completed RECEIVE net
|
||
* bios call. For successful completions, it examines the data
|
||
* received to determine which of the SMB-processing functions
|
||
* should be called.
|
||
*
|
||
* MsgReceiveService (net, ncbi, retval)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
* retval - value returned by the net bios
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function dispatches SMB's received to the proper processing
|
||
* function. It also handles a number of error conditions (noted
|
||
* in the code below).
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* See handling of error conditions.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgReceiveService(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi, // Index to completed NCB
|
||
char retval // SEND return value
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to completed NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
PSMB_HEADER smb; // Pointer to SMB header
|
||
|
||
|
||
MSG_LOG(TRACE,"In MsgReceiveService %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
|
||
switch(retval) {
|
||
|
||
case NRC_GOODRET: // Success
|
||
if(ncb->ncb_length >= sizeof(SMB_HEADER)) {
|
||
//
|
||
// If we could have an SMB
|
||
//
|
||
smb = (PSMB_HEADER)ncb->ncb_buffer;
|
||
|
||
// Get pointer to buffer
|
||
switch(smb->Command) { // Switch on SMB function code
|
||
case SMB_COM_SEND_MESSAGE: // Single block message
|
||
Msgsblockmes(net,ncbi);
|
||
return;
|
||
|
||
case SMB_COM_SEND_START_MB_MESSAGE: // Beginning of multi-block message
|
||
Msgmblockbeg(net,ncbi);
|
||
return;
|
||
|
||
case SMB_COM_SEND_END_MB_MESSAGE: // End of multi-block message
|
||
Msgmblockend(net,ncbi);
|
||
return;
|
||
|
||
case SMB_COM_SEND_TEXT_MB_MESSAGE: // Text of multi-block message
|
||
Msgmblocktxt(net,ncbi);
|
||
return;
|
||
|
||
case SMB_COM_GET_MACHINE_NAME: // Get Machine Name
|
||
MsgGetMachineName(net,ncbi);
|
||
return;
|
||
|
||
case SMB_COM_FORWARD_USER_NAME: // Add forward-name
|
||
//
|
||
// Not supported in NT.
|
||
// for now fall through as if unrecognized SMB.
|
||
//
|
||
|
||
case SMB_COM_CANCEL_FORWARD: // Delete forward-name
|
||
//
|
||
// Not supported in NT.
|
||
// for now fall through as if unrecognized SMB.
|
||
//
|
||
|
||
default: // Unrecognized SMB
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// If middle of multi-block message, Log an error
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
|
||
//
|
||
// Enter error in system error log
|
||
//
|
||
|
||
MsgErrorLogWrite(
|
||
NELOG_Msg_Unexpected_SMB_Type,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE)ncb->ncb_buffer,
|
||
ncb->ncb_length,
|
||
NULL,
|
||
0);
|
||
|
||
MSG_LOG(ERROR,"MsgReceiveService:An illegal SMB was received\n",0);
|
||
//
|
||
// HANGUP and LISTEN again
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
break;
|
||
|
||
case NRC_CMDTMO: // Command timed out
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// If middle of multi-block message
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi); // Log an error
|
||
}
|
||
//
|
||
// HANGUP and start new LISTEN
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
break;
|
||
|
||
case NRC_SCLOSED: // Session closed
|
||
case NRC_SABORT: // Session ended abnormally
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// If middle of multi-block message, Log an error
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
//
|
||
// Start a new LISTEN
|
||
//
|
||
MsgStartListen(net,ncbi);
|
||
break;
|
||
|
||
default: // Other errors
|
||
MSG_LOG(TRACE,"MsgReceiveService: Unrecognized retval %x\n",retval);
|
||
|
||
MsgNetBiosError(net,ncb,retval,ncbi);
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
//
|
||
// If middle of multi-block message, Log an error
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
|
||
MsgRestart(net,ncbi); // HANGUP and LISTEN again
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgRestart - issue a HANGUP net bios call
|
||
*
|
||
* This function is invoked to issue a HANGUP net bios call using
|
||
* a particular Network Control Block.
|
||
*
|
||
* MsgRestart (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function assumes that the NCB_LSN, NCB_POST, and NCB_LANA
|
||
* fields of the Network Control Block are already properly set.
|
||
* It sets the NCB_CMD field.
|
||
*
|
||
* This function is named "MsgRestart" since the very next routine
|
||
* to process the NCB used to issue the HANGUP should be
|
||
* MsgHangupService() which always invokes MsgStartListen() (assuming
|
||
* the HANGUP completes properly). Thus, the net effect of
|
||
* calling MsgRestart() is to terminate the current session and
|
||
* issue a LISTEN to start a new one.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgCallNetBios() to issue the net bios call. Sets mpncbifun[ncbi]
|
||
* to the address of MsgHangupService().
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgRestart(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to Network Control Block
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
|
||
MSG_LOG(TRACE,"In MsgRestart %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb;
|
||
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgHangupService; // Set function pointer
|
||
ncb->ncb_command = NCBHANGUP | ASYNCH; // Hang up (no wait)
|
||
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
}
|
||
|
||
/*
|
||
* Msgsblockmes - process a single block message
|
||
*
|
||
* This function logs and acknowledges a single block message.
|
||
*
|
||
* Msgsblockmes (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* This function is called from ReceivePost() (RecAnyPost()).
|
||
* It first check to see if it is appropriate for the ncbi'th
|
||
* name to have received a single block message SMB at the current
|
||
* time. It verifies the correctness of the SMB in the ncbi'th
|
||
* buffer. It attempts to log the single block message, and it
|
||
* sends an acknowledgement to the sender of the message.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgRestart() to terminate the session if the SMB has arrived
|
||
* at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
|
||
* Calls logsbm() to log the message. Calls MsgSendAck() to send an
|
||
* acknowledgement to the sender of the message.
|
||
*/
|
||
|
||
STATIC VOID
|
||
Msgsblockmes(
|
||
DWORD net, // Which network ?
|
||
DWORD ncbi // Index to NCB
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB
|
||
LPBYTE buffer; // Pointer to SMB buffer
|
||
LPSTR cp; // Save pointer
|
||
LPSTR from; // From-name
|
||
LPSTR to; // To-name
|
||
|
||
// to browse the SessionId List :
|
||
PMSG_SESSION_ID_ITEM pItem; // item in the list
|
||
PLIST_ENTRY pHead; // head of the list
|
||
PLIST_ENTRY pList; // list pointer
|
||
DWORD bError = 0; // error flag
|
||
|
||
MSG_LOG(TRACE,"In Msgsblockmes %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
|
||
if(pNcbData->State != MESSTART) {
|
||
|
||
//
|
||
// If wrong time for this block
|
||
// Hang up and start a new listen,
|
||
// log an error if mpncbistate[net][ncbi] == MESCONT;
|
||
// otherwise, do not log the error.
|
||
//
|
||
// Log error if message in progress
|
||
//
|
||
|
||
if(pNcbData->State == MESCONT) {
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
|
||
//
|
||
// HANGUP and LISTEN again
|
||
//
|
||
|
||
MsgRestart(net,ncbi);
|
||
return;
|
||
}
|
||
|
||
pNcbData->State = MESSTOP; // End of message state
|
||
|
||
//
|
||
// Check for malformed SMB
|
||
//
|
||
|
||
if(MsgVerifySmb(net,ncbi,(unsigned char)SMB_COM_SEND_MESSAGE,0,"ssb") != 0) {
|
||
return;
|
||
}
|
||
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
|
||
from = &buffer[sizeof(SMB_HEADER) + 4]; // Save pointer to from-name
|
||
to = &from[strlen(from) + 2]; // Save pointer to to-name
|
||
cp = &to[strlen(to) + 2]; // Skip over the name
|
||
|
||
|
||
if (g_IsTerminalServer)
|
||
{
|
||
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"Msgsblockmes");
|
||
pHead = &(SD_SIDLIST(net,ncbi));
|
||
pList = pHead;
|
||
while (pList->Flink != pHead) // loop all over the list
|
||
{
|
||
pList = pList->Flink;
|
||
pItem = CONTAINING_RECORD(pList, MSG_SESSION_ID_ITEM, List);
|
||
bError = Msglogsbm(from,to,cp, pItem->SessionId);
|
||
|
||
if (bError)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
MsgDatabaseLock(MSG_RELEASE,"Msgsblockmes");
|
||
}
|
||
else //regular NT
|
||
{
|
||
bError = Msglogsbm(from,to,cp,0);
|
||
}
|
||
|
||
if (bError)
|
||
{
|
||
//
|
||
// If message cannot be logged, enter error state
|
||
// and send error acknowledgement.
|
||
//
|
||
pNcbData->State = MESERR;
|
||
MsgSendAck(net,ncbi,'\002',SMB_ERR_NO_ROOM);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Otherwise acknowledge success
|
||
//
|
||
MsgSendAck(net, ncbi, SMB_ERR_SUCCESS, (USHORT)SMB_ERR_SUCCESS);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgSendAck - send an SMB to acknowledge a network transaction
|
||
*
|
||
* This function is used to send a Server Message Block to some
|
||
* machine with whom a session has been established acknowledging
|
||
* (positively or negatively) the occurrence of some event pertaining
|
||
* to the session.
|
||
*
|
||
* MsgSendAck (net, ncbi, smbrclass, smbrcode)
|
||
*
|
||
* ENTRY
|
||
* net - Network index
|
||
* ncbi - Network Control Block index
|
||
* smbrclass - SMB return class
|
||
* smbrcode - SMB return code
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* Using the NCB index to locate the buffer containing the last SMB
|
||
* received in the session, this function sets the return class and
|
||
* the return code in that SMB according to its arguments and sends
|
||
* the SMB to the other party in the session. This function will
|
||
* not return any parameters or buffers in that SMB.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* This function calls MsgCallNetBios() to send the SMB, and it sets
|
||
* the function vector so that control will pass to Send Service()
|
||
* when the NCB completes (assuming, of course, that it doesn't
|
||
* fail immediately).
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgSendAck(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi, // Network Control Block Index
|
||
UCHAR smbrclass, // SMB return class
|
||
USHORT smbrcode // SMB return code
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
LPBYTE buffer; // Pointer to buffer
|
||
|
||
MSG_LOG(TRACE,"In MsgSendAck %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to NCB
|
||
buffer = ncb->ncb_buffer; // Get pointer to buffer
|
||
|
||
//
|
||
// No parameters, buffers
|
||
//
|
||
buffer[sizeof(SMB_HEADER)+2]=
|
||
buffer[sizeof(SMB_HEADER)+1]=
|
||
buffer[sizeof(SMB_HEADER)]= '\0';
|
||
|
||
//
|
||
// Set return information
|
||
//
|
||
|
||
((PSMB_HEADER)buffer)->ErrorClass = smbrclass; // Set return class
|
||
|
||
SmbPutUshort( &(((PSMB_HEADER)buffer)->Error),smbrcode);// Set return code
|
||
|
||
// ((PSMB_HEADER)buffer)->Error = smbrcode; // Set return code
|
||
ncb->ncb_length = sizeof(SMB_HEADER) + 3; // Set length of buffer
|
||
ncb->ncb_command = NCBSEND | ASYNCH; // Send (no wait)
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgSendService; // Set function pointer
|
||
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
}
|
||
|
||
/*
|
||
* MsgSendService - service a completed SEND net bios call
|
||
*
|
||
* This function is called to service a completed SEND net bios
|
||
* call. The usual course of action is to issue a RECEIVE (ANY)
|
||
* net bios call.
|
||
*
|
||
* MsgSendService (net, ncbi, retval)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
* retval - value returned by net bios
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* If a SEND net bios call has completed successfully, this function
|
||
* will issue a RECEIVE (ANY) net bios call in all cases. The com-
|
||
* pleted SEND represents one of the following cases:
|
||
*
|
||
* - Acknowledgement of a Single Block Message
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
* - Acknowledgement of the start of a Multi-block Message
|
||
* The message originator will SEND a text block, completing the RECEIVE
|
||
* (ANY) call.
|
||
* - Acknowledgement of text of a Multi-block Message
|
||
* The message originator will SEND more text or the end of the message,
|
||
* completing the RECEIVE (ANY) call.
|
||
* - Acknowledgement of the end of a Multi-block Message
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
* - Response to a Get Machine Name request
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
* - Acknowledgement of a Forward Name request
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
* - Acknowledgement of a Cancel Forward request
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
* - An error response
|
||
* The message originator will HANG UP, completing the RECEIVE (ANY) call.
|
||
*
|
||
* In all cases, it is clear to the RECEIVE (ANY) service function what its
|
||
* course of action is.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* If a SEND has completed normally, this function issues a RECEIVE (ANY)
|
||
* net bios call. In some abnormal cases, this function calls MsgStartListen()
|
||
* to initiate a new session. In all other abnormal cases, it calls
|
||
* MsgNetBiosError().
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgSendService(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi, // Index of completed NCB
|
||
char retval // SEND return value
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to completed NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
PSMB_HEADER smb; // Pointer to SMB header
|
||
|
||
MSG_LOG(TRACE,"In MsgSendService %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb; // Get pointer to completed NCB
|
||
|
||
switch(retval) {
|
||
|
||
case NRC_GOODRET: // Success
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgReceiveService;
|
||
|
||
//
|
||
// Set function pointer
|
||
//
|
||
ncb->ncb_command = NCBRECV | ASYNCH; // Receive (no wait)
|
||
ncb->ncb_length = BUFLEN; // Set length of buffer
|
||
MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
|
||
break;
|
||
|
||
case NRC_CMDTMO: // Timeout
|
||
case NRC_SCLOSED: // Session closed
|
||
case NRC_SABORT: // Session ended abnormally
|
||
|
||
smb = (PSMB_HEADER)ncb->ncb_buffer; // Get pointer to SMB
|
||
|
||
if(smb->Command == SMB_COM_SEND_START_MB_MESSAGE || smb->Command == SMB_COM_SEND_TEXT_MB_MESSAGE) {
|
||
|
||
//
|
||
// Message ended abnormally
|
||
//
|
||
Msglogmbe(MESERR,net,ncbi);
|
||
}
|
||
//
|
||
// Issue a new LISTEN
|
||
//
|
||
MsgStartListen(net,ncbi);
|
||
break;
|
||
|
||
default: // Other failure
|
||
MSG_LOG(TRACE,"MsgSendService: Unrecognized retval %x\n",retval);
|
||
MsgNetBiosError(net,ncb,retval,ncbi);
|
||
//
|
||
// HANGUP and LISTEN again
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgServeNCBs - service completed Network Control Blocks
|
||
*
|
||
* This function scans the array of NCB's looking for NCB's in
|
||
* need of service.
|
||
*
|
||
* MsgServeNCBs (net)
|
||
*
|
||
* ENTRY
|
||
* net - network to service NCBs on
|
||
*
|
||
* RETURN
|
||
* TRUE - If this function actually services a completed NCB.
|
||
* FALSE - If this function didn't find any completed NCB's, or if
|
||
* the service is supposed to stop.
|
||
*
|
||
* This function scans the array of NCB's until a completed NCB cannot be
|
||
* found. Each time a completed NCB is found, the service function specified
|
||
* in the service function vector (mpncbifun[]) is called to service that
|
||
* NCB.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Maintains a private static index of the last NCB examined.
|
||
* Starts each search at first NCB after the last one serviced.
|
||
*/
|
||
|
||
BOOL
|
||
MsgServeNCBs(
|
||
DWORD net // Which network am I serving?
|
||
)
|
||
{
|
||
PNCB pNcb;
|
||
PNCB_DATA pNcbData;
|
||
int counter; // A counter
|
||
BOOL found = FALSE; // Indicates if a completed NCB was found.
|
||
|
||
// Bugfix: each net has its own index, addressing
|
||
// its part NCB array. All index values are initiliazed to zero
|
||
// when the messenger starts. This solves the muti thread
|
||
// problem.
|
||
|
||
static int ncbIndexArray[MSNGR_MAX_NETS] = {0};
|
||
// NCB index array
|
||
DWORD ncbi; // NCB index for this net
|
||
|
||
|
||
//
|
||
// get NCB index for this net
|
||
//
|
||
ncbi = ncbIndexArray[net];
|
||
|
||
//
|
||
// Loop until none completed found
|
||
//
|
||
do {
|
||
//
|
||
// Loop to search NCB array
|
||
//
|
||
for(counter = NCBMAX(net); counter != 0; --counter, ++ncbi) {
|
||
|
||
if(ncbi >= NCBMAX(net)) {
|
||
ncbi = 0;// Wrap around
|
||
}
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
pNcb = &pNcbData->Ncb;
|
||
if(pNcb->ncb_cmd_cplt != (unsigned char) 0xff) {
|
||
found=TRUE;
|
||
//
|
||
// If completed NCB found
|
||
//
|
||
if(pNcb->ncb_cmd_cplt == 0) {
|
||
//
|
||
// Clear err on success and error count
|
||
//
|
||
pNcbData->Status.last_final = 0;
|
||
pNcbData->Status.rep_count = 0;
|
||
}
|
||
else {
|
||
//
|
||
// Else mark error
|
||
//
|
||
pNcbData->Status.this_final = pNcb->ncb_cmd_cplt;
|
||
|
||
|
||
//
|
||
// If NetBios is failing with every call, we never
|
||
// return from this routine be cause there is always
|
||
// another NCB to service. Therefore, in error
|
||
// conditions it is necessary to check to see if a
|
||
// shutdown is in progress. If so, we want to return
|
||
// so that the adapter loop can handle the shutdown
|
||
// properly.
|
||
//
|
||
if (GetMsgrState() == STOPPING) {
|
||
ncbIndexArray[net] = ncbi;
|
||
return(FALSE);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Call the service function
|
||
//
|
||
(*pNcbData->IFunc)(net,ncbi,pNcb->ncb_cmd_cplt);
|
||
|
||
++ncbi; // Start next search after this NCB
|
||
break; // Exit loop
|
||
}
|
||
}
|
||
}
|
||
while(counter != 0); // Loop until counter zero
|
||
|
||
// update NCB index
|
||
ncbIndexArray[net] = ncbi;
|
||
return(found);
|
||
}
|
||
|
||
/*
|
||
* MsgSesFullService - complete deletion of a name after a system error
|
||
*
|
||
* MsgSesFullService() completes the process of deleting a name from
|
||
* the message system when the message server is unable to establish
|
||
* a session for that name.
|
||
*
|
||
* MsgSesFullService (net, ncbi, retval)
|
||
*
|
||
* ENTRY
|
||
* net - Network index
|
||
* ncbi - Network Control Block index
|
||
* retval - value returned by net bios
|
||
*
|
||
* RETURN
|
||
* nothing
|
||
*
|
||
* MsgSesFullService() is called to finish the job of cleaning up when
|
||
* a LISTEN fails because the local network adapter's session table
|
||
* is full. Specifically, this function is called when the DELETE
|
||
* NAME net bios call completes.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgDeleteName() to release the deleted name's entry in the
|
||
* shared data area. Calls MsgNetBiosError() if the DELETE NAME net
|
||
* bios call produced unexpected results.
|
||
*/
|
||
|
||
STATIC VOID
|
||
MsgSesFullService(
|
||
DWORD net, // Which network ?
|
||
DWORD ncbi, // Index of completed NCB
|
||
char retval // SEND return value
|
||
)
|
||
|
||
{
|
||
PNCB pNcb;
|
||
MSG_LOG(TRACE,"In MsgSesFullService %d\n",net);
|
||
|
||
switch(retval) {
|
||
|
||
case NRC_GOODRET: // Success
|
||
case NRC_ACTSES: // Name deregistered
|
||
|
||
//
|
||
// Log deletion in system error log file
|
||
//
|
||
MsgDeleteName(net,ncbi); // Delete name from database
|
||
break;
|
||
|
||
default: // Failure
|
||
|
||
MSG_LOG(TRACE,"MsgSesFullService: Unrecognized retval %x\n",retval);
|
||
pNcb = GETNCB(net,ncbi);
|
||
MsgNetBiosError(net, pNcb, retval, ncbi);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* MsgStartListen - issue a LISTEN net bios call
|
||
*
|
||
* This function is invoked to issue a LISTEN net bios call using
|
||
* a particular Network Control Block. This function does not
|
||
* examine or change any of the shareable data corresponding to
|
||
* the NCB in question.
|
||
*
|
||
* MsgStartListen (net, ncbi)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - Network Control Block index
|
||
*
|
||
* RETURN
|
||
* DWORD status from the netbios call.
|
||
*
|
||
* This function assumes that the NCB_NAME, NCB_POST, and NCB_LANA
|
||
* fields of the Network Control Block are already set to the
|
||
* proper values. It sets the NCB_CNAME, NCB_RTO, NCB_STO, and
|
||
* NCB_CMD fields.
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls MsgCallNetBios() to issue the net bios call. Calls FmtNcbName()
|
||
* to set the NCB_CNAME field of the NCB. Sets mpncbifun[ncbi] to
|
||
* the address of MsgListenService().
|
||
*/
|
||
|
||
NET_API_STATUS
|
||
MsgStartListen(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi // Network Control Block index
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to NCB
|
||
PNCB_DATA pNcbData; // Pointer to NCB Data
|
||
|
||
NET_API_STATUS status;
|
||
TCHAR name[2] = TEXT("*");
|
||
|
||
MSG_LOG(TRACE,"In MsgStartListen %d\n",net);
|
||
|
||
pNcbData = GETNCBDATA(net,ncbi);
|
||
ncb = &pNcbData->Ncb;
|
||
pNcbData->IFunc = (LPNCBIFCN)MsgListenService; // Set function pointer
|
||
|
||
//
|
||
// Set call name to a"anyone"
|
||
//
|
||
status = MsgFmtNcbName(ncb->ncb_callname,name,' ');
|
||
if (status != NERR_Success) {
|
||
//
|
||
// This is a bug if this can't be done.
|
||
//
|
||
MSG_LOG(ERROR,"MsgStartListen: NASTY BUG! Cannot format \"*\" name! %X\n",
|
||
status);
|
||
NetpAssert(0);
|
||
}
|
||
|
||
ncb->ncb_rto = 60; // Receives time out in 30 sec
|
||
ncb->ncb_sto = 40; // Sends time out in 20 sec
|
||
ncb->ncb_command = NCBLISTEN | ASYNCH; // Listen (no wait)
|
||
|
||
return(MsgCallNetBios(net,ncb,ncbi)); // Issue the net bios call
|
||
}
|
||
|
||
/*
|
||
* MsgVerifySmb - Verify the correctness of a Server Message Block
|
||
*
|
||
* This function verifies that a Server Message Block is properly
|
||
* formed. If it detects a malformed SMB, it terminates the session
|
||
* and returns a non-zero value.
|
||
*
|
||
* MsgVerifySmb (net, ncbi, func, parms, buffers)
|
||
*
|
||
* ENTRY
|
||
* net - network index
|
||
* ncbi - index to a Network Control Block
|
||
* func - SMB function code
|
||
* parms - number of parameters in SMB
|
||
* buffers - dope vector describing buffers in the SMB
|
||
*
|
||
* RETURN
|
||
* int - error code (zero means no error)
|
||
*
|
||
* SIDE EFFECTS
|
||
*
|
||
* Calls smbcheck() to check the SMB. Calls MsgRestart() if
|
||
* smbcheck() reports an error.
|
||
*/
|
||
|
||
STATIC int
|
||
MsgVerifySmb(
|
||
DWORD net, // Which network?
|
||
DWORD ncbi, // Index to Network Control Block
|
||
UCHAR func, // SMB function code
|
||
int parms, // Count of parameters in SMB
|
||
LPSTR buffers // Dope vector of SMB buffers
|
||
)
|
||
{
|
||
PNCB ncb; // Pointer to Network Control Block
|
||
int i; // Return code
|
||
|
||
|
||
ncb = GETNCB(net,ncbi); // Get pointer to NCB
|
||
|
||
i = Msgsmbcheck(
|
||
(ncb->ncb_buffer),
|
||
ncb->ncb_length,
|
||
func,
|
||
(char)parms,
|
||
buffers);
|
||
|
||
if (i != 0 ) {
|
||
|
||
//
|
||
// if SMB malformed, Enter error in system error log
|
||
//
|
||
|
||
MsgErrorLogWrite(
|
||
NELOG_SMB_Illegal,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE)ncb->ncb_buffer,
|
||
ncb->ncb_length,
|
||
NULL,
|
||
0);
|
||
|
||
MSG_LOG(ERROR,"MsgVerifySmb:An illegal SMB was received\n",0);
|
||
//
|
||
// HANGUP
|
||
//
|
||
MsgRestart(net,ncbi);
|
||
}
|
||
return(i); // Return error code
|
||
}
|
||
|
||
#if DBG
|
||
VOID
|
||
MsgDumpNcb(
|
||
IN PNCB pNcb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Displays the NCB on a debug terminal.
|
||
|
||
Arguments:
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
--*/
|
||
{
|
||
DbgPrint("NCBADDR: 0x%x\n"
|
||
"Command: 0x%x\n"
|
||
"RetCode: 0x%x\n"
|
||
"LanaNum: 0x%x\n"
|
||
"CmdCplt: 0x%x\n"
|
||
"Name : %s\n"
|
||
"callNam: %s\n",
|
||
pNcb, pNcb->ncb_command, pNcb->ncb_retcode, pNcb->ncb_lana_num,
|
||
pNcb->ncb_cmd_cplt, pNcb->ncb_name, pNcb->ncb_callname);
|
||
|
||
}
|
||
#endif // DBG
|