Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2093 lines
61 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. servencb.c
  5. Abstract:
  6. Routines to service completed NCB's. This file contains the following
  7. functions:
  8. MsgCallNetBios
  9. MsgDeleteName
  10. MsgGetMachineName
  11. MsgHangupService
  12. MsgListenService
  13. Msgmblockbeg
  14. Msgmblockend
  15. Msgmblocktxt
  16. MsgNetBiosError
  17. MsgRecBcastService
  18. MsgReceiveService
  19. MsgRestart
  20. Msgsblockmes
  21. MsgSendAck
  22. MsgSendService
  23. MsgServeNCBs
  24. MsgSesFullService
  25. MsgStartListen
  26. MsgStartRecBcast
  27. MsgVerifySmb
  28. Author:
  29. Dan Lafferty (danl) 15-Jul-1991
  30. Environment:
  31. User Mode -Win32
  32. Revision History:
  33. 19-Aug-1997 wlees
  34. Add PNP support for lana's
  35. 27-Jul-1994 danl
  36. MsgServeNCBs: This function now returns FALSE when the service
  37. is to shut down.
  38. 29-May-1992 danl
  39. MsgListenService: reset the NRC_NORES error count when a good
  40. return code accompanies the Listen completion.
  41. 18-Feb-1992 ritaw
  42. Convert to Win32 service control APIs.
  43. 15-Jul-1991 danl
  44. Ported from LM2.0
  45. --*/
  46. //
  47. // SMB translation
  48. //
  49. //
  50. // OLD NEW
  51. // SMB SMB_HEADER or PSMB_HEADER
  52. // -------- -------------------------
  53. // smb_idf Protocol
  54. // smb_com Command
  55. // smb_rcls ErrorClass
  56. // smb_reh Reserved
  57. // smb_err Error
  58. // smb_flg Flags
  59. // smb_flag2 Flags2
  60. // smb_res Reserved2
  61. // smb_gid Tid
  62. // smb_tid Pid
  63. // smb_pid Uid
  64. // smb_uid Mid
  65. // smb_mid Kludge
  66. //
  67. // Includes
  68. //
  69. #include "msrv.h"
  70. #include <tstring.h> // Unicode string macros
  71. #include <string.h> // memcpy
  72. #include <netdebug.h> // NetpAssert
  73. #include <lmerrlog.h> // NELOG_ messages
  74. #include <netlib.h> // UNUSED macro
  75. #include <smbtypes.h> // needed for smb.h
  76. #include <smb.h> // Server Message Block definitions
  77. #include <smbgtpt.h> // SMB field manipulation macros
  78. //#include <msgrutil.h> // NetpNetBiosReset
  79. #include <nb30.h> // NRC_GOODRET, ASYNC
  80. #include "msgdbg.h" // MSG_LOG
  81. #include "heap.h"
  82. #include "msgdata.h"
  83. #include "apiutil.h" // MsgMapNetError
  84. #define MAX_RETRIES 10
  85. //
  86. // Local Functions
  87. //
  88. STATIC NET_API_STATUS
  89. MsgCallNetBios(
  90. DWORD net,
  91. PNCB ncb,
  92. DWORD ncbi
  93. );
  94. STATIC VOID
  95. MsgDeleteName(
  96. DWORD net,
  97. DWORD ncbi
  98. );
  99. STATIC VOID
  100. MsgGetMachineName(
  101. DWORD net,
  102. DWORD ncbi
  103. );
  104. STATIC VOID
  105. MsgHangupService(
  106. DWORD net,
  107. DWORD ncbi,
  108. CHAR retval
  109. );
  110. STATIC VOID
  111. MsgListenService(
  112. DWORD net,
  113. DWORD ncbi,
  114. CHAR retval
  115. );
  116. STATIC VOID
  117. Msgmblockbeg(
  118. DWORD net,
  119. DWORD ncbi
  120. );
  121. STATIC VOID
  122. Msgmblockend(
  123. DWORD net,
  124. DWORD ncbi
  125. );
  126. STATIC VOID
  127. Msgmblocktxt(
  128. DWORD net,
  129. DWORD ncbi
  130. );
  131. STATIC DWORD
  132. MsgNetBiosError(
  133. DWORD net,
  134. PNCB ncb,
  135. char retval,
  136. DWORD ncbi
  137. );
  138. STATIC VOID
  139. MsgReceiveService(
  140. DWORD net,
  141. DWORD ncbi,
  142. char retval
  143. );
  144. STATIC VOID
  145. MsgRestart(
  146. DWORD net,
  147. DWORD ncbi
  148. );
  149. STATIC VOID
  150. Msgsblockmes(
  151. DWORD net,
  152. DWORD ncbi
  153. );
  154. STATIC VOID
  155. MsgSendAck(
  156. DWORD net,
  157. DWORD ncbi,
  158. UCHAR smbrclass,
  159. USHORT smbrcode
  160. );
  161. STATIC VOID
  162. MsgSendService(
  163. DWORD net,
  164. DWORD ncbi,
  165. CHAR retval
  166. );
  167. STATIC VOID
  168. MsgSesFullService(
  169. DWORD net,
  170. DWORD ncbi,
  171. char retval
  172. );
  173. STATIC int
  174. MsgVerifySmb(
  175. DWORD net,
  176. DWORD ncbi,
  177. UCHAR func,
  178. int parms,
  179. char *buffers
  180. );
  181. #if DBG
  182. VOID
  183. MsgDumpNcb(
  184. IN PNCB pNcb
  185. );
  186. #endif //DBG
  187. /*
  188. * MsgCallNetBios - issue a net bios call
  189. *
  190. * This function issues a net bios call and calls the
  191. * error handler if that call results in an error.
  192. *
  193. * MsgCallNetBios (net, ncb, ncbi)
  194. *
  195. * ENTRY
  196. * net - network index
  197. * ncb - pointer to a Network Control Block
  198. * ncbi - index of ncb in ncb array
  199. *
  200. * RETURN
  201. * state of the Messenger: Either RUNNING or STOPPING.
  202. *
  203. * SIDE EFFECTS
  204. *
  205. * Calls NetBios() to actually issue the net bios call.
  206. * Calls MsgNetBiosError() if there is an error.
  207. */
  208. STATIC NET_API_STATUS
  209. MsgCallNetBios(
  210. DWORD net, // Which network?
  211. PNCB ncb, // Pointer to Network Control Block
  212. DWORD ncbi
  213. )
  214. {
  215. int retval;
  216. PNCB_DATA pNcbData;
  217. retval = Msgsendncb(ncb, net);
  218. pNcbData = GETNCBDATA(net,ncbi);
  219. if (retval == NRC_GOODRET) {
  220. //
  221. // Clear err on success
  222. //
  223. pNcbData->Status.last_immediate = 0;
  224. pNcbData->Status.this_immediate = 0;
  225. }
  226. else {
  227. //
  228. // NEW (11-4-91):
  229. // --------------
  230. // It is ok to get a Session Closed error if the state is STOP.
  231. //
  232. if ( (pNcbData->State == MESSTOP) &&
  233. (retval == NRC_SCLOSED) ) {
  234. MSG_LOG(TRACE,"CallNetBios: At end of msg, Session is closed for NET %d\n",
  235. net);
  236. pNcbData->Status.last_immediate = 0;
  237. pNcbData->Status.this_immediate = 0;
  238. }
  239. else {
  240. //
  241. // Else mark error
  242. //
  243. pNcbData->Status.this_immediate = retval;
  244. //
  245. // Call the error handler if err
  246. //
  247. MSG_LOG(TRACE,"CallNetBios: net bios call failed 0x%x\n",retval);
  248. MsgNetBiosError(net,ncb,(char)retval,ncbi);
  249. return(MsgMapNetError((UCHAR)retval));
  250. }
  251. //
  252. // Make sure the event for this thread is in the signaled state
  253. // so that we can wake up and properly handle the error.
  254. //
  255. if (SetEvent(ncb->ncb_event) != TRUE) {
  256. MSG_LOG(ERROR,"CallNetBios: SetEvent Failed\n",0);
  257. }
  258. }
  259. return(NERR_Success);
  260. }
  261. /*
  262. * MsgDeleteName - Delete a name from the Message Server's name table
  263. *
  264. * This function is called when a LISTEN, a RECEIVE BROADCAST DATAGRAM,
  265. * or a RECEIVE ANY completes with the error code specifying that the
  266. * name in question has been deleted. This function marks the appropriate
  267. * entry in the flag table in the shared data area and sets the NCB_CPLT
  268. * field of the appropriate NCB to 0xFF (so that FindCompletedNCB() will
  269. * never find it).
  270. *
  271. * MsgDeleteName (net, ncbi)
  272. *
  273. * ENTRY
  274. * net - network index
  275. * ncbi - Network Control Block index
  276. *
  277. * RETURN
  278. * nothing
  279. *
  280. * SIDE EFFECTS
  281. *
  282. * Modifies an NCB and the shared data area.
  283. */
  284. STATIC VOID
  285. MsgDeleteName(
  286. DWORD net, // Which network?
  287. DWORD ncbi // Network Control Block index
  288. )
  289. {
  290. NCB ncb;
  291. PNCB pNcb;
  292. NET_API_STATUS status;
  293. MSG_LOG(TRACE,"In MsgDeleteName %d\n",net);
  294. if( SD_NAMEFLAGS(net,ncbi) & NFMACHNAME) {
  295. //
  296. // Name is the machine name. It may have been removed from the
  297. // card by a board reset, so try to re-add it.
  298. //
  299. // NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
  300. //
  301. // First reset the adapter
  302. //
  303. MSG_LOG1(TRACE,"Calling NetBiosReset for lana #%d\n",GETNETLANANUM(net));
  304. status = MsgsvcGlobalData->NetBiosReset(GETNETLANANUM(net));
  305. if (status != NERR_Success) {
  306. MSG_LOG(ERROR,"MsgDeleteName: NetBiosReset failed %d\n",
  307. status);
  308. MSG_LOG(ERROR,"MsgDeleteName: AdapterNum %d\n",net);
  309. //
  310. // I'm not sure what to do if this fails.
  311. //
  312. }
  313. //
  314. //
  315. // NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
  316. memcpy((char far *) ncb.ncb_name, SD_NAMES(net,ncbi),NCBNAMSZ);
  317. ncb.ncb_command = NCBADDNAME; // Add name (wait)
  318. ncb.ncb_lana_num = GETNETLANANUM(net); // Use the LANMAN adapter
  319. Msgsendncb( &ncb, net);
  320. MsgStartListen(net,ncbi);
  321. }
  322. else {
  323. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"MsgDeleteName"); // Wait for write access
  324. SD_NAMEFLAGS(net,ncbi) = NFDEL; // Name is deleted
  325. MsgDatabaseLock(MSG_RELEASE,"MsgDeleteName"); // Free lock on share table
  326. pNcb = GETNCB(net,ncbi);
  327. pNcb->ncb_cmd_cplt = 0xff; // Simulate command in progress
  328. }
  329. }
  330. /*
  331. * MsgGetMachineName - process a Get Machine Name Server Message Block
  332. *
  333. * This function sends to the caller the local machine name in
  334. * response to a Get Machine Name Server Message Block.
  335. *
  336. * MsgGetMachineName (net, ncbi)
  337. *
  338. * ENTRY
  339. * net - Network index
  340. * ncbi - Network Control Block index
  341. *
  342. * Globals used as input:
  343. *
  344. * machineName - Unicode version of the machine name.
  345. *
  346. * machineNameLen - The number of unicode characters in the machine
  347. * name.
  348. *
  349. * RETURN
  350. * nothing
  351. *
  352. * MsgGetMachineName() is called by MsgReceiveService (RecAnyService()).
  353. * After verifying that the request is valid, this function builds
  354. * an SMB containing the local machine name and sends it back to the
  355. * caller.
  356. *
  357. * SIDE EFFECTS
  358. *
  359. * Calls MsgVerifySmb() and MsgCallNetBios(). Sets MsgSendService() to be the
  360. * next service routine to be executed for the ncbi'th NCB.
  361. */
  362. STATIC VOID
  363. MsgGetMachineName(
  364. DWORD net, // Which network?
  365. DWORD ncbi // Index to NCB
  366. )
  367. {
  368. PNCB ncb; // Pointer to NCB
  369. PNCB_DATA pNcbData; // Pointer to NCB Data
  370. LPBYTE buffer; // Pointer to SMB buffer
  371. LPBYTE cp; // Save pointer
  372. PSHORT bufLen; // Pointer to buffer length field in SMB;
  373. NTSTATUS ntStatus;
  374. OEM_STRING ansiString;
  375. UNICODE_STRING unicodeString;
  376. MSG_LOG(TRACE,"In MsgGetMachineName %d\n",net);
  377. pNcbData = GETNCBDATA(net,ncbi);
  378. ncb = &pNcbData->Ncb; // Get pointer to NCB
  379. if(pNcbData->State != MESSTART) {
  380. //
  381. // If wrong time for this block
  382. //
  383. // Hang up and start a new listen,
  384. // log an error if mpncbistate[net][ncbi] == MESCONT;
  385. // otherwise, do not log the error.
  386. //
  387. if(pNcbData->State == MESCONT) {
  388. //
  389. // Log error if message in progress
  390. //
  391. Msglogmbe(MESERR,net,ncbi);
  392. }
  393. //
  394. // HANGUP and LISTEN again
  395. //
  396. MsgRestart(net,ncbi);
  397. return;
  398. }
  399. pNcbData->State = MESSTOP; // End of message state
  400. //
  401. // Check if SMB is malformed
  402. //
  403. if(MsgVerifySmb(net,ncbi,SMB_COM_GET_MACHINE_NAME,0,"") != 0) {
  404. return;
  405. }
  406. buffer = ncb->ncb_buffer; // Get pointer to buffer
  407. cp = &buffer[sizeof(SMB_HEADER)]; // Skip to end of header
  408. *cp++ = '\0'; // Return no parameters
  409. //
  410. // Length of name plus two
  411. //
  412. bufLen = (PSHORT)&cp[0];
  413. *bufLen = MachineNameLen + (SHORT)2;
  414. cp += sizeof(MachineNameLen); // Skip over buffer length field
  415. *cp++ = '\004'; // Null-terminated string next
  416. #ifdef UNICODE
  417. //
  418. // Translate the machineName from Unicode to Ansi and place it into
  419. // the buffer at the temp pointer location.
  420. //
  421. unicodeString.Length = (USHORT)(STRLEN(machineName)*sizeof(WCHAR));
  422. unicodeString.MaximumLength = (USHORT)((STRLEN(machineName)+1) * sizeof(WCHAR));
  423. unicodeString.Buffer = machineName;
  424. ansiString.Length = MachineNameLen;
  425. ansiString.MaximumLength = *bufLen;
  426. ansiString.Buffer = cp;
  427. ntStatus = RtlUnicodeStringToOemString(
  428. &ansiString,
  429. &unicodeString,
  430. FALSE); // Don't Allocate the ansiString Buffer
  431. if (!NT_SUCCESS(ntStatus)) {
  432. MSG_LOG(ERROR,
  433. "MsgGetMachineName:RtlUnicodeStringToOemString Failed rc=%X\n",
  434. ntStatus);
  435. return; // They return for other errors, so I will here too.
  436. }
  437. *(cp + ansiString.Length) = '\0';
  438. #else
  439. UNUSED(unicodeString);
  440. UNUSED(ansiString);
  441. UNUSED(ntStatus);
  442. strcpy( cp, (LPSTR)machineName); // Copy machine name
  443. #endif
  444. cp += MachineNameLen + 1; // Skip over machine name
  445. //
  446. // Set length of buffer
  447. //
  448. ncb->ncb_length = (USHORT)(cp - buffer);
  449. ncb->ncb_command = NCBSEND | ASYNCH; // Send (no wait)
  450. pNcbData->IFunc = (LPNCBIFCN)MsgSendService; // Set function pointer
  451. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  452. }
  453. /*
  454. * MsgHangupService - Service completed HANGUP net bios calls
  455. *
  456. * This function is invoked by NCBService() to process completed
  457. * HANGUP net bios calls. In response to a completed HANGUP,
  458. * this function issues a new LISTEN net bios call.
  459. *
  460. * MsgHangupService (net, ncbi, retval)
  461. *
  462. * ENTRY
  463. * net - network index
  464. * ncbi - Network Control Block index
  465. * retval - value returned from net bios call
  466. *
  467. * RETURN
  468. * nothing
  469. *
  470. * SIDE EFFECTS
  471. *
  472. * Calls MsgStartListen() to issue a new LISTEN net bios call. Calls
  473. * MsgNetBiosError() on errors it does not know how to deal with.
  474. */
  475. STATIC VOID
  476. MsgHangupService(
  477. DWORD net, // Which network
  478. DWORD ncbi, // Index of completed NCB
  479. CHAR retval // HANGUP return value
  480. )
  481. {
  482. PNCB pNcb;
  483. MSG_LOG(TRACE,"In MsgHangupService %d\n",net);
  484. switch(retval) { // Switch on return value
  485. case NRC_GOODRET: // Success
  486. case NRC_CMDTMO: // Command timed out
  487. case NRC_SCLOSED: // Session closed
  488. case NRC_SABORT: // Session ended abnormally
  489. //
  490. // BBSP - check if the name for this NCB ends in 0x3. If so,
  491. // add the 0x5 version and don't reissue the listen on the 0x03.
  492. // No need to worry about doing it on all nets, since on a machine
  493. // with more than one the 0x05 name will never leave home, and
  494. // the 0x03 version will never get a message.
  495. //
  496. MSG_LOG(TRACE," MsgHangupService: Issue a new LISTEN\n",0);
  497. MsgStartListen(net,ncbi); // Issue a new LISTEN net bios call
  498. break;
  499. default:
  500. //
  501. // Invoke error handler
  502. //
  503. MSG_LOG(TRACE," MsgHangupService: Unknown return value %x\n",retval);
  504. pNcb = GETNCB(net,ncbi);
  505. MsgNetBiosError(net,pNcb,retval,ncbi);
  506. //
  507. // BBSP - check if the name for this NCB ends in 0x3. If so,
  508. // add the 0x5 version and don't reissue the listen on the 0x03.
  509. // See note above.
  510. //
  511. MSG_LOG(TRACE," MsgHangupService: Issue a new LISTEN\n",0);
  512. MsgStartListen(net,ncbi); // Issue a new LISTEN net bios call
  513. break;
  514. }
  515. }
  516. /*
  517. * MsgListenService - service completed LISTEN net bios calls
  518. *
  519. * This function is called when a LISTEN net bios call completes
  520. * either due to an error or due to the establishment of a
  521. * session. In the latter case, it initiates message reception.
  522. *
  523. * MsgListenService (net, ncbi, retval)
  524. *
  525. * ENTRY
  526. * net - network index
  527. * ncbi - Network Control Block index
  528. * retval - value returned from NCB call
  529. *
  530. * RETURN
  531. * nothing
  532. *
  533. * If a session is established, this function issues a RECEIVE ANY
  534. * net bios call to initiate reception of a message. If the function
  535. * is invoked because the net bios call has failed due to the deletion
  536. * of a name from the local network adapter's name table, then this
  537. * function calls the routine responsible for deleting names from the
  538. * Message Server's data area. This is the mechanism by which the
  539. * NETNAME command notofies the Message Server of a deletion.
  540. *
  541. * SIDE EFFECTS
  542. *
  543. * Calls MsgCallNetBios() to issue a RECEIVE ANY net bios call. Calls
  544. * MsgDeleteName() if it is informed of the deletion of a name. Calls
  545. * MsgNetBiosError() on errors it does not know how to deal with. Sets
  546. * mpncbifun[ncbi] according to the net bios call it issues.
  547. */
  548. STATIC VOID
  549. MsgListenService(
  550. DWORD net, // Which network?
  551. DWORD ncbi, // Index of completed NCB
  552. CHAR retval // LISTEN return value
  553. )
  554. {
  555. PNCB ncb; // Pointer to completed NCB
  556. PNCB_DATA pNcbData; // Corresponding NCB data
  557. static DWORD SaveCount = 0;
  558. MSG_LOG(TRACE,"In MsgListenService %d\n",net);
  559. pNcbData = GETNCBDATA(net,ncbi);
  560. ncb = &pNcbData->Ncb; // Get pointer to completed NCB
  561. switch(retval) {
  562. case NRC_GOODRET:
  563. //
  564. // Success
  565. //
  566. //
  567. // Reset the No Resources error count if a good return code comes
  568. // in for this name.
  569. //
  570. SaveCount = 0;
  571. pNcbData->State = MESSTART; // Message start state
  572. pNcbData->IFunc = (LPNCBIFCN)MsgReceiveService;
  573. //
  574. // Set function pointer
  575. //
  576. ncb->ncb_command = NCBRECV | ASYNCH;
  577. //
  578. // Receive any (no wait)
  579. //
  580. ncb->ncb_length = BUFLEN; // Reset length of buffer
  581. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  582. break;
  583. case NRC_LOCTFUL:
  584. //
  585. // Session Table Full
  586. // Log error in system error log file
  587. //
  588. MSG_LOG(TRACE,"[%d]MsgListenService: Session Table is full\n",net);
  589. pNcbData->IFunc = (LPNCBIFCN)MsgSesFullService; // Set function pointer
  590. ncb->ncb_command = NCBDELNAME | ASYNCH; // Delete name (no wait)
  591. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  592. break;
  593. case NRC_NOWILD: // Name not found
  594. // Name not found
  595. // Name deleted between end of one session and start of next
  596. case NRC_NAMERR:
  597. //
  598. // Name was deleted
  599. //
  600. MSG_LOG(TRACE,"[%d]MsgListenService: Name was deleted for some reason\n",net);
  601. MsgDeleteName(net,ncbi); // Handle the deletion
  602. break;
  603. case NRC_NORES:
  604. //
  605. // We need to cover the case where we are adding a new name and
  606. // starting a new listen. In this case, the thread that is adding
  607. // the names will hangup and delete the name.
  608. //
  609. // So here we will sleep for a moment and then check to see if the
  610. // name is still there. If not we just return without setting
  611. // up to handle the NCB anymore. If the name is still there, then
  612. // we travel down the default path and try again.
  613. //
  614. MSG_LOG(TRACE,"[%d]No Net Resources. SLEEP FOR A WHILE\n",net);
  615. Sleep(1000);
  616. MSG_LOG(TRACE,"[%d]No Net Resources. WAKEUP\n",net);
  617. if (pNcbData->NameFlags == NFDEL)
  618. {
  619. MSG_LOG(TRACE,"[%d]MsgListenService: No Net Resources & Name Deleted\n",net);
  620. ncb->ncb_cmd_cplt = 0xff;
  621. }
  622. else
  623. {
  624. //
  625. // If a session goes away and we can't gain the resources for
  626. // it again, then we will attempt to re-connect MAX_RETRIES
  627. // times. If we still cannot connect, then the name will be
  628. // deleted.
  629. //
  630. // Don't deal with retries per net/ncbi -- if we've had
  631. // "out of resources" failures MAX_RETRIES times, odds are
  632. // the situation's not getting better even if we sleep/retry
  633. // for each individual net/ncbi combo.
  634. //
  635. if (SaveCount >= MAX_RETRIES)
  636. {
  637. //
  638. // Delete the Name
  639. //
  640. MSG_LOG(ERROR,
  641. "Out of Resources, Deleting %s\n",
  642. SD_NAMES(net,ncbi));
  643. MsgDeleteName(net,ncbi);
  644. //
  645. // Mark this as 0xff now to avoid another callback call the
  646. // next time this net/ncbi combo is hit in the loop (since that
  647. // call will simply set this value.
  648. //
  649. ncb->ncb_cmd_cplt = 0xff;
  650. //
  651. // Don't roll SaveCount back to zero until we have an NCB
  652. // completed with NRC_GOODRET in the future. This lets us
  653. // avoid rewaiting MAX_RETRIES times for every net/ncbi
  654. // combo as long as we keep getting NRC_NORES.
  655. //
  656. }
  657. else
  658. {
  659. SaveCount++;
  660. MSG_LOG(TRACE,
  661. "MsgListenService: new SaveCount = %d\n",
  662. SaveCount);
  663. }
  664. }
  665. break;
  666. case NRC_BRIDGE:
  667. //
  668. // Lana number no longer valid (network interface went away)
  669. //
  670. MSG_LOG(TRACE,"[%d] lana has become invalid\n", net);
  671. MsgNetBiosError(net, ncb, retval, ncbi);
  672. //
  673. // Indicate lana is now invalid
  674. //
  675. GETNETLANANUM(net) = 0xff;
  676. //
  677. // Mark current operation as deleted
  678. //
  679. ncb->ncb_cmd_cplt = 0xff;
  680. ncb->ncb_retcode = 0;
  681. break;
  682. default:
  683. //
  684. // Other failure
  685. //
  686. MSG_LOG(TRACE,"MsgListenService: Unrecognized retval %x\n",retval);
  687. MsgNetBiosError(net,ncb,retval,ncbi);
  688. // The listen error has been logged. Now as much as possible to
  689. // get another listen staterd. This involves performing
  690. // a HangUp for this name (which should fail but might help
  691. // to clear out the err) and then re-issuing the listen. If the
  692. // same error occurs SHUTDOWN_THRESHOLD consecutive times then
  693. // MsgNetBiosError will shut down the message server.
  694. //
  695. MsgRestart(net,ncbi); // Attempt to restart the Listen
  696. break;
  697. }
  698. }
  699. /*
  700. * Msgmblockbeg - process the header of a multi-block message
  701. *
  702. * This function acknowledges receipt of the header of a multi-block
  703. * message and initiates logging of that message.
  704. *
  705. * Msgmblockbeg (net, ncbi)
  706. *
  707. * ENTRY
  708. * net - network index
  709. * ncbi - Network Control Block index
  710. *
  711. * RETURN
  712. * nothing
  713. *
  714. * This function is called from ReceivePost() (RecAnyPost()).
  715. * It first check to see if it is appropriate for the ncbi'th
  716. * name to have received a begin-multi-block-message SMB at the
  717. * current time. It verifies the correctness of the SMB in the
  718. * ncbi'th buffer. It initiates logging of the multi-block message,
  719. * and it sends an acknowledgement to the sender of the message.
  720. *
  721. * SIDE EFFECTS
  722. *
  723. * Calls MsgRestart() to terminate the session if the SMB has arrived
  724. * at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
  725. * Calls logmbb() to begin logging. Calls MsgSendAck() to send an
  726. * acknowledgement to the sender of the message.
  727. */
  728. STATIC VOID
  729. Msgmblockbeg(
  730. DWORD net, // Which network?
  731. DWORD ncbi // Index to NCB
  732. )
  733. {
  734. PNCB ncb; // Pointer to NCB
  735. PNCB_DATA pNcbData; // Pointer to NCB Data
  736. LPBYTE buffer; // Pointer to SMB buffer
  737. LPSTR cp; // Save pointer
  738. LPSTR from; // From-name
  739. LPSTR to; // To-name
  740. MSG_LOG(TRACE,"In Msgmblockbeg %d\n",net);
  741. pNcbData = GETNCBDATA(net,ncbi);
  742. ncb = &pNcbData->Ncb; // Get pointer to NCB
  743. if(pNcbData->State != MESSTART) { // If wrong time for this block
  744. //
  745. // Hang up and start a new listen,
  746. // log an error if mpncbistate[net][ncbi] == MESCONT;
  747. // otherwise, do not log the error.
  748. //
  749. if(pNcbData->State == MESCONT) {
  750. //
  751. // Log error if message in progress
  752. //
  753. Msglogmbe(MESERR,net,ncbi);
  754. }
  755. //
  756. // HANGUP and LISTEN again
  757. //
  758. MsgRestart(net,ncbi);
  759. return;
  760. }
  761. pNcbData->State = MESCONT; // Processing multi-block message
  762. if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_START_MB_MESSAGE,0,"ss") != 0) {
  763. //
  764. // Check for malformed SMB
  765. //
  766. return;
  767. }
  768. buffer = ncb->ncb_buffer; // Get pointer to buffer
  769. from = &buffer[sizeof(SMB_HEADER) + 4]; // Save pointer to from-name
  770. to = &from[strlen(from) + 2]; // Save pointer to to-name
  771. if(Msglogmbb(from,to,net,ncbi)) { // If attempt to log header fails
  772. pNcbData->State = MESERR; // Enter error state
  773. //
  774. // Send negative acknowledgement
  775. //
  776. MsgSendAck(net,ncbi,'\002',SMB_ERR_NO_ROOM);
  777. return;
  778. }
  779. //
  780. // Indicate message received
  781. //
  782. SmbPutUshort(&(((PSMB_HEADER)buffer)->Error), (USHORT)SMB_ERR_SUCCESS);
  783. // ((PSMB_HEADER)buffer)->Error = (USHORT)SMB_ERR_SUCCESS;
  784. cp = &buffer[sizeof(SMB_HEADER)]; // Point just past header
  785. *cp++ = '\001'; // One parameter
  786. ((short UNALIGNED far *) cp)[0] = ++mgid; // Message group ID
  787. pNcbData->mgid = mgid; // Save message group i.d.
  788. ((short UNALIGNED far *) cp)[1] = 0; // No buffer
  789. ncb->ncb_length = sizeof(SMB_HEADER) + 5; // Set length of buffer
  790. ncb->ncb_command = NCBSEND | ASYNCH; // Send(no wait)
  791. //
  792. // Set function pointer & issue the net bios call
  793. //
  794. pNcbData->IFunc = (LPNCBIFCN)MsgSendService;
  795. MsgCallNetBios(net,ncb,ncbi);
  796. }
  797. /*
  798. * Msgmblockend - process end of a multi-block message
  799. *
  800. * This function acknowledges receipt of the end of a
  801. * multi-block message and terminates logging of the message.
  802. *
  803. * Msgmblockend (net, ncbi)
  804. *
  805. * ENTRY
  806. * net - network index
  807. * ncbi - Network Control Block index
  808. *
  809. * RETURN
  810. * nothing
  811. *
  812. * This function is called from ReceivePost() (RecAnyPost()).
  813. * It first check to see if it is appropriate for the ncbi'th
  814. * name to have received an end-multi-block-message SMB at the
  815. * current time. It verifies the correctness of the SMB in the
  816. * ncbi'th buffer. It terminates logging, and it sends an
  817. * acknowledgement to the sender of the message.
  818. *
  819. * SIDE EFFECTS
  820. *
  821. * Calls MsgRestart() to terminate the session if the SMB has arrived
  822. * at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
  823. * Calls logmbe() to terminate logging. Calls MsgSendAck() to send an
  824. * acknowledgement to the sender of the message.
  825. */
  826. STATIC VOID
  827. Msgmblockend(
  828. DWORD net, // Which network?
  829. DWORD ncbi // Index to NCB
  830. )
  831. {
  832. PNCB ncb; // Pointer to NCB
  833. PNCB_DATA pNcbData; // Pointer to NCB Data
  834. LPBYTE buffer; // Pointer to SMB buffer
  835. int error; // Error flag
  836. char smbrclass; // SMB return class
  837. unsigned short smbrcode; // SMB return code
  838. MSG_LOG(TRACE,"In Msgmblockend %d\n",net);
  839. pNcbData = GETNCBDATA(net,ncbi);
  840. ncb = &pNcbData->Ncb; // Get pointer to NCB
  841. if(pNcbData->State != MESCONT) { // If wrong time for this block
  842. //
  843. // Hang up and start a new listen,
  844. // no error to log since no message in progress.
  845. // HANGUP and LISTEN again
  846. //
  847. MsgRestart(net,ncbi);
  848. return;
  849. }
  850. pNcbData->State = MESSTOP; // End of message state
  851. if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_END_MB_MESSAGE,1,"") != 0) {
  852. //
  853. // If SMB is malformed, log error and return
  854. //
  855. Msglogmbe(MESERR,net,ncbi);
  856. return;
  857. }
  858. buffer = ncb->ncb_buffer; // Get pointer to buffer
  859. if(*((short UNALIGNED far *) &buffer[sizeof(SMB_HEADER) + 1]) != pNcbData->mgid) {
  860. //
  861. // If i.d. does not match
  862. //
  863. error = 1; // Error found
  864. smbrclass = '\002'; // Error return
  865. smbrcode = SMB_ERR_ERROR; // Non-specific error
  866. }
  867. else {
  868. //
  869. // Else if message group i.d. okay
  870. //
  871. error = 0; // No error found
  872. smbrclass = '\0'; // Good return
  873. smbrcode = (USHORT)SMB_ERR_SUCCESS; // Message received
  874. }
  875. MsgSendAck(net,ncbi,smbrclass,smbrcode); // Send acknowledgement
  876. if(!error) Msglogmbe(MESSTOP,net,ncbi); // Log end of message
  877. }
  878. /*
  879. * Msgmblocktxt - process text of a multi-block message
  880. *
  881. * This function acknowledges receipt of a block of text of a
  882. * multi-block message and logs that block.
  883. *
  884. * Msgmblocktxt (net, ncbi)
  885. *
  886. * ENTRY
  887. * net - Network index
  888. * ncbi - Network Control Block index
  889. *
  890. * RETURN
  891. * nothing
  892. *
  893. * This function is called from ReceivePost() (RecAnyPost()).
  894. * It first check to see if it is appropriate for the ncbi'th
  895. * name to have received a multi-block-message-text SMB at the
  896. * current time. It verifies the correctness of the SMB in the
  897. * ncbi'th buffer. It logs the text block, and it sends an
  898. * acknowledgement to the sender of the message.
  899. *
  900. * SIDE EFFECTS
  901. *
  902. * Calls MsgRestart() to terminate the session if the SMB has arrived
  903. * at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
  904. * Calls logmbt() to log the text block. Calls MsgSendAck() to send an
  905. * acknowledgement to the sender of the message.
  906. */
  907. STATIC VOID
  908. Msgmblocktxt(
  909. DWORD net, // Which network?
  910. DWORD ncbi // Index to NCB
  911. )
  912. {
  913. PNCB ncb; // Pointer to NCB
  914. PNCB_DATA pNcbData; // Pointer to NCB Data
  915. LPBYTE buffer; // Pointer to SMB buffer
  916. LPSTR cp; // Save pointer
  917. char smbrclass; // SMB return class
  918. unsigned short smbrcode; // SMB return code
  919. MSG_LOG(TRACE,"In Msgmblocktxt %d\n",net);
  920. pNcbData = GETNCBDATA(net,ncbi);
  921. ncb = &pNcbData->Ncb; // Get pointer to NCB
  922. if(pNcbData->State != MESCONT) { // If wrong time for this block
  923. //
  924. // HANGUP and start a new LISTEN.
  925. // no error to log since no message in progress.
  926. //
  927. MsgRestart(net,ncbi);
  928. return;
  929. }
  930. if(MsgVerifySmb(net,ncbi,SMB_COM_SEND_TEXT_MB_MESSAGE,1,"b") != 0) {
  931. //
  932. // If SMB is malformed
  933. //
  934. Msglogmbe(MESERR,net,ncbi); // Log error
  935. return;
  936. }
  937. buffer = ncb->ncb_buffer; // Get pointer to buffer
  938. cp = &buffer[sizeof(SMB_HEADER) + 1]; // Skip to message group i.d.
  939. if(*((short UNALIGNED far *) cp) != pNcbData->mgid) {
  940. //
  941. // If i.d. does not match
  942. //
  943. smbrclass = '\002'; // Error return
  944. smbrcode = SMB_ERR_ERROR; // Non-specific error
  945. }
  946. else if(Msglogmbt(&buffer[sizeof(SMB_HEADER) + 6], net, ncbi)) {
  947. //
  948. // Else if text cannot be logged
  949. //
  950. pNcbData->State = MESERR; // Enter error state
  951. smbrclass = '\002'; // Error return
  952. smbrcode = SMB_ERR_NO_ROOM; // No room in buffer
  953. }
  954. else {
  955. //
  956. // Else if message logged okay
  957. //
  958. smbrclass = '\0'; // Good return
  959. smbrcode = (USHORT)SMB_ERR_SUCCESS; // Message received
  960. }
  961. MsgSendAck(net,ncbi,smbrclass,smbrcode); // Send acknowledgement
  962. }
  963. /*
  964. * MsgNetBiosError - process an error returned by a net bios call
  965. *
  966. * This function performs generic error handling for
  967. * failed net bios calls. If the error is a fatal one because the error
  968. * counted exceeded the SHUTDOWN_THRESHOLD, this routine begins a forced
  969. * shutdown of the messenger. This shutdown will not complete until all
  970. * threads have woken up and returned to the main loop where the
  971. * messenger status is examined.
  972. *
  973. * MsgNetBiosError (net, ncb, retval, ncbi)
  974. *
  975. * ENTRY
  976. * net - Network index
  977. * ncb - Network Control Block pointer
  978. * retval - value returned from the net bios call
  979. * ncbi - ncb array index of ncb which resulted in this error
  980. *
  981. * RETURN
  982. * state of the Messenger: Either RUNNING or STOPPING.
  983. *
  984. * Chcks in ncbStatus array that this is not a repeated error
  985. * that has already been entered in the error log, and logs
  986. * the error.
  987. *
  988. * SIDE EFFECTS
  989. *
  990. * Calls MsgErrorLogWrite() to log errors in the Network System Error Log.
  991. * If this is a new error, the error status in the ncbStatus array for this
  992. * ncb is updated so that the same error will not be reported if it is
  993. * repeated.
  994. */
  995. STATIC DWORD
  996. MsgNetBiosError(
  997. DWORD net, // Which network?
  998. PNCB ncb, // Pointer to NCB
  999. char retval, // Error code
  1000. DWORD ncbi // Index of array causing the error
  1001. )
  1002. {
  1003. PNCB_DATA pNcbData;
  1004. //
  1005. // First check the immediate status for this ncb. If it is in error
  1006. // then this must be the error, else it is a final error code.
  1007. //
  1008. pNcbData = GETNCBDATA(net,ncbi);
  1009. if (pNcbData->Status.this_immediate != 0)
  1010. {
  1011. if(pNcbData->Status.this_immediate == pNcbData->Status.last_immediate)
  1012. {
  1013. if (++(pNcbData->Status.rep_count) >= SHUTDOWN_THRESHOLD) {
  1014. //
  1015. // The same error has occured SHUTDOWN_THRESHOLD times in
  1016. // a row. Shutdown the messenger.
  1017. //
  1018. MSG_LOG(ERROR,"MsgNetBiosError1:repeated MsgNetBiosError(ncb error) - shutting down\n",0);
  1019. return(MsgBeginForcedShutdown(
  1020. PENDING,
  1021. NERR_InternalError));
  1022. }
  1023. return(RUNNING); // Same as last error so don't report it
  1024. }
  1025. else
  1026. {
  1027. //
  1028. // This error was not the same as the last error. So just
  1029. // update the last error place holder.
  1030. //
  1031. pNcbData->Status.last_immediate =
  1032. pNcbData->Status.this_immediate;
  1033. }
  1034. }
  1035. else
  1036. {
  1037. //
  1038. // Must have been a final ret code (ncb completion code) that was
  1039. // in error.
  1040. //
  1041. if(pNcbData->Status.this_final == pNcbData->Status.last_final)
  1042. {
  1043. if (++(pNcbData->Status.rep_count) >= SHUTDOWN_THRESHOLD)
  1044. {
  1045. MSG_LOG(ERROR,"MsgNetBiosError2:repeated MsgNetBiosError (final ret code) - shutting down\n",0);
  1046. return(MsgBeginForcedShutdown(
  1047. PENDING,
  1048. NERR_InternalError));
  1049. }
  1050. return(RUNNING); // Same as last error so don't report it
  1051. }
  1052. else
  1053. {
  1054. pNcbData->Status.last_final = pNcbData->Status.this_final;
  1055. }
  1056. }
  1057. //
  1058. // Here if a new error has occured
  1059. //
  1060. MSG_LOG(ERROR,"MsgNetBiosError3:An unexpected NCB was received 0x%x\n",retval);
  1061. UNUSED(retval);
  1062. #if DBG
  1063. MsgDumpNcb(ncb);
  1064. #endif
  1065. return (RUNNING);
  1066. }
  1067. /*
  1068. * MsgReceiveService - service a completed RECEIVE net bios call
  1069. *
  1070. * This function is called to service a completed RECEIVE net
  1071. * bios call. For successful completions, it examines the data
  1072. * received to determine which of the SMB-processing functions
  1073. * should be called.
  1074. *
  1075. * MsgReceiveService (net, ncbi, retval)
  1076. *
  1077. * ENTRY
  1078. * net - network index
  1079. * ncbi - Network Control Block index
  1080. * retval - value returned by the net bios
  1081. *
  1082. * RETURN
  1083. * nothing
  1084. *
  1085. * This function dispatches SMB's received to the proper processing
  1086. * function. It also handles a number of error conditions (noted
  1087. * in the code below).
  1088. *
  1089. * SIDE EFFECTS
  1090. *
  1091. * See handling of error conditions.
  1092. */
  1093. STATIC VOID
  1094. MsgReceiveService(
  1095. DWORD net, // Which network?
  1096. DWORD ncbi, // Index to completed NCB
  1097. char retval // SEND return value
  1098. )
  1099. {
  1100. PNCB ncb; // Pointer to completed NCB
  1101. PNCB_DATA pNcbData; // Pointer to NCB Data
  1102. PSMB_HEADER smb; // Pointer to SMB header
  1103. MSG_LOG(TRACE,"In MsgReceiveService %d\n",net);
  1104. pNcbData = GETNCBDATA(net,ncbi);
  1105. ncb = &pNcbData->Ncb; // Get pointer to NCB
  1106. switch(retval) {
  1107. case NRC_GOODRET: // Success
  1108. if(ncb->ncb_length >= sizeof(SMB_HEADER)) {
  1109. //
  1110. // If we could have an SMB
  1111. //
  1112. smb = (PSMB_HEADER)ncb->ncb_buffer;
  1113. // Get pointer to buffer
  1114. switch(smb->Command) { // Switch on SMB function code
  1115. case SMB_COM_SEND_MESSAGE: // Single block message
  1116. Msgsblockmes(net,ncbi);
  1117. return;
  1118. case SMB_COM_SEND_START_MB_MESSAGE: // Beginning of multi-block message
  1119. Msgmblockbeg(net,ncbi);
  1120. return;
  1121. case SMB_COM_SEND_END_MB_MESSAGE: // End of multi-block message
  1122. Msgmblockend(net,ncbi);
  1123. return;
  1124. case SMB_COM_SEND_TEXT_MB_MESSAGE: // Text of multi-block message
  1125. Msgmblocktxt(net,ncbi);
  1126. return;
  1127. case SMB_COM_GET_MACHINE_NAME: // Get Machine Name
  1128. MsgGetMachineName(net,ncbi);
  1129. return;
  1130. case SMB_COM_FORWARD_USER_NAME: // Add forward-name
  1131. //
  1132. // Not supported in NT.
  1133. // for now fall through as if unrecognized SMB.
  1134. //
  1135. case SMB_COM_CANCEL_FORWARD: // Delete forward-name
  1136. //
  1137. // Not supported in NT.
  1138. // for now fall through as if unrecognized SMB.
  1139. //
  1140. default: // Unrecognized SMB
  1141. break;
  1142. }
  1143. }
  1144. if(pNcbData->State == MESCONT) {
  1145. //
  1146. // If middle of multi-block message, Log an error
  1147. //
  1148. Msglogmbe(MESERR,net,ncbi);
  1149. }
  1150. MSG_LOG(ERROR,"MsgReceiveService:An illegal SMB was received\n",0);
  1151. //
  1152. // HANGUP and LISTEN again
  1153. //
  1154. MsgRestart(net,ncbi);
  1155. break;
  1156. case NRC_CMDTMO: // Command timed out
  1157. if(pNcbData->State == MESCONT) {
  1158. //
  1159. // If middle of multi-block message
  1160. //
  1161. Msglogmbe(MESERR,net,ncbi); // Log an error
  1162. }
  1163. //
  1164. // HANGUP and start new LISTEN
  1165. //
  1166. MsgRestart(net,ncbi);
  1167. break;
  1168. case NRC_SCLOSED: // Session closed
  1169. case NRC_SABORT: // Session ended abnormally
  1170. if(pNcbData->State == MESCONT) {
  1171. //
  1172. // If middle of multi-block message, Log an error
  1173. //
  1174. Msglogmbe(MESERR,net,ncbi);
  1175. }
  1176. //
  1177. // Start a new LISTEN
  1178. //
  1179. MsgStartListen(net,ncbi);
  1180. break;
  1181. default: // Other errors
  1182. MSG_LOG(TRACE,"MsgReceiveService: Unrecognized retval %x\n",retval);
  1183. MsgNetBiosError(net,ncb,retval,ncbi);
  1184. if(pNcbData->State == MESCONT) {
  1185. //
  1186. // If middle of multi-block message, Log an error
  1187. //
  1188. Msglogmbe(MESERR,net,ncbi);
  1189. }
  1190. MsgRestart(net,ncbi); // HANGUP and LISTEN again
  1191. break;
  1192. }
  1193. }
  1194. /*
  1195. * MsgRestart - issue a HANGUP net bios call
  1196. *
  1197. * This function is invoked to issue a HANGUP net bios call using
  1198. * a particular Network Control Block.
  1199. *
  1200. * MsgRestart (net, ncbi)
  1201. *
  1202. * ENTRY
  1203. * net - network index
  1204. * ncbi - Network Control Block index
  1205. *
  1206. * RETURN
  1207. * nothing
  1208. *
  1209. * This function assumes that the NCB_LSN, NCB_POST, and NCB_LANA
  1210. * fields of the Network Control Block are already properly set.
  1211. * It sets the NCB_CMD field.
  1212. *
  1213. * This function is named "MsgRestart" since the very next routine
  1214. * to process the NCB used to issue the HANGUP should be
  1215. * MsgHangupService() which always invokes MsgStartListen() (assuming
  1216. * the HANGUP completes properly). Thus, the net effect of
  1217. * calling MsgRestart() is to terminate the current session and
  1218. * issue a LISTEN to start a new one.
  1219. *
  1220. * SIDE EFFECTS
  1221. *
  1222. * Calls MsgCallNetBios() to issue the net bios call. Sets mpncbifun[ncbi]
  1223. * to the address of MsgHangupService().
  1224. */
  1225. STATIC VOID
  1226. MsgRestart(
  1227. DWORD net, // Which network?
  1228. DWORD ncbi // Index to NCB
  1229. )
  1230. {
  1231. PNCB ncb; // Pointer to Network Control Block
  1232. PNCB_DATA pNcbData; // Pointer to NCB Data
  1233. MSG_LOG(TRACE,"In MsgRestart %d\n",net);
  1234. pNcbData = GETNCBDATA(net,ncbi);
  1235. ncb = &pNcbData->Ncb;
  1236. pNcbData->IFunc = (LPNCBIFCN)MsgHangupService; // Set function pointer
  1237. ncb->ncb_command = NCBHANGUP | ASYNCH; // Hang up (no wait)
  1238. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  1239. }
  1240. /*
  1241. * Msgsblockmes - process a single block message
  1242. *
  1243. * This function logs and acknowledges a single block message.
  1244. *
  1245. * Msgsblockmes (net, ncbi)
  1246. *
  1247. * ENTRY
  1248. * net - network index
  1249. * ncbi - Network Control Block index
  1250. *
  1251. * RETURN
  1252. * nothing
  1253. *
  1254. * This function is called from ReceivePost() (RecAnyPost()).
  1255. * It first check to see if it is appropriate for the ncbi'th
  1256. * name to have received a single block message SMB at the current
  1257. * time. It verifies the correctness of the SMB in the ncbi'th
  1258. * buffer. It attempts to log the single block message, and it
  1259. * sends an acknowledgement to the sender of the message.
  1260. *
  1261. * SIDE EFFECTS
  1262. *
  1263. * Calls MsgRestart() to terminate the session if the SMB has arrived
  1264. * at a bad time. Calls MsgVerifySmb() to check the SMB for correctness.
  1265. * Calls logsbm() to log the message. Calls MsgSendAck() to send an
  1266. * acknowledgement to the sender of the message.
  1267. */
  1268. STATIC VOID
  1269. Msgsblockmes(
  1270. DWORD net, // Which network ?
  1271. DWORD ncbi // Index to NCB
  1272. )
  1273. {
  1274. PNCB ncb; // Pointer to NCB
  1275. PNCB_DATA pNcbData; // Pointer to NCB
  1276. LPBYTE buffer; // Pointer to SMB buffer
  1277. LPSTR cp; // Save pointer
  1278. LPSTR from; // From-name
  1279. LPSTR to; // To-name
  1280. // to browse the SessionId List :
  1281. PMSG_SESSION_ID_ITEM pItem; // item in the list
  1282. PLIST_ENTRY pHead; // head of the list
  1283. PLIST_ENTRY pList; // list pointer
  1284. DWORD bError = 0; // error flag
  1285. MSG_LOG(TRACE,"In Msgsblockmes %d\n",net);
  1286. pNcbData = GETNCBDATA(net,ncbi);
  1287. ncb = &pNcbData->Ncb; // Get pointer to NCB
  1288. if(pNcbData->State != MESSTART) {
  1289. //
  1290. // If wrong time for this block
  1291. // Hang up and start a new listen,
  1292. // log an error if mpncbistate[net][ncbi] == MESCONT;
  1293. // otherwise, do not log the error.
  1294. //
  1295. // Log error if message in progress
  1296. //
  1297. if(pNcbData->State == MESCONT) {
  1298. Msglogmbe(MESERR,net,ncbi);
  1299. }
  1300. //
  1301. // HANGUP and LISTEN again
  1302. //
  1303. MsgRestart(net,ncbi);
  1304. return;
  1305. }
  1306. pNcbData->State = MESSTOP; // End of message state
  1307. //
  1308. // Check for malformed SMB
  1309. //
  1310. if(MsgVerifySmb(net,ncbi,(unsigned char)SMB_COM_SEND_MESSAGE,0,"ssb") != 0) {
  1311. return;
  1312. }
  1313. buffer = ncb->ncb_buffer; // Get pointer to buffer
  1314. from = &buffer[sizeof(SMB_HEADER) + 4]; // Save pointer to from-name
  1315. to = &from[strlen(from) + 2]; // Save pointer to to-name
  1316. cp = &to[strlen(to) + 2]; // Skip over the name
  1317. if (g_IsTerminalServer)
  1318. {
  1319. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"Msgsblockmes");
  1320. pHead = &(SD_SIDLIST(net,ncbi));
  1321. pList = pHead;
  1322. while (pList->Flink != pHead) // loop all over the list
  1323. {
  1324. pList = pList->Flink;
  1325. pItem = CONTAINING_RECORD(pList, MSG_SESSION_ID_ITEM, List);
  1326. bError = Msglogsbm(from,to,cp, pItem->SessionId);
  1327. if (bError)
  1328. {
  1329. break;
  1330. }
  1331. }
  1332. MsgDatabaseLock(MSG_RELEASE,"Msgsblockmes");
  1333. }
  1334. else //regular NT
  1335. {
  1336. bError = Msglogsbm(from,to,cp,0);
  1337. }
  1338. if (bError)
  1339. {
  1340. //
  1341. // If message cannot be logged, enter error state
  1342. // and send error acknowledgement.
  1343. //
  1344. pNcbData->State = MESERR;
  1345. MsgSendAck(net,ncbi,'\002',SMB_ERR_NO_ROOM);
  1346. }
  1347. else
  1348. {
  1349. //
  1350. // Otherwise acknowledge success
  1351. //
  1352. MsgSendAck(net, ncbi, SMB_ERR_SUCCESS, (USHORT)SMB_ERR_SUCCESS);
  1353. }
  1354. }
  1355. /*
  1356. * MsgSendAck - send an SMB to acknowledge a network transaction
  1357. *
  1358. * This function is used to send a Server Message Block to some
  1359. * machine with whom a session has been established acknowledging
  1360. * (positively or negatively) the occurrence of some event pertaining
  1361. * to the session.
  1362. *
  1363. * MsgSendAck (net, ncbi, smbrclass, smbrcode)
  1364. *
  1365. * ENTRY
  1366. * net - Network index
  1367. * ncbi - Network Control Block index
  1368. * smbrclass - SMB return class
  1369. * smbrcode - SMB return code
  1370. *
  1371. * RETURN
  1372. * nothing
  1373. *
  1374. * Using the NCB index to locate the buffer containing the last SMB
  1375. * received in the session, this function sets the return class and
  1376. * the return code in that SMB according to its arguments and sends
  1377. * the SMB to the other party in the session. This function will
  1378. * not return any parameters or buffers in that SMB.
  1379. *
  1380. * SIDE EFFECTS
  1381. *
  1382. * This function calls MsgCallNetBios() to send the SMB, and it sets
  1383. * the function vector so that control will pass to Send Service()
  1384. * when the NCB completes (assuming, of course, that it doesn't
  1385. * fail immediately).
  1386. */
  1387. STATIC VOID
  1388. MsgSendAck(
  1389. DWORD net, // Which network?
  1390. DWORD ncbi, // Network Control Block Index
  1391. UCHAR smbrclass, // SMB return class
  1392. USHORT smbrcode // SMB return code
  1393. )
  1394. {
  1395. PNCB ncb; // Pointer to NCB
  1396. PNCB_DATA pNcbData; // Pointer to NCB Data
  1397. LPBYTE buffer; // Pointer to buffer
  1398. MSG_LOG(TRACE,"In MsgSendAck %d\n",net);
  1399. pNcbData = GETNCBDATA(net,ncbi);
  1400. ncb = &pNcbData->Ncb; // Get pointer to NCB
  1401. buffer = ncb->ncb_buffer; // Get pointer to buffer
  1402. //
  1403. // No parameters, buffers
  1404. //
  1405. buffer[sizeof(SMB_HEADER)+2]=
  1406. buffer[sizeof(SMB_HEADER)+1]=
  1407. buffer[sizeof(SMB_HEADER)]= '\0';
  1408. //
  1409. // Set return information
  1410. //
  1411. ((PSMB_HEADER)buffer)->ErrorClass = smbrclass; // Set return class
  1412. SmbPutUshort( &(((PSMB_HEADER)buffer)->Error),smbrcode);// Set return code
  1413. // ((PSMB_HEADER)buffer)->Error = smbrcode; // Set return code
  1414. ncb->ncb_length = sizeof(SMB_HEADER) + 3; // Set length of buffer
  1415. ncb->ncb_command = NCBSEND | ASYNCH; // Send (no wait)
  1416. pNcbData->IFunc = (LPNCBIFCN)MsgSendService; // Set function pointer
  1417. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  1418. }
  1419. /*
  1420. * MsgSendService - service a completed SEND net bios call
  1421. *
  1422. * This function is called to service a completed SEND net bios
  1423. * call. The usual course of action is to issue a RECEIVE (ANY)
  1424. * net bios call.
  1425. *
  1426. * MsgSendService (net, ncbi, retval)
  1427. *
  1428. * ENTRY
  1429. * net - network index
  1430. * ncbi - Network Control Block index
  1431. * retval - value returned by net bios
  1432. *
  1433. * RETURN
  1434. * nothing
  1435. *
  1436. * If a SEND net bios call has completed successfully, this function
  1437. * will issue a RECEIVE (ANY) net bios call in all cases. The com-
  1438. * pleted SEND represents one of the following cases:
  1439. *
  1440. * - Acknowledgement of a Single Block Message
  1441. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1442. * - Acknowledgement of the start of a Multi-block Message
  1443. * The message originator will SEND a text block, completing the RECEIVE
  1444. * (ANY) call.
  1445. * - Acknowledgement of text of a Multi-block Message
  1446. * The message originator will SEND more text or the end of the message,
  1447. * completing the RECEIVE (ANY) call.
  1448. * - Acknowledgement of the end of a Multi-block Message
  1449. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1450. * - Response to a Get Machine Name request
  1451. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1452. * - Acknowledgement of a Forward Name request
  1453. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1454. * - Acknowledgement of a Cancel Forward request
  1455. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1456. * - An error response
  1457. * The message originator will HANG UP, completing the RECEIVE (ANY) call.
  1458. *
  1459. * In all cases, it is clear to the RECEIVE (ANY) service function what its
  1460. * course of action is.
  1461. *
  1462. * SIDE EFFECTS
  1463. *
  1464. * If a SEND has completed normally, this function issues a RECEIVE (ANY)
  1465. * net bios call. In some abnormal cases, this function calls MsgStartListen()
  1466. * to initiate a new session. In all other abnormal cases, it calls
  1467. * MsgNetBiosError().
  1468. */
  1469. STATIC VOID
  1470. MsgSendService(
  1471. DWORD net, // Which network?
  1472. DWORD ncbi, // Index of completed NCB
  1473. char retval // SEND return value
  1474. )
  1475. {
  1476. PNCB ncb; // Pointer to completed NCB
  1477. PNCB_DATA pNcbData; // Pointer to NCB Data
  1478. PSMB_HEADER smb; // Pointer to SMB header
  1479. MSG_LOG(TRACE,"In MsgSendService %d\n",net);
  1480. pNcbData = GETNCBDATA(net,ncbi);
  1481. ncb = &pNcbData->Ncb; // Get pointer to completed NCB
  1482. switch(retval) {
  1483. case NRC_GOODRET: // Success
  1484. pNcbData->IFunc = (LPNCBIFCN)MsgReceiveService;
  1485. //
  1486. // Set function pointer
  1487. //
  1488. ncb->ncb_command = NCBRECV | ASYNCH; // Receive (no wait)
  1489. ncb->ncb_length = BUFLEN; // Set length of buffer
  1490. MsgCallNetBios(net,ncb,ncbi); // Issue the net bios call
  1491. break;
  1492. case NRC_CMDTMO: // Timeout
  1493. case NRC_SCLOSED: // Session closed
  1494. case NRC_SABORT: // Session ended abnormally
  1495. smb = (PSMB_HEADER)ncb->ncb_buffer; // Get pointer to SMB
  1496. if(smb->Command == SMB_COM_SEND_START_MB_MESSAGE || smb->Command == SMB_COM_SEND_TEXT_MB_MESSAGE) {
  1497. //
  1498. // Message ended abnormally
  1499. //
  1500. Msglogmbe(MESERR,net,ncbi);
  1501. }
  1502. //
  1503. // Issue a new LISTEN
  1504. //
  1505. MsgStartListen(net,ncbi);
  1506. break;
  1507. default: // Other failure
  1508. MSG_LOG(TRACE,"MsgSendService: Unrecognized retval %x\n",retval);
  1509. MsgNetBiosError(net,ncb,retval,ncbi);
  1510. //
  1511. // HANGUP and LISTEN again
  1512. //
  1513. MsgRestart(net,ncbi);
  1514. break;
  1515. }
  1516. }
  1517. /*
  1518. * MsgServeNCBs - service completed Network Control Blocks
  1519. *
  1520. * This function scans the array of NCB's looking for NCB's in
  1521. * need of service.
  1522. *
  1523. * MsgServeNCBs (net)
  1524. *
  1525. * ENTRY
  1526. * net - network to service NCBs on
  1527. *
  1528. * RETURN
  1529. * TRUE - If this function actually services a completed NCB.
  1530. * FALSE - If this function didn't find any completed NCB's, or if
  1531. * the service is supposed to stop.
  1532. *
  1533. * This function scans the array of NCB's until a completed NCB cannot be
  1534. * found. Each time a completed NCB is found, the service function specified
  1535. * in the service function vector (mpncbifun[]) is called to service that
  1536. * NCB.
  1537. *
  1538. * SIDE EFFECTS
  1539. *
  1540. * Maintains a private static index of the last NCB examined.
  1541. * Starts each search at first NCB after the last one serviced.
  1542. */
  1543. BOOL
  1544. MsgServeNCBs(
  1545. DWORD net // Which network am I serving?
  1546. )
  1547. {
  1548. PNCB pNcb;
  1549. PNCB_DATA pNcbData;
  1550. int counter; // A counter
  1551. BOOL found = FALSE; // Indicates if a completed NCB was found.
  1552. // Bugfix: each net has its own index, addressing
  1553. // its part NCB array. All index values are initiliazed to zero
  1554. // when the messenger starts. This solves the muti thread
  1555. // problem.
  1556. static int ncbIndexArray[MSNGR_MAX_NETS] = {0};
  1557. // NCB index array
  1558. DWORD ncbi; // NCB index for this net
  1559. //
  1560. // get NCB index for this net
  1561. //
  1562. ncbi = ncbIndexArray[net];
  1563. //
  1564. // Loop until none completed found
  1565. //
  1566. do {
  1567. //
  1568. // Loop to search NCB array
  1569. //
  1570. for(counter = NCBMAX(net); counter != 0; --counter, ++ncbi) {
  1571. if(ncbi >= NCBMAX(net)) {
  1572. ncbi = 0;// Wrap around
  1573. }
  1574. pNcbData = GETNCBDATA(net,ncbi);
  1575. pNcb = &pNcbData->Ncb;
  1576. if(pNcb->ncb_cmd_cplt != (unsigned char) 0xff) {
  1577. found=TRUE;
  1578. //
  1579. // If completed NCB found
  1580. //
  1581. if(pNcb->ncb_cmd_cplt == 0) {
  1582. //
  1583. // Clear err on success and error count
  1584. //
  1585. pNcbData->Status.last_final = 0;
  1586. pNcbData->Status.rep_count = 0;
  1587. }
  1588. else {
  1589. //
  1590. // Else mark error
  1591. //
  1592. pNcbData->Status.this_final = pNcb->ncb_cmd_cplt;
  1593. //
  1594. // If NetBios is failing with every call, we never
  1595. // return from this routine be cause there is always
  1596. // another NCB to service. Therefore, in error
  1597. // conditions it is necessary to check to see if a
  1598. // shutdown is in progress. If so, we want to return
  1599. // so that the adapter loop can handle the shutdown
  1600. // properly.
  1601. //
  1602. if (GetMsgrState() == STOPPING) {
  1603. ncbIndexArray[net] = ncbi;
  1604. return(FALSE);
  1605. }
  1606. }
  1607. //
  1608. // Call the service function
  1609. //
  1610. (*pNcbData->IFunc)(net,ncbi,pNcb->ncb_cmd_cplt);
  1611. ++ncbi; // Start next search after this NCB
  1612. break; // Exit loop
  1613. }
  1614. }
  1615. }
  1616. while(counter != 0); // Loop until counter zero
  1617. // update NCB index
  1618. ncbIndexArray[net] = ncbi;
  1619. return(found);
  1620. }
  1621. /*
  1622. * MsgSesFullService - complete deletion of a name after a system error
  1623. *
  1624. * MsgSesFullService() completes the process of deleting a name from
  1625. * the message system when the message server is unable to establish
  1626. * a session for that name.
  1627. *
  1628. * MsgSesFullService (net, ncbi, retval)
  1629. *
  1630. * ENTRY
  1631. * net - Network index
  1632. * ncbi - Network Control Block index
  1633. * retval - value returned by net bios
  1634. *
  1635. * RETURN
  1636. * nothing
  1637. *
  1638. * MsgSesFullService() is called to finish the job of cleaning up when
  1639. * a LISTEN fails because the local network adapter's session table
  1640. * is full. Specifically, this function is called when the DELETE
  1641. * NAME net bios call completes.
  1642. *
  1643. * SIDE EFFECTS
  1644. *
  1645. * Calls MsgDeleteName() to release the deleted name's entry in the
  1646. * shared data area. Calls MsgNetBiosError() if the DELETE NAME net
  1647. * bios call produced unexpected results.
  1648. */
  1649. STATIC VOID
  1650. MsgSesFullService(
  1651. DWORD net, // Which network ?
  1652. DWORD ncbi, // Index of completed NCB
  1653. char retval // SEND return value
  1654. )
  1655. {
  1656. PNCB pNcb;
  1657. MSG_LOG(TRACE,"In MsgSesFullService %d\n",net);
  1658. switch(retval) {
  1659. case NRC_GOODRET: // Success
  1660. case NRC_ACTSES: // Name deregistered
  1661. //
  1662. // Log deletion in system error log file
  1663. //
  1664. MsgDeleteName(net,ncbi); // Delete name from database
  1665. break;
  1666. default: // Failure
  1667. MSG_LOG(TRACE,"MsgSesFullService: Unrecognized retval %x\n",retval);
  1668. pNcb = GETNCB(net,ncbi);
  1669. MsgNetBiosError(net, pNcb, retval, ncbi);
  1670. break;
  1671. }
  1672. }
  1673. /*
  1674. * MsgStartListen - issue a LISTEN net bios call
  1675. *
  1676. * This function is invoked to issue a LISTEN net bios call using
  1677. * a particular Network Control Block. This function does not
  1678. * examine or change any of the shareable data corresponding to
  1679. * the NCB in question.
  1680. *
  1681. * MsgStartListen (net, ncbi)
  1682. *
  1683. * ENTRY
  1684. * net - network index
  1685. * ncbi - Network Control Block index
  1686. *
  1687. * RETURN
  1688. * DWORD status from the netbios call.
  1689. *
  1690. * This function assumes that the NCB_NAME, NCB_POST, and NCB_LANA
  1691. * fields of the Network Control Block are already set to the
  1692. * proper values. It sets the NCB_CNAME, NCB_RTO, NCB_STO, and
  1693. * NCB_CMD fields.
  1694. *
  1695. * SIDE EFFECTS
  1696. *
  1697. * Calls MsgCallNetBios() to issue the net bios call. Calls FmtNcbName()
  1698. * to set the NCB_CNAME field of the NCB. Sets mpncbifun[ncbi] to
  1699. * the address of MsgListenService().
  1700. */
  1701. NET_API_STATUS
  1702. MsgStartListen(
  1703. DWORD net, // Which network?
  1704. DWORD ncbi // Network Control Block index
  1705. )
  1706. {
  1707. PNCB ncb; // Pointer to NCB
  1708. PNCB_DATA pNcbData; // Pointer to NCB Data
  1709. NET_API_STATUS status;
  1710. TCHAR name[2] = TEXT("*");
  1711. MSG_LOG(TRACE,"In MsgStartListen %d\n",net);
  1712. pNcbData = GETNCBDATA(net,ncbi);
  1713. ncb = &pNcbData->Ncb;
  1714. pNcbData->IFunc = (LPNCBIFCN)MsgListenService; // Set function pointer
  1715. //
  1716. // Set call name to a"anyone"
  1717. //
  1718. status = MsgFmtNcbName(ncb->ncb_callname,name,' ');
  1719. if (status != NERR_Success) {
  1720. //
  1721. // This is a bug if this can't be done.
  1722. //
  1723. MSG_LOG(ERROR,"MsgStartListen: NASTY BUG! Cannot format \"*\" name! %X\n",
  1724. status);
  1725. NetpAssert(0);
  1726. }
  1727. ncb->ncb_rto = 60; // Receives time out in 30 sec
  1728. ncb->ncb_sto = 40; // Sends time out in 20 sec
  1729. ncb->ncb_command = NCBLISTEN | ASYNCH; // Listen (no wait)
  1730. return(MsgCallNetBios(net,ncb,ncbi)); // Issue the net bios call
  1731. }
  1732. /*
  1733. * MsgVerifySmb - Verify the correctness of a Server Message Block
  1734. *
  1735. * This function verifies that a Server Message Block is properly
  1736. * formed. If it detects a malformed SMB, it terminates the session
  1737. * and returns a non-zero value.
  1738. *
  1739. * MsgVerifySmb (net, ncbi, func, parms, buffers)
  1740. *
  1741. * ENTRY
  1742. * net - network index
  1743. * ncbi - index to a Network Control Block
  1744. * func - SMB function code
  1745. * parms - number of parameters in SMB
  1746. * buffers - dope vector describing buffers in the SMB
  1747. *
  1748. * RETURN
  1749. * int - error code (zero means no error)
  1750. *
  1751. * SIDE EFFECTS
  1752. *
  1753. * Calls smbcheck() to check the SMB. Calls MsgRestart() if
  1754. * smbcheck() reports an error.
  1755. */
  1756. STATIC int
  1757. MsgVerifySmb(
  1758. DWORD net, // Which network?
  1759. DWORD ncbi, // Index to Network Control Block
  1760. UCHAR func, // SMB function code
  1761. int parms, // Count of parameters in SMB
  1762. LPSTR buffers // Dope vector of SMB buffers
  1763. )
  1764. {
  1765. PNCB ncb; // Pointer to Network Control Block
  1766. int i; // Return code
  1767. ncb = GETNCB(net,ncbi); // Get pointer to NCB
  1768. i = Msgsmbcheck(
  1769. (ncb->ncb_buffer),
  1770. ncb->ncb_length,
  1771. func,
  1772. (char)parms,
  1773. buffers);
  1774. if (i != 0 )
  1775. {
  1776. MSG_LOG(ERROR,"MsgVerifySmb:An illegal SMB was received\n",0);
  1777. //
  1778. // HANGUP
  1779. //
  1780. MsgRestart(net,ncbi);
  1781. }
  1782. return(i); // Return error code
  1783. }
  1784. #if DBG
  1785. VOID
  1786. MsgDumpNcb(
  1787. IN PNCB pNcb
  1788. )
  1789. /*++
  1790. Routine Description:
  1791. Displays the NCB on a debug terminal.
  1792. Arguments:
  1793. Return Value:
  1794. --*/
  1795. {
  1796. DbgPrint("NCBADDR: 0x%x\n"
  1797. "Command: 0x%x\n"
  1798. "RetCode: 0x%x\n"
  1799. "LanaNum: 0x%x\n"
  1800. "CmdCplt: 0x%x\n"
  1801. "Name : %s\n"
  1802. "callNam: %s\n",
  1803. pNcb, pNcb->ncb_command, pNcb->ncb_retcode, pNcb->ncb_lana_num,
  1804. pNcb->ncb_cmd_cplt, pNcb->ncb_name, pNcb->ncb_callname);
  1805. }
  1806. #endif // DBG