Source code of Windows XP (NT5)
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.

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