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.

893 lines
19 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. net\routing\ip\rtrmgr\ipipcfg.c
  5. Abstract:
  6. The configuration code for ipinip
  7. Revision History:
  8. Amritansh Raghav
  9. --*/
  10. #include "allinc.h"
  11. //
  12. // All the following are protected by the ICB_LIST lock
  13. //
  14. HKEY g_hIpIpIfKey;
  15. DWORD g_dwNumIpIpInterfaces;
  16. HANDLE g_hIpInIpDevice;
  17. DWORD
  18. OpenIpIpKey(
  19. VOID
  20. )
  21. /*++
  22. Routine Description
  23. Opens the necessary reg keys for IP in IP
  24. Locks
  25. None
  26. Arguments
  27. None
  28. Return Value
  29. Win32 errors
  30. --*/
  31. {
  32. DWORD dwResult;
  33. g_hIpIpIfKey = NULL;
  34. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  35. REG_KEY_TCPIP_INTERFACES,
  36. 0,
  37. KEY_ALL_ACCESS,
  38. &g_hIpIpIfKey);
  39. if(dwResult isnot NO_ERROR)
  40. {
  41. g_hIpIpIfKey = NULL;
  42. Trace1(ERR,
  43. "OpenIpIpKey: Error %d opening interfaces key\n",
  44. dwResult);
  45. return dwResult;
  46. }
  47. return NO_ERROR;
  48. }
  49. VOID
  50. CloseIpIpKey(
  51. VOID
  52. )
  53. /*++
  54. Routine Description
  55. Closes the necessary reg keys for IP in IP
  56. Locks
  57. None
  58. Arguments
  59. None
  60. Return Value
  61. None
  62. --*/
  63. {
  64. if(g_hIpIpIfKey isnot NULL)
  65. {
  66. RegCloseKey(g_hIpIpIfKey);
  67. g_hIpIpIfKey = NULL;
  68. }
  69. }
  70. VOID
  71. DeleteIpIpKeyAndInfo(
  72. IN PICB pIcb
  73. )
  74. /*++
  75. Routine Description
  76. Deletes the key used for the interface
  77. Locks
  78. ICB_LIST as writer
  79. Arguments
  80. pIcb ICB of the interface to delete
  81. Return Value
  82. None
  83. --*/
  84. {
  85. if(pIcb->pIpIpInfo)
  86. {
  87. HeapFree(IPRouterHeap,
  88. 0,
  89. pIcb->pIpIpInfo);
  90. pIcb->pIpIpInfo = NULL;
  91. }
  92. RegDeleteKeyW(g_hIpIpIfKey,
  93. pIcb->pwszName);
  94. }
  95. DWORD
  96. CreateIpIpKeyAndInfo(
  97. IN PICB pIcb
  98. )
  99. /*++
  100. Routine Description
  101. Creates a key under the tcpip interfaces
  102. Locks
  103. ICB_LIST lock held as READER (atleast)
  104. Arguments
  105. ICB for whom to create a key
  106. Return Value
  107. Win32 errors
  108. --*/
  109. {
  110. DWORD dwResult, dwDisposition, dwIndex, dwSize;
  111. HKEY hNewIfKey;
  112. TCHAR ptszNoAddr[] = "0.0.0.0\0";
  113. dwDisposition = 0;
  114. dwResult = RegCreateKeyExW(g_hIpIpIfKey,
  115. pIcb->pwszName,
  116. 0,
  117. UNICODE_NULL,
  118. 0,
  119. KEY_ALL_ACCESS,
  120. NULL,
  121. &hNewIfKey,
  122. &dwDisposition);
  123. if(dwResult isnot NO_ERROR)
  124. {
  125. Trace2(ERR,
  126. "CreateIpIpKey: Error %d creating %S",
  127. dwResult,
  128. pIcb->pwszName);
  129. return ERROR_CAN_NOT_COMPLETE;
  130. }
  131. //
  132. // Good, key is done, now do the minimum needed by IP
  133. //
  134. do
  135. {
  136. //
  137. // Create a block for the configuration. When the dwLocalAddress is
  138. // 0, it means that the information hasnt been set
  139. //
  140. pIcb->pIpIpInfo = HeapAlloc(IPRouterHeap,
  141. HEAP_ZERO_MEMORY,
  142. sizeof(IPINIP_CONFIG_INFO));
  143. if(pIcb->pIpIpInfo is NULL)
  144. {
  145. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  146. break;
  147. }
  148. dwResult = RegSetValueEx(hNewIfKey,
  149. REG_VAL_DEFGATEWAY,
  150. 0,
  151. REG_MULTI_SZ,
  152. NULL,
  153. 0);
  154. if(dwResult isnot NO_ERROR)
  155. {
  156. Trace2(ERR,
  157. "CreateIpIpKey: Error %d setting %s",
  158. dwResult, REG_VAL_DEFGATEWAY);
  159. break;
  160. }
  161. dwDisposition = 0;
  162. dwResult = RegSetValueEx(hNewIfKey,
  163. REG_VAL_ENABLEDHCP,
  164. 0,
  165. REG_DWORD,
  166. (CONST BYTE *)&dwDisposition,
  167. sizeof(DWORD));
  168. if(dwResult isnot NO_ERROR)
  169. {
  170. Trace2(ERR,
  171. "CreateIpIpKey: Error %d setting %s",
  172. dwResult, REG_VAL_ENABLEDHCP);
  173. break;
  174. }
  175. dwResult = RegSetValueEx(hNewIfKey,
  176. REG_VAL_IPADDRESS,
  177. 0,
  178. REG_MULTI_SZ,
  179. (CONST BYTE *)ptszNoAddr,
  180. sizeof(ptszNoAddr));
  181. if(dwResult isnot NO_ERROR)
  182. {
  183. Trace2(ERR,
  184. "CreateIpIpKey: Error %d setting %s",
  185. dwResult, REG_VAL_IPADDRESS);
  186. break;
  187. }
  188. dwResult = RegSetValueEx(hNewIfKey,
  189. REG_VAL_NTECONTEXTLIST,
  190. 0,
  191. REG_MULTI_SZ,
  192. NULL,
  193. 0);
  194. if(dwResult isnot NO_ERROR)
  195. {
  196. Trace2(ERR,
  197. "CreateIpIpKey: Error %d setting %s",
  198. dwResult, REG_VAL_NTECONTEXTLIST);
  199. break;
  200. }
  201. dwResult = RegSetValueEx(hNewIfKey,
  202. REG_VAL_SUBNETMASK,
  203. 0,
  204. REG_MULTI_SZ,
  205. (CONST BYTE *)ptszNoAddr,
  206. sizeof(ptszNoAddr));
  207. if(dwResult isnot NO_ERROR)
  208. {
  209. Trace2(ERR,
  210. "CreateIpIpKey: Error %d setting %s",
  211. dwResult, REG_VAL_SUBNETMASK);
  212. break;
  213. }
  214. dwDisposition = 0;
  215. dwResult = RegSetValueEx(hNewIfKey,
  216. REG_VAL_ZEROBCAST,
  217. 0,
  218. REG_DWORD,
  219. (CONST BYTE *)&dwDisposition,
  220. sizeof(DWORD));
  221. if(dwResult isnot NO_ERROR)
  222. {
  223. Trace2(ERR,
  224. "CreateIpIpKey: Error %d setting %s",
  225. dwResult, REG_VAL_ZEROBCAST);
  226. break;
  227. }
  228. }while(FALSE);
  229. RegCloseKey(hNewIfKey);
  230. if(dwResult isnot NO_ERROR)
  231. {
  232. DeleteIpIpKeyAndInfo(pIcb);
  233. }
  234. return dwResult;
  235. }
  236. DWORD
  237. AddInterfaceToIpInIp(
  238. IN GUID *pGuid,
  239. IN PICB pIcb
  240. )
  241. /*++
  242. Routine Description
  243. Adds an interface to IP in IP driver
  244. Locks
  245. ICB_LIST lock held as WRITER
  246. Arguments
  247. pIcb ICB of the interface to add
  248. Return Value
  249. NO_ERROR
  250. --*/
  251. {
  252. DWORD dwResult;
  253. NTSTATUS ntStatus;
  254. PADAPTER_INFO pBindNode;
  255. ULONG ulSize;
  256. IO_STATUS_BLOCK IoStatusBlock;
  257. IPINIP_CREATE_TUNNEL CreateInfo;
  258. IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
  259. //
  260. // Get a key for this interface
  261. //
  262. dwResult = CreateIpIpKeyAndInfo(pIcb);
  263. if(dwResult isnot NO_ERROR)
  264. {
  265. Trace2(ERR,
  266. "AddInterfaceToIpInIp: Error %d creating key for %S",
  267. dwResult,
  268. pIcb->pwszName);
  269. return ERROR_CAN_NOT_COMPLETE;
  270. }
  271. //
  272. // See if we need to start IP in IP
  273. //
  274. g_dwNumIpIpInterfaces++;
  275. if(g_dwNumIpIpInterfaces is 1)
  276. {
  277. dwResult = StartDriverAndOpenHandle(IPINIP_SERVICE_NAME,
  278. DD_IPINIP_DEVICE_NAME,
  279. &g_hIpInIpDevice);
  280. if(dwResult isnot NO_ERROR)
  281. {
  282. Trace2(ERR,
  283. "AddInterfaceToIpInIp: Error %d starting ipinip for %S",
  284. dwResult,
  285. pIcb->pwszName);
  286. g_dwNumIpIpInterfaces--;
  287. DeleteIpIpKeyAndInfo(pIcb);
  288. return dwResult;
  289. }
  290. //
  291. // Once you start, post a notification
  292. //
  293. PostIpInIpNotification();
  294. }
  295. //
  296. // Copy out the name
  297. //
  298. CreateInfo.Guid = *pGuid;
  299. ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
  300. NULL,
  301. NULL,
  302. NULL,
  303. &IoStatusBlock,
  304. IOCTL_IPINIP_CREATE_TUNNEL,
  305. &CreateInfo,
  306. sizeof(IPINIP_CREATE_TUNNEL),
  307. &CreateInfo,
  308. sizeof(IPINIP_CREATE_TUNNEL));
  309. if(!NT_SUCCESS(ntStatus))
  310. {
  311. Trace1(ERR,
  312. "AddInterfaceToIpInIp: NtStatus %x creating tunnel",
  313. ntStatus);
  314. g_dwNumIpIpInterfaces--;
  315. if(g_dwNumIpIpInterfaces is 0)
  316. {
  317. StopDriverAndCloseHandle(IPINIP_SERVICE_NAME,
  318. g_hIpInIpDevice);
  319. }
  320. DeleteIpIpKeyAndInfo(pIcb);
  321. return ERROR_CAN_NOT_COMPLETE;
  322. }
  323. //
  324. // Set the interface index
  325. //
  326. pIcb->bBound = TRUE;
  327. pIcb->dwNumAddresses = 0;
  328. pIcb->dwIfIndex = CreateInfo.dwIfIndex;
  329. return NO_ERROR;
  330. }
  331. DWORD
  332. DeleteInterfaceFromIpInIp(
  333. PICB pIcb
  334. )
  335. /*++
  336. Routine Description
  337. Removes an interface to IP in IP driver. Also removes binding information
  338. and frees the ipipcfg
  339. Locks
  340. ICB_LIST lock held as WRITER
  341. Arguments
  342. pIcb ICB of the interface to remove
  343. Return Value
  344. NO_ERROR
  345. --*/
  346. {
  347. NTSTATUS ntStatus;
  348. IPINIP_DELETE_TUNNEL DeleteInfo;
  349. PADAPTER_INFO pBindNode;
  350. IO_STATUS_BLOCK IoStatusBlock;
  351. DWORD dwResult;
  352. IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
  353. //
  354. // See if the interface was added to ipinip
  355. //
  356. if(pIcb->pIpIpInfo is NULL)
  357. {
  358. return NO_ERROR;
  359. }
  360. DeleteInfo.dwIfIndex = pIcb->dwIfIndex;
  361. ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
  362. NULL,
  363. NULL,
  364. NULL,
  365. &IoStatusBlock,
  366. IOCTL_IPINIP_DELETE_TUNNEL,
  367. (PVOID)&DeleteInfo,
  368. sizeof(IPINIP_DELETE_TUNNEL),
  369. NULL,
  370. 0);
  371. if(!NT_SUCCESS(ntStatus))
  372. {
  373. Trace1(ERR,
  374. "DeleteInterfaceFromIpInIp: NtStatus %x setting info",
  375. ntStatus);
  376. }
  377. pIcb->bBound = FALSE;
  378. pIcb->dwNumAddresses = 0;
  379. //
  380. // These interfaces always have a binding
  381. // Clear out any info there
  382. //
  383. pIcb->pibBindings[0].dwAddress = 0;
  384. pIcb->pibBindings[0].dwMask = 0;
  385. DeleteIpIpKeyAndInfo(pIcb);
  386. g_dwNumIpIpInterfaces--;
  387. if(g_dwNumIpIpInterfaces is 0)
  388. {
  389. StopDriverAndCloseHandle(IPINIP_SERVICE_NAME,
  390. g_hIpInIpDevice);
  391. }
  392. return NO_ERROR;
  393. }
  394. DWORD
  395. SetIpInIpInfo(
  396. PICB pIcb,
  397. PRTR_INFO_BLOCK_HEADER pInterfaceInfo
  398. )
  399. /*++
  400. Routine Description
  401. The routine sets the IP in IP info to the driver. The interface must
  402. have already been added to the driver
  403. Locks
  404. ICB_LIST lock held as WRITER
  405. Arguments
  406. pIcb ICB of the tunnel interface
  407. pInterfaceInfo Header to the interface info
  408. Return Value
  409. NO_ERROR
  410. --*/
  411. {
  412. PRTR_TOC_ENTRY pToc;
  413. PIPINIP_CONFIG_INFO pInfo;
  414. IPINIP_SET_TUNNEL_INFO SetInfo;
  415. IO_STATUS_BLOCK IoStatusBlock;
  416. NTSTATUS ntStatus;
  417. DWORD dwResult;
  418. if(pIcb->ritType isnot ROUTER_IF_TYPE_TUNNEL1)
  419. {
  420. return NO_ERROR;
  421. }
  422. pToc = GetPointerToTocEntry(IP_IPINIP_CFG_INFO,
  423. pInterfaceInfo);
  424. if(pToc is NULL)
  425. {
  426. //
  427. // No change
  428. //
  429. return NO_ERROR;
  430. }
  431. IpRtAssert(pToc->InfoSize isnot 0);
  432. #if 0
  433. if(pToc->InfoSize is 0)
  434. {
  435. //
  436. // Blow the interface away from protocols etc
  437. //
  438. dwResult = LanEtcInterfaceUpToDown(pIcb,
  439. FALSE);
  440. if(dwResult isnot NO_ERROR)
  441. {
  442. Trace2(ERR,
  443. "SetIpInIpInfo: Error %d bringing %S down\n",
  444. dwResult,
  445. pIcb->pwszName);
  446. }
  447. //
  448. // Tear down the tunnel
  449. //
  450. DeleteInterfaceFromIpInIp(pIcb);
  451. return NO_ERROR;
  452. }
  453. #endif
  454. //
  455. // Verify the information
  456. //
  457. pInfo = GetInfoFromTocEntry(pInterfaceInfo,
  458. pToc);
  459. if (pInfo is NULL)
  460. {
  461. return ERROR_INVALID_PARAMETER;
  462. }
  463. if((pInfo->dwLocalAddress is INVALID_IP_ADDRESS) or
  464. (pInfo->dwRemoteAddress is INVALID_IP_ADDRESS) or
  465. ((DWORD)(pInfo->dwLocalAddress & 0x000000E0) >= (DWORD)0x000000E0) or
  466. ((DWORD)(pInfo->dwRemoteAddress & 0x000000E0) >= (DWORD)0x000000E0) or
  467. (pInfo->byTtl is 0))
  468. {
  469. return ERROR_INVALID_PARAMETER;
  470. }
  471. //
  472. // See if the interface has already been added to the driver
  473. //
  474. IpRtAssert(pIcb->pIpIpInfo isnot NULL);
  475. SetInfo.dwIfIndex = pIcb->dwIfIndex;
  476. SetInfo.dwRemoteAddress = pInfo->dwRemoteAddress;
  477. SetInfo.dwLocalAddress = pInfo->dwLocalAddress;
  478. SetInfo.byTtl = pInfo->byTtl;
  479. //
  480. // Set the info to the driver
  481. //
  482. ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
  483. NULL,
  484. NULL,
  485. NULL,
  486. &IoStatusBlock,
  487. IOCTL_IPINIP_SET_TUNNEL_INFO,
  488. (PVOID)&SetInfo,
  489. sizeof(IPINIP_SET_TUNNEL_INFO),
  490. NULL,
  491. 0);
  492. if(!NT_SUCCESS(ntStatus))
  493. {
  494. Trace1(ERR,
  495. "SetIpInIpInfo: NtStatus %x setting info",
  496. ntStatus);
  497. #if 0
  498. DeleteInterfaceFromIpInIp(pIcb);
  499. #endif
  500. return ERROR_CAN_NOT_COMPLETE;
  501. }
  502. pIcb->dwOperationalState = SetInfo.dwOperationalState;
  503. pIcb->pIpIpInfo->dwRemoteAddress = SetInfo.dwRemoteAddress;
  504. pIcb->pIpIpInfo->dwLocalAddress = SetInfo.dwLocalAddress;
  505. pIcb->pIpIpInfo->byTtl = SetInfo.byTtl;
  506. //
  507. // Also set the operational state to UP
  508. //
  509. pIcb->dwOperationalState = CONNECTED;
  510. return NO_ERROR;
  511. }
  512. DWORD
  513. GetInterfaceIpIpInfo(
  514. IN PICB pIcb,
  515. IN PRTR_TOC_ENTRY pToc,
  516. IN PBYTE pbDataPtr,
  517. IN OUT PRTR_INFO_BLOCK_HEADER pInfoHdr,
  518. IN OUT PDWORD pdwInfoSize
  519. )
  520. {
  521. PIPINIP_CONFIG_INFO pInfo;
  522. TraceEnter("GetInterfaceIpIpInfo");
  523. IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
  524. if(*pdwInfoSize < sizeof(IPINIP_CONFIG_INFO))
  525. {
  526. *pdwInfoSize = sizeof(IPINIP_CONFIG_INFO);
  527. return ERROR_INSUFFICIENT_BUFFER;
  528. }
  529. *pdwInfoSize = 0;
  530. if(pIcb->pIpIpInfo is NULL)
  531. {
  532. //
  533. // Have no info
  534. //
  535. return ERROR_NO_DATA;
  536. }
  537. *pdwInfoSize = sizeof(IPINIP_CONFIG_INFO);
  538. //pToc->InfoVersion sizeof(IPINIP_CONFIG_INFO);
  539. pToc->InfoSize = sizeof(IPINIP_CONFIG_INFO);
  540. pToc->InfoType = IP_IPINIP_CFG_INFO;
  541. pToc->Count = 1;
  542. pToc->Offset = (ULONG)(pbDataPtr - (PBYTE) pInfoHdr);
  543. pInfo = (PIPINIP_CONFIG_INFO)pbDataPtr;
  544. *pInfo = *(pIcb->pIpIpInfo);
  545. TraceLeave("GetInterfaceIpIpInfo");
  546. return NO_ERROR;
  547. }
  548. DWORD
  549. PostIpInIpNotification(
  550. VOID
  551. )
  552. {
  553. DWORD dwBytesRead;
  554. DWORD dwErr = NO_ERROR;
  555. TraceEnter("PostIpInIpNotification");
  556. ZeroMemory(&g_IpInIpOverlapped,
  557. sizeof(OVERLAPPED));
  558. g_IpInIpOverlapped.hEvent = g_hIpInIpEvent ;
  559. if (!DeviceIoControl(g_hIpInIpDevice,
  560. IOCTL_IPINIP_NOTIFICATION,
  561. &g_inIpInIpMsg,
  562. sizeof(g_inIpInIpMsg),
  563. &g_inIpInIpMsg,
  564. sizeof(g_inIpInIpMsg),
  565. (PDWORD) &dwBytesRead,
  566. &g_IpInIpOverlapped))
  567. {
  568. dwErr = GetLastError();
  569. if(dwErr isnot ERROR_IO_PENDING)
  570. {
  571. Trace1(ERR,
  572. "PostIpInIpNotification: Couldnt post irp with IpInIp: %d",
  573. dwErr);
  574. dwErr = NO_ERROR;
  575. }
  576. else
  577. {
  578. Trace0(IF,
  579. "PostIpInIpNotification: Notification pending in IpInIP");
  580. }
  581. }
  582. return dwErr;
  583. }
  584. VOID
  585. HandleIpInIpEvent(
  586. VOID
  587. )
  588. {
  589. PICB pIcb;
  590. DWORD dwBytes;
  591. ENTER_WRITER(ICB_LIST);
  592. TraceEnter("HandleIpInIpEvent");
  593. do
  594. {
  595. if((g_inIpInIpMsg.ieEvent isnot IE_INTERFACE_UP) and
  596. (g_inIpInIpMsg.ieEvent isnot IE_INTERFACE_DOWN))
  597. {
  598. Trace1(IF,
  599. "HandleIpInIpEvent: Unknown event code %d\n",
  600. g_inIpInIpMsg.ieEvent);
  601. break;
  602. }
  603. if(!GetOverlappedResult(g_hIpInIpDevice,
  604. &g_IpInIpOverlapped,
  605. &dwBytes,
  606. FALSE))
  607. {
  608. Trace1(IF,
  609. "HandleIpInIpEvent: Error %d from GetOverlappedResult",
  610. GetLastError());
  611. break;
  612. }
  613. pIcb = InterfaceLookupByIfIndex(g_inIpInIpMsg.dwIfIndex);
  614. if(pIcb is NULL)
  615. {
  616. Trace1(IF,
  617. "HandleIpInIpEvent: Interface %x not found",
  618. g_inIpInIpMsg.dwIfIndex);
  619. break;
  620. }
  621. if(pIcb->ritType isnot ROUTER_IF_TYPE_TUNNEL1)
  622. {
  623. Trace1(IF,
  624. "HandleIpInIpEvent: Interface %x not an IpInIp tunnel",
  625. g_inIpInIpMsg.dwIfIndex);
  626. IpRtAssert(FALSE);
  627. break;
  628. }
  629. Trace3(IF,
  630. "HandleIpInIpEvent: Interface %S is %s due to %d",
  631. pIcb->pwszName,
  632. (g_inIpInIpMsg.ieEvent is IE_INTERFACE_UP) ? "operational" : "non-operational",
  633. g_inIpInIpMsg.iseSubEvent);
  634. pIcb->dwOperationalState =
  635. (g_inIpInIpMsg.ieEvent is IE_INTERFACE_UP) ? OPERATIONAL : NON_OPERATIONAL;
  636. }while(FALSE);
  637. EXIT_LOCK(ICB_LIST);
  638. PostIpInIpNotification();
  639. return;
  640. }