Windows NT 4.0 source code leak
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.

879 lines
18 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. winsock.c
  5. Abstract:
  6. Common code for winsock-based datagram transports.
  7. Author:
  8. Dave Steckler (davidst) 15-Mar-1993
  9. Revision History:
  10. Jeff Roberts (jroberts) 02-Dec-1994
  11. Separated the protocol-independent parts from the UDP- and
  12. IPX-specific parts.
  13. --*/
  14. #include <stdlib.h>
  15. #include <sysinc.h>
  16. #include <rpc.h>
  17. #include <rpcdcep.h>
  18. #include <rpcerrp.h>
  19. #include <rpctran.h>
  20. #include <winsock.h>
  21. #define MAX_PACKET_SIZE (1024)
  22. struct ENDPOINT_INFO
  23. {
  24. SOCKET Socket;
  25. unsigned Timeout;
  26. };
  27. //
  28. // The protocol-specific file should define these fns.
  29. //
  30. RPC_STATUS RPC_ENTRY
  31. RegisterEndpoint(
  32. IN void * pServerAddress,
  33. IN RPC_CHAR * pEndpoint,
  34. OUT PDG_SERVER_TRANS_ADDRESS * ppTransAddress,
  35. OUT RPC_CHAR PAPI * NetworkAddress,
  36. IN unsigned int NetworkAddressLength //CLH 9/19/93
  37. );
  38. RPC_STATUS RPC_ENTRY
  39. DeregisterEndpoint(
  40. IN OUT PDG_SERVER_TRANS_ADDRESS * pServerTransAddress
  41. );
  42. int
  43. SetTransportSpecificSocketOptions(
  44. SOCKET Socket
  45. );
  46. RPC_STATUS
  47. QueryClientEndpoint
  48. (
  49. IN void * pClientEndpoint,
  50. OUT RPC_CHAR * pClientAddress
  51. );
  52. RPC_STATUS
  53. CreateServerEndpoint(
  54. IN char * pEndpoint,
  55. IN void * pServerAddr
  56. );
  57. //
  58. // The protocol-specific file can use these fns.
  59. //
  60. RPC_STATUS
  61. MapStatusCode(
  62. int SocketError,
  63. RPC_STATUS Default
  64. );
  65. PDG_SERVER_TRANS_ADDRESS
  66. CreateTransAddress(
  67. void * pServerAddress,
  68. RPC_CHAR * pEndpoint,
  69. RPC_STATUS * pStatus
  70. );
  71. void DeleteTransAddress(
  72. PDG_SERVER_TRANS_ADDRESS * ppTransAddress
  73. );
  74. #if defined(IPX)
  75. #include <wsipx.h>
  76. #include <wsnwlink.h>
  77. #include <nspapi.h>
  78. #include "dgipxs.h"
  79. #include "dgipxs.c"
  80. #elif defined(UDP)
  81. #include "dgudps.h"
  82. #include "dgudps.c"
  83. #else
  84. #error "unknown winsock protocol"
  85. #endif
  86. RPC_STATUS RPC_ENTRY
  87. TransportUnload()
  88. /*++
  89. Routine Description:
  90. Destructor for the server transport.
  91. Arguments:
  92. <none>
  93. Return Value:
  94. <none>
  95. --*/
  96. {
  97. (void)WSACleanup();
  98. return RPC_S_OK;
  99. }
  100. RPC_STATUS RPC_ENTRY
  101. ReceivePacket(
  102. IN void *Address,
  103. IN PDG_SERVER_TRANS_ADDRESS pTransAddress,
  104. IN unsigned long LargestPacketSize,
  105. IN char * pNcaPacketHeader,
  106. IN unsigned * pDataLength,
  107. unsigned long Timeout,
  108. void * pClientEndpoint
  109. )
  110. /*++
  111. Routine Description:
  112. Receives a packet from the transport address the passed packet is
  113. associated with.
  114. Arguments:
  115. pTransAddress - Server's transport address information.
  116. LargestPacketSize - Size of largest packet we can accept.
  117. pNcaPacketHeader - Pointer to buffer to place incoming pkt into.
  118. pDataLength - Number of bytes read in.
  119. Timeout - Receive timeout in milliseconds.
  120. ppClientEndpoint - Pointer to the client address structure.
  121. Return Value:
  122. result of recv
  123. Revision History:
  124. --*/
  125. {
  126. unsigned SocketError;
  127. int BytesReceived;
  128. int FromLen=sizeof(struct sockaddr);
  129. struct ENDPOINT_INFO * pInfo = (struct ENDPOINT_INFO *) pTransAddress->pTsap;
  130. ADDRESS_TYPE * pSockaddr = (ADDRESS_TYPE *) pClientEndpoint;
  131. if (Timeout != pInfo->Timeout)
  132. {
  133. pInfo->Timeout = Timeout;
  134. setsockopt(pInfo->Socket,
  135. SOL_SOCKET,
  136. SO_RCVTIMEO,
  137. (char *) &Timeout,
  138. sizeof(Timeout)
  139. );
  140. //
  141. // If we can't set the timeout, too bad. We will carry on anyway.
  142. //
  143. }
  144. //
  145. // Receive something on our socket.
  146. //
  147. BytesReceived = recvfrom(
  148. pInfo->Socket, // socket
  149. (char *)pNcaPacketHeader, // buffer
  150. (int)LargestPacketSize, // buflen
  151. 0, // flags
  152. (struct sockaddr *) pSockaddr, // where received from
  153. &FromLen // received from length
  154. );
  155. //
  156. // Did we get something?
  157. //
  158. if ((BytesReceived == SOCKET_ERROR) || (BytesReceived == 0))
  159. {
  160. return MapStatusCode(WSAGetLastError(), RPC_P_RECEIVE_FAILED);
  161. }
  162. else
  163. {
  164. *pDataLength = BytesReceived;
  165. return RPC_S_OK;
  166. }
  167. }
  168. RPC_STATUS RPC_ENTRY
  169. RegisterAnyEndpoint(
  170. IN void * pServerAddress,
  171. OUT RPC_CHAR * pEndpointName,
  172. OUT PDG_SERVER_TRANS_ADDRESS * ppServerTransAddress,
  173. OUT RPC_CHAR PAPI * NetworkAddress,
  174. IN unsigned int NetworkAddressLength, // CLH 9/19/93
  175. IN unsigned int EndpointLength // CLH 9/19/93
  176. )
  177. /*++
  178. Routine Description:
  179. Figures out a unique endpoint and creates it.
  180. Arguments:
  181. pServerAddress - pointer to the DG_ADDRESS object we are associated with.
  182. (see comments in RegisterEndpoint about why this is 'void *')
  183. pEndpointName - Memory of at least MAX_ANY_ENDPOINT_NAME RPC_CHARS
  184. in length. This will be filled in with the endpoint.
  185. ppServerAddress - Where to place the newly created address.
  186. NetworkAddress - Network address in string format - ie "11.2.39.56"
  187. Return Value:
  188. RPC_S_OK
  189. <any error from RegisterEndpoint>
  190. Revision History:
  191. Connie Hoppe (CLH) (connieh) 8-Aug-93 Return Network Address
  192. Connie Hoppe (CLH) (connieh) 17-Sep-93 Return err if addr len too small
  193. Added NetworkAddresLength and
  194. Endpointlength to i/f
  195. 15-Feb-94 Fixed to ask for an assigned endpoint
  196. --*/
  197. {
  198. RPC_STATUS Status;
  199. int i = 0;
  200. if ( NetworkAddressLength < (2 * (NETADDR_LEN + 1)) )
  201. return( RPC_P_NETWORK_ADDRESS_TOO_SMALL );
  202. pEndpointName[0] = (RPC_CHAR)(i+'0');
  203. pEndpointName[1] = '\0';
  204. Status = RegisterEndpoint(
  205. pServerAddress,
  206. pEndpointName,
  207. ppServerTransAddress,
  208. NetworkAddress, //CLH 8/8/93
  209. NetworkAddressLength //CLH 9/17/93
  210. );
  211. return Status;
  212. }
  213. RPC_STATUS RPC_ENTRY
  214. SendPacketBack(
  215. IN PDG_SERVER_TRANS_ADDRESS pTransAddress,
  216. IN char * pNcaPacketHeader,
  217. IN unsigned DataLength,
  218. void * pClientEndpoint
  219. )
  220. /*++
  221. Routine Description:
  222. Sends a packet back to the client it was received from.
  223. Arguments:
  224. pTransAddress - Server's transport address information.
  225. pNcaPacketHeader - Pointer to buffer to place incoming pkt into.
  226. pDataLength - Number of bytes read in.
  227. pClientEndpoint - Pointer to the client address structure in
  228. sockaddr format.
  229. Return Value:
  230. result of send
  231. --*/
  232. {
  233. PDG_SERVER_TRANS_ADDRESS pTransportAddress =
  234. (PDG_SERVER_TRANS_ADDRESS) pTransAddress;
  235. unsigned BytesSent;
  236. struct ENDPOINT_INFO *pInfo = (struct ENDPOINT_INFO *) pTransAddress->pTsap;
  237. ADDRESS_TYPE * pSockaddr = (ADDRESS_TYPE *) pClientEndpoint;
  238. BytesSent = sendto(
  239. pInfo->Socket, // socket
  240. pNcaPacketHeader, // buffer
  241. DataLength, // buflen
  242. 0, // flags
  243. (struct sockaddr *) pSockaddr, // address
  244. sizeof(ADDRESS_TYPE) // svr addr size
  245. );
  246. if (BytesSent == DataLength)
  247. {
  248. return RPC_S_OK;
  249. }
  250. else
  251. {
  252. return MapStatusCode(WSAGetLastError(), RPC_P_SEND_FAILED);
  253. }
  254. }
  255. RPC_STATUS RPC_ENTRY
  256. ForwardPacket(
  257. IN PDG_SERVER_TRANS_ADDRESS pTransAddress,
  258. IN char * pNcaPacketHeader,
  259. IN unsigned long DataLength,
  260. void * pEndpoint
  261. )
  262. /*++
  263. Routine Description:
  264. Sends a packet to the server it was originally destined for (that
  265. is, the client had a dynamic endpoint it wished the enpoint mapper
  266. to resolve and forward the packet to).
  267. Arguments:
  268. pTransAddress - Server's transport address information.
  269. pNcaPacketHeader - Pointer to buffer to place incoming pkt into.
  270. pDataLength - Number of bytes read in.
  271. pEndpoint - Pointer to the server port num to forward to.
  272. This is in string format.
  273. Return Value:
  274. result of send
  275. Revision History:
  276. Connie Hoppe (CLH) (connieh) 17-Feb-94 Created.
  277. --*/
  278. {
  279. // If a transport had specific needs placed into the
  280. // transport address, it would cast pTransAddress into
  281. // its own trans address datastructure. UDP has
  282. // no additional info.
  283. PDG_SERVER_TRANS_ADDRESS pTransportAddress =
  284. (PDG_SERVER_TRANS_ADDRESS) pTransAddress;
  285. unsigned BytesSent;
  286. struct ENDPOINT_INFO * pInfo = (struct ENDPOINT_INFO *) pTransAddress->pTsap;
  287. ADDRESS_TYPE SockAddr;
  288. //Create an endpoint from the enpoint string name.
  289. if ((CreateServerEndpoint(((char*) pEndpoint), &SockAddr)) != RPC_S_OK)
  290. {
  291. return RPC_S_CANT_CREATE_ENDPOINT;
  292. }
  293. BytesSent = sendto(
  294. pInfo->Socket, // socket
  295. pNcaPacketHeader, // buffer
  296. DataLength, // buflen
  297. 0, // flags
  298. (struct sockaddr *) &SockAddr, // address
  299. sizeof(ADDRESS_TYPE) // svr addr size
  300. );
  301. if (BytesSent == DataLength)
  302. {
  303. return RPC_S_OK;
  304. }
  305. else
  306. {
  307. return MapStatusCode(WSAGetLastError(), RPC_P_SEND_FAILED);
  308. }
  309. }
  310. void RPC_ENTRY
  311. CloseClientEndpoint(
  312. IN OUT ADDRESS_TYPE * pHandle
  313. )
  314. /*++
  315. Routine Description:
  316. Deletes a "client handle"
  317. Arguments:
  318. The handle.
  319. Return Value:
  320. <none>
  321. --*/
  322. {
  323. // nothing to do here on IPX or UDP.
  324. }
  325. PDG_SERVER_TRANS_ADDRESS
  326. CreateTransAddress(
  327. void * pServerAddress,
  328. RPC_CHAR * pEndpoint,
  329. RPC_STATUS * pStatus
  330. )
  331. /*++
  332. Routine Description:
  333. Creates a new endpoint on this server.
  334. Arguments:
  335. pServerAddress - DG_ADDRESS object this endpoint is associated with. This
  336. is a 'void *' instead of a PDG_ADDRESS because we don't want to include
  337. or link in all the garbage associated with PDG_ADDRESS.
  338. pEndpoint - Name of the endpoint to create.
  339. pStatus - Where to place the output status.
  340. RPC_S_OK
  341. RPC_S_INVALID_ENDPOINT_FORMAT
  342. Return Value:
  343. <none>
  344. Revision History:
  345. Connie Hoppe (CLH) (connieh) 15-Feb-94 Fixed to return Endpoint.
  346. --*/
  347. {
  348. long Endpoint;
  349. int EndpointLength;
  350. int i;
  351. int SockStatus;
  352. int Socket;
  353. int PacketType;
  354. PDG_SERVER_TRANS_ADDRESS pTransAddress;
  355. int length;
  356. SOCKET PortUsed;
  357. char PortAscii[10];
  358. UNICODE_STRING UnicodePortNum;
  359. ANSI_STRING AsciiPortNum;
  360. ADDRESS_TYPE ReceiveAddr;
  361. struct ENDPOINT_INFO * pInfo;
  362. int NewSize = 0x40000;
  363. //
  364. // Convert the endpoint to a number.
  365. //
  366. EndpointLength = RpcpStringLength(pEndpoint);
  367. for (i=0, Endpoint=0 ; i< EndpointLength ; i++)
  368. {
  369. if ( ((char)pEndpoint[i] >= '0') && ((char)pEndpoint[i] <= '9'))
  370. {
  371. Endpoint *= 10;
  372. Endpoint += (char)pEndpoint[i]-'0';
  373. // Watch out for overflow.
  374. if (Endpoint > 0x10000)
  375. {
  376. *pStatus = RPC_S_INVALID_ENDPOINT_FORMAT;
  377. return NULL;
  378. }
  379. }
  380. else
  381. {
  382. *pStatus = RPC_S_INVALID_ENDPOINT_FORMAT;
  383. return NULL;
  384. }
  385. }
  386. //
  387. // Create a socket.
  388. //
  389. Socket = socket(ADDRESS_FAMILY, SOCK_DGRAM, PROTOCOL);
  390. if (Socket == INVALID_SOCKET)
  391. {
  392. *pStatus = RPC_S_CANT_CREATE_ENDPOINT;
  393. return NULL;
  394. }
  395. //
  396. // Set transport-variable options.
  397. //
  398. SockStatus = SetTransportSpecificSocketOptions(Socket);
  399. if (NO_ERROR != SockStatus)
  400. {
  401. closesocket(Socket);
  402. *pStatus = MapStatusCode(SockStatus, RPC_S_INTERNAL_ERROR);
  403. return NULL;
  404. }
  405. //
  406. // set socket recv buffer size..
  407. //
  408. SockStatus = setsockopt(Socket,
  409. SOL_SOCKET,
  410. SO_RCVBUF,
  411. (char *) &NewSize,
  412. sizeof(NewSize)
  413. );
  414. //
  415. // Create a binding to that socket.
  416. //
  417. InitLocalAddress(ReceiveAddr, (unsigned short) Endpoint);
  418. //Bind the socket to the port number.
  419. SockStatus = bind(
  420. Socket,
  421. (struct sockaddr *)&ReceiveAddr,
  422. sizeof(ReceiveAddr)
  423. );
  424. if (SockStatus == SOCKET_ERROR)
  425. {
  426. SockStatus = WSAGetLastError();
  427. switch (SockStatus)
  428. {
  429. case WSAEADDRINUSE:
  430. {
  431. *pStatus= RPC_S_DUPLICATE_ENDPOINT;
  432. break;
  433. }
  434. case WSAENOBUFS:
  435. {
  436. *pStatus= RPC_S_OUT_OF_MEMORY;
  437. break;
  438. }
  439. default:
  440. {
  441. #ifdef DEBUGRPC
  442. DbgPrint("RPC DG: surprising error 0x%lx (%lu) from bind()\n",
  443. SockStatus, SockStatus);
  444. #endif
  445. *pStatus= RPC_S_CANT_CREATE_ENDPOINT;
  446. }
  447. }
  448. closesocket(Socket);
  449. return NULL;
  450. }
  451. length = sizeof ( ReceiveAddr );
  452. //Puts the string name of the endpoint used into ReceiveAddr.sin_port
  453. if (getsockname ( Socket, (struct sockaddr *) &ReceiveAddr, &length ))
  454. {
  455. *pStatus = RPC_S_CANT_CREATE_ENDPOINT;
  456. closesocket(Socket);
  457. return(NULL);
  458. }
  459. //
  460. // If we asked for a specific port(endpoint != 0), return it
  461. // Otherwise, fetch the assigned port number (asssigned during the bind)
  462. // and stuff it into the given endpoint structure in appropriate format.
  463. if (Endpoint == 0)
  464. {
  465. PortUsed = GetSocket(ReceiveAddr);
  466. _itoa ( PortUsed, PortAscii, 10 );
  467. RtlInitAnsiString ( &AsciiPortNum, PortAscii);
  468. RtlAnsiStringToUnicodeString( &UnicodePortNum, &AsciiPortNum, TRUE );
  469. memcpy ( pEndpoint, UnicodePortNum.Buffer,
  470. UnicodePortNum.Length + sizeof(UNICODE_NULL) );
  471. RtlFreeUnicodeString ( &UnicodePortNum );
  472. }
  473. // Allocate mem for the TransAddress
  474. pTransAddress = I_RpcAllocate(sizeof(DG_SERVER_TRANS_ADDRESS) +
  475. sizeof(struct ENDPOINT_INFO));
  476. if (pTransAddress == 0)
  477. {
  478. *pStatus = RPC_S_OUT_OF_MEMORY;
  479. closesocket(Socket);
  480. return NULL;
  481. }
  482. pTransAddress->pServerAddress = pServerAddress;
  483. pInfo = (struct ENDPOINT_INFO *) &pTransAddress[1];
  484. pInfo->Socket = Socket;
  485. pInfo->Timeout = INFINITE;
  486. pTransAddress->pTsap = pInfo;
  487. *pStatus = RPC_S_OK;
  488. return pTransAddress;
  489. }
  490. void
  491. DeleteTransAddress(
  492. PDG_SERVER_TRANS_ADDRESS * ppTransAddress
  493. )
  494. /*++
  495. Routine Description:
  496. Destroys an endpoint.
  497. Arguments:
  498. <none>
  499. Return Value:
  500. <none> RRR
  501. --*/
  502. {
  503. struct ENDPOINT_INFO * pInfo = (struct ENDPOINT_INFO *) (*ppTransAddress)->pTsap;
  504. if (pInfo->Socket != INVALID_SOCKET)
  505. {
  506. closesocket(pInfo->Socket);
  507. pInfo->Socket = INVALID_SOCKET;
  508. pInfo->Timeout = INFINITE;
  509. }
  510. }
  511. RPC_STATUS RPC_ENTRY
  512. StartListening(
  513. IN PDG_SERVER_TRANS_ADDRESS pTransAddress
  514. )
  515. {
  516. return RPC_S_OK;
  517. }
  518. RPC_STATUS RPC_ENTRY
  519. SetBufferLength(
  520. IN void PAPI * Endpoint,
  521. IN unsigned Length
  522. )
  523. {
  524. struct ENDPOINT_INFO * pInfo = (struct ENDPOINT_INFO *) Endpoint;
  525. int SockStatus;
  526. SockStatus = setsockopt(pInfo->Socket,
  527. SOL_SOCKET,
  528. SO_RCVBUF,
  529. (char *) &Length,
  530. sizeof(Length)
  531. );
  532. if (SockStatus == SOCKET_ERROR)
  533. {
  534. return RPC_S_OUT_OF_MEMORY;
  535. }
  536. return RPC_S_OK;
  537. }
  538. DG_RPC_SERVER_TRANSPORT_INFO TransportInformation = {
  539. RPC_TRANSPORT_INTERFACE_VERSION,
  540. MAX_PACKET_SIZE,
  541. sizeof(ADDRESS_TYPE),
  542. sizeof(SOCKET),
  543. ADDRESS_STRING_SIZE,
  544. ENDPOINT_STRING_SIZE,
  545. TransportUnload,
  546. ReceivePacket,
  547. RegisterEndpoint,
  548. DeregisterEndpoint,
  549. RegisterAnyEndpoint,
  550. SendPacketBack,
  551. ForwardPacket,
  552. CloseClientEndpoint,
  553. QueryClientAddress,
  554. QueryClientEndpoint,
  555. StartListening,
  556. SetBufferLength
  557. };
  558. PDG_RPC_SERVER_TRANSPORT_INFO
  559. TransportLoad(
  560. RPC_CHAR * pProtocolSequence
  561. )
  562. /*++
  563. Routine Description:
  564. This routine is the "psuedo constructor" for the server transport object.
  565. This is the exported entry point into this dll.
  566. Arguments:
  567. pProtocolSequence - The protocol sequence we're running on.
  568. Return Value:
  569. Pointer to a DG_UDP_SERVER_TRANSPORT if successful, otherwise NULL.
  570. --*/
  571. {
  572. WSADATA Data;
  573. RPC_STATUS Status = 0;
  574. //
  575. // Initialize Winsock.
  576. //
  577. Status = WSAStartup(
  578. 0x0101, // version required
  579. &Data
  580. );
  581. if (Status != 0)
  582. {
  583. return 0;
  584. }
  585. return(&TransportInformation);
  586. }
  587. RPC_STATUS
  588. MapStatusCode(
  589. int SocketError,
  590. RPC_STATUS Default
  591. )
  592. /*++
  593. Routine Description:
  594. Maps a winsock return value into a RPC_STATUS.
  595. Arguments:
  596. ErrorCode - Input error code.
  597. Return Value:
  598. mapped status code
  599. --*/
  600. {
  601. RPC_STATUS Status;
  602. switch (SocketError)
  603. {
  604. case 0:
  605. {
  606. Status = RPC_S_OK;
  607. break;
  608. }
  609. case WSAETIMEDOUT:
  610. {
  611. Status = RPC_P_TIMEOUT;
  612. break;
  613. }
  614. case WSAENOBUFS:
  615. {
  616. Status = RPC_S_OUT_OF_MEMORY;
  617. break;
  618. }
  619. case WSAEMSGSIZE:
  620. {
  621. Status = RPC_P_OVERSIZE_PACKET;
  622. break;
  623. }
  624. default:
  625. {
  626. #ifdef DEBUGRPC
  627. PrintToDebugger("RPC DG: Winsock error %d\n", SocketError);
  628. #endif
  629. Status = Default;
  630. }
  631. }
  632. return Status;
  633. }