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.

2214 lines
49 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ipinip\adapter.c
  5. Abstract:
  6. The file contains the section interface of the IP in IP tunnel driver
  7. to the TCP/IP stack that is involved with Binding Notification and
  8. Querying/Setting information for interfaces
  9. The code is a cleaned up version of wanarp\ipif.c which in turn
  10. was derived from HenrySa's ip\arp.c
  11. Revision History:
  12. AmritanR
  13. --*/
  14. #define __FILE_SIG__ ADAPTER_SIG
  15. #include "inc.h"
  16. VOID
  17. IpIpOpenAdapter(
  18. IN PVOID pvContext
  19. )
  20. /*++
  21. Routine Description
  22. Called by IP when the adapter from it IPAddInterface() call
  23. Locks
  24. Arguments
  25. pvContext Pointer to the TUNNEL structure
  26. Return Value
  27. None
  28. --*/
  29. {
  30. TraceEnter(TUNN, "IpIpOpenAdapter");
  31. //
  32. // Nothing to be done here, really
  33. //
  34. TraceLeave(TUNN, "IpIpOpenAdapter");
  35. }
  36. VOID
  37. IpIpCloseAdapter(
  38. IN PVOID pvContext
  39. )
  40. /*++
  41. Routine Description
  42. Called by IP when it wants to close an adapter. Currently this is done
  43. from CloseNets() and IPDelInterface().
  44. Locks
  45. Arguments
  46. pvContext Pointer to the TUNNEL
  47. Return Value
  48. None
  49. --*/
  50. {
  51. TraceEnter(TUNN, "IpIpCloseAdapter");
  52. TraceLeave(TUNN, "IpIpCloseAdapter");
  53. }
  54. UINT
  55. IpIpAddAddress(
  56. IN PVOID pvContext,
  57. IN UINT uiType,
  58. IN DWORD dwAddress,
  59. IN DWORD dwMask,
  60. IN PVOID pvUnused
  61. )
  62. /*++
  63. Routine Description
  64. This routine is called by the upper layer to add an address as a local
  65. address, or specify the broadcast address for this Interface
  66. Locks
  67. Arguments
  68. Return Value
  69. NO_ERROR
  70. --*/
  71. {
  72. TraceEnter(TUNN, "IpIpAddAddress");
  73. TraceLeave(TUNN, "IpIpAddAddress");
  74. return (UINT)TRUE;
  75. }
  76. UINT
  77. IpIpDeleteAddress(
  78. IN PVOID pvContext,
  79. IN UINT uiType,
  80. IN DWORD dwAddress,
  81. IN DWORD dwMask
  82. )
  83. /*++
  84. Routine Description
  85. Called to delete a local or proxy address.
  86. Locks
  87. Arguments
  88. Return Value
  89. NO_ERROR
  90. --*/
  91. {
  92. TraceEnter(TUNN, "IpIpDeleteAddress");
  93. TraceLeave(TUNN, "IpIpDeleteAddress");
  94. return TRUE;
  95. }
  96. INT
  97. IpIpQueryInfo(
  98. IN PVOID pvIfContext,
  99. IN TDIObjectID *pTdiObjId,
  100. IN PNDIS_BUFFER pnbBuffer,
  101. IN PUINT puiSize,
  102. IN PVOID pvContext
  103. )
  104. /*++
  105. Routine Description
  106. Routine is called by IP to query the MIB-II information related
  107. to the TUNNEL interface
  108. Locks
  109. We acquire the TUNNEL lock. We dont need to refcount the tunnel as
  110. explained in ipinip.h
  111. Arguments
  112. pvIfContext The context we returned to IP, a pointer to the TUNNEL
  113. Return Value
  114. --*/
  115. {
  116. PTUNNEL pTunnel;
  117. ULONG ulOffset;
  118. ULONG ulBufferSize;
  119. UINT BytesCopied = 0;
  120. BYTE rgbyInfoBuff[sizeof(IFEntry)];
  121. DWORD dwEntity;
  122. DWORD dwInstance;
  123. IFEntry *pIFE;
  124. NTSTATUS nStatus;
  125. pTunnel = (PTUNNEL)pvIfContext;
  126. dwEntity = pTdiObjId->toi_entity.tei_entity;
  127. dwInstance = pTdiObjId->toi_entity.tei_instance;
  128. //
  129. // We support only Interface MIBs - no address xlation - pretty much like
  130. // a loopback i/f (per Henry circa 1994)
  131. //
  132. if((dwEntity isnot IF_ENTITY) or
  133. (dwInstance isnot pTunnel->dwIfInstance))
  134. {
  135. return TDI_INVALID_REQUEST;
  136. }
  137. if(pTdiObjId->toi_type isnot INFO_TYPE_PROVIDER)
  138. {
  139. Trace(TUNN, INFO,
  140. ("IpIpQueryInfo: toi_type is wrong 0x%x\n",
  141. pTdiObjId->toi_type));
  142. return TDI_INVALID_PARAMETER;
  143. }
  144. //
  145. // a safe initialization.
  146. //
  147. ulBufferSize = *puiSize;
  148. *puiSize = 0;
  149. ulOffset = 0;
  150. if(pTdiObjId->toi_class is INFO_CLASS_GENERIC)
  151. {
  152. if(pTdiObjId->toi_id isnot ENTITY_TYPE_ID)
  153. {
  154. Trace(TUNN, INFO,
  155. ("IpIpQueryInfo: toi_id is wrong 0x%x\n",
  156. pTdiObjId->toi_id));
  157. return TDI_INVALID_PARAMETER;
  158. }
  159. //
  160. // He's trying to see what type we are.
  161. //
  162. if(ulBufferSize < sizeof(DWORD))
  163. {
  164. Trace(TUNN, ERROR,
  165. ("IpIpQueryInfo: Buffer size %d too small\n",
  166. ulBufferSize));
  167. return TDI_BUFFER_TOO_SMALL;
  168. }
  169. *(PDWORD)&rgbyInfoBuff[0] = (dwEntity is AT_ENTITY) ?
  170. AT_ARP : IF_MIB;
  171. #if NDISBUFFERISMDL
  172. nStatus = TdiCopyBufferToMdl(rgbyInfoBuff,
  173. 0,
  174. sizeof(DWORD),
  175. (PMDL)pnbBuffer,
  176. 0,
  177. &ulOffset);
  178. #else
  179. #error "Fix this"
  180. #endif
  181. *puiSize = ulOffset;
  182. return nStatus;
  183. }
  184. if(pTdiObjId->toi_class isnot INFO_CLASS_PROTOCOL)
  185. {
  186. Trace(TUNN, INFO,
  187. ("IpIpQueryInfo: toi_class is wrong 0x%x\n",
  188. pTdiObjId->toi_class));
  189. return TDI_INVALID_PARAMETER;
  190. }
  191. //
  192. // The usermust be asking for Interface level information.
  193. // See if we support what is being asked for
  194. //
  195. if(pTdiObjId->toi_id isnot IF_MIB_STATS_ID)
  196. {
  197. Trace(TUNN, INFO,
  198. ("IpIpQueryInfo: toi_id 0x%x is not MIB_STATS\n",
  199. pTdiObjId->toi_id));
  200. return TDI_INVALID_PARAMETER;
  201. }
  202. //
  203. // He's asking for statistics. Make sure his buffer is at least big
  204. // enough to hold the fixed part.
  205. //
  206. if(ulBufferSize < IFE_FIXED_SIZE)
  207. {
  208. Trace(TUNN, ERROR,
  209. ("IpIpQueryInfo: Buffer size %d smaller than IFE %d\n",
  210. ulBufferSize, IFE_FIXED_SIZE));
  211. return TDI_BUFFER_TOO_SMALL;
  212. }
  213. pIFE = (IFEntry *)rgbyInfoBuff;
  214. RtlZeroMemory(pIFE,
  215. sizeof(IFEntry));
  216. //
  217. // He's got enough to hold the fixed part. Build the IFEntry structure,
  218. // and copy it to his buffer.
  219. //
  220. pIFE->if_index = pTunnel->dwIfIndex;
  221. pIFE->if_type = IF_TYPE_TUNNEL;
  222. pIFE->if_physaddrlen = ARP_802_ADDR_LENGTH;
  223. RtlCopyMemory(pIFE->if_physaddr,
  224. pTunnel->rgbyHardwareAddr,
  225. ARP_802_ADDR_LENGTH);
  226. pIFE->if_mtu = pTunnel->ulMtu;
  227. pIFE->if_speed = DEFAULT_SPEED;
  228. pIFE->if_adminstatus = GetAdminState(pTunnel);
  229. pIFE->if_operstatus = pTunnel->dwOperState;
  230. pIFE->if_lastchange = pTunnel->dwLastChange;
  231. pIFE->if_inoctets = pTunnel->ulInOctets;
  232. pIFE->if_inucastpkts = pTunnel->ulInUniPkts;
  233. pIFE->if_innucastpkts = pTunnel->ulInNonUniPkts;
  234. pIFE->if_indiscards = pTunnel->ulInDiscards;
  235. pIFE->if_inerrors = pTunnel->ulInErrors;
  236. pIFE->if_inunknownprotos = pTunnel->ulInUnknownProto;
  237. pIFE->if_outoctets = pTunnel->ulOutOctets;
  238. pIFE->if_outucastpkts = pTunnel->ulOutUniPkts;
  239. pIFE->if_outnucastpkts = pTunnel->ulOutNonUniPkts;
  240. pIFE->if_outdiscards = pTunnel->ulOutDiscards;
  241. pIFE->if_outerrors = pTunnel->ulOutErrors;
  242. pIFE->if_outqlen = pTunnel->ulOutQLen;
  243. pIFE->if_descrlen = strlen(VENDOR_DESCRIPTION_STRING);
  244. #if NDISBUFFERISMDL
  245. nStatus = TdiCopyBufferToMdl(pIFE,
  246. 0,
  247. IFE_FIXED_SIZE,
  248. (PMDL)pnbBuffer,
  249. 0,
  250. &ulOffset);
  251. #else
  252. #error "Fix this"
  253. #endif
  254. //
  255. // See if he has room for the descriptor string.
  256. //
  257. if(ulBufferSize < (IFE_FIXED_SIZE + strlen(VENDOR_DESCRIPTION_STRING)))
  258. {
  259. Trace(TUNN, ERROR,
  260. ("IpIpQueryInfo: Buffer size %d too small for VENDOR string\n",
  261. ulBufferSize));
  262. //
  263. // Not enough room to copy the desc. string.
  264. //
  265. *puiSize = IFE_FIXED_SIZE;
  266. return TDI_BUFFER_OVERFLOW;
  267. }
  268. #if NDISBUFFERISMDL
  269. nStatus = TdiCopyBufferToMdl(VENDOR_DESCRIPTION_STRING,
  270. 0,
  271. strlen(VENDOR_DESCRIPTION_STRING),
  272. (PMDL)pnbBuffer,
  273. ulOffset,
  274. &ulOffset);
  275. #else
  276. #error "Fix this"
  277. #endif
  278. *puiSize = IFE_FIXED_SIZE + strlen(VENDOR_DESCRIPTION_STRING);
  279. return TDI_SUCCESS;
  280. }
  281. INT
  282. IpIpSetRequest(
  283. PVOID pvContext,
  284. NDIS_OID Oid,
  285. UINT Type
  286. )
  287. {
  288. return NDIS_STATUS_SUCCESS;
  289. }
  290. INT
  291. IpIpSetInfo(
  292. IN PVOID pvContext,
  293. IN TDIObjectID *pTdiObjId,
  294. IN PVOID pvBuffer,
  295. IN UINT uiSize
  296. )
  297. {
  298. PTUNNEL pTunnel;
  299. INT iStatus;
  300. IFEntry *pIFE;
  301. DWORD dwEntity;
  302. DWORD dwInstance;
  303. KIRQL kiIrql;
  304. pIFE = (IFEntry *)pvBuffer;
  305. pTunnel = (PTUNNEL)pvContext;
  306. dwEntity = pTdiObjId->toi_entity.tei_entity;
  307. dwInstance = pTdiObjId->toi_entity.tei_instance;
  308. //
  309. // Might be able to handle this.
  310. //
  311. if((dwEntity isnot IF_ENTITY) or
  312. (dwInstance isnot pTunnel->dwIfInstance))
  313. {
  314. return TDI_INVALID_REQUEST;
  315. }
  316. //
  317. // It's for the I/F level, see if it's for the statistics.
  318. //
  319. if (pTdiObjId->toi_class isnot INFO_CLASS_PROTOCOL)
  320. {
  321. Trace(TUNN, INFO,
  322. ("IpIpSetInfo: toi_class is wrong 0x%x\n",
  323. pTdiObjId->toi_class));
  324. return TDI_INVALID_PARAMETER;
  325. }
  326. if (pTdiObjId->toi_id isnot IF_MIB_STATS_ID)
  327. {
  328. Trace(TUNN, INFO,
  329. ("IpIpSetInfo: toi_id 0x%x is not MIB_STATS\n",
  330. pTdiObjId->toi_id));
  331. return TDI_INVALID_PARAMETER;
  332. }
  333. //
  334. // It's for the stats. Make sure it's a valid size.
  335. //
  336. if(uiSize < IFE_FIXED_SIZE)
  337. {
  338. Trace(TUNN, ERROR,
  339. ("IpIpSetInfo: Buffer size %d too small\n",
  340. uiSize));
  341. return TDI_BUFFER_TOO_SMALL;
  342. }
  343. //
  344. // Good size
  345. //
  346. RtAcquireSpinLock(&(pTunnel->rlLock),
  347. &kiIrql);
  348. switch(pIFE->if_adminstatus)
  349. {
  350. case IF_STATUS_UP:
  351. {
  352. iStatus = TDI_SUCCESS;
  353. if(GetAdminState(pTunnel) is IF_STATUS_UP)
  354. {
  355. //
  356. // Nothing to do
  357. //
  358. break;
  359. }
  360. pTunnel->dwAdminState =
  361. (pTunnel->dwAdminState & 0xFFFF0000) | IF_STATUS_UP;
  362. if(pTunnel->dwAdminState & TS_ADDRESS_PRESENT)
  363. {
  364. //
  365. // This will set the oper. status
  366. //
  367. UpdateMtuAndReachability(pTunnel);
  368. }
  369. break;
  370. }
  371. case IF_STATUS_DOWN:
  372. {
  373. iStatus = TDI_SUCCESS;
  374. if(GetAdminState(pTunnel) is IF_STATUS_DOWN)
  375. {
  376. //
  377. // Nothing to do
  378. //
  379. break;
  380. }
  381. pTunnel->dwAdminState =
  382. (pTunnel->dwAdminState & 0xFFFF0000) | IF_STATUS_DOWN;
  383. pTunnel->dwOperState = IF_OPER_STATUS_NON_OPERATIONAL;
  384. break;
  385. }
  386. case IF_STATUS_TESTING:
  387. {
  388. //
  389. // Not supported, just return SUCCESS
  390. //
  391. iStatus = TDI_SUCCESS;
  392. break;
  393. }
  394. default:
  395. {
  396. iStatus = TDI_INVALID_PARAMETER;
  397. break;
  398. }
  399. }
  400. RtReleaseSpinLock(&(pTunnel->rlLock),
  401. kiIrql);
  402. return iStatus;
  403. }
  404. INT
  405. IpIpGetEntityList(
  406. IN PVOID pvContext,
  407. IN TDIEntityID *pTdiEntityList,
  408. IN PUINT puiCount
  409. )
  410. {
  411. PTUNNEL pTunnel;
  412. UINT uiEntityCount;
  413. UINT uiMyIFBase;
  414. UINT i;
  415. TDIEntityID *pTdiIFEntity;
  416. KIRQL kiIrql;
  417. pTunnel = (PTUNNEL)pvContext;
  418. //
  419. // Walk down the list, looking for existing IF entities, and
  420. // adjust our base instance accordingly.
  421. //
  422. uiMyIFBase = 0;
  423. pTdiIFEntity = NULL;
  424. for(i = 0;
  425. i < *puiCount;
  426. i++, pTdiEntityList++)
  427. {
  428. if(pTdiEntityList->tei_entity is IF_ENTITY)
  429. {
  430. //
  431. // if we are already on the list remember our entity item
  432. // o/w find an instance # for us.
  433. //
  434. if((pTdiEntityList->tei_instance is pTunnel->dwIfInstance) and
  435. (pTdiEntityList->tei_instance isnot INVALID_ENTITY_INSTANCE))
  436. {
  437. //
  438. // Matched our instance
  439. //
  440. pTdiIFEntity = pTdiEntityList;
  441. break;
  442. }
  443. else
  444. {
  445. //
  446. // Take the max of the two
  447. //
  448. uiMyIFBase = uiMyIFBase > (pTdiEntityList->tei_instance + 1)?
  449. uiMyIFBase : (pTdiEntityList->tei_instance + 1);
  450. }
  451. }
  452. }
  453. RtAcquireSpinLock(&(pTunnel->rlLock),
  454. &kiIrql);
  455. if(pTdiIFEntity is NULL )
  456. {
  457. //
  458. // we are not on the list.
  459. // make sure we have the room for it.
  460. //
  461. if (*puiCount >= MAX_TDI_ENTITIES)
  462. {
  463. return FALSE;
  464. }
  465. pTunnel->dwIfInstance = uiMyIFBase;
  466. //
  467. // Now fill it in.
  468. //
  469. pTdiEntityList->tei_entity = IF_ENTITY;
  470. pTdiEntityList->tei_instance = uiMyIFBase;
  471. (*puiCount)++;
  472. }
  473. else
  474. {
  475. if(pTunnel->dwAdminState & TS_DELETING)
  476. {
  477. pTunnel->dwIfInstance = INVALID_ENTITY_INSTANCE;
  478. pTdiEntityList->tei_instance = INVALID_ENTITY_INSTANCE;
  479. }
  480. }
  481. RtReleaseSpinLock(&(pTunnel->rlLock),
  482. kiIrql);
  483. return TRUE;
  484. }
  485. INT
  486. IpIpBindAdapter(
  487. IN PNDIS_STATUS pnsRetStatus,
  488. IN NDIS_HANDLE nhBindContext,
  489. IN PNDIS_STRING pnsAdapterName,
  490. IN PVOID pvSS1,
  491. IN PVOID pvSS2
  492. )
  493. /*++
  494. Routine Description
  495. Called by IP to bind an adapter.
  496. Locks
  497. The routine acquires the global adapter list lock, so it is not
  498. PAGEABLE.
  499. Arguments
  500. Return Value
  501. --*/
  502. {
  503. #if 0
  504. DWORD fFlags;
  505. PTUNNEL pNewTunnel; // Newly created adapter block.
  506. UNICODE_STRING usTempUnicodeString;
  507. NTSTATUS nStatus;
  508. KIRQL irql;
  509. #if DBG
  510. ANSI_STRING asTempAnsiString;
  511. #endif
  512. TraceEnter(TUNN, "IpIpBindAdapter");
  513. //
  514. // All our adapter names must be upper case
  515. //
  516. //
  517. // Increase length so we have space to null terminate
  518. //
  519. pnsAdapterName->Length += sizeof(WCHAR);
  520. //
  521. // Allocate memory for the string, instead of passing TRUE to RtlUpcase
  522. // because that allocates from the heap
  523. //
  524. usTempUnicodeString.Buffer = RtAllocate(NonPagedPool,
  525. pnsAdapterName->Length,
  526. STRING_TAG);
  527. if(usTempUnicodeString.Buffer is NULL)
  528. {
  529. Trace(TUNN, ERROR,
  530. ("IpIpBindAdapter: Unable to allocate %d bytes\n",
  531. pnsAdapterName->Length));
  532. return STATUS_INSUFFICIENT_RESOURCES;
  533. }
  534. usTempUnicodeString.MaximumLength = pnsAdapterName->Length;
  535. #if DBG
  536. asTempAnsiString.Buffer = RtAllocate(NonPagedPool,
  537. (pnsAdapterName->Length + 1)/2,
  538. STRING_TAG);
  539. if(asTempAnsiString.Buffer is NULL)
  540. {
  541. Trace(TUNN, ERROR,
  542. ("IpIpBindAdapter: Unable to allocate %d bytes\n",
  543. (pnsAdapterName->Length + 1)/2));
  544. RtFree(usTempUnicodeString.Buffer);
  545. usTempUnicodeString.MaximumLength = 0;
  546. return STATUS_INSUFFICIENT_RESOURCES;
  547. }
  548. asTempAnsiString.MaximumLength = (pnsAdapterName->Length + 1)/2;
  549. #endif
  550. RtlUpcaseUnicodeString(&usTempUnicodeString,
  551. pnsAdapterName,
  552. FALSE);
  553. pnsAdapterName->Length -= sizeof(WCHAR);
  554. //
  555. // Null terminate the temp string
  556. //
  557. usTempUnicodeString.Buffer[usTempUnicodeString.MaximumLength/sizeof(WCHAR) - 1] = UNICODE_NULL;
  558. #if DBG
  559. //
  560. // This must be run at PASSIVE
  561. //
  562. RtlUnicodeStringToAnsiString(&asTempAnsiString,
  563. &usTempUnicodeString,
  564. FALSE);
  565. asTempAnsiString.Length -= sizeof(CHAR);
  566. #endif
  567. usTempUnicodeString.Length -= sizeof(WCHAR);
  568. Trace(TUNN, INFO,
  569. ("IpIpBindAdapter: IP called to bind to adapter %S\n",
  570. usTempUnicodeString.Buffer));
  571. //
  572. // Lock the TUNNEL list - since we may be adding
  573. //
  574. EnterWriter(&g_rwlTunnelLock,
  575. &irql);
  576. //
  577. // Since we dont NdisOpenAdapter on the bindings we may
  578. // get duplicates. Check if this has already been indicated
  579. //
  580. if(IsBindingPresent(&usTempUnicodeString))
  581. {
  582. ExitWriter(&g_rwlTunnelLock,
  583. irql);
  584. Trace(TUNN, WARN,
  585. ("IpIpBindAdapter: Adapter %S already present\n",
  586. usTempUnicodeString.Buffer));
  587. *pnsRetStatus = NDIS_STATUS_SUCCESS;
  588. RtFree(usTempUnicodeString.Buffer);
  589. usTempUnicodeString.MaximumLength = 0;
  590. #if DBG
  591. RtFree(asTempAnsiString.Buffer);
  592. asTempAnsiString.MaximumLength = 0;
  593. #endif
  594. TraceLeave(TUNN, "IpIpBindAdapter");
  595. return (int) TRUE;
  596. }
  597. pNewTunnel = NULL;
  598. #if DBG
  599. nStatus = CreateTunnel(&usTempUnicodeString,
  600. &pNewTunnel,
  601. &asTempAnsiString);
  602. #else
  603. nStatus = CreateTunnel(&usTempUnicodeString,
  604. &pNewTunnel);
  605. #endif
  606. ExitWriter(&g_rwlTunnelLock,
  607. irql);
  608. #if DBG
  609. RtFree(asTempAnsiString.Buffer);
  610. asTempAnsiString.MaximumLength = 0;
  611. #endif
  612. if(nStatus isnot STATUS_SUCCESS)
  613. {
  614. Trace(TUNN, ERROR,
  615. ("IpIpBindAdapter: CreateTunnel failed with error %x for %w\n",
  616. nStatus,
  617. usTempUnicodeString.Buffer));
  618. *pnsRetStatus = NDIS_STATUS_FAILURE;
  619. RtFree(usTempUnicodeString.Buffer);
  620. usTempUnicodeString.MaximumLength = 0;
  621. TraceLeave(TUNN, "IpIpBindAdapter");
  622. return (int) TRUE;
  623. }
  624. InterlockedIncrement(&g_ulNumTunnels);
  625. //
  626. // The tunnel has been created with a ref count of 2
  627. //
  628. RtAssert(pNewTunnel);
  629. //
  630. // At this point the TUNNEL is ref counted , but not locked
  631. // We add it to IP (and keep a ref count because IP has a pointer to
  632. // the structure)
  633. //
  634. if(AddInterfaceToIP(pNewTunnel,
  635. &usTempUnicodeString,
  636. pvSS1,
  637. pvSS2) isnot STATUS_SUCCESS)
  638. {
  639. Trace(TUNN, ERROR,
  640. ("IpIpBindAdapter: Add interface to IP failed for adapter %S\n",
  641. usTempUnicodeString.Buffer));
  642. //
  643. // Remove the TUNNEL from the list
  644. //
  645. EnterWriter(&g_rwlTunnelLock,
  646. &irql);
  647. RemoveEntryList(&(pNewTunnel->leTunnelLink));
  648. ExitWriter(&g_rwlTunnelLock,
  649. irql);
  650. //
  651. // Since one ref count was kept because the list had a pointer,
  652. // deref it once
  653. //
  654. DereferenceTunnel(pNewTunnel);
  655. *pnsRetStatus = NDIS_STATUS_FAILURE;
  656. }
  657. else
  658. {
  659. //
  660. // We are done with the
  661. //
  662. *pnsRetStatus = NDIS_STATUS_SUCCESS;
  663. //
  664. // The tunnel was added to IP, so increment the ref count
  665. //
  666. ReferenceTunnel(pNewTunnel);
  667. Trace(TUNN, TRACE,
  668. ("IpIpBindAdapter: Successfully bound to adapter %ws\n",
  669. usTempUnicodeString.Buffer));
  670. }
  671. //
  672. // This bit of code is done with the TUNNEL.
  673. // If everything succeeded, the the current refcount is 3
  674. // One is because it is on the TUNNEL list, the second because it
  675. // is with IP and ofcourse the third because of this code
  676. // So we deref it here and the refcount is 2, as it should be
  677. //
  678. // If the add to IP failed, then the refcount is 1 (because we would
  679. // never incremented it for adding it to IP, and RemoveTunnel() would
  680. // have decremented the refcount by 1
  681. // So derefing it here will free the memory
  682. //
  683. DereferenceTunnel(pNewTunnel);
  684. RtFree(usTempUnicodeString.Buffer);
  685. usTempUnicodeString.MaximumLength = 0;
  686. TraceLeave(TUNN, "IpIpBindAdapter");
  687. return (int) TRUE;
  688. }
  689. NTSTATUS
  690. AddInterfaceToIP(
  691. IN PTUNNEL pTunnel,
  692. IN PNDIS_STRING pnsName,
  693. IN PVOID pvSystemSpecific1,
  694. IN PVOID pvSystemSpecific2
  695. )
  696. /*++
  697. Routine Description
  698. Adds an interface to IP. We add one interface for every adapter
  699. Code is pageable hence must be called at PASSIVE
  700. Locks
  701. The TUNNEL must be ref counted BUT NOT LOCKED
  702. Arguments
  703. Return Value
  704. --*/
  705. {
  706. LLIPBindInfo BindInfo;
  707. IP_STATUS IPStatus;
  708. NDIS_STRING IPConfigName = NDIS_STRING_CONST("IPConfig");
  709. NDIS_STRING nsRemoteAddrName = NDIS_STRING_CONST("RemoteAddress");
  710. NDIS_STRING nsLocalAddrName = NDIS_STRING_CONST("LocalAddress");
  711. NDIS_STATUS nsStatus;
  712. NDIS_HANDLE nhConfigHandle;
  713. PNDIS_CONFIGURATION_PARAMETER pParam;
  714. PAGED_CODE();
  715. TraceEnter(TUNN, "AddInterfaceToIP");
  716. //
  717. // Open the key for this "adapter"
  718. //
  719. NdisOpenProtocolConfiguration(&nsStatus,
  720. &nhConfigHandle,
  721. (PNDIS_STRING)pvSystemSpecific1);
  722. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  723. {
  724. Trace(TUNN, ERROR,
  725. ("AddInterfaceToIP: Unable to Open Protocol Configuration %x\n",
  726. nsStatus));
  727. TraceLeave(TUNN, "AddInterfaceToIP");
  728. return nsStatus;
  729. }
  730. //
  731. // Read in the IPConfig string. If this is not present,
  732. // fail this call.
  733. //
  734. NdisReadConfiguration(&nsStatus,
  735. &pParam,
  736. nhConfigHandle,
  737. &IPConfigName,
  738. NdisParameterMultiString);
  739. if((nsStatus isnot NDIS_STATUS_SUCCESS) or
  740. (pParam->ParameterType isnot NdisParameterMultiString))
  741. {
  742. Trace(TUNN, ERROR,
  743. ("AddInterfaceToIP: Unable to Read Configuration. Status %x \n",
  744. nsStatus));
  745. NdisCloseConfiguration(nhConfigHandle);
  746. TraceLeave(TUNN, "AddInterfaceToIP");
  747. return STATUS_UNSUCCESSFUL;
  748. }
  749. //
  750. // We add one interface per adapter for IP
  751. //
  752. BindInfo.lip_context = pTunnel;
  753. BindInfo.lip_mss = pTunnel->ulMtu;
  754. BindInfo.lip_speed = DEFAULT_SPEED;
  755. //
  756. // Our "ARP" header is an IPHeader
  757. //
  758. BindInfo.lip_txspace = sizeof(IPHeader);
  759. BindInfo.lip_transmit = IpIpSend;
  760. BindInfo.lip_transfer = IpIpTransferData;
  761. BindInfo.lip_returnPkt = IpIpReturnPacket;
  762. BindInfo.lip_close = IpIpCloseAdapter;
  763. BindInfo.lip_addaddr = IpIpAddAddress;
  764. BindInfo.lip_deladdr = IpIpDeleteAddress;
  765. BindInfo.lip_invalidate = IpIpInvalidateRce;
  766. BindInfo.lip_open = IpIpOpenAdapter;
  767. BindInfo.lip_qinfo = IpIpQueryInfo;
  768. BindInfo.lip_setinfo = IpIpSetInfo;
  769. BindInfo.lip_getelist = IpIpGetEntityList;
  770. BindInfo.lip_flags = LIP_COPY_FLAG | LIP_NOIPADDR_FLAG | LIP_P2P_FLAG;
  771. BindInfo.lip_addrlen = ARP_802_ADDR_LENGTH;
  772. BindInfo.lip_addr = pTunnel->rgbyHardwareAddr;
  773. BindInfo.lip_dowakeupptrn = NULL;
  774. BindInfo.lip_pnpcomplete = NULL;
  775. BindInfo.lip_OffloadFlags = 0;
  776. BindInfo.lip_arpflushate = NULL;
  777. BindInfo.lip_arpflushallate = NULL;
  778. BindInfo.lip_setndisrequest = NULL;
  779. IPStatus = g_pfnIpAddInterface(pnsName,
  780. &(pParam->ParameterData.StringData),
  781. NULL,
  782. pTunnel,
  783. IpIpDynamicRegister,
  784. &BindInfo,
  785. 0);
  786. NdisCloseConfiguration(nhConfigHandle);
  787. if(IPStatus isnot IP_SUCCESS)
  788. {
  789. //
  790. // NB: freeing of resources not done.
  791. //
  792. Trace(TUNN, ERROR,
  793. ("AddInterfaceToIP: IPAddInterface failed for %w\n",
  794. pTunnel->usBindName.Buffer));
  795. TraceLeave(TUNN, "AddInterfaceToIP");
  796. return STATUS_UNSUCCESSFUL;
  797. }
  798. Trace(TUNN, TRACE,
  799. ("IPAddInterface succeeded for adapter %w\n",
  800. pTunnel->usBindName.Buffer));
  801. TraceLeave(TUNN, "AddInterfaceToIP");
  802. #endif // 0
  803. return STATUS_SUCCESS;
  804. }
  805. NTSTATUS
  806. IpIpCreateAdapter(
  807. IN PIPINIP_CREATE_TUNNEL pCreateInfo,
  808. IN USHORT usKeyLength,
  809. OUT PDWORD pdwIfIndex
  810. )
  811. /*++
  812. Routine Description
  813. Our dynamic interface creation routine. Looks a bit like a bindadapter
  814. call
  815. Locks
  816. The routine acquires the global adapter list lock, so it is not
  817. PAGEABLE.
  818. Arguments
  819. pCreateInfo Info from the ioctl
  820. usKeyLength Length in bytes of the pwszKeyName (without the NULL)
  821. Return Value
  822. STATUS_OBJECT_NAME_EXISTS
  823. --*/
  824. {
  825. DWORD fFlags;
  826. PTUNNEL pNewTunnel;
  827. UNICODE_STRING usTempUnicodeString;
  828. NTSTATUS nStatus;
  829. KIRQL irql;
  830. USHORT usOldLength;
  831. PWCHAR pwszBuffer;
  832. #if DBG
  833. ANSI_STRING asTempAnsiString;
  834. #endif
  835. TraceEnter(TUNN, "IpIpCreateAdapter");
  836. nStatus = RtlStringFromGUID(&(pCreateInfo->Guid),
  837. &usTempUnicodeString);
  838. if(nStatus isnot STATUS_SUCCESS)
  839. {
  840. Trace(TUNN, ERROR,
  841. ("IpIpCreateAdapter: Unable to create GUID\n"));
  842. TraceLeave(TUNN, "IpIpCreateAdapter");
  843. return nStatus;
  844. }
  845. //
  846. // Now create a non-paged buffer to store the GUID string. This is because
  847. // the Rtl routines allocate memory from heap
  848. //
  849. usOldLength = usTempUnicodeString.Length;
  850. RtAssert((usOldLength % sizeof(WCHAR)) == 0);
  851. pwszBuffer = RtAllocate(NonPagedPool,
  852. usOldLength + sizeof(WCHAR),
  853. STRING_TAG);
  854. if(pwszBuffer is NULL)
  855. {
  856. Trace(TUNN, ERROR,
  857. ("IpIpCreateAdapter: Unable to allocate %d bytes\n",
  858. usOldLength + sizeof(WCHAR)));
  859. RtlFreeUnicodeString(&usTempUnicodeString);
  860. TraceLeave(TUNN, "IpIpCreateAdapter");
  861. return STATUS_INSUFFICIENT_RESOURCES;
  862. }
  863. RtlCopyMemory(pwszBuffer,
  864. usTempUnicodeString.Buffer,
  865. usOldLength);
  866. //
  867. // Zero out the last bit
  868. //
  869. pwszBuffer[usOldLength/sizeof(WCHAR)] = UNICODE_NULL;
  870. //
  871. // Now free the old string, make usTempUnicodeString point to this
  872. // non paged buffer
  873. //
  874. RtlFreeUnicodeString(&usTempUnicodeString);
  875. usTempUnicodeString.Buffer = pwszBuffer;
  876. usTempUnicodeString.MaximumLength = usOldLength + sizeof(WCHAR);
  877. usTempUnicodeString.Length = usOldLength;
  878. //
  879. // Increase the length of the unicode string so that
  880. // the ansi string is null terminated
  881. //
  882. usTempUnicodeString.Length += sizeof(WCHAR);
  883. #if DBG
  884. //
  885. // This must be run at PASSIVE
  886. //
  887. asTempAnsiString.Buffer = RtAllocate(NonPagedPool,
  888. usTempUnicodeString.MaximumLength,
  889. STRING_TAG);
  890. if(asTempAnsiString.Buffer is NULL)
  891. {
  892. Trace(TUNN, ERROR,
  893. ("IpIpCreateAdapter: Unable to allocate %d bytes\n",
  894. usTempUnicodeString.MaximumLength));
  895. RtFree(usTempUnicodeString.Buffer);
  896. usTempUnicodeString.Buffer = NULL;
  897. usTempUnicodeString.MaximumLength = 0;
  898. usTempUnicodeString.Length = 0;
  899. TraceLeave(TUNN, "IpIpCreateAdapter");
  900. return STATUS_INSUFFICIENT_RESOURCES;
  901. }
  902. RtlUnicodeStringToAnsiString(&asTempAnsiString,
  903. &usTempUnicodeString,
  904. FALSE);
  905. asTempAnsiString.Length -= sizeof(CHAR);
  906. #endif
  907. usTempUnicodeString.Length -= sizeof(WCHAR);
  908. Trace(TUNN, INFO,
  909. ("IpIpCreateAdapter: IP called to bind to adapter %S\n",
  910. usTempUnicodeString.Buffer));
  911. //
  912. // Lock the TUNNEL list - since we may be adding
  913. //
  914. EnterWriter(&g_rwlTunnelLock,
  915. &irql);
  916. //
  917. // Make sure this is not a duplicate
  918. //
  919. if(IsBindingPresent(&usTempUnicodeString))
  920. {
  921. ExitWriter(&g_rwlTunnelLock,
  922. irql);
  923. Trace(TUNN, WARN,
  924. ("IpIpCreateAdapter: Adapter %S already present\n",
  925. usTempUnicodeString.Buffer));
  926. #if DBG
  927. RtFree(asTempAnsiString.Buffer);
  928. asTempAnsiString.Buffer = NULL;
  929. asTempAnsiString.MaximumLength = 0;
  930. asTempAnsiString.Length = 0;
  931. #endif
  932. RtFree(usTempUnicodeString.Buffer);
  933. usTempUnicodeString.Buffer = NULL;
  934. usTempUnicodeString.MaximumLength = 0;
  935. usTempUnicodeString.Length = 0;
  936. TraceLeave(TUNN, "IpIpCreateAdapter");
  937. return STATUS_OBJECT_NAME_EXISTS;
  938. }
  939. pNewTunnel = NULL;
  940. #if DBG
  941. nStatus = CreateTunnel(&usTempUnicodeString,
  942. &pNewTunnel,
  943. &asTempAnsiString);
  944. #else
  945. nStatus = CreateTunnel(&usTempUnicodeString,
  946. &pNewTunnel);
  947. #endif
  948. ExitWriter(&g_rwlTunnelLock,
  949. irql);
  950. #if DBG
  951. RtFree(asTempAnsiString.Buffer);
  952. asTempAnsiString.Buffer = NULL;
  953. asTempAnsiString.MaximumLength = 0;
  954. asTempAnsiString.Length = 0;
  955. #endif
  956. if(nStatus isnot STATUS_SUCCESS)
  957. {
  958. Trace(TUNN, ERROR,
  959. ("IpIpCreateAdapter: CreateTunnel failed with error %x for %w\n",
  960. nStatus,
  961. usTempUnicodeString.Buffer));
  962. RtFree(usTempUnicodeString.Buffer);
  963. usTempUnicodeString.Buffer = NULL;
  964. usTempUnicodeString.MaximumLength = 0;
  965. usTempUnicodeString.Length = 0;
  966. TraceLeave(TUNN, "IpIpCreateAdapter");
  967. return nStatus;
  968. }
  969. InterlockedIncrement(&g_ulNumTunnels);
  970. //
  971. // The tunnel has been created with a ref count of 2
  972. //
  973. RtAssert(pNewTunnel);
  974. //
  975. // At this point the TUNNEL is ref counted , but not locked
  976. // We add it to IP (and keep a ref count because IP has a pointer to
  977. // the structure)
  978. //
  979. nStatus = AddInterfaceToIP2(pNewTunnel,
  980. &usTempUnicodeString);
  981. if(nStatus isnot STATUS_SUCCESS)
  982. {
  983. Trace(TUNN, ERROR,
  984. ("IpIpCreateAdapter: Add interface to IP failed for adapter %S\n",
  985. usTempUnicodeString.Buffer));
  986. //
  987. // Remove the TUNNEL from the list
  988. //
  989. EnterWriter(&g_rwlTunnelLock,
  990. &irql);
  991. RemoveEntryList(&(pNewTunnel->leTunnelLink));
  992. ExitWriter(&g_rwlTunnelLock,
  993. irql);
  994. //
  995. // Since one ref count was kept because the list had a pointer,
  996. // deref it once
  997. //
  998. DereferenceTunnel(pNewTunnel);
  999. }
  1000. else
  1001. {
  1002. //
  1003. // The tunnel was added to IP, so increment the ref count
  1004. //
  1005. ReferenceTunnel(pNewTunnel);
  1006. Trace(TUNN, TRACE,
  1007. ("IpIpCreateAdapter: Successfully bound to adapter %ws\n",
  1008. usTempUnicodeString.Buffer));
  1009. }
  1010. *pdwIfIndex = pNewTunnel->dwIfIndex;
  1011. //
  1012. // This bit of code is done with the TUNNEL.
  1013. // If everything succeeded, the the current refcount is 3
  1014. // One is because it is on the TUNNEL list, the second because it
  1015. // is with IP and ofcourse the third because of this code
  1016. // So we deref it here and the refcount is 2, as it should be
  1017. //
  1018. // If the add to IP failed, then the refcount is 1 (because we would
  1019. // never incremented it for adding it to IP, and RemoveTunnel() would
  1020. // have decremented the refcount by 1
  1021. // So derefing it here will free the memory
  1022. //
  1023. DereferenceTunnel(pNewTunnel);
  1024. RtFree(usTempUnicodeString.Buffer);
  1025. usTempUnicodeString.Buffer = NULL;
  1026. usTempUnicodeString.MaximumLength = 0;
  1027. usTempUnicodeString.Length = 0;
  1028. TraceLeave(TUNN, "IpIpCreateAdapter");
  1029. return nStatus;
  1030. }
  1031. NTSTATUS
  1032. AddInterfaceToIP2(
  1033. IN PTUNNEL pTunnel,
  1034. IN PNDIS_STRING pnsName
  1035. )
  1036. /*++
  1037. Routine Description
  1038. Adds an interface to IP. We add one interface for every adapter
  1039. Code is pageable hence must be called at PASSIVE
  1040. Locks
  1041. The TUNNEL must be ref counted BUT NOT LOCKED
  1042. Arguments
  1043. Return Value
  1044. --*/
  1045. {
  1046. LLIPBindInfo BindInfo;
  1047. IP_STATUS IPStatus;
  1048. NDIS_STRING nsIPConfigKey, nsIfName;
  1049. NDIS_STATUS nsStatus;
  1050. ULONG ulKeyLen, ulPrefixLen;
  1051. PWCHAR pwszKeyBuffer, pwszNameBuffer;
  1052. PAGED_CODE();
  1053. TraceEnter(TUNN, "AddInterfaceToIP2");
  1054. //
  1055. // Fake the key for the adapter
  1056. //
  1057. ulPrefixLen = wcslen(TCPIP_INTERFACES_KEY);
  1058. ulKeyLen = pnsName->Length + ((ulPrefixLen + 1) * sizeof(WCHAR));
  1059. pwszKeyBuffer = RtAllocate(NonPagedPool,
  1060. ulKeyLen,
  1061. TUNNEL_TAG);
  1062. if(pwszKeyBuffer is NULL)
  1063. {
  1064. Trace(TUNN, ERROR,
  1065. ("AddInterfaceToIP2: Couldnt allocate %d bytes of paged pool\n",
  1066. ulKeyLen));
  1067. return STATUS_INSUFFICIENT_RESOURCES;
  1068. }
  1069. RtlZeroMemory(pwszKeyBuffer,
  1070. ulKeyLen);
  1071. nsIPConfigKey.MaximumLength = (USHORT)ulKeyLen;
  1072. nsIPConfigKey.Length = (USHORT)ulKeyLen - sizeof(WCHAR);
  1073. nsIPConfigKey.Buffer = pwszKeyBuffer;
  1074. //
  1075. // Copy over the prefix
  1076. //
  1077. RtlCopyMemory(pwszKeyBuffer,
  1078. TCPIP_INTERFACES_KEY,
  1079. ulPrefixLen * sizeof(WCHAR));
  1080. //
  1081. // Cat the name
  1082. //
  1083. RtlCopyMemory(&(pwszKeyBuffer[ulPrefixLen]),
  1084. pnsName->Buffer,
  1085. pnsName->Length);
  1086. //
  1087. // TCPIP expects the name of the interface to be of the type \Device\<Name>
  1088. // The name in pnsName is only <Name>, so create a new string
  1089. //
  1090. ulPrefixLen = wcslen(TCPIP_IF_PREFIX);
  1091. ulKeyLen = pnsName->Length + ((ulPrefixLen + 1) * sizeof(WCHAR));
  1092. pwszNameBuffer = RtAllocate(NonPagedPool,
  1093. ulKeyLen,
  1094. TUNNEL_TAG);
  1095. if(pwszNameBuffer is NULL)
  1096. {
  1097. Trace(TUNN, ERROR,
  1098. ("AddInterfaceToIP2: Couldnt allocate %d bytes for name\n",
  1099. ulKeyLen));
  1100. return STATUS_INSUFFICIENT_RESOURCES;
  1101. }
  1102. RtlZeroMemory(pwszNameBuffer,
  1103. ulKeyLen);
  1104. nsIfName.MaximumLength = (USHORT)ulKeyLen;
  1105. nsIfName.Length = (USHORT)ulKeyLen - sizeof(WCHAR);
  1106. nsIfName.Buffer = pwszNameBuffer;
  1107. //
  1108. // Start with \Device\
  1109. //
  1110. RtlCopyMemory(pwszNameBuffer,
  1111. TCPIP_IF_PREFIX,
  1112. ulPrefixLen * sizeof(WCHAR));
  1113. //
  1114. // Cat the name
  1115. //
  1116. RtlCopyMemory(&(pwszNameBuffer[ulPrefixLen]),
  1117. pnsName->Buffer,
  1118. pnsName->Length);
  1119. RtlZeroMemory(&BindInfo,
  1120. sizeof(LLIPBindInfo));
  1121. //
  1122. // We add one interface per adapter for IP
  1123. //
  1124. BindInfo.lip_context = pTunnel;
  1125. BindInfo.lip_mss = pTunnel->ulMtu;
  1126. BindInfo.lip_speed = DEFAULT_SPEED;
  1127. //
  1128. // Our "ARP" header is an IPHeader
  1129. //
  1130. BindInfo.lip_txspace = sizeof(IPHeader);
  1131. BindInfo.lip_transmit = IpIpSend;
  1132. BindInfo.lip_transfer = IpIpTransferData;
  1133. BindInfo.lip_returnPkt = IpIpReturnPacket;
  1134. BindInfo.lip_close = IpIpCloseAdapter;
  1135. BindInfo.lip_addaddr = IpIpAddAddress;
  1136. BindInfo.lip_deladdr = IpIpDeleteAddress;
  1137. BindInfo.lip_invalidate = IpIpInvalidateRce;
  1138. BindInfo.lip_open = IpIpOpenAdapter;
  1139. BindInfo.lip_qinfo = IpIpQueryInfo;
  1140. BindInfo.lip_setinfo = IpIpSetInfo;
  1141. BindInfo.lip_getelist = IpIpGetEntityList;
  1142. BindInfo.lip_flags = LIP_NOIPADDR_FLAG | LIP_P2P_FLAG | LIP_COPY_FLAG;
  1143. BindInfo.lip_addrlen = ARP_802_ADDR_LENGTH;
  1144. BindInfo.lip_addr = pTunnel->rgbyHardwareAddr;
  1145. BindInfo.lip_dowakeupptrn = NULL;
  1146. BindInfo.lip_pnpcomplete = NULL;
  1147. BindInfo.lip_setndisrequest = IpIpSetRequest;
  1148. IPStatus = g_pfnIpAddInterface(&nsIfName,
  1149. NULL,
  1150. &nsIPConfigKey,
  1151. NULL,
  1152. pTunnel,
  1153. IpIpDynamicRegister,
  1154. &BindInfo,
  1155. 0,
  1156. IF_TYPE_TUNNEL,
  1157. IF_ACCESS_POINTTOPOINT,
  1158. IF_CONNECTION_DEDICATED);
  1159. RtFree(pwszKeyBuffer);
  1160. RtFree(pwszNameBuffer);
  1161. if(IPStatus isnot IP_SUCCESS)
  1162. {
  1163. Trace(TUNN, ERROR,
  1164. ("AddInterfaceToIP2: IPAddInterface failed for %w\n",
  1165. pTunnel->usBindName.Buffer));
  1166. TraceLeave(TUNN, "AddInterfaceToIP2");
  1167. return STATUS_UNSUCCESSFUL;
  1168. }
  1169. Trace(TUNN, TRACE,
  1170. ("IPAddInterface succeeded for adapter %w\n",
  1171. pTunnel->usBindName.Buffer));
  1172. TraceLeave(TUNN, "AddInterfaceToIP2");
  1173. return STATUS_SUCCESS;
  1174. }
  1175. INT
  1176. IpIpDynamicRegister(
  1177. IN PNDIS_STRING InterfaceName,
  1178. IN PVOID pvIpInterfaceContext,
  1179. IN struct _IP_HANDLERS * IpHandlers,
  1180. IN struct LLIPBindInfo * ARPBindInfo,
  1181. IN UINT uiInterfaceNumber
  1182. )
  1183. {
  1184. PTUNNEL pTunnel;
  1185. KIRQL irql;
  1186. TraceEnter(TUNN, "DynamicRegisterIp");
  1187. pTunnel = (PTUNNEL)(ARPBindInfo->lip_context);
  1188. RtAcquireSpinLock(&(pTunnel->rlLock),
  1189. &irql);
  1190. #if DBG
  1191. Trace(TUNN, INFO,
  1192. ("IP called out to dynamically register %s\n",
  1193. pTunnel->asDebugBindName.Buffer));
  1194. #endif
  1195. pTunnel->pvIpContext = pvIpInterfaceContext;
  1196. pTunnel->dwIfIndex = uiInterfaceNumber;
  1197. if(g_pfnIpRcv is NULL)
  1198. {
  1199. g_pfnIpRcv = IpHandlers->IpRcvHandler;
  1200. g_pfnIpRcvComplete = IpHandlers->IpRcvCompleteHandler;
  1201. g_pfnIpSendComplete = IpHandlers->IpTxCompleteHandler;
  1202. g_pfnIpTDComplete = IpHandlers->IpTransferCompleteHandler;
  1203. g_pfnIpStatus = IpHandlers->IpStatusHandler;
  1204. g_pfnIpRcvPkt = IpHandlers->IpRcvPktHandler;
  1205. g_pfnIpPnp = IpHandlers->IpPnPHandler;
  1206. }
  1207. RtReleaseSpinLock(&(pTunnel->rlLock),
  1208. irql);
  1209. TraceLeave(TUNN, "DynamicRegisterIp");
  1210. return TRUE;
  1211. }
  1212. BOOLEAN
  1213. IsBindingPresent(
  1214. IN PUNICODE_STRING pusBindName
  1215. )
  1216. /*++
  1217. Routine Description
  1218. Code to catch duplicate bind notifications
  1219. Locks
  1220. Must be called with the g_rwlTunnelLock held as READER
  1221. Arguments
  1222. Return Value
  1223. TRUE if an adapter with a matching name was found
  1224. FALSE otherwise
  1225. --*/
  1226. {
  1227. BOOLEAN bFound;
  1228. PTUNNEL pTunnel;
  1229. PLIST_ENTRY pleNode;
  1230. bFound = FALSE;
  1231. for(pleNode = g_leTunnelList.Flink;
  1232. pleNode != &g_leTunnelList;
  1233. pleNode = pleNode->Flink)
  1234. {
  1235. pTunnel = CONTAINING_RECORD(pleNode, TUNNEL, leTunnelLink);
  1236. if(CompareUnicodeStrings(&(pTunnel->usBindName),
  1237. pusBindName))
  1238. {
  1239. bFound = TRUE;
  1240. break;
  1241. }
  1242. }
  1243. return bFound;
  1244. }
  1245. #if DBG
  1246. NTSTATUS
  1247. CreateTunnel(
  1248. IN PNDIS_STRING pnsBindName,
  1249. OUT TUNNEL **ppNewTunnel,
  1250. IN PANSI_STRING pasAnsiName
  1251. )
  1252. #else
  1253. NTSTATUS
  1254. CreateTunnel(
  1255. IN PNDIS_STRING pnsBindName,
  1256. OUT TUNNEL **ppNewTunnel
  1257. )
  1258. #endif
  1259. /*++
  1260. Routine Description
  1261. Creates and initializes an TUNNEL when we get a bind notification
  1262. The tunnel is added to the tunnel list
  1263. Locks
  1264. Must be called with the g_rwlTunnelLock held as WRITER
  1265. Arguments
  1266. pnsBindName Name of binding
  1267. ppNewTunnel Pointer to location to return a pointer to created
  1268. tunnel
  1269. pasAnsiBindName Only in DBG versions. Binding name, as ANSI string
  1270. Return Value
  1271. STATUS_SUCCESS
  1272. STATUS_NO_MEMORY
  1273. --*/
  1274. {
  1275. DWORD dwSize;
  1276. PBYTE pbyBuffer;
  1277. PTUNNEL pTunnel;
  1278. PTDI_ADDRESS_IP pTdiIp;
  1279. TraceEnter(TUNN, "CreateTunnel");
  1280. *ppNewTunnel = NULL;
  1281. //
  1282. // The size that one needs is the size of the adapter + the length of the
  1283. // name. Add 4 to help with alignment
  1284. //
  1285. dwSize = ALIGN_UP(sizeof(TUNNEL),ULONG) +
  1286. ALIGN_UP(pnsBindName->Length + sizeof(WCHAR), ULONG);
  1287. #if DBG
  1288. //
  1289. // For debug code we also store the adapter name in ANSI
  1290. //
  1291. dwSize += ALIGN_UP((pnsBindName->Length/sizeof(WCHAR)) + sizeof(CHAR),
  1292. ULONG);
  1293. #endif
  1294. pTunnel = RtAllocate(NonPagedPool,
  1295. dwSize,
  1296. TUNNEL_TAG);
  1297. if(pTunnel is NULL)
  1298. {
  1299. Trace(TUNN, ERROR,
  1300. ("CreateTunnel: Failed to allocate memory\n"));
  1301. TraceLeave(TUNN, "CreateTunnel");
  1302. return STATUS_NO_MEMORY;
  1303. }
  1304. //
  1305. // Clear all the fields out
  1306. //
  1307. RtlZeroMemory(pTunnel,
  1308. dwSize);
  1309. //
  1310. // The Unicode name buffer starts at the end of the adapter structure.
  1311. //
  1312. pbyBuffer = (PBYTE)pTunnel + sizeof(TUNNEL);
  1313. //
  1314. // We DWORD align it for better compare/copy
  1315. //
  1316. pbyBuffer = ALIGN_UP_POINTER(pbyBuffer, ULONG);
  1317. pTunnel->usBindName.Length = pnsBindName->Length;
  1318. pTunnel->usBindName.MaximumLength = pnsBindName->Length;
  1319. pTunnel->usBindName.Buffer = (PWCHAR)(pbyBuffer);
  1320. RtlCopyMemory(pTunnel->usBindName.Buffer,
  1321. pnsBindName->Buffer,
  1322. pnsBindName->Length);
  1323. #if DBG
  1324. //
  1325. // The debug string comes after the UNICODE adapter name buffer
  1326. //
  1327. pbyBuffer = pbyBuffer + pnsBindName->Length + sizeof(WCHAR);
  1328. pbyBuffer = ALIGN_UP_POINTER(pbyBuffer, ULONG);
  1329. pTunnel->asDebugBindName.Buffer = pbyBuffer;
  1330. pTunnel->asDebugBindName.MaximumLength = pasAnsiName->MaximumLength;
  1331. pTunnel->asDebugBindName.Length = pasAnsiName->Length;
  1332. RtlCopyMemory(pTunnel->asDebugBindName.Buffer,
  1333. pasAnsiName->Buffer,
  1334. pasAnsiName->Length);
  1335. #endif
  1336. //
  1337. // Must be set to INVALID so that GetEntityList can work
  1338. //
  1339. pTunnel->dwATInstance = INVALID_ENTITY_INSTANCE;
  1340. pTunnel->dwIfInstance = INVALID_ENTITY_INSTANCE;
  1341. //
  1342. // Set the admin state to UP, but mark the interface unmapped
  1343. //
  1344. pTunnel->dwAdminState = IF_ADMIN_STATUS_UP;
  1345. pTunnel->dwOperState = IF_OPER_STATUS_NON_OPERATIONAL;
  1346. //
  1347. // This hardware index is needed to generate the Unique ID that
  1348. // DHCP uses.
  1349. // NOTE - we dont have an index so all hardware addrs will be the same
  1350. //
  1351. BuildHardwareAddrFromIndex(pTunnel->rgbyHardwareAddr,
  1352. pTunnel->dwIfIndex);
  1353. //
  1354. // Initialize the lock for the tunnel
  1355. //
  1356. RtInitializeSpinLock(&(pTunnel->rlLock));
  1357. InitRefCount(pTunnel);
  1358. pTunnel->ulMtu = DEFAULT_MTU;
  1359. //
  1360. // Initialize the TDI related stuff
  1361. //
  1362. pTunnel->tiaIpAddr.TAAddressCount = 1;
  1363. pTunnel->tiaIpAddr.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
  1364. pTunnel->tiaIpAddr.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  1365. pTunnel->tciConnInfo.UserDataLength = 0;
  1366. pTunnel->tciConnInfo.UserData = NULL;
  1367. pTunnel->tciConnInfo.OptionsLength = 0;
  1368. pTunnel->tciConnInfo.Options = NULL;
  1369. pTunnel->tciConnInfo.RemoteAddress = &(pTunnel->tiaIpAddr);
  1370. pTunnel->tciConnInfo.RemoteAddressLength = sizeof(pTunnel->tiaIpAddr);
  1371. InitBufferPool(&(pTunnel->HdrBufferPool),
  1372. HEADER_BUFFER_SIZE,
  1373. 0,
  1374. 5,
  1375. 0,
  1376. TRUE,
  1377. HEADER_TAG);
  1378. InitPacketPool(&(pTunnel->PacketPool),
  1379. PACKET_RSVD_LENGTH,
  1380. 0,
  1381. 20,
  1382. 0,
  1383. PACKET_TAG);
  1384. //
  1385. // Initialize the packet queue
  1386. //
  1387. InitializeListHead(&(pTunnel->lePacketQueueHead));
  1388. InsertHeadList(&g_leTunnelList,
  1389. &(pTunnel->leTunnelLink));
  1390. *ppNewTunnel = pTunnel;
  1391. TraceLeave(TUNN, "CreateTunnel");
  1392. return STATUS_SUCCESS;
  1393. }
  1394. VOID
  1395. DeleteTunnel(
  1396. IN PTUNNEL pTunnel
  1397. )
  1398. /*++
  1399. Routine Description
  1400. Locks
  1401. Arguments
  1402. Return Value
  1403. NO_ERROR
  1404. --*/
  1405. {
  1406. TraceEnter(TUNN, "DeleteTunnel");
  1407. Trace(TUNN, INFO,
  1408. ("DeleteTunnel: Deleting tunnel 0x%x. Index %d\n",
  1409. pTunnel, pTunnel->dwIfIndex));
  1410. if(FreeBufferPool(&(pTunnel->HdrBufferPool)) is FALSE)
  1411. {
  1412. Trace(TUNN, ERROR,
  1413. ("DeleteTunnel: Couldnt free buffer pool %x for tunnel %x\n",
  1414. pTunnel,
  1415. pTunnel->HdrBufferPool));
  1416. RtAssert(FALSE);
  1417. }
  1418. RtFree(pTunnel);
  1419. TraceLeave(TUNN, "DeleteTunnel");
  1420. }
  1421. PTUNNEL
  1422. FindTunnel(
  1423. IN PULARGE_INTEGER puliTunnelId
  1424. )
  1425. /*++
  1426. Routine Description
  1427. Routine to lookup tunnels given a TunnelId (which is a 64 bit integer
  1428. created by concatenating the RemoteEnpoint Address and LocalEndpoint
  1429. Address)
  1430. The tunnel returned is refcounted and locked
  1431. Locks
  1432. The g_rwlTunnelLock must be taken as READER
  1433. Arguments
  1434. uliTunnelId a 64 bit integer created by concatenating the RemoteEndpoint
  1435. Address and LocalEndpoint Address
  1436. Return Value
  1437. Address of the TUNNEL if found
  1438. NULL otherwise
  1439. --*/
  1440. {
  1441. PLIST_ENTRY pleNode;
  1442. PTUNNEL pTunnel;
  1443. for(pleNode = g_leTunnelList.Flink;
  1444. pleNode isnot &g_leTunnelList;
  1445. pleNode = pleNode->Flink)
  1446. {
  1447. pTunnel = CONTAINING_RECORD(pleNode,
  1448. TUNNEL,
  1449. leTunnelLink);
  1450. if(pTunnel->uliTunnelId.QuadPart is puliTunnelId->QuadPart)
  1451. {
  1452. RtAcquireSpinLockAtDpcLevel(&(pTunnel->rlLock));
  1453. ReferenceTunnel(pTunnel);
  1454. return pTunnel;
  1455. }
  1456. }
  1457. return NULL;
  1458. }
  1459. PTUNNEL
  1460. FindTunnelGivenIndex(
  1461. IN DWORD dwIfIndex
  1462. )
  1463. /*++
  1464. Routine Description
  1465. Routine to lookup tunnels given an IfIndex. This is a slow routine
  1466. The tunnel returned is refcounted - BUT NOT LOCKED
  1467. Locks
  1468. The g_rwlTunnelLock must be taken as READER
  1469. Arguments
  1470. dwIfIndex Interface Index of the tunnel
  1471. Return Value
  1472. Address of the TUNNEL if found
  1473. NULL otherwise
  1474. --*/
  1475. {
  1476. PLIST_ENTRY pleNode;
  1477. PTUNNEL pTunnel;
  1478. for(pleNode = g_leTunnelList.Flink;
  1479. pleNode isnot &g_leTunnelList;
  1480. pleNode = pleNode->Flink)
  1481. {
  1482. pTunnel = CONTAINING_RECORD(pleNode,
  1483. TUNNEL,
  1484. leTunnelLink);
  1485. if(pTunnel->dwIfIndex is dwIfIndex)
  1486. {
  1487. RtAcquireSpinLockAtDpcLevel(&(pTunnel->rlLock));
  1488. ReferenceTunnel(pTunnel);
  1489. return pTunnel;
  1490. }
  1491. }
  1492. return NULL;
  1493. }
  1494. VOID
  1495. RemoveAllTunnels(
  1496. VOID
  1497. )
  1498. /*++
  1499. Routine Description
  1500. Removes all the tunnels in the system.
  1501. We remove the tunnel from the list and delete the corresponding
  1502. interface from IP, dereferencing the tunnel twice.
  1503. If the tunnels is not being used any more, this should delete the tunnel
  1504. Locks
  1505. This is called from the Unload handler so does not need any locks
  1506. Arguments
  1507. None
  1508. Return Value
  1509. None
  1510. --*/
  1511. {
  1512. PLIST_ENTRY pleNode;
  1513. PTUNNEL pTunnel;
  1514. while(!IsListEmpty(&g_leTunnelList))
  1515. {
  1516. pleNode = RemoveHeadList(&g_leTunnelList);
  1517. pTunnel = CONTAINING_RECORD(pleNode,
  1518. TUNNEL,
  1519. leTunnelLink);
  1520. //
  1521. // Deref the tunnel once for deleting it from the list
  1522. //
  1523. DereferenceTunnel(pTunnel);
  1524. //
  1525. // Delete the interface from IP
  1526. //
  1527. g_pfnIpDeleteInterface(pTunnel->pvIpContext,
  1528. TRUE);
  1529. //
  1530. // Dereference the tunnel for deleting it from IP
  1531. //
  1532. DereferenceTunnel(pTunnel);
  1533. }
  1534. g_ulNumTunnels = 0;
  1535. }