📄 netbiostransport.cpp
字号:
}
}
pAddr = pAddr->Next;
}
pAdapTemp = pAdapTemp->Next;
}
Done:
#ifdef DEBUG
if(FALSE == fAllowed) {
TRACEMSG(ZONE_ERROR, (L"NETBIOS: not an allowed interface -- this is okay, but might mean the adapter should be configured -- see docs"));
}
#endif
if(NULL != pAdapInfo && &AdapInfo[0] != pAdapInfo) {
delete [] pAdapInfo;
}
return fAllowed;
}
//
// Init a NetBIOS lana -- this involves
// registering for our name on the interface
// and spinning transport threads to queue
// our CIFS packets
HRESULT InitLana(UCHAR ulLANIdx, DWORD dwNTE)
{
TRACEMSG(ZONE_INIT, (TEXT("SMBSRV:Initing NETBIOS LANA(%d)"),ulLANIdx));
HRESULT hr = E_FAIL;
BYTE *pCName;
UCHAR retVal;
UINT uiCNameLen;
ncb tNcb;
NetBIOSAdapter *pNewAdapter = NULL;
LANA_INFO LanaInfo;
//
// Get the CName from globals
if(FAILED(hr = SMB_Globals::GetCName(&pCName, &uiCNameLen)) ||
NULL == pCName ||
0 == uiCNameLen ||
uiCNameLen > 15)
{
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:Invalid CName returned from globals!")));
if(SUCCEEDED(hr)) //preserve any failure HR we might have
hr = E_FAIL;
goto Done;
}
//
// Query into netbios for the ipaddress of the new adapter
tNcb.ncb_command = NCBQUERYLANA;
tNcb.ncb_length = sizeof(LANA_INFO);
tNcb.ncb_buffer = (BYTE *)&LanaInfo;
tNcb.ncb_lana_num = ulLANIdx;
retVal = Netbios(&tNcb);
if (0 != (retVal = tNcb.ncb_retcode)) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: NCBQUERYLANA returned %s"), NETBIOS_TRANSPORT::NCBError(retVal)));
if(SUCCEEDED(hr)) //preserve any failure HR we might have
hr = E_FAIL;
goto Done;
}
//
// See if we want to listen on this adapter
if(FALSE == AllowLana(&LanaInfo)) {
TRACEMSG(ZONE_NETBIOS, (L"SMBSRV:InitLana: we dont allow this LANA (%d)", ulLANIdx));
hr = S_OK;
goto Done;
}
RETAILMSG(1, (TEXT("SMBSRV:InitLana: staring lana: %d"), ulLANIdx));
//
// Setup addname and claim our name
tNcb.ncb_command = NCBADDNAME;
tNcb.ncb_lana_num = ulLANIdx;
tNcb.ncb_length = 0;
tNcb.ncb_buffer = NULL;
memset(tNcb.ncb_name, ' ', 16);
memcpy(tNcb.ncb_name, pCName, uiCNameLen);
retVal = Netbios(&tNcb);
if (0 != (retVal = tNcb.ncb_retcode)) {
RETAILMSG(1, (TEXT("SMBSRV:InitLana: NCBADDNAME returned %s"), NETBIOS_TRANSPORT::NCBError(retVal)));
if(SUCCEEDED(hr)) //preserve any failure HR we might have
hr = E_FAIL;
goto Done;
}
//
// Startup a TCP transport
if(FAILED(hr = StartTCPListenThread(LanaInfo.IPAddr, ulLANIdx))) {
goto Done;
}
//fire up the interface (by creating a new NetBIOSAdapter object) --
// inside that will spin any threads it needs (it will be self contained)
if(NULL == (pNewAdapter = new NetBIOSAdapter(ulLANIdx))) {
hr = E_OUTOFMEMORY;
goto Done;
}
pNewAdapter->SetNTE(dwNTE);
pNewAdapter->SetCName(tNcb.ncb_name);
if(!NBAdapterStack.push_back(pNewAdapter)) {
hr = E_OUTOFMEMORY;
}
pNewAdapter = NULL;
hr = S_OK;
Done:
//
// NOTE: this is nulled on init/success... only on failure would
// it be non-null
if(pNewAdapter)
delete pNewAdapter;
return hr;
}
HRESULT
InitNetbiosTransport()
{
if(g_fIsInited) {
return S_OK;
}
g_fIsInited = TRUE;
InitializeCriticalSection(&csSendLock);
InitializeCriticalSection(&csActiveRecvListLock);
InitializeCriticalSection(&csAdapterStackList);
InitializeCriticalSection(&csNCBLock);
//
// Create an event to stop any threads that we may create
if(NULL == g_hHaltNetbiosTransport) {
g_hHaltNetbiosTransport = CreateEvent(NULL, TRUE, FALSE, NULL);
}
return (NULL == g_hHaltNetbiosTransport)?E_FAIL:S_OK;
}
HRESULT
DestroyNetbiosTransport()
{
if(!g_fIsInited) {
return S_OK;
}
g_fIsInited = FALSE;
if(NULL != g_hHaltNetbiosTransport) {
CloseHandle(g_hHaltNetbiosTransport);
g_hHaltNetbiosTransport = NULL;
}
DeleteCriticalSection(&csSendLock);
DeleteCriticalSection(&csActiveRecvListLock);
DeleteCriticalSection(&csAdapterStackList);
DeleteCriticalSection(&csNCBLock);
return S_OK;
}
//
// Start the netbios transport -- this includes
// initing any global variables before threads get spun
// etc
HRESULT StartNetbiosTransport()
{
TRACEMSG(ZONE_INIT, (TEXT("SMBSRV:Starting NETBIOS transport")));
HRESULT hr=E_FAIL;
//
// If we are already running dont start up
if(TRUE == g_fIsRunning) {
hr = S_OK;
goto Done;
}
//
// running must be true for the enumeration code to operate properly
InterlockedExchange(&g_fIsRunning, TRUE);
ASSERT(INVALID_HANDLE_VALUE == g_hNetbiosIOCTL);
if(INVALID_HANDLE_VALUE == (g_hNetbiosIOCTL = CreateFile(NETBIOS_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL))) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:Couldnt connect to NETBIOS!")));
ASSERT(FALSE);
goto Done;
}
//
// Start up a thread to listen for name change events (this thread never goes away)
if(FAILED(hr = StartListenOnNameChange())) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:Failed to start the netbios name listen thread!")));
goto Done;
}
//
// Start enuming netbios calls -- this registers with netbios to receive lan up/down events
if(FAILED(hr = StartEnumeratingNetbios())) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:Failed getting number of interfaces!")));
goto Done;
}
hr = S_OK;
InterlockedExchange(&g_fIsAccepting, TRUE);
Done:
if(FAILED(hr)) {
InterlockedExchange(&g_fIsRunning, FALSE);
}
return hr;
}
HRESULT StopNetbiosTransport(void)
{
TRACEMSG(ZONE_INIT, (TEXT("SMBSRV:Stopping NETBIOS transport")));
HRESULT hr = S_OK;
BOOL fHaldAdapterFailed = FALSE;
//
// Stop listening on name change (NOTE; this maybe running even when the rest
// of netbios isnt, so dont check g_fIsRunning
if(FAILED(hr = StopListeningOnNameChange())) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:error stoping listening on name change")));
ASSERT(FALSE);
goto Done;
}
if(FALSE == g_fIsRunning) {
hr = S_OK;
goto Done;
}
InterlockedExchange(&g_fIsRunning, FALSE);
ASSERT(INVALID_HANDLE_VALUE != g_hNetbiosIOCTL);
//
// Stop enumerating netbios devices
if(FAILED(hr = StopEnumeratingNetbios())) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:error stoping enum thread")));
ASSERT(FALSE);
goto Done;
}
//
// Flush out any remaining adapters
while(NBAdapterStack.size()) {
NetBIOSAdapter *pAdapter = NBAdapterStack.front();
if(NULL == pAdapter) {
ASSERT(FALSE);
} else {
if(FAILED(hr = pAdapter->HaltAdapter())) {
fHaldAdapterFailed = TRUE;
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:error stoping netbios adapter")));
}
NBAdapterStack.pop_front();
delete pAdapter;
}
}
//
// Just empty out the list -- the values inside it are worthless now
// as the NBAdapterStack has been flushed
while(NBAdapterDeleteStack.size()) {
NBAdapterDeleteStack.pop_front();
}
InterlockedExchange(&g_fIsAccepting, FALSE);
Done:
if(fHaldAdapterFailed || FAILED(hr)) {
hr = E_FAIL;
InterlockedExchange(&g_fIsAccepting, TRUE);
InterlockedExchange(&g_fIsRunning, TRUE);
}
if(INVALID_HANDLE_VALUE != g_hNetbiosIOCTL) {
CloseHandle(g_hNetbiosIOCTL);
g_hNetbiosIOCTL = INVALID_HANDLE_VALUE;
}
return hr;
}
DWORD
NETBIOS_TRANSPORT::SMBSRVR_NetbiosListenThread(LPVOID _pMyAdapter)
{
HRESULT hr = E_FAIL;
PREFAST_ASSERT(_pMyAdapter);
NetBIOSAdapter *pMyAdapter = (NetBIOSAdapter *)_pMyAdapter;
ASSERT(pMyAdapter);
UINT uiConsecFails = 0;
// See if we have been shut down -- (note we were created suspended so
// errors can be checked for
if(pMyAdapter->DuringShutDown()) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-LSTNTHREAD:Listen thread not starting -- error before launch")));
hr = E_FAIL;
goto Done;
}
//
// Loop as long as we are not shutting down
while (FALSE == pMyAdapter->DuringShutDown()) {
ncb ncb;
BYTE *pCName;
UINT uiCNameLen;
UCHAR ncb_err;
#ifdef DEBUG
memset(&ncb, 0xAB, sizeof(ncb));
#endif
ncb.ncb_lana_num = pMyAdapter->GetLANA();
ncb.ncb_command = NCBLISTEN;
ncb.ncb_callname[0] = '*';
ncb.ncb_length = 0;
ncb.ncb_buffer = NULL;
//
// Get the CName from globals
if(FAILED(hr = SMB_Globals::GetCName(&pCName, &uiCNameLen)) ||
NULL == pCName ||
0 == uiCNameLen ||
uiCNameLen > 15)
{
//
// If getting the CName fails, there really isnt much we can do
// just abort out
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-LSTNTHREAD:Invalid CName returned from globals!")));
if(SUCCEEDED(hr)) //preserve any failure HR we might have
hr = E_FAIL;
goto Done;
}
memset(ncb.ncb_name, ' ', 16);
memcpy(ncb.ncb_name, pCName, uiCNameLen);
ncb_err = Netbios(&ncb);
//
// Make sure we didnt return from the blocked state into a shutdown
if(TRUE == pMyAdapter->DuringShutDown()) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-LSTNTHREAD:ListenThread -- recved shutdown")));
break;
}
//
// Check for errors on the return of NETBIOS
if(NRC_ADPTMALFN == ncb_err || NRC_IFAIL == ncb_err) {
RETAILMSG(1, (TEXT("SMBSRV-LSTNTHREAD:ListenThread stopping because of adapter malfunction -- prob was pulled?")));
break;
} else if(0 != ncb_err) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-LSTNTHREAD:ListenThread NCBLISTEN(%d) returned %s"), pMyAdapter->GetLANA(), NETBIOS_TRANSPORT::NCBError(ncb_err)));
ASSERT(FALSE);
uiConsecFails ++;
} else {
TRACEMSG(ZONE_ERROR, (L"NETBIOS Listen got -- LSN:%d on LANA:%d", ncb.ncb_lsn, ncb.ncb_lana_num));
HANDLE hRecvThread;
RecvNode NewNode;
RecvNode *pNodePtr = NULL;
CCritSection csLock(&csActiveRecvListLock);
csLock.Lock();
if(!ActiveRecvList.push_front(NewNode)) {
hr = E_OUTOFMEMORY;
goto Done;
}
pNodePtr = &(ActiveRecvList.front());
hRecvThread = CreateThread(NULL, 0, SMBSRVR_NetbiosRecvThread, (LPVOID)pNodePtr, CREATE_SUSPENDED, NULL);
pNodePtr->pAdapter = pMyAdapter;
pNodePtr->LANA = ncb.ncb_lana_num;
pNodePtr->usLSN = ncb.ncb_lsn;
pNodePtr->MyHandle = hRecvThread;
if(NULL == hRecvThread) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: CreateThread failed starting NB Recv:%d"), GetLastError()));
ActiveRecvList.pop_front();
goto Done;
}
if(0xFFFFFFFF == ResumeThread(hRecvThread)) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV:Resuming recv thread %d FAILED!"));
CloseHandle(hRecvThread);
}
uiConsecFails = 0;
}
//
// If we have failed a bunch of times in a row, abort... something is wrong
if(uiConsecFails >= 20) { //BUGBUG: use some real number here
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-LSTNTHREAD:ListenThread too many back to back fails... quitting thread\n")));
break;
}
}
Done:
TRACEMSG(ZONE_DETAIL, (TEXT("SMBSRV-LSTNTHREAD:Exiting thread!")));
if(FAILED(hr))
return -1;
else
return 0;
}
HRESULT
NETBIOS_TRANSPORT::CopyNBTransportToken(VOID *pToken, VOID **pNewToken)
{
((ref_ncb *)pToken)->AddRef();
*pNewToken = pToken;
return S_OK;
}
HRESULT
NETBIOS_TRANSPORT::DeleteNBTransportToken(VOID *pToken)
{
((ref_ncb *)pToken)->Release();
return S_OK;
}
DWORD
NETBIOS_TRANSPORT::SMBSRVR_NetbiosRecvThread(LPVOID _pAdapter)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -