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.

517 lines
9.2 KiB

  1. /*******************************************************************/
  2. /* Copyright(c) 1993 Microsoft Corporation */
  3. /*******************************************************************/
  4. //***
  5. //
  6. // Filename: misc.c
  7. //
  8. // Description: misc & aux routines
  9. //
  10. //
  11. // Author: Stefan Solomon (stefans) October 27, 1995
  12. //
  13. // Revision History:
  14. //
  15. //***
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. // Hash Table for the case where we have to accept the remote client node number and
  19. // we have a global wan net. The table is used to detect if the same node number
  20. // is not allocated twice
  21. #define NODE_HASH_TABLE_SIZE 31
  22. LIST_ENTRY NodeHT[NODE_HASH_TABLE_SIZE];
  23. // Coonection Id Hash Table
  24. #define CONN_HASH_TABLE_SIZE 31
  25. LIST_ENTRY ConnHT[CONN_HASH_TABLE_SIZE];
  26. #define connhash(ConnectionId) (ConnectionId) % CONN_HASH_TABLE_SIZE;
  27. //***
  28. //
  29. // Function: IpxCpGetNegotiatedInfo
  30. //
  31. // Descr: returns the client IPX address
  32. //
  33. //***
  34. DWORD
  35. IpxCpGetNegotiatedInfo(IN VOID *pWorkBuffer,
  36. OUT VOID * pIpxCpResultBuf
  37. )
  38. {
  39. PIPXCP_CONTEXT contextp = (PIPXCP_CONTEXT)pWorkBuffer;
  40. PPP_IPXCP_RESULT * pIpxCpResult = (PPP_IPXCP_RESULT *)pIpxCpResultBuf;
  41. memcpy( pIpxCpResult->bLocalAddress, contextp->Config.Network, 4 );
  42. memcpy( pIpxCpResult->bLocalAddress+4, contextp->Config.LocalNode, 6 );
  43. memcpy( pIpxCpResult->bRemoteAddress, contextp->Config.Network, 4 );
  44. memcpy( pIpxCpResult->bRemoteAddress+4, contextp->Config.RemoteNode, 6 );
  45. return NO_ERROR;
  46. }
  47. /*++
  48. Function: GetInterfaceType
  49. Dscr:
  50. --*/
  51. ULONG
  52. GetInterfaceType(PPPPCP_INIT initp)
  53. {
  54. ULONG InterfaceType;
  55. InterfaceType = IF_TYPE_OTHER;
  56. if(initp->hInterface == INVALID_HANDLE_VALUE) {
  57. // The handle has invalid value. This happens in 2 cases:
  58. // 1. Dialed out as a standalone workstation
  59. // 2. Dialed out from a router but using the client UI. This will
  60. // result later in an interface added to the router.
  61. if(!initp->fServer) {
  62. // Workstation dialing out
  63. if(IsRouterStarted()) {
  64. InterfaceType = IF_TYPE_ROUTER_WORKSTATION_DIALOUT;
  65. }
  66. else
  67. {
  68. InterfaceType = IF_TYPE_STANDALONE_WORKSTATION_DIALOUT;
  69. }
  70. }
  71. else
  72. {
  73. // Somebody dialed in but it doesn't have an interface handle !!!
  74. SS_ASSERT(FALSE);
  75. }
  76. }
  77. else
  78. {
  79. // The handle has a valid value
  80. if(!initp->fServer) {
  81. // Dialout - this can be only a WAN router interface
  82. if(IsRouterStarted()) {
  83. // double check with the PPP router type
  84. switch(initp->IfType) {
  85. case ROUTER_IF_TYPE_FULL_ROUTER:
  86. InterfaceType = IF_TYPE_WAN_ROUTER;
  87. break;
  88. case ROUTER_IF_TYPE_HOME_ROUTER:
  89. InterfaceType = IF_TYPE_PERSONAL_WAN_ROUTER;
  90. break;
  91. default:
  92. // Doesn't match the PPP Interface Type
  93. SS_ASSERT(FALSE);
  94. break;
  95. }
  96. }
  97. else
  98. {
  99. // Router not started but we got a valid handle !!!
  100. SS_ASSERT(FALSE);
  101. }
  102. }
  103. else
  104. {
  105. // Dialin - this can be:
  106. // 1. Remote router dialing in
  107. // 2. Remote client dialing in
  108. if(IsRouterStarted()) {
  109. switch(initp->IfType) {
  110. case ROUTER_IF_TYPE_FULL_ROUTER:
  111. InterfaceType = IF_TYPE_WAN_ROUTER;
  112. break;
  113. case ROUTER_IF_TYPE_HOME_ROUTER:
  114. InterfaceType = IF_TYPE_PERSONAL_WAN_ROUTER;
  115. break;
  116. case ROUTER_IF_TYPE_CLIENT:
  117. InterfaceType = IF_TYPE_WAN_WORKSTATION;
  118. break;
  119. default:
  120. // Doesn't match the PPP Interface Type
  121. SS_ASSERT(FALSE);
  122. break;
  123. }
  124. }
  125. else
  126. {
  127. // Router not started but we got a valid handle !!!
  128. SS_ASSERT(FALSE);
  129. }
  130. }
  131. }
  132. return InterfaceType;
  133. }
  134. VOID
  135. NetToAscii(PUCHAR ascp,
  136. PUCHAR net)
  137. {
  138. PUCHAR hexdigit = "0123456789ABCDEF";
  139. int i;
  140. for(i=0; i<4; i++) {
  141. *ascp++ = hexdigit[net[i] / 16];
  142. *ascp++ = hexdigit[net[i] % 16];
  143. }
  144. }
  145. VOID
  146. NetToWideChar(
  147. OUT PWCHAR ascp,
  148. IN PUCHAR net)
  149. {
  150. PWCHAR hexdigit = L"0123456789ABCDEF";
  151. int i;
  152. for (i = 0; i < 4; i++)
  153. {
  154. *ascp++ = hexdigit[net[i] / 16];
  155. *ascp++ = hexdigit[net[i] % 16];
  156. }
  157. }
  158. //*** Routines for handling the hash table of node numbers ***
  159. //***
  160. //
  161. // Function: InitializeNodeHT
  162. //
  163. // Descr:
  164. //
  165. //***
  166. VOID
  167. InitializeNodeHT(VOID)
  168. {
  169. int i;
  170. PLIST_ENTRY NodeHTBucketp;
  171. NodeHTBucketp = NodeHT;
  172. for(i=0; i<NODE_HASH_TABLE_SIZE; i++, NodeHTBucketp++) {
  173. InitializeListHead(NodeHTBucketp);
  174. }
  175. }
  176. //***
  177. //
  178. // Function: ndhash
  179. //
  180. // Descr: compute the hash index for this node
  181. //
  182. //***
  183. int
  184. ndhash(PUCHAR nodep)
  185. {
  186. USHORT ndindex = 6;
  187. int hv = 0; // hash value
  188. while(ndindex--) {
  189. hv += nodep[ndindex] & 0xff;
  190. }
  191. return hv % NODE_HASH_TABLE_SIZE;
  192. }
  193. //***
  194. //
  195. // Function: NodeIsUnique
  196. //
  197. // Descr: returns TRUE if the node is not in the Node Table
  198. //
  199. //***
  200. BOOL
  201. NodeIsUnique(PUCHAR nodep)
  202. {
  203. int hv;
  204. PLIST_ENTRY nextp;
  205. PIPXCP_CONTEXT contextp;
  206. hv = ndhash(nodep);
  207. // walk the niccbs list until we get to the node
  208. nextp = NodeHT[hv].Flink;
  209. while(nextp != &NodeHT[hv]) {
  210. contextp = CONTAINING_RECORD(nextp, IPXCP_CONTEXT, NodeHtLinkage);
  211. if(!memcmp(contextp->Config.RemoteNode, nodep, 6)) {
  212. return FALSE;
  213. }
  214. nextp = contextp->NodeHtLinkage.Flink;
  215. }
  216. return TRUE;
  217. }
  218. //***
  219. //
  220. // Function: AddToNodeHT
  221. //
  222. // Descr: Inserts a new context buffer in the Node Hash Table
  223. //
  224. //***
  225. VOID
  226. AddToNodeHT(PIPXCP_CONTEXT contextp)
  227. {
  228. int hv;
  229. hv = ndhash(contextp->Config.RemoteNode);
  230. InsertTailList(&NodeHT[hv], &contextp->NodeHtLinkage);
  231. }
  232. //***
  233. //
  234. // Function: RemoveFromNodeHT
  235. //
  236. // Descr: Removes a context buffer from the Node Hash Table
  237. //
  238. //***
  239. VOID
  240. RemoveFromNodeHT(PIPXCP_CONTEXT contextp)
  241. {
  242. if (contextp->NodeHtLinkage.Flink)
  243. {
  244. RemoveEntryList(&contextp->NodeHtLinkage);
  245. }
  246. }
  247. /*++
  248. Function: GetUniqueHigherNetNumber
  249. Descr: Try to generate a network number which is higher then oldnet
  250. and is unique for this router's routing table
  251. --*/
  252. DWORD
  253. GetUniqueHigherNetNumber(PUCHAR newnet,
  254. PUCHAR oldnet,
  255. PIPXCP_CONTEXT contextp)
  256. {
  257. ULONG ulnewnet, uloldnet, i;
  258. GETLONG2ULONG(&ulnewnet, oldnet);
  259. // if this connection is a remote client and global wan is set, we can't
  260. // change the network number
  261. if((contextp->InterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  262. (GlobalConfig.RParams.EnableGlobalWanNet)) {
  263. // we cannot change the client's net number
  264. return ERROR_CAN_NOT_COMPLETE;
  265. }
  266. // if the router is not started, anything will do
  267. if(contextp->InterfaceType == IF_TYPE_STANDALONE_WORKSTATION_DIALOUT) {
  268. ulnewnet++;
  269. PUTULONG2LONG(newnet, ulnewnet);
  270. return NO_ERROR;
  271. }
  272. for(i=0, ulnewnet++; i<100000; i++, ulnewnet++) {
  273. if(ulnewnet > 0xFFFFFFFE) {
  274. return ERROR_CAN_NOT_COMPLETE;
  275. }
  276. PUTULONG2LONG(newnet, ulnewnet);
  277. if(!IsRoute(newnet)) {
  278. return NO_ERROR;
  279. }
  280. }
  281. return ERROR_CAN_NOT_COMPLETE;
  282. }
  283. BOOL
  284. IsWorkstationDialoutActive(VOID)
  285. {
  286. BOOL rc = FALSE;;
  287. ACQUIRE_DATABASE_LOCK;
  288. if(WorkstationDialoutActive) {
  289. rc = TRUE;
  290. }
  291. RELEASE_DATABASE_LOCK;
  292. return rc;
  293. }
  294. BOOL
  295. IsRouterStarted(VOID)
  296. {
  297. BOOL rc = FALSE;;
  298. ACQUIRE_DATABASE_LOCK;
  299. if(RouterStarted) {
  300. rc = TRUE;
  301. }
  302. RELEASE_DATABASE_LOCK;
  303. return rc;
  304. }
  305. //*** Routines for handling the hash table of connection ids ***
  306. //***
  307. //
  308. // Function: InitializeConnHT
  309. //
  310. // Descr:
  311. //
  312. //***
  313. VOID
  314. InitializeConnHT(VOID)
  315. {
  316. int i;
  317. PLIST_ENTRY ConnHTBucketp;
  318. ConnHTBucketp = ConnHT;
  319. for(i=0; i<CONN_HASH_TABLE_SIZE; i++, ConnHTBucketp++) {
  320. InitializeListHead(ConnHTBucketp);
  321. }
  322. }
  323. //***
  324. //
  325. // Function: AddToConnHT
  326. //
  327. // Descr: Inserts a new context buffer in the Connection Hash Table
  328. //
  329. // Remark: >> Called with database lock held <<
  330. //
  331. //***
  332. VOID
  333. AddToConnHT(PIPXCP_CONTEXT contextp)
  334. {
  335. ULONG hv;
  336. hv = connhash(contextp->Config.ConnectionId);
  337. InsertTailList(&ConnHT[hv], &contextp->ConnHtLinkage);
  338. }
  339. //***
  340. //
  341. // Function: RemoveFromConnHT
  342. //
  343. // Descr: Removes a context buffer from the Node Hash Table
  344. //
  345. // Remark: >> Called with database lock held <<
  346. //
  347. //***
  348. VOID
  349. RemoveFromConnHT(PIPXCP_CONTEXT contextp)
  350. {
  351. RemoveEntryList(&contextp->ConnHtLinkage);
  352. }
  353. /*++
  354. Function: GetContextBuffer
  355. Descr: gets a ptr to the context buffer based on the connection id
  356. Remark: >> Called with database lock held <<
  357. --*/
  358. PIPXCP_CONTEXT
  359. GetContextBuffer(ULONG_PTR ConnectionId)
  360. {
  361. ULONG hv;
  362. PLIST_ENTRY nextp;
  363. PIPXCP_CONTEXT contextp;
  364. hv = (ULONG)connhash(ConnectionId);
  365. nextp = ConnHT[hv].Flink;
  366. while(nextp != &ConnHT[hv]) {
  367. contextp = CONTAINING_RECORD(nextp, IPXCP_CONTEXT, ConnHtLinkage);
  368. if(contextp->Config.ConnectionId == ConnectionId) {
  369. return contextp;
  370. }
  371. nextp = contextp->ConnHtLinkage.Flink;
  372. }
  373. return NULL;
  374. }