summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/browser2/bwatch/bwatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/browser2/bwatch/bwatch.c')
-rw-r--r--private/net/svcdlls/browser2/bwatch/bwatch.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/private/net/svcdlls/browser2/bwatch/bwatch.c b/private/net/svcdlls/browser2/bwatch/bwatch.c
new file mode 100644
index 000000000..2cd5ebfe5
--- /dev/null
+++ b/private/net/svcdlls/browser2/bwatch/bwatch.c
@@ -0,0 +1,704 @@
+/*++
+
+Copyright (c) 1993 Micorsoft Corporation
+
+Module Name:
+
+ bwatch.c
+
+Abstract:
+
+ Browser Monitor main program.
+
+Author:
+ Dan Hinsley (DanHi) 10-Oct-1992
+ Congpa You (CongpaY) 10-Feb-1993
+
+Revision History:
+
+--*/
+#define INCLUDE_SMB_TRANSACTION
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <lm.h>
+#include <ntddbrow.h>
+#include <brcommon.h>
+#include <rpcutil.h>
+#include <nb30.h>
+#include <smbtypes.h>
+#include <smb.h>
+#include <smbgtpt.h>
+#include <hostannc.h>
+#include "bwatch.h"
+
+// main is going to be changed into a function which taks lpTransportName
+// and pDomainName as parameter.
+_cdecl main()
+{
+ INT nFileSizeLimit;
+ INT nIndex = 0;
+ DWORD dwVal;
+ CHAR pDomain[BUFFERLENGTH];
+ FILE * pFile;
+ PLMDR_TRANSPORT_LIST TransportList = NULL;
+ PLMDR_TRANSPORT_LIST TransportEntry = NULL;
+
+ // Tell user the program is running.
+ fprintf(stdout, "BWATCH is started.\n") ;
+
+ //Create a logfile for writing all the errors and other information to it.
+ pFile = fopen (szBWATCH, "w+");
+
+ // Print the start new run header in the logfile.
+ PrintHeader (pFile);
+
+ // Initialize global data.
+ if (!Init())
+ return;
+
+ // Get lpDomain from bwatch.ini.
+ if (!GetDomain (pDomain))
+ return;
+
+ nFileSizeLimit = GetLimit();
+
+ // Find all transports that we have.
+ dwVal = GetBrowserTransportList (&TransportList);
+ if (dwVal != NERR_Success)
+ {
+ if (TransportList != NULL)
+ {
+ MIDL_user_free (TransportList);
+ }
+ ReportError (dwVal);
+ return;
+ }
+
+ TransportEntry = TransportList;
+
+ // Enumerate on the transports.
+ while (TransportEntry != NULL)
+ {
+ CHAR * pDomainName;
+ CHAR pDomainList[BUFFERLENGTH];
+ CCHAR lana_num;
+ NET_API_STATUS Status;
+ PSUPER_NCB psuperncb;
+
+ strcpy (pDomainList, pDomain);
+
+ pDomainName = strtok (pDomainList, szSeps);
+
+ // Initialize psuperncb.
+
+ Status = BrGetLanaNumFromNetworkName (TransportEntry->TransportName, &lana_num);
+
+ if (Status != NERR_Success) {
+ ReportError (Status);
+ MIDL_user_free (TransportList);
+ return;
+ }
+
+ // Reset the adapter. You have to reset before doing anything.
+ if (Reset(FALSE, lana_num))
+ {
+ while (pDomainName != NULL)
+ {
+ psuperncb = (PSUPER_NCB) LocalAlloc (LPTR, sizeof(*psuperncb));
+ if (psuperncb != NULL)
+ {
+ psuperncb->lanaNumber = lana_num;
+
+ // Add DOMAIN(1e).
+ Registe (TransportEntry->TransportName, pDomainName, psuperncb, nIndex);
+
+ // Run Netbios.
+ SubmitRCDg (psuperncb);
+
+ nIndex++;
+ }
+
+ pDomainName = strtok (NULL, szSeps);
+ }
+
+#ifdef INCLUDE_MSBROWSE
+ psuperncb = (PSUPER_NCB) LocalAlloc (LPTR, sizeof(*psuperncb));
+
+ if (psuperncb != NULL)
+ {
+ psuperncb->lanaNumber = lana_num;
+
+ // Add MSBROWSE.
+ RegisteWkgroupName (TransportEntry->TransportName, "MSBROWSE", psuperncb, nIndex);
+
+ // Run Netbios.
+ SubmitRCDg (psuperncb);
+
+ nIndex++;
+ }
+#endif // INCLUDE_BRWOSE
+
+ }
+
+ if (TransportEntry->NextEntryOffset == 0)
+ {
+ TransportEntry = NULL;
+ }
+ else
+ {
+ TransportEntry = (PLMDR_TRANSPORT_LIST) ((PCHAR) TransportEntry
+ + TransportEntry->NextEntryOffset);
+ }
+ }
+
+ // Free the memory of TransportList.
+ MIDL_user_free (TransportList);
+
+ // Tell user the program is running.
+ fprintf(stdout, "BWATCH is now running.\n") ;
+
+ while (TRUE)
+ {
+ ProcessQueue(pFile, nFileSizeLimit);
+ }
+}
+
+// Report if an error occurs.
+void ReportError (DWORD dwError)
+{
+ printf("An error occured: %lu", dwError);
+}
+
+// Initialize the structure.
+BOOL Init()
+{
+ InitializeListHead (&WorkQueueHead);
+ InitializeListHead (&FreeQueueHead);
+
+ InitializeCriticalSection (&CSWorkQueue);
+ InitializeCriticalSection (&CSFreeQueue);
+
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ if (hEvent == NULL)
+ {
+ return(FALSE);
+ }
+ return(TRUE);
+}
+
+// Before we start a new session, we have to reset.
+// ncb.lana_num must be already set.
+
+BOOL Reset (UCHAR Reset,
+ CCHAR LanaNum)
+{
+ NCB ncb;
+ ClearNcb( &ncb );
+ ncb.ncb_command = NCBRESET;
+
+ ncb.ncb_lsn = Reset;
+
+ ncb.ncb_callname[0] = ncb.ncb_callname[1] = ncb.ncb_callname[2] =
+ ncb.ncb_callname[3] = 0;
+
+ ncb.ncb_lana_num = LanaNum;
+
+ Netbios( &ncb );
+ if ( ncb.ncb_retcode != NRC_GOODRET ) {
+ printf( "Reset returned an error %lx\n", ncb.ncb_retcode);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+// Registe a session.
+void Registe (LPTSTR lpTransportName,
+ CHAR * pDomainName,
+ PSUPER_NCB psuperncb,
+ INT nIndex)
+{
+ // Receive Datagram.
+ printf ("Running Netbios on transport %s, domain %s...\n", toansi(lpTransportName), pDomainName);
+
+ strcpy (psuperncb->pTransportName, toansi(lpTransportName));
+
+ strcpy (psuperncb->pDomainName, pDomainName);
+
+ psuperncb->nIndex = nIndex;
+
+ psuperncb->ncb.ncb_lana_num = psuperncb->lanaNumber;
+
+ // Registe DOMAIN(1e) for hearing Election and AnnouncementRequest packets.
+ AddName(0x1e, (NCB *) psuperncb);
+
+ psuperncb->nameNumber = psuperncb->ncb.ncb_num;
+
+}
+
+// Registe Netbios name.
+VOID AddName(UCHAR Suffix,
+ NCB * pncb)
+{
+ CHAR localName[32];
+
+ strcpy (localName, _strupr(((PSUPER_NCB) pncb)->pDomainName));
+ strcat (localName, SIXTEENSPACES);
+
+ ClearNcb( pncb );
+ pncb->ncb_command = NCBADDGRNAME;
+
+ localName[15] = Suffix;
+ RtlCopyMemory( pncb->ncb_name, localName, 16);
+ pncb->ncb_lana_num = ((PSUPER_NCB) pncb)->lanaNumber;
+ Netbios( pncb );
+ if ( pncb->ncb_retcode != NRC_GOODRET ) {
+ printf( "AddGroupname 0x%x returned an error %lx\n", Suffix,
+ pncb->ncb_retcode);
+ return;
+ }
+}
+
+// Registe a session.
+void RegisteWkgroupName (LPTSTR lpTransportName,
+ CHAR * pDomainName,
+ PSUPER_NCB psuperncb,
+ INT nIndex)
+{
+ CHAR localName[16];
+
+ printf ("Running Netbios on transport %s, domain %s...\n", toansi(lpTransportName), pDomainName);
+
+ strcpy (psuperncb->pTransportName, toansi(lpTransportName));
+
+ strcpy (psuperncb->pDomainName, pDomainName);
+
+ psuperncb->nIndex = nIndex;
+
+ psuperncb->ncb.ncb_lana_num = psuperncb->lanaNumber;
+
+ // Jam in Domain announcement name
+ strcpy (&localName[2], "__MSBROWSE__");
+ localName[0] = 0x01;
+ localName[1] = 0x02;
+ localName[14] = 0x02;
+ localName[15] = 0x01;
+
+ RtlCopyMemory (psuperncb->ncb.ncb_name, localName, 16);
+ psuperncb->ncb.ncb_command = NCBADDGRNAME;
+ psuperncb->ncb.ncb_lana_num = psuperncb->lanaNumber;
+ Netbios ((NCB *) psuperncb);
+
+ if (psuperncb->ncb.ncb_retcode != NRC_GOODRET) {
+ printf("AddGroupname MSBROUSE returned an error %lx\n", psuperncb->ncb.ncb_retcode);
+ }
+
+ psuperncb->nameNumber = psuperncb->ncb.ncb_num;
+
+}
+
+// This is the function which calls Netbios.
+void SubmitRCDg (PSUPER_NCB psuperncb)
+{
+ ClearNcb ((NCB *) psuperncb);
+
+ psuperncb->ncb.ncb_command = NCBDGRECV|ASYNCH;
+ psuperncb->ncb.ncb_lana_num = (UCHAR)psuperncb->lanaNumber;
+ psuperncb->ncb.ncb_num = psuperncb->nameNumber;
+ psuperncb->ncb.ncb_length = BUFFERLENGTH;
+ psuperncb->ncb.ncb_buffer = psuperncb->Buffer;
+ psuperncb->ncb.ncb_post = RCDgPost;
+ Netbios ((NCB *) psuperncb);
+}
+
+// Netbios's call back function.
+void RCDgPost (NCB * pncb)
+{
+ PSUPER_NCB psuperncb = (PSUPER_NCB) pncb;
+
+ if (pncb->ncb_retcode != NRC_GOODRET)
+ {
+ printf ("ReceiveDatagram returned an error %lx\n", pncb->ncb_retcode);
+ if (pncb->ncb_retcode != NRC_INCOMP)
+ {
+ return;
+ }
+ }
+
+ LoadWorkQueue (psuperncb);
+
+ SubmitRCDg(psuperncb);
+}
+
+// This is the function get entries from the queue and print out the content.
+void ProcessQueue(FILE * pFile, INT nFileSizeLimit)
+{
+ PQUEUE_ENTRY pBuffer;
+ struct _stat buf;
+ BOOL fRet;
+
+ if (_fstat (_fileno(pFile), &buf) != -1)
+ {
+ if (buf.st_size > nFileSizeLimit)
+ {
+ fflush (pFile);
+
+ fclose (pFile);
+
+ fRet = MoveFileEx (szLOGFILE, szBACKUP, MOVEFILE_REPLACE_EXISTING);
+ if (!fRet)
+ {
+ pFile = fopen (szBWATCH, "w+");
+ ReportError (GetLastError());
+ }
+ else
+ pFile = fopen (szBWATCH, "w+");
+ }
+ }
+
+ WaitForSingleObject (hEvent, INFINITE);
+
+ while (TRUE)
+ {
+ CHAR DecodedName[20];
+
+ pBuffer = PullBufferFromQueue (&WorkQueueHead, &CSWorkQueue);
+
+ if (pBuffer == NULL)
+ {
+ return;
+ }
+
+ DecodeName (DecodedName, pBuffer->ncb_callname);
+
+ DecodeSmb (pFile, DecodedName, pBuffer);
+
+ PutBufferOnQueue (&FreeQueueHead, pBuffer, &CSFreeQueue);
+ }
+}
+
+// put the buffer returned from Netbios on the queue.
+void LoadWorkQueue (PSUPER_NCB psuperncb)
+{
+ PQUEUE_ENTRY pEntry;
+
+ // Allocate memory for pEntry.
+
+ pEntry = PullBufferFromQueue (&FreeQueueHead, &CSFreeQueue);
+
+ if (pEntry == NULL)
+ {
+ pEntry = (PQUEUE_ENTRY) LocalAlloc (LPTR, sizeof(*pEntry));
+ if (pEntry == NULL)
+ {
+ return;
+ }
+ }
+
+ GetLocalTime (&pEntry->systime);
+
+ strcpy (pEntry->ncb_callname, psuperncb->ncb.ncb_callname);
+ memcpy (pEntry->ncb_buffer, psuperncb->ncb.ncb_buffer, BUFFERLENGTH);
+ strcpy (pEntry->pTransportName, psuperncb->pTransportName);
+ strcpy (pEntry->pDomainName, psuperncb->pDomainName);
+ pEntry->nIndex = psuperncb->nIndex;
+
+ PutBufferOnQueue (&WorkQueueHead, pEntry, &CSWorkQueue);
+ SetEvent (hEvent);
+}
+
+// add a new entry to queue.
+void PutBufferOnQueue (PLIST_ENTRY pQueueHead,
+ PQUEUE_ENTRY pEntry,
+ CRITICAL_SECTION * pCSQueue)
+{
+ EnterCriticalSection (pCSQueue);
+
+ InsertTailList (pQueueHead, &(pEntry->List));
+
+ LeaveCriticalSection (pCSQueue);
+}
+
+// get an entry from queue.
+PQUEUE_ENTRY PullBufferFromQueue(PLIST_ENTRY pQueueHead,
+ CRITICAL_SECTION * pCSQueue)
+{
+ PQUEUE_ENTRY pEntry;
+
+ EnterCriticalSection (pCSQueue);
+
+ if (IsListEmpty (pQueueHead))
+ pEntry = NULL;
+ else
+ pEntry = (PQUEUE_ENTRY) RemoveHeadList (pQueueHead);
+
+ LeaveCriticalSection (pCSQueue);
+
+ return(pEntry);
+}
+
+
+
+// Change Netbios name into readable form: NAME(XX)
+VOID
+DecodeName(
+ LPSTR DecodedName,
+ LPSTR EncodedName
+ )
+{
+
+ CHAR TempString[6];
+ int i;
+
+ //
+ // Find first blank
+ //
+
+ for (i = 0; i < 15 ; i++) {
+ if (EncodedName[i] == ' ') {
+ break;
+ }
+ }
+
+ strncpy(DecodedName, EncodedName, i);
+ DecodedName[i] = '\0';
+ sprintf(TempString, "<%x>", EncodedName[15]);
+ strcat(DecodedName, TempString);
+
+}
+
+// Print out what's in the buffer.
+BOOL
+DecodeSmb(FILE * pFile,
+ LPSTR DecodedName,
+ PQUEUE_ENTRY pEntry)
+{
+ PBYTE Smb;
+ LPSTR MailslotName;
+ PUCHAR pPacketType;
+ PNT_SMB_HEADER pSmbHeader;
+ PREQ_TRANSACTION pSmbTransaction;
+ PBROWSE_ANNOUNCE_PACKET pBrowseAnnouncePacket;
+ PREQUEST_ELECTION pRequestElection;
+ PBECOME_BACKUP pBecomeBackup;
+ PREQUEST_ANNOUNCE_PACKET pRequestAnnouncement;
+
+ if (pEntry->nIndex != nIndex)
+ {
+ fprintf (pFile,
+ "\nTransport: %s, Domain: %s\n",
+ pEntry->pTransportName,
+ pEntry->pDomainName);
+
+ nIndex = pEntry->nIndex;
+ }
+
+ TimeStamp (pFile, &pEntry->systime);
+
+ Smb = pEntry->ncb_buffer;
+ //
+ // Decipher the SMB in the packet
+ //
+
+ pSmbHeader = (PNT_SMB_HEADER) Smb;
+ if (pSmbHeader->Protocol[0] != 0xff &&
+ pSmbHeader->Protocol[1] != 'S' &&
+ pSmbHeader->Protocol[2] != 'M' &&
+ pSmbHeader->Protocol[3] != 'B') {
+ fprintf(pFile, "Not a valid SMB header\n");
+ return(FALSE);
+ }
+ pSmbTransaction = (PREQ_TRANSACTION)
+ (Smb + sizeof(NT_SMB_HEADER));
+
+ MailslotName = (LPSTR) (pSmbTransaction->Buffer +
+ pSmbTransaction->SetupCount + 5);
+
+ if (!strcmp(MailslotName, "\\MAILSLOT\\BROWSE")) {
+ pPacketType = (PUCHAR) Smb +
+ pSmbTransaction->DataOffset;
+ switch (*pPacketType) {
+
+ case AnnouncementRequest:
+ fprintf(pFile, "Announcement request from %s. ", DecodedName);
+ pRequestAnnouncement =
+ (PREQUEST_ANNOUNCE_PACKET) pPacketType;
+ fprintf(pFile, "Reply %s\n",
+ pRequestAnnouncement->RequestAnnouncement.Reply);
+ break;
+
+ case Election:
+ fprintf(pFile, "Election request: %s ", DecodedName);
+ pRequestElection = (PREQUEST_ELECTION) pPacketType;
+ fprintf(pFile, "Version(%d) Criteria(0x%x) ",
+ pRequestElection->ElectionRequest.Version,
+ pRequestElection->ElectionRequest.Criteria);
+ fprintf(pFile, "TimeUp(%d)\n",
+ pRequestElection->ElectionRequest.TimeUp);
+ break;
+
+ case BecomeBackupServer:
+ fprintf(pFile, "BecomeBackupServer from %s ", DecodedName);
+ pBecomeBackup = (PBECOME_BACKUP) pPacketType;
+ fprintf(pFile, "to %s\n", pBecomeBackup->BecomeBackup.BrowserToPromote);
+ break;
+
+ case LocalMasterAnnouncement:
+ case WkGroupAnnouncement:
+ pBrowseAnnouncePacket =
+ (PBROWSE_ANNOUNCE_PACKET) pPacketType;
+ switch (*pPacketType) {
+ case LocalMasterAnnouncement:
+ fprintf(pFile, "LocalMasterAnnouncement from %s. ", DecodedName);
+ break;
+ case WkGroupAnnouncement:
+ fprintf(pFile, "Workgroup Announcement from %s. Domain: %s, Master %s. ", DecodedName, pBrowseAnnouncePacket->BrowseAnnouncement.ServerName, pBrowseAnnouncePacket->BrowseAnnouncement.Comment);
+ break;
+ }
+ fprintf(pFile, "UpdateCount = %d\n",
+ pBrowseAnnouncePacket->BrowseAnnouncement.UpdateCount);
+ break;
+
+ default:
+ fprintf(pFile, "\n**** Packet type %d from %s ****\n",
+ *pPacketType, DecodedName);
+ }
+ }
+ else if (strcmp(MailslotName, "\\MAILSLOT\\NET\\REPL_CLI") &&
+ strcmp(MailslotName, "\\MAILSLOT\\NET\\NTLOGON") &&
+ strcmp(MailslotName, "\\MAILSLOT\\NET\\NETLOGON") &&
+ strcmp(MailslotName, "\\MAILSLOT\\LANMAN")) {
+ fprintf(pFile, "Received an unknown datagram, name = %s\n",
+ MailslotName);
+ }
+
+ return(TRUE);
+}
+
+// Convert an unicode string to ansi string.
+LPSTR toansi(LPTSTR lpUnicode)
+{
+ static CHAR lpAnsi[BUFFERLENGTH];
+ BOOL fDummy;
+ INT i;
+
+ i = WideCharToMultiByte (CP_ACP,
+ 0,
+ lpUnicode,
+ lstrlen(lpUnicode),
+ lpAnsi,
+ BUFFERLENGTH,
+ NULL,
+ &fDummy);
+
+ lpAnsi[i] = 0;
+
+ return(lpAnsi);
+}
+
+// Get Domains from bwatch.ini.
+BOOL GetDomain (CHAR * pDomain)
+{
+ DWORD dwVal;
+
+ // Read all the domains that we want to check from bchk.ini
+ dwVal = GetPrivateProfileStringA (szAPPNAME,
+ szDOMAINS,
+ szDefaultDomain,
+ pDomain,
+ BUFFERLENGTH,
+ szFILENAME);
+
+ if (dwVal >= (BUFFERLENGTH-2)) // The memory assigned to lpDomainList is not big enough.
+ {
+ printf ("ERROR_NOT_ENOUGH_MEMORY");
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+INT GetLimit ()
+{
+ DWORD dwVal;
+ CHAR pTemp[10];
+ INT nFileSizeLimit;
+
+ // Read all the domains that we want to check from bchk.ini
+ dwVal = GetPrivateProfileStringA (szAPPNAME,
+ szFILESIZELIMIT,
+ szDefaultFileSizeLimit,
+ pTemp,
+ 10,
+ szFILENAME);
+
+ if (dwVal >= (BUFFERLENGTH-2)) // The memory assigned to lpDomainList is not big enough.
+ {
+ printf ("ERROR_NOT_ENOUGH_MEMORY");
+ return(atoi(szDefaultFileSizeLimit));
+ }
+
+ return(atoi(pTemp));
+}
+
+// Copied from ..\client\browstub.c.
+NET_API_STATUS GetBrowserTransportList (OUT PLMDR_TRANSPORT_LIST *TransportList)
+{
+
+ NET_API_STATUS Status;
+ HANDLE BrowserHandle;
+ LMDR_REQUEST_PACKET RequestPacket;
+
+ Status = OpenBrowser(&BrowserHandle);
+
+ if (Status != NERR_Success) {
+ return Status;
+ }
+
+ RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION;
+
+ RequestPacket.Type = EnumerateXports;
+
+ RtlInitUnicodeString(&RequestPacket.TransportName, NULL);
+ RtlInitUnicodeString(&RequestPacket.EmulatedDomainName, NULL);
+
+ Status = DeviceControlGetInfo(
+ BrowserHandle,
+ IOCTL_LMDR_ENUMERATE_TRANSPORTS,
+ &RequestPacket,
+ sizeof(RequestPacket),
+ (PVOID *)TransportList,
+ 0xffffffff,
+ 4096,
+ NULL);
+
+ NtClose(BrowserHandle);
+
+ return Status;
+}
+
+// Print out the header line in the log file.
+void PrintHeader (FILE * pFile)
+{
+ fprintf(pFile, "**********************************************\n");
+ fprintf(pFile, "******************* BWATCH *******************\n");
+ fprintf(pFile, "**********************************************\n");
+}
+
+// Print out the time in the log file.
+void TimeStamp (FILE * pFile, SYSTEMTIME * psystime)
+{
+ fprintf (pFile,
+ "%d:%d:%d ",
+ psystime->wHour,
+ psystime->wMinute,
+ psystime->wSecond);
+}