Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

738 lines
17 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Tower.cxx
  5. Abstract:
  6. Common code from building and exploding towers. Each
  7. protocol supported by the transport interface needs
  8. a section in this file.
  9. Author:
  10. Mario Goertzel [MarioGo]
  11. Revision History:
  12. MarioGo 11/11/1996 Bits 'n pieces
  13. --*/
  14. #include <precomp.hxx>
  15. #ifndef UNALIGNED
  16. #error UNALIGNED macro undefined
  17. #endif
  18. // Tower structures are totally packed
  19. #include <pshpack1.h>
  20. // CODE REVIEW: cleanup mtrt tower stuff and have only one copy of these.
  21. typedef struct _FLOOR_0OR1 {
  22. unsigned short ProtocolIdByteCount;
  23. byte FloorId;
  24. UUID Uuid;
  25. unsigned short MajorVersion;
  26. unsigned short AddressByteCount;
  27. unsigned short MinorVersion;
  28. } FLOOR_0OR1;
  29. typedef FLOOR_0OR1 UNALIGNED * PFLOOR_0OR1;
  30. typedef struct _FLOOR_234 {
  31. unsigned short ProtocolIdByteCount;
  32. byte FloorId;
  33. unsigned short AddressByteCount;
  34. byte Data[2];
  35. } FLOOR_234;
  36. typedef FLOOR_234 UNALIGNED * PFLOOR_234;
  37. typedef struct _FLOOR_2 {
  38. unsigned short ProtocolIdByteCount;
  39. byte RpcProtocol;
  40. unsigned short AddressByteCount;
  41. unsigned short RpcProtocolMinor;
  42. } FLOOR_2;
  43. typedef FLOOR_2 UNALIGNED * PFLOOR_2;
  44. typedef struct _FLOOR_3 {
  45. unsigned short ProtocolIdByteCount;
  46. byte PortType;
  47. unsigned short AddressByteCount;
  48. char EndPoint[2];
  49. } FLOOR_3;
  50. typedef FLOOR_3 UNALIGNED * PFLOOR_3;
  51. typedef struct _FLOOR_4 {
  52. unsigned short ProtocolIdByteCount;
  53. byte HostType;
  54. unsigned short AddressByteCount;
  55. char Host[2];
  56. } FLOOR_4;
  57. typedef FLOOR_4 UNALIGNED * PFLOOR_4;
  58. typedef struct _GENERIC_ID {
  59. UUID Uuid;
  60. unsigned short MajorVersion;
  61. unsigned short MinorVersion;
  62. } GENERIC_ID;
  63. typedef GENERIC_ID UNALIGNED * PGENERIC_ID;
  64. #include <poppack.h>
  65. // Restore normal packing
  66. // Transport protocols defined in cotrans.hxx and dgtrans.hxx
  67. // Given a FLOOR type and a pointer computes a pointer to the next floor.
  68. #define NEXTFLOOR(t,x) (t)((byte *)x + ((t)x)->ProtocolIdByteCount \
  69. + ((t)x)->AddressByteCount \
  70. + sizeof(((t)x)->ProtocolIdByteCount)\
  71. + sizeof(((t)x)->AddressByteCount))
  72. RPC_STATUS
  73. RPC_ENTRY
  74. COMMON_TowerConstruct(
  75. IN PCHAR Protseq,
  76. IN PCHAR NetworkAddress,
  77. IN PCHAR Endpoint,
  78. OUT PUSHORT Floors,
  79. OUT PULONG ByteCount,
  80. OUT PUCHAR *Tower
  81. )
  82. /*++
  83. Routine Description:
  84. Constructs a OSF tower for the protocol, network address and endpoint.
  85. Arguments:
  86. Protseq - The protocol for the tower.
  87. NetworkAddress - The network address to be encoded in the tower.
  88. Endpoint - The endpoint to be encoded in the tower.
  89. Floors - The number of twoer floors it encoded into the tower.
  90. ByteCount - The size of the "upper-transport-specific" tower that
  91. is encoded by this call.
  92. Tower - The encoded "upper tower" that is encoded by this call.
  93. This caller is responsible for freeing this memory.
  94. Return Value:
  95. RPC_S_OK
  96. RPC_S_OUT_OF_MEMORY
  97. RPC_S_OUT_OF_RESOURCES
  98. RPC_S_INVALID_RPC_PROTSEQ
  99. --*/
  100. {
  101. PFLOOR_234 Floor;
  102. ADDRINFO *AddrInfo;
  103. ADDRINFO Hint;
  104. INT index = MapProtseq(Protseq);
  105. if (index == 0)
  106. {
  107. return(RPC_S_INVALID_RPC_PROTSEQ);
  108. }
  109. RPC_TRANSPORT_INTERFACE pInfo = TransportTable[index].pInfo;
  110. ASSERT(pInfo);
  111. if (Endpoint == NULL || *Endpoint == '\0')
  112. {
  113. Endpoint = pInfo->WellKnownEndpoint;
  114. }
  115. // Currently all protocols have 5 floors. If a new protocol
  116. // is added with < 5 floors watch out in tower explode.
  117. *Floors = 5;
  118. // Figure out the size of the tower
  119. size_t addr_size;
  120. size_t ept_size;
  121. size_t size;
  122. // Figure out the endpoint size
  123. switch (index)
  124. {
  125. // Protocols which use port numbers (ushorts) as endpoints
  126. case TCP:
  127. #ifdef SPX_ON
  128. case SPX:
  129. #endif
  130. case HTTP:
  131. case UDP:
  132. #ifdef IPX_ON
  133. case IPX:
  134. #endif
  135. ept_size = 2;
  136. break;
  137. // Protocols which use strings as endpoints
  138. case NMP:
  139. #ifdef NETBIOS_ON
  140. case NBF:
  141. case NBT:
  142. case NBI:
  143. #endif
  144. #ifdef NCADG_MQ_ON
  145. case MSMQ:
  146. #endif
  147. #ifdef APPLETALK_ON
  148. case DSP:
  149. #endif
  150. {
  151. ASSERT(Endpoint && *Endpoint);
  152. ept_size = strlen(Endpoint) + 1;
  153. break;
  154. }
  155. #if DBG
  156. default:
  157. ASSERT(0);
  158. return(RPC_S_INTERNAL_ERROR);
  159. #endif
  160. }
  161. // Figure out the address size
  162. switch(index)
  163. {
  164. // Protocols which use 4 bytes longs as the address size
  165. case TCP:
  166. case UDP:
  167. case HTTP:
  168. {
  169. addr_size = 4;
  170. break;
  171. }
  172. #ifndef SPX_IPX_OFF
  173. // Protocols which use 10 byte (32+48 bit) address size
  174. #ifdef SPX_ON
  175. case SPX:
  176. #endif
  177. #ifdef IPX_ON
  178. case IPX:
  179. #endif
  180. {
  181. addr_size = 10;
  182. break;
  183. }
  184. #endif
  185. // Protocols which use the string as the address
  186. case NMP:
  187. #ifdef NETBIOS_ON
  188. case NBF:
  189. case NBT:
  190. case NBI:
  191. #endif
  192. #ifdef NCADG_MQ_ON
  193. case MSMQ:
  194. #endif
  195. #ifdef APPLETALK_ON
  196. case DSP:
  197. #endif
  198. {
  199. if ((NetworkAddress == NULL) || (*NetworkAddress== '\0'))
  200. {
  201. addr_size = 2;
  202. }
  203. else
  204. {
  205. addr_size = strlen(NetworkAddress) + 1;
  206. }
  207. break;
  208. }
  209. #if DBG
  210. default:
  211. ASSERT(0);
  212. return(RPC_S_INTERNAL_ERROR);
  213. #endif
  214. }
  215. // Compute total size.
  216. // Note: FLOOR_234 already contains 2 bytes of data.
  217. size = addr_size + ept_size + 2*(sizeof(FLOOR_234) - 2);
  218. // Allocate tower
  219. *Tower = new UCHAR[size];
  220. if (!*Tower)
  221. {
  222. return(RPC_S_OUT_OF_MEMORY);
  223. }
  224. *ByteCount = size;
  225. // Now fill-in the endpoint part of the tower
  226. Floor = (PFLOOR_234)*Tower;
  227. Floor->ProtocolIdByteCount = 1;
  228. Floor->FloorId = (UCHAR)pInfo->TransId;
  229. switch(index)
  230. {
  231. // Protocols which use big endian ushorts
  232. case TCP:
  233. case HTTP:
  234. #ifdef SPX_ON
  235. case SPX:
  236. #endif
  237. case UDP:
  238. #ifdef IPX_ON
  239. case IPX:
  240. #endif
  241. {
  242. Floor->AddressByteCount = 2;
  243. USHORT port = (USHORT) atoi(Endpoint);
  244. port = htons(port);
  245. memcpy((char PAPI *)&Floor->Data[0], &port, 2);
  246. break;
  247. }
  248. // Protocols which use ansi strings
  249. case NMP:
  250. #ifdef NETBIOS_ON
  251. case NBT:
  252. case NBF:
  253. case NBI:
  254. #endif
  255. #ifdef NCADG_MQ_ON
  256. case MSMQ:
  257. #endif
  258. #ifdef APPLETALK_ON
  259. case DSP:
  260. #endif
  261. {
  262. Floor->AddressByteCount = (unsigned short) ept_size;
  263. memcpy(&Floor->Data[0], Endpoint, ept_size);
  264. break;
  265. }
  266. #if DBG
  267. default:
  268. ASSERT(0);
  269. #endif
  270. }
  271. // Move to the next tower and fill-in the address part of the tower
  272. Floor = NEXTFLOOR(PFLOOR_234, Floor);
  273. Floor->ProtocolIdByteCount = 1;
  274. Floor->FloorId = (unsigned char) pInfo->TransAddrId;
  275. switch (index)
  276. {
  277. // IP protocols use 4 byte big endian IP addreses
  278. case TCP:
  279. case HTTP:
  280. case UDP:
  281. {
  282. int err;
  283. RpcpMemorySet(&Hint, 0, sizeof(Hint));
  284. Hint.ai_flags = AI_NUMERICHOST;
  285. err = getaddrinfo(NetworkAddress,
  286. NULL,
  287. &Hint,
  288. &AddrInfo);
  289. if (err)
  290. {
  291. // if it's not a dot address, keep it zero
  292. RpcpMemorySet(&Floor->Data[0], 0, 4);
  293. }
  294. else
  295. {
  296. RpcpMemoryCopy(&Floor->Data[0], &(((SOCKADDR_IN *)AddrInfo->ai_addr)->sin_addr.s_addr), 4);
  297. freeaddrinfo(AddrInfo);
  298. }
  299. Floor->AddressByteCount = 4;
  300. break;
  301. }
  302. #ifndef SPX_IPX_OFF
  303. // IPX protocols use little endian net (32 bit) + node (48 bit) addresses
  304. #ifdef SPX_ON
  305. case SPX:
  306. #endif
  307. #ifdef IPX_ON
  308. case IPX:
  309. #endif
  310. {
  311. Floor->AddressByteCount = 10;
  312. memset(&Floor->Data[0], 0, 10); // Zero is fine..
  313. break;
  314. }
  315. #endif
  316. // Protocols which use string names.
  317. case NMP:
  318. #ifdef NETBIOS_ON
  319. case NBF:
  320. case NBT:
  321. case NBI:
  322. #endif
  323. #ifdef NCADG_MQ_ON
  324. case MSMQ:
  325. #endif
  326. #ifdef APPLETALK_ON
  327. case DSP:
  328. #endif
  329. {
  330. if ((NetworkAddress) && (*NetworkAddress))
  331. {
  332. Floor->AddressByteCount = (unsigned short) addr_size;
  333. memcpy(&Floor->Data[0], NetworkAddress, addr_size);
  334. }
  335. else
  336. {
  337. Floor->AddressByteCount = 2;
  338. Floor->Data[0] = 0;
  339. }
  340. break;
  341. }
  342. #if DBG
  343. default:
  344. ASSERT(0);
  345. #endif
  346. }
  347. return(RPC_S_OK);
  348. }
  349. const INT HTTP_OLD_ADDRESS_ID = 0x20;
  350. RPC_STATUS
  351. RPC_ENTRY
  352. COMMON_TowerExplode(
  353. IN PUCHAR Tower,
  354. OUT PCHAR *Protseq,
  355. OUT PCHAR *NetworkAddress,
  356. OUT PCHAR *Endpoint
  357. )
  358. /*++
  359. Routine Description:
  360. Decodes an OSF transport "upper tower" for the runtime.
  361. Arguments:
  362. Tower - The encoded "upper tower" to decode
  363. Protseq - The protseq encoded in the Tower
  364. Does not need to be freed by the caller.
  365. NetworkAddress - The network address encoded in the Tower
  366. Must be freed by the caller.
  367. Endpoint - The endpoint encoded in the Tower.
  368. Must be freed by the caller.
  369. Return Value:
  370. RPC_S_OK
  371. RPC_S_INVALID_RPC_PROTSEQ
  372. RPC_S_OUT_OF_MEMORY
  373. --*/
  374. {
  375. PFLOOR_234 Floor = (PFLOOR_234)Tower;
  376. PFLOOR_234 NextFloor = NEXTFLOOR(PFLOOR_234, Tower);
  377. RPC_STATUS Status = RPC_S_OK;
  378. INT Index;
  379. // Find the protocol based first on the ID from this floor,
  380. // and then the next floor. We only dereference the next
  381. // floor if we match the ID on this floor.
  382. for (unsigned i = 1; i < cTransportTable; i++)
  383. {
  384. if (TransportTable[i].ProtocolTowerId == Floor->FloorId)
  385. {
  386. if (TransportTable[i].AddressTowerId == NextFloor->FloorId)
  387. break;
  388. //
  389. // The & 0x0F is needed because the legacy server code incorrectly
  390. // cleared the high nibble before sending the address tower id
  391. //
  392. if ((TransportTable[i].AddressTowerId & 0x0F) == NextFloor->FloorId )
  393. break;
  394. // N.B. Old (Win9x/NT4) clients would send a AddressTowerId of 0x20
  395. // (HTTP_OLD_ADDRESS_ID). We need to match this as well.
  396. if ((Floor->FloorId == HTTP_TOWER_ID)
  397. && (NextFloor->FloorId == HTTP_OLD_ADDRESS_ID))
  398. break;
  399. }
  400. }
  401. if (i == cTransportTable)
  402. {
  403. return(RPC_S_INVALID_RPC_PROTSEQ);
  404. }
  405. Index = i;
  406. RPC_TRANSPORT_INTERFACE pInfo = TransportTable[Index].pInfo;
  407. ASSERT(pInfo);
  408. //
  409. // Figure out the protseq
  410. //
  411. if (ARGUMENT_PRESENT(Protseq))
  412. {
  413. size_t len = RpcpStringLength(pInfo->ProtocolSequence);
  414. *Protseq = new char[len + 1];
  415. if (*Protseq)
  416. {
  417. RPC_CHAR *MySrc = (RPC_CHAR *) pInfo->ProtocolSequence;
  418. char *MyDest = *Protseq;
  419. while (*MyDest++ = (char) *MySrc++);
  420. }
  421. else
  422. {
  423. return(RPC_S_OUT_OF_MEMORY);
  424. }
  425. }
  426. //
  427. // Figure out the endpoint
  428. //
  429. if (ARGUMENT_PRESENT(Endpoint))
  430. {
  431. Status = RPC_S_OUT_OF_MEMORY;
  432. switch(Index)
  433. {
  434. // Protocols which use strings as the endpoint format.
  435. case NMP:
  436. #ifdef NETBIOS_ON
  437. case NBT:
  438. case NBI:
  439. case NBF:
  440. #endif
  441. #ifdef NCADG_MQ_ON
  442. case MSMQ:
  443. #endif
  444. #ifdef APPLETALK_ON
  445. case DSP:
  446. #endif
  447. {
  448. *Endpoint = new CHAR[Floor->AddressByteCount];
  449. if (*Endpoint)
  450. {
  451. memcpy(*Endpoint, (PCHAR)&Floor->Data[0],
  452. Floor->AddressByteCount);
  453. Status = RPC_S_OK;
  454. }
  455. }
  456. break;
  457. // Protocols which use ushort's as the endpoint format.
  458. case TCP:
  459. #ifdef SPX_ON
  460. case SPX:
  461. #endif
  462. case HTTP:
  463. case UDP:
  464. #ifdef IPX_ON
  465. case IPX:
  466. #endif
  467. {
  468. USHORT PortNum = *(PUSHORT)(&Floor->Data[0]);
  469. PortNum = RpcpByteSwapShort(PortNum); // Towers are big endian.
  470. *Endpoint = new CHAR[6]; // 65535'\0'
  471. if (*Endpoint)
  472. {
  473. _itoa(PortNum, *Endpoint, 10);
  474. Status = RPC_S_OK;
  475. }
  476. }
  477. break;
  478. default:
  479. ASSERT(0);
  480. }
  481. if (Status != RPC_S_OK)
  482. {
  483. if (ARGUMENT_PRESENT(Protseq))
  484. {
  485. delete *Protseq;
  486. *Protseq = 0;
  487. }
  488. return(Status);
  489. }
  490. }
  491. //
  492. // Now the hard part, figure out the network address.
  493. //
  494. if (ARGUMENT_PRESENT(NetworkAddress))
  495. {
  496. Floor = NEXTFLOOR(PFLOOR_234, Floor);
  497. Status = RPC_S_OUT_OF_MEMORY;
  498. switch(Index)
  499. {
  500. // Protocols which use strings as their network address
  501. case NMP:
  502. #ifdef NETBIOS_ON
  503. case NBF:
  504. case NBT:
  505. case NBI:
  506. #endif
  507. #ifdef NCADG_MQ_ON
  508. case MSMQ:
  509. #endif
  510. #ifdef APPLETALK_ON
  511. case DSP:
  512. #endif
  513. *NetworkAddress = new CHAR[Floor->AddressByteCount];
  514. if (*NetworkAddress)
  515. {
  516. memcpy(*NetworkAddress,
  517. &Floor->Data[0],
  518. Floor->AddressByteCount);
  519. Status = RPC_S_OK;
  520. }
  521. break;
  522. // Protocols using IP addresses
  523. case TCP:
  524. case HTTP:
  525. case UDP:
  526. {
  527. if (Floor->AddressByteCount != 4)
  528. {
  529. Status = RPC_S_INVALID_RPC_PROTSEQ;
  530. break;
  531. }
  532. struct in_addr in;
  533. in.S_un.S_un_b.s_b1 = Floor->Data[0];
  534. in.S_un.S_un_b.s_b2 = Floor->Data[1];
  535. in.S_un.S_un_b.s_b3 = Floor->Data[2];
  536. in.S_un.S_un_b.s_b4 = Floor->Data[3];
  537. PCHAR t = inet_ntoa(in);
  538. if (t)
  539. {
  540. *NetworkAddress = new CHAR[16+1];
  541. if (*NetworkAddress)
  542. {
  543. strcpy(*NetworkAddress, t);
  544. Status = RPC_S_OK;
  545. }
  546. }
  547. else
  548. {
  549. ASSERT(0);
  550. Status = RPC_S_INVALID_RPC_PROTSEQ;
  551. }
  552. }
  553. break;
  554. #ifndef SPX_IPX_OFF
  555. // Protocols using IPX 80 bit addresses
  556. #ifdef SPX_ON
  557. case SPX:
  558. #endif
  559. #ifdef IPX_ON
  560. case IPX:
  561. #endif
  562. {
  563. if (Floor->AddressByteCount != 10)
  564. {
  565. Status = RPC_S_INVALID_RPC_PROTSEQ;
  566. break;
  567. }
  568. // Format: ~NNNNNNNNAAAAAAAAAAAA'\0'
  569. // Network number (32bits) and IEEE 802 address (48bits)
  570. *NetworkAddress = new CHAR[1 + 8 + 12 + 1];
  571. if (*NetworkAddress)
  572. {
  573. PCHAR p = *NetworkAddress;
  574. PCHAR pInput = (PCHAR) &Floor->Data[0];
  575. *p++ = '~';
  576. for (int i = 0; i < 10; i++)
  577. {
  578. CHAR c = *pInput ++;
  579. *p++ = (char) HexDigits[(c >> 4) & 0xF];
  580. *p++ = (char) HexDigits[ c & 0xF];
  581. }
  582. *p = '\0';
  583. Status = RPC_S_OK;
  584. }
  585. break;
  586. }
  587. #endif
  588. }
  589. if (Status != RPC_S_OK)
  590. {
  591. if (ARGUMENT_PRESENT(Endpoint))
  592. {
  593. delete *Endpoint;
  594. *Endpoint = 0;
  595. }
  596. if (ARGUMENT_PRESENT(Protseq))
  597. {
  598. delete *Protseq;
  599. *Protseq = 0;
  600. }
  601. return(Status);
  602. }
  603. }
  604. ASSERT(Status == RPC_S_OK);
  605. return(Status);
  606. }