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.

1085 lines
30 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1998 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: rasatcp.c
  7. //
  8. // Description: Contains routines that implement the ATCP functionality.
  9. //
  10. // History: Feb 26, 1998 Shirish Koti Created original version.
  11. //
  12. //***
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <lmcons.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <llinfo.h>
  21. #include <rasman.h>
  22. #include <rtutils.h>
  23. #include <devioctl.h>
  24. #include <rasppp.h>
  25. #include <pppcp.h>
  26. #define INCL_HOSTWIRE
  27. #include <ppputil.h>
  28. #include <raserror.h>
  29. #include <arapio.h>
  30. #include "rasatcp.h"
  31. //
  32. // Globals
  33. //
  34. HANDLE AtcpHandle=NULL;
  35. CRITICAL_SECTION AtcpCritSect;
  36. BOOLEAN fCritSectInitialized = FALSE;
  37. NET_ADDR AtcpServerAddress;
  38. NET_ADDR AtcpDefaultRouter;
  39. DWORD AtcpNumConnections=0;
  40. UCHAR AtcpServerName[NAMESTR_LEN];
  41. UCHAR AtcpZoneName[ZONESTR_LEN];
  42. //***
  43. //
  44. // Function: atcpStartup
  45. // This routine does init time setup
  46. //
  47. // Return: result of operation
  48. //
  49. //***$
  50. DWORD
  51. atcpStartup(
  52. IN VOID
  53. )
  54. {
  55. DWORD dwRetCode=NO_ERROR;
  56. DWORD dwSrvNameLen=MAX_COMPUTERNAME_LENGTH+1;
  57. // get the server name
  58. if (!GetComputerName((LPTSTR)&AtcpServerName[1],&dwSrvNameLen))
  59. {
  60. dwRetCode = GetLastError();
  61. ATCP_DBGPRINT(("atcpStartup: GetComputerName failed %ld\n",dwRetCode));
  62. return(dwRetCode);
  63. }
  64. // store it in Pascal string format
  65. AtcpServerName[0] = (BYTE)dwSrvNameLen;
  66. InitializeCriticalSection( &AtcpCritSect );
  67. fCritSectInitialized = TRUE;
  68. return(dwRetCode);
  69. }
  70. //***
  71. //
  72. // Function: atcpShutdown
  73. // This routine does de-init time work
  74. //
  75. // Return: result of operation
  76. //
  77. //***$
  78. DWORD
  79. atcpShutdown(
  80. IN VOID
  81. )
  82. {
  83. DWORD dwRetCode=NO_ERROR;
  84. if (fCritSectInitialized)
  85. {
  86. fCritSectInitialized = FALSE;
  87. DeleteCriticalSection( &AtcpCritSect );
  88. }
  89. return(dwRetCode);
  90. }
  91. //***
  92. //
  93. // Function: atcpOpenHandle
  94. // Opens the RAS device exported by the appletalk stack
  95. //
  96. // Parameters: None
  97. //
  98. // Return: None
  99. //
  100. // Globals: AtcpHandle, if successful
  101. //
  102. //***$
  103. VOID
  104. atcpOpenHandle(
  105. IN VOID
  106. )
  107. {
  108. NTSTATUS status;
  109. OBJECT_ATTRIBUTES ObjectAttributes;
  110. UNICODE_STRING DeviceName;
  111. IO_STATUS_BLOCK IoStatus;
  112. HANDLE hLocalHandle;
  113. if (AtcpHandle)
  114. {
  115. ATCP_DBGPRINT(("atcpOpenHandle: handle %lx already open!\n",AtcpHandle));
  116. return;
  117. }
  118. RtlInitUnicodeString( &DeviceName, ARAP_DEVICE_NAME );
  119. InitializeObjectAttributes(
  120. &ObjectAttributes,
  121. &DeviceName,
  122. OBJ_CASE_INSENSITIVE,
  123. NULL,
  124. NULL );
  125. status = NtCreateFile(
  126. &hLocalHandle,
  127. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  128. &ObjectAttributes,
  129. &IoStatus,
  130. NULL,
  131. FILE_ATTRIBUTE_NORMAL,
  132. FILE_SHARE_READ | FILE_SHARE_WRITE,
  133. FILE_OPEN_IF,
  134. 0,
  135. NULL,
  136. 0 );
  137. if ( NT_SUCCESS(status) )
  138. {
  139. AtcpHandle = hLocalHandle;
  140. ATCP_DBGPRINT(("atcpOpenHandle: NtCreateFile succeeded\n",status));
  141. }
  142. else
  143. {
  144. ATCP_DBGPRINT(("atcpOpenHandle: NtCreateFile failed %lx\n",status));
  145. }
  146. }
  147. //***
  148. //
  149. // Function: atcpCloseHandle
  150. // Closes the RAS device (opened in atcpOpenHandle)
  151. //
  152. // Parameters: None
  153. //
  154. // Return: None
  155. //
  156. // Globals: AtalkHandle
  157. //
  158. //***$
  159. VOID
  160. atcpCloseHandle(
  161. IN VOID
  162. )
  163. {
  164. NTSTATUS status=STATUS_SUCCESS;
  165. if (!AtcpHandle)
  166. {
  167. ATCP_DBGPRINT(("atcpCloseHandle: handle already closed!\n"));
  168. return;
  169. }
  170. status = NtClose( AtcpHandle );
  171. AtcpHandle = NULL;
  172. if ( !NT_SUCCESS( status ) )
  173. {
  174. ATCP_DBGPRINT(("atcpCloseHandle: NtClose failed %lx\n",status));
  175. ATCP_ASSERT(0);
  176. }
  177. else
  178. {
  179. ATCP_DBGPRINT(("atcpCloseHandle: NtClose succeeded\n",status));
  180. }
  181. }
  182. //***
  183. //
  184. // Function: atcpAtkSetup
  185. // This is the entry point into the stack to tell the stack to
  186. // set up a context for this connection, to get a network address
  187. // for the dial-in client, server's zone name, and router address
  188. //
  189. // Parameters: pAtcpConn - connection context
  190. //
  191. // Return: status returned by NtDeviceIoControlFile
  192. //
  193. //***$
  194. DWORD
  195. atcpAtkSetup(
  196. IN PATCPCONN pAtcpConn,
  197. IN ULONG IoControlCode
  198. )
  199. {
  200. NTSTATUS status;
  201. IO_STATUS_BLOCK iosb;
  202. HANDLE Event;
  203. BYTE Buffer[sizeof(ARAP_SEND_RECV_INFO) + sizeof(ATCPINFO)];
  204. PARAP_SEND_RECV_INFO pSndRcvInfo;
  205. PATCPINFO pAtcpInfo;
  206. PATCP_SUPPRESS_INFO pSupprInfo;
  207. DWORD dwRetCode=NO_ERROR;
  208. RtlZeroMemory((PBYTE)Buffer, sizeof(Buffer));
  209. pSndRcvInfo = (PARAP_SEND_RECV_INFO)Buffer;
  210. pSndRcvInfo->StatusCode = (DWORD)-1;
  211. pSndRcvInfo->pDllContext = (PVOID)pAtcpConn;
  212. pSndRcvInfo->IoctlCode = IoControlCode;
  213. pSndRcvInfo->ClientAddr = pAtcpConn->ClientAddr;
  214. if (IoControlCode == IOCTL_ATCP_SETUP_CONNECTION)
  215. {
  216. pSndRcvInfo->DataLen = sizeof(ATCPINFO);
  217. }
  218. else if (IoControlCode == IOCTL_ATCP_SUPPRESS_BCAST)
  219. {
  220. // if we don't need to suppress broadcasts, done here
  221. if ((!pAtcpConn->SuppressRtmp) && (!pAtcpConn->SuppressAllBcast))
  222. {
  223. return(NO_ERROR);
  224. }
  225. pSndRcvInfo->DataLen = sizeof(ATCP_SUPPRESS_INFO);
  226. pSupprInfo = (PATCP_SUPPRESS_INFO)&pSndRcvInfo->Data[0];
  227. pSupprInfo->SuppressRtmp = pAtcpConn->SuppressRtmp;
  228. pSupprInfo->SuppressAllBcast = pAtcpConn->SuppressAllBcast;
  229. }
  230. else
  231. {
  232. pSndRcvInfo->DataLen = 0;
  233. }
  234. Event = CreateEvent(NULL, FALSE, FALSE, NULL);
  235. if (Event == NULL)
  236. {
  237. ATCP_DBGPRINT(("atcpAtkSetup: CreateEvent failed (%ld)\n",GetLastError()));
  238. return(ARAPERR_OUT_OF_RESOURCES);
  239. }
  240. status = NtDeviceIoControlFile(
  241. AtcpHandle,
  242. Event, // Event
  243. NULL, // ApcRoutine
  244. NULL, // ApcContext
  245. &iosb, // IoStatusBlock
  246. IoControlCode, // IoControlCode
  247. Buffer, // InputBuffer
  248. sizeof(Buffer), // InputBufferSize
  249. Buffer, // OutputBuffer
  250. sizeof(Buffer)); // OutputBufferSize
  251. if (status == STATUS_PENDING)
  252. {
  253. status = NtWaitForSingleObject(
  254. Event, // Handle
  255. TRUE, // Alertable
  256. NULL); // Timeout
  257. if (NT_SUCCESS(status))
  258. {
  259. status = iosb.Status;
  260. }
  261. }
  262. if (status != STATUS_SUCCESS)
  263. {
  264. ATCP_DBGPRINT(("atcpAtkSetup: NtDeviceIoControlFile failure (%lx)\n",
  265. status));
  266. dwRetCode = ARAPERR_IOCTL_FAILURE;
  267. }
  268. CloseHandle(Event);
  269. dwRetCode = pSndRcvInfo->StatusCode;
  270. if (dwRetCode != NO_ERROR)
  271. {
  272. ATCP_DBGPRINT(("atcpAtkSetup: ioctl %lx failed %ld\n",
  273. IoControlCode,dwRetCode));
  274. return(dwRetCode);
  275. }
  276. //
  277. // for SETUP ioctl, we have some info from stack we need to copy
  278. //
  279. if (IoControlCode == IOCTL_ATCP_SETUP_CONNECTION)
  280. {
  281. pAtcpInfo = (PATCPINFO)&pSndRcvInfo->Data[0];
  282. // get the client's address out
  283. EnterCriticalSection(&pAtcpConn->CritSect);
  284. pAtcpConn->AtalkContext = pSndRcvInfo->AtalkContext;
  285. pAtcpConn->ClientAddr = pSndRcvInfo->ClientAddr;
  286. LeaveCriticalSection(&pAtcpConn->CritSect);
  287. //
  288. // get the default router's address and the zone name
  289. //
  290. EnterCriticalSection( &AtcpCritSect );
  291. AtcpServerAddress = pAtcpInfo->ServerAddr;
  292. AtcpDefaultRouter = pAtcpInfo->DefaultRouterAddr;
  293. ATCP_ASSERT(pAtcpInfo->ServerZoneName[0] < ZONESTR_LEN);
  294. CopyMemory(&AtcpZoneName[1],
  295. &pAtcpInfo->ServerZoneName[1],
  296. pAtcpInfo->ServerZoneName[0]);
  297. AtcpZoneName[0] = pAtcpInfo->ServerZoneName[0];
  298. // got one more connection!
  299. AtcpNumConnections++;
  300. LeaveCriticalSection( &AtcpCritSect );
  301. }
  302. return(dwRetCode);
  303. }
  304. //***
  305. //
  306. // Function: atcpAllocConnection
  307. // This routine allocates an ATCP connection block, initializes
  308. // it with info provided by PPP engine.
  309. //
  310. // Parameters: pInfo - PPPCP_INIT info
  311. //
  312. // Return: pointer to ATCP connection if successful, NULL otherwise
  313. //
  314. //***$
  315. PATCPCONN
  316. atcpAllocConnection(
  317. IN PPPCP_INIT *pPppInit
  318. )
  319. {
  320. PATCPCONN pAtcpConn=NULL;
  321. pAtcpConn = (PATCPCONN)LocalAlloc(LPTR, sizeof(ATCPCONN));
  322. if (pAtcpConn == NULL)
  323. {
  324. ATCP_DBGPRINT(("atcpAllocConnection: malloc failed\n"));
  325. return(NULL);
  326. }
  327. memset( pAtcpConn, 0, sizeof(ATCPCONN) );
  328. pAtcpConn->Signature = ATCP_SIGNATURE;
  329. // by default, broadcasts are not suppressed
  330. pAtcpConn->SuppressRtmp = FALSE;
  331. pAtcpConn->SuppressAllBcast = FALSE;
  332. pAtcpConn->fLineUpDone = FALSE;
  333. InitializeCriticalSection( &pAtcpConn->CritSect );
  334. pAtcpConn->fCritSectInitialized = TRUE;
  335. pAtcpConn->hPort = pPppInit->hPort;
  336. pAtcpConn->hConnection = pPppInit->hConnection;
  337. return(pAtcpConn);
  338. }
  339. //***
  340. //
  341. // Function: atcpParseRequest
  342. // This routine parses the incoming ATCP packet and prepares a
  343. // response as appropriate (Rej, Nak or Ack)
  344. //
  345. // AppleTalk-Address
  346. // 1 6 0 AT-NET(2) AT-Node (1)
  347. // Routing-Protocol
  348. // 2 4 0 0 (Routing protocol - last 2 bytes - can be 0, 1, 2, 3:
  349. // we only support 0)
  350. // Suppress-Broadcasts
  351. // 3 2 (to suppress all broadcasts)
  352. // 3 3 1 (to suppress RTMP bcasts. We don't support other types)
  353. // AT-Compression-Protocol
  354. // 4 4 Undefined!
  355. // Server-information
  356. // 6 Len .....
  357. // Zone-Information
  358. // 7 Len ZoneName
  359. // Default-Router-Address
  360. // 8 6 0 AT-NET(2) AT-Node (1)
  361. //
  362. //
  363. // Parameters: pAtcpConn - the connection
  364. // pReceiveBuf - PPP_CONFIG info: the request
  365. // pSendBuf - PPP_CONFIG info: our response
  366. // cbSendBuf - how big is the Data buffer for our response (for Rej)
  367. // ParseResult - array where we mark off options we saw
  368. // pfRejectingSomething - pointer to TRUE if Rejecting something
  369. //
  370. // Return: result of the operation
  371. //
  372. //***$
  373. DWORD
  374. atcpParseRequest(
  375. IN PATCPCONN pAtcpConn,
  376. IN PPP_CONFIG *pReceiveBuf,
  377. OUT PPP_CONFIG *pSendBuf,
  378. IN DWORD cbSendBuf,
  379. OUT BYTE ParseResult[ATCP_OPT_MAX_VAL+1],
  380. OUT BOOL *pfRejectingSomething
  381. )
  382. {
  383. PPP_OPTION UNALIGNED *pRequest;
  384. PPP_OPTION UNALIGNED *pReject;
  385. DWORD BytesLeftInSendBuf;
  386. PBYTE pOptData;
  387. USHORT OptDataLen;
  388. USHORT PktLen;
  389. USHORT RequestLen;
  390. USHORT UnParsedBytes;
  391. NET_ADDR ClientAddr;
  392. DWORD i;
  393. *pfRejectingSomething = FALSE;
  394. pRequest = (PPP_OPTION UNALIGNED* )pReceiveBuf->Data;
  395. pReject = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
  396. BytesLeftInSendBuf = cbSendBuf;
  397. PktLen = WireToHostFormat16( pReceiveBuf->Length );
  398. UnParsedBytes = PktLen - PPP_CONFIG_HDR_LEN;
  399. if (pRequest->Type > ATCP_OPT_MAX_VAL)
  400. {
  401. ATCP_DBGPRINT(("atcpParseRequest: invalid type %d\n",
  402. pRequest->Type));
  403. return(ERROR_PPP_INVALID_PACKET);
  404. }
  405. // initialize for now to "nothing requested"
  406. for (i=0; i<ATCP_OPT_MAX_VAL; i++)
  407. {
  408. ParseResult[i] = ATCP_NOT_REQUESTED;
  409. }
  410. //
  411. // we loop until we have parsed all the bytes
  412. //
  413. while (UnParsedBytes > 0)
  414. {
  415. RequestLen = (USHORT)pRequest->Length;
  416. if (UnParsedBytes < RequestLen)
  417. {
  418. ATCP_DBGPRINT(("atcpParseRequest: too few bytes %d vs. %d\n",
  419. UnParsedBytes,RequestLen));
  420. return(ERROR_PPP_INVALID_PACKET);
  421. }
  422. //
  423. // assume we're going to accept this option. We'll overwrite if that's
  424. // not the case
  425. //
  426. ParseResult[pRequest->Type] = ATCP_ACK;
  427. // the point where the data portion for this option starts
  428. pOptData = &pRequest->Data[0];
  429. // remove the Type and Len bytes, remaining is option data
  430. OptDataLen = RequestLen - 2;
  431. #if 0
  432. ATCP_DBGPRINT(("atcpParseRequest: type %d OptLen %d (",
  433. pRequest->Type,OptDataLen));
  434. for (i=0; i<OptDataLen; i++)
  435. {
  436. DbgPrint(" 0x%x",pOptData[i]);
  437. }
  438. DbgPrint(" )\n");
  439. #endif
  440. //
  441. // now look at each of the options and see if we should reject it,
  442. // modify it or accept it (Rej, Nak or Ack)
  443. //
  444. switch (pRequest->Type)
  445. {
  446. //
  447. // client wants an appletalk address. We don't allow the client to
  448. // request which address he wants.
  449. //
  450. case ATCP_OPT_APPLETALK_ADDRESS:
  451. if (RequestLen != 6)
  452. {
  453. ATCP_DBGPRINT(("atcpParseRequest: AT_ADDR wrong pktlen %d\n",
  454. RequestLen));
  455. return(ERROR_PPP_INVALID_PACKET);
  456. }
  457. ClientAddr.ata_Network =
  458. WireToHostFormat16(&pOptData[1]);
  459. ClientAddr.ata_Node = (USHORT)pOptData[3];
  460. if ((ClientAddr.ata_Network == 0) ||
  461. (ClientAddr.ata_Node == 0) ||
  462. (ClientAddr.ata_Network != pAtcpConn->ClientAddr.ata_Network) ||
  463. (ClientAddr.ata_Node != pAtcpConn->ClientAddr.ata_Node))
  464. {
  465. ParseResult[pRequest->Type] = ATCP_NAK;
  466. }
  467. break;
  468. //
  469. // client wants some routing protocol. we don't send out Routing
  470. // info, so we should just Nak this option (unless the client also
  471. // is telling us not to send any routing info)
  472. //
  473. case ATCP_OPT_ROUTING_PROTOCOL:
  474. if (RequestLen < 4)
  475. {
  476. ATCP_DBGPRINT(("atcpParseRequest: ROUTING wrong pktlen %d\n",
  477. RequestLen));
  478. return(ERROR_PPP_INVALID_PACKET);
  479. }
  480. //
  481. // we don't send out Routing info, so attempt to negotiate any
  482. // other protocol should be Nak'ed
  483. //
  484. if ((*(USHORT *)&pOptData[0]) != ATCP_OPT_ROUTING_NONE)
  485. {
  486. ParseResult[pRequest->Type] = ATCP_NAK;
  487. }
  488. break;
  489. //
  490. // client wants to suppress broadcasts of some (or all) types of
  491. // DDP types.
  492. //
  493. case ATCP_OPT_SUPPRESS_BROADCAST:
  494. //
  495. // client wants us to suppress only some bcasts?
  496. //
  497. if (OptDataLen > 0)
  498. {
  499. // if requesting RTMP data suppression, we'll allow it
  500. if (pOptData[0] == DDPPROTO_RTMPRESPONSEORDATA)
  501. {
  502. pAtcpConn->SuppressRtmp = TRUE;
  503. }
  504. // hmm, some other protocol: sorry, no can do
  505. else
  506. {
  507. ATCP_DBGPRINT(("atcpParseRequest: Naking suppression %d\n",
  508. pOptData[0]));
  509. ParseResult[pRequest->Type] = ATCP_NAK;
  510. }
  511. }
  512. else
  513. {
  514. pAtcpConn->SuppressAllBcast = TRUE;
  515. }
  516. break;
  517. //
  518. // client wants to negotiate some compression. No compression
  519. // scheme is defined, so we just have to reject this option
  520. //
  521. case ATCP_OPT_AT_COMPRESSION_PROTOCOL:
  522. ATCP_DBGPRINT(("atcpParseRequest: COMPRESSION sending Rej\n"));
  523. if (BytesLeftInSendBuf >= RequestLen)
  524. {
  525. CopyMemory((PVOID)pReject, (PVOID)pRequest, RequestLen);
  526. BytesLeftInSendBuf -= RequestLen;
  527. }
  528. else
  529. {
  530. ATCP_DBGPRINT(("atcpParseRequest: PPP engine's buffer too small\n",
  531. RequestLen));
  532. return(ERROR_BUFFER_TOO_SMALL);
  533. }
  534. pReject = (PPP_OPTION UNALIGNED *)((BYTE* )pReject + RequestLen);
  535. *pfRejectingSomething = TRUE;
  536. ParseResult[pRequest->Type] = ATCP_REJ;
  537. break;
  538. //
  539. // for the following options, we just take note of the fact that
  540. // the client has requested it and we send the info over. Nothing
  541. // to negotiate in these options.
  542. // (We aren't supposed to Nak these either)
  543. //
  544. case ATCP_OPT_RESERVED:
  545. case ATCP_OPT_SERVER_INFORMATION:
  546. case ATCP_OPT_ZONE_INFORMATION:
  547. case ATCP_OPT_DEFAULT_ROUTER_ADDRESS:
  548. break;
  549. default:
  550. ATCP_DBGPRINT(("atcpParseRequest: unknown type %d\n",
  551. pRequest->Type));
  552. return(ERROR_PPP_INVALID_PACKET);
  553. }
  554. //
  555. // move to the next option
  556. //
  557. UnParsedBytes -= RequestLen;
  558. pRequest = (PPP_OPTION UNALIGNED *)((BYTE* )pRequest + RequestLen);
  559. }
  560. //
  561. // see if we are rejecting some option. If so, set some values
  562. //
  563. if (*pfRejectingSomething)
  564. {
  565. pSendBuf->Code = CONFIG_REJ;
  566. HostToWireFormat16( (USHORT)((PBYTE)pReject - (PBYTE)pSendBuf),
  567. pSendBuf->Length );
  568. ATCP_DUMP_BYTES("atcpParseRequest: Rejecting these options:",
  569. &pSendBuf->Data[0],
  570. (DWORD)WireToHostFormat16( pSendBuf->Length)-4);
  571. }
  572. return(NO_ERROR);
  573. }
  574. //***
  575. //
  576. // Function: atcpPrepareResponse
  577. // This routine prepares a response, depending on what all info
  578. // was parsed out from the client's request.
  579. //
  580. // Parameters: pAtcpConn - the connection
  581. // pSendBuf - PPP_CONFIG info: our response
  582. // cbSendBuf - how big is the Data buffer for our response
  583. // ParseResult - array where we have the parsed info
  584. //
  585. // Return: result of the operation
  586. //
  587. //***$
  588. DWORD
  589. atcpPrepareResponse(
  590. IN PATCPCONN pAtcpConn,
  591. OUT PPP_CONFIG *pSendBuf,
  592. IN DWORD cbSendBuf,
  593. OUT BYTE ParseResult[ATCP_OPT_MAX_VAL+1]
  594. )
  595. {
  596. DWORD dwRetCode=NO_ERROR;
  597. DWORD BytesLeftInSendBuf;
  598. PPP_OPTION UNALIGNED *pResponse;
  599. PBYTE pOptData;
  600. USHORT OptDataLen;
  601. USHORT OptionType;
  602. DWORD i;
  603. BOOL fNakingSomething=FALSE;
  604. BOOL fRequestingSomething=FALSE;
  605. BOOL fIncludeThisOption;
  606. pResponse = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
  607. BytesLeftInSendBuf = cbSendBuf;
  608. // first find out if we are going to be Nak'ing anything
  609. for (OptionType=1; OptionType<ATCP_OPT_MAX_VAL; OptionType++ )
  610. {
  611. if (ParseResult[OptionType] == ATCP_NAK)
  612. {
  613. fNakingSomething = TRUE;
  614. }
  615. }
  616. //
  617. // go through our array to see which options we must send Nak to
  618. // (or construct Ack for the whole request)
  619. //
  620. for (OptionType=1; OptionType<ATCP_OPT_MAX_VAL; OptionType++ )
  621. {
  622. //
  623. // if this option is not (to be) requested, we don't send anything
  624. //
  625. if (ParseResult[OptionType] == ATCP_NOT_REQUESTED)
  626. {
  627. continue;
  628. }
  629. // if Nak'ing something and it's not this option to be Nak'ed, skip it
  630. if (fNakingSomething && (ParseResult[OptionType] != ATCP_NAK))
  631. {
  632. continue;
  633. }
  634. //
  635. // make sure we have at least 2 bytes for the OptionType and OptionLen
  636. //
  637. if (BytesLeftInSendBuf < 2)
  638. {
  639. ATCP_DBGPRINT(("atcpPrepareResponse: A: buf too small\n"));
  640. return(ERROR_BUFFER_TOO_SMALL);
  641. }
  642. BytesLeftInSendBuf -= 2;
  643. pOptData = &pResponse->Data[0];
  644. OptDataLen = 0;
  645. fIncludeThisOption = TRUE;
  646. switch (OptionType)
  647. {
  648. //
  649. // tell client (again) the client's network address
  650. //
  651. case ATCP_OPT_APPLETALK_ADDRESS:
  652. OptDataLen = sizeof(NET_ADDR);
  653. if (BytesLeftInSendBuf < OptDataLen)
  654. {
  655. ATCP_DBGPRINT(("atcpPrepareResponse: B: buf too small\n"));
  656. return(ERROR_BUFFER_TOO_SMALL);
  657. }
  658. // skip the reserved byte
  659. *pOptData++ = 0;
  660. //
  661. // if we are sending our REQUEST, send server's address
  662. //
  663. if (ParseResult[OptionType] == ATCP_REQ)
  664. {
  665. // put in the network address
  666. HostToWireFormat16(AtcpServerAddress.ata_Network, pOptData);
  667. pOptData += sizeof(USHORT);
  668. // put in the network node
  669. ATCP_ASSERT(pAtcpConn->ClientAddr.ata_Node != 0);
  670. *pOptData++ = (BYTE)AtcpServerAddress.ata_Node;
  671. fRequestingSomething = TRUE;
  672. }
  673. //
  674. // no, we must send the client's network address
  675. //
  676. else
  677. {
  678. // put in the network address
  679. HostToWireFormat16(pAtcpConn->ClientAddr.ata_Network, pOptData);
  680. pOptData += sizeof(USHORT);
  681. // put in the network node
  682. ATCP_ASSERT(pAtcpConn->ClientAddr.ata_Node != 0);
  683. *pOptData++ = (BYTE)pAtcpConn->ClientAddr.ata_Node;
  684. }
  685. break;
  686. //
  687. // tell client (again) that we support no routing info
  688. //
  689. case ATCP_OPT_ROUTING_PROTOCOL:
  690. OptDataLen = sizeof(USHORT);
  691. HostToWireFormat16(ATCP_OPT_ROUTING_NONE, pOptData);
  692. pOptData += sizeof(USHORT);
  693. break;
  694. //
  695. // tell client that we can suppress RTMP or all Bcast
  696. //
  697. case ATCP_OPT_SUPPRESS_BROADCAST:
  698. // if this is an ack, see if we have agreed to suppressing RTMP
  699. if (!fNakingSomething)
  700. {
  701. if (pAtcpConn->SuppressRtmp)
  702. {
  703. OptDataLen = 1;
  704. *pOptData++ = DDPPROTO_RTMPRESPONSEORDATA;
  705. }
  706. }
  707. break;
  708. //
  709. // we reach here only if are Acking the client's entire request
  710. //
  711. case ATCP_OPT_SERVER_INFORMATION:
  712. ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
  713. ATCP_ASSERT(!fNakingSomething);
  714. OptDataLen = sizeof(USHORT) + sizeof(DWORD) + AtcpServerName[0];
  715. if (BytesLeftInSendBuf < OptDataLen)
  716. {
  717. ATCP_DBGPRINT(("atcpPrepareResponse: C: buf too small\n"));
  718. return(ERROR_BUFFER_TOO_SMALL);
  719. }
  720. // copy the server's class-id
  721. HostToWireFormat16(ATCP_SERVER_CLASS, pOptData);
  722. pOptData += sizeof(USHORT);
  723. // copy the server's implementation-id
  724. HostToWireFormat32(ATCP_SERVER_IMPLEMENTATION_ID, pOptData);
  725. pOptData += sizeof(DWORD);
  726. // copy the server's name
  727. CopyMemory(pOptData, &AtcpServerName[1], AtcpServerName[0]);
  728. break;
  729. //
  730. // we reach here only if are Acking the client's entire request
  731. //
  732. case ATCP_OPT_ZONE_INFORMATION:
  733. ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
  734. ATCP_ASSERT(!fNakingSomething);
  735. // if we don't have a zone name, skip this option
  736. if (AtcpZoneName[0] == 0)
  737. {
  738. fIncludeThisOption = FALSE;
  739. break;
  740. }
  741. OptDataLen = AtcpZoneName[0];
  742. if (BytesLeftInSendBuf < OptDataLen)
  743. {
  744. ATCP_DBGPRINT(("atcpPrepareResponse: D: buf too small\n"));
  745. return(ERROR_BUFFER_TOO_SMALL);
  746. }
  747. // copy the zone name
  748. CopyMemory(pOptData, &AtcpZoneName[1], AtcpZoneName[0]);
  749. break;
  750. //
  751. // we reach here only if are Acking the client's entire request
  752. //
  753. case ATCP_OPT_DEFAULT_ROUTER_ADDRESS:
  754. ATCP_ASSERT(ParseResult[OptionType] != ATCP_NAK);
  755. ATCP_ASSERT(!fNakingSomething);
  756. // if we don't have a router address, skip this option
  757. if (AtcpDefaultRouter.ata_Network == 0)
  758. {
  759. fIncludeThisOption = FALSE;
  760. break;
  761. }
  762. OptDataLen = sizeof(NET_ADDR);
  763. if (BytesLeftInSendBuf < OptDataLen)
  764. {
  765. ATCP_DBGPRINT(("atcpPrepareResponse: E: buf too small\n"));
  766. return(ERROR_BUFFER_TOO_SMALL);
  767. }
  768. // skip the reserved byte
  769. *pOptData++ = 0;
  770. // put in the network address
  771. HostToWireFormat16(AtcpDefaultRouter.ata_Network, pOptData);
  772. pOptData += sizeof(USHORT);
  773. // put in the network node
  774. *pOptData++ = (BYTE)AtcpDefaultRouter.ata_Node;
  775. break;
  776. default:
  777. ATCP_DBGPRINT(("atcpPrepareResponse: opt %d ignored\n",OptionType));
  778. ATCP_ASSERT(0);
  779. break;
  780. }
  781. if (fIncludeThisOption)
  782. {
  783. BytesLeftInSendBuf -= OptDataLen;
  784. pResponse->Type = (BYTE)OptionType;
  785. pResponse->Length = OptDataLen + 2; // 2 = 1 Type byte + 1 Length byte
  786. pResponse = (PPP_OPTION UNALIGNED *)
  787. ((BYTE* )pResponse + pResponse->Length);
  788. }
  789. }
  790. HostToWireFormat16( (USHORT)((PBYTE)pResponse - (PBYTE)pSendBuf),
  791. pSendBuf->Length );
  792. pSendBuf->Code = (fNakingSomething) ? CONFIG_NAK :
  793. ((fRequestingSomething)? CONFIG_REQ : CONFIG_ACK);
  794. #if 0
  795. if (pSendBuf->Code == CONFIG_REQ)
  796. {
  797. ATCP_DUMP_BYTES("atcpParseRequest: Sending our request:",
  798. &pSendBuf->Data[0],
  799. (DWORD)WireToHostFormat16( pSendBuf->Length)-4);
  800. }
  801. else if (pSendBuf->Code == CONFIG_NAK)
  802. {
  803. ATCP_DUMP_BYTES("atcpParseRequest: Nak'ing these options:",
  804. &pSendBuf->Data[0],
  805. (DWORD)WireToHostFormat16( pSendBuf->Length)-4);
  806. }
  807. else
  808. {
  809. ATCP_DUMP_BYTES("atcpParseRequest: Ack packet from us to client:",
  810. &pSendBuf->Data[0],
  811. (DWORD)WireToHostFormat16( pSendBuf->Length)-4);
  812. }
  813. #endif
  814. return(NO_ERROR);
  815. }
  816. //***
  817. //
  818. // Function: atcpCloseAtalkConnection
  819. // This routine tells the stack to close this ATCP connection
  820. //
  821. // Parameters: pAtcpConn - the connection to close
  822. //
  823. // Return: result of the operation
  824. //
  825. //***$
  826. DWORD
  827. atcpCloseAtalkConnection(
  828. IN PATCPCONN pAtcpConn
  829. )
  830. {
  831. DWORD dwRetCode=NO_ERROR;
  832. // tell the stack that this connection is going away!
  833. dwRetCode = atcpAtkSetup(pAtcpConn, IOCTL_ATCP_CLOSE_CONNECTION);
  834. return(dwRetCode);
  835. }
  836. #if DBG
  837. //***
  838. //
  839. // Function: atcpDumpBytes
  840. // DEBUG only: This routine dumps out a given packet to debugger
  841. //
  842. // Parameters: Str - string, if any, to be printed out
  843. // Packet - packet!
  844. // PacketLen - how big is the packet
  845. //
  846. // Return: none
  847. //
  848. //***$
  849. VOID
  850. atcpDumpBytes(
  851. IN PBYTE Str,
  852. IN PBYTE Packet,
  853. IN DWORD PacketLen
  854. )
  855. {
  856. DWORD i;
  857. if (Str)
  858. {
  859. DbgPrint("%s: Packet size %ld\n ",Str,PacketLen);
  860. }
  861. else
  862. {
  863. DbgPrint("Packet size %ld\n ",PacketLen);
  864. }
  865. for (i=0; i<PacketLen; i++)
  866. {
  867. DbgPrint("%x ",Packet[i]);
  868. }
  869. DbgPrint("\n");
  870. }
  871. #endif