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.

1567 lines
40 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. nbtrans.cxx
  5. Abstract:
  6. Netbios connection transport interface. Parts are similar
  7. to wstran.cxx but there are major differences due to
  8. addresses supporting multiple listen sockets.
  9. Author:
  10. Mario Goertzel [MarioGo]
  11. Revision History:
  12. MarioGo 3/28/1996 Based and depends on wstrans.cxx
  13. MarioGo 2/04/1997 Updated for async and client
  14. --*/
  15. #include <precomp.hxx>
  16. #include <CharConv.hxx>
  17. // Globals
  18. BOOL fNetbiosLoaded = FALSE;
  19. const DWORD MAX_LANA = 256;
  20. const DWORD MAX_RESERVED_EPT = 32; // LanMan uses ports < 32.
  21. typedef struct
  22. {
  23. RPC_CHAR *Protseq;
  24. UINT ProtseqLength;
  25. PROTOCOL_ID id;
  26. BYTE MinEndpoint;
  27. BYTE MaxEndpoint;
  28. } NB_PROTSEQ_CONFIG;
  29. const NB_PROTSEQ_CONFIG NbProtseqConfig[] =
  30. {
  31. {
  32. RPC_STRING_LITERAL("ncacn_nb_nb"),
  33. 11,
  34. NBF,
  35. 33,
  36. 105
  37. },
  38. {
  39. RPC_STRING_LITERAL("ncacn_nb_tcp"),
  40. 12,
  41. NBT,
  42. 106,
  43. 180
  44. },
  45. {
  46. RPC_STRING_LITERAL("ncacn_nb_ipx"),
  47. 12,
  48. NBI,
  49. 181,
  50. 255
  51. }
  52. };
  53. const DWORD cNetbiosProtseqs = sizeof(NbProtseqConfig)/sizeof(NB_PROTSEQ_CONFIG);
  54. typedef struct
  55. {
  56. UCHAR ProtocolId;
  57. UCHAR Lana;
  58. } NB_PROTOCOL_MAP;
  59. DWORD cLanas;
  60. NB_PROTOCOL_MAP *pNetbiosLanaMap = 0;
  61. BOOL *afUsedEndpoints = 0;
  62. const RPC_CHAR *NetbiosRegistryKey =
  63. RPC_CONST_STRING("Software\\Microsoft\\Rpc\\NetBios");
  64. // enough to contain ncacn_nb_tcp#\0
  65. const size_t MaxNbProtseqLength = 16;
  66. RPC_STATUS
  67. LoadNetbios()
  68. /*++
  69. Routine Description:
  70. Loads RPC netbios configuration data from the registry.
  71. Note:
  72. Unlike wsock32.dll, advapi32.dll (required for registry APIs)
  73. is already loaded by rpcrt4.dll. So it is okay to link
  74. directly to advapi32.dll.
  75. Arguments:
  76. None
  77. Return Value:
  78. RPC_S_OK
  79. RPC_S_OUT_OF_MEMORY
  80. RPC_S_OUT_OF_RESOURCES
  81. --*/
  82. {
  83. HKEY hKey;
  84. RPC_STATUS status;
  85. int i;
  86. PROTOCOL_ID id;
  87. RPC_CHAR protseq[MaxNbProtseqLength];
  88. DWORD cProtseq;
  89. DWORD datatype;
  90. DWORD lana;
  91. DWORD cLana;
  92. ASSERT(fNetbiosLoaded == FALSE);
  93. if (!pNetbiosLanaMap)
  94. {
  95. // Alloc space for the lana to RPC protocol mapping
  96. cLanas = 0;
  97. pNetbiosLanaMap = new NB_PROTOCOL_MAP[MAX_LANA];
  98. if (!pNetbiosLanaMap)
  99. {
  100. return(RPC_S_OUT_OF_MEMORY);
  101. }
  102. }
  103. if (!afUsedEndpoints)
  104. {
  105. // Alloc space to keep track of which endpoints are in use.
  106. afUsedEndpoints = new BOOL[256];
  107. if (!afUsedEndpoints)
  108. {
  109. return(RPC_S_OUT_OF_MEMORY);
  110. }
  111. for (int i = 0; i <= MAX_RESERVED_EPT; i++)
  112. {
  113. afUsedEndpoints[i] = TRUE;
  114. }
  115. for (i = MAX_RESERVED_EPT + 1; i < 256; i++)
  116. {
  117. afUsedEndpoints[i] = FALSE;
  118. }
  119. }
  120. status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  121. NetbiosRegistryKey,
  122. 0,
  123. KEY_READ,
  124. &hKey);
  125. if (status)
  126. {
  127. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  128. DPFLTR_WARNING_LEVEL,
  129. RPCTRANS "Unable to open netbios key: %d\n",
  130. GetLastError()));
  131. return(RPC_S_OUT_OF_RESOURCES);
  132. }
  133. ASSERT(hKey);
  134. for(i = 0, cLanas = 0; cLanas < MAX_LANA; i++)
  135. {
  136. cProtseq = MaxNbProtseqLength;
  137. cLana = sizeof(lana);
  138. status = RegEnumValueW(hKey,
  139. i,
  140. protseq,
  141. &cProtseq,
  142. 0,
  143. &datatype,
  144. (PBYTE)&lana,
  145. &cLana);
  146. if (status == ERROR_NO_MORE_ITEMS)
  147. {
  148. // This is the normal exit path.
  149. break;
  150. }
  151. if (status)
  152. {
  153. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  154. DPFLTR_WARNING_LEVEL,
  155. RPCTRANS "Unable to read netbios key %d, %d\n",
  156. i,
  157. GetLastError()));
  158. return(RPC_S_OUT_OF_RESOURCES);
  159. }
  160. if (datatype != REG_DWORD || lana >= MAX_LANA)
  161. {
  162. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  163. DPFLTR_WARNING_LEVEL,
  164. RPCTRANS "Invalid config for netbios entry %d\n",
  165. i));
  166. ASSERT(0);
  167. continue;
  168. }
  169. for (int j = 0; j < cNetbiosProtseqs; j++)
  170. {
  171. if (wcsncmp(protseq,
  172. NbProtseqConfig[j].Protseq,
  173. NbProtseqConfig[j].ProtseqLength) == 0)
  174. {
  175. id = NbProtseqConfig[j].id;
  176. break;
  177. }
  178. }
  179. if (j == cNetbiosProtseqs)
  180. {
  181. // Unknown protsrq.
  182. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  183. DPFLTR_WARNING_LEVEL,
  184. RPCTRANS "Invalid config for netbios entry %S %d\n",
  185. protseq,
  186. i));
  187. ASSERT(0);
  188. continue;
  189. }
  190. pNetbiosLanaMap[cLanas].ProtocolId = (UCHAR)id;
  191. pNetbiosLanaMap[cLanas].Lana = (UCHAR)lana;
  192. cLanas++;
  193. }
  194. ASSERT(cLanas < MAX_LANA); // If this gets hit we may want to
  195. // grow the table size or fix setup.
  196. if (cLanas == 0)
  197. {
  198. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  199. DPFLTR_WARNING_LEVEL,
  200. RPCTRANS "Invalid NETBIOS configuration\n"));
  201. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  202. }
  203. return(RPC_S_OK);
  204. }
  205. void RPC_ENTRY WS_ServerAbortListen(RPC_TRANSPORT_ADDRESS);
  206. RPC_STATUS
  207. NB_ServerListenHelper(
  208. IN PWS_ADDRESS pAddress,
  209. IN USHORT port,
  210. IN const NB_PROTSEQ_CONFIG *pConfig,
  211. IN unsigned int PendingQueueSize
  212. )
  213. /*++
  214. Routine Description:
  215. This routine does the work of actually creating a server address.
  216. Arguments:
  217. pAddress - A pointer to the loadable transport interface address.
  218. Will contain the newly allocated listen socket when finished.
  219. port - The port number to use, never zero here.
  220. pConfig - Config data for the protseq we're using.
  221. PendingQueueSize - Supplies the size of the queue of pending
  222. requests which should be created by the transport.
  223. In this case it is simply passed to listen().
  224. ReturnValue:
  225. RPC_S_OK
  226. RPC_S_OUT_OF_MEMORY
  227. RPC_S_OUT_OF_RESOURCES
  228. RPC_S_CANT_CREATE_ENDPOINT
  229. --*/
  230. {
  231. int retval, length;
  232. RPC_STATUS status;
  233. WS_SOCKADDR sockaddr;
  234. PWS_ADDRESS pList, pOld;
  235. SOCKET sock;
  236. PROTOCOL_ID index = pConfig->id;
  237. BOOL found = FALSE;
  238. DWORD dwLastError;
  239. pList = pAddress;
  240. status = RPC_S_CANT_CREATE_ENDPOINT;
  241. ASSERT(cLanas > 0 && cLanas < MAX_LANA);
  242. for (unsigned i = 0; i < cLanas; i++)
  243. {
  244. if (pNetbiosLanaMap[i].ProtocolId == (UCHAR)index)
  245. {
  246. //
  247. // Open a socket.
  248. //
  249. sock = WSASocketT(WsTransportTable[index].AddressFamily,
  250. WsTransportTable[index].SocketType,
  251. WsTransportTable[index].Protocol * pNetbiosLanaMap[i].Lana,
  252. 0,
  253. 0,
  254. WSA_FLAG_OVERLAPPED);
  255. if (sock == INVALID_SOCKET)
  256. {
  257. switch(GetLastError())
  258. {
  259. case WSAEAFNOSUPPORT:
  260. case WSAEPROTONOSUPPORT:
  261. case WSAENETDOWN:
  262. case WSAESOCKTNOSUPPORT:
  263. case WSAEINVAL: // when registry is not yet setup.
  264. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  265. break;
  266. case WSAENOBUFS:
  267. case WSAEMFILE:
  268. status = RPC_S_OUT_OF_MEMORY;
  269. break;
  270. default:
  271. ASSERT(0);
  272. status = RPC_S_OUT_OF_RESOURCES;
  273. break;
  274. }
  275. break;
  276. }
  277. //
  278. // Try to bind to the lana.
  279. //
  280. {
  281. DWORD Size = 1+MAX_COMPUTERNAME_LENGTH;
  282. char AsciiComputerName[1+MAX_COMPUTERNAME_LENGTH];
  283. if (!GetComputerNameA( AsciiComputerName, &Size) )
  284. {
  285. status = RPC_S_CANT_CREATE_ENDPOINT;
  286. closesocket(sock);
  287. break;
  288. }
  289. SET_NETBIOS_SOCKADDR(&sockaddr.nbaddr,
  290. NETBIOS_UNIQUE_NAME,
  291. AsciiComputerName,
  292. (char) port);
  293. }
  294. if ( bind(sock,&sockaddr.generic,sizeof(WS_SOCKADDR)) )
  295. {
  296. dwLastError = GetLastError();
  297. if (dwLastError == WSAEADDRINUSE)
  298. {
  299. //
  300. // If the caller is trying use a dynamic endpoint
  301. // then we may want to retry with another port.
  302. //
  303. status = ERROR_RETRY;
  304. }
  305. else if(dwLastError == WSAENETDOWN)
  306. {
  307. closesocket(sock);
  308. continue;
  309. }
  310. else
  311. status = RPC_S_CANT_CREATE_ENDPOINT;
  312. closesocket(sock);
  313. break;
  314. }
  315. if(listen(sock, PendingQueueSize) == SOCKET_ERROR)
  316. {
  317. status = RPC_S_OUT_OF_MEMORY;
  318. closesocket(sock);
  319. break;
  320. }
  321. //
  322. // Allocate a new address object, if needed.
  323. //
  324. found = TRUE;
  325. if (0 == pList)
  326. {
  327. // >1 lana, need to allocate another address.
  328. pList = new WS_ADDRESS;
  329. if (pList == 0)
  330. {
  331. status = RPC_S_OUT_OF_MEMORY;
  332. break;
  333. }
  334. // Insert new address into list of nb addresses.
  335. pOld->pNextAddress = pList;
  336. }
  337. pList->type = ADDRESS;
  338. pList->id = index;
  339. pList->ConnectionSocket = 0;
  340. SetProtocolMultiplier(pList, pNetbiosLanaMap[i].Lana);
  341. pList->NewConnection = WS_NewConnection;
  342. pList->SubmitListen = WS_SubmitAccept;
  343. pList->InAddressList = NotInList;
  344. pList->pFirstAddress = pAddress;
  345. pList->ListenSocket = 0;
  346. pList->ConnectionSocket = 0;
  347. pList->pNextAddress = 0;
  348. pList->Endpoint = 0;
  349. pList->pAddressVector = 0;
  350. pList->pNext = 0;
  351. memset(&pList->Listen, 0, sizeof(BASE_OVERLAPPED));
  352. pList->Listen.pAsyncObject = pList;
  353. pList->ListenSocket = sock;
  354. RpcpInitializeListHead(&pList->ObjectList);
  355. retval = pList->GetExtensionFunctionPointers(sock);
  356. if (!retval)
  357. {
  358. switch (GetLastError())
  359. {
  360. case WSAEFAULT:
  361. case WSAEINVAL:
  362. status = RPC_S_INTERNAL_ERROR;
  363. break;
  364. case WSAEOPNOTSUPP:
  365. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  366. break;
  367. default:
  368. status = RPC_S_OUT_OF_RESOURCES;
  369. }
  370. closesocket(sock);
  371. break;
  372. }
  373. status = COMMON_PrepareNewHandle((HANDLE)sock);
  374. if (status != RPC_S_OK)
  375. {
  376. closesocket(sock);
  377. break;
  378. }
  379. ASSERT(status == RPC_S_OK);
  380. pOld = pList;
  381. pList = 0;
  382. }
  383. }
  384. //
  385. // Cleanup only if we find something
  386. //
  387. if ((TRUE == found) && (status != RPC_S_OK))
  388. {
  389. WS_ServerAbortListen(pAddress);
  390. }
  391. return(status);
  392. }
  393. RPC_STATUS
  394. NB_ServerListen(
  395. IN PROTOCOL_ID index,
  396. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  397. IN OUT PWSTR *pEndpoint,
  398. IN UINT PendingQueueSize,
  399. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector
  400. )
  401. /*++
  402. Routine Description:
  403. This routine allocates a netbios server address receive new client
  404. connections. If successful a call to NB_CompleteListen() will actually
  405. allow new connection callbacks to the RPC runtime to occur. If the
  406. runtime is unable to complete then it must abort the address by calling
  407. WS_ServerAbortListen().
  408. Arguments:
  409. pAddress - A pointer to the loadable transport interface address.
  410. pEndpoint - Optionally, the endpoint (0-255) to listen on. Set to
  411. to listened port for dynamically allocated endpoints.
  412. PendingQueueSize - Count to call listen() with.
  413. ppAddressVector - Network address of this machine.
  414. Return Value:
  415. RPC_S_OK
  416. RPC_S_OUT_OF_MEMORY
  417. RPC_S_OUT_OF_RESOURCES
  418. RPC_S_CANT_CREATE_ENDPOINT
  419. RPC_S_DUPLICATE_ENDPOINT
  420. --*/
  421. {
  422. RPC_STATUS status;
  423. NTSTATUS NtStatus;
  424. USHORT port, maxport;
  425. const NB_PROTSEQ_CONFIG *pConfig;
  426. PWS_ADDRESS pAddress = (PWS_ADDRESS)ThisAddress;
  427. // Figure out which flavor of Netbios we're going to use.
  428. pConfig = 0;
  429. for (int i = 0; i < cNetbiosProtseqs; i++)
  430. {
  431. if (index == NbProtseqConfig[i].id)
  432. {
  433. pConfig = &NbProtseqConfig[i];
  434. break;
  435. }
  436. }
  437. if (0 == pConfig)
  438. {
  439. ASSERT(0);
  440. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  441. }
  442. // Figure out what ports to try to listen on.
  443. if (*pEndpoint)
  444. {
  445. status = EndpointToPortNumber(*pEndpoint, port);
  446. if (status != RPC_S_OK)
  447. {
  448. return(status);
  449. }
  450. if (port > 255)
  451. {
  452. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  453. }
  454. // Static endpoint, only try the one endpoint.
  455. status = NB_ServerListenHelper(pAddress,
  456. port,
  457. pConfig,
  458. PendingQueueSize);
  459. afUsedEndpoints[port] = TRUE;
  460. }
  461. else
  462. {
  463. port = pConfig->MinEndpoint;
  464. maxport = pConfig->MaxEndpoint;
  465. // Try to listen to a port. This is iterative for dynamic endpoints.
  466. for(; port <= maxport; port++)
  467. {
  468. if (InterlockedExchange((PLONG)&afUsedEndpoints[port], TRUE) == FALSE)
  469. {
  470. status = NB_ServerListenHelper(pAddress,
  471. port,
  472. pConfig,
  473. PendingQueueSize);
  474. if (status == RPC_S_OK)
  475. {
  476. break;
  477. }
  478. if (status != ERROR_RETRY)
  479. {
  480. return(status);
  481. }
  482. }
  483. else
  484. {
  485. status = ERROR_RETRY;
  486. }
  487. }
  488. }
  489. if (status != RPC_S_OK)
  490. {
  491. if (status == ERROR_RETRY)
  492. {
  493. if (*pEndpoint)
  494. {
  495. return(RPC_S_DUPLICATE_ENDPOINT);
  496. }
  497. return(RPC_S_CANT_CREATE_ENDPOINT);
  498. }
  499. return(status);
  500. }
  501. //
  502. // Build address vector
  503. //
  504. ASSERT(pAddress->pAddressVector == 0);
  505. NETWORK_ADDRESS_VECTOR *pVector;
  506. pVector = new( sizeof(RPC_CHAR *)
  507. + gdwComputerNameLength * sizeof(RPC_CHAR))
  508. NETWORK_ADDRESS_VECTOR;
  509. if (pVector)
  510. {
  511. pVector->Count = 1;
  512. pVector->NetworkAddresses[0] = (RPC_CHAR *)&pVector->NetworkAddresses[1];
  513. wcscpy(pVector->NetworkAddresses[0], gpstrComputerName);
  514. pAddress->pAddressVector = pVector;
  515. *ppAddressVector = pVector;
  516. }
  517. else
  518. {
  519. WS_ServerAbortListen(ThisAddress);
  520. return(RPC_S_OUT_OF_MEMORY);
  521. }
  522. //
  523. // If needed, return the dynamic endpoint as a string.
  524. //
  525. if (!*pEndpoint)
  526. {
  527. *pEndpoint = new RPC_CHAR[NB_MAXIMUM_ENDPOINT];
  528. if (!*pEndpoint)
  529. {
  530. WS_ServerAbortListen(ThisAddress);
  531. return(RPC_S_OUT_OF_MEMORY);
  532. }
  533. PortNumberToEndpoint(port, *pEndpoint);
  534. }
  535. return(RPC_S_OK);
  536. }
  537. C_ASSERT(FIELD_OFFSET(NB_CONNECTION, fReceivePending) == FIELD_OFFSET(WS_CLIENT_CONNECTION, fReceivePending));
  538. RPC_STATUS
  539. RPC_ENTRY
  540. NB_ClientOpen(
  541. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  542. IN RPC_CHAR * ProtocolSequence,
  543. IN RPC_CHAR * NetworkAddress,
  544. IN RPC_CHAR * Endpoint,
  545. IN RPC_CHAR * NetworkOptions,
  546. IN UINT Timeout,
  547. IN UINT SendBufferSize,
  548. IN UINT RecvBufferSize,
  549. IN void *ResolverHint,
  550. IN BOOL fHintInitialized
  551. )
  552. /*++
  553. Routine Description:
  554. Opens a connection to a server.
  555. Arguments:
  556. ThisConnection - A place to store the connection
  557. ProtocolSeqeunce - "ncacn_nb_*"
  558. NetworkAddress - The name of the server, a 1-15 character netbios name
  559. NetworkOptions - Ignored
  560. Timeout - See RpcMgmtSetComTimeout
  561. 0 - Min
  562. 5 - Default
  563. 9 - Max
  564. 10 - Infinite
  565. SendBufferSize -
  566. RecvBufferSize - (Both optional) Specifies the size of the send/recv
  567. transport buffers.
  568. Return Value:
  569. RPC_S_OK
  570. RPC_S_OUT_OF_MEMORY
  571. RPC_S_OUT_OF_RESOURCES
  572. RPC_S_SERVER_UNAVAILABLE
  573. RPC_S_INVALID_ENDPOINT_FORMAT
  574. RPC_S_INVALID_NET_ADDR
  575. --*/
  576. {
  577. PNB_CONNECTION p = (PNB_CONNECTION)ThisConnection;
  578. unsigned i;
  579. PROTOCOL_ID id = 0;
  580. USHORT port;
  581. RPC_STATUS status;
  582. UCHAR nbname[NB_MAXIMUM_NAME];
  583. SOCKET sock;
  584. WS_SOCKADDR addr;
  585. BOOL fIsUserModeConnection;
  586. // Figure out which specific Netbios protocol we're using
  587. for (i = 0; i < cNetbiosProtseqs; i++)
  588. {
  589. if (wcscmp(NbProtseqConfig[i].Protseq, ProtocolSequence) == 0)
  590. {
  591. id = NbProtseqConfig[i].id;
  592. break;
  593. }
  594. }
  595. ASSERT(id);
  596. // Initialize common part of the connection object
  597. // use explicit placement to initialize vtable
  598. p = new (p) NB_CONNECTION;
  599. p->id = id;
  600. p->type = CLIENT | CONNECTION;
  601. p->Conn.Socket = 0;
  602. p->fAborted = 0;
  603. p->pReadBuffer = 0;
  604. p->maxReadBuffer = 0;
  605. p->iPostSize = CO_MIN_RECV;
  606. p->iLastRead = 0;
  607. memset(&p->Read.ol, 0, sizeof(p->Read.ol));
  608. p->Read.pAsyncObject = p;
  609. p->Read.thread = 0;
  610. p->SequenceNumber = 0;
  611. p->InitIoCounter();
  612. p->fReceivePending = 0;
  613. RpcpInitializeListHead(&p->ObjectList);
  614. // The netbios endpoint is really just the 16th character in the
  615. // netbios name registered by the server. The value is 1-255.
  616. status = EndpointToPortNumber(Endpoint, port);
  617. if (status != RPC_S_OK)
  618. {
  619. return status;
  620. }
  621. if (port > 255)
  622. {
  623. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  624. }
  625. // Build the uppercase netbios name we're looking for.
  626. if (NetworkAddress && *NetworkAddress)
  627. {
  628. if (wcslen(NetworkAddress) >= NB_MAXIMUM_NAME)
  629. {
  630. return(RPC_S_INVALID_NET_ADDR);
  631. }
  632. PlatformToAnsi(NetworkAddress, (PCHAR)nbname);
  633. }
  634. else
  635. {
  636. PlatformToAnsi(gpstrComputerName, (PCHAR)nbname);
  637. }
  638. _strupr((PCHAR)nbname);
  639. // Loop over every lana until we run out or succeed.
  640. unsigned ErrorCount = 0;
  641. for (i = 0; i < cLanas; i++)
  642. {
  643. if (pNetbiosLanaMap[i].ProtocolId != id)
  644. {
  645. continue;
  646. }
  647. UCHAR lana = pNetbiosLanaMap[i].Lana;
  648. //
  649. // Open socket
  650. //
  651. sock = WSASocketT(AF_NETBIOS,
  652. SOCK_SEQPACKET,
  653. -1 * lana,
  654. 0,
  655. 0,
  656. WSA_FLAG_OVERLAPPED);
  657. if (sock == INVALID_SOCKET)
  658. {
  659. switch(GetLastError())
  660. {
  661. case WSAEAFNOSUPPORT:
  662. case WSAEPROTONOSUPPORT:
  663. case WSAESOCKTNOSUPPORT:
  664. case WSAEINVAL: // when registry is not yet setup.
  665. ErrorCount++;
  666. break;
  667. default:
  668. break;
  669. }
  670. // Keep trying until we run out of lana's.
  671. // This was a 4.0 hot fix for exchange, they had an invalid lana
  672. // in the configuration and it caused us to abort too early.
  673. continue;
  674. }
  675. DWORD option = TRUE;
  676. int retval;
  677. retval = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
  678. (PCHAR)&option, sizeof(option) );
  679. ASSERT(0 == retval);
  680. SET_NETBIOS_SOCKADDR( (&addr.nbaddr),
  681. NETBIOS_UNIQUE_NAME,
  682. nbname,
  683. (CHAR)port );
  684. //
  685. // Connect the socket to the server. This is where we expect to block
  686. // and/or fail.
  687. //
  688. if (connect(sock, &addr.generic, sizeof(addr)) == SOCKET_ERROR)
  689. {
  690. closesocket(sock);
  691. // Keep trying until we run out of lana's.
  692. continue;
  693. }
  694. status = COMMON_PrepareNewHandle((HANDLE)sock);
  695. if (status != RPC_S_OK)
  696. {
  697. closesocket(sock);
  698. return RPC_S_OUT_OF_MEMORY;
  699. }
  700. // Connected, life is good.
  701. p->Conn.Socket = sock;
  702. fIsUserModeConnection = IsUserModeSocket(sock, &status);
  703. if (status)
  704. {
  705. closesocket(sock);
  706. ErrorCount ++;
  707. continue;
  708. }
  709. // if this is a user mode connection, use Winsock functions ...
  710. if (fIsUserModeConnection)
  711. p = new (p) NB_SAN_CONNECTION;
  712. return(RPC_S_OK);
  713. }
  714. // Either no lana's configured or none of them worked.
  715. if (ErrorCount == cLanas)
  716. {
  717. return (RPC_S_PROTSEQ_NOT_SUPPORTED);
  718. }
  719. return(RPC_S_SERVER_UNAVAILABLE);
  720. }
  721. RPC_STATUS
  722. RPC_ENTRY
  723. NB_Send(
  724. RPC_TRANSPORT_CONNECTION ThisConnection,
  725. UINT Length,
  726. BUFFER Buffer,
  727. PVOID SendContext
  728. )
  729. /*++
  730. Routine Description:
  731. Submits a send of the buffer on the connection. Will complete with
  732. ConnectionServerSend or ConnectionClientSend event either when
  733. the data has been sent on the network or when the send fails.
  734. This routine is specific to netbios since it supports sending
  735. sequence numbers.
  736. Arguments:
  737. ThisConnection - The connection to send the data on.
  738. Length - The length of the data to send.
  739. Buffer - The data to send.
  740. SendContext - A buffer to use as the CO_SEND_CONTEXT for
  741. this operation.
  742. Return Value:
  743. RPC_S_OK
  744. RPC_P_SEND_FAILED - Connection aborted
  745. --*/
  746. {
  747. PNB_CONNECTION pConnection = (PNB_CONNECTION)ThisConnection;
  748. CO_SEND_CONTEXT *pSend = (CO_SEND_CONTEXT *)SendContext;
  749. BOOL b;
  750. DWORD ignored;
  751. RPC_STATUS status;
  752. pConnection->StartingWriteIO();
  753. if (pConnection->fAborted)
  754. {
  755. pConnection->WriteIOFinished();
  756. return(RPC_P_SEND_FAILED);
  757. }
  758. pSend->maxWriteBuffer = Length;
  759. pSend->pWriteBuffer = Buffer;
  760. pSend->Write.pAsyncObject = pConnection;
  761. pSend->Write.ol.hEvent = 0;
  762. pSend->Write.ol.Offset = 0;
  763. pSend->Write.ol.OffsetHigh = 0;
  764. pSend->Write.thread = I_RpcTransProtectThread();
  765. if ((pConnection->type & TYPE_MASK) == CLIENT)
  766. {
  767. // Client sends need to be prefixed with the sequence number.
  768. // Note: this depends on having only a single client side
  769. // send pending on a connection at a time. If this changes
  770. // we can move the sequence number into the SEND_CONTEXT.
  771. WSABUF bufs[2];
  772. bufs[0].buf = (PCHAR)&pConnection->SequenceNumber;
  773. bufs[0].len = sizeof(ULONG);
  774. bufs[1].buf = (PCHAR)Buffer;
  775. bufs[1].len = Length;
  776. status = RPC_S_OK;
  777. if (WSASend(pConnection->Conn.Socket,
  778. bufs,
  779. 2,
  780. &ignored,
  781. 0,
  782. &pSend->Write.ol,
  783. 0))
  784. {
  785. status = GetLastError();
  786. }
  787. }
  788. else
  789. {
  790. status = pConnection->Send(pConnection->Conn.Handle,
  791. Buffer,
  792. Length,
  793. &ignored,
  794. &pSend->Write.ol
  795. );
  796. }
  797. ASSERT(WSA_IO_PENDING == ERROR_IO_PENDING);
  798. pConnection->WriteIOFinished();
  799. if ( status != RPC_S_OK
  800. && status != ERROR_IO_PENDING)
  801. {
  802. if ( status != ERROR_NETNAME_DELETED
  803. && status != ERROR_GRACEFUL_DISCONNECT
  804. && status != WSAESHUTDOWN
  805. && status != WSAECONNRESET
  806. && status != WSAECONNABORTED
  807. && status != WSAENETRESET
  808. )
  809. {
  810. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  811. DPFLTR_WARNING_LEVEL,
  812. RPCTRANS "NB Send failed %d on %p\n",
  813. status,
  814. pConnection));
  815. }
  816. I_RpcTransUnprotectThread(pSend->Write.thread);
  817. pConnection->WS_CONNECTION::Abort();
  818. return(RPC_P_SEND_FAILED);
  819. }
  820. return(RPC_S_OK);
  821. }
  822. RPC_STATUS
  823. RPC_ENTRY
  824. NB_Recv(
  825. RPC_TRANSPORT_CONNECTION ThisConnection
  826. )
  827. /*++
  828. Routine Description:
  829. Called be the runtime on a connection without a currently
  830. pending recv. This will submit the first recv on the
  831. connection. Later recv's maybe posted by CO_Recv. This is
  832. required to strip the sequence number off of fragments.
  833. Arguments:
  834. ThisConnection - A connection without a read pending on it.
  835. Return Value:
  836. RPC_S_OK
  837. RPC_P_RECEIVE_FAILED
  838. --*/
  839. {
  840. PNB_CONNECTION pConnection = (PNB_CONNECTION)ThisConnection;
  841. // Reply fragments don't have a sequence number, so we'll
  842. // just let the standard code deal with them.
  843. if ((pConnection->type & TYPE_MASK) == CLIENT)
  844. {
  845. pConnection->SequenceNumber = 0;
  846. return(CO_Recv(ThisConnection));
  847. }
  848. ASSERT(pConnection->iLastRead == 0);
  849. static ULONG NetbiosSequenceNumber;
  850. BOOL b;
  851. DWORD ignored;
  852. DWORD bytes;
  853. RPC_STATUS status;
  854. WSABUF bufs[2];
  855. int retval;
  856. if (pConnection->pReadBuffer == 0)
  857. {
  858. pConnection->pReadBuffer = TransConnectionAllocatePacket(pConnection,
  859. pConnection->iPostSize);
  860. if (NULL == pConnection->pReadBuffer)
  861. {
  862. pConnection->WS_CONNECTION::Abort();
  863. return(RPC_P_RECEIVE_FAILED);
  864. }
  865. pConnection->maxReadBuffer = pConnection->iPostSize;
  866. }
  867. pConnection->StartingReadIO();
  868. if (pConnection->fAborted)
  869. {
  870. pConnection->ReadIOFinished();
  871. return(RPC_P_RECEIVE_FAILED);
  872. }
  873. pConnection->Read.thread = I_RpcTransProtectThread();
  874. pConnection->Read.ol.hEvent = 0;
  875. bufs[0].buf = (PCHAR)&NetbiosSequenceNumber;
  876. bufs[0].len = sizeof(ULONG);
  877. bufs[1].buf = (PCHAR)pConnection->pReadBuffer;
  878. bufs[1].len = pConnection->maxReadBuffer;
  879. ignored = 0;
  880. retval = WSARecv(pConnection->Conn.Socket,
  881. bufs,
  882. 2,
  883. &bytes,
  884. &ignored,
  885. &pConnection->Read.ol,
  886. 0);
  887. pConnection->ReadIOFinished();
  888. if ( (0 != retval)
  889. && ((status = GetLastError()) != ERROR_IO_PENDING)
  890. && (status != WSAEMSGSIZE) )
  891. {
  892. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  893. DPFLTR_INFO_LEVEL,
  894. RPCTRANS "NB WSARecv failed %d on %p\n",
  895. status,
  896. pConnection));
  897. I_RpcTransUnprotectThread(pConnection->Read.thread);
  898. pConnection->WS_CONNECTION::Abort();
  899. return(RPC_P_RECEIVE_FAILED);
  900. }
  901. // Even if the read completed here, it will also be posted to the
  902. // completion port. This means we don't need to handle the read here.
  903. return(RPC_S_OK);
  904. }
  905. RPC_STATUS NB_CONNECTION::ProcessRead(IN DWORD bytes, OUT BUFFER *pBuffer,
  906. OUT PUINT pBufferLength)
  907. /*++
  908. Routine Description:
  909. Wrapper for BASE_CONNECTION::ProcessRead. This removes alls signs of the sequence
  910. number and return the results of BASE_CONNECTION::ProcessRead.
  911. Arguments:
  912. Return Value:
  913. See BASE_CONNECTION::ProcessRead
  914. --*/
  915. {
  916. // If this is the first read on the server then we need to substract
  917. // four from the bytes read since reading the sequence number doesn't count.
  918. if (type & SERVER)
  919. {
  920. // Server
  921. if (iLastRead == 0)
  922. {
  923. // First read
  924. if (bytes <= 4)
  925. {
  926. ASSERT(0);
  927. WS_CONNECTION::Abort();
  928. return(RPC_P_RECEIVE_FAILED);
  929. }
  930. bytes -= sizeof(ULONG);
  931. }
  932. }
  933. else
  934. {
  935. SequenceNumber = 0;
  936. }
  937. return(WS_CONNECTION::ProcessRead(bytes,
  938. pBuffer,
  939. pBufferLength));
  940. }
  941. RPC_STATUS
  942. RPC_ENTRY
  943. NB_SyncSend(
  944. IN RPC_TRANSPORT_CONNECTION Connection,
  945. IN UINT BufferLength,
  946. IN BUFFER Buffer,
  947. IN BOOL fDisableShutdownCheck,
  948. IN BOOL fDisableCancelCheck,
  949. ULONG Timeout
  950. )
  951. /*++
  952. Routine Description:
  953. Sends a message on the connection. This method must appear
  954. to be synchronous from the callers perspective.
  955. Arguments:
  956. Connection - The connection of send to.
  957. BufferLength - The size of the buffer.
  958. Buffer - The data to sent.
  959. fDisableShutdownCheck - N/A to netbios.
  960. Return Value:
  961. RPC_P_SEND_FAILED - Connection will be closed if this is returned.
  962. RPC_S_OK - Data sent
  963. --*/
  964. {
  965. PNB_CONNECTION p = (PNB_CONNECTION)Connection;
  966. ULONG bytes;
  967. INT retval;
  968. RPC_STATUS status;
  969. WSABUF bufs[2];
  970. int count;
  971. HANDLE hEvent = I_RpcTransGetThreadEvent();
  972. BOOL fWaitAlertably;
  973. p->StartingWriteIO();
  974. if (p->fAborted)
  975. {
  976. p->WriteIOFinished();
  977. return(RPC_P_SEND_FAILED);
  978. }
  979. // Setting the low bit of the event indicates that the write
  980. // completion should NOT be sent to the i/o completion port.
  981. OVERLAPPED olWrite;
  982. olWrite.Internal = 0;
  983. olWrite.InternalHigh = 0;
  984. olWrite.Offset = 0;
  985. olWrite.OffsetHigh = 0;
  986. olWrite.hEvent = (HANDLE) ((ULONG_PTR)hEvent | 0x1);
  987. if ((p->type & TYPE_MASK) == CLIENT)
  988. {
  989. bufs[0].buf = (PCHAR)&p->SequenceNumber;
  990. bufs[0].len = sizeof(ULONG);
  991. bufs[1].buf = (PCHAR)Buffer;
  992. bufs[1].len = BufferLength;
  993. count = 2;
  994. BufferLength += sizeof(ULONG);
  995. }
  996. else
  997. {
  998. bufs[0].buf = (PCHAR)Buffer;
  999. bufs[0].len = BufferLength;
  1000. count = 1;
  1001. }
  1002. retval = WSASend(p->Conn.Socket,
  1003. bufs,
  1004. count,
  1005. &bytes,
  1006. 0,
  1007. &olWrite,
  1008. 0);
  1009. p->WriteIOFinished();
  1010. if (retval == 0)
  1011. {
  1012. ASSERT(bytes == BufferLength);
  1013. p->SequenceNumber++;
  1014. return(RPC_S_OK);
  1015. }
  1016. status = GetLastError();
  1017. if (status == WSA_IO_PENDING)
  1018. {
  1019. fWaitAlertably = !fDisableCancelCheck;
  1020. status = UTIL_GetOverlappedResultEx(p,
  1021. &olWrite,
  1022. &bytes,
  1023. fWaitAlertably,
  1024. Timeout);
  1025. if (status == RPC_S_OK)
  1026. {
  1027. ASSERT(bytes == BufferLength);
  1028. p->SequenceNumber++;
  1029. return(RPC_S_OK);
  1030. }
  1031. }
  1032. p->WS_CONNECTION::Abort();
  1033. if (status == RPC_S_CALL_CANCELLED)
  1034. {
  1035. // Wait for the write to finish. Since we closed the
  1036. // connection this won't take very long.
  1037. UTIL_WaitForSyncIO(&olWrite,
  1038. FALSE,
  1039. INFINITE);
  1040. }
  1041. else
  1042. {
  1043. if (status != RPC_P_TIMEOUT)
  1044. status = RPC_P_SEND_FAILED;
  1045. }
  1046. return(status);
  1047. }
  1048. RPC_STATUS
  1049. RPC_ENTRY
  1050. NBF_ServerListen(
  1051. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  1052. IN RPC_CHAR *NetworkAddress,
  1053. IN OUT PWSTR *pEndpoint,
  1054. IN UINT PendingQueueSize,
  1055. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1056. IN ULONG EndpointFlags,
  1057. IN ULONG NICFlags,
  1058. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector
  1059. )
  1060. // See NB_ServerListen
  1061. {
  1062. return( NB_ServerListen(NBF,
  1063. ThisAddress,
  1064. pEndpoint,
  1065. PendingQueueSize,
  1066. ppAddressVector) );
  1067. }
  1068. RPC_STATUS
  1069. RPC_ENTRY
  1070. NBT_ServerListen(
  1071. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  1072. IN RPC_CHAR *NetworkAddress,
  1073. IN OUT PWSTR *pEndpoint,
  1074. IN UINT PendingQueueSize,
  1075. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1076. IN ULONG EndpointFlags,
  1077. IN ULONG NICFlags,
  1078. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector
  1079. )
  1080. // See NB_ServerListen
  1081. {
  1082. return( NB_ServerListen(NBT,
  1083. ThisAddress,
  1084. pEndpoint,
  1085. PendingQueueSize,
  1086. ppAddressVector) );
  1087. }
  1088. RPC_STATUS
  1089. RPC_ENTRY
  1090. NBI_ServerListen(
  1091. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  1092. IN RPC_CHAR *NetworkAddress,
  1093. IN OUT PWSTR *pEndpoint,
  1094. IN UINT PendingQueueSize,
  1095. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1096. IN ULONG EndpointFlags,
  1097. IN ULONG NICFlags,
  1098. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector
  1099. )
  1100. // See NB_ServerListen
  1101. {
  1102. return( NB_ServerListen(NBI,
  1103. ThisAddress,
  1104. pEndpoint,
  1105. PendingQueueSize,
  1106. ppAddressVector) );
  1107. }
  1108. //
  1109. // Transport interface definitions
  1110. //
  1111. const RPC_CONNECTION_TRANSPORT
  1112. NBF_TransportInterface =
  1113. {
  1114. RPC_TRANSPORT_INTERFACE_VERSION,
  1115. NB_TOWER_ID,
  1116. NBF_ADDRESS_ID,
  1117. RPC_STRING_LITERAL("ncacn_nb_nb"),
  1118. "135",
  1119. COMMON_ProcessCalls,
  1120. COMMON_StartPnpNotifications,
  1121. COMMON_ListenForPNPNotifications,
  1122. COMMON_TowerConstruct,
  1123. COMMON_TowerExplode,
  1124. COMMON_PostRuntimeEvent,
  1125. FALSE,
  1126. sizeof(WS_ADDRESS),
  1127. sizeof(NB_CONNECTION),
  1128. sizeof(NB_CONNECTION),
  1129. sizeof(CO_SEND_CONTEXT),
  1130. 0,
  1131. NBF_MAX_SEND,
  1132. 0,
  1133. 0,
  1134. NB_ClientOpen,
  1135. 0, // No SendRecv on winsock
  1136. CO_SyncRecv,
  1137. WS_Abort,
  1138. WS_Close,
  1139. NB_Send,
  1140. NB_Recv,
  1141. NB_SyncSend,
  1142. 0, // turn on/off keep alives
  1143. NBF_ServerListen,
  1144. WS_ServerAbortListen,
  1145. COMMON_ServerCompleteListen,
  1146. 0, // query client address support.
  1147. 0, // query local address
  1148. 0, // query client id support.
  1149. 0, // Impersonate
  1150. 0 // Revert
  1151. };
  1152. const RPC_CONNECTION_TRANSPORT
  1153. NBT_TransportInterface =
  1154. {
  1155. RPC_TRANSPORT_INTERFACE_VERSION,
  1156. NB_TOWER_ID,
  1157. IP_ADDRESS_ID,
  1158. RPC_STRING_LITERAL("ncacn_nb_tcp"),
  1159. "135",
  1160. COMMON_ProcessCalls,
  1161. COMMON_StartPnpNotifications,
  1162. COMMON_ListenForPNPNotifications,
  1163. COMMON_TowerConstruct,
  1164. COMMON_TowerExplode,
  1165. COMMON_PostRuntimeEvent,
  1166. FALSE,
  1167. sizeof(WS_ADDRESS),
  1168. sizeof(NB_CONNECTION),
  1169. sizeof(NB_CONNECTION),
  1170. sizeof(CO_SEND_CONTEXT),
  1171. 0,
  1172. NBT_MAX_SEND,
  1173. 0,
  1174. 0,
  1175. NB_ClientOpen,
  1176. 0, // No SendRecv on winsock
  1177. CO_SyncRecv,
  1178. WS_Abort,
  1179. WS_Close,
  1180. NB_Send,
  1181. NB_Recv,
  1182. NB_SyncSend,
  1183. 0, // turn on/off keep alives
  1184. NBT_ServerListen,
  1185. WS_ServerAbortListen,
  1186. COMMON_ServerCompleteListen,
  1187. 0, // query client address support.
  1188. 0, // query local address
  1189. 0, // query client id support.
  1190. 0, // Impersonate
  1191. 0 // Revert
  1192. };
  1193. const RPC_CONNECTION_TRANSPORT
  1194. NBI_TransportInterface =
  1195. {
  1196. RPC_TRANSPORT_INTERFACE_VERSION,
  1197. NB_TOWER_ID,
  1198. IPX_ADDRESS_ID,
  1199. RPC_STRING_LITERAL("ncacn_nb_ipx"),
  1200. "135",
  1201. COMMON_ProcessCalls,
  1202. COMMON_StartPnpNotifications,
  1203. COMMON_ListenForPNPNotifications,
  1204. COMMON_TowerConstruct,
  1205. COMMON_TowerExplode,
  1206. COMMON_PostRuntimeEvent,
  1207. FALSE,
  1208. sizeof(WS_ADDRESS),
  1209. sizeof(NB_CONNECTION),
  1210. sizeof(NB_CONNECTION),
  1211. sizeof(CO_SEND_CONTEXT),
  1212. 0,
  1213. NBI_MAX_SEND,
  1214. 0,
  1215. 0,
  1216. NB_ClientOpen,
  1217. 0, // No SendRecv on winsock
  1218. CO_SyncRecv,
  1219. WS_Abort,
  1220. WS_Close,
  1221. NB_Send,
  1222. NB_Recv,
  1223. NB_SyncSend,
  1224. 0, // turn on/off keep alives
  1225. NBI_ServerListen,
  1226. WS_ServerAbortListen,
  1227. COMMON_ServerCompleteListen,
  1228. 0, // query client address support.
  1229. 0, // query local address
  1230. 0, // query client id support.
  1231. 0, // Impersonate
  1232. 0 // Revert
  1233. };
  1234. const RPC_CONNECTION_TRANSPORT *
  1235. NB_TransportLoad (
  1236. IN PROTOCOL_ID index
  1237. )
  1238. {
  1239. RPC_STATUS status;
  1240. if (fWinsockLoaded == FALSE)
  1241. {
  1242. if (RPC_WSAStartup() == FALSE)
  1243. {
  1244. return 0;
  1245. }
  1246. fWinsockLoaded = TRUE;
  1247. }
  1248. if (fNetbiosLoaded == FALSE)
  1249. {
  1250. status = LoadNetbios();
  1251. if (status != RPC_S_OK)
  1252. {
  1253. return 0;
  1254. }
  1255. fNetbiosLoaded = TRUE;
  1256. }
  1257. switch(index)
  1258. {
  1259. case NBF:
  1260. return(&NBF_TransportInterface);
  1261. break;
  1262. case NBT:
  1263. return(&NBT_TransportInterface);
  1264. break;
  1265. case NBI:
  1266. return(&NBI_TransportInterface);
  1267. break;
  1268. default:
  1269. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  1270. DPFLTR_WARNING_LEVEL,
  1271. RPCTRANS "NB_TransportLoad called with index: %d\n",
  1272. index));
  1273. ASSERT(0);
  1274. }
  1275. return(0);
  1276. }