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

3061 lines
81 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. dgtrans.cxx
  5. Abstract:
  6. Common code for winsock-based datagram transports.
  7. Author:
  8. Dave Steckler (davidst) 15-Mar-1993
  9. Jeff Roberts (jroberts) 02-Dec-1994
  10. Mario Goertzel (mariogo) 10-Apr-1996
  11. Michael Burton (t-mburt) 05-Sep-1997
  12. Charlie Wickham (charlwi) 01-Oct-1997
  13. Revision History:
  14. Dave wrote a version.
  15. Connie changed it but forgot to add her name.
  16. Jeff made it work.
  17. Mario rewrote most of it for NT and io completion ports.
  18. MarioGo 12/10/1996 Changes for async support, added client
  19. t-mburt 09/05/1997 Added prelim support for clusters
  20. charlwi 10/01/1997 Finished cluster work
  21. --*/
  22. #include <precomp.hxx>
  23. #include <trans.hxx>
  24. #include <dgtrans.hxx>
  25. #include <wswrap.hxx>
  26. #ifdef NCADG_MQ_ON
  27. #include "mqtrans.hxx"
  28. #endif
  29. //
  30. // If a datagram send doesn't complete within 5 seconds, abort it.
  31. //
  32. #define DG_SEND_TIMEOUT (5000)
  33. // Cluster SOCKADDR_CLUSTER initialization routine
  34. inline void
  35. CDP_InitLocalAddress(
  36. SOCKADDR_CLUSTER *Address,
  37. unsigned short Endpoint
  38. )
  39. {
  40. Address->sac_family = AF_CLUSTER;
  41. Address->sac_node = CLUSADDR_ANY;
  42. Address->sac_port = Endpoint;
  43. Address->sac_zero = 0;
  44. }
  45. extern RPC_STATUS CDP_InitializeSockAddr(char *Endpoint, WS_SOCKADDR *, DG_TRANSPORT_ENDPOINT ThisEndpoint = NULL);
  46. extern RPC_STATUS UDP_InitializeSockAddr(char *Endpoint, WS_SOCKADDR *, DG_TRANSPORT_ENDPOINT ThisEndpoint = NULL);
  47. #ifdef IPX_ON
  48. extern RPC_STATUS IPX_InitializeSockAddr(char *Endpoint, WS_SOCKADDR *);
  49. #endif
  50. const DG_TRANS_INFO DgTransportTable[] =
  51. {
  52. // UDP
  53. {
  54. AF_INET,
  55. SOCK_DGRAM,
  56. IPPROTO_UDP,
  57. 0x40000,
  58. 0x10000,
  59. UDP_InitializeSockAddr
  60. },
  61. #ifdef IPX_ON
  62. // IPX
  63. {
  64. AF_IPX,
  65. SOCK_DGRAM,
  66. NSPROTO_IPX,
  67. 0x40000,
  68. 0x10000,
  69. IPX_InitializeSockAddr
  70. },
  71. #else
  72. // IPX
  73. {
  74. 0,
  75. 0,
  76. 0,
  77. 0,
  78. 0,
  79. 0
  80. },
  81. #endif
  82. // CDP
  83. {
  84. AF_CLUSTER,
  85. SOCK_DGRAM,
  86. CLUSPROTO_CDP,
  87. 0x40000,
  88. 0x10000,
  89. CDP_InitializeSockAddr
  90. }
  91. };
  92. inline const DG_TRANS_INFO *GetDgTransportInfo(PROTOCOL_ID id)
  93. {
  94. #ifdef IPX_ON
  95. ASSERT(id == UDP || id == IPX || id == CDP);
  96. #else
  97. ASSERT(id == UDP || id == CDP);
  98. #endif
  99. return &DgTransportTable[id - UDP];
  100. }
  101. typedef const DG_TRANS_INFO *PDG_TRANS_INFO;
  102. // may be TRUE only for rpcss. For all others it's FALSE
  103. BOOL fWSARecvMsgFnPtrInitialized = FALSE;
  104. const UUID WSARecvMsgFnPtrUuid = WSAID_WSARECVMSG;
  105. ////////////////////////////////////////////////////////////////////////
  106. //
  107. // Generic datagram (winsock and NT based) routines.
  108. //
  109. RPC_STATUS
  110. DG_SubmitReceive(IN PWS_DATAGRAM_ENDPOINT pEndpoint,
  111. IN PWS_DATAGRAM pDatagram)
  112. /*++
  113. Arguments:
  114. pEndpoint - The endpoint on which the receive should be posted.
  115. pDatagram - The datagram object to manage the receive.
  116. Return Value:
  117. RPC_P_IO_PENDING - OK
  118. RPC_S_OUT_OF_MEMORY
  119. RPC_S_OUT_OF_RESOURCES
  120. --*/
  121. {
  122. RPC_STATUS status;
  123. NTSTATUS NtStatus;
  124. DWORD bytes, flags;
  125. int err;
  126. if (pDatagram->Packet.buf == 0)
  127. {
  128. status = I_RpcTransDatagramAllocate(pEndpoint,
  129. (BUFFER *)&pDatagram->Packet.buf,
  130. (PUINT) &pDatagram->Packet.len,
  131. &pDatagram->AddressPair);
  132. if (status != RPC_S_OK)
  133. {
  134. return(RPC_S_OUT_OF_MEMORY);
  135. }
  136. pDatagram->AddressPair->LocalAddress
  137. = WSA_CMSG_DATA(&pDatagram->MessageAncillaryData)
  138. + FIELD_OFFSET(in_pktinfo, ipi_addr);
  139. ASSERT( pDatagram->Packet.buf );
  140. }
  141. ASSERT(*(PDWORD)pDatagram->Packet.buf = 0xDEADF00D);
  142. bytes = flags = 0;
  143. if (!fWSARecvMsgFnPtrInitialized)
  144. {
  145. pDatagram->cRecvAddr = sizeof(WS_SOCKADDR);
  146. err = WSARecvFrom(((WS_DATAGRAM_ENDPOINT*)(pDatagram->pEndpoint))->Socket,
  147. &pDatagram->Packet,
  148. 1,
  149. &bytes,
  150. &flags,
  151. &((WS_SOCKADDR *)pDatagram->AddressPair->RemoteAddress)->generic,
  152. &pDatagram->cRecvAddr,
  153. &pDatagram->Read.ol,
  154. 0);
  155. }
  156. else
  157. {
  158. pDatagram->Msg.lpBuffers = &pDatagram->Packet;
  159. pDatagram->Msg.name = &((WS_SOCKADDR *)pDatagram->AddressPair->RemoteAddress)->generic;
  160. pDatagram->Msg.namelen = sizeof(WS_SOCKADDR);
  161. pDatagram->Msg.dwBufferCount = 1;
  162. pDatagram->Msg.Control.buf = (char *)pDatagram->MessageAncillaryData;
  163. pDatagram->Msg.Control.len = sizeof(pDatagram->MessageAncillaryData);
  164. pDatagram->Msg.dwFlags = 0;
  165. err = WSARecvMsg(((WS_DATAGRAM_ENDPOINT*)(pDatagram->pEndpoint))->Socket,
  166. &pDatagram->Msg,
  167. &bytes,
  168. &pDatagram->Read.ol,
  169. 0);
  170. }
  171. #if 0
  172. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  173. DPFLTR_WARNING_LEVEL,
  174. RPCTRANS "ERROR: RecvFrom: %p buf %p (%d bytes) status %d\n",
  175. pDatagram,
  176. pDatagram->Packet.buf,
  177. pDatagram->Packet.len,
  178. err == 0 ? 0 : GetLastError()));
  179. #endif
  180. if (err == NO_ERROR)
  181. {
  182. return(RPC_P_IO_PENDING);
  183. }
  184. status = GetLastError();
  185. if ( status == ERROR_IO_PENDING
  186. || status == WSAEMSGSIZE )
  187. {
  188. // WSAEMSGSIZE will be handled in complete.cxx. This is like "NO_ERROR"
  189. return(RPC_P_IO_PENDING);
  190. }
  191. RpcpErrorAddRecord( EEInfoGCWinsock,
  192. status,
  193. EEInfoDLWinsockDatagramSubmitReceive10,
  194. ((WS_DATAGRAM_ENDPOINT*)(pDatagram->pEndpoint))->Socket
  195. );
  196. if (WSAECONNRESET == status)
  197. {
  198. return RPC_P_PORT_DOWN;
  199. }
  200. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  201. DPFLTR_WARNING_LEVEL,
  202. RPCTRANS "WSARecvFrom failed %p\n",
  203. GetLastError()));
  204. return(RPC_S_OUT_OF_RESOURCES);
  205. }
  206. void
  207. DG_SubmitReceives(
  208. BASE_ADDRESS *ThisEndpoint
  209. )
  210. /*++
  211. Routine Description:
  212. Helper function called when the pending IO count
  213. on an address is too low.
  214. Arguments:
  215. ThisEndpoint - The address to submit IOs on.
  216. Return Value:
  217. None
  218. --*/
  219. {
  220. PWS_DATAGRAM pDg;
  221. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  222. if (pEndpoint->Socket == 0)
  223. {
  224. //
  225. // The address is currently deactivated, don't submit more I/O
  226. //
  227. return;
  228. }
  229. do
  230. {
  231. BOOL fIoSubmitted;
  232. fIoSubmitted = FALSE;
  233. // Only one thread should be trying to submit IOs at a time.
  234. // This saves locking each DATAGRAM object.
  235. // Simple lock - but requires a loop. See the comment at the end
  236. // of the loop.
  237. if (pEndpoint->fSubmittingIos != 0)
  238. break;
  239. if (InterlockedIncrement(&pEndpoint->fSubmittingIos) != 1)
  240. break;
  241. // Submit new IOs on all the idle datagram objects
  242. for (int i = 0; i < pEndpoint->cMaximumIos; i++)
  243. {
  244. pDg = &pEndpoint->aDatagrams[i];
  245. if (pDg->Busy)
  246. {
  247. continue;
  248. }
  249. // Must be all set for the IO to complete before trying
  250. // to submit the IO.
  251. InterlockedIncrement(&pEndpoint->cPendingIos);
  252. pDg->Busy = TRUE;
  253. if (DG_SubmitReceive(pEndpoint, pDg) == RPC_P_IO_PENDING)
  254. {
  255. fIoSubmitted = TRUE;
  256. }
  257. else
  258. {
  259. pDg->Busy = FALSE;
  260. InterlockedDecrement(&pEndpoint->cPendingIos);
  261. break;
  262. }
  263. }
  264. // Release the "lock" on the endpoint object.
  265. //
  266. // Xeon processors have eratta G40:
  267. // Potential Loss of Data Coherency Duaring MP Data Ownership Transfer.
  268. // To work around it, it is necessary to use InterlockedExchange rather then an assignment
  269. // to force cache coherency.
  270. InterlockedExchange(&pEndpoint->fSubmittingIos, 0);
  271. if (!fIoSubmitted && pEndpoint->cPendingIos == 0)
  272. {
  273. // It appears that no IO is pending on the endpoint.
  274. COMMON_AddressManager(pEndpoint);
  275. return;
  276. }
  277. // Even if we submitted new IOs, they may all have completed
  278. // already. Which means we may need to loop and submit more
  279. // IOs. This is needed since the thread which completed the
  280. // last IO may have run into our lock and returned.
  281. }
  282. while (pEndpoint->cPendingIos == 0);
  283. return;
  284. }
  285. NETWORK_ADDRESS_VECTOR *
  286. DG_GetNetworkAddressVector(
  287. IN RPC_TRANSPORT_ADDRESS pAddress
  288. )
  289. {
  290. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT) pAddress;
  291. ASSERT(pEndpoint->pAddressVector);
  292. return pEndpoint->pAddressVector;
  293. }
  294. RPC_STATUS RPC_ENTRY
  295. DG_SendPacket(
  296. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  297. IN DG_TRANSPORT_ADDRESS pAddress,
  298. IN BUFFER pHeader,
  299. IN unsigned cHeader,
  300. IN BUFFER pBody,
  301. IN unsigned cBody,
  302. IN BUFFER pTrailer,
  303. IN unsigned cTrailer
  304. )
  305. /*++
  306. Routine Description:
  307. Sends a packet to an address.
  308. The routine will send a packet built out of the three buffers supplied.
  309. All the buffers are optional, the actual packet sent will be built from
  310. all the buffers actually supplied. In each call at least buffer should
  311. NOT be null.
  312. Arguments:
  313. ThisEndpoint - Endpoint to send from.
  314. pAddress - Address to send to.
  315. pHeader - First data buffer
  316. cHeader - Size of the first data buffer or 0.
  317. pBody - Second data buffer
  318. cBody - Size of the second data buffer or 0.
  319. pTrailer - Third data buffer.
  320. cTrailer - Size of the first data buffer or 0.
  321. Return Value:
  322. RPC_S_OK
  323. RPC_S_OUT_OF_RESOURCES
  324. RPC_P_SEND_FAILED
  325. --*/
  326. {
  327. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  328. WS_SOCKADDR* pSockAddr = (WS_SOCKADDR *)pAddress;
  329. WSABUF buffers[3];
  330. int cBuffers;
  331. HANDLE hIoEvent;
  332. DWORD Status = 0;
  333. if (pHeader)
  334. {
  335. CallTestHook( TH_X_DG_SEND, pHeader, &Status );
  336. }
  337. else
  338. {
  339. CallTestHook( TH_X_DG_SEND, pBody, &Status );
  340. }
  341. if (Status)
  342. {
  343. return Status;
  344. }
  345. hIoEvent = I_RpcTransGetThreadEvent();
  346. cBuffers = 0;
  347. if (cHeader)
  348. {
  349. buffers[cBuffers].len = cHeader;
  350. buffers[cBuffers].buf = (PCHAR) pHeader;
  351. cBuffers++;
  352. }
  353. if (cBody)
  354. {
  355. buffers[cBuffers].len = cBody;
  356. buffers[cBuffers].buf = (PCHAR) pBody;
  357. cBuffers++;
  358. }
  359. if (cTrailer)
  360. {
  361. buffers[cBuffers].len = cTrailer;
  362. buffers[cBuffers].buf = (PCHAR) pTrailer;
  363. cBuffers++;
  364. }
  365. ASSERT(cBuffers);
  366. // All RPC packets have version 4.
  367. //
  368. ASSERT( buffers[0].buf[0] == 4 );
  369. OVERLAPPED ol;
  370. ol.hEvent = (HANDLE)(ULONG_PTR(hIoEvent) | 1);
  371. DWORD bytes;
  372. if ( WSASendTo(pEndpoint->Socket,
  373. buffers,
  374. cBuffers,
  375. &bytes,
  376. 0,
  377. &pSockAddr->generic,
  378. WsTransportTable[pEndpoint->id].SockAddrSize,
  379. &ol,
  380. 0) != 0)
  381. {
  382. DWORD Status = GetLastError();
  383. RpcpErrorAddRecord( EEInfoGCWinsock,
  384. Status,
  385. EEInfoDLWinsockDatagramSend10,
  386. PULONG(&pSockAddr->generic)[0],
  387. PULONG(&pSockAddr->generic)[1]
  388. );
  389. if (WSAENETUNREACH == Status)
  390. {
  391. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  392. DPFLTR_INFO_LEVEL,
  393. RPCTRANS "WSASendTo failed with net unreachable\n",
  394. GetLastError()));
  395. return RPC_P_PORT_DOWN;
  396. }
  397. if (WSAEHOSTDOWN == Status)
  398. {
  399. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  400. DPFLTR_INFO_LEVEL,
  401. RPCTRANS "WSASendTo failed with host down\n",
  402. GetLastError()));
  403. return RPC_P_HOST_DOWN;
  404. }
  405. if (Status != WSA_IO_PENDING)
  406. {
  407. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  408. DPFLTR_INFO_LEVEL,
  409. RPCTRANS "WSASendTo failed %d\n",
  410. GetLastError()));
  411. return(RPC_P_SEND_FAILED);
  412. }
  413. if (WAIT_OBJECT_0 != WaitForSingleObject( hIoEvent, DG_SEND_TIMEOUT ))
  414. {
  415. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  416. DPFLTR_INFO_LEVEL,
  417. RPCTRANS "Dg Send timed out\n"));
  418. //
  419. // Cancel the send and wait for it to complete.
  420. //
  421. CancelIo( (HANDLE)pEndpoint->Socket );
  422. GetOverlappedResult((HANDLE)pEndpoint->Socket,
  423. &ol,
  424. &bytes,
  425. TRUE);
  426. return(RPC_P_SEND_FAILED);
  427. }
  428. BOOL b = GetOverlappedResult((HANDLE)pEndpoint->Socket,
  429. &ol,
  430. &bytes,
  431. TRUE);
  432. if (!b)
  433. {
  434. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  435. DPFLTR_INFO_LEVEL,
  436. RPCTRANS "Dg Send wait failed %d\n",
  437. GetLastError()));
  438. return(RPC_P_SEND_FAILED);
  439. }
  440. }
  441. ASSERT(bytes == cHeader + cBody + cTrailer);
  442. if (pEndpoint->cMinimumIos &&
  443. pEndpoint->cPendingIos <= pEndpoint->cMinimumIos)
  444. {
  445. // It's ok if this fails, this is just a performance optimization.
  446. // Right after a send there often "idle" time waiting for the response
  447. // so this is a good time to submit receives.
  448. DG_SubmitReceives(pEndpoint);
  449. }
  450. return(RPC_S_OK);
  451. }
  452. RPC_STATUS RPC_ENTRY
  453. DG_ForwardPacket(
  454. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  455. IN BUFFER pHeader,
  456. IN unsigned cHeader,
  457. IN BUFFER pBody,
  458. IN unsigned cBody,
  459. IN BUFFER pTrailer,
  460. IN unsigned cTrailer,
  461. IN CHAR * pszPort
  462. )
  463. /*++
  464. Routine Description:
  465. Sends a packet to the server it was originally destined for (that
  466. is, the client had a dynamic endpoint it wished the enpoint mapper
  467. to resolve and forward the packet to).
  468. Arguments:
  469. ThisEndpoint - The endpoint to forward the packet from.
  470. // Buffer like DG_SendPacket
  471. pszPort - Pointer to the server port num to forward to.
  472. This is in an Ansi string.
  473. Return Value:
  474. RPC_S_CANT_CREATE_ENDPOINT - pEndpoint invalid.
  475. results of SendPacket().
  476. --*/
  477. {
  478. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  479. WS_SOCKADDR SockAddr;
  480. PDG_TRANS_INFO pInfo = GetDgTransportInfo(pEndpoint->id);
  481. DG_TRANSPORT_ENDPOINT EndpointWithAddressToForwardTo;
  482. ASSERT(pEndpoint->type | SERVER);
  483. // If selective bindings are enabled, forward the packet to the
  484. // interface that the current endpoint is listening on
  485. // rather then to the loopback address. Otherwise, forward to
  486. // the loopback address by default.
  487. if (pFirewallTable != NULL)
  488. EndpointWithAddressToForwardTo = ThisEndpoint;
  489. else
  490. EndpointWithAddressToForwardTo = NULL;
  491. if (pInfo->EndpointToAddr(pszPort, &SockAddr, EndpointWithAddressToForwardTo) != RPC_S_OK)
  492. {
  493. return RPC_S_CANT_CREATE_ENDPOINT;
  494. }
  495. return ( DG_SendPacket(ThisEndpoint,
  496. (PVOID)&SockAddr,
  497. pHeader,
  498. cHeader,
  499. pBody,
  500. cBody,
  501. pTrailer,
  502. cTrailer) );
  503. }
  504. RPC_STATUS
  505. RPC_ENTRY
  506. DG_ReceivePacket(
  507. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  508. OUT DG_TRANSPORT_ADDRESS *pReplyAddress,
  509. OUT PUINT pBufferLength,
  510. OUT BUFFER *pBuffer,
  511. IN LONG Timeout
  512. )
  513. /*++
  514. Routine Description:
  515. Used to wait for a datagram from a server. Returns the data
  516. returned and the address of the machine which replied.
  517. This is a blocking API. It should only be called during sync
  518. client RPC threads.
  519. Arguments:
  520. Endpoint - The endpoint to receive from.
  521. ReplyAddress - Contain the source address of the datagram if
  522. successful.
  523. BufferLength - The size of Buffer on input, the size of the
  524. datagram received on output.
  525. Timeout - Milliseconds to wait for a datagram.
  526. Return Value:
  527. RPC_S_OK
  528. RPC_P_OVERSIZE_PACKET - Datagram > BufferLength arrived,
  529. first BufferLength bytes of Buffer contain the partial datagram.
  530. RPC_P_RECEIVE_FAILED
  531. RPC_P_TIMEOUT
  532. --*/
  533. {
  534. RPC_STATUS status;
  535. BOOL b;
  536. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  537. PWS_DATAGRAM pDatagram = &pEndpoint->aDatagrams[0];
  538. DWORD bytes;
  539. DWORD flags;
  540. int err;
  541. ASSERT((pEndpoint->type & TYPE_MASK) == CLIENT);
  542. ASSERT(pEndpoint->aDatagrams[0].Read.ol.hEvent);
  543. DWORD Status = 0;
  544. CallTestHook( TH_X_DG_SYNC_RECV, ThisEndpoint, &Status );
  545. if (Status)
  546. {
  547. return Status;
  548. }
  549. if (pDatagram->Busy == 0)
  550. {
  551. if (pEndpoint->aDatagrams[0].Packet.buf == 0)
  552. {
  553. status = I_RpcTransDatagramAllocate(pEndpoint,
  554. (BUFFER *)&pDatagram->Packet.buf,
  555. (PUINT) &pDatagram->Packet.len,
  556. &pDatagram->AddressPair);
  557. if (status != RPC_S_OK)
  558. {
  559. return(RPC_S_OUT_OF_MEMORY);
  560. }
  561. pDatagram->cRecvAddr = sizeof(WS_SOCKADDR);
  562. pDatagram->AddressPair->LocalAddress
  563. = WSA_CMSG_DATA(&pDatagram->MessageAncillaryData)
  564. + FIELD_OFFSET(in_pktinfo, ipi_addr);
  565. ASSERT( pDatagram->Packet.buf );
  566. }
  567. bytes = flags = 0;
  568. if (!fWSARecvMsgFnPtrInitialized)
  569. {
  570. err = WSARecvFrom(pEndpoint->Socket,
  571. &pDatagram->Packet,
  572. 1,
  573. &bytes,
  574. &flags,
  575. &((WS_SOCKADDR *)pDatagram->AddressPair->RemoteAddress)->generic,
  576. &pDatagram->cRecvAddr,
  577. &pDatagram->Read.ol,
  578. 0);
  579. }
  580. else
  581. {
  582. pDatagram->Msg.lpBuffers = &pDatagram->Packet;
  583. pDatagram->Msg.name = &((WS_SOCKADDR *)pDatagram->AddressPair->RemoteAddress)->generic;
  584. pDatagram->Msg.namelen = sizeof(WS_SOCKADDR);
  585. pDatagram->Msg.dwBufferCount = 1;
  586. pDatagram->Msg.Control.buf = (char *)&pDatagram->MessageAncillaryData;
  587. pDatagram->Msg.Control.len = sizeof(pDatagram->MessageAncillaryData);
  588. pDatagram->Msg.dwFlags = 0;
  589. err = WSARecvMsg(((WS_DATAGRAM_ENDPOINT*)(pDatagram->pEndpoint))->Socket,
  590. &pDatagram->Msg,
  591. &bytes,
  592. &pDatagram->Read.ol,
  593. 0);
  594. }
  595. if ( err != 0)
  596. {
  597. status = GetLastError();
  598. if (status != WSA_IO_PENDING)
  599. {
  600. RpcpErrorAddRecord( EEInfoGCWinsock,
  601. status,
  602. EEInfoDLWinsockDatagramReceive10,
  603. pEndpoint->Socket
  604. );
  605. if (status == WSAEMSGSIZE)
  606. {
  607. status = RPC_P_OVERSIZE_PACKET;
  608. }
  609. else if (status == WSAECONNRESET)
  610. {
  611. return RPC_P_PORT_DOWN;
  612. }
  613. else
  614. {
  615. // No need to free the packet now.
  616. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  617. DPFLTR_INFO_LEVEL,
  618. RPCTRANS "WSARecvFrom failed %d\n",
  619. status));
  620. ASSERT(pDatagram->Busy == 0);
  621. return(RPC_P_RECEIVE_FAILED);
  622. }
  623. }
  624. else
  625. {
  626. status = RPC_P_IO_PENDING;
  627. }
  628. }
  629. else
  630. {
  631. status = RPC_S_OK;
  632. }
  633. pDatagram->Busy = TRUE;
  634. }
  635. else
  636. {
  637. ASSERT(pDatagram->Busy);
  638. ASSERT(pDatagram->Packet.buf);
  639. status = RPC_P_IO_PENDING;
  640. }
  641. // Wait for IO to complete or timeout
  642. if (status == RPC_P_IO_PENDING)
  643. {
  644. status = WaitForSingleObjectEx(pDatagram->Read.ol.hEvent,
  645. Timeout,
  646. TRUE);
  647. if (status != STATUS_WAIT_0)
  648. {
  649. // In the timeout case we just want to return and
  650. // leave. We'll finish the receive on the next call.
  651. if (status == WAIT_IO_COMPLETION)
  652. {
  653. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  654. DPFLTR_WARNING_LEVEL,
  655. RPCTRANS "DG received cancelled (%p)\n",
  656. pDatagram));
  657. }
  658. else
  659. {
  660. ASSERT(status == STATUS_TIMEOUT);
  661. }
  662. ASSERT(pDatagram->Busy);
  663. return(RPC_P_TIMEOUT);
  664. }
  665. BOOL b = GetOverlappedResult((HANDLE)pEndpoint->Socket,
  666. &pDatagram->Read.ol,
  667. &bytes,
  668. FALSE);
  669. if (!b)
  670. {
  671. RpcpErrorAddRecord( EEInfoGCWinsock,
  672. GetLastError(),
  673. EEInfoDLWinsockDatagramSend20,
  674. pEndpoint->Socket
  675. );
  676. switch (GetLastError())
  677. {
  678. case WSAEMSGSIZE:
  679. case ERROR_MORE_DATA:
  680. ASSERT(bytes == pDatagram->Packet.len);
  681. status = RPC_P_OVERSIZE_PACKET;
  682. break;
  683. case ERROR_PORT_UNREACHABLE:
  684. pDatagram->Busy = 0;
  685. return RPC_P_PORT_DOWN;
  686. break;
  687. case STATUS_TIMEOUT:
  688. ASSERT(0);
  689. case ERROR_OPERATION_ABORTED:
  690. // ERROR_OPERATION_ABORTED can occur if one thread
  691. // tried to make a call and failed, leaving a pending
  692. // receive. That thread dies. Then the endpoint is
  693. // reused by a different thread and the IO is aborted.
  694. // Returning receive failed will cause the runtime to
  695. // retransmit which will do the right thing.
  696. default:
  697. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  698. DPFLTR_INFO_LEVEL,
  699. RPCTRANS "DG sync recv failed %d\n",
  700. GetLastError()));
  701. pDatagram->Busy = 0;
  702. return(RPC_P_RECEIVE_FAILED);
  703. break;
  704. }
  705. }
  706. else
  707. {
  708. status = RPC_S_OK;
  709. }
  710. }
  711. ASSERT( status == RPC_S_OK
  712. || status == RPC_P_OVERSIZE_PACKET);
  713. ASSERT(pDatagram->Busy);
  714. ASSERT(pDatagram->Packet.buf);
  715. ASSERT(bytes <= pDatagram->Packet.len);
  716. *pBuffer = (BUFFER)pDatagram->Packet.buf;
  717. *pBufferLength = bytes;
  718. *pReplyAddress = pDatagram->AddressPair->RemoteAddress;
  719. pDatagram->Packet.buf = 0;
  720. pDatagram->Busy = 0;
  721. return(status);
  722. }
  723. RPC_STATUS
  724. RPC_ENTRY
  725. DG_ReceivePacket_Avrf(
  726. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  727. OUT DG_TRANSPORT_ADDRESS *pReplyAddress,
  728. OUT PUINT pBufferLength,
  729. OUT BUFFER *pBuffer,
  730. IN LONG Timeout
  731. )
  732. /*++
  733. Routine Description:
  734. Wrapper for DG_ReceivePacket implementing corruption injection
  735. under the RPC verifier.
  736. SyncRecv member of the transport interface may only be called
  737. by the cliet, hence we inject the corruption for a client receive.
  738. Arguments:
  739. Return Value:
  740. --*/
  741. {
  742. RPC_STATUS Status;
  743. Status = DG_ReceivePacket(
  744. ThisEndpoint,
  745. pReplyAddress,
  746. pBufferLength,
  747. pBuffer,
  748. Timeout
  749. );
  750. if (!Status)
  751. {
  752. if (gfRPCVerifierEnabled)
  753. {
  754. CorruptionInject(ClientReceive,
  755. pBufferLength,
  756. (void **)pBuffer);
  757. }
  758. }
  759. return Status;
  760. }
  761. RPC_STATUS
  762. DG_CreateEndpoint(
  763. OUT WS_DATAGRAM_ENDPOINT *pEndpoint
  764. )
  765. /*++
  766. Routine Description:
  767. Creates a new endpoint.
  768. Arguments:
  769. pEndpoint - The runtime allocated endpoint structure to
  770. filled in.
  771. pSockAddr - An initialized sockaddr with the correct
  772. (or no) endpoint.
  773. id - The id of the protocol to use in creating the address.
  774. fClient - If TRUE this is a client endpoint
  775. fAsync - If TRUE this endpoint is "async" which means that
  776. a) It should be added to the IO completion port and
  777. b) that the transport should pend a number of receives
  778. on the endpoint automatically.
  779. EndpointFlags - used in allocation IP ports.
  780. Return Value:
  781. RPC_S_OK
  782. RPC_S_OUT_OF_MEMORY
  783. RPC_S_OUT_OF_RESOURCES
  784. RPC_S_CANT_CREATE_ENDPOINT
  785. RPC_S_DUPLICATE_ENDPOINT
  786. --*/
  787. {
  788. PWS_DATAGRAM pDatagram;
  789. int i, err;
  790. int length;
  791. RPC_STATUS status = RPC_S_OK;
  792. SOCKET sock = 0;
  793. PDG_TRANS_INFO pInfo = GetDgTransportInfo(pEndpoint->id);
  794. BOOL fClient = pEndpoint->fClient;
  795. BOOL fAsync = pEndpoint->fAsync;
  796. LPFN_WSARECVMSG WSARecvMsgFnPtr;
  797. DWORD dwBytesReturned;
  798. // Common stuff
  799. pEndpoint->type = DATAGRAM | ADDRESS;
  800. pEndpoint->Socket = 0;
  801. pEndpoint->Endpoint = 0;
  802. pEndpoint->pAddressVector = 0;
  803. pEndpoint->SubmitListen = DG_SubmitReceives;
  804. pEndpoint->InAddressList = NotInList;
  805. pEndpoint->pNext = 0;
  806. pEndpoint->fSubmittingIos = 0;
  807. pEndpoint->cPendingIos = 0;
  808. pEndpoint->cMinimumIos = 0;
  809. pEndpoint->cMaximumIos = 0;
  810. pEndpoint->aDatagrams = 0;
  811. pEndpoint->pFirstAddress = pEndpoint;
  812. pEndpoint->pNextAddress = 0;
  813. pEndpoint->fAborted = 0;
  814. if (fClient)
  815. {
  816. pEndpoint->type |= CLIENT;
  817. }
  818. else
  819. {
  820. pEndpoint->type |= SERVER;
  821. }
  822. //
  823. // Check if we can use a wrapper around the AFD send/recv
  824. // IOCTLs instead WSASendTo.
  825. //
  826. TryUsingAfd();
  827. //
  828. // Create the socket.
  829. //
  830. sock = WSASocketT(pInfo->AddressFamily,
  831. pInfo->SocketType,
  832. pInfo->Protocol,
  833. 0,
  834. 0,
  835. WSA_FLAG_OVERLAPPED);
  836. if (sock == INVALID_SOCKET)
  837. {
  838. RpcpErrorAddRecord( EEInfoGCWinsock,
  839. GetLastError(),
  840. EEInfoDLWinsockDatagramCreate10,
  841. (ULONG) pInfo->AddressFamily,
  842. (ULONG) pInfo->Protocol
  843. );
  844. switch(GetLastError())
  845. {
  846. case WSAEAFNOSUPPORT:
  847. case WSAEPROTONOSUPPORT:
  848. case WSAENETDOWN:
  849. case WSAEINVAL:
  850. case WSAEPROTOTYPE:
  851. case WSAENOPROTOOPT:
  852. case WSAESOCKTNOSUPPORT:
  853. case WSAEPFNOSUPPORT:
  854. case WSAEADDRNOTAVAIL:
  855. status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  856. break;
  857. case WSAENOBUFS:
  858. case WSAEMFILE:
  859. case WSA_NOT_ENOUGH_MEMORY:
  860. // This failure is possible in low memory conditions
  861. // or due to fault injection during registry read or
  862. // notification creation.
  863. case WSASYSCALLFAILURE:
  864. status = RPC_S_OUT_OF_MEMORY;
  865. break;
  866. default:
  867. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  868. DPFLTR_WARNING_LEVEL,
  869. RPCTRANS "DG socket() returned 0x%lx\n",
  870. GetLastError()));
  871. ASSERT(0);
  872. // no break
  873. case WSAEPROVIDERFAILEDINIT:
  874. status = RPC_S_OUT_OF_RESOURCES;
  875. break;
  876. }
  877. return(status);
  878. }
  879. if (fWSARecvMsgFnPtrInitialized == FALSE)
  880. {
  881. // if the AddressChangeFn is non-default (i.e. we are in RPCSS),
  882. // use WSARecvMsg so that we can retrieve the local address as
  883. // well
  884. if (AddressChangeFn && (AddressChangeFn != NullAddressChangeFn))
  885. {
  886. // retrieve the WSARecvMsg function pointer
  887. err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (void *) &WSARecvMsgFnPtrUuid,
  888. sizeof(UUID), (void *) &WSARecvMsgFnPtr, sizeof(void *), &dwBytesReturned,
  889. NULL, NULL);
  890. if (err == SOCKET_ERROR)
  891. {
  892. closesocket(sock);
  893. return RPC_S_PROTSEQ_NOT_SUPPORTED;
  894. }
  895. WFT.pWSARecvMsg = WSARecvMsgFnPtr;
  896. fWSARecvMsgFnPtrInitialized = TRUE;
  897. }
  898. }
  899. //
  900. // Make the handle non-inheritable so it goes away when we close it.
  901. //
  902. if (FALSE == SetHandleInformation( (HANDLE) sock, HANDLE_FLAG_INHERIT, 0))
  903. {
  904. closesocket(sock);
  905. return RPC_S_OUT_OF_RESOURCES;
  906. }
  907. //
  908. // Protect the socket to prevent another server from using our port.
  909. //
  910. WS_ProtectListeningSocket(sock, TRUE);
  911. //
  912. // Bind the socket to the endpoint (or to a dynamic endpoint)
  913. //
  914. status = WS_Bind(sock,
  915. &pEndpoint->ListenAddr,
  916. (pEndpoint->id == UDP),
  917. pEndpoint->EndpointFlags);
  918. if (status != RPC_S_OK)
  919. {
  920. closesocket(sock);
  921. return(status);
  922. }
  923. pEndpoint->Socket = sock;
  924. //
  925. // Turn on ring buffering for server- and client-side async endpoints.
  926. // Any error is ignored.
  927. //
  928. if (fAsync || !fClient)
  929. {
  930. DWORD BytesReturned;
  931. if (0 != WSAIoctl( sock, SIO_ENABLE_CIRCULAR_QUEUEING, 0, 0, 0, 0, &BytesReturned, 0, 0 ))
  932. {
  933. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  934. DPFLTR_WARNING_LEVEL,
  935. RPCTRANS "DG couldn't enable circular queueing 0x%lx\n",
  936. GetLastError()));
  937. }
  938. }
  939. if (!fClient)
  940. {
  941. //
  942. // Set server socket recv buffer size..
  943. //
  944. int size;
  945. int PacketInfoOn = TRUE;
  946. if (gfServerPlatform == TRUE && gPhysicalMemorySize >= 40)
  947. {
  948. size = pInfo->ServerBufferSize;
  949. }
  950. else
  951. {
  952. size = pInfo->WorkstationBufferSize;
  953. }
  954. if (fWSARecvMsgFnPtrInitialized)
  955. {
  956. err = setsockopt(sock,
  957. IPPROTO_IP,
  958. IP_PKTINFO,
  959. (char *)&PacketInfoOn,
  960. sizeof(PacketInfoOn)
  961. );
  962. if (err != 0)
  963. {
  964. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  965. DPFLTR_WARNING_LEVEL,
  966. RPCTRANS "DG couldn't set packet info %d\n",
  967. GetLastError()));
  968. closesocket(sock);
  969. return(RPC_S_OUT_OF_MEMORY);
  970. }
  971. }
  972. err = setsockopt(sock,
  973. SOL_SOCKET,
  974. SO_RCVBUF,
  975. (char *) &size,
  976. sizeof(size)
  977. );
  978. #if DBG
  979. if (err != 0)
  980. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  981. DPFLTR_WARNING_LEVEL,
  982. RPCTRANS "DG couldn't set buffer size %d\n",
  983. GetLastError()));
  984. #endif
  985. }
  986. else
  987. {
  988. // Enable broadcast send on the client
  989. DWORD option = TRUE;
  990. err = setsockopt(sock,
  991. SOL_SOCKET,
  992. SO_BROADCAST,
  993. (PCHAR)&option,
  994. sizeof(option));
  995. ASSERT(err == 0);
  996. }
  997. //
  998. // If the endpoint is going to async initialize async part
  999. // and add the socket to the IO completion port.
  1000. //
  1001. if (status == RPC_S_OK)
  1002. {
  1003. int cMaxIos;
  1004. int cMinIos;
  1005. ASSERT(fAsync || fClient);
  1006. // Step one, figure out the high and low mark for ios.
  1007. if (fAsync)
  1008. {
  1009. cMinIos = 1;
  1010. cMaxIos = 2;
  1011. if (gPhysicalMemorySize >= 40) // megabytes
  1012. {
  1013. cMaxIos = 2
  1014. + (gfServerPlatform == TRUE) * 2
  1015. + (fClient == FALSE) * gNumberOfProcessors;
  1016. // This should be larger than zero so that we'll generally submit new
  1017. // recvs during idle time rather then just after receiving a datagram.
  1018. cMinIos = 1 + (fClient == FALSE ) * (gNumberOfProcessors/2);
  1019. }
  1020. }
  1021. else
  1022. {
  1023. // For sync endpoints we need to allocate a single datagram
  1024. // object for the receive.
  1025. cMinIos = 0;
  1026. cMaxIos = 1;
  1027. }
  1028. ASSERT(cMinIos < cMaxIos);
  1029. pEndpoint->cMinimumIos = cMinIos;
  1030. pEndpoint->cMaximumIos = cMaxIos;
  1031. // Allocate a chunk on memory to hold the array of datagrams
  1032. // PERF: For clients, allocate larger array but don't submit all
  1033. // the IOs unless we determine that the port is "really" active.
  1034. pEndpoint->aDatagrams = new WS_DATAGRAM[cMaxIos];
  1035. if (pEndpoint->aDatagrams)
  1036. {
  1037. UINT type;
  1038. type = DATAGRAM | RECEIVE;
  1039. type |= (fClient) ? CLIENT : SERVER;
  1040. for (i = 0; i < cMaxIos; i++)
  1041. {
  1042. pDatagram = &pEndpoint->aDatagrams[i];
  1043. pDatagram->id = pEndpoint->id;
  1044. pDatagram->type = type;
  1045. pDatagram->pEndpoint = pEndpoint;
  1046. pDatagram->Busy = 0;
  1047. pDatagram->Packet.buf = 0;
  1048. memset(&pDatagram->Read, 0, sizeof(pDatagram->Read));
  1049. pDatagram->Read.pAsyncObject = pDatagram;
  1050. }
  1051. if (fAsync)
  1052. {
  1053. status = COMMON_PrepareNewHandle((HANDLE)sock);
  1054. }
  1055. else
  1056. {
  1057. // The receive operation on sync endpoints will may span
  1058. // several receives. This means it can't use the thread
  1059. // event, so allocate an event for the receive.
  1060. HANDLE hEvent = CreateEventW(0, TRUE, FALSE, 0);
  1061. if (!hEvent)
  1062. {
  1063. status = RPC_S_OUT_OF_RESOURCES;
  1064. }
  1065. else
  1066. {
  1067. ASSERT(pDatagram == &pEndpoint->aDatagrams[0]);
  1068. pDatagram->Read.ol.hEvent = hEvent;
  1069. }
  1070. }
  1071. }
  1072. else
  1073. {
  1074. status = RPC_S_OUT_OF_MEMORY;
  1075. }
  1076. }
  1077. // If adding a new failure case here, add code to close the sync receive event.
  1078. if (status != RPC_S_OK)
  1079. {
  1080. closesocket(sock);
  1081. delete pEndpoint->aDatagrams;
  1082. return(status);
  1083. }
  1084. TransportProtocol::AddObjectToProtocolList((BASE_ASYNC_OBJECT *) pEndpoint);
  1085. if (!fClient)
  1086. {
  1087. TransportProtocol::FunctionalProtocolDetected(pEndpoint->id);
  1088. }
  1089. return(RPC_S_OK);
  1090. }
  1091. VOID
  1092. DG_DeactivateAddress (
  1093. IN WS_DATAGRAM_ENDPOINT *pEndpoint
  1094. )
  1095. /*++
  1096. Function Name:DG_DeactivateAddress
  1097. Parameters:
  1098. Description:
  1099. Returns:
  1100. --*/
  1101. {
  1102. if (InterlockedIncrement(&pEndpoint->fAborted) != 1)
  1103. {
  1104. return;
  1105. }
  1106. if (pEndpoint->Socket)
  1107. {
  1108. closesocket(pEndpoint->Socket);
  1109. pEndpoint->Socket = 0;
  1110. }
  1111. }
  1112. RPC_STATUS
  1113. DG_ReactivateAddress (
  1114. IN WS_DATAGRAM_ENDPOINT *pEndpoint
  1115. )
  1116. /*++
  1117. Function Name:DG_DeactivateAddress
  1118. Parameters:
  1119. Description:
  1120. Returns:
  1121. --*/
  1122. {
  1123. RPC_STATUS Status;
  1124. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  1125. //
  1126. // If the endpoint is dynamic, clear out the endpoint
  1127. //
  1128. if (pEndpoint->fDynamicEndpoint)
  1129. {
  1130. //
  1131. // Clear out the listenaddr
  1132. //
  1133. switch (pEndpoint->id)
  1134. {
  1135. #ifdef IPX_ON
  1136. case IPX:
  1137. addr->ipxaddr.sa_socket = 0;
  1138. break;
  1139. #endif
  1140. case CDP:
  1141. CDP_InitLocalAddress(&addr->clusaddr, 0);
  1142. break;
  1143. case UDP:
  1144. addr->inetaddr.sin_port = 0;
  1145. break;
  1146. default:
  1147. ASSERT(0);
  1148. }
  1149. }
  1150. Status = DG_CreateEndpoint(pEndpoint);
  1151. if (Status == RPC_S_OK)
  1152. {
  1153. pEndpoint->fAborted = 0;
  1154. DG_SubmitReceives(pEndpoint);
  1155. }
  1156. return Status;
  1157. }
  1158. void RPC_ENTRY
  1159. DG_ServerAbortListen(
  1160. IN DG_TRANSPORT_ENDPOINT ThisEndpoint
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. Callback after DG_CreateEndpoint has completed successfully
  1165. but the runtime for some reason is not going to be able to
  1166. listen on the endpoint.
  1167. --*/
  1168. {
  1169. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1170. ASSERT(pEndpoint->cPendingIos == 0);
  1171. ASSERT(pEndpoint->Socket);
  1172. ASSERT(pEndpoint->pNext == 0);
  1173. ASSERT(pEndpoint->type & SERVER);
  1174. delete pEndpoint->pAddressVector;
  1175. delete pEndpoint->aDatagrams;
  1176. closesocket(pEndpoint->Socket);
  1177. return;
  1178. }
  1179. RPC_STATUS RPC_ENTRY
  1180. DG_ClientCloseEndpoint(
  1181. IN DG_TRANSPORT_ENDPOINT ThisEndpoint
  1182. )
  1183. /*++
  1184. Routine Description:
  1185. Called on sync client endpoints when they are no longer needed.
  1186. Arguments:
  1187. ThisEndpoint
  1188. Return Value:
  1189. RPC_S_OK
  1190. --*/
  1191. {
  1192. BOOL b;
  1193. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1194. PWS_DATAGRAM pDatagram = &pEndpoint->aDatagrams[0];
  1195. ASSERT((pEndpoint->type & TYPE_MASK) == CLIENT);
  1196. ASSERT(pEndpoint->Socket); // Open must have worked
  1197. ASSERT(pEndpoint->cMinimumIos == 0);
  1198. ASSERT(pEndpoint->cMaximumIos == 1); // Must not be async!
  1199. ASSERT(pEndpoint->aDatagrams);
  1200. ASSERT(pEndpoint->aDatagrams[0].Read.ol.hEvent);
  1201. ASSERT(pEndpoint->Endpoint == 0);
  1202. ASSERT(pEndpoint->pAddressVector == 0);
  1203. ASSERT(pEndpoint->pNext == 0);
  1204. // If there is a pending receive, closing the socket will cancel the IO.
  1205. closesocket(pEndpoint->Socket);
  1206. // Wait for the pending receive to actually complete.
  1207. if (pDatagram->Busy)
  1208. {
  1209. DWORD bytes;
  1210. ASSERT(pDatagram->Busy);
  1211. ASSERT(pDatagram->Packet.buf);
  1212. GetOverlappedResult((HANDLE)pEndpoint->Socket,
  1213. &pDatagram->Read.ol,
  1214. &bytes,
  1215. TRUE);
  1216. if (GetLastError() != ERROR_OPERATION_ABORTED)
  1217. {
  1218. // Overactive output, the receive may have completed normally..
  1219. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  1220. DPFLTR_WARNING_LEVEL,
  1221. RPCTRANS "DG receive completed %d on %p after closed\n",
  1222. GetLastError(),
  1223. pDatagram));
  1224. }
  1225. }
  1226. b = CloseHandle(pEndpoint->aDatagrams[0].Read.ol.hEvent);
  1227. ASSERT(b);
  1228. TransportProtocol::RemoveObjectFromProtocolList(pEndpoint);
  1229. // Free the receive buffer if allocated
  1230. if (pDatagram->Packet.buf)
  1231. {
  1232. I_RpcTransDatagramFree(pEndpoint,
  1233. (BUFFER)pDatagram->Packet.buf
  1234. );
  1235. }
  1236. delete pDatagram;
  1237. return(RPC_S_OK);
  1238. }
  1239. RPC_STATUS
  1240. RPC_ENTRY
  1241. DG_GetEndpointStats(
  1242. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1243. OUT DG_ENDPOINT_STATS * pStats
  1244. )
  1245. {
  1246. DWORD Status;
  1247. DWORD Data;
  1248. int Length;
  1249. BOOL Ok;
  1250. PWS_DATAGRAM_ENDPOINT Endpoint = (PWS_DATAGRAM_ENDPOINT) ThisEndpoint;
  1251. Length = sizeof(DWORD);
  1252. Status = getsockopt(Endpoint->Socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &Data, &Length);
  1253. if (Status)
  1254. {
  1255. return GetLastError();
  1256. }
  1257. //
  1258. // jroberts, 10-Jan-2001 : I believe that getsockopt is returning 0xffffffff occasionally.
  1259. // This is an attempt to catch it.
  1260. //
  1261. if (Endpoint->id == UDP)
  1262. {
  1263. ASSERT( Data < 0x10000 );
  1264. }
  1265. Data &= ~7UL;
  1266. pStats->MaxPduSize = Data;
  1267. Length = sizeof(DWORD);
  1268. Status = getsockopt(Endpoint->Socket, SOL_SOCKET, SO_RCVBUF, (char *) &Data, &Length);
  1269. if (Status)
  1270. {
  1271. return GetLastError();
  1272. }
  1273. Data &= ~7UL;
  1274. pStats->ReceiveBufferSize = Data;
  1275. return RPC_S_OK;
  1276. }
  1277. ////////////////////////////////////////////////////////////////////////
  1278. //
  1279. // CDP/IP specific functions.
  1280. //
  1281. RPC_STATUS RPC_ENTRY
  1282. CDP_ServerListen(
  1283. IN OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1284. IN RPC_CHAR *NetworkAddress,
  1285. IN OUT RPC_CHAR **pPort,
  1286. IN void *pSecurityDescriptor,
  1287. IN ULONG EndpointFlags,
  1288. IN ULONG NICFlags
  1289. )
  1290. /*++
  1291. Routine Description:
  1292. Creates a server endpoint object to receive packets. New
  1293. packets won't actually arrive until CompleteListen is
  1294. called.
  1295. Arguments:
  1296. ThisEndpoint - Storage for the server endpoint object.
  1297. pPort - The endpoint to listen on or a pointer to 0 if
  1298. the transport should choose the address.
  1299. Contains the endpoint listened to on output. The
  1300. caller should free this.
  1301. pSecurityDiscriptor - Security to attach to this endpoint (not
  1302. used by this transport).
  1303. EndpointFlags - Application flags passed into RPC via
  1304. RpcServerUseProtseq*Ex.
  1305. NICFlags - Application flags passed into RPC via
  1306. RpcServerUseProtseq*Ex.
  1307. pNetworkAddresses - A vector of the network addresses
  1308. listened on by this call. This vector does
  1309. not need to be freed.
  1310. Return Value:
  1311. RPC_S_OK
  1312. RPC_S_OUT_OF_MEMORY
  1313. RPC_S_OUT_OF_RESOURCES
  1314. RPC_S_CANT_CREATE_ENDPOINT
  1315. RPC_S_INVALID_ENDPOINT_FORMAT
  1316. RPC_S_DUPLICATE_ENDPOINT
  1317. --*/
  1318. {
  1319. RPC_STATUS status;
  1320. NTSTATUS NtStatus;
  1321. USHORT port;
  1322. UNICODE_STRING UnicodeString;
  1323. ANSI_STRING AsciiString;
  1324. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1325. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  1326. NETWORK_ADDRESS_VECTOR * ServerAddress;
  1327. // Figure out the port to listen on.
  1328. if (*pPort)
  1329. {
  1330. status = EndpointToPortNumber(*pPort, port);
  1331. if (status != RPC_S_OK)
  1332. {
  1333. return(status);
  1334. }
  1335. pEndpoint->fDynamicEndpoint = 0;
  1336. CDP_InitLocalAddress( &addr->clusaddr, port );
  1337. }
  1338. else
  1339. {
  1340. return RPC_S_INVALID_ENDPOINT_FORMAT;
  1341. }
  1342. pEndpoint->id = CDP;
  1343. pEndpoint->fClient = FALSE;
  1344. pEndpoint->fAsync = TRUE;
  1345. pEndpoint->EndpointFlags = 0;
  1346. //
  1347. // Actually create the endpoint
  1348. //
  1349. status = DG_CreateEndpoint(pEndpoint);
  1350. if (status != RPC_S_OK)
  1351. {
  1352. return(status);
  1353. }
  1354. // Figure out the network addresses.
  1355. // The only way we can determine our cluster
  1356. // address is to read it out of the registry
  1357. status = CDP_BuildAddressVector(&pEndpoint->pAddressVector);
  1358. if (status != RPC_S_OK)
  1359. {
  1360. DG_ServerAbortListen(ThisEndpoint);
  1361. return(status);
  1362. }
  1363. return RPC_S_OK;
  1364. }
  1365. RPC_STATUS
  1366. CDP_QueryEndpoint
  1367. (
  1368. IN void * pOriginalEndpoint,
  1369. OUT RPC_CHAR * pClientEndpoint
  1370. )
  1371. {
  1372. WS_SOCKADDR * pSockAddr = (WS_SOCKADDR *)pOriginalEndpoint;
  1373. unsigned NativeSocket = pSockAddr->clusaddr.sac_port;
  1374. char AnsiBuffer[CDP_MAXIMUM_ENDPOINT];
  1375. char * pAnsi = AnsiBuffer;
  1376. RPC_CHAR * pUni = pClientEndpoint;
  1377. //
  1378. // Convert endpoint to an ASCII string, and thence to Unicode.
  1379. //
  1380. _ultoa(NativeSocket, AnsiBuffer, 10);
  1381. while ( *pUni++ = *pAnsi++ );
  1382. return RPC_S_OK;
  1383. }
  1384. RPC_STATUS
  1385. CDP_QueryAddress
  1386. (
  1387. IN void * pOriginalEndpoint,
  1388. OUT RPC_CHAR * pClientAddress
  1389. )
  1390. {
  1391. PSOCKADDR_CLUSTER pSockAddr = (PSOCKADDR_CLUSTER) pOriginalEndpoint;
  1392. _ultow(pSockAddr->sac_node, pClientAddress, 10);
  1393. return(RPC_S_OK);
  1394. }
  1395. RPC_STATUS
  1396. RPC_ENTRY
  1397. CDP_ClientInitializeAddress
  1398. (
  1399. OUT DG_TRANSPORT_ADDRESS Address,
  1400. IN RPC_CHAR *NetworkAddress,
  1401. IN RPC_CHAR *pPort,
  1402. IN BOOL fUseCache,
  1403. IN BOOL fBroadcast
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Initializes a address object for sending to a server.
  1408. Arguments:
  1409. Address - Storage for the address
  1410. NetworkAddress - The address of the server or 0 if local
  1411. Endpoint - The endpoint of the server
  1412. fUseCache - If TRUE then the transport may use a cached
  1413. value from a previous call on the same NetworkAddress.
  1414. fBroadcast - If TRUE, NetworkAddress is ignored and a broadcast
  1415. address is used.
  1416. Return Value:
  1417. RPC_S_OK - Success, name resolved and, optionally, added to cache.
  1418. RPC_P_FOUND_IN_CACHE - Success, returned only if fUseCache is TRUE
  1419. and the was name found in local cache.
  1420. RPC_P_MATCHED_CACHE - Partial success, fUseCache is FALSE and the
  1421. result of the lookup was the same as the value previously
  1422. in the cache.
  1423. RPC_S_OUT_OF_MEMORY
  1424. RPC_S_OUT_OF_RESOURCES
  1425. RPC_S_INVALID_ENDPOINT_FORMAT
  1426. RPC_S_SERVER_UNAVAILABLE
  1427. --*/
  1428. {
  1429. WS_SOCKADDR *pAddr = (WS_SOCKADDR *)Address;
  1430. ULONG HostAddr;
  1431. ULONG Endpoint;
  1432. int i;
  1433. USHORT port;
  1434. RPC_STATUS status;
  1435. // Figure out the destination port
  1436. status = EndpointToPortNumber(pPort, port);
  1437. if (RPC_S_OK != status)
  1438. {
  1439. ASSERT( 0 );
  1440. return(status);
  1441. }
  1442. CDP_InitLocalAddress( &pAddr->clusaddr, port );
  1443. // Resolve the network address - CDP addresses are
  1444. // numbers representing a member ID in the cluster.
  1445. pAddr->clusaddr.sac_node = _wtol( NetworkAddress );
  1446. return(status);
  1447. }
  1448. RPC_STATUS
  1449. RPC_ENTRY
  1450. CDP_ClientOpenEndpoint(
  1451. OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1452. IN BOOL fAsync,
  1453. DWORD Flags,
  1454. IN DG_TRANSPORT_ENDPOINT ServerEndpoint OPTIONAL
  1455. )
  1456. {
  1457. RPC_STATUS Status;
  1458. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1459. // We don't care what port we bind to, we also don't care what
  1460. // port we bind to.
  1461. // I think he's trying to say that we don't care what port
  1462. // we bind to.
  1463. CDP_InitLocalAddress(&pEndpoint->ListenAddr.clusaddr, 0);
  1464. pEndpoint->id = CDP;
  1465. pEndpoint->fClient = TRUE;
  1466. pEndpoint->fAsync = fAsync;
  1467. pEndpoint->EndpointFlags = 0;
  1468. pEndpoint->fDynamicEndpoint = 1;
  1469. Status = DG_CreateEndpoint(pEndpoint);
  1470. return Status;
  1471. }
  1472. RPC_STATUS
  1473. CDP_InitializeSockAddr(
  1474. IN char *Endpoint,
  1475. OUT WS_SOCKADDR *pSockAddr,
  1476. DG_TRANSPORT_ENDPOINT ThisEndpoint
  1477. )
  1478. /*++
  1479. Routine Description:
  1480. Initialized the sockaddr to be a loopback address to the
  1481. endpoint specified. Used to forward packets locally.
  1482. Arguments:
  1483. Endpoint - The string value of the servers endpoint.
  1484. pSockAddr - The sockaddr to fill in.
  1485. Return Value:
  1486. RPC_S_INVALID_ENDPOINT_FORMAT
  1487. RPC_S_OK
  1488. --*/
  1489. {
  1490. long port;
  1491. port = atol(Endpoint);
  1492. if (port <= 0 || port > 0xFFFF)
  1493. {
  1494. ASSERT( 0 );
  1495. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  1496. }
  1497. CDP_InitLocalAddress(&pSockAddr->clusaddr, (unsigned short) port);
  1498. return(RPC_S_OK);
  1499. }
  1500. RPC_STATUS
  1501. RPC_ENTRY
  1502. CDP_GetEndpointStats(
  1503. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1504. OUT DG_ENDPOINT_STATS * pStats
  1505. )
  1506. {
  1507. RPC_STATUS Status;
  1508. Status = DG_GetEndpointStats(ThisEndpoint, pStats);
  1509. if (Status)
  1510. {
  1511. pStats->MaxPduSize = 1452;
  1512. pStats->MaxPacketSize = 1452;
  1513. pStats->PreferredPduSize = 1452;
  1514. pStats->ReceiveBufferSize= 8192;
  1515. return Status;
  1516. }
  1517. //
  1518. // ethernet frame (1500) - UDP/IP headers (28) - CNP/CDP headers (20)
  1519. //
  1520. pStats->MaxPacketSize = 1452;
  1521. pStats->PreferredPduSize = 4096;
  1522. if (pStats->PreferredPduSize > pStats->MaxPduSize)
  1523. {
  1524. pStats->PreferredPduSize = pStats->MaxPduSize;
  1525. }
  1526. return RPC_S_OK;
  1527. }
  1528. ////////////////////////////////////////////////////////////////////////
  1529. //
  1530. // UDP/IP specific functions.
  1531. //
  1532. RPC_STATUS RPC_ENTRY
  1533. UDP_ServerListen(
  1534. IN OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1535. IN RPC_CHAR *NetworkAddress,
  1536. IN OUT RPC_CHAR **pPort,
  1537. IN void *pSecurityDescriptor,
  1538. IN ULONG EndpointFlags,
  1539. IN ULONG NICFlags
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. Creates a server endpoint object to receive packets. New
  1544. packets won't actually arrive until CompleteListen is
  1545. called.
  1546. Arguments:
  1547. ThisEndpoint - Storage for the server endpoint object.
  1548. pPort - The endpoint to listen on or a pointer to 0 if
  1549. the transport should choose the address.
  1550. Contains the endpoint listened to on output. The
  1551. caller should free this.
  1552. pSecurityDiscriptor - Security to attach to this endpoint (not
  1553. used by UDP).
  1554. EndpointFlags - Application flags passed into RPC via
  1555. RpcServerUseProtseq*Ex.
  1556. NICFlags - Application flags passed into RPC via
  1557. RpcServerUseProtseq*Ex.
  1558. pNetworkAddresses - A vector of the network addresses
  1559. listened on by this call. This vector does
  1560. not need to be freed.
  1561. Return Value:
  1562. RPC_S_OK
  1563. RPC_S_OUT_OF_MEMORY
  1564. RPC_S_OUT_OF_RESOURCES
  1565. RPC_S_CANT_CREATE_ENDPOINT
  1566. RPC_S_INVALID_ENDPOINT_FORMAT
  1567. RPC_S_DUPLICATE_ENDPOINT
  1568. --*/
  1569. {
  1570. RPC_STATUS status;
  1571. NTSTATUS NtStatus;
  1572. USHORT port;
  1573. UNICODE_STRING UnicodeString;
  1574. ANSI_STRING AsciiString;
  1575. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1576. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  1577. addr->inetaddr.sin_family = AF_INET;
  1578. if (NetworkAddress)
  1579. {
  1580. IP_ADDRESS_RESOLVER resolver(NetworkAddress,
  1581. cosServer,
  1582. ipvtuIPv4 // IP version to use
  1583. );
  1584. // Loop until success, fatal failure or we run out of addresses.
  1585. status = resolver.NextAddress(&addr->inetaddr);
  1586. if (status != RPC_S_OK)
  1587. {
  1588. return RPC_S_INVALID_NET_ADDR;
  1589. }
  1590. }
  1591. else
  1592. {
  1593. addr->inetaddr.sin_addr.s_addr = INADDR_ANY;
  1594. }
  1595. // Figure out the port to listen on.
  1596. if (*pPort)
  1597. {
  1598. status = EndpointToPortNumber(*pPort, port);
  1599. if (status != RPC_S_OK)
  1600. {
  1601. return(status);
  1602. }
  1603. pEndpoint->fDynamicEndpoint = 0;
  1604. addr->inetaddr.sin_port = htons(port);
  1605. }
  1606. else
  1607. {
  1608. addr->inetaddr.sin_port = 0;
  1609. pEndpoint->fDynamicEndpoint = 1;
  1610. }
  1611. pEndpoint->id = UDP;
  1612. pEndpoint->fClient = FALSE;
  1613. pEndpoint->fAsync = TRUE;
  1614. pEndpoint->EndpointFlags = EndpointFlags;
  1615. //
  1616. // Actually create the endpoint
  1617. //
  1618. status = DG_CreateEndpoint(pEndpoint);
  1619. if (status != RPC_S_OK)
  1620. {
  1621. return(status);
  1622. }
  1623. // If needed, return the endpoint.
  1624. if (!*pPort)
  1625. {
  1626. *pPort = new RPC_CHAR[IP_MAXIMUM_ENDPOINT];
  1627. if (!*pPort)
  1628. {
  1629. DG_ServerAbortListen(ThisEndpoint);
  1630. return(RPC_S_OUT_OF_MEMORY);
  1631. }
  1632. port = ntohs(addr->inetaddr.sin_port);
  1633. PortNumberToEndpoint(port, *pPort);
  1634. }
  1635. // Figure out the network addresses
  1636. ASSERT(pEndpoint->pAddressVector == NULL);
  1637. status = IP_BuildAddressVector(&pEndpoint->pAddressVector,
  1638. NICFlags,
  1639. NetworkAddress,
  1640. NULL);
  1641. if (status != RPC_S_OK)
  1642. {
  1643. DG_ServerAbortListen(ThisEndpoint);
  1644. return(status);
  1645. }
  1646. return RPC_S_OK;
  1647. }
  1648. RPC_STATUS
  1649. UDP_QueryEndpoint
  1650. (
  1651. IN void * pOriginalEndpoint,
  1652. OUT RPC_CHAR * pClientEndpoint
  1653. )
  1654. {
  1655. WS_SOCKADDR * pSockAddr = (WS_SOCKADDR *)pOriginalEndpoint;
  1656. unsigned NativeSocket = ntohs(pSockAddr->inetaddr.sin_port);
  1657. char AnsiBuffer[IP_MAXIMUM_ENDPOINT];
  1658. char * pAnsi = AnsiBuffer;
  1659. RPC_CHAR * pUni = pClientEndpoint;
  1660. //
  1661. // Convert endpoint to an ASCII string, and thence to Unicode.
  1662. //
  1663. _ultoa(NativeSocket, AnsiBuffer, 10);
  1664. while ( *pUni++ = *pAnsi++ );
  1665. return RPC_S_OK;
  1666. }
  1667. RPC_STATUS
  1668. UDP_QueryAddress
  1669. (
  1670. IN void * pOriginalEndpoint,
  1671. OUT RPC_CHAR * pClientAddress
  1672. )
  1673. {
  1674. UNICODE_STRING UnicodeString;
  1675. ANSI_STRING AsciiString;
  1676. WS_SOCKADDR *pSockAddr = (WS_SOCKADDR *)pOriginalEndpoint;
  1677. NTSTATUS NtStatus;
  1678. UnicodeString.Buffer = pClientAddress;
  1679. UnicodeString.Length = 0;
  1680. UnicodeString.MaximumLength = IP_MAXIMUM_RAW_NAME * sizeof(RPC_CHAR);
  1681. char *t = inet_ntoa(pSockAddr->inetaddr.sin_addr);
  1682. ASSERT(t);
  1683. RtlInitAnsiString(&AsciiString, t);
  1684. ASSERT(AsciiString.Length < IP_MAXIMUM_RAW_NAME);
  1685. NtStatus = RtlAnsiStringToUnicodeString(&UnicodeString,
  1686. &AsciiString,
  1687. FALSE);
  1688. if (!NT_SUCCESS(NtStatus))
  1689. {
  1690. ASSERT(0);
  1691. return(RPC_S_OUT_OF_RESOURCES);
  1692. }
  1693. return(RPC_S_OK);
  1694. }
  1695. RPC_STATUS
  1696. RPC_ENTRY
  1697. UDP_ClientInitializeAddress
  1698. (
  1699. OUT DG_TRANSPORT_ADDRESS Address,
  1700. IN RPC_CHAR *NetworkAddress,
  1701. IN RPC_CHAR *pPort,
  1702. IN BOOL fUseCache,
  1703. IN BOOL fBroadcast
  1704. )
  1705. /*++
  1706. Routine Description:
  1707. Initializes a address object for sending to a server.
  1708. Arguments:
  1709. Address - Storage for the address
  1710. NetworkAddress - The address of the server or 0 if local
  1711. Endpoint - The endpoint of the server
  1712. fUseCache - If TRUE then the transport may use a cached
  1713. value from a previous call on the same NetworkAddress.
  1714. fBroadcast - If TRUE, NetworkAddress is ignored and a broadcast
  1715. address is used.
  1716. Return Value:
  1717. RPC_S_OK - Success, name resolved and, optionally, added to cache.
  1718. RPC_P_FOUND_IN_CACHE - Success, returned only if fUseCache is TRUE
  1719. and the was name found in local cache.
  1720. RPC_P_MATCHED_CACHE - Partial success, fUseCache is FALSE and the
  1721. result of the lookup was the same as the value previously
  1722. in the cache.
  1723. RPC_S_OUT_OF_MEMORY
  1724. RPC_S_OUT_OF_RESOURCES
  1725. RPC_S_INVALID_ENDPOINT_FORMAT
  1726. RPC_S_SERVER_UNAVAILABLE
  1727. --*/
  1728. {
  1729. WS_SOCKADDR *pAddr = (WS_SOCKADDR *)Address;
  1730. ULONG HostAddr;
  1731. ULONG Endpoint;
  1732. int i;
  1733. USHORT port;
  1734. RPC_STATUS status;
  1735. // Contant part of address
  1736. memset(pAddr->inetaddr.sin_zero, 0, 8);
  1737. pAddr->inetaddr.sin_family = AF_INET;
  1738. // Figure out the destination port
  1739. status = EndpointToPortNumber(pPort, port);
  1740. if (RPC_S_OK != status)
  1741. {
  1742. return(status);
  1743. }
  1744. pAddr->inetaddr.sin_port = htons(port);
  1745. // Resolve the network address
  1746. if (fBroadcast)
  1747. {
  1748. pAddr->inetaddr.sin_addr.s_addr = INADDR_BROADCAST;
  1749. return(RPC_S_OK);
  1750. }
  1751. // Multiple server address support for UDP/IP is not available.
  1752. IP_ADDRESS_RESOLVER resolver(NetworkAddress,
  1753. cosClient,
  1754. ipvtuIPv4 // IP version to use
  1755. );
  1756. status = resolver.NextAddress(&pAddr->inetaddr);
  1757. if (status)
  1758. {
  1759. RpcpErrorAddRecord( EEInfoGCWinsock,
  1760. status,
  1761. EEInfoDLWinsockDatagramResolve10,
  1762. NetworkAddress
  1763. );
  1764. }
  1765. return(status);
  1766. }
  1767. RPC_STATUS
  1768. RPC_ENTRY
  1769. UDP_ClientOpenEndpoint(
  1770. OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1771. IN BOOL fAsync,
  1772. DWORD EndpointFlags,
  1773. IN DG_TRANSPORT_ENDPOINT ServerEndpoint OPTIONAL
  1774. )
  1775. {
  1776. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1777. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  1778. //
  1779. // We don't care what port we bind to.
  1780. // Ordinarily, we don't care what interface we bind to. When using selective
  1781. // bindings and making a callback, we should bind to the same IP address that
  1782. // was the original target of the call. This will come from the server endpoint.
  1783. //
  1784. memset(addr, 0, sizeof(*addr));
  1785. // ServerEndpoint is provided only when processing a callback with selective bindings.
  1786. if (ServerEndpoint != NULL)
  1787. {
  1788. memcpy(&(addr->inetaddr.sin_addr), &(((PWS_DATAGRAM_ENDPOINT)ServerEndpoint)->ListenAddr.inetaddr.sin_addr), sizeof(addr->inetaddr.sin_addr));
  1789. }
  1790. addr->inetaddr.sin_family = AF_INET;
  1791. pEndpoint->id = UDP;
  1792. pEndpoint->fClient = TRUE;
  1793. pEndpoint->fAsync = fAsync;
  1794. pEndpoint->EndpointFlags = EndpointFlags;
  1795. pEndpoint->fDynamicEndpoint = 1;
  1796. return(DG_CreateEndpoint(pEndpoint));
  1797. }
  1798. RPC_STATUS
  1799. UDP_InitializeSockAddr(
  1800. IN char *Endpoint,
  1801. OUT WS_SOCKADDR *pSockAddr,
  1802. DG_TRANSPORT_ENDPOINT ThisEndpoint
  1803. )
  1804. /*++
  1805. Routine Description:
  1806. Initialized the sockaddr to be a loopback address to the
  1807. endpoint specified or the address from ThisEndpoint to the
  1808. endpoint specified. Used to forward packets locally.
  1809. ThisEndpoint will be provided when running with selective bindings
  1810. to make sure that the packet is forwarded to the same interface
  1811. on which the endpoint mapper received it, to ensure that the reply
  1812. can reach the client.
  1813. Arguments:
  1814. Endpoint - The string value of the servers endpoint.
  1815. pSockAddr - The sockaddr to fill in.
  1816. Return Value:
  1817. RPC_S_INVALID_ENDPOINT_FORMAT
  1818. RPC_S_OK
  1819. --*/
  1820. {
  1821. int len;
  1822. long port;
  1823. pSockAddr->generic.sa_family = AF_INET;
  1824. if (ThisEndpoint == NULL)
  1825. {
  1826. pSockAddr->inetaddr.sin_addr.s_addr = 0x0100007F; // byte swapped, 127.0.0.1
  1827. }
  1828. else
  1829. {
  1830. memcpy(&(pSockAddr->inetaddr.sin_addr.s_addr), &(((WS_DATAGRAM_ENDPOINT *)ThisEndpoint)->ListenAddr.inetaddr.sin_addr), sizeof(in_addr));
  1831. }
  1832. port = atol(Endpoint);
  1833. if (port <= 0 || port > 0xFFFF)
  1834. {
  1835. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  1836. }
  1837. pSockAddr->inetaddr.sin_port = htons((USHORT) port);
  1838. return(RPC_S_OK);
  1839. }
  1840. RPC_STATUS
  1841. RPC_ENTRY
  1842. UDP_GetEndpointStats(
  1843. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1844. OUT DG_ENDPOINT_STATS * pStats
  1845. )
  1846. {
  1847. RPC_STATUS Status;
  1848. Status = DG_GetEndpointStats(ThisEndpoint, pStats);
  1849. if (Status)
  1850. {
  1851. pStats->MaxPduSize = 1472;
  1852. pStats->MaxPacketSize = 1472;
  1853. pStats->PreferredPduSize = 1472;
  1854. pStats->ReceiveBufferSize= 8192;
  1855. return Status;
  1856. }
  1857. pStats->MaxPacketSize = 1472;
  1858. pStats->PreferredPduSize = 4096;
  1859. if (pStats->PreferredPduSize > pStats->MaxPduSize)
  1860. {
  1861. pStats->PreferredPduSize = pStats->MaxPduSize;
  1862. }
  1863. return RPC_S_OK;
  1864. }
  1865. #ifdef IPX_ON
  1866. ////////////////////////////////////////////////////////////////////////
  1867. //
  1868. // IPX specific functions.
  1869. //
  1870. RPC_STATUS RPC_ENTRY
  1871. IPX_ServerListen(
  1872. IN OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  1873. IN RPC_CHAR *NetworkAddress,
  1874. IN OUT RPC_CHAR **pPort,
  1875. IN void *pSecurityDescriptor,
  1876. IN ULONG EndpointFlags,
  1877. IN ULONG NICFlags
  1878. )
  1879. /*++
  1880. Routine Description:
  1881. Creates a server endpoint object to receive packets. New
  1882. packets won't actually arrive until CompleteListen is
  1883. called.
  1884. Arguments:
  1885. ThisEndpoint - Storage for the server endpoint object.
  1886. pPort - The endpoint to listen on or a pointer to 0 if
  1887. the transport should choose the address.
  1888. Contains the endpoint listened to on output. The
  1889. caller should free this.
  1890. pSecurityDiscriptor - Security to attach to this endpoint (not
  1891. used by the IPX transport).
  1892. EndpointFlags - Application flags passed into RPC via
  1893. RpcServerUseProtseq*Ex.
  1894. NICFlags - Application flags passed into RPC via
  1895. RpcServerUseProtseq*Ex.
  1896. pNetworkAddresses - A vector of the network addresses
  1897. listened on by this call. This vector does
  1898. not need to be freed.
  1899. Return Value:
  1900. RPC_S_OK
  1901. RPC_S_OUT_OF_MEMORY
  1902. RPC_S_OUT_OF_RESOURCES
  1903. RPC_S_CANT_CREATE_ENDPOINT
  1904. RPC_S_INVALID_ENDPOINT_FORMAT
  1905. RPC_S_DUPLICATE_ENDPOINT
  1906. --*/
  1907. {
  1908. RPC_STATUS status;
  1909. NTSTATUS NtStatus;
  1910. USHORT port;
  1911. UNICODE_STRING UnicodeString;
  1912. ANSI_STRING AsciiString;
  1913. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  1914. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  1915. //
  1916. // Figure out what port to listen on.
  1917. //
  1918. if (*pPort)
  1919. {
  1920. status = EndpointToPortNumber(*pPort, port);
  1921. if (status != RPC_S_OK)
  1922. {
  1923. return(status);
  1924. }
  1925. pEndpoint->fDynamicEndpoint = 0;
  1926. }
  1927. else
  1928. {
  1929. port = 0;
  1930. pEndpoint->fDynamicEndpoint = 1;
  1931. }
  1932. addr->generic.sa_family = AF_IPX;
  1933. addr->ipxaddr.sa_socket = htons(port);
  1934. pEndpoint->id = IPX;
  1935. pEndpoint->fClient = FALSE;
  1936. pEndpoint->fAsync = TRUE;
  1937. pEndpoint->EndpointFlags = 0;
  1938. //
  1939. // Actually create the endpoint
  1940. //
  1941. status =
  1942. DG_CreateEndpoint(pEndpoint);
  1943. if (status != RPC_S_OK)
  1944. {
  1945. return(status);
  1946. }
  1947. // If needed, figure out the dynamically allocated endpoint.
  1948. if (!*pPort)
  1949. {
  1950. *pPort = new RPC_CHAR[IP_MAXIMUM_ENDPOINT];
  1951. if (!*pPort)
  1952. {
  1953. DG_ServerAbortListen(ThisEndpoint);
  1954. return(RPC_S_OUT_OF_MEMORY);
  1955. }
  1956. port = ntohs(addr->ipxaddr.sa_socket);
  1957. PortNumberToEndpoint(port, *pPort);
  1958. }
  1959. // Update the local address cache
  1960. //
  1961. // Since there is only one addess no lock is required.
  1962. //
  1963. memcpy(IpxAddr.sa_netnum, addr->ipxaddr.sa_netnum, sizeof(IpxAddr.sa_netnum));
  1964. memcpy(IpxAddr.sa_nodenum, addr->ipxaddr.sa_nodenum, sizeof(IpxAddr.sa_nodenum));
  1965. fIpxAddrValid = TRUE;
  1966. //
  1967. // Figure out our server's raw IPX address.
  1968. //
  1969. status = IPX_BuildAddressVector(&(pEndpoint->pAddressVector));
  1970. if (status != RPC_S_OK)
  1971. {
  1972. DG_ServerAbortListen(ThisEndpoint);
  1973. delete *pPort;
  1974. return(status);
  1975. }
  1976. return RPC_S_OK;
  1977. }
  1978. RPC_STATUS
  1979. IPX_QueryEndpoint
  1980. (
  1981. IN void * pOriginalEndpoint,
  1982. OUT RPC_CHAR * pClientEndpoint
  1983. )
  1984. {
  1985. WS_SOCKADDR * pSockAddr = (WS_SOCKADDR *)pOriginalEndpoint;
  1986. unsigned NativeSocket = ntohs(pSockAddr->ipxaddr.sa_socket);
  1987. char AnsiBuffer[IPX_MAXIMUM_ENDPOINT];
  1988. char * pAnsi = AnsiBuffer;
  1989. RPC_CHAR * pUni = pClientEndpoint;
  1990. //
  1991. // Convert endpoint to an ASCII string, and thence to Unicode.
  1992. //
  1993. _ultoa(NativeSocket, AnsiBuffer, 10);
  1994. while ( *pUni++ = *pAnsi++ );
  1995. return RPC_S_OK;
  1996. }
  1997. RPC_STATUS
  1998. IPX_QueryAddress
  1999. (
  2000. IN void * pOriginalEndpoint,
  2001. OUT RPC_CHAR * pString
  2002. )
  2003. {
  2004. WS_SOCKADDR *pSockAddr = (WS_SOCKADDR *) pOriginalEndpoint;
  2005. IPX_AddressToName(&pSockAddr->ipxaddr, pString);
  2006. return RPC_S_OK;
  2007. }
  2008. RPC_STATUS
  2009. RPC_ENTRY
  2010. IPX_ClientInitializeAddress
  2011. (
  2012. OUT DG_TRANSPORT_ADDRESS Address,
  2013. IN RPC_CHAR *NetworkAddress,
  2014. IN RPC_CHAR *pPort,
  2015. IN BOOL fUseCache,
  2016. IN BOOL fBroadcast
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. Initializes a address object for sending to a server.
  2021. Arguments:
  2022. Address - Storage for the address
  2023. NetworkAddress - The address of the server or 0 if local
  2024. pPort - The endpoint of the server
  2025. fUseCache - If TRUE then the transport may use a cached
  2026. value from a previous call on the same NetworkAddress.
  2027. fBroadcast - If TRUE, NetworkAddress is ignored and a broadcast
  2028. address is used.
  2029. Return Value:
  2030. RPC_S_OK - Success, name resolved and, optionally, added to cache.
  2031. RPC_P_FOUND_IN_CACHE - Success, returned only if fUseCache is TRUE
  2032. and the was name found in local cache.
  2033. RPC_P_MATCHED_CACHE - Partial success, fUseCache is FALSE and the
  2034. result of the lookup was the same as the value previously
  2035. in the cache.
  2036. RPC_S_OUT_OF_MEMORY
  2037. RPC_S_OUT_OF_RESOURCES
  2038. RPC_S_INVALID_ENDPOINT_FORMAT
  2039. RPC_S_SERVER_UNAVAILABLE
  2040. --*/
  2041. {
  2042. WS_SOCKADDR *pAddr = (WS_SOCKADDR *)Address;
  2043. RPC_STATUS status = RPC_S_OK;
  2044. USHORT port = 0;
  2045. pAddr->ipxaddr.sa_family = AF_IPX;
  2046. pAddr->ipxaddr.sa_socket = 0;
  2047. // Convert unicode endpoint to port number
  2048. status = EndpointToPortNumber(pPort, port);
  2049. if (status != RPC_S_OK)
  2050. {
  2051. return(status);
  2052. }
  2053. //
  2054. // Convert unicode network address to ipx address
  2055. //
  2056. if (FALSE == fBroadcast)
  2057. {
  2058. status = IPX_NameToAddress(NetworkAddress,
  2059. fUseCache,
  2060. &pAddr->ipxaddr
  2061. );
  2062. }
  2063. else
  2064. {
  2065. memset(pAddr->ipxaddr.sa_netnum, 0, sizeof(pAddr->ipxaddr.sa_netnum));
  2066. memset(pAddr->ipxaddr.sa_nodenum, 0xFF, sizeof(pAddr->ipxaddr.sa_nodenum));
  2067. }
  2068. pAddr->ipxaddr.sa_socket = htons(port);
  2069. return(status);
  2070. }
  2071. RPC_STATUS
  2072. RPC_ENTRY
  2073. IPX_ClientOpenEndpoint(
  2074. OUT DG_TRANSPORT_ENDPOINT ThisEndpoint,
  2075. IN BOOL fAsync,
  2076. DWORD Flags
  2077. )
  2078. {
  2079. RPC_STATUS status;
  2080. PWS_DATAGRAM_ENDPOINT pEndpoint = (PWS_DATAGRAM_ENDPOINT)ThisEndpoint;
  2081. WS_SOCKADDR *addr = &pEndpoint->ListenAddr;
  2082. // We don't care what port we bind to, we also don't care what
  2083. // port we bind to.
  2084. memset(addr, 0, sizeof(*addr));
  2085. addr->ipxaddr.sa_family = AF_IPX;
  2086. pEndpoint->id = IPX;
  2087. pEndpoint->fClient = TRUE ;
  2088. pEndpoint->fAsync = fAsync;
  2089. pEndpoint->EndpointFlags = 0;
  2090. pEndpoint->fDynamicEndpoint = 1;
  2091. status = DG_CreateEndpoint(pEndpoint);
  2092. if (status == RPC_S_OK)
  2093. {
  2094. // Update cache
  2095. memcpy(IpxAddr.sa_netnum, addr->ipxaddr.sa_netnum, sizeof(IpxAddr.sa_netnum));
  2096. memcpy(IpxAddr.sa_nodenum, addr->ipxaddr.sa_nodenum, sizeof(IpxAddr.sa_nodenum));
  2097. fIpxAddrValid = TRUE;
  2098. }
  2099. return(status);
  2100. }
  2101. RPC_STATUS
  2102. IPX_InitializeSockAddr(
  2103. IN char *Endpoint,
  2104. OUT WS_SOCKADDR *pSockAddr
  2105. )
  2106. /*++
  2107. Routine Description:
  2108. Initialized the sockaddr to be a loopback address to the
  2109. endpoint specified. Used to forward packets locally.
  2110. Arguments:
  2111. Endpoint - The string value of the servers endpoint.
  2112. pSockAddr - The sockaddr to fill in.
  2113. Return Value:
  2114. RPC_S_INVALID_ENDPOINT_FORMAT
  2115. RPC_S_OK
  2116. --*/
  2117. {
  2118. int len;
  2119. long port;
  2120. pSockAddr->generic.sa_family = AF_IPX;
  2121. port = atol(Endpoint);
  2122. if (port <= 0 || port > 0xFFFF)
  2123. {
  2124. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  2125. }
  2126. pSockAddr->ipxaddr.sa_socket = htons((USHORT)port);
  2127. //
  2128. // In order to get this far this server must have
  2129. // alrady listened to IPX.
  2130. //
  2131. ASSERT(fIpxAddrValid);
  2132. memcpy(pSockAddr->ipxaddr.sa_netnum, IpxAddr.sa_netnum, sizeof(pSockAddr->ipxaddr.sa_netnum));
  2133. memcpy(pSockAddr->ipxaddr.sa_nodenum, IpxAddr.sa_nodenum, sizeof(pSockAddr->ipxaddr.sa_nodenum));
  2134. return(RPC_S_OK);
  2135. }
  2136. RPC_STATUS
  2137. RPC_ENTRY
  2138. IPX_GetEndpointStats(
  2139. IN DG_TRANSPORT_ENDPOINT ThisEndpoint,
  2140. OUT DG_ENDPOINT_STATS * pStats
  2141. )
  2142. {
  2143. RPC_STATUS Status;
  2144. Status = DG_GetEndpointStats(ThisEndpoint, pStats);
  2145. if (Status)
  2146. {
  2147. pStats->MaxPduSize = 1478;
  2148. pStats->MaxPacketSize = 1478;
  2149. pStats->PreferredPduSize = 1478;
  2150. pStats->ReceiveBufferSize= 8192;
  2151. return Status;
  2152. }
  2153. pStats->MaxPacketSize = 1478;
  2154. pStats->PreferredPduSize = pStats->MaxPduSize;
  2155. pStats->MaxPacketSize = pStats->MaxPduSize;
  2156. return RPC_S_OK;
  2157. }
  2158. #endif
  2159. ////////////////////////////////////////////////////////////////////////
  2160. //
  2161. // Transport interface structures and loader
  2162. //
  2163. const RPC_DATAGRAM_TRANSPORT
  2164. UDP_TransportInterface = {
  2165. RPC_TRANSPORT_INTERFACE_VERSION,
  2166. UDP_TOWER_ID,
  2167. IP_ADDRESS_ID,
  2168. RPC_STRING_LITERAL("ncadg_ip_udp"),
  2169. "135",
  2170. COMMON_ProcessCalls,
  2171. COMMON_StartPnpNotifications,
  2172. COMMON_ListenForPNPNotifications,
  2173. COMMON_TowerConstruct,
  2174. COMMON_TowerExplode,
  2175. COMMON_PostRuntimeEvent,
  2176. TRUE,
  2177. DG_GetNetworkAddressVector,
  2178. sizeof(WS_DATAGRAM_ENDPOINT),
  2179. sizeof(WS_DATAGRAM_ENDPOINT),
  2180. sizeof(WS_SOCKADDR),
  2181. IP_MAXIMUM_ENDPOINT,
  2182. IP_MAXIMUM_PRETTY_NAME,
  2183. 1024,
  2184. 1472,
  2185. DG_SendPacket,
  2186. UDP_ClientOpenEndpoint,
  2187. UDP_ClientInitializeAddress,
  2188. DG_ClientCloseEndpoint,
  2189. DG_ReceivePacket,
  2190. UDP_ServerListen,
  2191. DG_ServerAbortListen,
  2192. COMMON_ServerCompleteListen,
  2193. DG_ForwardPacket,
  2194. UDP_QueryAddress,
  2195. UDP_QueryEndpoint,
  2196. UDP_GetEndpointStats,
  2197. FALSE, // fIsMessageTransport (TRUE/FALSE).
  2198. 0, // OptionSize
  2199. 0, // InitOptions()
  2200. 0, // SetOption()
  2201. 0, // InqOption()
  2202. 0, // ImplementOptions()
  2203. 0, // AllowReceives()
  2204. 0 // InquireAuthClient()
  2205. };
  2206. // When the RPC verifier is enabled and we are corrupting client receives,
  2207. // we will use a modified transport interface given below. It will have the sync
  2208. // receive members overwritten.
  2209. RPC_DATAGRAM_TRANSPORT *pUDP_TransportInterface_Avrf = NULL;
  2210. const RPC_DATAGRAM_TRANSPORT
  2211. CDP_TransportInterface = {
  2212. RPC_TRANSPORT_INTERFACE_VERSION,
  2213. CDP_TOWER_ID,
  2214. IP_ADDRESS_ID,
  2215. RPC_STRING_LITERAL("ncadg_cluster"),
  2216. NULL,
  2217. COMMON_ProcessCalls,
  2218. COMMON_StartPnpNotifications,
  2219. COMMON_ListenForPNPNotifications,
  2220. COMMON_TowerConstruct,
  2221. COMMON_TowerExplode,
  2222. COMMON_PostRuntimeEvent,
  2223. TRUE,
  2224. DG_GetNetworkAddressVector,
  2225. sizeof(WS_DATAGRAM_ENDPOINT),
  2226. sizeof(WS_DATAGRAM_ENDPOINT),
  2227. sizeof(WS_SOCKADDR),
  2228. IP_MAXIMUM_ENDPOINT,
  2229. IP_MAXIMUM_PRETTY_NAME,
  2230. 1024,
  2231. 1452,
  2232. DG_SendPacket,
  2233. CDP_ClientOpenEndpoint,
  2234. CDP_ClientInitializeAddress,
  2235. DG_ClientCloseEndpoint,
  2236. DG_ReceivePacket,
  2237. CDP_ServerListen,
  2238. DG_ServerAbortListen,
  2239. COMMON_ServerCompleteListen,
  2240. DG_ForwardPacket,
  2241. CDP_QueryAddress,
  2242. CDP_QueryEndpoint,
  2243. CDP_GetEndpointStats,
  2244. FALSE, // fIsMessageTransport (TRUE/FALSE).
  2245. 0, // OptionSize
  2246. 0, // InitOptions()
  2247. 0, // SetOption()
  2248. 0, // InqOption()
  2249. 0, // ImplementOptions()
  2250. 0, // AllowReceives()
  2251. 0 // InquireAuthClient()
  2252. };
  2253. RPC_DATAGRAM_TRANSPORT *pCDP_TransportInterface_Avrf = NULL;
  2254. #ifdef IPX_ON
  2255. const RPC_DATAGRAM_TRANSPORT
  2256. IPX_TransportInterface = {
  2257. RPC_TRANSPORT_INTERFACE_VERSION,
  2258. IPX_TOWER_ID,
  2259. IPX_ADDRESS_ID,
  2260. RPC_STRING_LITERAL("ncadg_ipx"),
  2261. "34280",
  2262. COMMON_ProcessCalls,
  2263. COMMON_StartPnpNotifications,
  2264. COMMON_ListenForPNPNotifications,
  2265. COMMON_TowerConstruct,
  2266. COMMON_TowerExplode,
  2267. COMMON_PostRuntimeEvent,
  2268. TRUE,
  2269. DG_GetNetworkAddressVector,
  2270. sizeof(WS_DATAGRAM_ENDPOINT),
  2271. sizeof(WS_DATAGRAM_ENDPOINT),
  2272. sizeof(WS_SOCKADDR),
  2273. IPX_MAXIMUM_ENDPOINT,
  2274. IPX_MAXIMUM_PRETTY_NAME,
  2275. 1024,
  2276. 1464,
  2277. DG_SendPacket,
  2278. IPX_ClientOpenEndpoint,
  2279. IPX_ClientInitializeAddress,
  2280. DG_ClientCloseEndpoint,
  2281. DG_ReceivePacket,
  2282. IPX_ServerListen,
  2283. DG_ServerAbortListen,
  2284. COMMON_ServerCompleteListen,
  2285. DG_ForwardPacket,
  2286. IPX_QueryAddress,
  2287. IPX_QueryEndpoint,
  2288. IPX_GetEndpointStats,
  2289. FALSE, // fIsMessageTransport (TRUE/FALSE).
  2290. 0, // OptionSize
  2291. 0, // InitOptions()
  2292. 0, // SetOption()
  2293. 0, // InqOption()
  2294. 0, // ImplementOptions()
  2295. 0, // AllowReceives()
  2296. 0 // InquireAuthClient()
  2297. };
  2298. #endif
  2299. #ifdef NCADG_MQ_ON
  2300. const RPC_DATAGRAM_TRANSPORT
  2301. MQ_TransportInterface = {
  2302. RPC_TRANSPORT_INTERFACE_VERSION,
  2303. MQ_TOWER_ID,
  2304. MQ_ADDRESS_ID,
  2305. RPC_STRING_LITERAL("ncadg_mq"),
  2306. "EpMapper",
  2307. COMMON_ProcessCalls,
  2308. COMMON_StartPnpNotifications,
  2309. COMMON_ListenForPNPNotifications,
  2310. COMMON_TowerConstruct,
  2311. COMMON_TowerExplode,
  2312. COMMON_PostRuntimeEvent,
  2313. TRUE,
  2314. MQ_GetNetworkAddressVector, // Since MQ is being depricated, this is not defined.
  2315. sizeof(MQ_DATAGRAM_ENDPOINT),
  2316. sizeof(MQ_DATAGRAM_ENDPOINT),
  2317. sizeof(MQ_ADDRESS),
  2318. MQ_MAXIMUM_ENDPOINT,
  2319. MQ_MAXIMUM_PRETTY_NAME,
  2320. MQ_MAX_PDU_SIZE,
  2321. MQ_PREFERRED_PDU_SIZE,
  2322. MQ_SendPacket,
  2323. MQ_ClientOpenEndpoint,
  2324. MQ_ClientInitializeAddress,
  2325. MQ_ClientCloseEndpoint,
  2326. MQ_ReceivePacket,
  2327. MQ_ServerListen,
  2328. MQ_ServerAbortListen,
  2329. COMMON_ServerCompleteListen,
  2330. MQ_ForwardPacket,
  2331. MQ_QueryAddress,
  2332. MQ_QueryEndpoint,
  2333. MQ_GetEndpointStats,
  2334. TRUE, // fIsMessageTransport (TRUE/FALSE).
  2335. sizeof(MQ_OPTIONS), // OptionSize
  2336. MQ_InitOptions, // InitOptions()
  2337. MQ_SetOption, // SetOption()
  2338. MQ_InqOption, // InqOption()
  2339. MQ_ImplementOptions, // ImplementOptions()
  2340. MQ_AllowReceives, // AllowReceives()
  2341. MQ_InquireAuthClient
  2342. };
  2343. #endif // NCADG_MQ_ON
  2344. const RPC_DATAGRAM_TRANSPORT *
  2345. DG_TransportLoad (
  2346. IN PROTOCOL_ID index
  2347. )
  2348. /*++
  2349. Routine Description:
  2350. Loads a datagram protocol and returns the transport interface
  2351. information for the protocol.
  2352. Arguments:
  2353. index - the PROTOCOL_ID value of the protocol to load.
  2354. Return Value:
  2355. 0 - failure
  2356. !0 - success
  2357. --*/
  2358. {
  2359. const RPC_DATAGRAM_TRANSPORT *pInfo;
  2360. if (fWinsockLoaded == FALSE)
  2361. {
  2362. if (RPC_WSAStartup() == FALSE)
  2363. {
  2364. return(0);
  2365. }
  2366. fWinsockLoaded = TRUE;
  2367. }
  2368. switch(index)
  2369. {
  2370. case UDP:
  2371. if (DoFirewallInit())
  2372. {
  2373. // Overwrite the SyncReceive member of the transport interface if the
  2374. // RPC verifier is enabled.
  2375. if (gfRpcVerifierCorruptionInjectClientReceives)
  2376. {
  2377. // Check if we have previously initialized the Avrf transport interface.
  2378. if (pUDP_TransportInterface_Avrf == NULL)
  2379. {
  2380. // Allocate a transport interface structure to override the default.
  2381. pUDP_TransportInterface_Avrf = new (RPC_DATAGRAM_TRANSPORT);
  2382. if (pUDP_TransportInterface_Avrf == NULL)
  2383. {
  2384. return NULL;
  2385. }
  2386. // Initialize the Avrf transport interface with the default values.
  2387. RpcpMemoryCopy(pUDP_TransportInterface_Avrf,
  2388. &UDP_TransportInterface,
  2389. sizeof(RPC_DATAGRAM_TRANSPORT));
  2390. // Override the interface function for sync receive.
  2391. ASSERT(pUDP_TransportInterface_Avrf->SyncReceive == DG_ReceivePacket);
  2392. pUDP_TransportInterface_Avrf->SyncReceive = DG_ReceivePacket_Avrf;
  2393. }
  2394. pInfo = pUDP_TransportInterface_Avrf;
  2395. }
  2396. else
  2397. {
  2398. pInfo = &UDP_TransportInterface;
  2399. }
  2400. break;
  2401. }
  2402. #ifdef IPX_ON
  2403. case IPX:
  2404. if (InitializeIpxNameCache() != RPC_S_OK)
  2405. {
  2406. pInfo = 0;
  2407. }
  2408. else
  2409. {
  2410. pInfo = &IPX_TransportInterface;
  2411. }
  2412. break;
  2413. #endif
  2414. #ifdef NCADG_MQ_ON
  2415. case MSMQ:
  2416. if (!MQ_Initialize())
  2417. {
  2418. return(0);
  2419. }
  2420. else
  2421. {
  2422. pInfo = &MQ_TransportInterface;
  2423. }
  2424. break;
  2425. #endif // NCADG_MQ_ON
  2426. case CDP:
  2427. // Overwrite the SyncReceive member of the transport interface if the
  2428. // RPC verifier is enabled.
  2429. if (gfRpcVerifierCorruptionInjectClientReceives)
  2430. {
  2431. // Check if we have previously initialized the Avrf transport interface.
  2432. if (pCDP_TransportInterface_Avrf == NULL)
  2433. {
  2434. // Allocate a transport interface structure to override the default.
  2435. pCDP_TransportInterface_Avrf = new (RPC_DATAGRAM_TRANSPORT);
  2436. if (pCDP_TransportInterface_Avrf == NULL)
  2437. {
  2438. return NULL;
  2439. }
  2440. // Initialize the Avrf transport interface with the default values.
  2441. RpcpMemoryCopy(pCDP_TransportInterface_Avrf,
  2442. &CDP_TransportInterface,
  2443. sizeof(RPC_DATAGRAM_TRANSPORT));
  2444. // Override the interface function for sync receive.
  2445. ASSERT(pCDP_TransportInterface_Avrf->SyncReceive == DG_ReceivePacket);
  2446. pCDP_TransportInterface_Avrf->SyncReceive = DG_ReceivePacket_Avrf;
  2447. }
  2448. pInfo = pCDP_TransportInterface_Avrf;
  2449. }
  2450. else
  2451. {
  2452. pInfo = &CDP_TransportInterface;
  2453. }
  2454. break;
  2455. default:
  2456. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  2457. DPFLTR_WARNING_LEVEL,
  2458. RPCTRANS "DG_TransportLoad called with index: %d\n",
  2459. index));
  2460. ASSERT(0);
  2461. pInfo = 0;
  2462. break;
  2463. }
  2464. // PERFBUG: Add code to lookup real PDU sizes
  2465. return(pInfo);
  2466. }