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.

5918 lines
166 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. wstrans.cxx
  5. Abstract:
  6. Winsock connection transport interface.
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 3/18/1996 Bits 'n pieces
  11. MarioGo 12/1997 Async and client parts
  12. KamenM Aug 2/2000 IPv6 Support added - rewrote parts of it
  13. --*/
  14. #include <precomp.hxx>
  15. #include <CharConv.hxx>
  16. //
  17. // Globals
  18. //
  19. BOOL fWinsockLoaded = FALSE;
  20. const WS_TRANS_INFO WsTransportTable[] =
  21. // indexed by protocol ID
  22. {
  23. {
  24. 0
  25. },
  26. // TCP
  27. {
  28. AF_INET,
  29. SOCK_STREAM,
  30. IPPROTO_TCP,
  31. sizeof(SOCKADDR_IN),
  32. FALSE,
  33. TRUE,
  34. TRUE, TRUE, FALSE, FALSE
  35. },
  36. #ifdef SPX_ON
  37. // SPX
  38. {
  39. AF_IPX,
  40. SOCK_STREAM,
  41. NSPROTO_SPXII,
  42. sizeof(SOCKADDR_IPX),
  43. FALSE,
  44. FALSE,
  45. FALSE, FALSE, FALSE, FALSE
  46. },
  47. #else
  48. {
  49. 0,
  50. 0,
  51. 0,
  52. 0,
  53. 0, 0, 0
  54. },
  55. #endif
  56. // NMP - not winsock.
  57. {
  58. 0,
  59. 0,
  60. 0,
  61. 0,
  62. 0, 0, 0
  63. },
  64. #ifdef NETBIOS_ON
  65. // NBF
  66. {
  67. AF_NETBIOS,
  68. SOCK_SEQPACKET,
  69. -1, // Protocol is -1*(LANA),
  70. sizeof(SOCKADDR_NB),
  71. TRUE,
  72. FALSE,
  73. FALSE, FALSE, FALSE, FALSE
  74. },
  75. // NBT
  76. {
  77. AF_NETBIOS,
  78. 0,
  79. -1, // Protocol is -1*(LANA)
  80. sizeof(SOCKADDR_NB),
  81. TRUE,
  82. FALSE,
  83. FALSE, FALSE, FALSE, FALSE
  84. },
  85. // NBI
  86. {
  87. AF_NETBIOS,
  88. SOCK_SEQPACKET,
  89. -1, // Protocol is -1*(LANA)
  90. sizeof(SOCKADDR_NB),
  91. TRUE,
  92. FALSE,
  93. FALSE, FALSE, FALSE, FALSE
  94. },
  95. #else
  96. // NBF
  97. {
  98. 0,
  99. 0,
  100. 0,
  101. 0,
  102. 0, 0, 0
  103. },
  104. // NBT
  105. {
  106. 0,
  107. 0,
  108. 0,
  109. 0,
  110. 0, 0, 0
  111. },
  112. // NBI
  113. {
  114. 0,
  115. 0,
  116. 0,
  117. 0,
  118. 0, 0, 0
  119. },
  120. #endif
  121. #ifdef APPLETALK_ON
  122. // DSP
  123. {
  124. AF_APPLETALK,
  125. SOCK_RDM,
  126. ATPROTO_ADSP,
  127. sizeof(SOCKADDR_AT),
  128. FALSE,
  129. FALSE,
  130. FALSE, FALSE, FALSE, FALSE
  131. },
  132. #else
  133. // DSP
  134. {
  135. 0,
  136. 0,
  137. 0,
  138. 0,
  139. 0, 0, 0
  140. },
  141. #endif
  142. // SPP
  143. {
  144. 0,
  145. 0,
  146. 0,
  147. 0,
  148. 0, 0, 0
  149. },
  150. // HTTP
  151. {
  152. AF_INET,
  153. SOCK_STREAM,
  154. IPPROTO_TCP,
  155. sizeof(SOCKADDR_IN),
  156. FALSE,
  157. TRUE,
  158. TRUE, TRUE, FALSE, FALSE
  159. },
  160. // UDP
  161. {
  162. AF_INET,
  163. SOCK_DGRAM,
  164. IPPROTO_UDP,
  165. sizeof(SOCKADDR_IN),
  166. FALSE,
  167. FALSE,
  168. FALSE, FALSE, FALSE, FALSE
  169. },
  170. #ifdef IPX_ON
  171. // IPX
  172. {
  173. AF_IPX,
  174. SOCK_DGRAM,
  175. NSPROTO_IPX,
  176. sizeof(SOCKADDR_IPX),
  177. FALSE,
  178. FALSE,
  179. FALSE, FALSE, FALSE, FALSE
  180. },
  181. #else
  182. // IPX
  183. {
  184. 0,
  185. 0,
  186. 0,
  187. 0,
  188. 0,
  189. 0,
  190. 0, 0, 0, 0
  191. },
  192. #endif
  193. // CDP (Cluster datagram protocol)
  194. {
  195. AF_CLUSTER,
  196. SOCK_DGRAM,
  197. CLUSPROTO_CDP,
  198. sizeof(SOCKADDR_CLUSTER),
  199. FALSE,
  200. FALSE,
  201. FALSE, FALSE, FALSE, FALSE
  202. },
  203. // MSMQ - not winsock.
  204. {
  205. 0,
  206. 0,
  207. 0,
  208. 0,
  209. 0, 0, 0
  210. },
  211. // TCP over IPv6
  212. {
  213. AF_INET6,
  214. SOCK_STREAM,
  215. IPPROTO_TCP,
  216. sizeof(SOCKADDR_IN6),
  217. FALSE,
  218. TRUE,
  219. TRUE, TRUE, FALSE, FALSE
  220. },
  221. // HTTPv2
  222. {
  223. AF_INET,
  224. SOCK_STREAM,
  225. IPPROTO_TCP,
  226. sizeof(SOCKADDR_IN),
  227. FALSE, // fNetbios
  228. FALSE, // fCheckShutdowns
  229. TRUE, // fSetNoDelay
  230. TRUE, // fSetKeepAlive
  231. FALSE, // fSetRecvBuffer
  232. FALSE // fSetSendBuffer
  233. },
  234. };
  235. const DWORD cWsTransportTable = sizeof(WsTransportTable)/sizeof(WS_TRANS_INFO);
  236. const DWORD cTcpTimeoutDefault = 120 * 60 * 1000; // Normal TCP/IP timeout, 120 minutes
  237. const UUID WS_ADDRESS::ExtensionFunctionsUuids[] = {WSAID_ACCEPTEX, WSAID_GETACCEPTEXSOCKADDRS};
  238. const int WS_ADDRESS::AcceptExFunctionId = 0;
  239. const int WS_ADDRESS::GetAcceptExSockAddressFunctionId = 1;
  240. #define FIRST_EXTENSION_FUNCTION_CODE (WS_ADDRESS::AcceptExFunctionId)
  241. #define LAST_EXTENSION_FUNCTION_CODE (WS_ADDRESS::GetAcceptExSockAddressFunctionId)
  242. inline BOOL IsNetbiosProtocol(PROTOCOL_ID id)
  243. {
  244. #ifdef NETBIOS_ON
  245. return ((id == NBT) || (id == NBF) || (id == NBI));
  246. #else
  247. return FALSE;
  248. #endif
  249. }
  250. void
  251. TCPResolverHint::GetResolverHint (
  252. OUT BOOL *fIPv4Hint,
  253. OUT WS_SOCKADDR *sa
  254. )
  255. /*++
  256. Routine Description:
  257. Retrieves the resolver hint from the runtime supplied hint
  258. (the this object).
  259. Arguments:
  260. fIPv4Hint - on output true if the store hint was about IPv4
  261. sa - on output, the IP address is retrieved from the hint
  262. and stored in sa.
  263. Return Value:
  264. --*/
  265. {
  266. SOCKADDR_IN6 *IPv6Address = (SOCKADDR_IN6 *)sa;
  267. *fIPv4Hint = fIPv4HintValid;
  268. if (fIPv4HintValid)
  269. {
  270. ((SOCKADDR_IN *)sa)->sin_addr.s_addr = u.IPv4Hint;
  271. }
  272. else
  273. {
  274. IPv6Address->sin6_flowinfo = 0;
  275. *((u_long *)(IPv6Address->sin6_addr.s6_addr) ) = *((u_long *)(u.IPv6Hint.u.Word) );
  276. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 1) = *((u_long *)(u.IPv6Hint.u.Word) + 1);
  277. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 2) = *((u_long *)(u.IPv6Hint.u.Word) + 2);
  278. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 3) = *((u_long *)(u.IPv6Hint.u.Word) + 3);
  279. IPv6Address->sin6_scope_id = 0;
  280. }
  281. }
  282. void
  283. TCPResolverHint::SetResolverHint (
  284. IN BOOL fIPv4Hint,
  285. IN WS_SOCKADDR *sa
  286. )
  287. /*++
  288. Routine Description:
  289. Sets the resolver hint in the runtime supplied hint
  290. (the this object).
  291. Arguments:
  292. fIPv4Hint - true if the stored hint is about IPv4
  293. sa - the IP address is retrieved from sa
  294. and is stored in the hint.
  295. Return Value:
  296. --*/
  297. {
  298. SOCKADDR_IN6 *IPv6Address = (SOCKADDR_IN6 *)sa;
  299. fIPv4HintValid = fIPv4Hint;
  300. if (fIPv4HintValid)
  301. {
  302. u.IPv4Hint = ((SOCKADDR_IN *)sa)->sin_addr.s_addr;
  303. }
  304. else
  305. {
  306. *((u_long *)(u.IPv6Hint.u.Word) ) = *((u_long *)(IPv6Address->sin6_addr.s6_addr) );
  307. *((u_long *)(u.IPv6Hint.u.Word) + 1) = *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 1);
  308. *((u_long *)(u.IPv6Hint.u.Word) + 2) = *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 2);
  309. *((u_long *)(u.IPv6Hint.u.Word) + 3) = *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 3);
  310. }
  311. }
  312. BOOL WS_ADDRESS::GetExtensionFunctionPointers(SOCKET sock)
  313. {
  314. int i;
  315. for (i = FIRST_EXTENSION_FUNCTION_CODE; i <= LAST_EXTENSION_FUNCTION_CODE; i ++)
  316. {
  317. if (GetExtensionFunctionPointerForFunction(sock, i) == FALSE)
  318. return FALSE;
  319. }
  320. return TRUE;
  321. }
  322. BOOL WS_ADDRESS::GetExtensionFunctionPointerForFunction(SOCKET sock, int nFunctionCode)
  323. {
  324. DWORD dwBytesReturned;
  325. int retval;
  326. ASSERT(nFunctionCode >= FIRST_EXTENSION_FUNCTION_CODE);
  327. ASSERT(nFunctionCode <= LAST_EXTENSION_FUNCTION_CODE);
  328. ASSERT(sizeof(ExtensionFunctionPointers)/sizeof(ExtensionFunctionPointers[0]) == (LAST_EXTENSION_FUNCTION_CODE - FIRST_EXTENSION_FUNCTION_CODE + 1));
  329. retval = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (void *) &ExtensionFunctionsUuids[nFunctionCode],
  330. sizeof(UUID), (void *) &ExtensionFunctionPointers[nFunctionCode], sizeof(void *), &dwBytesReturned,
  331. NULL, NULL);
  332. if (retval == SOCKET_ERROR)
  333. return FALSE;
  334. ASSERT(dwBytesReturned == sizeof(void *));
  335. return TRUE;
  336. }
  337. //
  338. // General winsock interfaces
  339. //
  340. RPC_STATUS WS_CONNECTION::Abort(void)
  341. /*++
  342. Routine Description:
  343. Closes a connection, will be called only before WS_Close() and
  344. maybe called by several threads at once. It must also handle
  345. the case where another thread is about to start IO on the connection.
  346. Arguments:
  347. Connection - pointer to a server connection object to abort.
  348. Return Value:
  349. RPC_S_OK
  350. --*/
  351. {
  352. if (InterlockedIncrement(&fAborted) != 1)
  353. {
  354. // Another thread beat us to it. Normal during
  355. // a call to WS_Close.
  356. return(RPC_S_OK);
  357. }
  358. I_RpcLogEvent(SU_TRANS_CONN, EV_ABORT, this, ULongToPtr(GetLastError()), 0, 1, 2);
  359. // Wait for any threads which are starting IO to do so.
  360. while(IsIoStarting())
  361. Sleep(1);
  362. RTL_SOFT_ASSERT(fAborted != 0 && IsIoStarting() == 0);
  363. if (type & SERVER)
  364. {
  365. ASSERT(pAddress != NULL);
  366. }
  367. if (Conn.Socket)
  368. {
  369. closesocket(Conn.Socket);
  370. Conn.Socket = 0;
  371. }
  372. return(RPC_S_OK);
  373. }
  374. VOID
  375. WS_DeactivateAddress (
  376. IN WS_ADDRESS *pAddress
  377. )
  378. /*++
  379. Function Name:WS_DeactivateAddress
  380. Parameters:
  381. Note:
  382. Doesn't deal with multiple transport addresses/runtime address
  383. case in netbios or TCP/IP bound to a subset of NICs case. These
  384. cases currently don't PnP.
  385. Description:
  386. Returns:
  387. --*/
  388. {
  389. switch (pAddress->id)
  390. {
  391. case TCP:
  392. case TCP_IPv6:
  393. case HTTP:
  394. #ifdef SPX_ON
  395. case SPX:
  396. #endif
  397. #ifdef APPLETALK_ON
  398. case DSP:
  399. #endif
  400. break;
  401. default:
  402. //
  403. // Don't deactivate the other guys
  404. //
  405. #ifdef NETBIOS_ON
  406. ASSERT((pAddress->id == NMP)
  407. || (pAddress->id == NBF)
  408. || (pAddress->id == NBT)
  409. || (pAddress->id == NBI)
  410. || (pAddress->id == CDP)
  411. );
  412. #else
  413. ASSERT((pAddress->id == NMP)
  414. || (pAddress->id == CDP)
  415. );
  416. #endif
  417. return;
  418. }
  419. if (InterlockedIncrement(&pAddress->fAborted) != 1)
  420. {
  421. return;
  422. }
  423. if (pAddress->ListenSocket)
  424. {
  425. closesocket(pAddress->ListenSocket);
  426. pAddress->ListenSocket = 0;
  427. }
  428. if (pAddress->ConnectionSocket)
  429. {
  430. closesocket(pAddress->ConnectionSocket);
  431. pAddress->ConnectionSocket = 0;
  432. }
  433. }
  434. RPC_STATUS
  435. WS_ServerListenCommon (
  436. IN WS_ADDRESS *pAddress,
  437. IN BOOL fResetAddressListEntries = TRUE, OPTIONAL
  438. IN BOOL fAddToProtocolList = TRUE OPTIONAL
  439. );
  440. USHORT
  441. WS_GetPortForTCPAddressOnAddressRestart (
  442. IN WS_ADDRESS *pAddress
  443. )
  444. /*++
  445. Function Name: WS_GetPortForTCPAddressOnAddressRestart
  446. Parameters:
  447. pAddress - the address for which we need to get the port
  448. Description:
  449. When an address is restarted and it happens to be a TCP
  450. address, we need to call this function to get the port to
  451. be used. This is necessary so that if we are in a dual
  452. transport configuration with an active address we can get
  453. the port from the other address in order to maintain
  454. consistency
  455. Returns:
  456. the port number or 0 (means no known ports or not a dual
  457. transport configuration)
  458. --*/
  459. {
  460. WS_ADDRESS *NextAddress;
  461. USHORT PortNumber = 0;
  462. ASSERT((pAddress->id == TCP) || (pAddress->id == TCP_IPv6));
  463. ASSERT(pAddress->fDynamicEndpoint);
  464. if (pAddress->pFirstAddress != NULL)
  465. {
  466. NextAddress = (WS_ADDRESS *)pAddress->pFirstAddress;
  467. }
  468. else
  469. NextAddress = pAddress;
  470. while (NextAddress != NULL)
  471. {
  472. ASSERT(NextAddress->fDynamicEndpoint);
  473. ASSERT((NextAddress->id == TCP) || (NextAddress->id == TCP_IPv6));
  474. if (!NextAddress->fAborted)
  475. {
  476. PortNumber = RpcpGetIpPort(&NextAddress->ListenAddr);
  477. ASSERT(PortNumber != 0);
  478. break;
  479. }
  480. NextAddress = (WS_ADDRESS *)NextAddress->pNextAddress;
  481. }
  482. return PortNumber;
  483. }
  484. RPC_STATUS
  485. WS_ReactivateAddress (
  486. IN WS_ADDRESS *pAddress,
  487. IN BOOL fResetAddressListEntries OPTIONAL
  488. )
  489. /*++
  490. Function Name:WS_ReactivateAddress
  491. Parameters:
  492. Description:
  493. Returns:
  494. --*/
  495. {
  496. RPC_STATUS Status;
  497. WS_SOCKADDR *sockaddr = &(pAddress->ListenAddr);
  498. //
  499. // If the endpoint is dynamic, clear out the endpoint
  500. //
  501. switch (pAddress->id)
  502. {
  503. case TCP:
  504. case TCP_IPv6:
  505. if (pAddress->fDynamicEndpoint)
  506. {
  507. RpcpSetIpPort(sockaddr, WS_GetPortForTCPAddressOnAddressRestart(pAddress));
  508. }
  509. break;
  510. case HTTP:
  511. if (pAddress->fDynamicEndpoint)
  512. {
  513. RpcpSetIpPort(sockaddr, 0);
  514. }
  515. break;
  516. #ifdef SPX_ON
  517. case SPX:
  518. if (pAddress->fDynamicEndpoint)
  519. {
  520. sockaddr->ipxaddr.sa_socket = 0;
  521. }
  522. break;
  523. #endif
  524. #ifdef APPLETALK_ON
  525. case DSP:
  526. // Don't need to null out the endpoint
  527. break;
  528. #endif
  529. default:
  530. VALIDATE(pAddress->id)
  531. {
  532. NMP,
  533. #ifdef NETBIOS_ON
  534. NBF,
  535. NBT,
  536. NBI,
  537. #endif
  538. CDP
  539. } END_VALIDATE;
  540. //
  541. // Don't reactivate the other guys
  542. //
  543. return RPC_S_OK;
  544. }
  545. // Pass in fAddToProtocolList = FALSE since the object is already in the protocol list.
  546. Status = WS_ServerListenCommon (pAddress, fResetAddressListEntries, FALSE);
  547. if (Status == RPC_S_OK)
  548. {
  549. pAddress->fAborted = 0;
  550. pAddress->GetExtensionFunctionPointers(pAddress->ListenSocket);
  551. }
  552. else if (Status == RPC_P_ADDRESS_FAMILY_INVALID)
  553. {
  554. Status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  555. }
  556. return Status;
  557. }
  558. RPC_STATUS
  559. RPC_ENTRY
  560. WS_Close(
  561. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  562. IN BOOL fDontFlush
  563. )
  564. /*++
  565. Routine Description:
  566. Called once when the connection object is to be really deleted.
  567. At this point there will be no async IO pending on the connection.
  568. Arguments:
  569. ThisConnection - The connection object to close
  570. Return Value:
  571. RPC_S_OK
  572. --*/
  573. {
  574. SOCKET s;
  575. WS_CONNECTION *p = (WS_CONNECTION *)ThisConnection;
  576. p->WS_CONNECTION::Abort();
  577. if (p->iLastRead)
  578. {
  579. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  580. DPFLTR_WARNING_LEVEL,
  581. RPCTRANS "Closing connection %p with left over data (%d) %p \n",
  582. p,
  583. p->iLastRead,
  584. p->pReadBuffer));
  585. }
  586. // Wait for the pending receive, if any, to actually complete.
  587. if ((p->type & TYPE_MASK) == CLIENT)
  588. {
  589. // these operations don't apply to all netbios flavors - they
  590. // apply to protocols which interop with OSF servers only
  591. // (because of the check for shutdown)
  592. if (!IsNetbiosProtocol(p->id))
  593. {
  594. PWS_CCONNECTION pcc = (PWS_CCONNECTION)ThisConnection;
  595. if (pcc->fReceivePending)
  596. {
  597. UTIL_WaitForSyncIO(&pcc->Read.ol,
  598. FALSE,
  599. INFINITE);
  600. }
  601. }
  602. }
  603. // Now free the read buffer
  604. TransConnectionFreePacket(ThisConnection, p->pReadBuffer);
  605. p->pReadBuffer = 0;
  606. TransportProtocol::RemoveObjectFromProtocolList((BASE_ASYNC_OBJECT *) ThisConnection);
  607. return(RPC_S_OK);
  608. }
  609. BOOL
  610. WS_ProtectListeningSocket(
  611. IN SOCKET sock,
  612. IN BOOL newValue
  613. )
  614. /*++
  615. Routine Description:
  616. Sets the SO_EXCLUSIVEADDRUSE socket option on the sock parameter. This
  617. prevents another process from using same port # and stealing our
  618. connections.
  619. Note: This option can only be set by administrators. This routine has no
  620. affect when called by non-administrator.
  621. Arguments:
  622. sock - The socket to protect
  623. newValue - TRUE if the socket is to be protected, FALSE if it is to be unprotected
  624. Return Value:
  625. 0 if it succeeds, 1 if it fails
  626. --*/
  627. {
  628. int fSocketExclusive = newValue;
  629. int rval;
  630. rval = setsockopt(sock,
  631. SOL_SOCKET,
  632. SO_EXCLUSIVEADDRUSE,
  633. (const char *)&fSocketExclusive,
  634. sizeof(fSocketExclusive));
  635. if (rval != 0)
  636. {
  637. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  638. DPFLTR_WARNING_LEVEL,
  639. "Unable to protect listening socket %d\n",
  640. GetLastError()));
  641. }
  642. return rval;
  643. }
  644. RPC_STATUS
  645. WS_CheckForShutdowns(
  646. PWS_CCONNECTION p
  647. )
  648. /*++
  649. Routine Description:
  650. When a connection is idle OSF DCE 1.1+ machines will try to reduce
  651. resource usage by shutting down the connection. This is the place
  652. in the DCE RPC protocol where the servers send data to the client
  653. asychronously to the client sending a request.
  654. When a server decides to shutdown a connection it send three
  655. PDUs of the rpc_shutdown type. Then, if there are no open context
  656. handles on the connection, it will gracefully close the connection.
  657. Note: If there are context handles open on the connection then
  658. the connection is not acutally closed, but the shutdown PDUs are
  659. still sent.
  660. Algorithm:
  661. allocate a buffer large enough for a shutdown PDU.
  662. loop (i = 1 to 4 step 1)
  663. submit an async receive on the connection.
  664. If the receive doesn't complete immediately, return.
  665. type = PDU->type.
  666. If type != shutdown, save the PDU in the connection and return.
  667. goto Loop:
  668. If we get here it means we got too many shutdown PDUs. ASSERT and
  669. close the connection.
  670. Arguments:
  671. p - The connection to check for shutdowns on.
  672. Return Value:
  673. RPC_S_OK
  674. RPC_S_OUT_OF_MEMORY
  675. RPC_P_RECEIVE_FAILED
  676. RPC_P_SEND_FAILED
  677. --*/
  678. {
  679. RPC_STATUS status;
  680. BUFFER buffer;
  681. UINT length;
  682. HANDLE hEvent;
  683. if (p->iLastRead == 0)
  684. {
  685. // The server may have sent us a shutdown packet while the client
  686. // was idle. We'll submit a recv now and check the result without
  687. // waiting.
  688. //
  689. // OSF servers will send 3 shutdown packets and then close the
  690. // connection. We try to submit four receives, this way if the
  691. // connection has already been closed we can fail here.
  692. // Allocate a packet
  693. p->pReadBuffer = TransConnectionAllocatePacket(p, p->iPostSize);
  694. if (NULL == p->pReadBuffer)
  695. {
  696. p->WS_CONNECTION::Abort();
  697. return(RPC_S_OUT_OF_MEMORY);
  698. }
  699. p->maxReadBuffer = p->iPostSize;
  700. }
  701. else
  702. {
  703. ASSERT(p->pReadBuffer);
  704. }
  705. InitReadEvent(p);
  706. for (int i = 0; i < 4; i++)
  707. {
  708. status = CO_SubmitSyncRead(p, &buffer, &length);
  709. if (status == RPC_S_OK)
  710. {
  711. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  712. DPFLTR_WARNING_LEVEL,
  713. RPCTRANS "Shutdown check completed!\n"));
  714. PCONN_RPC_HEADER phdr = (PCONN_RPC_HEADER)buffer;
  715. switch (MessageType(phdr))
  716. {
  717. case rpc_shutdown:
  718. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  719. DPFLTR_WARNING_LEVEL,
  720. RPCTRANS "Received a shutdown\n"));
  721. p->fShutdownReceived = TRUE;
  722. // Reset the buffers and try again.
  723. if (p->pReadBuffer == 0)
  724. {
  725. // we don't know how big the buffer actually is. It may be
  726. // gPostSize, but it also may be only length (if the
  727. // previous receive was coalesced). Play it safe and choose
  728. // what we know - length
  729. p->pReadBuffer = buffer;
  730. p->maxReadBuffer = length;
  731. }
  732. // else
  733. // it is possible that by now all shutdowns
  734. // are coalesced in memory - in this case
  735. // pReadbuffer and maxReadBuffer are already
  736. // set and there is nothing for us to do here -
  737. // just loop around and get them
  738. RpcpErrorAddRecord(EEInfoGCWinsock,
  739. RPC_P_SEND_FAILED,
  740. EEInfoDLWSCheckForShutdowns10,
  741. i);
  742. break;
  743. case rpc_fault:
  744. // Io pending - don't free the buffer.
  745. p->fReceivePending = TRUE;
  746. if (p->pReadBuffer == 0)
  747. {
  748. // see comment in buffer resetting logic in rpc_shutdown
  749. // for explanation of this.
  750. p->pReadBuffer = buffer;
  751. p->maxReadBuffer = length;
  752. }
  753. if (((CONN_RPC_FAULT *) buffer)->status == NCA_STATUS_PROTO_ERROR)
  754. {
  755. //
  756. // This can happen if the server is NT 4.0 and it received a cancel
  757. // after a call completed.
  758. //
  759. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  760. DPFLTR_WARNING_LEVEL,
  761. RPCTRANS "Received an out of sequence packet: %p %p\n",
  762. p,
  763. phdr));
  764. RpcpErrorAddRecord(EEInfoGCWinsock,
  765. RPC_P_SEND_FAILED,
  766. EEInfoDLWSCheckForShutdowns20,
  767. (ULONG)((CONN_RPC_FAULT *) buffer)->status,
  768. (ULONG)i);
  769. goto Cleanup;
  770. }
  771. RpcpErrorAddRecord(EEInfoGCWinsock,
  772. RPC_P_RECEIVE_COMPLETE,
  773. EEInfoDLWSCheckForShutdowns30,
  774. (ULONG)((CONN_RPC_FAULT *) buffer)->status,
  775. (ULONG)i);
  776. return RPC_P_RECEIVE_COMPLETE;
  777. default:
  778. // Got something else - this is probably a protocol error.
  779. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  780. DPFLTR_WARNING_LEVEL,
  781. RPCTRANS "Received an out of sequence packet: %p %p\n",
  782. p,
  783. phdr));
  784. RpcpErrorAddRecord(EEInfoGCWinsock,
  785. RPC_P_SEND_FAILED,
  786. EEInfoDLWSCheckForShutdowns40,
  787. (ULONG)MessageType(phdr),
  788. (ULONG)i);
  789. CORRUPTION_ASSERT(0);
  790. goto Cleanup;
  791. }
  792. }
  793. else
  794. {
  795. if (status == RPC_P_IO_PENDING)
  796. {
  797. // Io pending - don't free the buffer.
  798. p->fReceivePending = TRUE;
  799. return(RPC_S_OK);
  800. }
  801. RpcpErrorAddRecord(EEInfoGCWinsock,
  802. status,
  803. EEInfoDLWSCheckForShutdowns50,
  804. i);
  805. return(status);
  806. }
  807. }
  808. Cleanup:
  809. p->WS_CONNECTION::Abort();
  810. return(RPC_P_SEND_FAILED);
  811. }
  812. RPC_STATUS
  813. RPC_ENTRY
  814. WS_SyncSend(
  815. IN RPC_TRANSPORT_CONNECTION Connection,
  816. IN UINT BufferLength,
  817. IN BUFFER Buffer,
  818. IN BOOL fDisableShutdownCheck,
  819. IN BOOL fDisableCancelCheck,
  820. ULONG Timeout
  821. )
  822. /*++
  823. Routine Description:
  824. Sends a message on the connection. This method must appear
  825. to be synchronous from the callers perspective.
  826. Note: This routine must check for OSF DCE shutdown PDUs
  827. on TCP/IP to avoid interop problems.
  828. Arguments:
  829. Connection - The connection of send to.
  830. BufferLength - The size of the buffer.
  831. Buffer - The data to sent.
  832. fDisableShutdownCheck - Normally FALSE, when true this disables
  833. the transport check for async shutdown PDUs. This is needed
  834. when sending the third leg.
  835. Return Value:
  836. RPC_P_SEND_FAILED - Connection will be closed if this is returned.
  837. RPC_S_OK - Data sent
  838. --*/
  839. {
  840. DWORD bytes;
  841. RPC_STATUS status;
  842. PWS_CCONNECTION p = (PWS_CCONNECTION)Connection;
  843. ASSERT(!IsNetbiosProtocol(p->id));
  844. // Note: this can be called on SERVER connections, too.
  845. // All references to CLIENT-ONLY members must be guarded with
  846. // (p->type & CLIENT).
  847. //
  848. // OSF 1.1(+) server's send, asynchronously to the client sending a
  849. // request, shutdown PDUs on "idle" connections. Here we check for
  850. // shutdown PDUs in order to allow the client to retry the call on
  851. // another connection if this one has closed.
  852. //
  853. if ( ((p->type & TYPE_MASK) == CLIENT)
  854. && (FALSE == p->fCallStarted)
  855. && WsTransportTable[p->id].fCheckShutdowns
  856. && (fDisableShutdownCheck == FALSE)
  857. && (GetTickCount() - p->dwLastCallTime) > MILLISECONDS_BEFORE_PEEK)
  858. {
  859. p->fShutdownReceived = FALSE;
  860. status = WS_CheckForShutdowns(p);
  861. if (status != RPC_S_OK)
  862. {
  863. VALIDATE(status)
  864. {
  865. RPC_P_RECEIVE_FAILED,
  866. RPC_P_CONNECTION_SHUTDOWN,
  867. RPC_P_SEND_FAILED,
  868. RPC_S_OUT_OF_MEMORY,
  869. RPC_P_RECEIVE_COMPLETE
  870. } END_VALIDATE;
  871. if (status == RPC_P_RECEIVE_COMPLETE)
  872. {
  873. return status;
  874. }
  875. RpcpErrorAddRecord(EEInfoGCWinsock,
  876. RPC_P_SEND_FAILED,
  877. EEInfoDLWSSyncSend10);
  878. return(RPC_P_SEND_FAILED);
  879. }
  880. // There is no need to to this again until SyncRecv is called.
  881. p->fCallStarted = TRUE;
  882. }
  883. HANDLE hEvent = I_RpcTransGetThreadEvent();
  884. p->StartingWriteIO();
  885. if (p->fAborted)
  886. {
  887. p->WriteIOFinished();
  888. return(RPC_P_SEND_FAILED);
  889. }
  890. // Setting the low bit of the event indicates that the write
  891. // completion should NOT be sent to the i/o completion port.
  892. OVERLAPPED olWrite;
  893. olWrite.Internal = 0;
  894. olWrite.InternalHigh = 0;
  895. olWrite.Offset = 0;
  896. olWrite.OffsetHigh = 0;
  897. olWrite.hEvent = (HANDLE) ((ULONG_PTR)hEvent | 0x1);
  898. #ifdef _INTERNAL_RPC_BUILD_
  899. if (gpfnFilter)
  900. {
  901. (*gpfnFilter) (Buffer, BufferLength, 0);
  902. }
  903. #endif
  904. status = p->Send(p->Conn.Handle,
  905. Buffer,
  906. BufferLength,
  907. &bytes,
  908. &olWrite
  909. );
  910. p->WriteIOFinished();
  911. if (status == RPC_S_OK)
  912. {
  913. ASSERT(bytes == BufferLength);
  914. return(RPC_S_OK);
  915. }
  916. if (status == ERROR_IO_PENDING)
  917. {
  918. // if fDisableCancelCheck, make the thread wait non-alertably,
  919. // otherwise, make it wait alertably.
  920. status = UTIL_GetOverlappedResultEx(Connection,
  921. &olWrite,
  922. &bytes,
  923. !fDisableCancelCheck,
  924. Timeout);
  925. if (status == RPC_S_OK)
  926. {
  927. ASSERT(bytes == BufferLength);
  928. return(RPC_S_OK);
  929. }
  930. }
  931. ASSERT(status != RPC_S_OK);
  932. RpcpErrorAddRecord(EEInfoGCWinsock,
  933. status,
  934. EEInfoDLWSSyncSend20);
  935. p->WS_CONNECTION::Abort();
  936. if ((status == RPC_S_CALL_CANCELLED) || (status == RPC_P_TIMEOUT))
  937. {
  938. // Wait for the write to finish. Since we closed the
  939. // connection this won't take very long.
  940. UTIL_WaitForSyncIO(&olWrite,
  941. FALSE,
  942. INFINITE);
  943. }
  944. else
  945. {
  946. RpcpErrorAddRecord(EEInfoGCRuntime,
  947. RPC_P_SEND_FAILED,
  948. EEInfoDLWSSyncSend30);
  949. status = RPC_P_SEND_FAILED;
  950. }
  951. return(status);
  952. }
  953. VOID
  954. WS_P_SetKeepAliveTimeout(
  955. IN SOCKET Socket,
  956. IN BOOL OnOff,
  957. IN UINT KATime,
  958. IN UINT KAInterval = 5000 OPTIONAL)
  959. /*++
  960. Arguments:
  961. Socket - The socket to set the keepalive timeout on
  962. OnOff - TRUE to turn if on. FALSE to turn it off
  963. KATime - The time between the last keep alive
  964. response and the next probe.
  965. KAInterval - The timeout in milliseconds for the
  966. subsequent keepalive packets. The time between
  967. two consequitive keep alive probes if the first one
  968. did not receive a response.
  969. --*/
  970. {
  971. int r;
  972. tcp_keepalive tcpka;
  973. DWORD t;
  974. // make sure we indeed get TRUE of FALSE - we don't know how Winsock will
  975. // take it otherwise
  976. ASSERT((OnOff == TRUE) || (OnOff == FALSE));
  977. tcpka.onoff = OnOff;
  978. tcpka.keepalivetime = KATime; // Milliseconds, time to send first KA
  979. tcpka.keepaliveinterval = KAInterval; // Milliseconds, this is the TCP/IP default.
  980. r = WSAIoctl(Socket,
  981. SIO_KEEPALIVE_VALS,
  982. (PVOID)&tcpka,
  983. sizeof(tcpka),
  984. (PVOID)&tcpka,
  985. sizeof(tcpka),
  986. &t,
  987. 0,
  988. 0);
  989. if (r != 0)
  990. {
  991. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  992. DPFLTR_WARNING_LEVEL,
  993. RPCTRANS "setsockopt KEEPALIVE_VALS failed %d\n",
  994. GetLastError()));
  995. }
  996. }
  997. RPC_STATUS
  998. RPC_ENTRY
  999. WS_TurnOnOffKeepAlives (
  1000. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  1001. IN BOOL TurnOn,
  1002. IN BOOL bProtectIO,
  1003. IN KEEPALIVE_TIMEOUT_UNITS Units,
  1004. IN OUT KEEPALIVE_TIMEOUT KATime,
  1005. IN ULONG KAInterval OPTIONAL
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. Turns on keep alives for Winsock transports supporting keepalives.
  1010. Arguments:
  1011. ThisConnection - The connection to turn keep alives on on.
  1012. TurnOn - if non-zero, keep alives are turned on. If zero, keep alives
  1013. are turned off.
  1014. KATime - how much to wait before sending first keep alive. The time between the last keep alive
  1015. response and the next probe.
  1016. KAInterval - the time between two consequitive keep alive probes if the first one did not
  1017. receive a response. 5000 milliseconds is the default.
  1018. Return Value:
  1019. RPC_S_OK or RPC_S_* / Win32 errors on failure
  1020. Note:
  1021. If we use it on the server, we must protect
  1022. the handle by calling StartingOtherIO
  1023. --*/
  1024. {
  1025. PWS_CCONNECTION p = (PWS_CCONNECTION)ThisConnection;
  1026. const WS_TRANS_INFO *pInfo = &WsTransportTable[p->id];
  1027. RPC_STATUS RpcStatus = RPC_S_OK;
  1028. // convert the timeout from runtime scale to transport scale
  1029. if (Units == tuRuntime)
  1030. {
  1031. ASSERT(KATime.RuntimeUnits != RPC_C_BINDING_INFINITE_TIMEOUT);
  1032. KATime.Milliseconds = ConvertRuntimeTimeoutToWSTimeout(KATime.RuntimeUnits);
  1033. }
  1034. // When the server is turning on keepalives it must protect
  1035. // the operation by calling StartingOtherIO
  1036. if (bProtectIO)
  1037. {
  1038. p->StartingOtherIO();
  1039. }
  1040. //
  1041. // It is possible that this code is executed before TCP_Open and WS_Open
  1042. // have been called or that unrecoverable failure has been hit.
  1043. // In this case p->id will be invalid or fAborted will be set.
  1044. //
  1045. if (p->id == INVALID_PROTOCOL_ID || p->fAborted)
  1046. {
  1047. RpcStatus = RPC_P_CONNECTION_CLOSED;
  1048. goto Cleanup;
  1049. }
  1050. ASSERT(pInfo->fSetKeepAlive);
  1051. WS_P_SetKeepAliveTimeout(
  1052. p->Conn.Socket,
  1053. TurnOn ? TRUE : FALSE,
  1054. KATime.Milliseconds,
  1055. KAInterval);
  1056. Cleanup:
  1057. if (bProtectIO)
  1058. {
  1059. p->OtherIOFinished();
  1060. }
  1061. return RpcStatus;
  1062. }
  1063. RPC_STATUS
  1064. RPC_ENTRY
  1065. WS_SyncRecv(
  1066. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  1067. OUT BUFFER *pBuffer,
  1068. OUT PUINT pBufferLength,
  1069. IN DWORD dwTimeout
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Receive the next PDU to arrive at the connection.
  1074. Arguments:
  1075. ThisConnection - The connection to wait on.
  1076. fCancelable - If TRUE, the wait will also include the threads cancel
  1077. event and will timeout after the cancel event is signaled.
  1078. pBuffer - If successful, points to a buffer containing the next PDU.
  1079. BufferSize - If successful, contains the length of the message.
  1080. Return Value:
  1081. RPC_S_OK
  1082. RPC_P_RECEIVE_FAILED - Connection aborted.
  1083. RPC_P_CONNECTION_SHUTDOWN - Graceful disconnect from server, connection aborted.
  1084. RPC_S_CALL_CANCELLED - Timeout after cancel event, connection aborted.
  1085. Note:
  1086. Used only on the client. If we use it on the server, we must protect
  1087. the handle with StartingOtherIO.
  1088. --*/
  1089. {
  1090. RPC_STATUS status;
  1091. DWORD bytes;
  1092. HANDLE hEvent;
  1093. BOOL fReceivePending;
  1094. BOOL fSetKeepAliveVals = FALSE;
  1095. PWS_CCONNECTION p = (PWS_CCONNECTION)ThisConnection;
  1096. DWORD dwActualTimeout;
  1097. BOOL fWaitOnConnectionTimeout;
  1098. ASSERT((p->type & TYPE_MASK) == CLIENT);
  1099. ASSERT(!IsNetbiosProtocol(p->id));
  1100. // There maybe a receive already pending from the shutdown check
  1101. // in WS_SyncSend. If so, we want to skip the first submit.
  1102. fReceivePending = p->fReceivePending;
  1103. p->fReceivePending = FALSE;
  1104. p->fCallStarted = FALSE;
  1105. // if there's a per operation timeout, use the lesser of the operation
  1106. // and connection timeout
  1107. if (dwTimeout != INFINITE)
  1108. {
  1109. if (dwTimeout <= p->Timeout)
  1110. {
  1111. dwActualTimeout = dwTimeout;
  1112. fWaitOnConnectionTimeout = FALSE;
  1113. }
  1114. else
  1115. {
  1116. dwActualTimeout = p->Timeout;
  1117. fWaitOnConnectionTimeout = TRUE;
  1118. }
  1119. }
  1120. else
  1121. {
  1122. // wait on the connection timeout
  1123. dwActualTimeout = p->Timeout;
  1124. fWaitOnConnectionTimeout = TRUE;
  1125. }
  1126. ASSERT( (fReceivePending == FALSE)
  1127. || (p->Read.ol.hEvent == (HANDLE) ((ULONG_PTR)I_RpcTransGetThreadEvent() | 0x1)) );
  1128. //
  1129. // Keep looping until we have a complete message.
  1130. //
  1131. // Note that SubmitSyncRecv may complete with a whole message read.
  1132. //
  1133. do
  1134. {
  1135. if (!fReceivePending)
  1136. {
  1137. // Allocate a receive buffer if needed.
  1138. if (p->pReadBuffer == NULL)
  1139. {
  1140. ASSERT(p->iLastRead == 0);
  1141. p->pReadBuffer = TransConnectionAllocatePacket(p,
  1142. p->iPostSize);
  1143. if (p->pReadBuffer == NULL)
  1144. {
  1145. p->WS_CONNECTION::Abort();
  1146. return(RPC_P_RECEIVE_FAILED);
  1147. }
  1148. p->maxReadBuffer = p->iPostSize;
  1149. }
  1150. InitReadEvent(p);
  1151. status = CO_SubmitSyncRead(p, pBuffer, pBufferLength);
  1152. if (status != RPC_P_IO_PENDING)
  1153. {
  1154. break;
  1155. }
  1156. }
  1157. else
  1158. {
  1159. fReceivePending = FALSE;
  1160. }
  1161. do
  1162. {
  1163. //
  1164. // Wait for the pending receive on the connection to complete
  1165. //
  1166. status = UTIL_GetOverlappedResultEx(ThisConnection,
  1167. &p->Read.ol,
  1168. &bytes,
  1169. TRUE, // Alertable
  1170. dwActualTimeout);
  1171. if ( status != RPC_S_OK
  1172. || bytes == 0 )
  1173. {
  1174. // if we timed out ...
  1175. if (status == RPC_P_TIMEOUT)
  1176. {
  1177. ASSERT(dwActualTimeout != INFINITE);
  1178. // if we waited on the per connection timeout ...
  1179. if (fWaitOnConnectionTimeout)
  1180. {
  1181. ASSERT(p->Timeout != INFINITE);
  1182. if (dwTimeout == INFINITE)
  1183. {
  1184. // enable keep alives and wait forever
  1185. dwActualTimeout = INFINITE;
  1186. }
  1187. else
  1188. {
  1189. ASSERT(p->Timeout < dwTimeout);
  1190. // enable keep alives and wait the difference
  1191. dwActualTimeout = dwTimeout - p->Timeout;
  1192. fWaitOnConnectionTimeout = FALSE;
  1193. }
  1194. // Enable aggressive keepalives on the socket if transport
  1195. // supports it
  1196. if (WsTransportTable[p->id].fSetKeepAlive)
  1197. {
  1198. WS_P_SetKeepAliveTimeout(p->Conn.Socket,
  1199. TRUE, // OnOff
  1200. p->Timeout);
  1201. fSetKeepAliveVals = TRUE;
  1202. }
  1203. continue;
  1204. }
  1205. // else we have chosen the per operation timeout and
  1206. // have timed out on that - time to bail out
  1207. }
  1208. // Normal error path
  1209. RpcpErrorAddRecord(EEInfoGCWinsock,
  1210. status,
  1211. EEInfoDLWSSyncRecv10,
  1212. (status == RPC_S_OK ? bytes : 0));
  1213. p->WS_CONNECTION::Abort();
  1214. if ((status == RPC_S_CALL_CANCELLED) || (status == RPC_P_TIMEOUT))
  1215. {
  1216. UTIL_WaitForSyncIO(&p->Read.ol,
  1217. FALSE,
  1218. INFINITE);
  1219. if ((status == RPC_P_TIMEOUT) && fWaitOnConnectionTimeout)
  1220. {
  1221. status = RPC_P_RECEIVE_FAILED;
  1222. RpcpErrorAddRecord(EEInfoGCWinsock,
  1223. status,
  1224. EEInfoDLWSSyncRecv20);
  1225. }
  1226. }
  1227. else
  1228. {
  1229. status = RPC_P_RECEIVE_FAILED;
  1230. RpcpErrorAddRecord(EEInfoGCWinsock,
  1231. status,
  1232. EEInfoDLWSSyncRecv30);
  1233. }
  1234. return(status);
  1235. }
  1236. }
  1237. while (status == RPC_P_TIMEOUT);
  1238. status = p->ProcessRead(bytes, pBuffer, pBufferLength);
  1239. }
  1240. while (status == RPC_P_PARTIAL_RECEIVE);
  1241. p->dwLastCallTime = GetTickCount();
  1242. if (fSetKeepAliveVals)
  1243. {
  1244. // Call complete okay, clear keep alives
  1245. WS_P_SetKeepAliveTimeout(p->Conn.Socket,
  1246. FALSE, // OnOff
  1247. 0);
  1248. }
  1249. return(status);
  1250. }
  1251. RPC_STATUS
  1252. RPC_ENTRY
  1253. WS_SyncRecv_Avrf(
  1254. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  1255. OUT BUFFER *pBuffer,
  1256. OUT PUINT pBufferLength,
  1257. IN DWORD dwTimeout
  1258. )
  1259. /*++
  1260. Routine Description:
  1261. Wrapper for WS_SyncRecv implementing corruption injection
  1262. under the RPC verifier.
  1263. SyncRecv member of the transport interface may only be called
  1264. by the cliet, hence we inject the corruption for a client receive.
  1265. Arguments:
  1266. Return Value:
  1267. --*/
  1268. {
  1269. RPC_STATUS Status;
  1270. Status = WS_SyncRecv(
  1271. ThisConnection,
  1272. pBuffer,
  1273. pBufferLength,
  1274. dwTimeout);
  1275. if (!Status)
  1276. {
  1277. if (gfRPCVerifierEnabled)
  1278. {
  1279. CorruptionInject(ClientReceive,
  1280. pBufferLength,
  1281. (void **)pBuffer);
  1282. }
  1283. }
  1284. return Status;
  1285. }
  1286. void
  1287. RPC_ENTRY
  1288. WS_ServerAbortListen(
  1289. IN RPC_TRANSPORT_ADDRESS Address
  1290. )
  1291. /*++
  1292. Routine Description:
  1293. This routine will be called if an error occurs in setting up the
  1294. address between the time that SetupWithEndpoint or SetupUnknownEndpoint
  1295. successfully completed and before the next call into this loadable
  1296. transport module. We need to do any cleanup from Setup*.
  1297. Arguments:
  1298. pAddress - The address which is being aborted.
  1299. Return Value:
  1300. None
  1301. --*/
  1302. {
  1303. PWS_ADDRESS pList = (PWS_ADDRESS)Address;
  1304. PWS_ADDRESS pLast = 0;
  1305. INT i, retval;
  1306. delete pList->pAddressVector;
  1307. delete pList->Endpoint;
  1308. TransportProtocol::RemoveObjectFromProtocolList(pList);
  1309. while(pList)
  1310. {
  1311. if (pList->ListenSocket)
  1312. {
  1313. closesocket(pList->ListenSocket);
  1314. }
  1315. if (pList->ConnectionSocket)
  1316. {
  1317. closesocket(pList->ConnectionSocket);
  1318. }
  1319. pLast = pList;
  1320. pList = (PWS_ADDRESS) pList->pNextAddress;
  1321. if (pLast != (PWS_ADDRESS)Address)
  1322. {
  1323. TransportProtocol::RemoveObjectFromProtocolList(pLast);
  1324. delete pLast;
  1325. }
  1326. }
  1327. return;
  1328. }
  1329. VOID
  1330. WS_SubmitAccept(
  1331. BASE_ADDRESS *Address
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. Used to submit an accept on a listen socket. Called once when the
  1336. listen socket is created and again after each client connects.
  1337. The listen socket must already be added to the completion port.
  1338. Arguments:
  1339. Address - The address to accept on.
  1340. ->ConnectionSocket - socket to accept on, or zero in
  1341. which case a new socket is allocated and put here.
  1342. Return Value:
  1343. None
  1344. --*/
  1345. {
  1346. PWS_ADDRESS pAddress = (PWS_ADDRESS)Address;
  1347. const WS_TRANS_INFO *pInfo = &WsTransportTable[pAddress->id];
  1348. SOCKET sAccept;
  1349. RPC_STATUS status;
  1350. #ifdef MAJOR_TRANS_DEBUG
  1351. DbgPrint("WS_SubmitAccept: Address=0x%x ListenAddr=%x\n", pAddress, (DWORD)pAddress->ListenAddr.inetaddr.sin_addr.S_un.S_addr);
  1352. #endif
  1353. if (pAddress->ConnectionSocket != 0)
  1354. {
  1355. closesocket(pAddress->ConnectionSocket);
  1356. pAddress->ConnectionSocket = 0;
  1357. }
  1358. pAddress->ConnectionSocket =
  1359. WSASocketT(pInfo->AddressFamily,
  1360. pInfo->SocketType,
  1361. pInfo->Protocol * GetProtocolMultiplier(pAddress),
  1362. 0,
  1363. 0,
  1364. WSA_FLAG_OVERLAPPED);
  1365. #ifdef MAJOR_TRANS_DEBUG
  1366. DbgPrint("WS_SubmitAccept: WSASocketT: pAddress->ConnectionSocket=%x\n", pAddress->ConnectionSocket);
  1367. #endif
  1368. if (pAddress->ConnectionSocket == SOCKET_ERROR)
  1369. {
  1370. pAddress->ConnectionSocket = 0;
  1371. COMMON_AddressManager(Address);
  1372. return;
  1373. }
  1374. //
  1375. // make the handle non-inheritable so it goes away when we close it.
  1376. // join the socket to the completion port
  1377. //
  1378. if (FALSE == SetHandleInformation( (HANDLE) pAddress->ConnectionSocket, HANDLE_FLAG_INHERIT, 0) ||
  1379. RPC_S_OK != COMMON_PrepareNewHandle((HANDLE) pAddress->ConnectionSocket))
  1380. {
  1381. closesocket(pAddress->ConnectionSocket);
  1382. pAddress->ConnectionSocket = 0;
  1383. COMMON_AddressManager(Address);
  1384. return;
  1385. }
  1386. ASSERT(pAddress->ConnectionSocket != INVALID_SOCKET);
  1387. DWORD bytes = 0;
  1388. BOOL b = pAddress->pAcceptExFunction(pAddress->ListenSocket,
  1389. pAddress->ConnectionSocket,
  1390. &pAddress->AcceptBuffer,
  1391. 0,
  1392. 0,
  1393. sizeof(WS_SOCKADDR) + 16,
  1394. &bytes,
  1395. &pAddress->Listen.ol
  1396. );
  1397. #ifdef MAJOR_TRANS_DEBUG
  1398. DbgPrint("WS_SubmitAccept: pAddress->pAcceptExFunction: b=%x GetLastError()=%x\n", b, GetLastError());
  1399. #endif
  1400. if (!b && (GetLastError() != ERROR_IO_PENDING))
  1401. {
  1402. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  1403. DPFLTR_WARNING_LEVEL,
  1404. "AcceptEx failed %p, %d %d\n",
  1405. pAddress,
  1406. pAddress->ConnectionSocket,
  1407. GetLastError()));
  1408. closesocket(pAddress->ConnectionSocket);
  1409. pAddress->ConnectionSocket = 0;
  1410. COMMON_AddressManager(Address);
  1411. }
  1412. return;
  1413. }
  1414. void
  1415. WS_SetSockOptForConnection (
  1416. IN const WS_TRANS_INFO *pInfo,
  1417. IN SOCKET sock
  1418. )
  1419. /*++
  1420. Routine Description:
  1421. Sets the socket options for the given socket for a server
  1422. side connection socket.
  1423. Arguments:
  1424. pInfo - the transport information for the Winsock transport
  1425. sock - the socket on which to set options
  1426. Return Value:
  1427. None. Setting the options is a best effort. Failures are ignored.
  1428. --*/
  1429. {
  1430. int retval = 0;
  1431. if (pInfo->fSetNoDelay)
  1432. {
  1433. INT NoDelay = TRUE;
  1434. retval = setsockopt(sock,
  1435. pInfo->Protocol,
  1436. TCP_NODELAY,
  1437. (PCHAR)&NoDelay, sizeof(NoDelay)
  1438. );
  1439. }
  1440. if ( pInfo->fSetKeepAlive
  1441. && retval == 0)
  1442. {
  1443. INT KeepAlive = TRUE;
  1444. retval = setsockopt(sock,
  1445. pInfo->Protocol,
  1446. SO_KEEPALIVE,
  1447. (PCHAR)&KeepAlive, sizeof(KeepAlive)
  1448. );
  1449. }
  1450. if (retval != 0)
  1451. {
  1452. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  1453. DPFLTR_WARNING_LEVEL,
  1454. RPCTRANS "setsockopt failed %d, %d\n",
  1455. retval,
  1456. GetLastError()));
  1457. }
  1458. }
  1459. RPC_STATUS
  1460. WS_NewConnection(
  1461. IN PADDRESS Address,
  1462. OUT PCONNECTION *ppConnection
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Called when an AcceptEx completes on an I/O completion thread.
  1467. Arguments:
  1468. Address - The address used as context in a previous AcceptEx.
  1469. ppConnection - A place to store the new pConnection. Used
  1470. when a connection been created and then a failure occurs.
  1471. Return Value:
  1472. RPC_S_OK
  1473. RPC_S_OUT_OF_RESOURCES
  1474. RPC_S_OUT_OF_MEMORY
  1475. --*/
  1476. {
  1477. RPC_STATUS status;
  1478. BOOL b;
  1479. WS_ADDRESS *pAddress = (WS_ADDRESS *)Address;
  1480. const WS_TRANS_INFO *pInfo = &WsTransportTable[pAddress->id];
  1481. WS_CONNECTION *pConnection;
  1482. UINT fReceiveDirect;
  1483. SOCKET sock = pAddress->ConnectionSocket;
  1484. int retval = 0;
  1485. WS_SOCKADDR *saAddrs;
  1486. WS_SOCKADDR saClient;
  1487. INT adwAddrLen;
  1488. BOOL fSANConnection;
  1489. int LocalAddressLength = 0;
  1490. PSOCKADDR DummyAddr = NULL;
  1491. ASSERT(sock);
  1492. pAddress->ConnectionSocket = 0;
  1493. // First, parse the client address out of the accept
  1494. // since the next accept will reuse the same buffer.
  1495. pAddress->pGetAcceptExSockaddressFunction(&pAddress->AcceptBuffer,
  1496. 0,
  1497. 0,
  1498. sizeof(WS_SOCKADDR) + 16,
  1499. &DummyAddr,
  1500. &LocalAddressLength,
  1501. (struct sockaddr **)&saAddrs,
  1502. &adwAddrLen);
  1503. ASSERT(adwAddrLen <= sizeof(WS_SOCKADDR));
  1504. // Save the client address before submitting the next accept.
  1505. saClient = *saAddrs;
  1506. // Submit the next accept.
  1507. WS_SubmitAccept(pAddress);
  1508. // Now, try process the new connection..
  1509. WS_SetSockOptForConnection(pInfo, sock);
  1510. /*
  1511. fSANConnection = IsUserModeSocket(sock, &status);
  1512. if (status != RPC_S_OK)
  1513. {
  1514. closesocket(sock);
  1515. return status;
  1516. }
  1517. */
  1518. fSANConnection = TRUE;
  1519. //
  1520. // Notes:
  1521. //
  1522. // a. For security reasons, we require the RPC HTTP Servers to send back
  1523. // an identification message.
  1524. //
  1525. // b. This should "really" be done in WS_SubmitAccept(). This is done here
  1526. // for convenience. This is OK if HttpSendIdentifyRespomse() rarely
  1527. // fails.
  1528. //
  1529. if ((pAddress->id == HTTP) &&
  1530. (status = HttpSendIdentifyResponse(sock)))
  1531. {
  1532. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  1533. DPFLTR_WARNING_LEVEL,
  1534. "HttpSendIdentifyResponse failed %p, %d - %d\n",
  1535. pAddress,
  1536. sock,
  1537. status
  1538. ));
  1539. closesocket(sock);
  1540. return(RPC_S_OUT_OF_RESOURCES);
  1541. }
  1542. BASE_ADDRESS *pRealAddress = pAddress->pFirstAddress;
  1543. pConnection = (WS_CONNECTION *)
  1544. I_RpcTransServerNewConnection(pRealAddress);
  1545. *ppConnection = pConnection;
  1546. if (!pConnection)
  1547. {
  1548. // Abort the connection.
  1549. INT DontLinger = TRUE;
  1550. // REVIEW: check a protocol flag to do this?
  1551. retval = setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
  1552. (PCHAR)&DontLinger, sizeof(DontLinger));
  1553. // setsockopt can fail with something like WSAENOBUFS in low
  1554. // memory conditions. We can't handle this in any special way.
  1555. closesocket(sock);
  1556. return(RPC_S_OUT_OF_MEMORY);
  1557. }
  1558. // Got a good connection, initialize it..
  1559. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1560. // This function cannot fail after this point. There is no
  1561. // way to notify the runtime that the connection has been closed.
  1562. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1563. #ifdef NETBIOS_ON
  1564. if ((pAddress->id == NBF)
  1565. || (pAddress->id == NBT)
  1566. || (pAddress->id == NBI))
  1567. {
  1568. if (fSANConnection)
  1569. pConnection = new (pConnection) NB_SAN_CONNECTION;
  1570. else
  1571. pConnection = new (pConnection) NB_CONNECTION;
  1572. }
  1573. else
  1574. #endif
  1575. if (pAddress->id == HTTP)
  1576. {
  1577. pConnection = new (pConnection) WS_HTTP2_INITIAL_CONNECTION;
  1578. }
  1579. else
  1580. {
  1581. if (fSANConnection)
  1582. pConnection = new (pConnection) WS_SAN_CONNECTION;
  1583. else
  1584. pConnection = new (pConnection) WS_CONNECTION;
  1585. }
  1586. pConnection->type = SERVER | CONNECTION;
  1587. pConnection->id = pAddress->id;
  1588. pConnection->Conn.Socket = sock;
  1589. pConnection->fAborted = 0;
  1590. pConnection->pReadBuffer = 0;
  1591. pConnection->maxReadBuffer = 0;
  1592. pConnection->iLastRead = 0;
  1593. pConnection->iPostSize = gPostSize;
  1594. pConnection->saClientAddress = saClient;
  1595. RpcpMemorySet(&pConnection->Read.ol, 0, sizeof(pConnection->Read.ol));
  1596. pConnection->Read.pAsyncObject = pConnection;
  1597. pConnection->InitIoCounter();
  1598. pConnection->pAddress = pAddress;
  1599. TransportProtocol::AddObjectToProtocolList((BASE_ASYNC_OBJECT *) *ppConnection);
  1600. return(RPC_S_OK);
  1601. }
  1602. BOOL
  1603. IsUserModeSocket(
  1604. IN SOCKET s,
  1605. OUT RPC_STATUS *pStatus)
  1606. /*++
  1607. Routine Description:
  1608. Given a socket, it tells whether this is a true kernel socket or not. This test is based per VadimE's input
  1609. that:
  1610. "Just call getsockopt (SOL_SOCKET, SO_PROTOCOL_INFOW) and check XP1_IFS_HANDLES in
  1611. dwServiceFlags1 of WSAPROTOCOL_INFOW. If flag is not set, the handle is not "TRUE"
  1612. IFS handle and file system calls on them carry performance penalty.
  1613. Make sure you call after connection is established or information returned may be
  1614. inaccurate."
  1615. Arguments:
  1616. s - The socket to be tested
  1617. pStatus - RPC_S_OK if everything is fine. RPC_S_OUT_OF_MEMORY if the test could not be performed. Note
  1618. that in the latter case the return value is undefined and should be disregarded.
  1619. Return Value:
  1620. TRUE - the socket is a true kernel socket
  1621. FALSE - the socket is not a kernel socket
  1622. --*/
  1623. {
  1624. WSAPROTOCOL_INFO protocolInfo;
  1625. int paramSize = sizeof(protocolInfo);
  1626. int retval;
  1627. // check whether this is a kernel connection. We do this by checking whether this socket is a true
  1628. // IFS_HANDLE. If yes, then this is not a kernel socket. If not, then it is a kernel socket
  1629. retval = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOW, (char *) &protocolInfo, &paramSize);
  1630. if (retval == SOCKET_ERROR)
  1631. {
  1632. *pStatus = RPC_S_OUT_OF_MEMORY;
  1633. return FALSE;
  1634. }
  1635. *pStatus = RPC_S_OK;
  1636. if (protocolInfo.dwServiceFlags1 & XP1_IFS_HANDLES)
  1637. return FALSE;
  1638. else
  1639. return TRUE;
  1640. }
  1641. RPC_STATUS
  1642. WS_ServerListenCommon (
  1643. IN WS_ADDRESS *pAddress,
  1644. IN BOOL fResetAddressListEntries, OPTIONAL
  1645. IN BOOL fAddToProtocolList OPTIONAL
  1646. )
  1647. /*++
  1648. Routine Description:
  1649. This routine does common server address setup.
  1650. Arguments:
  1651. pAddress - A pointer to the loadable transport interface address.
  1652. Will contain the newly allocated listen socket when finished.
  1653. pListenAddr - Initalized socket address to bind to. On output
  1654. it will contain results of the bind.
  1655. PendingQueueSize - Value specified in use protseq, used
  1656. to set the pending queue size for listens.
  1657. ReturnValue:
  1658. RPC_S_OK
  1659. RPC_S_OUT_OF_MEMORY
  1660. RPC_S_OUT_OF_RESOURCES
  1661. RPC_S__CANT_CREATE_ENDPOINT
  1662. --*/
  1663. {
  1664. SOCKET sock;
  1665. int retval, length;
  1666. RPC_STATUS status;
  1667. const WS_TRANS_INFO *pInfo = &WsTransportTable[pAddress->id];
  1668. WS_SOCKADDR *pListenAddr = &(pAddress->ListenAddr);
  1669. DWORD EndpointFlags = pAddress->EndpointFlags;
  1670. BOOL fRetVal;
  1671. int i;
  1672. DWORD LastError;
  1673. pAddress->type = ADDRESS;
  1674. pAddress->InAddressList = NotInList;
  1675. pAddress->fAborted = 0;
  1676. pAddress->pNext = 0;
  1677. pAddress->ListenSocket = 0;
  1678. pAddress->ConnectionSocket = 0;
  1679. // We may be called on an address that is enlinked in a list
  1680. // and does not want these entries reset.
  1681. if (fResetAddressListEntries)
  1682. {
  1683. pAddress->pNextAddress = 0;
  1684. pAddress->pFirstAddress = pAddress;
  1685. }
  1686. memset(&pAddress->Listen, 0, sizeof(BASE_OVERLAPPED));
  1687. pAddress->Listen.pAsyncObject = pAddress;
  1688. for (i = FIRST_EXTENSION_FUNCTION_CODE; i < LAST_EXTENSION_FUNCTION_CODE; i ++)
  1689. {
  1690. pAddress->ExtensionFunctionPointers[i] = NULL;
  1691. }
  1692. if (fAddToProtocolList)
  1693. {
  1694. RpcpInitializeListHead(&pAddress->ObjectList);
  1695. }
  1696. // First order of business: get a valid socket
  1697. //
  1698. sock = WSASocketT(pInfo->AddressFamily,
  1699. pInfo->SocketType,
  1700. pInfo->Protocol,
  1701. 0,
  1702. 0,
  1703. WSA_FLAG_OVERLAPPED);
  1704. if (sock == INVALID_SOCKET)
  1705. {
  1706. LastError = GetLastError();
  1707. RpcpErrorAddRecord(EEInfoGCWinsock,
  1708. LastError,
  1709. EEInfoDLWSServerListenCommon10,
  1710. pInfo->AddressFamily,
  1711. pInfo->SocketType,
  1712. pInfo->Protocol);
  1713. switch(LastError)
  1714. {
  1715. case WSAENETDOWN:
  1716. case WSAEINVAL:
  1717. case WSAEPROTOTYPE:
  1718. case WSAENOPROTOOPT:
  1719. case WSAEPROTONOSUPPORT:
  1720. case WSAESOCKTNOSUPPORT:
  1721. case WSAEPFNOSUPPORT:
  1722. case WSAEADDRNOTAVAIL:
  1723. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  1724. break;
  1725. case WSAEAFNOSUPPORT:
  1726. status = RPC_P_ADDRESS_FAMILY_INVALID;
  1727. break;
  1728. case WSAENOBUFS:
  1729. case WSAEMFILE:
  1730. case WSA_NOT_ENOUGH_MEMORY:
  1731. status = RPC_S_OUT_OF_MEMORY;
  1732. break;
  1733. default:
  1734. ASSERT(0);
  1735. // !break
  1736. case WSAEPROVIDERFAILEDINIT:
  1737. status = RPC_S_OUT_OF_RESOURCES;
  1738. break;
  1739. }
  1740. RpcpErrorAddRecord(EEInfoGCRuntime,
  1741. status,
  1742. EEInfoDLWSServerListenCommon30);
  1743. return(status);
  1744. }
  1745. //
  1746. // Make the handle non-inheritable so it goes away when we close it.
  1747. //
  1748. if (FALSE == SetHandleInformation( (HANDLE) sock, HANDLE_FLAG_INHERIT, 0))
  1749. {
  1750. closesocket(sock);
  1751. return RPC_S_OUT_OF_RESOURCES;
  1752. }
  1753. fRetVal = pAddress->GetExtensionFunctionPointers(sock);
  1754. if (!fRetVal)
  1755. {
  1756. switch (GetLastError())
  1757. {
  1758. case WSAEFAULT:
  1759. case WSAEINVAL:
  1760. status = RPC_S_INTERNAL_ERROR;
  1761. break;
  1762. case WSAEOPNOTSUPP:
  1763. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  1764. break;
  1765. default:
  1766. status = RPC_S_OUT_OF_RESOURCES;
  1767. }
  1768. closesocket(sock);
  1769. return(status);
  1770. }
  1771. //
  1772. // Try to bind to the given port number...
  1773. //
  1774. pListenAddr->generic.sa_family = pInfo->AddressFamily;
  1775. // N.B. - we should think how the port allocation will look for TCP/IPv6
  1776. status = WS_Bind(sock, pListenAddr, (pAddress->id == TCP) || (pAddress->id == HTTP), EndpointFlags);
  1777. if (status != RPC_S_OK)
  1778. {
  1779. closesocket(sock);
  1780. return(status);
  1781. }
  1782. if(listen(sock, pAddress->QueueSize) == SOCKET_ERROR)
  1783. {
  1784. RpcpErrorAddRecord(EEInfoGCWinsock,
  1785. RPC_S_OUT_OF_RESOURCES,
  1786. EEInfoDLWSServerListenCommon20,
  1787. GetLastError(),
  1788. (ULONGLONG)sock,
  1789. (ULONG)pAddress->QueueSize);
  1790. closesocket(sock);
  1791. return(RPC_S_OUT_OF_RESOURCES);
  1792. }
  1793. status = COMMON_PrepareNewHandle((HANDLE)sock);
  1794. if (status != RPC_S_OK)
  1795. {
  1796. closesocket(sock);
  1797. return(status);
  1798. }
  1799. pAddress->ListenSocket = sock;
  1800. if (fAddToProtocolList)
  1801. {
  1802. TransportProtocol::AddObjectToProtocolList((BASE_ASYNC_OBJECT *) pAddress);
  1803. }
  1804. TransportProtocol::FunctionalProtocolDetected(pAddress->id);
  1805. return(RPC_S_OK);
  1806. }
  1807. NETWORK_ADDRESS_VECTOR *
  1808. WS_GetNetworkAddressVector (
  1809. IN RPC_TRANSPORT_ADDRESS ThisAddress
  1810. )
  1811. {
  1812. PWS_ADDRESS pAddress = (PWS_ADDRESS)ThisAddress;
  1813. ASSERT(pAddress->pAddressVector);
  1814. #ifdef MAJOR_TRANS_DEBUG
  1815. DbgPrint("WS_GetNetworkAddressVector: pAddress=0x%x pAddressVector=0x%x\n", pAddress, pAddress->pAddressVector);
  1816. #endif
  1817. return pAddress->pAddressVector;
  1818. }
  1819. RPC_STATUS
  1820. WS_Initialize_Internal (
  1821. IN PWS_CCONNECTION pConnection
  1822. )
  1823. {
  1824. pConnection->Initialize();
  1825. pConnection->fCallStarted = FALSE;
  1826. pConnection->fShutdownReceived = FALSE;
  1827. pConnection->fReceivePending = FALSE;
  1828. pConnection->dwLastCallTime = GetTickCount();
  1829. pConnection->pAddress = NULL;
  1830. RpcpInitializeListHead(&pConnection->ObjectList);
  1831. return RPC_S_OK;
  1832. }
  1833. RPC_STATUS
  1834. WS_Initialize (
  1835. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  1836. IN RPC_CHAR *NetworkAddress,
  1837. IN RPC_CHAR *NetworkOptions,
  1838. IN BOOL fAsync
  1839. )
  1840. {
  1841. PWS_CCONNECTION p = (PWS_CCONNECTION) ThisConnection;
  1842. p->id = INVALID_PROTOCOL_ID;
  1843. return WS_Initialize_Internal(p);
  1844. }
  1845. const UUID ConnectExExtensionFunctionUuid = WSAID_CONNECTEX;
  1846. RPC_STATUS
  1847. WS_Open(
  1848. IN PWS_CCONNECTION p,
  1849. IN WS_SOCKADDR *psa,
  1850. IN UINT ConnTimeout,
  1851. IN UINT SendBufferSize,
  1852. IN UINT RecvBufferSize,
  1853. IN ULONG CallTimeout,
  1854. IN BOOL fHTTP2Open
  1855. )
  1856. /*++
  1857. Routine Description:
  1858. Common part of opening a winsock connection to a server.
  1859. Arguments:
  1860. p - The partially initialized client connection object. If fHTTP2,
  1861. this is a connection object, not client connection object.
  1862. psa - sockaddr with protocol specific part already containing
  1863. this address and port of the server.
  1864. ConnTimeout - Valid for TCP/IP, see SyncRecv error handling.
  1865. {Send,Recv}BufferSize - Used to set the transport buffer
  1866. sizes on some protocols. Currently ignored.
  1867. CallTimeout - call timeout in milliseconds
  1868. fHTTP2Open - the open is an HTTP2 open
  1869. Return Value:
  1870. RPC_S_OK
  1871. RPC_S_OUT_OF_RESOURCES
  1872. RPC_S_OUT_OF_MEMORY
  1873. RPC_S_SERVER_UNAVAILABLE - failed
  1874. ERROR_RETRY - failed, but another address might work.
  1875. --*/
  1876. {
  1877. // Initialize common part of the connection object
  1878. const WS_TRANS_INFO *pInfo = &WsTransportTable[p->id];
  1879. SOCKET sock;
  1880. RPC_STATUS status;
  1881. BOOL fSANConnection;
  1882. DWORD LastError;
  1883. RPC_CLIENT_PROCESS_IDENTIFIER ServerAddress;
  1884. HANDLE hEvent;
  1885. OVERLAPPED ol;
  1886. DWORD dwBytesReturned;
  1887. LPFN_CONNECTEX ConnectEx;
  1888. union
  1889. {
  1890. SOCKADDR_IN sockaddr;
  1891. SOCKADDR_IN6 sockaddr6;
  1892. };
  1893. int NameLen;
  1894. DWORD Transfer;
  1895. DWORD Flags;
  1896. // Set if we had already called GetLastErrorand added EEInfo.
  1897. // Adding EEInfo may overwrite the LastError and getting it second
  1898. // time will return 0 and cause an assert.
  1899. BOOL fGetLastErrorCalled = FALSE;
  1900. if (!fHTTP2Open)
  1901. {
  1902. WS_Initialize_Internal(p);
  1903. }
  1904. //
  1905. // Open a socket
  1906. //
  1907. sock = WSASocketT(pInfo->AddressFamily,
  1908. pInfo->SocketType,
  1909. pInfo->Protocol,
  1910. 0,
  1911. 0,
  1912. WSA_FLAG_OVERLAPPED);
  1913. if (sock == INVALID_SOCKET)
  1914. {
  1915. LastError = GetLastError();
  1916. RpcpErrorAddRecord(EEInfoGCWinsock,
  1917. LastError,
  1918. EEInfoDLWSOpen10,
  1919. pInfo->AddressFamily,
  1920. pInfo->SocketType,
  1921. pInfo->Protocol);
  1922. switch(LastError)
  1923. {
  1924. case WSAEAFNOSUPPORT:
  1925. case WSAEPROTONOSUPPORT:
  1926. case WSAEPROTOTYPE:
  1927. case WSAENETDOWN:
  1928. case WSAESOCKTNOSUPPORT:
  1929. case WSAEINVAL: // when registry is not yet setup.
  1930. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  1931. break;
  1932. case ERROR_NOT_ENOUGH_QUOTA:
  1933. case WSAENOBUFS:
  1934. case WSAEMFILE:
  1935. case WSA_NOT_ENOUGH_MEMORY:
  1936. // This failure is possible in low memory conditions
  1937. // or due to fault injection during registry read or
  1938. // notification creation.
  1939. case WSASYSCALLFAILURE:
  1940. status = RPC_S_OUT_OF_MEMORY;
  1941. break;
  1942. case ERROR_ACCESS_DENIED:
  1943. status = RPC_S_ACCESS_DENIED;
  1944. break;
  1945. default:
  1946. ASSERT(0);
  1947. // no break - fall through
  1948. case WSAEPROVIDERFAILEDINIT:
  1949. status = RPC_S_OUT_OF_RESOURCES;
  1950. break;
  1951. }
  1952. RpcpErrorAddRecord(EEInfoGCRuntime,
  1953. status,
  1954. EEInfoDLWSOpen30);
  1955. return (status);
  1956. }
  1957. //
  1958. // make the handle non-inheritable so it goes away when we close it.
  1959. //
  1960. if (FALSE == SetHandleInformation( (HANDLE) sock, HANDLE_FLAG_INHERIT, 0))
  1961. {
  1962. closesocket(sock);
  1963. return RPC_S_OUT_OF_RESOURCES;
  1964. }
  1965. p->Conn.Socket = sock;
  1966. //
  1967. // Set socket options
  1968. //
  1969. // REVIEW: Set loopback socket option? Ask winsock folks.
  1970. DWORD option;
  1971. int retval = 0;
  1972. if (pInfo->fSetNoDelay)
  1973. {
  1974. option = TRUE;
  1975. retval = setsockopt( sock, pInfo->Protocol, TCP_NODELAY,
  1976. (PCHAR)&option, sizeof(option) );
  1977. }
  1978. if (pInfo->fSetKeepAlive && retval == 0)
  1979. {
  1980. option = TRUE;
  1981. retval = setsockopt( sock, pInfo->Protocol, SO_KEEPALIVE,
  1982. (PCHAR)&option, sizeof(option) );
  1983. }
  1984. if ( pInfo->fSetSendBuffer
  1985. && SendBufferSize
  1986. && retval == 0)
  1987. {
  1988. ASSERT(SendBufferSize <= 0xFFFF);
  1989. retval = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
  1990. (PCHAR)&SendBufferSize, sizeof(UINT) );
  1991. }
  1992. if ( pInfo->fSetRecvBuffer
  1993. && RecvBufferSize
  1994. && retval == 0 )
  1995. {
  1996. ASSERT(RecvBufferSize <= 0xFFFF);
  1997. retval = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
  1998. (PCHAR)&RecvBufferSize, sizeof(UINT) );
  1999. }
  2000. if (retval)
  2001. {
  2002. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  2003. DPFLTR_WARNING_LEVEL,
  2004. RPCTRANS "setsockopt failed %d\n",
  2005. GetLastError()));
  2006. p->WS_CONNECTION::Abort();
  2007. return(RPC_S_OUT_OF_RESOURCES);
  2008. }
  2009. if (!fHTTP2Open)
  2010. {
  2011. //
  2012. // Set timeout
  2013. //
  2014. if ( WsTransportTable[p->id].fSetKeepAlive
  2015. && ConnTimeout != RPC_C_BINDING_INFINITE_TIMEOUT)
  2016. {
  2017. ASSERT( ((long)ConnTimeout >= RPC_C_BINDING_MIN_TIMEOUT)
  2018. && (ConnTimeout <= RPC_C_BINDING_MAX_TIMEOUT));
  2019. // convert the timeout from runtime scale to transport scale
  2020. p->Timeout = ConvertRuntimeTimeoutToWSTimeout(ConnTimeout);
  2021. }
  2022. else
  2023. {
  2024. p->Timeout = INFINITE;
  2025. }
  2026. }
  2027. //
  2028. // HTTP specific connect() done in HTTP_Open().
  2029. //
  2030. if (p->id == HTTP)
  2031. {
  2032. //
  2033. // For HTTP, add the new socket to the io completion port
  2034. // now. For TCP, we'll add it later.
  2035. //
  2036. status = COMMON_PrepareNewHandle((HANDLE)sock);
  2037. if (status != RPC_S_OK)
  2038. {
  2039. closesocket(sock);
  2040. return status;
  2041. }
  2042. return (RPC_S_OK);
  2043. }
  2044. //
  2045. // Connect the socket to the server
  2046. //
  2047. psa->generic.sa_family = pInfo->AddressFamily;
  2048. if ((CallTimeout == INFINITE) || (CallTimeout == 0)
  2049. #ifdef SPX_ON
  2050. || (p->id == SPX)
  2051. #endif
  2052. )
  2053. {
  2054. retval = connect(sock, &psa->generic, pInfo->SockAddrSize);
  2055. }
  2056. else
  2057. {
  2058. // we have a specified call timeout. Use ConnectEx instead
  2059. // first, bind the socket. Unlike connect, ConnectEx doesn't
  2060. // accept unbound sockets
  2061. if (p->id != TCP_IPv6)
  2062. {
  2063. sockaddr.sin_addr.S_un.S_addr = INADDR_ANY;
  2064. sockaddr.sin_family = AF_INET;
  2065. sockaddr.sin_port = 0;
  2066. NameLen = sizeof(sockaddr);
  2067. }
  2068. else
  2069. {
  2070. IN6ADDR_SETANY(&sockaddr6);
  2071. sockaddr6.sin6_scope_id = 0;
  2072. NameLen = sizeof(sockaddr6);
  2073. }
  2074. retval = bind(sock,
  2075. (SOCKADDR *)&sockaddr,
  2076. NameLen);
  2077. if (retval == SOCKET_ERROR)
  2078. {
  2079. status = GetLastError();
  2080. RpcpErrorAddRecord(EEInfoGCWinsock,
  2081. status,
  2082. EEInfoDLWSOpen60);
  2083. fGetLastErrorCalled = TRUE;
  2084. goto Handle_WS_OpenError;
  2085. }
  2086. // second retrieve address of ConnectEx
  2087. retval = WSAIoctl(sock,
  2088. SIO_GET_EXTENSION_FUNCTION_POINTER,
  2089. (void *) &ConnectExExtensionFunctionUuid,
  2090. sizeof(UUID),
  2091. (void *) &ConnectEx,
  2092. sizeof(void *),
  2093. &dwBytesReturned,
  2094. NULL, // lpOverlapped
  2095. NULL // lpCompletionRoutine
  2096. );
  2097. if (retval == SOCKET_ERROR)
  2098. {
  2099. // ConnectEx is not available. We need to default to using connect.
  2100. retval = connect(sock, &psa->generic, pInfo->SockAddrSize);
  2101. }
  2102. else
  2103. {
  2104. // Use ConnectEx.
  2105. ASSERT(dwBytesReturned == sizeof(void *));
  2106. hEvent = I_RpcTransGetThreadEvent();
  2107. ASSERT(hEvent);
  2108. ol.Internal = 0;
  2109. ol.InternalHigh = 0;
  2110. ol.Offset = 0;
  2111. ol.OffsetHigh = 0;
  2112. // There may be a window between winsock's raising the event to signal IO completion
  2113. // and checking if there is a completion port associated with the socket. We
  2114. // need to make sure that the IO completion packet will not be posted to a port if
  2115. // we associate it with the socket after the event is raised but before the packet is posted.
  2116. ol.hEvent = (HANDLE) ((ULONG_PTR)hEvent | 0x1);
  2117. retval = ConnectEx(sock,
  2118. &psa->generic,
  2119. pInfo->SockAddrSize,
  2120. NULL, // lpSendBuffer
  2121. 0, // dwSendDataLength
  2122. NULL, // lpdwBytesSent
  2123. &ol);
  2124. // N.B. ConnectEx returns the opposite of connect - TRUE for
  2125. // success and FALSE for failure. Since the error handling is
  2126. // common, we must make the return value consistent. We do this
  2127. // by reverting the return value for ConnectEx
  2128. retval = !retval;
  2129. if (retval != 0)
  2130. {
  2131. LastError = GetLastError();
  2132. if ((LastError != ERROR_IO_PENDING) && (LastError != WSA_IO_PENDING))
  2133. {
  2134. RpcpErrorAddRecord(EEInfoGCWinsock,
  2135. LastError,
  2136. EEInfoDLWSOpen80);
  2137. status = LastError;
  2138. fGetLastErrorCalled = TRUE;
  2139. goto Handle_WS_OpenError;
  2140. }
  2141. // wait for the result or for timeout
  2142. LastError = WaitForSingleObject(hEvent, CallTimeout);
  2143. if (LastError == WAIT_TIMEOUT)
  2144. {
  2145. // we have hit a timeout. Kill the socket and bail out
  2146. status = RPC_S_CALL_CANCELLED;
  2147. RpcpErrorAddRecord(EEInfoGCRuntime,
  2148. status,
  2149. EEInfoDLWSOpen50,
  2150. CallTimeout);
  2151. p->WS_CONNECTION::Abort();
  2152. // wait for our IO to complete. Should be quick after
  2153. // we closed the socket
  2154. LastError = WaitForSingleObject(hEvent, INFINITE);
  2155. ASSERT(LastError == WAIT_OBJECT_0);
  2156. ASSERT(HasOverlappedIoCompleted(&ol));
  2157. return status;
  2158. }
  2159. else
  2160. {
  2161. ASSERT(LastError == WAIT_OBJECT_0);
  2162. ASSERT(HasOverlappedIoCompleted(&ol));
  2163. // Retrieve the overlapped result. No need to wait since the IO has
  2164. // already completed.
  2165. if (!WSAGetOverlappedResult(sock, &ol, &Transfer, FALSE, &Flags))
  2166. {
  2167. // set retval to the WSA error code.
  2168. retval = WSAGetLastError();
  2169. RpcpErrorAddRecord(EEInfoGCWinsock,
  2170. retval,
  2171. EEInfoDLWSOpen90);
  2172. status = retval;
  2173. fGetLastErrorCalled = TRUE;
  2174. }
  2175. else
  2176. {
  2177. retval = setsockopt(sock,
  2178. SOL_SOCKET,
  2179. SO_UPDATE_CONNECT_CONTEXT,
  2180. NULL,
  2181. 0
  2182. );
  2183. }
  2184. }
  2185. }
  2186. else
  2187. {
  2188. retval = setsockopt(sock,
  2189. SOL_SOCKET,
  2190. SO_UPDATE_CONNECT_CONTEXT,
  2191. NULL,
  2192. 0
  2193. );
  2194. }
  2195. }
  2196. }
  2197. if (retval == 0)
  2198. {
  2199. //
  2200. // After we're done with connect/ConnectEx, add the socket
  2201. // to the completion port.
  2202. //
  2203. status = COMMON_PrepareNewHandle((HANDLE)sock);
  2204. if (status != RPC_S_OK)
  2205. {
  2206. goto Handle_WS_OpenError;
  2207. }
  2208. fSANConnection = IsUserModeSocket(sock, &status);
  2209. if (status == RPC_S_OK)
  2210. {
  2211. if (fSANConnection && !fHTTP2Open)
  2212. {
  2213. // reinitialize vtbl
  2214. p = new (p) WS_SAN_CLIENT_CONNECTION;
  2215. }
  2216. TransportProtocol::AddObjectToProtocolList((BASE_ASYNC_OBJECT *) p);
  2217. return(RPC_S_OK);
  2218. }
  2219. }
  2220. Handle_WS_OpenError:
  2221. if (!fGetLastErrorCalled)
  2222. {
  2223. status = GetLastError();
  2224. }
  2225. ServerAddress.ZeroOut();
  2226. if (p->id == TCP)
  2227. {
  2228. ServerAddress.SetIPv4ClientIdentifier(psa->inetaddr.sin_addr.S_un.S_addr, FALSE);
  2229. }
  2230. else if (p->id == TCP_IPv6)
  2231. {
  2232. ServerAddress.SetIPv6ClientIdentifier(&psa->ipaddr, sizeof(psa->ipaddr), FALSE);
  2233. }
  2234. RpcpErrorAddRecord(EEInfoGCWinsock,
  2235. status,
  2236. EEInfoDLWSOpen20,
  2237. (ULONG)ntohs(RpcpGetIpPort(psa)),
  2238. ServerAddress.GetDebugULongLong1(),
  2239. ServerAddress.GetDebugULongLong2());
  2240. switch(status)
  2241. {
  2242. case WSAENETUNREACH:
  2243. case STATUS_BAD_NETWORK_PATH:
  2244. case STATUS_NETWORK_UNREACHABLE:
  2245. case STATUS_PROTOCOL_UNREACHABLE:
  2246. case WSAEHOSTUNREACH:
  2247. case STATUS_HOST_UNREACHABLE:
  2248. case WSAETIMEDOUT:
  2249. case STATUS_LINK_TIMEOUT:
  2250. case STATUS_IO_TIMEOUT:
  2251. case STATUS_TIMEOUT:
  2252. case WSAEADDRNOTAVAIL:
  2253. case STATUS_INVALID_ADDRESS:
  2254. case STATUS_INVALID_ADDRESS_COMPONENT:
  2255. status = ERROR_RETRY;
  2256. break;
  2257. case WSAENOBUFS:
  2258. case STATUS_INSUFFICIENT_RESOURCES:
  2259. case STATUS_PAGEFILE_QUOTA:
  2260. case STATUS_COMMITMENT_LIMIT:
  2261. case STATUS_WORKING_SET_QUOTA:
  2262. case STATUS_NO_MEMORY:
  2263. case STATUS_QUOTA_EXCEEDED:
  2264. case STATUS_TOO_MANY_PAGING_FILES:
  2265. case STATUS_REMOTE_RESOURCES:
  2266. case ERROR_NOT_ENOUGH_MEMORY:
  2267. status = RPC_S_OUT_OF_MEMORY;
  2268. break;
  2269. case WSAECONNREFUSED:
  2270. case STATUS_REMOTE_NOT_LISTENING:
  2271. case STATUS_CONNECTION_REFUSED:
  2272. // for conn refused, we have different logic for IPv4 and IPv6
  2273. // since IPv6 is installed optionally at the time of this writing
  2274. // and is not PnP compliant in the way we need, it will not be
  2275. // picked up by the server by default. Yet the DNS entries will
  2276. // be updated. So if we have an IPv6 address, the server may
  2277. // not have picke dup IPv6 and we need to retry for IPv6 only.
  2278. if (p->id == TCP_IPv6)
  2279. {
  2280. status = ERROR_RETRY;
  2281. }
  2282. else
  2283. {
  2284. status = RPC_S_SERVER_UNAVAILABLE;
  2285. }
  2286. break;
  2287. default:
  2288. VALIDATE(status)
  2289. {
  2290. WSAENETDOWN,
  2291. STATUS_INVALID_NETWORK_RESPONSE,
  2292. STATUS_NETWORK_BUSY,
  2293. STATUS_NO_SUCH_DEVICE,
  2294. STATUS_NO_SUCH_FILE,
  2295. STATUS_OBJECT_PATH_NOT_FOUND,
  2296. STATUS_OBJECT_NAME_NOT_FOUND,
  2297. STATUS_UNEXPECTED_NETWORK_ERROR,
  2298. WSAECONNABORTED,
  2299. STATUS_LOCAL_DISCONNECT,
  2300. STATUS_TRANSACTION_ABORTED,
  2301. STATUS_CONNECTION_ABORTED,
  2302. WSAEADDRINUSE,
  2303. ERROR_CONNECTION_REFUSED,
  2304. WSAECONNRESET
  2305. } END_VALIDATE;
  2306. status = RPC_S_SERVER_UNAVAILABLE;
  2307. break;
  2308. }
  2309. RpcpErrorAddRecord(EEInfoGCWinsock,
  2310. status,
  2311. EEInfoDLWSOpen40);
  2312. p->WS_CONNECTION::Abort();
  2313. return(status);
  2314. }
  2315. /////////////////////////////////////////////////////////////////////
  2316. //
  2317. // TCP/IP specific stuff
  2318. //
  2319. RPC_STATUS
  2320. IP_ADDRESS_RESOLVER::NextAddress(
  2321. OUT SOCKADDR_STORAGE *pAddress
  2322. )
  2323. /*++
  2324. Routine Description:
  2325. Returns the next IP address associated with the Name
  2326. parameter to the constructor.
  2327. During the first call if check for loopback and for dotted numeric IP
  2328. address formats. If these fail then it begins a complex lookup
  2329. (WSALookupServiceBegin) and returns the first available address.
  2330. During successive calls in which a complex lookup was started
  2331. it returns sucessive addressed returned by WSALookupServiceNext().
  2332. Arguments:
  2333. pAddress - If successful, the pAddress->sin_addr.s_addr member is set
  2334. to an IP address to try. For all cosClients, if IPvToUse is ipvtuIPAny,
  2335. pAddress->sin_family is set to the actual address family for the
  2336. returned address. This allows client to find out what address was
  2337. returned to them.
  2338. Return Value:
  2339. RPC_S_OK - pAddress contains a new IP address
  2340. RPC_S_SERVER_UNAVAILABLE - Unable to find any more addresses
  2341. RPC_S_OUT_OF_MEMORY
  2342. --*/
  2343. {
  2344. int err;
  2345. RPC_STATUS status;
  2346. SOCKADDR_IN6 *IPv6Address = (SOCKADDR_IN6 *)pAddress;
  2347. SOCKADDR_STORAGE addr;
  2348. int ai_flags;
  2349. int i;
  2350. USES_CONVERSION;
  2351. CStackAnsi AnsiName;
  2352. BOOL fValidIPv4;
  2353. BOOL fValidIPv6;
  2354. ADDRINFO *ThisAddrInfo;
  2355. if (!AddrInfo)
  2356. {
  2357. if (!Name)
  2358. {
  2359. if (cos == cosServer)
  2360. {
  2361. if (IPvToUse == ipvtuIPv6)
  2362. {
  2363. IPv6Address->sin6_flowinfo = 0;
  2364. *((u_long *)(IPv6Address->sin6_addr.s6_addr) ) = 0;
  2365. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 1) = 0;
  2366. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 2) = 0;
  2367. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 3) = 0;
  2368. IPv6Address->sin6_scope_id = 0;
  2369. }
  2370. else
  2371. {
  2372. ASSERT(IPvToUse == ipvtuIPv4);
  2373. ((SOCKADDR_IN *)pAddress)->sin_addr.s_addr = INADDR_ANY;
  2374. }
  2375. }
  2376. else
  2377. {
  2378. if (LoopbacksReturned > 2)
  2379. {
  2380. RpcpErrorAddRecord(EEInfoGCWinsock,
  2381. RPC_S_SERVER_UNAVAILABLE,
  2382. EEInfoDLNextAddress40);
  2383. return RPC_S_SERVER_UNAVAILABLE;
  2384. }
  2385. if ((IPvToUse == ipvtuIPv6)
  2386. || ((IPvToUse == ipvtuIPAny)
  2387. &&
  2388. (LoopbacksReturned == 1)
  2389. )
  2390. )
  2391. {
  2392. IPv6Address->sin6_family = AF_INET6;
  2393. IPv6Address->sin6_flowinfo = 0;
  2394. *((u_long *)(IPv6Address->sin6_addr.s6_addr) ) = 0;
  2395. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 1) = 0;
  2396. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 2) = 0;
  2397. *((u_long *)(IPv6Address->sin6_addr.s6_addr) + 3) = 1;
  2398. IPv6Address->sin6_scope_id = 0;
  2399. }
  2400. else if ((IPvToUse == ipvtuIPv4)
  2401. || ((IPvToUse == ipvtuIPAny)
  2402. &&
  2403. (LoopbacksReturned == 0)
  2404. )
  2405. )
  2406. {
  2407. // Loopback - assign result of htonl(INADDR_LOOPBACK)
  2408. // Little-endian dependence.
  2409. ((SOCKADDR_IN *)pAddress)->sin_addr.s_addr = 0x0100007F;
  2410. ((SOCKADDR_IN *)pAddress)->sin_family = AF_INET;
  2411. }
  2412. else
  2413. {
  2414. RpcpErrorAddRecord(EEInfoGCWinsock,
  2415. RPC_S_SERVER_UNAVAILABLE,
  2416. EEInfoDLNextAddress40);
  2417. return RPC_S_SERVER_UNAVAILABLE;
  2418. }
  2419. LoopbacksReturned ++;
  2420. }
  2421. return RPC_S_OK;
  2422. }
  2423. if (cos == cosServer)
  2424. ai_flags = AI_PASSIVE;
  2425. else
  2426. ai_flags = 0;
  2427. switch (IPvToUse)
  2428. {
  2429. case ipvtuIPAny:
  2430. // make a hint for any protocol
  2431. Hint.ai_flags = ai_flags | AI_NUMERICHOST;
  2432. Hint.ai_family = PF_UNSPEC;
  2433. break;
  2434. case ipvtuIPv4:
  2435. // make a hint for any v4 protocol
  2436. Hint.ai_flags = ai_flags | AI_NUMERICHOST;
  2437. Hint.ai_family = AF_INET;
  2438. break;
  2439. case ipvtuIPv6:
  2440. // make a hint for TCPv6
  2441. Hint.ai_flags = ai_flags | AI_NUMERICHOST;
  2442. Hint.ai_family = AF_INET6;
  2443. break;
  2444. default:
  2445. ASSERT((IPvToUse == ipvtuIPAny)
  2446. || (IPvToUse == ipvtuIPv4)
  2447. || (IPvToUse == ipvtuIPv6));
  2448. }
  2449. ATTEMPT_STACK_W2A(AnsiName, Name);
  2450. err = getaddrinfo(AnsiName,
  2451. NULL,
  2452. &Hint,
  2453. &AddrInfo);
  2454. if (err)
  2455. {
  2456. ASSERT((err != EAI_BADFLAGS)
  2457. && (err != EAI_SOCKTYPE));
  2458. // take down the numeric hosts flag - we'll try
  2459. // to resolve it as a DNS name
  2460. Hint.ai_flags &= ~AI_NUMERICHOST;
  2461. err = getaddrinfo(AnsiName,
  2462. NULL,
  2463. &Hint,
  2464. &AddrInfo);
  2465. if (err)
  2466. {
  2467. RpcpErrorAddRecord(EEInfoGCWinsock,
  2468. err,
  2469. EEInfoDLNextAddress10,
  2470. Name);
  2471. if (err == EAI_MEMORY)
  2472. {
  2473. RpcpErrorAddRecord(EEInfoGCWinsock,
  2474. RPC_S_OUT_OF_MEMORY,
  2475. EEInfoDLNextAddress20);
  2476. return RPC_S_OUT_OF_MEMORY;
  2477. }
  2478. else
  2479. {
  2480. VALIDATE(err)
  2481. {
  2482. EAI_AGAIN,
  2483. EAI_FAMILY,
  2484. EAI_FAIL,
  2485. EAI_NODATA,
  2486. EAI_NONAME,
  2487. EAI_SERVICE
  2488. } END_VALIDATE;
  2489. RpcpErrorAddRecord(EEInfoGCWinsock,
  2490. RPC_S_SERVER_UNAVAILABLE,
  2491. EEInfoDLNextAddress30);
  2492. return RPC_S_SERVER_UNAVAILABLE;
  2493. }
  2494. }
  2495. }
  2496. // successfully resolved this address
  2497. // just stick it in and we'll let the code below handle it
  2498. CurrentAddrInfo = AddrInfo;
  2499. }
  2500. ASSERT(AddrInfo != NULL);
  2501. // get the next value from the cache
  2502. while (CurrentAddrInfo)
  2503. {
  2504. ThisAddrInfo = CurrentAddrInfo;
  2505. CurrentAddrInfo = CurrentAddrInfo->ai_next;
  2506. fValidIPv4 = FALSE;
  2507. fValidIPv6 = FALSE;
  2508. if (ThisAddrInfo->ai_family == AF_INET)
  2509. {
  2510. fValidIPv4 = TRUE;
  2511. }
  2512. if (ThisAddrInfo->ai_family == AF_INET6)
  2513. {
  2514. fValidIPv6 = TRUE;
  2515. }
  2516. if ((IPvToUse == ipvtuIPv4) && !fValidIPv4)
  2517. continue;
  2518. if ((IPvToUse == ipvtuIPv6) && !fValidIPv6)
  2519. continue;
  2520. if ((IPvToUse == ipvtuIPAny) && !fValidIPv4 && !fValidIPv6)
  2521. continue;
  2522. if (ThisAddrInfo->ai_family == AF_INET)
  2523. {
  2524. ASSERT((IPvToUse == ipvtuIPv4)
  2525. || (IPvToUse == ipvtuIPAny));
  2526. RpcpCopyIPv4Address((SOCKADDR_IN *)ThisAddrInfo->ai_addr, (SOCKADDR_IN *)pAddress);
  2527. ((SOCKADDR_IN *)pAddress)->sin_family = AF_INET;
  2528. }
  2529. else
  2530. {
  2531. ASSERT((IPvToUse == ipvtuIPv6)
  2532. || (IPvToUse == ipvtuIPAny));
  2533. RpcpCopyIPv6Address((SOCKADDR_IN6 *)ThisAddrInfo->ai_addr, IPv6Address);
  2534. IPv6Address->sin6_family = AF_INET6;
  2535. IPv6Address->sin6_scope_id = ((SOCKADDR_IN6 *)ThisAddrInfo->ai_addr)->sin6_scope_id;
  2536. IPv6Address->sin6_flowinfo = 0;
  2537. }
  2538. return RPC_S_OK;
  2539. }
  2540. RpcpErrorAddRecord(EEInfoGCWinsock,
  2541. RPC_S_SERVER_UNAVAILABLE,
  2542. EEInfoDLNextAddress40);
  2543. return RPC_S_SERVER_UNAVAILABLE;
  2544. }
  2545. IP_ADDRESS_RESOLVER::~IP_ADDRESS_RESOLVER()
  2546. {
  2547. if (AddrInfo)
  2548. freeaddrinfo(AddrInfo);
  2549. }
  2550. RPC_STATUS
  2551. IP_BuildAddressVector(
  2552. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector,
  2553. IN ULONG NICFlags,
  2554. IN RPC_CHAR *NetworkAddress OPTIONAL,
  2555. IN WS_ADDRESS *Address OPTIONAL
  2556. )
  2557. /*++
  2558. Routine Description:
  2559. Builds a vector of IP addresses supported by this machine.
  2560. Arguments:
  2561. ppAddressVector - A place to store the vector. If a non-NULL
  2562. pointer is passed in, the memory will be freed before returning
  2563. a new vector. Queries should always specify *ppAddressVector == NULL.
  2564. NICFlags - the flags as specified in the RPC_POLICY of the
  2565. RpcServerUse*Protseq* APIs
  2566. NetworkAddess - the network address we were asked to listen
  2567. on. May be NULL.
  2568. Address - in the case of firewall, the addresses we chose to
  2569. listen on.
  2570. Return Value:
  2571. RPC_S_OK
  2572. RPC_S_OUT_OF_MEMORY
  2573. RPC_S_OUT_OF_RESOURCES
  2574. --*/
  2575. {
  2576. //
  2577. // Figure out all of our IP addresses
  2578. //
  2579. NETWORK_ADDRESS_VECTOR *pVector;
  2580. unsigned i, iActive;
  2581. RPC_CHAR *NextAddress;
  2582. int NumberOfAddresses;
  2583. WS_ADDRESS *CurrentAddress;
  2584. // If we were called with an old address vector, delete it.
  2585. if (*ppAddressVector)
  2586. {
  2587. delete (*ppAddressVector);
  2588. }
  2589. if ((pFirewallTable == 0 || NICFlags == RPC_C_BIND_TO_ALL_NICS) && !NetworkAddress)
  2590. {
  2591. ULONG Ignored;
  2592. // Get Dns hostname
  2593. pVector = (NETWORK_ADDRESS_VECTOR *)AllocateAndGetComputerName(cnaNew,
  2594. ComputerNameDnsHostname,
  2595. FIELD_OFFSET(NETWORK_ADDRESS_VECTOR, NetworkAddresses[1]),
  2596. FIELD_OFFSET(NETWORK_ADDRESS_VECTOR, NetworkAddresses[1]),
  2597. &Ignored);
  2598. if (pVector == NULL)
  2599. {
  2600. RpcpErrorAddRecord(EEInfoGCWinsock,
  2601. RPC_S_OUT_OF_MEMORY,
  2602. EEInfoDLIPBuildAddressVector10,
  2603. GetLastError());
  2604. return RPC_S_OUT_OF_MEMORY;
  2605. }
  2606. pVector->Count = 1;
  2607. pVector->NetworkAddresses[0] = (RPC_CHAR*)&pVector->NetworkAddresses[1];
  2608. }
  2609. else if (NetworkAddress)
  2610. {
  2611. // the length of the network address including the terminating NULL
  2612. // (in characters)
  2613. int NetworkAddressLength;
  2614. #if DBG
  2615. {
  2616. // if we have a network address, it must be in IP address notation
  2617. // make an ASSERT to verify that nobody ever passes an dns name here
  2618. ADDRINFO Hint;
  2619. ADDRINFO *AddrInfo;
  2620. USES_CONVERSION;
  2621. CStackAnsi AnsiName;
  2622. int err;
  2623. RpcpMemorySet(&Hint, 0, sizeof(Hint));
  2624. Hint.ai_flags = AI_NUMERICHOST;
  2625. ATTEMPT_STACK_W2A(AnsiName, NetworkAddress);
  2626. err = getaddrinfo(AnsiName,
  2627. NULL,
  2628. &Hint,
  2629. &AddrInfo);
  2630. // this is a numeric address. It should never fail
  2631. ASSERT (!err);
  2632. }
  2633. #endif
  2634. NetworkAddressLength = RpcpStringLength(NetworkAddress) + 1;
  2635. pVector = (NETWORK_ADDRESS_VECTOR *)
  2636. I_RpcAllocate( sizeof(NETWORK_ADDRESS_VECTOR)
  2637. + sizeof(RPC_CHAR *)
  2638. + (sizeof(RPC_CHAR) * NetworkAddressLength));
  2639. if (pVector == NULL)
  2640. {
  2641. return (RPC_S_OUT_OF_MEMORY);
  2642. }
  2643. pVector->Count = 1;
  2644. NextAddress = (RPC_CHAR *)&pVector->NetworkAddresses[1];
  2645. pVector->NetworkAddresses[0] = NextAddress;
  2646. RpcpMemoryCopy(NextAddress, NetworkAddress, NetworkAddressLength * 2);
  2647. }
  2648. else
  2649. {
  2650. NumberOfAddresses = 0;
  2651. CurrentAddress = Address;
  2652. while (CurrentAddress != NULL)
  2653. {
  2654. NumberOfAddresses ++;
  2655. CurrentAddress = (WS_ADDRESS *)CurrentAddress->pNextAddress;
  2656. }
  2657. pVector = (NETWORK_ADDRESS_VECTOR *)
  2658. I_RpcAllocate( sizeof(NETWORK_ADDRESS_VECTOR)
  2659. + (sizeof(RPC_CHAR *)
  2660. + max(IPv6_MAXIMUM_RAW_NAME, IP_MAXIMUM_RAW_NAME) * sizeof(RPC_CHAR))
  2661. * ((WS_ADDRESS *)Address->pFirstAddress)->NumActiveAddresses);
  2662. if (pVector == NULL)
  2663. {
  2664. return (RPC_S_OUT_OF_MEMORY);
  2665. }
  2666. // Only populate the vector with addresses that have been initialized.
  2667. // It is possible that the list contains some address object that have
  2668. // not yet had their DHCP address assigned - they should be skipped.
  2669. pVector->Count = ((WS_ADDRESS *)Address->pFirstAddress)->NumActiveAddresses;
  2670. NextAddress = (RPC_CHAR*)&pVector->NetworkAddresses[NumberOfAddresses];
  2671. IN_ADDR addr;
  2672. SOCKADDR_IN6 *Ipv6Address;
  2673. unsigned j;
  2674. CurrentAddress = Address;
  2675. iActive = 0;
  2676. for (i = 0; i < NumberOfAddresses; i++)
  2677. {
  2678. if (CurrentAddress->fAddressInitialized)
  2679. {
  2680. pVector->NetworkAddresses[iActive] = NextAddress;
  2681. iActive++;
  2682. if (CurrentAddress->id != TCP_IPv6)
  2683. {
  2684. addr.s_addr = ((SOCKADDR_IN *)(&CurrentAddress->ListenAddr.inetaddr))->sin_addr.s_addr;
  2685. swprintf((RPC_SCHAR *)NextAddress, RPC_CONST_SSTRING("%d.%d.%d.%d"),
  2686. addr.s_net, addr.s_host, addr.s_lh, addr.s_impno);
  2687. }
  2688. else
  2689. {
  2690. Ipv6Address = (SOCKADDR_IN6 *)(&CurrentAddress->ListenAddr.inetaddr);
  2691. swprintf((RPC_SCHAR *)NextAddress, RPC_CONST_SSTRING("%X:%X:%X:%X:%X:%X:%X:%X"),
  2692. Ipv6Address->sin6_addr.u.Word[0],
  2693. Ipv6Address->sin6_addr.u.Word[1],
  2694. Ipv6Address->sin6_addr.u.Word[2],
  2695. Ipv6Address->sin6_addr.u.Word[3],
  2696. Ipv6Address->sin6_addr.u.Word[4],
  2697. Ipv6Address->sin6_addr.u.Word[5],
  2698. Ipv6Address->sin6_addr.u.Word[6],
  2699. Ipv6Address->sin6_addr.u.Word[7]
  2700. );
  2701. }
  2702. NextAddress += max(IPv6_MAXIMUM_RAW_NAME, IP_MAXIMUM_RAW_NAME);
  2703. }
  2704. CurrentAddress = (WS_ADDRESS *)CurrentAddress->pNextAddress;
  2705. }
  2706. }
  2707. *ppAddressVector = pVector;
  2708. return(RPC_S_OK);
  2709. }
  2710. RPC_STATUS
  2711. WS_Bind(
  2712. IN SOCKET sock,
  2713. IN OUT WS_SOCKADDR *pListenAddr,
  2714. IN BOOL IpProtocol,
  2715. IN DWORD EndpointFlags
  2716. )
  2717. /*++
  2718. Routine Description:
  2719. Binds the socket to a port. Takes into account the endpoint flags
  2720. and the value of the port in the WS_SOCKADDR. There is IP specific
  2721. code for firewalls which is keyed off of the EndpointFlags.
  2722. Arguments:
  2723. sock - The socket to bind
  2724. pListenAddr - On input the sin_port member is checked. For fixed endpoints
  2725. this is set and is the only address bound to. On output it contains
  2726. the info on the fully bound socket.
  2727. IpProtocol - Whether this is an IP protocol. TRUE for TCP/IP and HTTP.
  2728. EndpointFlags - see RpcTrans.hxx. If non-zero and we're allocating a
  2729. dynamic port then we must call the runtime.
  2730. Return Value:
  2731. RPC_S_OK
  2732. RPC_S_DUPLICATE_ENDPOINT : when a fixed endpoint is already in use.
  2733. RPC_S_OUT_OF_MEMORY
  2734. RPC_S_OUT_OF_RESOURCES
  2735. RPC_S_CANT_CREATE_ENDPOINT
  2736. --*/
  2737. {
  2738. RPC_STATUS status;
  2739. int Retries = 0;
  2740. BOOL fFirewallPorts = FALSE;
  2741. BOOL fSetSockOptFailed;
  2742. DWORD LastError;
  2743. USHORT Port;
  2744. if (IpProtocol && (RpcpGetIpPort(pListenAddr) == 0))
  2745. {
  2746. Retries = 8;
  2747. }
  2748. // Protect the socket to prevent another server from using our port.
  2749. if (WS_ProtectListeningSocket(sock, TRUE) != 0)
  2750. {
  2751. return RPC_S_CANT_CREATE_ENDPOINT;
  2752. }
  2753. do
  2754. {
  2755. if (Retries)
  2756. {
  2757. status = I_RpcServerAllocateIpPort(EndpointFlags, &Port);
  2758. if (status != RPC_S_OK)
  2759. {
  2760. RpcpErrorAddRecord(EEInfoGCRuntime,
  2761. status,
  2762. EEInfoDLWSBind10,
  2763. EndpointFlags);
  2764. break;
  2765. }
  2766. RpcpSetIpPort(pListenAddr, Port);
  2767. // Check if any firewall ports are defined. If they are remember
  2768. // that so we can map the error correctly.
  2769. if (!fFirewallPorts && (RpcpGetIpPort(pListenAddr) == 0))
  2770. {
  2771. Retries = 0;
  2772. }
  2773. else
  2774. {
  2775. Retries--;
  2776. fFirewallPorts = TRUE;
  2777. }
  2778. RpcpSetIpPort(pListenAddr, htons(RpcpGetIpPort(pListenAddr)));
  2779. }
  2780. else
  2781. {
  2782. status = RPC_S_OK;
  2783. }
  2784. WS_Bind_Rebind:
  2785. if ( bind(sock,
  2786. &pListenAddr->generic,
  2787. sizeof(WS_SOCKADDR)) )
  2788. {
  2789. LastError = GetLastError();
  2790. switch(LastError)
  2791. {
  2792. case WSAEACCES:
  2793. // This error can only be returned when a bind is done for a socket
  2794. // with SO_REUSEADDR following a bind with SO_EXCLUSIVEADDRUSE. Since
  2795. // we never bind with SO_REUSEADDR we should not see this error unless
  2796. // the port is being allocated dynamically and happens to use
  2797. // an already listening port.
  2798. ASSERT(Retries > 0);
  2799. status = RPC_S_DUPLICATE_ENDPOINT;
  2800. break;
  2801. case WSAEADDRINUSE:
  2802. {
  2803. status = RPC_S_DUPLICATE_ENDPOINT;
  2804. RpcpErrorAddRecord(EEInfoGCWinsock,
  2805. status,
  2806. EEInfoDLWSBind45,
  2807. (ULONG)ntohs(RpcpGetIpPort(pListenAddr)));
  2808. break;
  2809. }
  2810. case WSAENOBUFS:
  2811. {
  2812. RpcpErrorAddRecord(EEInfoGCWinsock,
  2813. LastError,
  2814. EEInfoDLWSBind40);
  2815. status = RPC_S_OUT_OF_MEMORY;
  2816. break;
  2817. }
  2818. default:
  2819. {
  2820. RpcpErrorAddRecord(EEInfoGCWinsock,
  2821. LastError,
  2822. EEInfoDLWSBind50);
  2823. status = RPC_S_CANT_CREATE_ENDPOINT;
  2824. break;
  2825. }
  2826. }
  2827. }
  2828. }
  2829. while ( (status == RPC_S_DUPLICATE_ENDPOINT) && Retries);
  2830. if (status != RPC_S_OK)
  2831. {
  2832. if (fFirewallPorts && status == RPC_S_DUPLICATE_ENDPOINT)
  2833. {
  2834. status = RPC_S_OUT_OF_RESOURCES;
  2835. }
  2836. RpcpErrorAddRecord(EEInfoGCWinsock,
  2837. status,
  2838. EEInfoDLWSBind30);
  2839. return(status);
  2840. }
  2841. int length = sizeof(WS_SOCKADDR);
  2842. if (getsockname(sock, &pListenAddr->generic, &length))
  2843. {
  2844. return(RPC_S_OUT_OF_RESOURCES);
  2845. }
  2846. return(RPC_S_OK);
  2847. }
  2848. RPC_STATUS
  2849. CDP_BuildAddressVector(
  2850. OUT NETWORK_ADDRESS_VECTOR **ppAddressVector
  2851. )
  2852. /*++
  2853. Routine Description:
  2854. Look up the Cluster node number of this node and build
  2855. the appropriate vector
  2856. Arguments:
  2857. ppAddressVector - A place to store the vector.
  2858. Return Value:
  2859. RPC_S_OK
  2860. RPC_S_OUT_OF_MEMORY
  2861. RPC_S_OUT_OF_RESOURCES
  2862. --*/
  2863. {
  2864. HKEY ParamsKey;
  2865. NETWORK_ADDRESS_VECTOR * pVector;
  2866. const RPC_CHAR *ClussvcParams =
  2867. RPC_CONST_STRING("System\\CurrentControlSet\\Services\\ClusSvc\\Parameters");
  2868. RPC_CHAR *ClusRegNodeId = RPC_STRING_LITERAL("NodeId");
  2869. DWORD KeyType;
  2870. RPC_CHAR NodeIdString[ CDP_MAXIMUM_RAW_NAME ];
  2871. DWORD StringLength = CDP_MAXIMUM_RAW_NAME * sizeof( RPC_CHAR );
  2872. DWORD status;
  2873. //
  2874. // open the Clussvc parameters key and extrace the NodeId
  2875. //
  2876. status = RegOpenKey( HKEY_LOCAL_MACHINE,
  2877. (const RPC_SCHAR *)ClussvcParams,
  2878. &ParamsKey );
  2879. if ( status != ERROR_SUCCESS )
  2880. {
  2881. return RPC_S_INVALID_NET_ADDR;
  2882. }
  2883. status = RegQueryValueEx(ParamsKey,
  2884. (const RPC_SCHAR *)ClusRegNodeId,
  2885. NULL,
  2886. &KeyType,
  2887. (LPBYTE)NodeIdString,
  2888. &StringLength);
  2889. RegCloseKey( ParamsKey );
  2890. if ( status != ERROR_SUCCESS ||
  2891. KeyType != REG_SZ ||
  2892. (( StringLength / sizeof( RPC_CHAR )) > CDP_MAXIMUM_RAW_NAME ))
  2893. {
  2894. return RPC_S_INVALID_NET_ADDR;
  2895. }
  2896. pVector = (NETWORK_ADDRESS_VECTOR *)
  2897. I_RpcAllocate( sizeof(NETWORK_ADDRESS_VECTOR ) +
  2898. sizeof(RPC_CHAR *) +
  2899. StringLength );
  2900. if (pVector == NULL)
  2901. {
  2902. return(RPC_S_OUT_OF_MEMORY);
  2903. }
  2904. pVector->Count = 1;
  2905. pVector->NetworkAddresses[0] = (RPC_CHAR *)&pVector->NetworkAddresses[1];
  2906. RpcpStringCopy( pVector->NetworkAddresses[0], NodeIdString );
  2907. *ppAddressVector = pVector;
  2908. return RPC_S_OK;
  2909. }
  2910. typedef struct tagIPVersionSettings
  2911. {
  2912. IPVersionToUse IPVersion;
  2913. BOOL fUseIPv6;
  2914. } IPVersionSettings;
  2915. const static IPVersionSettings ListenIPVersionSettings[2] = {{ipvtuIPv4, FALSE}, {ipvtuIPv6, TRUE}};
  2916. typedef enum tagIPVersionSettingsIndexes
  2917. {
  2918. ipvsiIPv4SettingsIndex = 0,
  2919. ipvsiIPv6SettingsIndex
  2920. } IPVersionSettingsIndexes;
  2921. typedef struct tagListenAddressListElement
  2922. {
  2923. INT ProtocolId;
  2924. IPVersionSettingsIndexes IPVersionSettingsIndex;
  2925. BOOL fSuccessfullyInitialized;
  2926. RPC_STATUS ErrorCode;
  2927. union
  2928. {
  2929. SOCKADDR_IN6 inet6Addr;
  2930. SOCKADDR_IN inetAddr;
  2931. } u;
  2932. } ListenAddressListElement;
  2933. typedef struct tagTCPServerListenParams
  2934. {
  2935. INT ProtocolId;
  2936. IPVersionSettingsIndexes IPVersionSettingsIndex;
  2937. } TCPServerListenParams;
  2938. const static TCPServerListenParams HTTPListenParams[1] = {HTTP, ipvsiIPv4SettingsIndex};
  2939. const static TCPServerListenParams TCPListenParams[2] =
  2940. {{TCP, ipvsiIPv4SettingsIndex},
  2941. {TCP_IPv6, ipvsiIPv6SettingsIndex}};
  2942. const int MAX_TCP_SERVER_LISTEN_LOOP_ITERATIONS = 2;
  2943. RPC_STATUS
  2944. TCP_ServerListenEx(
  2945. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  2946. IN RPC_CHAR *NetworkAddress,
  2947. IN OUT RPC_CHAR * *pEndpoint,
  2948. IN UINT PendingQueueSize,
  2949. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2950. IN ULONG EndpointFlags,
  2951. IN ULONG NICFlags,
  2952. IN BOOL fHttp
  2953. )
  2954. /*++
  2955. Routine Description:
  2956. This routine allocates a port to receive new client connections.
  2957. If successful a call to COMMON_ServerCompleteListen() will actually allow
  2958. new connection callbacks to the RPC runtime to occur. If the runtime
  2959. is unable to complete then it must abort the address by calling
  2960. WS_ServerAbortListen().
  2961. Arguments:
  2962. ThisAddress - A pointer to the loadable transport interface address.
  2963. NetworkAddress - the address to listen on. This can be specified for
  2964. IP only, and it *cannot* be a DNS name. If it is, this function
  2965. will work incorrectly for multihomed/multi IP machines.
  2966. pEndpoint - Optionally, the endpoint (port) to listen on. Set to
  2967. to listened port for dynamically allocated endpoints.
  2968. PendingQueueSize - Count to call listen() with.
  2969. EndpointFlags - Flags that control dynamic port allocation
  2970. NICFlags - Flags that control network (IP) address binding
  2971. SecurityDescriptor - Meaningless for TCP
  2972. Return Value:
  2973. RPC_S_OK
  2974. RPC_S_OUT_OF_MEMORY
  2975. RPC_S_OUT_OF_RESOURCES
  2976. RPC_S_CANT_CREATE_ENDPOINT
  2977. RPC_S_DUPLICATE_ENDPOINT
  2978. --*/
  2979. {
  2980. PWS_ADDRESS pAddress = (PWS_ADDRESS)ThisAddress;
  2981. RPC_STATUS status;
  2982. WS_SOCKADDR *sockaddr = &(pAddress->ListenAddr);
  2983. unsigned i;
  2984. PWS_ADDRESS pList, pOld;
  2985. int NeededAddressListSize;
  2986. ListenAddressListElement *ListenAddressList;
  2987. ListenAddressListElement *CurrentListElement;
  2988. int AddressListSize;
  2989. SOCKADDR_IN IPv4Address;
  2990. SOCKADDR_IN6 *IPv6Address;
  2991. int LoopIterations;
  2992. TCPServerListenParams *ParamsToUse;
  2993. IPVersionSettingsIndexes IPVersionSettingsIndex;
  2994. BOOL fAtLeastOneAddressInitialized;
  2995. USHORT PortNumber; // in network byte order!
  2996. BOOL fPortNumberInitialized;
  2997. BOOL fDynamicEndpoint;
  2998. BOOL fFatalErrorEncountered;
  2999. RPC_STATUS FatalErrorCode;
  3000. WS_ADDRESS *LastSuccessfullyInitializedAddress;
  3001. WS_ADDRESS *NextAddress;
  3002. BOOL fDualTransportConfiguration = FALSE;
  3003. BOOL fLoopbackAddressProcessed;
  3004. FIREWALL_INFO *pCopyOfFirewallTable = NULL;
  3005. RequestGlobalMutex();
  3006. // Get a copy of pFirewallTable while in the critical section
  3007. // to protect against a race with the PnP table update.
  3008. // We should only access the local copy and remember to delete it.
  3009. pCopyOfFirewallTable = GetFirewallTableCopy();
  3010. if (pFirewallTable != NULL &&
  3011. pCopyOfFirewallTable == NULL)
  3012. {
  3013. ClearGlobalMutex();
  3014. return RPC_S_OUT_OF_MEMORY;
  3015. }
  3016. ClearGlobalMutex();
  3017. // sizing pass - allocate sufficient memory
  3018. if (pCopyOfFirewallTable == 0 || NICFlags == RPC_C_BIND_TO_ALL_NICS)
  3019. {
  3020. if (fHttp)
  3021. AddressListSize = 1;
  3022. else
  3023. {
  3024. AddressListSize = 2;
  3025. fDualTransportConfiguration = TRUE;
  3026. }
  3027. }
  3028. else
  3029. {
  3030. AddressListSize = pCopyOfFirewallTable->NumAddresses + 1;
  3031. }
  3032. NeededAddressListSize = AddressListSize * sizeof(ListenAddressListElement);
  3033. ListenAddressList = new ListenAddressListElement[NeededAddressListSize];
  3034. if (ListenAddressList == NULL)
  3035. {
  3036. delete pCopyOfFirewallTable;
  3037. return RPC_S_OUT_OF_MEMORY;
  3038. }
  3039. fAtLeastOneAddressInitialized = FALSE;
  3040. RpcpMemorySet(ListenAddressList,
  3041. 0,
  3042. NeededAddressListSize);
  3043. // processing pass. Set all the required addresses in the array
  3044. if (pCopyOfFirewallTable == 0 || NICFlags == RPC_C_BIND_TO_ALL_NICS)
  3045. {
  3046. if (fHttp)
  3047. {
  3048. ASSERT(AddressListSize == 1);
  3049. ParamsToUse = (TCPServerListenParams *)HTTPListenParams;
  3050. LoopIterations = 1;
  3051. }
  3052. else
  3053. {
  3054. ParamsToUse = (TCPServerListenParams *)TCPListenParams;
  3055. LoopIterations = 2;
  3056. }
  3057. for (i = 0; i < LoopIterations; i ++)
  3058. {
  3059. CurrentListElement = &ListenAddressList[i];
  3060. CurrentListElement->ProtocolId = ParamsToUse[i].ProtocolId;
  3061. IPVersionSettingsIndex = ParamsToUse[i].IPVersionSettingsIndex;
  3062. CurrentListElement->IPVersionSettingsIndex = IPVersionSettingsIndex;
  3063. IP_ADDRESS_RESOLVER resolver(NetworkAddress,
  3064. cosServer,
  3065. ListenIPVersionSettings[IPVersionSettingsIndex].IPVersion // IP version to use
  3066. );
  3067. // resolve the address. Since this cannot be a DNS name, we will resolve
  3068. // to one address at most. We choose the ipv6 address, because it has space
  3069. // for both. The actual parameter that determines the type of name resolution
  3070. // to be done is IP version to use passed to the constructor
  3071. status = resolver.NextAddress((SOCKADDR_STORAGE *)&CurrentListElement->u.inet6Addr);
  3072. if (status == RPC_S_OK)
  3073. {
  3074. fAtLeastOneAddressInitialized = TRUE;
  3075. CurrentListElement->fSuccessfullyInitialized = TRUE;
  3076. }
  3077. }
  3078. }
  3079. else
  3080. {
  3081. fAtLeastOneAddressInitialized = TRUE;
  3082. fLoopbackAddressProcessed = FALSE;
  3083. for (i = 0; i < AddressListSize; i++)
  3084. {
  3085. CurrentListElement = &ListenAddressList[i];
  3086. if (fHttp)
  3087. {
  3088. CurrentListElement->ProtocolId = HTTP;
  3089. }
  3090. else
  3091. {
  3092. CurrentListElement->ProtocolId = TCP;
  3093. }
  3094. CurrentListElement->IPVersionSettingsIndex = ipvsiIPv4SettingsIndex;
  3095. CurrentListElement->fSuccessfullyInitialized = TRUE;
  3096. if (i == pCopyOfFirewallTable->NumAddresses)
  3097. {
  3098. CurrentListElement->u.inetAddr.sin_addr.s_addr = 0x0100007F;
  3099. }
  3100. else
  3101. {
  3102. if (pCopyOfFirewallTable->Entries[i].Address == 0x0100007F)
  3103. fLoopbackAddressProcessed = TRUE;
  3104. CurrentListElement->u.inetAddr.sin_addr.s_addr = pCopyOfFirewallTable->Entries[i].Address;
  3105. }
  3106. }
  3107. // if the loopback address was in the firewall configuration, 'forget' about
  3108. // the last entry we added for the loopback address. Otherwise, we'll have
  3109. // it twice in the list, and this will cause errors
  3110. if (fLoopbackAddressProcessed)
  3111. {
  3112. AddressListSize --;
  3113. // since we added one, and fLoopbackAddressProcessed is set only if
  3114. // we find something in the list, then AddressListSize must still be
  3115. // greater than 0.
  3116. ASSERT(AddressListSize > 0);
  3117. }
  3118. }
  3119. if (fAtLeastOneAddressInitialized)
  3120. {
  3121. fAtLeastOneAddressInitialized = FALSE;
  3122. }
  3123. else
  3124. {
  3125. // the only place where we can fail so far is name resolution. If this
  3126. // fails, return the status
  3127. delete [] ListenAddressList;
  3128. delete pCopyOfFirewallTable;
  3129. return status;
  3130. }
  3131. // Figure out what port to bind to.
  3132. if (*pEndpoint)
  3133. {
  3134. status = EndpointToPortNumber(*pEndpoint, PortNumber);
  3135. if (status != RPC_S_OK)
  3136. {
  3137. delete [] ListenAddressList;
  3138. delete pCopyOfFirewallTable;
  3139. return(status);
  3140. }
  3141. PortNumber = htons(PortNumber);
  3142. fDynamicEndpoint = 0;
  3143. fPortNumberInitialized = TRUE;
  3144. }
  3145. else
  3146. {
  3147. PortNumber = 0;
  3148. fDynamicEndpoint = TRUE;
  3149. fPortNumberInitialized = FALSE;
  3150. }
  3151. // zoom in through the array address, and listen on all successfully initialized
  3152. // protocols
  3153. pList = pAddress;
  3154. pAddress->NumActiveAddresses = 0;
  3155. fFatalErrorEncountered = FALSE;
  3156. for (i = 0; i < AddressListSize; i ++)
  3157. {
  3158. CurrentListElement = &ListenAddressList[i];
  3159. if (!CurrentListElement->fSuccessfullyInitialized)
  3160. continue;
  3161. if (pList == 0)
  3162. {
  3163. pList = new WS_ADDRESS;
  3164. if (pList == 0)
  3165. {
  3166. fFatalErrorEncountered = TRUE;
  3167. FatalErrorCode = RPC_S_OUT_OF_MEMORY;
  3168. break;
  3169. }
  3170. pOld->pNextAddress = pList;
  3171. }
  3172. sockaddr = &(pList->ListenAddr);
  3173. RpcpMemorySet(sockaddr, 0, sizeof(*sockaddr));
  3174. // the port we have set is already in network byte order -
  3175. // no need to change it
  3176. RpcpSetIpPort(sockaddr, PortNumber);
  3177. pList->fDynamicEndpoint = fDynamicEndpoint;
  3178. if (ListenIPVersionSettings[CurrentListElement->IPVersionSettingsIndex].fUseIPv6)
  3179. {
  3180. ((SOCKADDR_IN6 *)sockaddr)->sin6_flowinfo = 0;
  3181. RpcpCopyIPv6Address(&CurrentListElement->u.inet6Addr, (SOCKADDR_IN6 *)sockaddr);
  3182. }
  3183. else
  3184. {
  3185. RpcpCopyIPv4Address(&CurrentListElement->u.inetAddr, (SOCKADDR_IN *)sockaddr);
  3186. }
  3187. pList->id = CurrentListElement->ProtocolId;
  3188. pList->NewConnection = WS_NewConnection;
  3189. pList->SubmitListen = WS_SubmitAccept;
  3190. SetProtocolMultiplier(pList, 1);
  3191. pList->pAddressVector = 0;
  3192. pList->Endpoint = 0;
  3193. pList->QueueSize = PendingQueueSize;
  3194. pList->EndpointFlags = EndpointFlags;
  3195. pList->fAddressInitialized = TRUE;
  3196. pList->pFirstAddress = pAddress;
  3197. pList->pNextAddress = NULL;
  3198. sockaddr->generic.sa_family = WsTransportTable[CurrentListElement->ProtocolId].AddressFamily;
  3199. // If we are running with the firewall address table
  3200. // and the address has not yet been initialized or enabled, delay listening on it.
  3201. if (pCopyOfFirewallTable != NULL &&
  3202. (pCopyOfFirewallTable->Entries[i].fInitialized == FALSE
  3203. || pCopyOfFirewallTable->Entries[i].fEnabled == FALSE
  3204. )
  3205. )
  3206. {
  3207. ASSERT(pCopyOfFirewallTable->NumAddresses > i);
  3208. pList->InAddressList = Inactive;
  3209. // We need to register the address to receive
  3210. // PnP notifications. This is necessary to allow
  3211. // the initialization and activation of the address later on
  3212. // when the corresponding interface has been initialized.
  3213. TransportProtocol::AddObjectToProtocolList(pList);
  3214. pList->type = ADDRESS;
  3215. // Record that the address has not yet been initialized and
  3216. // keep track of the interface index so that we can later use
  3217. // the pFirewallTable to initialize this address.
  3218. pList->fAddressInitialized = FALSE;
  3219. }
  3220. // Either selective bindings are not used, or the address has been initialized.
  3221. else
  3222. {
  3223. // we must know whether we got WSAEAFNOSUPPORT when we opened the socket
  3224. // if yes, we must record this in CurrentElement, and we must not blow
  3225. // the address. If we got something else, we should abort even in dual
  3226. // transport config. The addresses on the firewall are a separate thing -
  3227. // we ignore the ones we can't listen on.
  3228. pAddress->NumActiveAddresses++;
  3229. // Actually listen.
  3230. // Pass in fResetAddressListEntries = FALSE since the address list
  3231. // fields have already been initialized.
  3232. status = WS_ServerListenCommon(pList, FALSE);
  3233. if (status != RPC_S_OK)
  3234. {
  3235. if ((status == RPC_S_DUPLICATE_ENDPOINT)
  3236. || (fDualTransportConfiguration && (status != RPC_P_ADDRESS_FAMILY_INVALID)))
  3237. {
  3238. // if either somebody else is listening on our port for this address,
  3239. // or this is a dual transport configuratuon, and we fail to listen
  3240. // on one of the transports for reasons other that it not being
  3241. // installed, bail out
  3242. fFatalErrorEncountered = TRUE;
  3243. FatalErrorCode = status;
  3244. break;
  3245. }
  3246. else if (fDualTransportConfiguration && (status == RPC_P_ADDRESS_FAMILY_INVALID))
  3247. {
  3248. pList->InAddressList = Inactive;
  3249. // we still need to register the address with PnP
  3250. // make sure it's not already there
  3251. ASSERT(RpcpIsListEmpty(&pList->ObjectList));
  3252. TransportProtocol::AddObjectToProtocolList(pList);
  3253. }
  3254. CurrentListElement->ErrorCode = status;
  3255. CurrentListElement->fSuccessfullyInitialized = FALSE;
  3256. }
  3257. else
  3258. {
  3259. if (!fPortNumberInitialized)
  3260. {
  3261. PortNumber = RpcpGetIpPort(&(pList->ListenAddr));
  3262. fPortNumberInitialized = TRUE;
  3263. }
  3264. fAtLeastOneAddressInitialized = TRUE;
  3265. }
  3266. }
  3267. pOld = pList;
  3268. pList = 0;
  3269. }
  3270. // If at least one address has initialized then that address should have picked
  3271. // the dynamic endpoint to listen on:
  3272. // fAtLeastOneAddressInitialized -> fPortNumberInitialized
  3273. ASSERT(!fAtLeastOneAddressInitialized || fPortNumberInitialized);
  3274. // compact the list by removing addresses we couldn't successfully listen on
  3275. pList = pAddress;
  3276. for (i = 0; i < AddressListSize; i ++)
  3277. {
  3278. // we may have an early break if a memory allocation failed
  3279. if (pList == NULL)
  3280. break;
  3281. // if this address has not initialized successfully, and this is not
  3282. // the first address, and either none of the elements initialized
  3283. // successfully or this is not a dual transport configuration with
  3284. // error RPC_P_ADDRESS_FAMILY_INVALID and this is not a
  3285. // delay-initialized address under dynamic binding that has not yet been
  3286. // assigned an IP address, delete the element.
  3287. if (!ListenAddressList[i].fSuccessfullyInitialized && (i > 0)
  3288. &&
  3289. (!fAtLeastOneAddressInitialized
  3290. || (!fDualTransportConfiguration
  3291. || (ListenAddressList[i].ErrorCode != RPC_P_ADDRESS_FAMILY_INVALID)
  3292. )
  3293. )
  3294. &&
  3295. !(pCopyOfFirewallTable != NULL && pCopyOfFirewallTable->Entries[i].fInitialized == FALSE)
  3296. )
  3297. {
  3298. ASSERT(pOld != pList);
  3299. pOld->pNextAddress = pList->pNextAddress;
  3300. NextAddress = (WS_ADDRESS *)pList->pNextAddress;
  3301. TransportProtocol::RemoveObjectFromProtocolList(pList);
  3302. delete pList;
  3303. }
  3304. else
  3305. {
  3306. pOld = pList;
  3307. NextAddress = (WS_ADDRESS *)pList->pNextAddress;
  3308. }
  3309. pList = NextAddress;
  3310. }
  3311. if (!fAtLeastOneAddressInitialized)
  3312. {
  3313. TransportProtocol::RemoveObjectFromProtocolList(pAddress);
  3314. delete [] ListenAddressList;
  3315. delete pCopyOfFirewallTable;
  3316. if (status == RPC_P_ADDRESS_FAMILY_INVALID)
  3317. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  3318. return status;
  3319. }
  3320. // the attempt to listen on dual protocol configurations may have left EEInfo
  3321. // record in the TEB. If we're here, we have succeeded, and we can delete them
  3322. RpcpPurgeEEInfo();
  3323. if (!ListenAddressList[0].fSuccessfullyInitialized)
  3324. {
  3325. // here, pOld must be the last successfully initialized element
  3326. // or the last element we haven't given up on (i.e. potentially
  3327. // active through PnP)
  3328. // It cannot be the first element, or we would have bailed out
  3329. // by now. We cannot have only one element either
  3330. ASSERT(pOld->pNextAddress == NULL);
  3331. ASSERT(pAddress->pNextAddress != NULL);
  3332. // here at least one has succeeded and all non-first failed
  3333. // elements are deleted, though a fatal error may have been
  3334. // encountered. We need to deal with the first element
  3335. // because we don't want to expose elements with failed
  3336. // initialization outside this routine.
  3337. //
  3338. // We will leave the first element alone if it is a delay-initialized address
  3339. // that has not yet been assigned a transport address.
  3340. if (!(fDualTransportConfiguration && (ListenAddressList[0].ErrorCode == RPC_P_ADDRESS_FAMILY_INVALID))
  3341. &&
  3342. !(pCopyOfFirewallTable != NULL && pCopyOfFirewallTable->Entries[0].fInitialized == FALSE))
  3343. {
  3344. // remove the element we will copy to the first element
  3345. TransportProtocol::RemoveObjectFromProtocolList(pOld);
  3346. NextAddress = (WS_ADDRESS *)pAddress->pNextAddress;
  3347. RpcpMemoryCopy(pAddress, pOld, sizeof(WS_ADDRESS));
  3348. pAddress->pNextAddress = NextAddress;
  3349. // find the element we just copied over the first, and free it
  3350. LastSuccessfullyInitializedAddress = pOld;
  3351. pList = pAddress;
  3352. while (pList->pNextAddress != LastSuccessfullyInitializedAddress)
  3353. {
  3354. pList = (WS_ADDRESS *)pList->pNextAddress;
  3355. }
  3356. delete pList->pNextAddress;
  3357. pList->pNextAddress = NULL;
  3358. // add the first element back on the list.
  3359. TransportProtocol::AddObjectToProtocolList(pAddress);
  3360. }
  3361. }
  3362. delete [] ListenAddressList;
  3363. delete pCopyOfFirewallTable;
  3364. // by now all elements in the list have listened successfully
  3365. // or are in transport PnP state. However
  3366. // if we encountered a fatal error, we need to abort any way
  3367. if (fFatalErrorEncountered)
  3368. {
  3369. WS_ServerAbortListen(pAddress);
  3370. // fatal error - bail out
  3371. return FatalErrorCode;
  3372. }
  3373. // Listened okay
  3374. // Figure out our network addresses
  3375. ASSERT(pAddress->pAddressVector == NULL);
  3376. status = IP_BuildAddressVector(
  3377. &pAddress->pAddressVector,
  3378. NICFlags,
  3379. NetworkAddress,
  3380. pAddress);
  3381. if (status != RPC_S_OK)
  3382. {
  3383. WS_ServerAbortListen(pAddress);
  3384. return(status);
  3385. }
  3386. // Return the dynamic port, if needed.
  3387. if (!*pEndpoint)
  3388. {
  3389. *pEndpoint = new RPC_CHAR[6]; // 65535 max
  3390. if (!*pEndpoint)
  3391. {
  3392. WS_ServerAbortListen(ThisAddress);
  3393. return(RPC_S_OUT_OF_MEMORY);
  3394. }
  3395. PortNumber = ntohs(PortNumber);
  3396. PortNumberToEndpoint(PortNumber, *pEndpoint);
  3397. }
  3398. // Save away the endpoint in the address, if needed, here.
  3399. // (PnP?)
  3400. return(status);
  3401. }
  3402. RPC_STATUS
  3403. TCP_ServerListen(
  3404. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  3405. IN RPC_CHAR *NetworkAddress,
  3406. IN OUT RPC_CHAR * *pEndpoint,
  3407. IN UINT PendingQueueSize,
  3408. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  3409. IN ULONG EndpointFlags,
  3410. IN ULONG NICFlags
  3411. )
  3412. {
  3413. return (TCP_ServerListenEx(
  3414. ThisAddress,
  3415. NetworkAddress,
  3416. pEndpoint,
  3417. PendingQueueSize,
  3418. SecurityDescriptor,
  3419. EndpointFlags,
  3420. NICFlags,
  3421. FALSE // Not HTTP
  3422. ));
  3423. }
  3424. RPC_STATUS
  3425. WS_ConvertClientAddress (
  3426. IN const SOCKADDR *ClientAddress,
  3427. IN ULONG ClientAddressType,
  3428. OUT RPC_CHAR **pNetworkAddress
  3429. )
  3430. /*++
  3431. Routine Description:
  3432. Converts a given IP address to a RPC network address
  3433. Arguments:
  3434. ClientAddress - the client IP address. Can be SOCKADDR_IN6
  3435. for IPv6.
  3436. ClientAddressType - TCP or TCP_IPv6
  3437. NetworkAddress - Will contain string on success.
  3438. Return Value:
  3439. RPC_S_OK or other RPC_S_* errors for error
  3440. --*/
  3441. {
  3442. USES_CONVERSION;
  3443. CNlUnicode nlUnicode;
  3444. int Result;
  3445. int SocketLength;
  3446. int HostLength;
  3447. char *HostName;
  3448. char *ScopeIdSeparator;
  3449. ASSERT((ClientAddressType == TCP) || (ClientAddressType == TCP_IPv6));
  3450. if (ClientAddressType == TCP)
  3451. SocketLength = sizeof(SOCKADDR_IN);
  3452. else
  3453. SocketLength = sizeof(SOCKADDR_IN6);
  3454. // allocate space for the numeric name plus the terminating NULL
  3455. HostLength = max(IP_MAXIMUM_RAW_NAME, IPv6_MAXIMUM_RAW_NAME) + 1;
  3456. HostName = (char *)alloca(HostLength);
  3457. Result = getnameinfo(ClientAddress,
  3458. SocketLength,
  3459. HostName,
  3460. HostLength,
  3461. NULL,
  3462. 0,
  3463. NI_NUMERICHOST);
  3464. ASSERT(Result == 0);
  3465. ScopeIdSeparator = strchr(HostName, '%');
  3466. if (ScopeIdSeparator)
  3467. {
  3468. // if there is a scope separator, whack everything after
  3469. // the scope separator (i.e. we don't care about the scope).
  3470. *ScopeIdSeparator = 0;
  3471. }
  3472. ATTEMPT_NL_A2W(nlUnicode, HostName);
  3473. *pNetworkAddress = (WCHAR *)nlUnicode;
  3474. return(RPC_S_OK);
  3475. }
  3476. RPC_STATUS
  3477. RPC_ENTRY
  3478. TCP_QueryClientAddress (
  3479. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  3480. OUT RPC_CHAR **pNetworkAddress
  3481. )
  3482. /*++
  3483. Routine Description:
  3484. Returns the IP address of the client on a connection as a string.
  3485. The clients address is saved when the client connects, so all
  3486. we need to do is format the address.
  3487. Arguments:
  3488. ThisConnection - The server connection of interest.
  3489. NetworkAddress - Will contain string on success.
  3490. Return Value:
  3491. RPC_S_OK or other RPC_S_* errors for error
  3492. --*/
  3493. {
  3494. PWS_CONNECTION p = (PWS_CONNECTION)ThisConnection;
  3495. return WS_ConvertClientAddress((const SOCKADDR *)&p->saClientAddress.ipaddr,
  3496. p->id,
  3497. pNetworkAddress
  3498. );
  3499. }
  3500. RPC_STATUS
  3501. RPC_ENTRY
  3502. TCP_QueryLocalAddress (
  3503. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  3504. IN OUT void *Buffer,
  3505. IN OUT unsigned long *BufferSize,
  3506. OUT unsigned long *AddressFormat
  3507. )
  3508. /*++
  3509. Routine Description:
  3510. Returns the local IP address of a connection.
  3511. Arguments:
  3512. ThisConnection - The server connection of interest.
  3513. Buffer - The buffer that will receive the output address
  3514. BufferSize - the size of the supplied Buffer on input. On output the
  3515. number of bytes written to the buffer. If the buffer is too small
  3516. to receive all the output data, ERROR_MORE_DATA is returned,
  3517. nothing is written to the buffer, and BufferSize is set to
  3518. the size of the buffer needed to return all the data.
  3519. AddressFormat - a constant indicating the format of the returned address.
  3520. Currently supported are RPC_P_ADDR_FORMAT_TCP_IPV4 and
  3521. RPC_P_ADDR_FORMAT_TCP_IPV6. Undefined on failure.
  3522. Return Value:
  3523. RPC_S_OK or other RPC_S_* errors for error
  3524. --*/
  3525. {
  3526. PWS_CONNECTION p = (PWS_CONNECTION)ThisConnection;
  3527. int MinimumBufferLength;
  3528. int Result;
  3529. const WS_TRANS_INFO *pInfo = &WsTransportTable[p->id];
  3530. ASSERT(p->type & SERVER);
  3531. if ((p->id == TCP) || (p->id == HTTP))
  3532. {
  3533. MinimumBufferLength = sizeof(SOCKADDR_IN);
  3534. *AddressFormat = RPC_P_ADDR_FORMAT_TCP_IPV4;
  3535. }
  3536. else
  3537. {
  3538. ASSERT(p->id == TCP_IPv6);
  3539. MinimumBufferLength = sizeof(SOCKADDR_STORAGE);
  3540. *AddressFormat = RPC_P_ADDR_FORMAT_TCP_IPV6;
  3541. }
  3542. if (*BufferSize < MinimumBufferLength)
  3543. {
  3544. *BufferSize = MinimumBufferLength;
  3545. return ERROR_MORE_DATA;
  3546. }
  3547. ASSERT(p->pAddress);
  3548. p->StartingOtherIO();
  3549. if (p->fAborted)
  3550. {
  3551. p->OtherIOFinished();
  3552. return(RPC_S_NO_CONTEXT_AVAILABLE);
  3553. }
  3554. Result = setsockopt(p->Conn.Socket,
  3555. SOL_SOCKET,
  3556. SO_UPDATE_ACCEPT_CONTEXT,
  3557. (char *)&p->pAddress->ListenSocket,
  3558. sizeof(p->pAddress->ListenSocket) );
  3559. if (Result != SOCKET_ERROR)
  3560. {
  3561. Result = getsockname(p->Conn.Socket,
  3562. (sockaddr *)Buffer,
  3563. (int *) BufferSize);
  3564. // SO_UPDATE_ACCEPT_CONTEXT has the nasty habit of deleting
  3565. // all of our socker options. Restore them
  3566. WS_SetSockOptForConnection(pInfo, p->Conn.Socket);
  3567. p->OtherIOFinished();
  3568. if (Result == SOCKET_ERROR)
  3569. {
  3570. RpcpErrorAddRecord(EEInfoGCWinsock,
  3571. RPC_S_OUT_OF_MEMORY,
  3572. EEInfoDLTCP_QueryLocalAddress10,
  3573. (ULONGLONG) p->Conn.Socket,
  3574. GetLastError());
  3575. return RPC_S_OUT_OF_MEMORY;
  3576. }
  3577. }
  3578. else
  3579. {
  3580. p->OtherIOFinished();
  3581. RpcpErrorAddRecord(EEInfoGCWinsock,
  3582. RPC_S_OUT_OF_MEMORY,
  3583. EEInfoDLTCP_QueryLocalAddress20,
  3584. (ULONGLONG) p->Conn.Socket,
  3585. GetLastError());
  3586. return RPC_S_OUT_OF_MEMORY;
  3587. }
  3588. return(RPC_S_OK);
  3589. }
  3590. RPC_STATUS
  3591. RPC_ENTRY
  3592. TCP_QueryClientId(
  3593. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  3594. OUT RPC_CLIENT_PROCESS_IDENTIFIER *ClientProcess
  3595. )
  3596. /*++
  3597. Routine Description:
  3598. For secure protocols (which TCP/IP is not) this is suppose to
  3599. give an ID which will be shared by all clients from the same
  3600. process. This prevents one user from grabbing another users
  3601. association group and using their context handles.
  3602. Since TCP/IP is not secure we return the IP address of the
  3603. client machine. This limits the attacks to other processes
  3604. running on the client machine which is better than nothing.
  3605. Arguments:
  3606. ThisConnection - Server connection in question.
  3607. ClientProcess - Transport identification of the "client".
  3608. Return Value:
  3609. RPC_S_OUT
  3610. --*/
  3611. {
  3612. PWS_CONNECTION p = (PWS_CONNECTION)ThisConnection;
  3613. ASSERT(p->type & SERVER);
  3614. // Currently, we don't have an efficient way of determining which clients
  3615. // are local, and which remote. Since some clients grant more permissions
  3616. // to local clients, we want to be on the safe side, and return all TCP
  3617. // clients as remote.
  3618. ClientProcess->ZeroOut();
  3619. if (p->id != TCP_IPv6)
  3620. {
  3621. ClientProcess->SetIPv4ClientIdentifier(p->saClientAddress.inetaddr.sin_addr.s_addr,
  3622. FALSE // fLocal
  3623. );
  3624. }
  3625. else
  3626. {
  3627. ClientProcess->SetIPv6ClientIdentifier(&p->saClientAddress.ipaddr,
  3628. sizeof(p->saClientAddress.ipaddr),
  3629. FALSE // fLocal
  3630. );
  3631. }
  3632. return(RPC_S_OK);
  3633. }
  3634. RPC_STATUS
  3635. RPC_ENTRY
  3636. TCP_QueryClientIpAddress (
  3637. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  3638. IN OUT RPC_CLIENT_IP_ADDRESS *ClientIpAddress
  3639. )
  3640. /*++
  3641. Routine Description:
  3642. Returns the IP address of the client on a connection as a SOCKADDR.
  3643. The clients address is saved when the client connects, so all
  3644. we need to do is copy it.
  3645. Arguments:
  3646. ThisConnection - The server connection of interest.
  3647. ClientIpAddress - the buffer to store the address to.
  3648. Return Value:
  3649. RPC_S_OK or other RPC_S_* errors for error
  3650. --*/
  3651. {
  3652. ULONG BufferLength;
  3653. PWS_CONNECTION p = (PWS_CONNECTION)ThisConnection;
  3654. if (p->id != TCP_IPv6)
  3655. {
  3656. BufferLength = sizeof(SOCKADDR_IN);
  3657. }
  3658. else
  3659. {
  3660. BufferLength = sizeof(SOCKADDR_IN6);
  3661. }
  3662. ASSERT(BufferLength <= sizeof(ClientIpAddress->Data));
  3663. ClientIpAddress->DataSize = BufferLength;
  3664. // we know both IPv4 and IPv6 start at the same offset. Just copy the respective
  3665. // size starting at the offset.
  3666. RpcpMemoryCopy (ClientIpAddress->Data, &p->saClientAddress.ipaddr, BufferLength);
  3667. return RPC_S_OK;
  3668. }
  3669. RPC_STATUS
  3670. TCPOrHTTP_Open(
  3671. IN WS_CONNECTION *Connection,
  3672. IN RPC_CHAR * NetworkAddress,
  3673. IN USHORT Endpoint,
  3674. IN UINT ConnTimeout,
  3675. IN UINT SendBufferSize,
  3676. IN UINT RecvBufferSize,
  3677. IN OUT TCPResolverHint *Hint,
  3678. IN BOOL fHintInitialized,
  3679. IN ULONG CallTimeout,
  3680. IN BOOL fHTTP2Open,
  3681. IN I_RpcProxyIsValidMachineFn IsValidMachineFn OPTIONAL
  3682. )
  3683. /*++
  3684. Routine Description:
  3685. Opens a connection to a server.
  3686. Arguments:
  3687. ThisConnection - A place to store the connection
  3688. NetworkAddress - The name of the server, either a dot address or DNS name
  3689. Endpoint - the port number in host byte order representation
  3690. ConnTimeout - See RpcMgmtSetComTimeout
  3691. 0 - Min
  3692. 5 - Default
  3693. 9 - Max
  3694. 10 - Infinite
  3695. SendBufferSize -
  3696. RecvBufferSize - (Both optional) Specifies the size of the send/recv
  3697. transport buffers.
  3698. ResolverHint - Resolver hint
  3699. fHintInitialized - If TRUE, the ResolveHint contains the IP address
  3700. of the server. If FALSE, do standard name resolution.
  3701. CallTimeout - the call timeout in milliseconds
  3702. fHTTP2Open - non-zero if this is an HTTP2 Open
  3703. IsValidMachineFn - a callback function that is used to validate machine/port
  3704. for access from this process. Used by HTTP only.
  3705. Return Value:
  3706. RPC_S_OK
  3707. RPC_S_OUT_OF_MEMORY
  3708. RPC_S_OUT_OF_RESOURCES
  3709. RPC_S_SERVER_UNAVAILABLE
  3710. RPC_S_INVALID_ENDPOINT_FORMAT
  3711. RPC_S_INVALID_NET_ADDR
  3712. --*/
  3713. {
  3714. RPC_STATUS status;
  3715. RPC_STATUS status2;
  3716. WS_SOCKADDR sa;
  3717. PVOID rnrContext;
  3718. BOOL fIPv4Hint;
  3719. USES_CONVERSION;
  3720. CStackAnsi AnsiName;
  3721. BOOL NetworkAddressConverted;
  3722. char *DotName;
  3723. char *DotNamePtr;
  3724. char DotNameBuffer[max(IP_MAXIMUM_RAW_NAME, IPv6_MAXIMUM_RAW_NAME) + 1];
  3725. ASSERT(NetworkAddress);
  3726. // All this function needs to is initialize transport specific
  3727. // parts of the connection and sockaddr. This includes resolving
  3728. // the network address into a `raw' address.
  3729. RpcpSetIpPort(&sa, htons(Endpoint));
  3730. if (fHTTP2Open)
  3731. {
  3732. Connection->id = HTTPv2;
  3733. NetworkAddressConverted = FALSE;
  3734. }
  3735. else
  3736. Connection->id = TCP;
  3737. // Two cases, previously saved address or first open
  3738. if (fHintInitialized)
  3739. {
  3740. Hint->GetResolverHint(&fIPv4Hint, &sa);
  3741. if (!fIPv4Hint)
  3742. Connection->id = TCP_IPv6;
  3743. ASSERT(IsValidMachineFn == FALSE);
  3744. status = WS_Open((PWS_CCONNECTION)Connection,
  3745. &sa,
  3746. ConnTimeout,
  3747. SendBufferSize,
  3748. RecvBufferSize,
  3749. CallTimeout,
  3750. fHTTP2Open
  3751. );
  3752. if (status == ERROR_RETRY)
  3753. {
  3754. status = RPC_S_SERVER_UNAVAILABLE;
  3755. }
  3756. return(status);
  3757. }
  3758. // Prepare to resolve the network address
  3759. IP_ADDRESS_RESOLVER resolver(NetworkAddress,
  3760. cosClient,
  3761. ipvtuIPAny // IP version to use
  3762. );
  3763. // Loop until success, fatal failure or we run out of addresses.
  3764. do
  3765. {
  3766. status = resolver.NextAddress(&sa.ipaddr);
  3767. // check the list of valid machines first. If this is not a valid
  3768. // machine, we don't want to return out information on whether the name
  3769. // resolves or not
  3770. if (IsValidMachineFn)
  3771. {
  3772. ASSERT(fHTTP2Open != FALSE);
  3773. if (NetworkAddressConverted == FALSE)
  3774. {
  3775. ATTEMPT_STACK_W2A(AnsiName, NetworkAddress);
  3776. NetworkAddressConverted = TRUE;
  3777. }
  3778. if (status == RPC_S_OK)
  3779. {
  3780. DotName = inet_ntoa(sa.inetaddr.sin_addr);
  3781. strcpy(DotNameBuffer, DotName);
  3782. DotNamePtr = DotNameBuffer;
  3783. }
  3784. else
  3785. {
  3786. DotNamePtr = NULL;
  3787. }
  3788. status2 = IsValidMachineFn(AnsiName,
  3789. DotNamePtr,
  3790. Endpoint
  3791. );
  3792. if (status2 != RPC_S_OK)
  3793. {
  3794. // if we're out of names, no point in continuing
  3795. if (status != RPC_S_OK)
  3796. {
  3797. // move the status from the allowed check to the return value
  3798. status = status2;
  3799. break;
  3800. }
  3801. // if the server is resolved, but not allowed for access, continue with next
  3802. status = ERROR_RETRY;
  3803. continue;
  3804. }
  3805. else if (status != RPC_S_OK)
  3806. {
  3807. // the server is allowed, but can't be resolved - break where we will return an error
  3808. break;
  3809. }
  3810. }
  3811. if (status != RPC_S_OK)
  3812. {
  3813. break;
  3814. }
  3815. if (sa.ipaddr.ss_family == AF_INET6)
  3816. Connection->id = TCP_IPv6;
  3817. else if (Connection->id == TCP_IPv6)
  3818. {
  3819. // if we were at IPv6 and we didn't select IPv6 this time, it must
  3820. // be IPv4
  3821. ASSERT(sa.ipaddr.ss_family == AF_INET);
  3822. Connection->id = TCP;
  3823. }
  3824. // Call common open function
  3825. status = WS_Open((PWS_CCONNECTION)Connection,
  3826. &sa,
  3827. ConnTimeout,
  3828. SendBufferSize,
  3829. RecvBufferSize,
  3830. CallTimeout,
  3831. fHTTP2Open
  3832. );
  3833. }
  3834. while (status == ERROR_RETRY);
  3835. if (status == RPC_S_OK)
  3836. {
  3837. Hint->SetResolverHint((Connection->id == TCP) || (Connection->id == HTTPv2), &sa);
  3838. }
  3839. return(status);
  3840. }
  3841. RPC_STATUS
  3842. RPC_ENTRY
  3843. TCP_Open(
  3844. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  3845. IN RPC_CHAR * ProtocolSequence,
  3846. IN RPC_CHAR * NetworkAddress,
  3847. IN RPC_CHAR * Endpoint,
  3848. IN RPC_CHAR * NetworkOptions,
  3849. IN UINT ConnTimeout,
  3850. IN UINT SendBufferSize,
  3851. IN UINT RecvBufferSize,
  3852. IN OUT PVOID ResolverHint,
  3853. IN BOOL fHintInitialized,
  3854. IN ULONG CallTimeout,
  3855. IN ULONG AdditionalTransportCredentialsType, OPTIONAL
  3856. IN void *AdditionalCredentials OPTIONAL
  3857. )
  3858. /*++
  3859. Routine Description:
  3860. Opens a connection to a server.
  3861. Arguments:
  3862. ThisConnection - A place to store the connection
  3863. ProtocolSeqeunce - "ncacn_ip_tcp". Ignored in this function
  3864. NetworkAddress - The name of the server, either a dot address or DNS name
  3865. NetworkOptions - Ignored
  3866. ConnTimeout - See RpcMgmtSetComTimeout
  3867. 0 - Min
  3868. 5 - Default
  3869. 9 - Max
  3870. 10 - Infinite
  3871. SendBufferSize -
  3872. RecvBufferSize - (Both optional) Specifies the size of the send/recv
  3873. transport buffers.
  3874. ResolverHint - IP address of server, if valid.
  3875. fHintInitialized - If TRUE, the ResolveHint contains the IP address
  3876. of the server. If FALSE, do standard name resolution.
  3877. CallTimeout - the call timeout in milliseconds
  3878. AdditionalTransportCredentialsType - the type of additional credentials that we were
  3879. given. Not used for TCP.
  3880. AdditionalCredentials - additional credentials that we were given.
  3881. Not used for TCP.
  3882. Return Value:
  3883. RPC_S_OK
  3884. RPC_S_OUT_OF_MEMORY
  3885. RPC_S_OUT_OF_RESOURCES
  3886. RPC_S_SERVER_UNAVAILABLE
  3887. RPC_S_INVALID_ENDPOINT_FORMAT
  3888. RPC_S_INVALID_NET_ADDR
  3889. --*/
  3890. {
  3891. RPC_STATUS status;
  3892. PWS_CCONNECTION p = (PWS_CCONNECTION)ThisConnection;
  3893. USHORT port;
  3894. ASSERT(NetworkAddress);
  3895. if ((AdditionalTransportCredentialsType != 0) || (AdditionalCredentials != NULL))
  3896. return RPC_S_CANNOT_SUPPORT;
  3897. // use explicit placement to initialize the vtable. We need this to
  3898. // be able to use the virtual functions
  3899. p = new (p) WS_CLIENT_CONNECTION;
  3900. // All this function needs to is initialize transport specific
  3901. // parts of the connection and sockaddr. This includes resolving
  3902. // the network address into a `raw' address.
  3903. // Figure out the destination port
  3904. status = EndpointToPortNumber(Endpoint, port);
  3905. if (status != RPC_S_OK)
  3906. {
  3907. return(status);
  3908. }
  3909. return TCPOrHTTP_Open (p,
  3910. NetworkAddress,
  3911. port,
  3912. ConnTimeout,
  3913. SendBufferSize,
  3914. RecvBufferSize,
  3915. (TCPResolverHint *)ResolverHint,
  3916. fHintInitialized,
  3917. CallTimeout,
  3918. FALSE, // fHTTP2Open
  3919. NULL // IsValidMachineFn
  3920. );
  3921. }
  3922. #ifdef SPX_ON
  3923. /////////////////////////////////////////////////////////////////////
  3924. //
  3925. // SPX specific functions
  3926. //
  3927. RPC_STATUS
  3928. SPX_ServerListen(
  3929. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  3930. IN RPC_CHAR *NetworkAddress,
  3931. IN OUT RPC_CHAR * *pEndpoint,
  3932. IN UINT PendingQueueSize,
  3933. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  3934. IN ULONG EndpointFlags,
  3935. IN ULONG NICFlags
  3936. )
  3937. /*++
  3938. Routine Description:
  3939. This routine allocates a new pipe to receive new client connections.
  3940. If successful a call to COMMON_ServerCompleteListen() will actually allow
  3941. new connection callbacks to the RPC runtime to occur. If the runtime
  3942. is unable to complete then it must abort the address by calling
  3943. WS_ServerAbortListen().
  3944. Arguments:
  3945. pAddress - A pointer to the loadable transport interface address.
  3946. pEndpoint - Optionally, the endpoint (port) to listen on. Set to
  3947. to listened port for dynamically allocated endpoints.
  3948. PendingQueueSize - Count to call listen() with.
  3949. EndpointFlags - Meaningless for SPX
  3950. NICFlags - Meaningless for SPX
  3951. SecurityDescriptor - Meaningless for SPX
  3952. Return Value:
  3953. RPC_S_OK
  3954. RPC_S_OUT_OF_MEMORY
  3955. RPC_S_OUT_OF_RESOURCES
  3956. RPC_S_CANT_CREATE_ENDPOINT
  3957. RPC_S_DUPLICATE_ENDPOINT
  3958. --*/
  3959. {
  3960. PWS_ADDRESS pAddress = (PWS_ADDRESS)ThisAddress;
  3961. RPC_STATUS status;
  3962. WS_SOCKADDR *sockaddr = &(pAddress->ListenAddr);
  3963. INT i;
  3964. USHORT port;
  3965. pAddress->id = SPX;
  3966. pAddress->NewConnection = WS_NewConnection;
  3967. pAddress->SubmitListen = WS_SubmitAccept;
  3968. SetProtocolMultiplier(pAddress, 1);
  3969. pAddress->pAddressVector = 0;
  3970. pAddress->Endpoint = 0;
  3971. pAddress->QueueSize = PendingQueueSize;
  3972. pAddress->EndpointFlags = EndpointFlags;
  3973. sockaddr->generic.sa_family = WsTransportTable[SPX].AddressFamily;
  3974. // Figure out what port to bind to.
  3975. if (*pEndpoint)
  3976. {
  3977. status = EndpointToPortNumber(*pEndpoint, port);
  3978. if (status != RPC_S_OK)
  3979. {
  3980. return(status);
  3981. }
  3982. sockaddr->ipxaddr.sa_socket = htons(port);
  3983. pAddress->fDynamicEndpoint = 0;
  3984. }
  3985. else
  3986. {
  3987. pAddress->fDynamicEndpoint = 1;
  3988. sockaddr->ipxaddr.sa_socket = 0;
  3989. }
  3990. // No need to bind to a specific address for SPX
  3991. memset(sockaddr->ipxaddr.sa_netnum, 0, sizeof(sockaddr->ipxaddr.sa_netnum) );
  3992. memset(sockaddr->ipxaddr.sa_nodenum, 0, sizeof(sockaddr->ipxaddr.sa_nodenum));
  3993. // Actually listen
  3994. status = WS_ServerListenCommon(pAddress);
  3995. if (status == RPC_S_OK)
  3996. {
  3997. // Listened okay, update local IPX address.
  3998. //
  3999. // Since there is only one addess no lock is required.
  4000. //
  4001. memcpy(IpxAddr.sa_netnum, sockaddr->ipxaddr.sa_netnum, 4);
  4002. memcpy(IpxAddr.sa_nodenum, sockaddr->ipxaddr.sa_nodenum, 6);
  4003. fIpxAddrValid = TRUE;
  4004. // Figure out our network addresses
  4005. status = IPX_BuildAddressVector(&pAddress->pAddressVector);
  4006. if (status != RPC_S_OK)
  4007. {
  4008. WS_ServerAbortListen(pAddress);
  4009. return(status);
  4010. }
  4011. // Return the dynamic port, if needed.
  4012. if (!*pEndpoint)
  4013. {
  4014. *pEndpoint = new RPC_CHAR[6]; // 65535 max
  4015. if (!*pEndpoint)
  4016. {
  4017. WS_ServerAbortListen(ThisAddress);
  4018. return(RPC_S_OUT_OF_MEMORY);
  4019. }
  4020. port = ntohs(sockaddr->ipxaddr.sa_socket);
  4021. PortNumberToEndpoint(port, *pEndpoint);
  4022. }
  4023. TransportProtocol::FunctionalProtocolDetected(pAddress->id);
  4024. // Save away the endpoint in the address, if needed, here.
  4025. // (PnP?)
  4026. }
  4027. else if (status == RPC_P_ADDRESS_FAMILY_INVALID)
  4028. {
  4029. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  4030. }
  4031. return(status);
  4032. }
  4033. RPC_STATUS
  4034. RPC_ENTRY
  4035. SPX_QueryClientAddress(
  4036. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  4037. OUT RPC_CHAR ** pNetworkAddress
  4038. )
  4039. /*++
  4040. Routine Description:
  4041. Returns the raw IPX of the client to a connection as a string. The
  4042. clients address is saved when the client connects, so all we need to do is
  4043. format the address.
  4044. Arguments:
  4045. ThisConnection - The connection of interest.
  4046. pNetworkAddress - Will contain string on success.
  4047. Return Value:
  4048. RPC_S_OK
  4049. RPC_S_OUT_OF_MEMORY
  4050. --*/
  4051. {
  4052. WS_CONNECTION *p= (WS_CONNECTION *)ThisConnection;
  4053. ASSERT(p->type & SERVER);
  4054. RPC_CHAR *Address = new RPC_CHAR[IPX_MAXIMUM_RAW_NAME];
  4055. if (!Address)
  4056. {
  4057. return(RPC_S_OUT_OF_MEMORY);
  4058. }
  4059. IPX_AddressToName(&p->saClientAddress.ipxaddr, Address);
  4060. *pNetworkAddress = Address;
  4061. return(RPC_S_OK);
  4062. }
  4063. RPC_STATUS
  4064. RPC_ENTRY
  4065. SPX_QueryClientId(
  4066. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  4067. OUT RPC_CLIENT_PROCESS_IDENTIFIER *ClientProcess
  4068. )
  4069. /*++
  4070. Routine Description:
  4071. For secure protocols (which SPX is not) this is suppose to give an ID
  4072. which will be shared by all connections from the same process or security
  4073. identity. This prevents one user from grabbing another users association
  4074. group and using their context handles.
  4075. Since SPX is not secure we return the IPX node number of the client.
  4076. This limits the attacks to other processes running on the client machine
  4077. which is better than nothing.
  4078. Arguments:
  4079. ThisConnection - Server connection in question.
  4080. ClientProcess - Transport identification of the "client".
  4081. Return Value:
  4082. RPC_S_OUT
  4083. --*/
  4084. {
  4085. PWS_CONNECTION p = (PWS_CONNECTION)ThisConnection;
  4086. ASSERT(p->type & SERVER);
  4087. // The runtime assumes that any connections with a ClientProcess->FirstPart is
  4088. // zero means the client is local.
  4089. // Currently, we don't have an efficient way of determining which clients
  4090. // are local, and which remote. Since some clients grant more permissions
  4091. // to local clients, we want to be on the safe side, and return all SPX
  4092. // clients as remote.
  4093. ClientProcess->ZeroOut();
  4094. ClientProcess->SetIPXClientIdentifier(p->saClientAddress.ipxaddr.sa_nodenum,
  4095. sizeof(p->saClientAddress.ipxaddr.sa_nodenum), FALSE);
  4096. return(RPC_S_OK);
  4097. }
  4098. RPC_STATUS
  4099. RPC_ENTRY
  4100. SPX_Open(
  4101. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  4102. IN RPC_CHAR * ProtocolSequence,
  4103. IN RPC_CHAR * NetworkAddress,
  4104. IN RPC_CHAR * Endpoint,
  4105. IN RPC_CHAR * NetworkOptions,
  4106. IN UINT ConnTimeout,
  4107. IN UINT SendBufferSize,
  4108. IN UINT RecvBufferSize,
  4109. IN void *ResolverHint,
  4110. IN BOOL fHintInitialized,
  4111. IN ULONG CallTimeout,
  4112. IN ULONG AdditionalTransportCredentialsType, OPTIONAL
  4113. IN void *AdditionalCredentials OPTIONAL
  4114. )
  4115. /*++
  4116. Routine Description:
  4117. Opens a connection to a server.
  4118. Arguments:
  4119. ThisConnection - A place to store the connection
  4120. ProtocolSeqeunce - "ncacn_spx"
  4121. NetworkAddress - The name of the server, either a raw address or pretty name
  4122. NetworkOptions - Ignored
  4123. ConnTimeout - See RpcMgmtSetComTimeout
  4124. 0 - Min
  4125. 5 - Default
  4126. 9 - Max
  4127. 10 - Infinite
  4128. SendBufferSize -
  4129. RecvBufferSize - (Both optional) Specifies the size of the send/recv
  4130. transport buffers.
  4131. CallTimeout - call timeout in milliseconds
  4132. AdditionalTransportCredentialsType - the type of additional credentials that we were
  4133. given. Not used for SPX.
  4134. AdditionalCredentials - additional credentials that we were given.
  4135. Not used for SPX.
  4136. Return Value:
  4137. RPC_S_OK
  4138. RPC_S_OUT_OF_MEMORY
  4139. RPC_S_OUT_OF_RESOURCES
  4140. RPC_S_SERVER_UNAVAILABLE
  4141. RPC_S_INVALID_ENDPOINT_FORMAT
  4142. RPC_S_INVALID_NET_ADDR
  4143. --*/
  4144. {
  4145. RPC_STATUS status;
  4146. PWS_CCONNECTION p = (PWS_CCONNECTION)ThisConnection;
  4147. SOCKET sock;
  4148. WS_SOCKADDR sa;
  4149. CHAR AnsiPort[IPX_MAXIMUM_ENDPOINT];
  4150. PCHAR AnsiNetworkAddress;
  4151. BOOL fUseCache = TRUE;
  4152. BOOL fFoundInCache = FALSE;
  4153. if ((AdditionalTransportCredentialsType != 0) || (AdditionalCredentials != NULL))
  4154. return RPC_S_CANNOT_SUPPORT;
  4155. // use explicit placement to initialize the vtable. We need this to
  4156. // be able to use the virtual functions
  4157. p = new (p) WS_CLIENT_CONNECTION;
  4158. // All this function needs to is initialize transport specific
  4159. // parts of the connection and sockaddr. This includes resolving
  4160. // the network address into a `raw' address.
  4161. p->id = SPX;
  4162. // Figure out the destination port
  4163. USHORT port;
  4164. status = EndpointToPortNumber(Endpoint, port);
  4165. if (status != RPC_S_OK)
  4166. {
  4167. return(status);
  4168. }
  4169. for (;;)
  4170. {
  4171. // Resolve network address
  4172. sa.ipxaddr.sa_family = AF_IPX;
  4173. sa.ipxaddr.sa_socket = 0;
  4174. status = IPX_NameToAddress(NetworkAddress, fUseCache, &sa.ipxaddr);
  4175. if (status == RPC_P_FOUND_IN_CACHE)
  4176. {
  4177. ASSERT(fUseCache);
  4178. fFoundInCache = TRUE;
  4179. status = RPC_S_OK;
  4180. }
  4181. if (status != RPC_S_OK)
  4182. {
  4183. if (status == RPC_P_MATCHED_CACHE)
  4184. {
  4185. status = RPC_S_SERVER_UNAVAILABLE;
  4186. }
  4187. return(status);
  4188. }
  4189. sa.ipxaddr.sa_socket = htons(port);
  4190. // Call common open function
  4191. status = WS_Open(p,
  4192. &sa,
  4193. ConnTimeout,
  4194. SendBufferSize,
  4195. RecvBufferSize,
  4196. CallTimeout,
  4197. FALSE // fHTTP2Open
  4198. );
  4199. if (status == ERROR_RETRY)
  4200. {
  4201. status = RPC_S_SERVER_UNAVAILABLE;
  4202. }
  4203. if ( status == RPC_S_SERVER_UNAVAILABLE
  4204. && fFoundInCache
  4205. && fUseCache )
  4206. {
  4207. fUseCache = FALSE;
  4208. continue;
  4209. }
  4210. break;
  4211. }
  4212. return(status);
  4213. }
  4214. #endif
  4215. #ifdef APPLETALK_ON
  4216. /////////////////////////////////////////////////////////////////////
  4217. //
  4218. // Appletalk data stream protocol (DSP) specific functions
  4219. //
  4220. RPC_STATUS DSP_GetAppleTalkName(
  4221. OUT CHAR *Buffer
  4222. )
  4223. /*++
  4224. Routine Description:
  4225. Returns the server's name for appletalk workstations. This value
  4226. defaults to GetComputerName() but can be changed. Mail from JameelH:
  4227. By default it is the netbios name of the server. It can be overwritten.
  4228. The new name is at:
  4229. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MacFile\Parameters\ServerName.
  4230. By default this value is not present.
  4231. Arguments:
  4232. Buffer - Supplies a buffer (at least 33 bytes) for the name.
  4233. Return Value:
  4234. RPC_S_OK - The operation completed successfully.
  4235. RPC_S_OUT_OF_RESOURCES - Unable to get the name for some reasons.
  4236. --*/
  4237. {
  4238. RPC_STATUS Status;
  4239. HKEY hKey;
  4240. DWORD Size = 33;
  4241. DWORD Type;
  4242. Status =
  4243. RegOpenKeyEx(
  4244. HKEY_LOCAL_MACHINE,
  4245. RPC_CONST_SSTRING("System\\CurrentControlSet\\Services\\MacFile\\Parameters"),
  4246. 0,
  4247. KEY_READ,
  4248. &hKey);
  4249. if ( Status != ERROR_SUCCESS
  4250. && Status != ERROR_FILE_NOT_FOUND )
  4251. {
  4252. ASSERT(0);
  4253. return(RPC_S_OUT_OF_RESOURCES);
  4254. }
  4255. if (Status == ERROR_SUCCESS)
  4256. {
  4257. Status =
  4258. RegQueryValueExA(
  4259. hKey,
  4260. "ServerName",
  4261. 0,
  4262. &Type,
  4263. (PBYTE)Buffer,
  4264. &Size);
  4265. }
  4266. (void) RegCloseKey(hKey);
  4267. if ( Status != ERROR_SUCCESS
  4268. && Status != ERROR_FILE_NOT_FOUND )
  4269. {
  4270. ASSERT(0);
  4271. return(RPC_S_OUT_OF_RESOURCES);
  4272. }
  4273. if (Status == ERROR_SUCCESS)
  4274. {
  4275. // Found a name in the registry.
  4276. ASSERT( Type == REG_SZ
  4277. && Size <= 32
  4278. && strlen(Buffer) == (Size + 1));
  4279. return(RPC_S_OK);
  4280. }
  4281. // Not in the registry, must be using the computer name.
  4282. Size = 33;
  4283. if ( GetComputerNameA(
  4284. Buffer,
  4285. &Size ) == FALSE )
  4286. {
  4287. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4288. DPFLTR_WARNING_LEVEL,
  4289. "GetComputerNameA failed! %d\n",
  4290. GetLastError()));
  4291. ASSERT(0);
  4292. return(RPC_S_OUT_OF_RESOURCES);
  4293. }
  4294. return(RPC_S_OK);
  4295. }
  4296. const PCHAR DSP_OBJECTTYPE_PREFIX = "DceDspRpc ";
  4297. RPC_STATUS
  4298. DSP_ServerListen(
  4299. IN RPC_TRANSPORT_ADDRESS ThisAddress,
  4300. IN RPC_CHAR *NetworkAddress,
  4301. IN OUT RPC_CHAR * *pEndpoint,
  4302. IN UINT PendingQueueSize,
  4303. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  4304. IN ULONG EndpointFlags,
  4305. IN ULONG NICFlags
  4306. )
  4307. /*++
  4308. Routine Description:
  4309. This routine allocates a port to receive new client connections.
  4310. If successful a call to COMMON_ServerCompleteListen() will actually allow
  4311. new connection callbacks to the RPC runtime to occur. If the runtime
  4312. is unable to complete then it must abort the address by calling
  4313. WS_ServerAbortListen().
  4314. Arguments:
  4315. pAddress - A pointer to the loadable transport interface address.
  4316. pEndpoint - Optionally, the endpoint (port) to listen on. Set to
  4317. to listened port for dynamically allocated endpoints.
  4318. PendingQueueSize - Count to call listen() with.
  4319. EndpointFlags - Meaningless for DSP
  4320. NICFlags - Meaningless for DSP
  4321. SecurityDescriptor - Meaningless for DSP
  4322. Return Value:
  4323. RPC_S_OK
  4324. RPC_S_OUT_OF_MEMORY
  4325. RPC_S_OUT_OF_RESOURCES
  4326. RPC_S_CANT_CREATE_ENDPOINT
  4327. RPC_S_DUPLICATE_ENDPOINT
  4328. --*/
  4329. {
  4330. PWS_ADDRESS pAddress = (PWS_ADDRESS)ThisAddress;
  4331. RPC_STATUS status;
  4332. WS_SOCKADDR *sockaddr = &(pAddress->ListenAddr);
  4333. USHORT port;
  4334. CHAR AnsiEndpoint[NBP_MAXIMUM_ENDPOINT];
  4335. pAddress->id = DSP;
  4336. pAddress->NewConnection = WS_NewConnection;
  4337. pAddress->SubmitListen = WS_SubmitAccept;
  4338. SetProtocolMultiplier(pAddress, 1);
  4339. pAddress->pAddressVector = 0;
  4340. pAddress->Endpoint = 0;
  4341. pAddress->QueueSize = PendingQueueSize;
  4342. pAddress->EndpointFlags = EndpointFlags;
  4343. //
  4344. // For DSP the endpoint is a character string. It is not actually used
  4345. // to allocate the socket. We let DSP allocate a port and then register
  4346. // the port along with our address and endpoint with NBP.
  4347. //
  4348. if (*pEndpoint)
  4349. {
  4350. // Runtime gave us an endpoint, convert it to ansi
  4351. int nLength;
  4352. *AnsiEndpoint = 0;
  4353. nLength = RpcpStringLength(*pEndpoint);
  4354. if ((nLength <= 0) || (nLength > 22))
  4355. {
  4356. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  4357. }
  4358. PlatformToAnsi(*pEndpoint, AnsiEndpoint);
  4359. pAddress->fDynamicEndpoint = 0;
  4360. }
  4361. else
  4362. {
  4363. static LONG EndpointCount = 0;
  4364. //
  4365. // Create a dynamic endpoint using Use process ID + 16-bit counter.
  4366. //
  4367. *pEndpoint = new RPC_CHAR[7 + 8 + 4 + 1 + 1];
  4368. if (!*pEndpoint)
  4369. {
  4370. return(RPC_S_OUT_OF_MEMORY);
  4371. }
  4372. CHAR buffer[9];
  4373. strcpy(AnsiEndpoint, "DynEpt ");
  4374. _ltoa(GetCurrentProcessId(), buffer, 16);
  4375. lstrcatA(AnsiEndpoint, buffer);
  4376. buffer[0] = '.';
  4377. LONG t = InterlockedIncrement(&EndpointCount);
  4378. _ltoa( t & 0xFFFF, buffer + 1, 16);
  4379. lstrcatA(AnsiEndpoint, buffer);
  4380. SimpleAnsiToPlatform(AnsiEndpoint, *pEndpoint);
  4381. pAddress->fDynamicEndpoint = 1;
  4382. }
  4383. ASSERT(strlen(AnsiEndpoint) > 0 && strlen(AnsiEndpoint) < NBP_MAXIMUM_ENDPOINT);
  4384. memset(&sockaddr->ataddr, 0, sizeof(WS_SOCKADDR));
  4385. sockaddr->generic.sa_family = WsTransportTable[DSP].AddressFamily;
  4386. // For DSP we always bind to a transport choosen port. The endpoint
  4387. // only exists in the NBP router as a mapping to our address and port.
  4388. // Create listen socket
  4389. status = WS_ServerListenCommon(pAddress);
  4390. if (status != RPC_S_OK)
  4391. {
  4392. if (status == RPC_P_ADDRESS_FAMILY_INVALID)
  4393. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  4394. return(status);
  4395. }
  4396. // Now, try to register our name and zone.
  4397. //
  4398. // The final format of the name to register is:
  4399. // <ComputerName>@<Zone>@DceDspRpc <Endpoint>
  4400. //
  4401. // The <ComputerName>@<Zone> string is treated as this machines
  4402. // name as far as the runtime cares. The <Endpoint> is used as
  4403. // the endpoint.
  4404. //
  4405. CHAR ComputerName[NBP_MAXIMUM_NAME];
  4406. status = DSP_GetAppleTalkName(ComputerName);
  4407. if (status != RPC_S_OK)
  4408. {
  4409. WS_ServerAbortListen(ThisAddress);
  4410. return(status);
  4411. }
  4412. // The following code segment is commented out to be consistent with
  4413. // what we did in NT4. In NT4, we had a bug where if the AppleTalk name
  4414. // registered is just the computer name without the zone name appended.
  4415. // In NT5, we achieve the same by commenting out this code which appends
  4416. // the zone name.
  4417. //
  4418. /*
  4419. INT cZone;
  4420. PSZ pszT = ComputerName;
  4421. while(*pszT)
  4422. pszT++;
  4423. *pszT++ = '@';
  4424. cZone = 33;
  4425. // So far we have ComputerName@ and a pointer to just after the @.
  4426. if (getsockopt(pAddress->ListenSocket,
  4427. SOL_APPLETALK,
  4428. SO_LOOKUP_MYZONE,
  4429. pszT,
  4430. &cZone) != 0)
  4431. {
  4432. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4433. DPFLTR_WARNING_LEVEL,
  4434. RPCTRANS "Failed to lookup zone: %d\n",
  4435. GetLastError()));
  4436. // Don't fail, this could be a small network, just register '*' for
  4437. // the broadcast/local zone.
  4438. *pszT++ = '*';
  4439. *pszT++ = '0';
  4440. }
  4441. */
  4442. //
  4443. // We need to register our computer name and endpoint next.
  4444. //
  4445. WSH_REGISTER_NAME AtalkNameToRegister;
  4446. int length;
  4447. ASSERT(MAX_COMPUTERNAME_LENGTH < MAX_ENTITY + 1);
  4448. length = strlen(AnsiEndpoint);
  4449. memcpy(AtalkNameToRegister.TypeName, DSP_OBJECTTYPE_PREFIX, 10);
  4450. memcpy(AtalkNameToRegister.TypeName + 10, AnsiEndpoint, length);
  4451. AtalkNameToRegister.TypeNameLen = length + 10;
  4452. length = strlen(ComputerName);
  4453. memcpy(AtalkNameToRegister.ObjectName, ComputerName, length);
  4454. AtalkNameToRegister.ObjectNameLen = (char) length;
  4455. AtalkNameToRegister.ZoneName[0] = '*';
  4456. AtalkNameToRegister.ZoneNameLen = 1;
  4457. // Could do a lookup and connect to see if our name is already registered..
  4458. if (setsockopt(
  4459. pAddress->ListenSocket,
  4460. SOL_APPLETALK,
  4461. SO_REGISTER_NAME,
  4462. (char *)&AtalkNameToRegister,
  4463. sizeof(AtalkNameToRegister)
  4464. ) != 0 )
  4465. {
  4466. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4467. DPFLTR_WARNING_LEVEL,
  4468. RPCTRANS "Failed to register name: %d\n",
  4469. GetLastError()));
  4470. WS_ServerAbortListen(ThisAddress);
  4471. return(RPC_S_CANT_CREATE_ENDPOINT);
  4472. }
  4473. // All done, build out parameters
  4474. ASSERT(length == (int) strlen(ComputerName));
  4475. NETWORK_ADDRESS_VECTOR *pVector;
  4476. pVector = new( sizeof(RPC_CHAR *)
  4477. + (length + 2) * sizeof(RPC_CHAR))
  4478. NETWORK_ADDRESS_VECTOR;
  4479. if (NULL == pVector)
  4480. {
  4481. WS_ServerAbortListen(ThisAddress);
  4482. return(RPC_S_OUT_OF_MEMORY);
  4483. }
  4484. pVector->Count = 1;
  4485. pVector->NetworkAddresses[0] = (RPC_CHAR*)&pVector->NetworkAddresses[1];
  4486. AnsiToPlatform(ComputerName, pVector->NetworkAddresses[0]);
  4487. pAddress->pAddressVector = pVector;
  4488. return(RPC_S_OK);
  4489. }
  4490. RPC_STATUS
  4491. RPC_ENTRY
  4492. DSP_Open(
  4493. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  4494. IN RPC_CHAR * ProtocolSequence,
  4495. IN RPC_CHAR * NetworkAddress,
  4496. IN RPC_CHAR * Endpoint,
  4497. IN RPC_CHAR * NetworkOptions,
  4498. IN UINT ConnTimeout,
  4499. IN UINT SendBufferSize,
  4500. IN UINT RecvBufferSize,
  4501. IN void *ResolverHint,
  4502. IN BOOL fHintInitialized,
  4503. IN ULONG CallTimeout,
  4504. IN ULONG AdditionalTransportCredentialsType, OPTIONAL
  4505. IN void *AdditionalCredentials OPTIONAL
  4506. )
  4507. /*++
  4508. Routine Description:
  4509. Not supported on Windows NT.
  4510. --*/
  4511. {
  4512. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  4513. }
  4514. #endif
  4515. RPC_STATUS RPC_ENTRY WS_Abort(IN RPC_TRANSPORT_CONNECTION Connection)
  4516. {
  4517. return ((WS_CONNECTION *)Connection)->WS_CONNECTION::Abort();
  4518. }
  4519. /////////////////////////////////////////////////////////////////////
  4520. //
  4521. // Transport information definitions
  4522. //
  4523. const RPC_CONNECTION_TRANSPORT
  4524. TCP_TransportInterface =
  4525. {
  4526. RPC_TRANSPORT_INTERFACE_VERSION,
  4527. TCP_TOWER_ID,
  4528. IP_ADDRESS_ID,
  4529. RPC_STRING_LITERAL("ncacn_ip_tcp"),
  4530. "135",
  4531. COMMON_ProcessCalls,
  4532. COMMON_StartPnpNotifications,
  4533. COMMON_ListenForPNPNotifications,
  4534. COMMON_TowerConstruct,
  4535. COMMON_TowerExplode,
  4536. COMMON_PostRuntimeEvent,
  4537. FALSE,
  4538. WS_GetNetworkAddressVector,
  4539. sizeof(WS_ADDRESS),
  4540. max(sizeof(WS_CLIENT_CONNECTION), sizeof(WS_SAN_CLIENT_CONNECTION)),
  4541. max(sizeof(WS_CONNECTION), sizeof(WS_SAN_CONNECTION)),
  4542. sizeof(CO_SEND_CONTEXT),
  4543. sizeof(TCPResolverHint),
  4544. TCP_MAX_SEND,
  4545. WS_Initialize,
  4546. 0,
  4547. TCP_Open,
  4548. 0, // No SendRecv on winsock
  4549. WS_SyncRecv,
  4550. WS_Abort,
  4551. WS_Close,
  4552. CO_Send,
  4553. CO_Recv,
  4554. WS_SyncSend,
  4555. WS_TurnOnOffKeepAlives,
  4556. TCP_ServerListen,
  4557. WS_ServerAbortListen,
  4558. COMMON_ServerCompleteListen,
  4559. TCP_QueryClientAddress,
  4560. TCP_QueryLocalAddress,
  4561. TCP_QueryClientId,
  4562. TCP_QueryClientIpAddress,
  4563. 0, // Impersonate
  4564. 0, // Revert
  4565. 0, // FreeResolverHint
  4566. 0, // CopyResolverHint
  4567. 0, // CompareResolverHint
  4568. 0 // SetLastBufferToFree
  4569. };
  4570. // When the RPC verifier is enabled and we are corrupting client receives,
  4571. // we will use a modified transport interface given below. It will have the sync
  4572. // receive members overwritten.
  4573. RPC_CONNECTION_TRANSPORT *pTCP_TransportInterface_Avrf = NULL;
  4574. #ifdef SPX_ON
  4575. const RPC_CONNECTION_TRANSPORT
  4576. SPX_TransportInterface =
  4577. {
  4578. RPC_TRANSPORT_INTERFACE_VERSION,
  4579. SPX_TOWER_ID,
  4580. IPX_ADDRESS_ID,
  4581. RPC_STRING_LITERAL("ncacn_spx"),
  4582. "34280",
  4583. COMMON_ProcessCalls,
  4584. COMMON_StartPnpNotifications,
  4585. COMMON_ListenForPNPNotifications,
  4586. COMMON_TowerConstruct,
  4587. COMMON_TowerExplode,
  4588. COMMON_PostRuntimeEvent,
  4589. FALSE,
  4590. WS_GetNetworkAddressVector,
  4591. sizeof(WS_ADDRESS),
  4592. max(sizeof(WS_CLIENT_CONNECTION), sizeof(WS_SAN_CLIENT_CONNECTION)),
  4593. max(sizeof(WS_CONNECTION), sizeof(WS_SAN_CONNECTION)),
  4594. sizeof(CO_SEND_CONTEXT),
  4595. 0,
  4596. SPX_MAX_SEND,
  4597. WS_Initialize,
  4598. 0,
  4599. SPX_Open,
  4600. 0, // No SendRecv on winsock
  4601. WS_SyncRecv,
  4602. WS_Abort,
  4603. WS_Close,
  4604. CO_Send,
  4605. CO_Recv,
  4606. WS_SyncSend,
  4607. 0, // turn on/off keep alives
  4608. SPX_ServerListen,
  4609. WS_ServerAbortListen,
  4610. COMMON_ServerCompleteListen,
  4611. SPX_QueryClientAddress,
  4612. 0, // query local address
  4613. SPX_QueryClientId,
  4614. 0, // query client ip address
  4615. 0, // Impersonate
  4616. 0, // Revert
  4617. 0, // FreeResolverHint
  4618. 0, // CopyResolverHint
  4619. 0, // CompareResolverHint
  4620. 0 // SetLastBufferToFree
  4621. };
  4622. #endif
  4623. #ifdef APPLETALK_ON
  4624. const RPC_CONNECTION_TRANSPORT
  4625. DSP_TransportInterface =
  4626. {
  4627. RPC_TRANSPORT_INTERFACE_VERSION,
  4628. DSP_TOWER_ID,
  4629. NBP_ADDRESS_ID,
  4630. RPC_STRING_LITERAL("ncacn_at_dsp"),
  4631. "Endpoint Mapper",
  4632. COMMON_ProcessCalls,
  4633. COMMON_StartPnpNotifications,
  4634. COMMON_ListenForPNPNotifications,
  4635. COMMON_TowerConstruct,
  4636. COMMON_TowerExplode,
  4637. COMMON_PostRuntimeEvent,
  4638. FALSE,
  4639. WS_GetNetworkAddressVector,
  4640. sizeof(WS_ADDRESS),
  4641. sizeof(WS_CLIENT_CONNECTION),
  4642. sizeof(WS_CONNECTION),
  4643. sizeof(CO_SEND_CONTEXT),
  4644. 0,
  4645. DSP_MAX_SEND,
  4646. WS_Initialize,
  4647. 0,
  4648. DSP_Open, // Not really supported.
  4649. 0, // No SendRecv on winsock
  4650. WS_SyncRecv,
  4651. WS_Abort,
  4652. WS_Close,
  4653. CO_Send,
  4654. CO_Recv,
  4655. WS_SyncSend,
  4656. 0, // turn on/off keep alives
  4657. DSP_ServerListen,
  4658. WS_ServerAbortListen,
  4659. COMMON_ServerCompleteListen,
  4660. 0, // DSP_QueryClientAddress,
  4661. 0, // DSP_QueryClientId,
  4662. 0, // query client ip address
  4663. 0, // Impersonate
  4664. 0, // Revert
  4665. 0, // FreeResolverHint
  4666. 0, // CopyResolverHint
  4667. 0, // CompareResolverHint
  4668. 0 // SetLastBufferToFree
  4669. };
  4670. #endif
  4671. const RPC_CONNECTION_TRANSPORT *
  4672. WS_TransportLoad (
  4673. IN PROTOCOL_ID index
  4674. )
  4675. {
  4676. RPC_STATUS status;
  4677. if (fWinsockLoaded == FALSE)
  4678. {
  4679. if (RPC_WSAStartup() == FALSE)
  4680. {
  4681. return 0;
  4682. }
  4683. fWinsockLoaded = TRUE;
  4684. }
  4685. switch(index)
  4686. {
  4687. case TCP:
  4688. AddressChangeFn = I_RpcServerInqAddressChangeFn();
  4689. if (AddressChangeFn)
  4690. {
  4691. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4692. DPFLTR_WARNING_LEVEL,
  4693. RPCTRANS "TCP address change function has been loaded"));
  4694. }
  4695. if (DoFirewallInit())
  4696. {
  4697. // Overwrite the SyncSendRecv and SyncRecv members of the transport interfaces if the
  4698. // RPC verifier is enabled.
  4699. if (gfRpcVerifierCorruptionInjectClientReceives)
  4700. {
  4701. // Check if we have previously initialized the Avrf transport interface.
  4702. if (pTCP_TransportInterface_Avrf == NULL)
  4703. {
  4704. // Allocate a transport interface structure to override the default.
  4705. pTCP_TransportInterface_Avrf = new (RPC_CONNECTION_TRANSPORT);
  4706. if (pTCP_TransportInterface_Avrf == NULL)
  4707. {
  4708. return NULL;
  4709. }
  4710. // Initialize the Avrf transport interface with the default values.
  4711. RpcpMemoryCopy(pTCP_TransportInterface_Avrf,
  4712. &TCP_TransportInterface,
  4713. sizeof(RPC_CONNECTION_TRANSPORT));
  4714. // Override the interface function for sync receive.
  4715. ASSERT(pTCP_TransportInterface_Avrf->SyncRecv == WS_SyncRecv);
  4716. pTCP_TransportInterface_Avrf->SyncRecv = WS_SyncRecv_Avrf;
  4717. }
  4718. return(pTCP_TransportInterface_Avrf);
  4719. }
  4720. return(&TCP_TransportInterface);
  4721. }
  4722. break;
  4723. #ifdef SPX_ON
  4724. case SPX:
  4725. AddressChangeFn = I_RpcServerInqAddressChangeFn();
  4726. if (AddressChangeFn)
  4727. {
  4728. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4729. DPFLTR_WARNING_LEVEL,
  4730. RPCTRANS "SPX address change function has been loaded"));
  4731. }
  4732. if (InitializeIpxNameCache() != RPC_S_OK)
  4733. {
  4734. return(0);
  4735. }
  4736. return(&SPX_TransportInterface);
  4737. #endif
  4738. #ifdef APPLETALK_ON
  4739. case DSP:
  4740. return(&DSP_TransportInterface);
  4741. #endif
  4742. case HTTP:
  4743. if (DoFirewallInit())
  4744. {
  4745. return(&HTTP_TransportInterface);
  4746. }
  4747. break;
  4748. default:
  4749. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  4750. DPFLTR_WARNING_LEVEL,
  4751. RPCTRANS "WS_TransportLoad called with index: %d\n",
  4752. index));
  4753. ASSERT(0);
  4754. }
  4755. return(0);
  4756. }
  4757. RPC_STATUS SAN_CONNECTION::SANReceive(HANDLE hFile, LPVOID lpBuffer,
  4758. DWORD nNumberOfBytesToRead,
  4759. LPDWORD lpNumberOfBytesRead,
  4760. LPOVERLAPPED lpOverlapped)
  4761. {
  4762. WSABUF wsaBuf;
  4763. int nResult;
  4764. wsaBuf.len = nNumberOfBytesToRead;
  4765. wsaBuf.buf = (char *)lpBuffer;
  4766. m_dwFlags = 0;
  4767. nResult = WSARecv((SOCKET)hFile, &wsaBuf, 1, lpNumberOfBytesRead, &m_dwFlags,
  4768. lpOverlapped, NULL);
  4769. if (nResult == SOCKET_ERROR)
  4770. return WSAGetLastError();
  4771. else
  4772. return RPC_S_OK;
  4773. }
  4774. RPC_STATUS SAN_CONNECTION::SANSend(HANDLE hFile, LPCVOID lpBuffer,
  4775. DWORD nNumberOfBytesToWrite,
  4776. LPDWORD lpNumberOfBytesWritten,
  4777. LPOVERLAPPED lpOverlapped)
  4778. {
  4779. WSABUF wsaBuf;
  4780. int nResult;
  4781. wsaBuf.len = nNumberOfBytesToWrite;
  4782. wsaBuf.buf = (char *)lpBuffer;
  4783. nResult = WSASend((SOCKET)hFile, &wsaBuf, 1, lpNumberOfBytesWritten, 0,
  4784. lpOverlapped, NULL);
  4785. if (nResult == SOCKET_ERROR)
  4786. return WSAGetLastError();
  4787. else
  4788. return RPC_S_OK;
  4789. }
  4790. RPC_STATUS WS_CONNECTION::Receive(HANDLE hFile, LPVOID lpBuffer,
  4791. DWORD nNumberOfBytesToRead,
  4792. LPDWORD lpNumberOfBytesRead,
  4793. LPOVERLAPPED lpOverlapped)
  4794. {
  4795. return UTIL_ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
  4796. }
  4797. RPC_STATUS WS_CONNECTION::Send(HANDLE hFile, LPCVOID lpBuffer,
  4798. DWORD nNumberOfBytesToWrite,
  4799. LPDWORD lpNumberOfBytesWritten,
  4800. LPOVERLAPPED lpOverlapped)
  4801. {
  4802. return UTIL_WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
  4803. }
  4804. void
  4805. RPC_CLIENT_PROCESS_IDENTIFIER::SetIPv6ClientIdentifier (
  4806. IN void *Buffer,
  4807. IN size_t BufferSize,
  4808. IN BOOL fLocal)
  4809. /*++
  4810. Routine Description:
  4811. IPv6 servers can use this to store their IP address in
  4812. the client identifier.
  4813. Arguments:
  4814. Buffer - the buffer with the client identifier
  4815. BufferSize - the size of the data in buffer
  4816. fLocal - TRUE if the client is guaranteed to be Local. False otherwise.
  4817. Return Value:
  4818. --*/
  4819. {
  4820. SOCKADDR_IN6 *IPv6Address;
  4821. ASSERT(BufferSize >= sizeof(SOCKADDR_IN6));
  4822. this->fLocal = fLocal;
  4823. RpcpMemoryCopy(u.ULongClientId, Buffer, sizeof(SOCKADDR_IN6));
  4824. IPv6Address = (SOCKADDR_IN6 *)u.ULongClientId;
  4825. IPv6Address->sin6_port = 0;
  4826. IPv6Address->sin6_flowinfo = 0;
  4827. IPv6Address->sin6_scope_id = 0;
  4828. }