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.

695 lines
18 KiB

  1. /*******************************************************************/
  2. /* Copyright(c) 1993 Microsoft Corporation */
  3. /*******************************************************************/
  4. //***
  5. //
  6. // Filename: options.c
  7. //
  8. // Description: routines for options handling
  9. //
  10. // Author: Stefan Solomon (stefans) November 24, 1993.
  11. //
  12. // Revision History:
  13. //
  14. //***
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. VOID
  18. NetToWideChar(
  19. OUT PWCHAR ascp,
  20. IN PUCHAR net);
  21. extern HANDLE g_hRouterLog;
  22. VOID
  23. SetNetworkNak(PUCHAR resptr,
  24. PIPXCP_CONTEXT contextp);
  25. VOID
  26. SetNodeNak(PUCHAR resptr,
  27. PIPXCP_CONTEXT contextp);
  28. VOID
  29. SetOptionTypeAndLength(PUCHAR dstptr,
  30. UCHAR opttype,
  31. UCHAR optlen);
  32. #if DBG
  33. #define GET_LOCAL_NET GETLONG2ULONG(&dbglocnet, contextp->Config.Network)
  34. #else
  35. #define GET_LOCAL_NET
  36. #endif
  37. //***
  38. //
  39. // Global description of option handlers
  40. //
  41. // Input: optptr - pointer to the respective option in the frame
  42. // contextp - pointer to the associated context (work buffer)
  43. // resptr - pointer to the response frame to be generated
  44. // Action - one of:
  45. // SNDREQ_OPTION - optptr is the frame to be sent as
  46. // a config request;
  47. // RCVNAK_OPTION - optptr is the frame received as NAK
  48. // RCVREQ_OPTION - optptr is the received request.
  49. // resptr is the frame to generate back
  50. // a response. If the response is not
  51. // an ACK, the return code is FALSE.
  52. // In this case if resptr is not NULL it
  53. // gets the NAK frame.
  54. //
  55. //***
  56. BOOL
  57. NetworkNumberHandler(PUCHAR optptr,
  58. PIPXCP_CONTEXT contextp,
  59. PUCHAR resptr,
  60. OPT_ACTION Action)
  61. {
  62. ULONG recvdnet;
  63. ULONG localnet;
  64. BOOL rc = TRUE;
  65. UCHAR newnet[4];
  66. WCHAR asc[9];
  67. PWCHAR ascp;
  68. // prepare to log if error
  69. ZeroMemory(asc, sizeof(asc));
  70. ascp = asc;
  71. switch(Action) {
  72. case SNDREQ_OPTION:
  73. SetOptionTypeAndLength(optptr, IPX_NETWORK_NUMBER, 6);
  74. memcpy(optptr + OPTIONH_DATA, contextp->Config.Network, 4);
  75. GETLONG2ULONG(&localnet, contextp->Config.Network);
  76. TraceIpx(OPTIONS_TRACE, "NetworkNumberHandler: SND REQ with net 0x%x\n", localnet);
  77. break;
  78. case RCVNAK_OPTION:
  79. contextp->NetNumberNakReceivedCount++;
  80. GETLONG2ULONG(&recvdnet, optptr + OPTIONH_DATA);
  81. GETLONG2ULONG(&localnet, contextp->Config.Network);
  82. TraceIpx(OPTIONS_TRACE, "NetworkNumberHandler: RCV NAK with net 0x%x\n", recvdnet);
  83. if(recvdnet > localnet) {
  84. if(IsRoute(optptr + OPTIONH_DATA)) {
  85. if(GetUniqueHigherNetNumber(newnet,
  86. optptr + OPTIONH_DATA,
  87. contextp) == NO_ERROR) {
  88. // store a new net proposal for the next net send config request
  89. memcpy(contextp->Config.Network, newnet, 4);
  90. }
  91. else
  92. {
  93. // cannot get a net number unique and higher
  94. break;
  95. }
  96. }
  97. else
  98. {
  99. if((contextp->InterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  100. GlobalConfig.RParams.EnableGlobalWanNet) {
  101. break;
  102. }
  103. else
  104. {
  105. memcpy(contextp->Config.Network, optptr + OPTIONH_DATA, 4);
  106. }
  107. }
  108. }
  109. break;
  110. case RCVACK_OPTION:
  111. if(memcmp(contextp->Config.Network, optptr + OPTIONH_DATA, 4)) {
  112. rc = FALSE;
  113. }
  114. break;
  115. case RCVREQ_OPTION:
  116. // if we have already negotiated and this is a renegociation, stick by
  117. // what we have already told the stack in line-up
  118. if(contextp->RouteState == ROUTE_ACTIVATED) {
  119. TraceIpx(OPTIONS_TRACE, "NetworkNumberHandler: rcv req in re-negociation\n");
  120. if(memcmp(contextp->Config.Network, optptr + OPTIONH_DATA, 4)) {
  121. SetNetworkNak(resptr, contextp);
  122. rc = FALSE;
  123. }
  124. break;
  125. }
  126. GETLONG2ULONG(&recvdnet, optptr + OPTIONH_DATA);
  127. GETLONG2ULONG(&localnet, contextp->Config.Network);
  128. // check if a network number has been requested
  129. if((recvdnet == 0) &&
  130. ((contextp->InterfaceType == IF_TYPE_STANDALONE_WORKSTATION_DIALOUT) ||
  131. (contextp->InterfaceType == IF_TYPE_ROUTER_WORKSTATION_DIALOUT))) {
  132. // this is a workstation and needs a network number
  133. if(GetUniqueHigherNetNumber(newnet,
  134. nullnet,
  135. contextp) == NO_ERROR) {
  136. memcpy(contextp->Config.Network, newnet, 4);
  137. }
  138. SetNetworkNak(resptr, contextp);
  139. rc = FALSE;
  140. }
  141. else
  142. {
  143. if(recvdnet > localnet) {
  144. // check if we don't have a net number conflict
  145. if(IsRoute(optptr + OPTIONH_DATA)) {
  146. NetToWideChar(ascp, optptr + OPTIONH_DATA);
  147. RouterLogErrorW(
  148. g_hRouterLog,
  149. ROUTERLOG_IPXCP_NETWORK_NUMBER_CONFLICT,
  150. 1,
  151. (PWCHAR*)&ascp,
  152. NO_ERROR);
  153. if(GetUniqueHigherNetNumber(newnet,
  154. optptr + OPTIONH_DATA,
  155. contextp) == NO_ERROR) {
  156. // new net is different, NAK with this new value
  157. memcpy(contextp->Config.Network, newnet, 4);
  158. }
  159. SetNetworkNak(resptr, contextp);
  160. rc = FALSE;
  161. }
  162. else
  163. {
  164. // the received net number is unique but is different
  165. // of the locally configured net number.
  166. if((contextp->InterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  167. GlobalConfig.RParams.EnableGlobalWanNet) {
  168. NetToWideChar(ascp, optptr + OPTIONH_DATA);
  169. RouterLogErrorW(
  170. g_hRouterLog,
  171. ROUTERLOG_IPXCP_CANNOT_CHANGE_WAN_NETWORK_NUMBER,
  172. 1,
  173. (PWCHAR*)&ascp,
  174. NO_ERROR);
  175. SetNetworkNak(resptr, contextp);
  176. rc = FALSE;
  177. }
  178. else
  179. {
  180. // router is not installed or net number is unique
  181. memcpy(contextp->Config.Network, optptr + OPTIONH_DATA, 4);
  182. }
  183. }
  184. }
  185. else
  186. {
  187. // recvdnet is smaller or equal with the local net
  188. if(recvdnet < localnet) {
  189. // as per RFC - return the highest network number
  190. SetNetworkNak(resptr, contextp);
  191. rc = FALSE;
  192. }
  193. }
  194. }
  195. break;
  196. case SNDNAK_OPTION:
  197. // this option has not been requested by the remote end.
  198. // Force it to request in a NAK
  199. SetNetworkNak(resptr, contextp);
  200. GETLONG2ULONG(&localnet, contextp->Config.Network);
  201. TraceIpx(OPTIONS_TRACE, "NetworkNumberHandler: SND NAK to force request for net 0x%x\n", localnet);
  202. rc = FALSE;
  203. break;
  204. default:
  205. SS_ASSERT(FALSE);
  206. break;
  207. }
  208. return rc;
  209. }
  210. BOOL
  211. NodeNumberHandler(PUCHAR optptr,
  212. PIPXCP_CONTEXT contextp,
  213. PUCHAR resptr,
  214. OPT_ACTION Action)
  215. {
  216. BOOL rc = TRUE;
  217. switch(Action) {
  218. case SNDREQ_OPTION:
  219. SetOptionTypeAndLength(optptr, IPX_NODE_NUMBER, 8);
  220. memcpy(optptr + OPTIONH_DATA, contextp->Config.LocalNode, 6);
  221. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: SND REQ with local node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  222. contextp->Config.LocalNode[0],
  223. contextp->Config.LocalNode[1],
  224. contextp->Config.LocalNode[2],
  225. contextp->Config.LocalNode[3],
  226. contextp->Config.LocalNode[4],
  227. contextp->Config.LocalNode[5]);
  228. break;
  229. case RCVNAK_OPTION:
  230. // If this is server config, then the client has rejected
  231. // our local node number. Ignore the suggestion
  232. // to use a new one. We will not negociate
  233. if(!contextp->Config.ConnectionClient)
  234. break;
  235. // If we are the client, then we'll be happy to accept
  236. // whatever the server assigns us.
  237. memcpy(contextp->Config.LocalNode, optptr + OPTIONH_DATA, 6);
  238. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV NAK accepted. New local node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  239. contextp->Config.LocalNode[0],
  240. contextp->Config.LocalNode[1],
  241. contextp->Config.LocalNode[2],
  242. contextp->Config.LocalNode[3],
  243. contextp->Config.LocalNode[4],
  244. contextp->Config.LocalNode[5]);
  245. break;
  246. case RCVACK_OPTION:
  247. if(memcmp(optptr + OPTIONH_DATA, contextp->Config.LocalNode, 6)) {
  248. rc = FALSE;
  249. }
  250. break;
  251. case RCVREQ_OPTION:
  252. // Is it legal to consider node options at this time?
  253. if(contextp->RouteState == ROUTE_ACTIVATED) {
  254. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: rcv req in re-negociation\n");
  255. if(memcmp(contextp->Config.RemoteNode, optptr + OPTIONH_DATA, 6)) {
  256. SetNodeNak(resptr, contextp);
  257. rc = FALSE;
  258. }
  259. break;
  260. }
  261. // Check if the remote machine has specified any node number
  262. if(!memcmp(optptr + OPTIONH_DATA, nullnode, 6)) {
  263. // the remote node wants us to specify its node number.
  264. SetNodeNak(resptr, contextp);
  265. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV REQ with remote node 0x0, snd NAK with remote node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  266. contextp->Config.RemoteNode[0],
  267. contextp->Config.RemoteNode[1],
  268. contextp->Config.RemoteNode[2],
  269. contextp->Config.RemoteNode[3],
  270. contextp->Config.RemoteNode[4],
  271. contextp->Config.RemoteNode[5]);
  272. rc = FALSE;
  273. }
  274. // Otherwise go through the process of determining whether we
  275. // are able/willing to accept the remote node number suggested.
  276. else {
  277. // If we have been set up as the ras server to reject the request for
  278. // a specific node number, do so here.
  279. if ( (GlobalConfig.AcceptRemoteNodeNumber == 0) &&
  280. (contextp->InterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  281. (memcmp(contextp->Config.RemoteNode, optptr + OPTIONH_DATA, 6)) )
  282. {
  283. SetNodeNak(resptr, contextp);
  284. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV REQ with remote client node but we force a specific node, snd NAK with remote node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  285. contextp->Config.RemoteNode[0],
  286. contextp->Config.RemoteNode[1],
  287. contextp->Config.RemoteNode[2],
  288. contextp->Config.RemoteNode[3],
  289. contextp->Config.RemoteNode[4],
  290. contextp->Config.RemoteNode[5]);
  291. rc = FALSE;
  292. }
  293. // else, if we are a ras server set up with a global network and the client
  294. // requests a specific node number (different from our suggestion), then accept
  295. // or reject the node based on whether that node is unique in the global network.
  296. else if ( (!contextp->Config.ConnectionClient) &&
  297. (contextp->InterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  298. (memcmp(contextp->Config.RemoteNode, optptr + OPTIONH_DATA, 6)) &&
  299. (GlobalConfig.RParams.EnableGlobalWanNet) )
  300. {
  301. ACQUIRE_DATABASE_LOCK;
  302. // remove the present node from the node HT
  303. RemoveFromNodeHT(contextp);
  304. // check the remote node is unique
  305. if(NodeIsUnique(optptr + OPTIONH_DATA)) {
  306. // copy this value in the context buffer
  307. memcpy(contextp->Config.RemoteNode, optptr + OPTIONH_DATA, 6);
  308. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV REQ with remote client node different, ACCEPT it\n");
  309. }
  310. else {
  311. // proposed node not unique -> NAK it
  312. SetNodeNak(resptr, contextp);
  313. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV REQ with non unique remote client node, snd NAK with remote node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  314. contextp->Config.RemoteNode[0],
  315. contextp->Config.RemoteNode[1],
  316. contextp->Config.RemoteNode[2],
  317. contextp->Config.RemoteNode[3],
  318. contextp->Config.RemoteNode[4],
  319. contextp->Config.RemoteNode[5]);
  320. rc = FALSE;
  321. }
  322. // add node to HT
  323. AddToNodeHT(contextp);
  324. RELEASE_DATABASE_LOCK;
  325. }
  326. // Otherwise, it's ok to accept the node number that the other side
  327. // requests. This is true for ras clients, ras servers that don't enforce
  328. // specific node numbers, and ras server that don't assign the same
  329. // network number to every dialed in client.
  330. else
  331. {
  332. memcpy(contextp->Config.RemoteNode, optptr + OPTIONH_DATA, 6);
  333. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: RCV REQ with remote node %.2x%.2x%.2x%.2x%.2x%.2x, accepted\n",
  334. contextp->Config.RemoteNode[0],
  335. contextp->Config.RemoteNode[1],
  336. contextp->Config.RemoteNode[2],
  337. contextp->Config.RemoteNode[3],
  338. contextp->Config.RemoteNode[4],
  339. contextp->Config.RemoteNode[5]);
  340. }
  341. }
  342. break;
  343. case SNDNAK_OPTION:
  344. // the remote node didn't specify this parameter as a desired
  345. // parameter. We suggest it what to specify in a further REQ
  346. SetNodeNak(resptr, contextp);
  347. TraceIpx(OPTIONS_TRACE, "NodeNumberHandler: SND NAK to force the remote to request node %.2x%.2x%.2x%.2x%.2x%.2x\n",
  348. contextp->Config.RemoteNode[0],
  349. contextp->Config.RemoteNode[1],
  350. contextp->Config.RemoteNode[2],
  351. contextp->Config.RemoteNode[3],
  352. contextp->Config.RemoteNode[4],
  353. contextp->Config.RemoteNode[5]);
  354. rc = FALSE;
  355. break;
  356. default:
  357. SS_ASSERT(FALSE);
  358. break;
  359. }
  360. return rc;
  361. }
  362. BOOL
  363. RoutingProtocolHandler(PUCHAR optptr,
  364. PIPXCP_CONTEXT contextp,
  365. PUCHAR resptr,
  366. OPT_ACTION Action)
  367. {
  368. USHORT RoutingProtocol;
  369. BOOL rc = TRUE;
  370. switch(Action) {
  371. case SNDREQ_OPTION:
  372. SetOptionTypeAndLength(optptr, IPX_ROUTING_PROTOCOL, 4);
  373. PUTUSHORT2SHORT(optptr + OPTIONH_DATA, (USHORT)RIP_SAP_ROUTING);
  374. break;
  375. case RCVNAK_OPTION:
  376. // if this option get NAK-ed, we ignore any other suggestions
  377. // for it
  378. break;
  379. case RCVACK_OPTION:
  380. GETSHORT2USHORT(&RoutingProtocol, optptr + OPTIONH_DATA);
  381. if(RoutingProtocol != RIP_SAP_ROUTING) {
  382. rc = FALSE;
  383. }
  384. break;
  385. case RCVREQ_OPTION:
  386. GETSHORT2USHORT(&RoutingProtocol, optptr + OPTIONH_DATA);
  387. if(RoutingProtocol != RIP_SAP_ROUTING) {
  388. SetOptionTypeAndLength(resptr, IPX_ROUTING_PROTOCOL, 4);
  389. PUTUSHORT2SHORT(resptr + OPTIONH_DATA, (USHORT)RIP_SAP_ROUTING);
  390. rc = FALSE;
  391. }
  392. break;
  393. case SNDNAK_OPTION:
  394. SetOptionTypeAndLength(resptr, IPX_ROUTING_PROTOCOL, 4);
  395. PUTUSHORT2SHORT(resptr + OPTIONH_DATA, (USHORT)RIP_SAP_ROUTING);
  396. rc = FALSE;
  397. break;
  398. default:
  399. SS_ASSERT(FALSE);
  400. break;
  401. }
  402. return rc;
  403. }
  404. BOOL
  405. CompressionProtocolHandler(PUCHAR optptr,
  406. PIPXCP_CONTEXT contextp,
  407. PUCHAR resptr,
  408. OPT_ACTION Action)
  409. {
  410. USHORT CompressionProtocol;
  411. BOOL rc = TRUE;
  412. switch(Action) {
  413. case SNDREQ_OPTION:
  414. SetOptionTypeAndLength(optptr, IPX_COMPRESSION_PROTOCOL, 4);
  415. PUTUSHORT2SHORT(optptr + OPTIONH_DATA, (USHORT)TELEBIT_COMPRESSED_IPX);
  416. break;
  417. case RCVNAK_OPTION:
  418. // if this option gets NAK-ed it means that the remote node doesn't
  419. // support Telebit compression but supports another type of compression
  420. // that we don't support. In this case we turn off compression negotiation.
  421. break;
  422. case RCVACK_OPTION:
  423. GETSHORT2USHORT(&CompressionProtocol, optptr + OPTIONH_DATA);
  424. if(CompressionProtocol != TELEBIT_COMPRESSED_IPX) {
  425. rc = FALSE;
  426. }
  427. else
  428. {
  429. // Our compression option got ACK-ed by the other end. This means that
  430. // we can receive compressed packets and have to set the receive
  431. // compression on our end.
  432. contextp->SetReceiveCompressionProtocol = TRUE;
  433. }
  434. break;
  435. case RCVREQ_OPTION:
  436. // if we have already negotiated and this is a renegociation, stick by
  437. // what we have already told the stack in line-up
  438. if(contextp->RouteState == ROUTE_ACTIVATED) {
  439. TraceIpx(OPTIONS_TRACE, "CompressionProtocolHandler: rcv req in re-negociation\n");
  440. }
  441. GETSHORT2USHORT(&CompressionProtocol, optptr + OPTIONH_DATA);
  442. if(CompressionProtocol != TELEBIT_COMPRESSED_IPX) {
  443. if(resptr) {
  444. SetOptionTypeAndLength(resptr, IPX_COMPRESSION_PROTOCOL, 4);
  445. PUTUSHORT2SHORT(resptr + OPTIONH_DATA, (USHORT)TELEBIT_COMPRESSED_IPX);
  446. }
  447. rc = FALSE;
  448. }
  449. else
  450. {
  451. // The remote requests the supported compression option and we ACK it.
  452. // This means it can receive compressed packets and we have to
  453. // set the send compression on our end.
  454. contextp->SetSendCompressionProtocol = TRUE;
  455. }
  456. break;
  457. default:
  458. SS_ASSERT(FALSE);
  459. break;
  460. }
  461. return rc;
  462. }
  463. BOOL
  464. ConfigurationCompleteHandler(PUCHAR optptr,
  465. PIPXCP_CONTEXT contextp,
  466. PUCHAR resptr,
  467. OPT_ACTION Action)
  468. {
  469. BOOL rc = TRUE;
  470. switch(Action) {
  471. case SNDREQ_OPTION:
  472. SetOptionTypeAndLength(optptr, IPX_CONFIGURATION_COMPLETE, 2);
  473. break;
  474. case RCVNAK_OPTION:
  475. // if this option gets NAK-ed we ignore any other suggestions
  476. case RCVREQ_OPTION:
  477. case RCVACK_OPTION:
  478. break;
  479. case SNDNAK_OPTION:
  480. SetOptionTypeAndLength(resptr, IPX_CONFIGURATION_COMPLETE, 2);
  481. rc = FALSE;
  482. break;
  483. default:
  484. SS_ASSERT(FALSE);
  485. break;
  486. }
  487. return rc;
  488. }
  489. VOID
  490. CopyOption(PUCHAR dstptr,
  491. PUCHAR srcptr)
  492. {
  493. USHORT optlen;
  494. optlen = *(srcptr + OPTIONH_LENGTH);
  495. memcpy(dstptr, srcptr, optlen);
  496. }
  497. VOID
  498. SetOptionTypeAndLength(PUCHAR dstptr,
  499. UCHAR opttype,
  500. UCHAR optlen)
  501. {
  502. *(dstptr + OPTIONH_TYPE) = opttype;
  503. *(dstptr + OPTIONH_LENGTH) = optlen;
  504. }
  505. VOID
  506. SetNetworkNak(PUCHAR resptr,
  507. PIPXCP_CONTEXT contextp)
  508. {
  509. SetOptionTypeAndLength(resptr, IPX_NETWORK_NUMBER, 6);
  510. memcpy(resptr + OPTIONH_DATA, contextp->Config.Network, 4);
  511. contextp->NetNumberNakSentCount++;
  512. }
  513. VOID
  514. SetNodeNak(PUCHAR resptr,
  515. PIPXCP_CONTEXT contextp)
  516. {
  517. SetOptionTypeAndLength(resptr, IPX_NODE_NUMBER, 8);
  518. memcpy(resptr + OPTIONH_DATA, contextp->Config.RemoteNode, 6);
  519. }