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.

2449 lines
84 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Common transport layer address object handling code.
  14. //
  15. // This file contains the TDI address object related procedures,
  16. // including TDI open address, TDI close address, etc.
  17. //
  18. // The local address objects are stored in a hash table, protected
  19. // by the AddrObjTableLock. In order to insert or delete from the
  20. // hash table this lock must be held, as well as the address object
  21. // lock. The table lock must always be taken before the object lock.
  22. //
  23. #include "oscfg.h"
  24. #include "ndis.h"
  25. #include "tdi.h"
  26. #include "tdistat.h"
  27. #include "ip6imp.h"
  28. #include "ip6def.h"
  29. #include "route.h"
  30. #include "mld.h"
  31. #include "tdint.h"
  32. #include "tdistat.h"
  33. #include "queue.h"
  34. #include "transprt.h"
  35. #include "addr.h"
  36. #include "udp.h"
  37. #include "raw.h"
  38. #ifndef UDP_ONLY
  39. #include "tcp.h"
  40. #include "tcpconn.h"
  41. #include "tcpdeliv.h"
  42. #else
  43. #include "tcpdeb.h"
  44. #endif
  45. #include "info.h"
  46. #include "tcpcfg.h"
  47. #include "ntddip6.h" // included only to get the common socket -> kernel interface structures.
  48. extern KSPIN_LOCK DGSendReqLock;
  49. // Addess object hash table.
  50. uint AddrObjTableSize;
  51. AddrObj **AddrObjTable;
  52. AddrObj *LastAO; // one element lookup cache.
  53. KSPIN_LOCK AddrObjTableLock;
  54. KMUTEX AddrSDMutex;
  55. #define AO_HASH(a, p) (((a).u.Word[7] + (uint)(p)) % AddrObjTableSize)
  56. ushort NextUserPort = MIN_USER_PORT;
  57. RTL_BITMAP PortBitmapTcp;
  58. RTL_BITMAP PortBitmapUdp;
  59. ulong PortBitmapBufferTcp[(1 << 16) / (sizeof(ulong) * 8)];
  60. ulong PortBitmapBufferUdp[(1 << 16) / (sizeof(ulong) * 8)];
  61. //
  62. // All of the init code can be discarded.
  63. //
  64. #ifdef ALLOC_PRAGMA
  65. int InitAddr();
  66. #pragma alloc_text(INIT, InitAddr)
  67. #endif // ALLOC_PRAGMA
  68. //* ReadNextAO - Read the next AddrObj in the table.
  69. //
  70. // Called to read the next AddrObj in the table. The needed information
  71. // is derived from the incoming context, which is assumed to be valid.
  72. // We'll copy the information, and then update the context value with
  73. // the next AddrObj to be read.
  74. //
  75. uint // Returns: TRUE if more data is available to be read, FALSE is not.
  76. ReadNextAO(
  77. void *Context, // Pointer to a UDPContext.
  78. void *Buffer) // Pointer to a UDP6ListenerEntry structure.
  79. {
  80. UDPContext *UContext = (UDPContext *)Context;
  81. UDP6ListenerEntry *UEntry = (UDP6ListenerEntry *)Buffer;
  82. AddrObj *CurrentAO;
  83. uint i;
  84. CurrentAO = UContext->uc_ao;
  85. CHECK_STRUCT(CurrentAO, ao);
  86. UEntry->ule_localaddr = CurrentAO->ao_addr;
  87. UEntry->ule_localscopeid = CurrentAO->ao_scope_id;
  88. UEntry->ule_localport = CurrentAO->ao_port;
  89. UEntry->ule_owningpid = CurrentAO->ao_owningpid;
  90. // We've filled it in. Now update the context.
  91. CurrentAO = CurrentAO->ao_next;
  92. if (CurrentAO != NULL && CurrentAO->ao_prot == IP_PROTOCOL_UDP) {
  93. UContext->uc_ao = CurrentAO;
  94. return TRUE;
  95. } else {
  96. // The next AO is NULL, or not a UDP AO. Loop through the AddrObjTable
  97. // looking for a new one.
  98. i = UContext->uc_index;
  99. for (;;) {
  100. while (CurrentAO != NULL) {
  101. if (CurrentAO->ao_prot == IP_PROTOCOL_UDP)
  102. break;
  103. else
  104. CurrentAO = CurrentAO->ao_next;
  105. }
  106. if (CurrentAO != NULL)
  107. break; // Get out of for (;;) loop.
  108. ASSERT(CurrentAO == NULL);
  109. // Didn't find one on this chain. Walk down the table, looking
  110. // for the next one.
  111. while (++i < AddrObjTableSize) {
  112. if (AddrObjTable[i] != NULL) {
  113. CurrentAO = AddrObjTable[i];
  114. break; // Out of while loop.
  115. }
  116. }
  117. if (i == AddrObjTableSize)
  118. break; // Out of for (;;) loop.
  119. }
  120. // If we found one, return it.
  121. if (CurrentAO != NULL) {
  122. UContext->uc_ao = CurrentAO;
  123. UContext->uc_index = i;
  124. return TRUE;
  125. } else {
  126. UContext->uc_index = 0;
  127. UContext->uc_ao = NULL;
  128. return FALSE;
  129. }
  130. }
  131. }
  132. //* ValidateAOContext - Validate the context for reading the AddrObj table.
  133. //
  134. // Called to start reading the AddrObj table sequentially. We take in
  135. // a context, and if the values are 0 we return information about the
  136. // first AddrObj in the table. Otherwise we make sure that the context value
  137. // is valid, and if it is we return TRUE.
  138. // We assume the caller holds the AddrObjTable lock.
  139. //
  140. uint // Returns: TRUE if data in table, FALSE if not.
  141. ValidateAOContext(
  142. void *Context, // Pointer to a UDPContext.
  143. uint *Valid) // Pointer to value to set to true if context is valid.
  144. {
  145. UDPContext *UContext = (UDPContext *)Context;
  146. uint i;
  147. AddrObj *TargetAO;
  148. AddrObj *CurrentAO;
  149. i = UContext->uc_index;
  150. TargetAO = UContext->uc_ao;
  151. // If the context values are 0 and NULL, we're starting from the beginning.
  152. if (i == 0 && TargetAO == NULL) {
  153. *Valid = TRUE;
  154. do {
  155. if ((CurrentAO = AddrObjTable[i]) != NULL) {
  156. CHECK_STRUCT(CurrentAO, ao);
  157. while (CurrentAO != NULL &&
  158. CurrentAO->ao_prot != IP_PROTOCOL_UDP)
  159. CurrentAO = CurrentAO->ao_next;
  160. if (CurrentAO != NULL)
  161. break;
  162. }
  163. i++;
  164. } while (i < AddrObjTableSize);
  165. if (CurrentAO != NULL) {
  166. UContext->uc_index = i;
  167. UContext->uc_ao = CurrentAO;
  168. return TRUE;
  169. } else
  170. return FALSE;
  171. } else {
  172. // We've been given a context. We just need to make sure that it's
  173. // valid.
  174. if (i < AddrObjTableSize) {
  175. CurrentAO = AddrObjTable[i];
  176. while (CurrentAO != NULL) {
  177. if (CurrentAO == TargetAO) {
  178. if (CurrentAO->ao_prot == IP_PROTOCOL_UDP) {
  179. *Valid = TRUE;
  180. return TRUE;
  181. }
  182. break;
  183. } else {
  184. CurrentAO = CurrentAO->ao_next;
  185. }
  186. }
  187. }
  188. // If we get here, we didn't find the matching AddrObj.
  189. *Valid = FALSE;
  190. return FALSE;
  191. }
  192. }
  193. //* FindIfIndexOnAO - Find an interface index in an address-object's list.
  194. //
  195. // This routine is called to determine whether a given interface index
  196. // appears in the list of interfaces with which the given address-object
  197. // is associated.
  198. //
  199. // The routine is called from 'GetAddrObj' with the table lock held
  200. // but with the object lock not held. We take the object lock to look at
  201. // its interface list, and release the lock before returning control.
  202. //
  203. uint // Returns: The index if found, or 0 if none.
  204. FindIfIndexOnAO(
  205. AddrObj *AO, // Address object to be searched.
  206. Interface *IF) // The interface to be found.
  207. {
  208. uint *IfList;
  209. KIRQL Irql;
  210. KeAcquireSpinLock(&AO->ao_lock, &Irql);
  211. if ((IfList = AO->ao_iflist) != NULL) {
  212. while (*IfList) {
  213. if (*IfList == IF->Index) {
  214. KeReleaseSpinLock(&AO->ao_lock, Irql);
  215. return IF->Index;
  216. }
  217. IfList++;
  218. }
  219. }
  220. KeReleaseSpinLock(&AO->ao_lock, Irql);
  221. //
  222. // If an interface list was present and the interface was not found,
  223. // return zero. Otherwise, if no interface list was present there is no
  224. // restriction on the object, so return the interface index as though the
  225. // interface appeared in the list.
  226. //
  227. return IfList ? 0 : IF->Index;
  228. }
  229. //* GetAddrObj - Find a local address object.
  230. //
  231. // This is the local address object lookup routine. We take as input the
  232. // local address and port and a pointer to a 'previous' address object.
  233. // The hash table entries in each bucket are sorted in order of increasing
  234. // address, and we skip over any object that has an address lower than the
  235. // 'previous' address. To get the first address object, pass in a previous
  236. // value of NULL.
  237. //
  238. // We assume that the table lock is held while we're in this routine. We
  239. // don't take each object lock, since the local address and port can't change
  240. // while the entry is in the table and the table lock is held so nothing can
  241. // be inserted or deleted.
  242. //
  243. AddrObj * // Returns: A pointer to the Address object, or NULL if none.
  244. GetAddrObj(
  245. IPv6Addr *LocalAddr, // Local IP address of object to find (may be NULL).
  246. IPv6Addr *RemoteAddr, // Remote IP address to check against (may be NULL
  247. // if IF is also NULL).
  248. uint LocalScopeId, // Scope identifier for local IP address.
  249. ushort LocalPort, // Local port of object to find.
  250. uchar Protocol, // Protocol to find address.
  251. AddrObj *PreviousAO, // Pointer to last address object found.
  252. Interface *IF) // Interface to find in interface list (may be NULL).
  253. {
  254. AddrObj *CurrentAO; // Current address object we're examining.
  255. #if DBG
  256. if (PreviousAO != NULL)
  257. CHECK_STRUCT(PreviousAO, ao);
  258. #endif
  259. #if 0
  260. //
  261. // Check our 1-element cache for a match.
  262. //
  263. if ((PreviousAO == NULL) && (LastAO != NULL)) {
  264. CHECK_STRUCT(LastAO, ao);
  265. if ((LastAO->ao_prot == Protocol) &&
  266. IP6_ADDR_EQUAL(LastAO->ao_addr, LocalAddr) &&
  267. (LastAO->ao_port == LocalPort))
  268. {
  269. return LastAO;
  270. }
  271. }
  272. #endif
  273. // Find the appropriate bucket in the hash table, and search for a match.
  274. // If we don't find one the first time through, we'll try again with a
  275. // wildcard local address.
  276. for (;;) {
  277. CurrentAO = AddrObjTable[AO_HASH(*LocalAddr, LocalPort)];
  278. // While we haven't hit the end of the list, examine each element.
  279. while (CurrentAO != NULL) {
  280. CHECK_STRUCT(CurrentAO, ao);
  281. // If the current one is greater than one we were given, check it.
  282. if (CurrentAO > PreviousAO) {
  283. if (!(CurrentAO->ao_flags & AO_RAW_FLAG)) {
  284. //
  285. // This is an ordinary (non-raw) socket.
  286. // Only match if we meet all the criteria.
  287. //
  288. if (IP6_ADDR_EQUAL(&CurrentAO->ao_addr, LocalAddr) &&
  289. (CurrentAO->ao_scope_id == LocalScopeId) &&
  290. (CurrentAO->ao_port == LocalPort) &&
  291. (CurrentAO->ao_prot == Protocol)) {
  292. if ((IF == NULL) ||
  293. DoesAOAllowPacket(CurrentAO, IF, RemoteAddr)) {
  294. // Found a match. Update cache and return.
  295. LastAO = CurrentAO;
  296. return CurrentAO;
  297. }
  298. }
  299. } else {
  300. //
  301. // This is a raw socket.
  302. //
  303. if ((Protocol != IP_PROTOCOL_UDP)
  304. #ifndef UDP_ONLY
  305. && (Protocol != IP_PROTOCOL_TCP)
  306. #endif
  307. )
  308. {
  309. IF_TCPDBG(TCP_DEBUG_RAW) {
  310. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  311. "matching <p, a> <%u, %lx> ao %lx <%u, %lx>\n",
  312. Protocol, LocalAddr, CurrentAO,
  313. CurrentAO->ao_prot, CurrentAO->ao_addr));
  314. }
  315. if (IP6_ADDR_EQUAL(&CurrentAO->ao_addr, LocalAddr) &&
  316. (CurrentAO->ao_scope_id == LocalScopeId) &&
  317. ((CurrentAO->ao_prot == Protocol) ||
  318. (CurrentAO->ao_prot == 0))) {
  319. if ((IF == NULL) ||
  320. DoesAOAllowPacket(CurrentAO, IF, RemoteAddr)) {
  321. // Found a match. Update cache and return.
  322. LastAO = CurrentAO;
  323. return CurrentAO;
  324. }
  325. }
  326. }
  327. }
  328. }
  329. // Either it was less than the previous one, or they didn't match.
  330. // Keep searching in this bucket.
  331. CurrentAO = CurrentAO->ao_next;
  332. }
  333. //
  334. // When we get here, we've hit the end of the list we were examining.
  335. // If we weren't examining a wildcard address, look for a wild card
  336. // address.
  337. //
  338. if (!IP6_ADDR_EQUAL(LocalAddr, &UnspecifiedAddr)) {
  339. LocalAddr = &UnspecifiedAddr;
  340. LocalScopeId = 0;
  341. PreviousAO = NULL;
  342. } else
  343. return NULL; // We looked for a wildcard and couldn't find
  344. // one, so fail.
  345. }
  346. }
  347. //* GetNextAddrObj - Get the next address object in a sequential search.
  348. //
  349. // This is the 'get next' routine, called when we are reading the address
  350. // object table sequentially. We pull the appropriate parameters from the
  351. // search context, call GetAddrObj, and update the search context with what
  352. // we find. This routine assumes the AddrObjTableLock is held by the caller.
  353. //
  354. AddrObj * // Returns: Pointer to AddrObj, or NULL if search failed.
  355. GetNextAddrObj(
  356. AOSearchContext *SearchContext) // Context for search taking place.
  357. {
  358. AddrObj *FoundAO; // Pointer to the address object we found.
  359. ASSERT(SearchContext != NULL);
  360. // Try and find a match.
  361. FoundAO = GetAddrObj(&SearchContext->asc_local_addr,
  362. &SearchContext->asc_remote_addr,
  363. SearchContext->asc_scope_id,
  364. SearchContext->asc_port, SearchContext->asc_prot,
  365. SearchContext->asc_previous,
  366. SearchContext->asc_interface);
  367. // Found a match. Update the search context for next time.
  368. if (FoundAO != NULL) {
  369. SearchContext->asc_previous = FoundAO;
  370. SearchContext->asc_local_addr = FoundAO->ao_addr;
  371. SearchContext->asc_scope_id = FoundAO->ao_scope_id;
  372. // Don't bother to update port or protocol, they don't change.
  373. }
  374. return FoundAO;
  375. }
  376. //* GetFirstAddrObj - Get the first matching address object.
  377. //
  378. // The routine called to start a sequential read of the AddrObj table. We
  379. // initialize the provided search context and then call GetNextAddrObj to do
  380. // the actual read. We assume the AddrObjTableLock is held by the caller.
  381. //
  382. AddrObj * // Returns: Pointer to AO found, or NULL if we couldn't find any.
  383. GetFirstAddrObj(
  384. IPv6Addr *LocalAddr, // Local IP address of object to be found.
  385. IPv6Addr *RemoteAddr, // Remote IP address to check against.
  386. uint LocalScopeId, // Scope identifier for local IP address.
  387. ushort LocalPort, // Local port of object to be found.
  388. uchar Protocol, // Protocol of object to be found.
  389. Interface *IF, // Interface to check against.
  390. AOSearchContext *SearchContext) // Context to be used during search.
  391. {
  392. ASSERT(SearchContext != NULL);
  393. // Fill in the search context.
  394. SearchContext->asc_previous = NULL; // Haven't found one yet.
  395. SearchContext->asc_local_addr = *LocalAddr;
  396. SearchContext->asc_remote_addr = *RemoteAddr;
  397. SearchContext->asc_scope_id = LocalScopeId;
  398. SearchContext->asc_port = LocalPort;
  399. SearchContext->asc_prot = Protocol;
  400. SearchContext->asc_interface = IF;
  401. return GetNextAddrObj(SearchContext);
  402. }
  403. //* InsertAddrObj - Insert an address object into the AddrObj table.
  404. //
  405. // Called to insert an AO into the table, assuming the table lock is held.
  406. // We hash on the addr and port, and then insert in into the correct place
  407. // (sorted by address of the objects).
  408. //
  409. void // Returns: Nothing.
  410. InsertAddrObj(
  411. AddrObj *NewAO) // Pointer to AddrObj to be inserted.
  412. {
  413. AddrObj *PrevAO; // Pointer to previous address object in hash chain.
  414. AddrObj *CurrentAO; // Pointer to current AO in table.
  415. CHECK_STRUCT(NewAO, ao);
  416. PrevAO = CONTAINING_RECORD(&AddrObjTable[AO_HASH(NewAO->ao_addr,
  417. NewAO->ao_port)],
  418. AddrObj, ao_next);
  419. CurrentAO = PrevAO->ao_next;
  420. // Loop through the chain until we hit the end or until we find an entry
  421. // whose address is greater than ours.
  422. while (CurrentAO != NULL) {
  423. CHECK_STRUCT(CurrentAO, ao);
  424. ASSERT(CurrentAO != NewAO); // Debug check to make sure we aren't
  425. // inserting the same entry.
  426. if (NewAO < CurrentAO)
  427. break;
  428. PrevAO = CurrentAO;
  429. CurrentAO = CurrentAO->ao_next;
  430. }
  431. // At this point, PrevAO points to the AO before the new one. Insert it
  432. // there.
  433. ASSERT(PrevAO != NULL);
  434. ASSERT(PrevAO->ao_next == CurrentAO);
  435. NewAO->ao_next = CurrentAO;
  436. PrevAO->ao_next = NewAO;
  437. if (NewAO->ao_prot == IP_PROTOCOL_UDP)
  438. UStats.us_numaddrs++;
  439. }
  440. //* RemoveAddrObj - Remove an address object from the table.
  441. //
  442. // Called when we need to remove an address object from the table. We hash on
  443. // the addr and port, then walk the table looking for the object. We assume
  444. // that the table lock is held.
  445. //
  446. // The AddrObj may have already been removed from the table if it was
  447. // invalidated for some reason, so we need to check for the case of not
  448. // finding it.
  449. //
  450. void // Returns: Nothing.
  451. RemoveAddrObj(
  452. AddrObj *RemovedAO) // AddrObj to delete.
  453. {
  454. AddrObj *PrevAO; // Pointer to previous address object in hash chain.
  455. AddrObj *CurrentAO; // Pointer to current AO in table.
  456. CHECK_STRUCT(RemovedAO, ao);
  457. PrevAO = CONTAINING_RECORD(&AddrObjTable[AO_HASH(RemovedAO->ao_addr,
  458. RemovedAO->ao_port)],
  459. AddrObj, ao_next);
  460. CurrentAO = PrevAO->ao_next;
  461. // Walk the table, looking for a match.
  462. while (CurrentAO != NULL) {
  463. CHECK_STRUCT(CurrentAO, ao);
  464. if (CurrentAO == RemovedAO) {
  465. PrevAO->ao_next = CurrentAO->ao_next;
  466. if (CurrentAO->ao_prot == IP_PROTOCOL_UDP) {
  467. UStats.us_numaddrs--;
  468. }
  469. if (CurrentAO == LastAO) {
  470. LastAO = NULL;
  471. }
  472. return;
  473. } else {
  474. PrevAO = CurrentAO;
  475. CurrentAO = CurrentAO->ao_next;
  476. }
  477. }
  478. //
  479. // If we get here, we didn't find him. This is OK, but we should say
  480. // something about it.
  481. //
  482. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  483. "RemoveAddrObj: Object not found.\n"));
  484. }
  485. //* FindAnyAddrObj - Find an AO with matching port on any local address.
  486. //
  487. // Called for wildcard address opens. We go through the entire addrobj table,
  488. // and see if anyone has the specified port. We assume that the lock is
  489. // already held on the table.
  490. //
  491. AddrObj * // Returns: Pointer to AO found, or NULL is noone has it.
  492. FindAnyAddrObj(
  493. ushort Port, // Port to be looked for.
  494. uchar Protocol) // Protocol on which to look.
  495. {
  496. uint i; // Index variable.
  497. AddrObj *CurrentAO; // Current AddrObj being examined.
  498. for (i = 0; i < AddrObjTableSize; i++) {
  499. CurrentAO = AddrObjTable[i];
  500. while (CurrentAO != NULL) {
  501. CHECK_STRUCT(CurrentAO, ao);
  502. if (CurrentAO->ao_port == Port && CurrentAO->ao_prot == Protocol)
  503. return CurrentAO;
  504. else
  505. CurrentAO = CurrentAO->ao_next;
  506. }
  507. }
  508. return NULL;
  509. }
  510. //* RebuildAddrObjBitmap - reconstruct the address-object bitmap from scratch.
  511. //
  512. // Called when we need to reconcile the contents of our lookaside bitmap
  513. // with the actual contents of the address-object table. We clear the bitmap,
  514. // then scan the address-object table and mark each entry's bit as 'in-use'.
  515. // Assumes the caller holds the AddrObjTableLock.
  516. //
  517. // Input: nothing.
  518. //
  519. // Return: nothing.
  520. //
  521. void
  522. RebuildAddrObjBitmap(void)
  523. {
  524. uint i;
  525. AddrObj* CurrentAO;
  526. RtlClearAllBits(&PortBitmapTcp);
  527. RtlClearAllBits(&PortBitmapUdp);
  528. for (i = 0; i < AddrObjTableSize; i++) {
  529. CurrentAO = AddrObjTable[i];
  530. while (CurrentAO != NULL) {
  531. CHECK_STRUCT(CurrentAO, ao);
  532. if (CurrentAO->ao_prot == IP_PROTOCOL_TCP) {
  533. RtlSetBit(&PortBitmapTcp, net_short(CurrentAO->ao_port));
  534. } else if (CurrentAO->ao_prot == IP_PROTOCOL_UDP) {
  535. RtlSetBit(&PortBitmapUdp, net_short(CurrentAO->ao_port));
  536. }
  537. CurrentAO = CurrentAO->ao_next;
  538. }
  539. }
  540. }
  541. //* GetAddress - Get an IP address and port from a TDI address structure.
  542. //
  543. // Called when we need to get our addressing information from a TDI
  544. // address structure. We go through the structure, and return what we
  545. // find.
  546. //
  547. uchar // Return: TRUE if we find an address, FALSE if we don't.
  548. GetAddress(
  549. TRANSPORT_ADDRESS UNALIGNED *AddrList, // Pointer to structure to search.
  550. IPv6Addr *Addr, // Where to return IP address.
  551. ulong *ScopeId, // Where to return address scope.
  552. ushort *Port) // Where to return Port.
  553. {
  554. int i; // Index variable.
  555. TA_ADDRESS *CurrentAddr; // Address we're examining and may use.
  556. // First, verify that someplace in Address is an address we can use.
  557. CurrentAddr = (TA_ADDRESS *) AddrList->Address;
  558. for (i = 0; i < AddrList->TAAddressCount; i++) {
  559. if (CurrentAddr->AddressType == TDI_ADDRESS_TYPE_IP6) {
  560. if (CurrentAddr->AddressLength >= TDI_ADDRESS_LENGTH_IP6) {
  561. //
  562. // It's an IPv6 address. Pull out the values.
  563. //
  564. TDI_ADDRESS_IP6 UNALIGNED *ValidAddr =
  565. (TDI_ADDRESS_IP6 UNALIGNED *)CurrentAddr->Address;
  566. *Port = ValidAddr->sin6_port;
  567. RtlCopyMemory(Addr, ValidAddr->sin6_addr, sizeof(IPv6Addr));
  568. *ScopeId = ValidAddr->sin6_scope_id;
  569. return TRUE;
  570. } else
  571. return FALSE; // Wrong length for address.
  572. } else {
  573. //
  574. // Wrong address type. Skip over it to next one in list.
  575. //
  576. CurrentAddr = (TA_ADDRESS *)(CurrentAddr->Address +
  577. CurrentAddr->AddressLength);
  578. }
  579. }
  580. return FALSE; // Didn't find a match.
  581. }
  582. //* InvalidateAddrs - Invalidate all AOs for a specific address.
  583. //
  584. // Called when we need to invalidate all AOs for a specific address. Walk
  585. // down the table with the lock held, and take the lock on each AddrObj.
  586. // If the address matches, mark it as invalid, pull off all requests,
  587. // and continue. At the end we'll complete all requests with an error.
  588. //
  589. void // Returns: Nothing.
  590. InvalidateAddrs(
  591. IPv6Addr *Addr, // Addr to be invalidated.
  592. uint ScopeId) // Scope id for Addr.
  593. {
  594. Queue SendQ, RcvQ;
  595. AORequest *ReqList;
  596. KIRQL Irql0, Irql1; // One per lock nesting level.
  597. uint i;
  598. AddrObj *AO;
  599. DGSendReq *SendReq;
  600. DGRcvReq *RcvReq;
  601. AOMCastAddr *MA;
  602. INITQ(&SendQ);
  603. INITQ(&RcvQ);
  604. ReqList = NULL;
  605. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  606. for (i = 0; i < AddrObjTableSize; i++) {
  607. // Walk down each hash bucket, looking for a match.
  608. AO = AddrObjTable[i];
  609. while (AO != NULL) {
  610. CHECK_STRUCT(AO, ao);
  611. KeAcquireSpinLock(&AO->ao_lock, &Irql1);
  612. if (IP6_ADDR_EQUAL(&AO->ao_addr, Addr) &&
  613. (AO->ao_scope_id == ScopeId) && AO_VALID(AO)) {
  614. // This one matches. Mark as invalid, then pull his requests.
  615. SET_AO_INVALID(AO);
  616. // If he has a request on him, pull him off.
  617. if (AO->ao_request != NULL) {
  618. AORequest *Temp;
  619. Temp = CONTAINING_RECORD(&AO->ao_request, AORequest,
  620. aor_next);
  621. do {
  622. Temp = Temp->aor_next;
  623. } while (Temp->aor_next != NULL);
  624. Temp->aor_next = ReqList;
  625. ReqList = AO->ao_request;
  626. AO->ao_request = NULL;
  627. }
  628. // Go down his send list, pulling things off the send q and
  629. // putting them on our local queue.
  630. while (!EMPTYQ(&AO->ao_sendq)) {
  631. DEQUEUE(&AO->ao_sendq, SendReq, DGSendReq, dsr_q);
  632. CHECK_STRUCT(SendReq, dsr);
  633. ENQUEUE(&SendQ, &SendReq->dsr_q);
  634. }
  635. // Do the same for the receive queue.
  636. while (!EMPTYQ(&AO->ao_rcvq)) {
  637. DEQUEUE(&AO->ao_rcvq, RcvReq, DGRcvReq, drr_q);
  638. CHECK_STRUCT(RcvReq, drr);
  639. ENQUEUE(&RcvQ, &RcvReq->drr_q);
  640. }
  641. // Free any multicast addresses he may have. IP will have
  642. // deleted them at that level before we get here, so all we
  643. // need to do if free the memory.
  644. MA = AO->ao_mcastlist;
  645. while (MA != NULL) {
  646. AOMCastAddr *Temp;
  647. Temp = MA;
  648. MA = MA->ama_next;
  649. ExFreePool(Temp);
  650. }
  651. AO->ao_mcastlist = NULL;
  652. }
  653. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  654. AO = AO->ao_next; // Go to the next one.
  655. }
  656. }
  657. KeReleaseSpinLock(&AddrObjTableLock, Irql0);
  658. // OK, now walk what we've collected, complete it, and free it.
  659. while (ReqList != NULL) {
  660. AORequest *Req;
  661. Req = ReqList;
  662. ReqList = Req->aor_next;
  663. (*Req->aor_rtn)(Req->aor_context, (uint) TDI_ADDR_INVALID, 0);
  664. FreeAORequest(Req);
  665. }
  666. // Walk down the rcv. q, completing and freeing requests.
  667. while (!EMPTYQ(&RcvQ)) {
  668. DEQUEUE(&RcvQ, RcvReq, DGRcvReq, drr_q);
  669. CHECK_STRUCT(RcvReq, drr);
  670. (*RcvReq->drr_rtn)(RcvReq->drr_context, (uint) TDI_ADDR_INVALID, 0);
  671. FreeDGRcvReq(RcvReq);
  672. }
  673. // Now do the same for sends.
  674. while (!EMPTYQ(&SendQ)) {
  675. DEQUEUE(&SendQ, SendReq, DGSendReq, dsr_q);
  676. CHECK_STRUCT(SendReq, dsr);
  677. (*SendReq->dsr_rtn)(SendReq->dsr_context, (uint) TDI_ADDR_INVALID, 0);
  678. KeAcquireSpinLock(&DGSendReqLock, &Irql0);
  679. FreeDGSendReq(SendReq);
  680. KeReleaseSpinLock(&DGSendReqLock, Irql0);
  681. }
  682. }
  683. //* RequestWorker - Handle a deferred request.
  684. //
  685. // This is the work item callback routine, called by a system worker
  686. // thread when the work item queued by DelayDerefAO is handled.
  687. // We just call ProcessAORequest on the AO.
  688. //
  689. void // Returns: Nothing.
  690. RequestWorker(
  691. void *Context) // Pointer to AddrObj.
  692. {
  693. AddrObj *AO = (AddrObj *)Context;
  694. CHECK_STRUCT(AO, ao);
  695. ASSERT(AO_BUSY(AO));
  696. ProcessAORequests(AO);
  697. }
  698. //* GetAddrOptions - Get the address options.
  699. //
  700. // Called when we're opening an address. We take in a pointer, and walk
  701. // down it looking for address options we know about.
  702. //
  703. void // Returns: Nothing.
  704. GetAddrOptions(
  705. void *Ptr, // Pointer to search.
  706. uchar *Reuse, // Pointer to reuse flag.
  707. uchar *DHCPAddr, // Pointer to DHCP flag.
  708. uchar *RawSock) // Pointer to raw socket flag.
  709. {
  710. uchar *OptPtr;
  711. *Reuse = 0;
  712. *DHCPAddr = 0;
  713. *RawSock = 0;
  714. if (Ptr == NULL)
  715. return;
  716. OptPtr = (uchar *)Ptr;
  717. while (*OptPtr != TDI_OPTION_EOL) {
  718. if (*OptPtr == TDI_ADDRESS_OPTION_REUSE)
  719. *Reuse = 1;
  720. else if (*OptPtr == TDI_ADDRESS_OPTION_DHCP)
  721. *DHCPAddr = 1;
  722. else if (*OptPtr == TDI_ADDRESS_OPTION_RAW)
  723. *RawSock = 1;
  724. OptPtr++;
  725. }
  726. }
  727. //* CheckAddrReuse - enforce port-sharing rules for a new TDI address object.
  728. //
  729. // Called when opening an address, to determine whether the open should
  730. // succeed in the presence of previous binds to the same port.
  731. //
  732. // N.B. Assumes the caller holds both AddrSDMutex and AddrObjTableLock.
  733. // The latter is freed and reacquired in this routine.
  734. //
  735. TDI_STATUS // Returns: TDI_STATUS code of attempt.
  736. CheckAddrReuse(
  737. PTDI_REQUEST Request, // Pointer to a TDI request for this open.
  738. uint Protocol, // Protocol on which to open the address.
  739. IPv6Addr* Addr, // Local IP address to open.
  740. ulong ScopeId, // Scope identifier for local IP address.
  741. ushort Port, // Local port number to open.
  742. BOOLEAN NewReuse, // Indicates if reuse requested for the open.
  743. PSECURITY_DESCRIPTOR NewSD, // Captured security-descriptor for the open.
  744. KIRQL* TableIrql) // IRQL at which AddrObjTableLock was taken.
  745. {
  746. PACCESS_STATE AccessState;
  747. BOOLEAN AllowReuse;
  748. AddrObj* ExistingAO;
  749. BOOLEAN ExistingReuse;
  750. PSECURITY_DESCRIPTOR ExistingSD;
  751. PIRP Irp;
  752. PIO_STACK_LOCATION IrpSp;
  753. ACCESS_MASK GrantedAccess;
  754. NTSTATUS status;
  755. // Look for an existing valid AO and succeed if none.
  756. // Otherwise, capture its reuse flag and security-descriptor.
  757. ExistingAO = GetBestAddrObj(Addr, NULL, ScopeId, Port, (uchar)Protocol,
  758. NULL);
  759. if (ExistingAO == NULL && IP6_ADDR_EQUAL(Addr, &UnspecifiedAddr) &&
  760. NewSD == NULL) {
  761. ExistingAO = FindAnyAddrObj(Port, (uchar)Protocol);
  762. }
  763. if (ExistingAO == NULL) {
  764. return TDI_SUCCESS;
  765. }
  766. do {
  767. // We've got at least one AO, so see if it allows reuse.
  768. // Note that we may need to repeat this for every AO on this port
  769. // in the case where we have multiple AOs sharing the port already,
  770. // since each AO has its own security descriptor. In that event,
  771. // we look at the AOs until one denies access or we've seen them all.
  772. ExistingReuse = !!AO_SHARE(ExistingAO);
  773. ExistingSD = ExistingAO->ao_sd;
  774. // Succeed immediately if reuse enabled on both instances.
  775. // Otherwise, fail if the two instances have the exact same address
  776. // (whether it's unspecified or specific).
  777. if (ExistingReuse && NewReuse) {
  778. return TDI_SUCCESS;
  779. }
  780. if (IP6_ADDR_EQUAL(&ExistingAO->ao_addr, Addr)) {
  781. return TDI_ADDR_IN_USE;
  782. }
  783. // The two instances have different addresses, and at least one of them
  784. // doesn't have reuse enabled. If the new instance is on the unspecified
  785. // address, the old instance must be on a specific address.
  786. // Allow the bind unless the new instance wants exclusive access
  787. // (i.e. NewSD == NULL).
  788. if (IP6_ADDR_EQUAL(Addr, &UnspecifiedAddr)) {
  789. if (NewSD == NULL) {
  790. return TDI_ADDR_IN_USE;
  791. }
  792. return TDI_SUCCESS;
  793. }
  794. // The two instances have different addresses, and the new instance is
  795. // on a specific address. If the old instance is on a specific address
  796. // too, the two are disjoint and can peacefully coexist.
  797. if (!IP6_ADDR_EQUAL(&ExistingAO->ao_addr, &UnspecifiedAddr)) {
  798. return TDI_SUCCESS;
  799. }
  800. // The new instance is on a specific address and the old instance is on
  801. // the wildcard address. If the old instance wanted exclusive access
  802. // (i.e. ExistingSD == NULL) fail the new instance right away.
  803. // Otherwise, drop the AO table lock and perform an access check
  804. // to see if it's OK for the new instance to steal some traffic from
  805. // the old instance.
  806. //
  807. // N.B. Even though we've dropped the AO table lock, ExistingSD is safe
  808. // since we still have the AO SD mutex.
  809. if (ExistingSD == NULL) {
  810. return STATUS_ACCESS_DENIED;
  811. }
  812. ASSERT(*TableIrql <= PASSIVE_LEVEL);
  813. KeReleaseSpinLock(&AddrObjTableLock, *TableIrql);
  814. Irp = (PIRP)Request->RequestContext;
  815. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  816. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  817. SeLockSubjectContext(&AccessState->SubjectSecurityContext);
  818. AllowReuse = SeAccessCheck(ExistingSD, &AccessState->SubjectSecurityContext,
  819. TRUE, FILE_READ_DATA|FILE_WRITE_DATA, 0,
  820. NULL, IoGetFileObjectGenericMapping(),
  821. (IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  822. ? UserMode : Irp->RequestorMode,
  823. &GrantedAccess, &status);
  824. SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
  825. KeAcquireSpinLock(&AddrObjTableLock, TableIrql);
  826. if (!AllowReuse) {
  827. return status;
  828. }
  829. // The existing wildcard AO doesn't mind if the new instance takes
  830. // some of its traffic. If the existing AO has reuse enabled, there
  831. // might be others too on the port, so we'll look for them and do an
  832. // access check against their security-descriptors too.
  833. } while(ExistingReuse &&
  834. (ExistingAO = GetAddrObj(&UnspecifiedAddr, NULL, ScopeId, Port,
  835. (uchar)Protocol, ExistingAO, NULL))
  836. != NULL);
  837. return TDI_SUCCESS;
  838. }
  839. //* TdiOpenAddress - Open a TDI address object.
  840. //
  841. // This is the external interface to open an address. The caller provides a
  842. // TDI_REQUEST structure and a TRANSPORT_ADDRESS structure, as well a pointer
  843. // to a variable identifying whether or not we are to allow reuse of an
  844. // address while it's still open.
  845. //
  846. TDI_STATUS // Returns: TDI_STATUS code of attempt.
  847. TdiOpenAddress(
  848. PTDI_REQUEST Request, // TDI request structure for this request.
  849. TRANSPORT_ADDRESS UNALIGNED *AddrList, // Address to be opened.
  850. uint Protocol, // Protocol on which to open the address (LSB only).
  851. void *Ptr, // Pointer to option buffer.
  852. PSECURITY_DESCRIPTOR AddrSD) // SD for port-reuse access checks.
  853. {
  854. uint i; // Index variable.
  855. ushort Port; // Local Port we'll use.
  856. IPv6Addr LocalAddr; // Actual address we'll use.
  857. ulong ScopeId; // Address scope.
  858. AddrObj *NewAO; // New AO we'll use.
  859. AddrObj *ExistingAO; // Pointer to existing AO, if any.
  860. KIRQL OldIrql;
  861. uchar Reuse, DHCPAddr, RawSock;
  862. PRTL_BITMAP PortBitmap;
  863. if (!GetAddress(AddrList, &LocalAddr, &ScopeId, &Port))
  864. return TDI_BAD_ADDR;
  865. // Find the address options we might need.
  866. GetAddrOptions(Ptr, &Reuse, &DHCPAddr, &RawSock);
  867. //
  868. // Allocate the new addr obj now, assuming that we need it,
  869. // so we don't have to do it with locks held later.
  870. //
  871. NewAO = ExAllocatePool(NonPagedPool, sizeof(AddrObj));
  872. if (NewAO == NULL) {
  873. // Couldn't allocate an address object.
  874. return TDI_NO_RESOURCES;
  875. }
  876. RtlZeroMemory(NewAO, sizeof(AddrObj));
  877. //
  878. // Check to make sure IP address is one of our local addresses. This
  879. // is protected with the address table lock, so we can interlock an IP
  880. // address going away through DHCP.
  881. //
  882. KeWaitForSingleObject(&AddrSDMutex, Executive, KernelMode, FALSE, NULL);
  883. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  884. if (!IP6_ADDR_EQUAL(&LocalAddr, &UnspecifiedAddr)) {
  885. NetTableEntry *NTE;
  886. //
  887. // The user specified a local address (i.e. not wildcarded).
  888. // Call IP to check that this is a valid local address.
  889. // We do this by looking up an NTE for the address; note
  890. // that this will fail if the scope id is specified
  891. // improperly or doesn't match exactly.
  892. //
  893. NTE = FindNetworkWithAddress(&LocalAddr, ScopeId);
  894. if (NTE == NULL) {
  895. // Not a local address. Fail the request.
  896. BadAddr:
  897. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  898. KeReleaseMutex(&AddrSDMutex, FALSE);
  899. ExFreePool(NewAO);
  900. return TDI_BAD_ADDR;
  901. }
  902. //
  903. // We don't actually want the NTE, we were just checking that
  904. // it exists. So release our reference.
  905. //
  906. ReleaseNTE(NTE);
  907. } else {
  908. //
  909. // The user specified the wildcard address.
  910. // Insist that the scope id is zero.
  911. //
  912. if (ScopeId != 0)
  913. goto BadAddr;
  914. }
  915. //
  916. // The specified IP address is a valid local address. Now we do
  917. // protocol-specific processing. An exception is raw sockets: we
  918. // don't allocate port space for them, regardless of their protocol.
  919. //
  920. if (Protocol == IP_PROTOCOL_TCP) {
  921. PortBitmap = &PortBitmapTcp;
  922. } else if (Protocol == IP_PROTOCOL_UDP) {
  923. PortBitmap = &PortBitmapUdp;
  924. } else {
  925. PortBitmap = NULL;
  926. }
  927. if (!RawSock && PortBitmap) {
  928. //
  929. // If no port is specified we have to assign one. If there is a
  930. // port specified, we need to make sure that the IPAddress/Port
  931. // combo isn't already open (unless Reuse is specified). If the
  932. // input address is a wildcard, we need to make sure the address
  933. // isn't open on any local ip address.
  934. //
  935. if (Port == WILDCARD_PORT) {
  936. // Have a wildcard port, need to assign an address.
  937. Port = NextUserPort;
  938. for (i = 0; i < NUM_USER_PORTS; i++, Port++) {
  939. ushort NetPort; // Port in net byte order.
  940. if (Port > MaxUserPort) {
  941. Port = MIN_USER_PORT;
  942. RebuildAddrObjBitmap();
  943. }
  944. NetPort = net_short(Port);
  945. if (IP6_ADDR_EQUAL(&LocalAddr, &UnspecifiedAddr)) {
  946. // Wildcard IP address.
  947. if (PortBitmap) {
  948. if (!RtlCheckBit(PortBitmap, Port))
  949. break;
  950. else
  951. continue;
  952. } else {
  953. ExistingAO = FindAnyAddrObj(NetPort, (uchar)Protocol);
  954. }
  955. } else {
  956. ExistingAO = GetBestAddrObj(&LocalAddr, NULL, ScopeId,
  957. NetPort, (uchar)Protocol, NULL);
  958. }
  959. if (ExistingAO == NULL)
  960. break; // Found an unused port.
  961. }
  962. if (i == NUM_USER_PORTS) {
  963. // Couldn't find a free port.
  964. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  965. KeReleaseMutex(&AddrSDMutex, FALSE);
  966. ExFreePool(NewAO);
  967. return TDI_NO_FREE_ADDR;
  968. }
  969. NextUserPort = Port + 1;
  970. Port = net_short(Port);
  971. } else {
  972. //
  973. // A particular port was specified.
  974. //
  975. // Don't check if a DHCP address is specified.
  976. if (!DHCPAddr) {
  977. TDI_STATUS Status;
  978. //
  979. // See if we already have this address open and, if so,
  980. // decide whether this request should succeed.
  981. //
  982. Status = CheckAddrReuse(Request, Protocol, &LocalAddr, ScopeId,
  983. Port, Reuse, AddrSD, &OldIrql);
  984. if (Status != TDI_SUCCESS) {
  985. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  986. KeReleaseMutex(&AddrSDMutex, FALSE);
  987. ExFreePool(NewAO);
  988. return Status;
  989. }
  990. }
  991. }
  992. //
  993. // We have a new AO. Set up the protocol specific portions.
  994. //
  995. if (Protocol == IP_PROTOCOL_UDP) {
  996. NewAO->ao_dgsend = UDPSend;
  997. NewAO->ao_maxdgsize = 0xFFFF - sizeof(UDPHeader);
  998. }
  999. } else {
  1000. //
  1001. // Either we have a raw socket or this is a protocol for which
  1002. // we don't allocate a port. Open over Raw IP.
  1003. //
  1004. ASSERT(!DHCPAddr);
  1005. //
  1006. // We must set the port to zero. This puts all the raw sockets
  1007. // in one hash bucket, which is necessary for GetAddrObj to
  1008. // work correctly. It wouldn't be a bad idea to come up with
  1009. // a better scheme...
  1010. //
  1011. Port = 0;
  1012. NewAO->ao_dgsend = RawSend;
  1013. NewAO->ao_maxdgsize = 0xFFFF;
  1014. NewAO->ao_flags |= AO_RAW_FLAG;
  1015. IF_TCPDBG(TCP_DEBUG_RAW) {
  1016. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1017. "raw open protocol %u AO %lx\n", Protocol, NewAO));
  1018. }
  1019. }
  1020. // When we get here, we know we're creating a brand new address object.
  1021. // Port contains the port in question, and NewAO points to the newly
  1022. // created AO.
  1023. KeInitializeSpinLock(&NewAO->ao_lock);
  1024. ExInitializeWorkItem(&NewAO->ao_workitem, RequestWorker, NewAO);
  1025. INITQ(&NewAO->ao_sendq);
  1026. INITQ(&NewAO->ao_rcvq);
  1027. INITQ(&NewAO->ao_activeq);
  1028. INITQ(&NewAO->ao_idleq);
  1029. INITQ(&NewAO->ao_listenq);
  1030. NewAO->ao_port = Port;
  1031. NewAO->ao_addr = LocalAddr;
  1032. NewAO->ao_scope_id = ScopeId;
  1033. NewAO->ao_prot = (uchar)Protocol;
  1034. NewAO->ao_ucast_hops = -1; // This causes system default to be used.
  1035. NewAO->ao_mcast_hops = -1; // This causes system default to be used.
  1036. NewAO->ao_mcast_loop = TRUE;// Multicast loopback is on by default.
  1037. #if DBG
  1038. NewAO->ao_sig = ao_signature;
  1039. #endif
  1040. NewAO->ao_sd = AddrSD;
  1041. NewAO->ao_flags |= AO_VALID_FLAG; // AO is valid.
  1042. NewAO->ao_protect = PROTECTION_LEVEL_DEFAULT;
  1043. if (DHCPAddr)
  1044. NewAO->ao_flags |= AO_DHCP_FLAG;
  1045. if (Reuse) {
  1046. SET_AO_SHARE(NewAO);
  1047. }
  1048. NewAO->ao_owningpid = HandleToUlong(PsGetCurrentProcessId());
  1049. //
  1050. // Note the following fields are left zero - which has this effect:
  1051. //
  1052. // ao_mcast_if - use the routing table by default.
  1053. // ao_udp_cksum_cover - checksum everything.
  1054. //
  1055. InsertAddrObj(NewAO);
  1056. if (PortBitmap) {
  1057. RtlSetBit(PortBitmap, net_short(Port));
  1058. }
  1059. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  1060. KeReleaseMutex(&AddrSDMutex, FALSE);
  1061. Request->Handle.AddressHandle = NewAO;
  1062. return TDI_SUCCESS;
  1063. }
  1064. //* DeleteAO - Delete an address object.
  1065. //
  1066. // The internal routine to delete an address object. We complete any pending
  1067. // requests with errors, and remove and free the address object.
  1068. //
  1069. void // Returns: Nothing.
  1070. DeleteAO(
  1071. AddrObj *DeletedAO) // AddrObj to be deleted.
  1072. {
  1073. KIRQL Irql0; // One per lock nesting level.
  1074. #ifndef UDP_ONLY
  1075. TCB *TCBHead = NULL, *CurrentTCB;
  1076. TCPConn *Conn;
  1077. Queue *Temp;
  1078. Queue *CurrentQ;
  1079. RequestCompleteRoutine Rtn; // Completion routine.
  1080. PVOID Context; // User context for completion routine.
  1081. #endif
  1082. AOMCastAddr *AMA;
  1083. PSECURITY_DESCRIPTOR AddrSD;
  1084. CHECK_STRUCT(DeletedAO, ao);
  1085. ASSERT(!AO_VALID(DeletedAO));
  1086. ASSERT(DeletedAO->ao_usecnt == 0);
  1087. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  1088. KeAcquireSpinLockAtDpcLevel(&DGSendReqLock);
  1089. KeAcquireSpinLockAtDpcLevel(&DeletedAO->ao_lock);
  1090. // If he's on an oor queue, remove him.
  1091. if (AO_OOR(DeletedAO))
  1092. REMOVEQ(&DeletedAO->ao_pendq);
  1093. KeReleaseSpinLockFromDpcLevel(&DGSendReqLock);
  1094. RemoveAddrObj(DeletedAO);
  1095. #ifndef UDP_ONLY
  1096. // Walk down the list of associated connections and zap their AO pointers.
  1097. // For each connection, we need to shut down the connection if it's active.
  1098. // If the connection isn't already closing, we'll put a reference on it
  1099. // so that it can't go away while we're dealing with the AO, and put it
  1100. // on a list. On our way out we'll walk down that list and zap each
  1101. // connection.
  1102. CurrentQ = &DeletedAO->ao_activeq;
  1103. for (;;) {
  1104. Temp = QHEAD(CurrentQ);
  1105. while (Temp != QEND(CurrentQ)) {
  1106. Conn = QSTRUCT(TCPConn, Temp, tc_q);
  1107. //
  1108. // Move our temp pointer to the next connection now,
  1109. // since we may free this connection below.
  1110. //
  1111. Temp = QNEXT(Temp);
  1112. //
  1113. // We'll need to unlock the AO in order to look at the Conn.
  1114. // While the AO is unlocked, we need to worry about the following
  1115. // requests being issued on the Conn:
  1116. //
  1117. // TdiDisAssociateAddress, TdiConnect: we hold AddrObjTableLock
  1118. // so the requests are blocked.
  1119. // TdiListen, FindListenConn: the AO is marked invalid already,
  1120. // so the requests will fail.
  1121. // TdiAccept: this request doesn't update the AO<->Conn link
  1122. // (just Conn<->TCB) so we don't care about it.
  1123. //
  1124. KeReleaseSpinLockFromDpcLevel(&DeletedAO->ao_lock);
  1125. KeAcquireSpinLockAtDpcLevel(&Conn->tc_ConnBlock->cb_lock);
  1126. CHECK_STRUCT(Conn, tc);
  1127. CurrentTCB = Conn->tc_tcb;
  1128. if (CurrentTCB != NULL) {
  1129. // We have a TCB.
  1130. CHECK_STRUCT(CurrentTCB, tcb);
  1131. KeAcquireSpinLockAtDpcLevel(&CurrentTCB->tcb_lock);
  1132. if (CurrentTCB->tcb_state != TCB_CLOSED &&
  1133. !CLOSING(CurrentTCB)) {
  1134. // It's not closing. Put a reference on it and save it
  1135. // on the list.
  1136. CurrentTCB->tcb_refcnt++;
  1137. CurrentTCB->tcb_aonext = TCBHead;
  1138. TCBHead = CurrentTCB;
  1139. }
  1140. CurrentTCB->tcb_conn = NULL;
  1141. CurrentTCB->tcb_rcvind = NULL;
  1142. if (CurrentTCB->tcb_rcvhndlr == IndicateData &&
  1143. CurrentTCB->tcb_indicated == 0) {
  1144. if (CurrentTCB->tcb_currcv != NULL) {
  1145. CurrentTCB->tcb_rcvhndlr = BufferData;
  1146. } else {
  1147. CurrentTCB->tcb_rcvhndlr = PendData;
  1148. }
  1149. }
  1150. KeReleaseSpinLockFromDpcLevel(&CurrentTCB->tcb_lock);
  1151. //
  1152. // Subtract one from the connection's ref count, since we
  1153. // are about to remove this TCB from the connection.
  1154. //
  1155. if (--(Conn->tc_refcnt) == 0) {
  1156. //
  1157. // We need to execute the code for the done
  1158. // routine. There are only three done routines that can
  1159. // be called. CloseDone(), DisassocDone(), and DummyDone().
  1160. // We execute the respective code here to avoid freeing locks.
  1161. // Note: DummyDone() does nothing.
  1162. //
  1163. if (Conn->tc_flags & CONN_CLOSING) {
  1164. //
  1165. // This is the relevant CloseDone() code.
  1166. //
  1167. Rtn = Conn->tc_rtn;
  1168. Context = Conn->tc_rtncontext;
  1169. KeReleaseSpinLockFromDpcLevel(
  1170. &Conn->tc_ConnBlock->cb_lock);
  1171. ExFreePool(Conn);
  1172. (*Rtn) (Context, TDI_SUCCESS, 0);
  1173. } else if (Conn->tc_flags & CONN_DISACC) {
  1174. //
  1175. // This is the relevant DisassocDone() code.
  1176. //
  1177. Rtn = Conn->tc_rtn;
  1178. Context = Conn->tc_rtncontext;
  1179. Conn->tc_flags &= ~CONN_DISACC;
  1180. Conn->tc_ao = NULL;
  1181. Conn->tc_tcb = NULL;
  1182. KeReleaseSpinLockFromDpcLevel(
  1183. &Conn->tc_ConnBlock->cb_lock);
  1184. (*Rtn) (Context, TDI_SUCCESS, 0);
  1185. } else {
  1186. Conn->tc_ao = NULL;
  1187. Conn->tc_tcb = NULL;
  1188. KeReleaseSpinLockFromDpcLevel(
  1189. &Conn->tc_ConnBlock->cb_lock);
  1190. }
  1191. } else {
  1192. Conn->tc_ao = NULL;
  1193. Conn->tc_tcb = NULL;
  1194. KeReleaseSpinLockFromDpcLevel(&Conn->tc_ConnBlock->cb_lock);
  1195. }
  1196. } else {
  1197. Conn->tc_ao = NULL;
  1198. KeReleaseSpinLockFromDpcLevel(&Conn->tc_ConnBlock->cb_lock);
  1199. }
  1200. KeAcquireSpinLockAtDpcLevel(&DeletedAO->ao_lock);
  1201. }
  1202. if (CurrentQ == &DeletedAO->ao_activeq) {
  1203. CurrentQ = &DeletedAO->ao_idleq;
  1204. } else if (CurrentQ == &DeletedAO->ao_idleq) {
  1205. CurrentQ = &DeletedAO->ao_listenq;
  1206. } else {
  1207. ASSERT(CurrentQ == &DeletedAO->ao_listenq);
  1208. break;
  1209. }
  1210. }
  1211. #endif
  1212. //
  1213. // Release excess locks. Note we release the locks in a different order
  1214. // from which we acquired them, but must return to IRQ levels in the order
  1215. // we left them.
  1216. //
  1217. KeReleaseSpinLockFromDpcLevel(&AddrObjTableLock);
  1218. // We've removed him from the queues, and he's marked as invalid. Return
  1219. // pending requests with errors.
  1220. // We still hold the lock on the AddrObj, although this may not be
  1221. // neccessary.
  1222. while (!EMPTYQ(&DeletedAO->ao_rcvq)) {
  1223. DGRcvReq *Rcv;
  1224. DEQUEUE(&DeletedAO->ao_rcvq, Rcv, DGRcvReq, drr_q);
  1225. CHECK_STRUCT(Rcv, drr);
  1226. KeReleaseSpinLock(&DeletedAO->ao_lock, Irql0);
  1227. (*Rcv->drr_rtn)(Rcv->drr_context, (uint) TDI_ADDR_DELETED, 0);
  1228. FreeDGRcvReq(Rcv);
  1229. KeAcquireSpinLock(&DeletedAO->ao_lock, &Irql0);
  1230. }
  1231. // Now destroy any sends.
  1232. while (!EMPTYQ(&DeletedAO->ao_sendq)) {
  1233. DGSendReq *Send;
  1234. DEQUEUE(&DeletedAO->ao_sendq, Send, DGSendReq, dsr_q);
  1235. CHECK_STRUCT(Send, dsr);
  1236. KeReleaseSpinLock(&DeletedAO->ao_lock, Irql0);
  1237. (*Send->dsr_rtn)(Send->dsr_context, (uint) TDI_ADDR_DELETED, 0);
  1238. KeAcquireSpinLock(&DGSendReqLock, &Irql0);
  1239. FreeDGSendReq(Send);
  1240. KeReleaseSpinLock(&DGSendReqLock, Irql0);
  1241. KeAcquireSpinLock(&DeletedAO->ao_lock, &Irql0);
  1242. }
  1243. AddrSD = DeletedAO->ao_sd;
  1244. KeReleaseSpinLock(&DeletedAO->ao_lock, Irql0);
  1245. // Free any associated multicast addresses.
  1246. AMA = DeletedAO->ao_mcastlist;
  1247. while (AMA != NULL) {
  1248. AOMCastAddr *CurrentAMA;
  1249. // Remove the group address from the IP layer.
  1250. MLDDropMCastAddr(AMA->ama_if, &AMA->ama_addr);
  1251. CurrentAMA = AMA;
  1252. AMA = AMA->ama_next;
  1253. ExFreePool(CurrentAMA);
  1254. }
  1255. if (DeletedAO->ao_iflist != NULL) {
  1256. ExFreePool(DeletedAO->ao_iflist);
  1257. }
  1258. if (AddrSD != NULL) {
  1259. KeWaitForSingleObject(&AddrSDMutex, Executive, KernelMode, FALSE, NULL);
  1260. ObDereferenceSecurityDescriptor(AddrSD, 1);
  1261. KeReleaseMutex(&AddrSDMutex, FALSE);
  1262. }
  1263. ExFreePool(DeletedAO);
  1264. #ifndef UDP_ONLY
  1265. // Now go down the TCB list, and destroy any we need to.
  1266. CurrentTCB = TCBHead;
  1267. while (CurrentTCB != NULL) {
  1268. TCB *NextTCB;
  1269. KeAcquireSpinLock(&CurrentTCB->tcb_lock, &Irql0);
  1270. CurrentTCB->tcb_flags |= NEED_RST; // Make sure we send a RST.
  1271. NextTCB = CurrentTCB->tcb_aonext;
  1272. TryToCloseTCB(CurrentTCB, TCB_CLOSE_ABORTED, Irql0);
  1273. KeAcquireSpinLock(&CurrentTCB->tcb_lock, &Irql0);
  1274. DerefTCB(CurrentTCB, Irql0);
  1275. CurrentTCB = NextTCB;
  1276. }
  1277. #endif
  1278. }
  1279. //* GetAORequest - Get an AO request structure.
  1280. //
  1281. // A routine to allocate a request structure from our free list.
  1282. //
  1283. AORequest * // Returns: Ptr to request struct, or NULL if we couldn't get one.
  1284. GetAORequest()
  1285. {
  1286. AORequest *NewRequest;
  1287. NewRequest = ExAllocatePool(NonPagedPool, sizeof(AORequest));
  1288. if (NewRequest != NULL) {
  1289. #if DBG
  1290. NewRequest->aor_sig = aor_signature;
  1291. #endif
  1292. }
  1293. return NewRequest;
  1294. }
  1295. //* FreeAORequest - Free an AO request structure.
  1296. //
  1297. // Called to free an AORequest structure.
  1298. //
  1299. void // Returns: Nothing.
  1300. FreeAORequest(
  1301. AORequest *Request) // AORequest structure to be freed.
  1302. {
  1303. CHECK_STRUCT(Request, aor);
  1304. ExFreePool(Request);
  1305. }
  1306. //* TDICloseAddress - Close an address.
  1307. //
  1308. // The user API to delete an address. Basically, we destroy the local address
  1309. // object if we can.
  1310. //
  1311. // This routine is interlocked with the AO busy bit - if the busy bit is set,
  1312. // we'll just flag the AO for later deletion.
  1313. //
  1314. TDI_STATUS // Returns: Status of attempt to delete the address -
  1315. // (either pending or success).
  1316. TdiCloseAddress(
  1317. PTDI_REQUEST Request) // TDI_REQUEST structure for this request.
  1318. {
  1319. AddrObj *DeletingAO;
  1320. KIRQL OldIrql;
  1321. DeletingAO = Request->Handle.AddressHandle;
  1322. CHECK_STRUCT(DeletingAO, ao);
  1323. KeAcquireSpinLock(&DeletingAO->ao_lock, &OldIrql);
  1324. if (!AO_BUSY(DeletingAO) && !(DeletingAO->ao_usecnt)) {
  1325. SET_AO_BUSY(DeletingAO);
  1326. SET_AO_INVALID(DeletingAO); // This address object is deleting.
  1327. KeReleaseSpinLock(&DeletingAO->ao_lock, OldIrql);
  1328. DeleteAO(DeletingAO);
  1329. return TDI_SUCCESS;
  1330. } else {
  1331. AORequest *NewRequest, *OldRequest;
  1332. RequestCompleteRoutine CmpltRtn;
  1333. PVOID ReqContext;
  1334. TDI_STATUS Status;
  1335. // Check and see if we already have a delete in progress. If we don't
  1336. // allocate and link up a delete request structure.
  1337. if (!AO_REQUEST(DeletingAO, AO_DELETE)) {
  1338. OldRequest = DeletingAO->ao_request;
  1339. NewRequest = GetAORequest();
  1340. if (NewRequest != NULL) {
  1341. // Got a request.
  1342. NewRequest->aor_rtn = Request->RequestNotifyObject;
  1343. NewRequest->aor_context = Request->RequestContext;
  1344. // Clear the option request, if there is one.
  1345. CLEAR_AO_REQUEST(DeletingAO, AO_OPTIONS);
  1346. SET_AO_REQUEST(DeletingAO, AO_DELETE);
  1347. SET_AO_INVALID(DeletingAO); // Address object is deleting.
  1348. DeletingAO->ao_request = NewRequest;
  1349. NewRequest->aor_next = NULL;
  1350. KeReleaseSpinLock(&DeletingAO->ao_lock, OldIrql);
  1351. while (OldRequest != NULL) {
  1352. AORequest *Temp;
  1353. CmpltRtn = OldRequest->aor_rtn;
  1354. ReqContext = OldRequest->aor_context;
  1355. (*CmpltRtn)(ReqContext, (uint) TDI_ADDR_DELETED, 0);
  1356. Temp = OldRequest;
  1357. OldRequest = OldRequest->aor_next;
  1358. FreeAORequest(Temp);
  1359. }
  1360. return TDI_PENDING;
  1361. } else
  1362. Status = TDI_NO_RESOURCES;
  1363. } else
  1364. Status = TDI_ADDR_INVALID; // Delete already in progress.
  1365. KeReleaseSpinLock(&DeletingAO->ao_lock, OldIrql);
  1366. return Status;
  1367. }
  1368. }
  1369. //* FindAOMCastAddr - Find a multicast address on an AddrObj.
  1370. //
  1371. // A utility routine to find a multicast address on an AddrObj. We also
  1372. // return a pointer to it's predecessor, for use in deleting.
  1373. //
  1374. // A loose comparison treats the unspecified interface (IFNo is 0)
  1375. // specially, selecting the first matching multicast address.
  1376. //
  1377. AOMCastAddr * // Returns: matching AMA structure, or NULL if there is none.
  1378. FindAOMCastAddr(
  1379. AddrObj *AO, // AddrObj to search.
  1380. IPv6Addr *Addr, // MCast address to search for.
  1381. uint IFNo, // The interface number.
  1382. AOMCastAddr **PrevAMA, // Pointer to where to return predecessor.
  1383. BOOLEAN Loose) // Special case the unspecified interface.
  1384. {
  1385. AOMCastAddr *FoundAMA, *Temp;
  1386. Temp = CONTAINING_RECORD(&AO->ao_mcastlist, AOMCastAddr, ama_next);
  1387. FoundAMA = AO->ao_mcastlist;
  1388. while (FoundAMA != NULL) {
  1389. if (IP6_ADDR_EQUAL(Addr, &FoundAMA->ama_addr) &&
  1390. ((IFNo == FoundAMA->ama_if) || ((IFNo == 0) && Loose)))
  1391. break;
  1392. Temp = FoundAMA;
  1393. FoundAMA = FoundAMA->ama_next;
  1394. }
  1395. *PrevAMA = Temp;
  1396. return FoundAMA;
  1397. }
  1398. //* MCastAddrOnAO - Test to see if a multicast address on an AddrObj.
  1399. //
  1400. // A utility routine to test to see if a multicast address is on an AddrObj.
  1401. //
  1402. uint // Returns: TRUE if Addr is on AO.
  1403. MCastAddrOnAO(
  1404. AddrObj *AO, // AddrObj to search.
  1405. IPv6Addr *Addr) // MCast address to search for.
  1406. {
  1407. AOMCastAddr *FoundAMA;
  1408. FoundAMA = AO->ao_mcastlist;
  1409. while (FoundAMA != NULL) {
  1410. if (IP6_ADDR_EQUAL(Addr, &FoundAMA->ama_addr))
  1411. return(TRUE);
  1412. FoundAMA = FoundAMA->ama_next;
  1413. }
  1414. return(FALSE);
  1415. }
  1416. //* DoesAOAllowPacket - Test to see if an AO is allowed to receive a packet.
  1417. //
  1418. // A utility routine to test whether the interface list and protection level
  1419. // of an AddrObj will accept a packet that arrives on a given interface,
  1420. // from a given remote address.
  1421. //
  1422. int // Returns: TRUE if AO can accept packet.
  1423. DoesAOAllowPacket(
  1424. AddrObj *AO, // AddrObj to test.
  1425. Interface *IF, // Interface on which the packet arrived.
  1426. IPv6Addr *RemoteAddr) // Remote address from which the packet arrived.
  1427. {
  1428. //
  1429. // See if an interface list was specified.
  1430. //
  1431. if ((AO->ao_iflist != NULL) &&
  1432. IP6_ADDR_EQUAL(&AO->ao_addr, &UnspecifiedAddr) &&
  1433. (FindIfIndexOnAO(AO, IF) == 0))
  1434. return FALSE;
  1435. //
  1436. // Only accept Teredo if the protection level is unrestricted.
  1437. //
  1438. if ((IF->Type == IF_TYPE_TUNNEL_TEREDO) &&
  1439. (AO->ao_protect != PROTECTION_LEVEL_UNRESTRICTED))
  1440. return FALSE;
  1441. //
  1442. // If the level is restricted, disallow global addresses which
  1443. // are not known to be within one of our sites. Note that we
  1444. // cannot use the IsGlobal() macro here, since we want v4-compatible
  1445. // addresses, etc., to be treated as global.
  1446. //
  1447. if ((AO->ao_protect == PROTECTION_LEVEL_RESTRICTED) &&
  1448. !IsSiteLocal(RemoteAddr) &&
  1449. !IsLinkLocal(RemoteAddr) &&
  1450. !IsLoopback(RemoteAddr) &&
  1451. (SitePrefixMatch(RemoteAddr) == 0))
  1452. return FALSE;
  1453. //
  1454. // TODO: Should eventually replace the simple firewall check here
  1455. // with hooks for ICF.
  1456. //
  1457. if ((IF->Flags & IF_FLAG_FIREWALL_ENABLED) &&
  1458. (AO->ao_dgsend != NULL) &&
  1459. !AO_SENTDATA(AO))
  1460. return FALSE;
  1461. return TRUE;
  1462. }
  1463. //* SetAOOptions - Set AddrObj options.
  1464. //
  1465. // The set options worker routine, called when we've validated the buffer
  1466. // and know that the AddrObj isn't busy.
  1467. //
  1468. TDI_STATUS // Returns: TDI_STATUS of attempt.
  1469. SetAOOptions(
  1470. AddrObj *OptionAO, // AddrObj for which options are being set.
  1471. uint ID,
  1472. uint Length,
  1473. uchar *Options) // AOOption buffer of options.
  1474. {
  1475. IP_STATUS IPStatus; // Status of IP option set request.
  1476. KIRQL OldIrql;
  1477. TDI_STATUS Status;
  1478. AOMCastAddr *AMA, *PrevAMA;
  1479. ASSERT(AO_BUSY(OptionAO));
  1480. if (Length == 0)
  1481. return TDI_BAD_OPTION;
  1482. if (ID == AO_OPTION_UNBIND) {
  1483. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  1484. RemoveAddrObj(OptionAO);
  1485. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  1486. return TDI_SUCCESS;
  1487. }
  1488. Status = TDI_SUCCESS;
  1489. KeAcquireSpinLock(&OptionAO->ao_lock, &OldIrql);
  1490. switch (ID) {
  1491. case AO_OPTION_TTL:
  1492. if (Length >= sizeof(int)) {
  1493. int Hops = (int) *Options;
  1494. if ((Hops >= -1) && (Hops <= 255)) {
  1495. OptionAO->ao_ucast_hops = Hops;
  1496. break;
  1497. }
  1498. }
  1499. Status = TDI_BAD_OPTION;
  1500. break;
  1501. case AO_OPTION_MCASTLOOP:
  1502. if (Length >= sizeof(int)) {
  1503. uint Loop = (uint) *Options;
  1504. if (Loop <= TRUE) {
  1505. OptionAO->ao_mcast_loop = Loop;
  1506. break;
  1507. }
  1508. }
  1509. Status = TDI_BAD_OPTION;
  1510. break;
  1511. case AO_OPTION_MCASTTTL:
  1512. if (Length >= sizeof(int)) {
  1513. int Hops = (int) *Options;
  1514. if ((Hops >= -1) && (Hops <= 255)) {
  1515. OptionAO->ao_mcast_hops = Hops;
  1516. break;
  1517. }
  1518. }
  1519. Status = TDI_BAD_OPTION;
  1520. break;
  1521. case AO_OPTION_MCASTIF:
  1522. if (Length >= sizeof(uint)) {
  1523. OptionAO->ao_mcast_if = (uint) *Options;
  1524. } else
  1525. Status = TDI_BAD_OPTION;
  1526. break;
  1527. case AO_OPTION_ADD_MCAST:
  1528. case AO_OPTION_DEL_MCAST:
  1529. if (Length >= sizeof(IPV6_MREQ)) {
  1530. IPV6_MREQ *Req = (IPV6_MREQ *)Options;
  1531. BOOLEAN IsInterfaceUnspecified = (Req->ipv6mr_interface == 0);
  1532. //
  1533. // Look for this multicast address on this Address Object.
  1534. //
  1535. // NOTE: A loose comparison of the interface index provides
  1536. // the following behavior (when ipv6mr_interface is 0):
  1537. // IPV6_ADD_MEMBERSHIP fails if the specified multicast
  1538. // group has already been added to any interface.
  1539. // IPV6_DROP_MEMBERSHIP drops the first matching multicast
  1540. // group.
  1541. //
  1542. AMA = FindAOMCastAddr(OptionAO, &Req->ipv6mr_multiaddr,
  1543. Req->ipv6mr_interface, &PrevAMA, TRUE);
  1544. if (ID == AO_OPTION_ADD_MCAST) {
  1545. // This is an add request. Fail it if it's already there.
  1546. if (AMA != NULL) {
  1547. // Address is already present on AO.
  1548. Status = TDI_BAD_OPTION;
  1549. break;
  1550. }
  1551. AMA = ExAllocatePool(NonPagedPool, sizeof(AOMCastAddr));
  1552. if (AMA == NULL) {
  1553. // Couldn't get the resource we need.
  1554. Status = TDI_NO_RESOURCES;
  1555. break;
  1556. }
  1557. // Add it to the list.
  1558. AMA->ama_next = OptionAO->ao_mcastlist;
  1559. OptionAO->ao_mcastlist = AMA;
  1560. // Fill in the address and interface information.
  1561. AMA->ama_addr = Req->ipv6mr_multiaddr;
  1562. AMA->ama_if = Req->ipv6mr_interface;
  1563. } else {
  1564. // This is a delete request. Fail it if it's not there.
  1565. if (AMA == NULL) {
  1566. // Address is not present on AO.
  1567. Status = TDI_BAD_OPTION;
  1568. break;
  1569. }
  1570. // Remove it from the list.
  1571. PrevAMA->ama_next = AMA->ama_next;
  1572. ExFreePool(AMA);
  1573. }
  1574. // Drop the AO lock since MLDAddMCastAddr/MLDDropMCastAddr
  1575. // assume that they are called with no locks held.
  1576. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1577. if (ID == AO_OPTION_ADD_MCAST) {
  1578. // If the interface is unspecified, MLDAddMCastAddr will
  1579. // try to pick a reasonable interface and then return
  1580. // the interface number that it picked.
  1581. IPStatus = MLDAddMCastAddr(&Req->ipv6mr_interface,
  1582. &Req->ipv6mr_multiaddr);
  1583. } else
  1584. IPStatus = MLDDropMCastAddr(Req->ipv6mr_interface,
  1585. &Req->ipv6mr_multiaddr);
  1586. KeAcquireSpinLock(&OptionAO->ao_lock, &OldIrql);
  1587. // Since we dropped the AO lock, we have to search for our
  1588. // AMA again if we need it. In fact, it might even have
  1589. // been deleted!
  1590. if ((ID == AO_OPTION_ADD_MCAST) &&
  1591. ((IPStatus != TDI_SUCCESS) || IsInterfaceUnspecified)) {
  1592. AMA = FindAOMCastAddr(
  1593. OptionAO, &Req->ipv6mr_multiaddr,
  1594. IsInterfaceUnspecified ? 0 : Req->ipv6mr_interface,
  1595. &PrevAMA, FALSE);
  1596. if (AMA != NULL) {
  1597. if (IPStatus != TDI_SUCCESS) {
  1598. // Some problem adding or deleting. If we were
  1599. // adding, we remove and free the one we just added.
  1600. PrevAMA->ama_next = AMA->ama_next;
  1601. ExFreePool(AMA);
  1602. } else {
  1603. // Interface 0 was specified, assign AMA->ama_if
  1604. // to the interface selected by MLDAddMCastAddr.
  1605. // Hence, incoming multicast packets will only
  1606. // be accepted on this AMA if they arrive on the
  1607. // chosen interface.
  1608. AMA->ama_if = Req->ipv6mr_interface;
  1609. }
  1610. }
  1611. }
  1612. if (IPStatus != TDI_SUCCESS)
  1613. Status = (IPStatus == IP_NO_RESOURCES) ? TDI_NO_RESOURCES :
  1614. TDI_ADDR_INVALID;
  1615. } else
  1616. Status = TDI_BAD_OPTION;
  1617. break;
  1618. case AO_OPTION_UDP_CKSUM_COVER:
  1619. if (Length >= sizeof(ushort)) {
  1620. ushort Value = *(ushort *)Options;
  1621. if ((0 < Value) && (Value < sizeof(UDPHeader)))
  1622. Status = TDI_BAD_OPTION;
  1623. else
  1624. OptionAO->ao_udp_cksum_cover = Value;
  1625. } else
  1626. Status = TDI_BAD_OPTION;
  1627. break;
  1628. case AO_OPTION_IP_HDRINCL:
  1629. if (Length >= sizeof(int)) {
  1630. uint HdrIncl = (uint) *Options;
  1631. if (HdrIncl <= TRUE) {
  1632. if (HdrIncl)
  1633. SET_AO_HDRINCL(OptionAO);
  1634. else
  1635. CLEAR_AO_HDRINCL(OptionAO);
  1636. break;
  1637. }
  1638. }
  1639. Status = TDI_BAD_OPTION;
  1640. break;
  1641. case AO_OPTION_IFLIST:
  1642. //
  1643. // Determine whether the interface-list is being enabled or cleared.
  1644. // When enabled, an empty zero-terminated interface-list is set.
  1645. // When disabled, any existing interface-list is freed.
  1646. //
  1647. // In both cases, the 'ao_iflist' pointer in the object is replaced
  1648. // using an interlocked operation to allow us to check the field
  1649. // in the receive-path without first locking the address-object.
  1650. //
  1651. if (Options[0]) {
  1652. if (OptionAO->ao_iflist) {
  1653. Status = TDI_SUCCESS;
  1654. } else if (!IP6_ADDR_EQUAL(&OptionAO->ao_addr, &UnspecifiedAddr)) {
  1655. Status = TDI_INVALID_PARAMETER;
  1656. } else {
  1657. uint *IfList = ExAllocatePool(NonPagedPool, sizeof(uint));
  1658. if (IfList == NULL) {
  1659. Status = TDI_NO_RESOURCES;
  1660. } else {
  1661. *IfList = 0;
  1662. OptionAO->ao_iflist = IfList;
  1663. Status = TDI_SUCCESS;
  1664. }
  1665. }
  1666. } else {
  1667. if (OptionAO->ao_iflist) {
  1668. ExFreePool(OptionAO->ao_iflist);
  1669. OptionAO->ao_iflist = NULL;
  1670. }
  1671. Status = TDI_SUCCESS;
  1672. }
  1673. break;
  1674. case AO_OPTION_ADD_IFLIST:
  1675. //
  1676. // An interface-index is being added to the object's interface-list
  1677. // so verify that an interface-list exists and, if not, fail.
  1678. // Otherwise, verify that the index specified is valid and, if so,
  1679. // verify that the index is not already in the interface list.
  1680. //
  1681. if (OptionAO->ao_iflist == NULL) {
  1682. Status = TDI_INVALID_PARAMETER;
  1683. } else {
  1684. uint IfIndex = *(uint *)Options;
  1685. Interface *IF = FindInterfaceFromIndex(IfIndex);
  1686. if (IF == NULL) {
  1687. Status = TDI_ADDR_INVALID;
  1688. } else {
  1689. uint i = 0;
  1690. ReleaseIF(IF);
  1691. while (OptionAO->ao_iflist[i] != 0 &&
  1692. OptionAO->ao_iflist[i] != IfIndex) {
  1693. i++;
  1694. }
  1695. if (OptionAO->ao_iflist[i] == IfIndex) {
  1696. Status = TDI_SUCCESS;
  1697. } else {
  1698. //
  1699. // The index to be added is not already present.
  1700. // Allocate space for an expanded interface-list,
  1701. // copy the old interface-list, append the new index,
  1702. // and replace the old interface-list using an
  1703. // interlocked operation.
  1704. //
  1705. uint *IfList = ExAllocatePool(NonPagedPool,
  1706. (i + 2) * sizeof(uint));
  1707. if (IfList == NULL) {
  1708. Status = TDI_NO_RESOURCES;
  1709. } else {
  1710. RtlCopyMemory(IfList, OptionAO->ao_iflist,
  1711. i * sizeof(uint));
  1712. IfList[i] = IfIndex;
  1713. IfList[i + 1] = 0;
  1714. ExFreePool(OptionAO->ao_iflist);
  1715. OptionAO->ao_iflist = IfList;
  1716. Status = TDI_SUCCESS;
  1717. }
  1718. }
  1719. }
  1720. }
  1721. break;
  1722. case AO_OPTION_DEL_IFLIST:
  1723. //
  1724. // An index is being removed from the object's interface-list,
  1725. // so verify that an interface-list exists and, if not, fail.
  1726. // Otherwise, search the list for the index and, if not found, fail.
  1727. //
  1728. // N.B. We do not validate the index first in this case, to allow
  1729. // an index to be removed even after the corresponding interface
  1730. // is no longer present.
  1731. //
  1732. if (OptionAO->ao_iflist == NULL) {
  1733. Status = TDI_INVALID_PARAMETER;
  1734. } else {
  1735. uint IfIndex = *(uint *) Options;
  1736. if (IfIndex == 0) {
  1737. Status = TDI_ADDR_INVALID;
  1738. } else {
  1739. uint j = (uint)-1;
  1740. uint i = 0;
  1741. while (OptionAO->ao_iflist[i] != 0) {
  1742. if (OptionAO->ao_iflist[i] == IfIndex) {
  1743. j = i;
  1744. }
  1745. i++;
  1746. }
  1747. if (j == (uint)-1) {
  1748. Status = TDI_ADDR_INVALID;
  1749. } else {
  1750. //
  1751. // We've found the index to be removed.
  1752. // Allocate a truncated interface-list, copy the old
  1753. // interface-list excluding the removed index, and
  1754. // replace the old interface-list using an interlocked
  1755. // operation.
  1756. //
  1757. uint *IfList = ExAllocatePool(NonPagedPool,
  1758. i * sizeof(uint));
  1759. if (IfList == NULL) {
  1760. Status = TDI_NO_RESOURCES;
  1761. } else {
  1762. i = 0;
  1763. j = 0;
  1764. while (OptionAO->ao_iflist[i] != 0) {
  1765. if (OptionAO->ao_iflist[i] != IfIndex) {
  1766. IfList[j++] = OptionAO->ao_iflist[i];
  1767. }
  1768. i++;
  1769. }
  1770. IfList[j] = 0;
  1771. ExFreePool(OptionAO->ao_iflist);
  1772. OptionAO->ao_iflist = IfList;
  1773. Status = TDI_SUCCESS;
  1774. }
  1775. }
  1776. }
  1777. }
  1778. break;
  1779. case AO_OPTION_IP_PKTINFO:
  1780. if (Options[0])
  1781. SET_AO_PKTINFO(OptionAO);
  1782. else
  1783. CLEAR_AO_PKTINFO(OptionAO);
  1784. break;
  1785. case AO_OPTION_RCV_HOPLIMIT:
  1786. if (Options[0])
  1787. SET_AO_RCV_HOPLIMIT(OptionAO);
  1788. else
  1789. CLEAR_AO_RCV_HOPLIMIT(OptionAO);
  1790. break;
  1791. case AO_OPTION_PROTECT:
  1792. if (Length >= sizeof(int)) {
  1793. int Level = (int) *Options;
  1794. if ((Level == PROTECTION_LEVEL_RESTRICTED) ||
  1795. (Level == PROTECTION_LEVEL_DEFAULT) ||
  1796. (Level == PROTECTION_LEVEL_UNRESTRICTED)) {
  1797. OptionAO->ao_protect = Level;
  1798. break;
  1799. }
  1800. }
  1801. Status = TDI_BAD_OPTION;
  1802. break;
  1803. default:
  1804. Status = TDI_BAD_OPTION;
  1805. break;
  1806. }
  1807. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1808. return Status;
  1809. }
  1810. //* SetAddrOptions - Set options on an address object.
  1811. //
  1812. // Called to set options on an address object. We validate the buffer,
  1813. // and if everything is OK we'll check the status of the AddrObj. If
  1814. // it's OK then we'll set them, otherwise we'll mark it for later use.
  1815. //
  1816. TDI_STATUS // Returns: TDI_STATUS of attempt.
  1817. SetAddrOptions(
  1818. PTDI_REQUEST Request, // Request describing AddrObj for option set.
  1819. uint ID, // ID for option to be set.
  1820. uint OptLength, // Length of options.
  1821. void *Options) // Pointer to options.
  1822. {
  1823. AddrObj *OptionAO;
  1824. TDI_STATUS Status;
  1825. KIRQL OldIrql;
  1826. OptionAO = Request->Handle.AddressHandle;
  1827. CHECK_STRUCT(OptionAO, ao);
  1828. KeAcquireSpinLock(&OptionAO->ao_lock, &OldIrql);
  1829. if (AO_VALID(OptionAO)) {
  1830. if (!AO_BUSY(OptionAO) && OptionAO->ao_usecnt == 0) {
  1831. SET_AO_BUSY(OptionAO);
  1832. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1833. Status = SetAOOptions(OptionAO, ID, OptLength, Options);
  1834. KeAcquireSpinLock(&OptionAO->ao_lock, &OldIrql);
  1835. if (!AO_PENDING(OptionAO)) {
  1836. CLEAR_AO_BUSY(OptionAO);
  1837. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1838. return Status;
  1839. } else {
  1840. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1841. ProcessAORequests(OptionAO);
  1842. return Status;
  1843. }
  1844. } else {
  1845. AORequest *NewRequest, *OldRequest;
  1846. // The AddrObj is busy somehow. We need to get a request, and link
  1847. // him on the request list.
  1848. NewRequest = GetAORequest();
  1849. if (NewRequest != NULL) {
  1850. // Got a request.
  1851. NewRequest->aor_rtn = Request->RequestNotifyObject;
  1852. NewRequest->aor_context = Request->RequestContext;
  1853. NewRequest->aor_id = ID;
  1854. NewRequest->aor_length = OptLength;
  1855. NewRequest->aor_buffer = Options;
  1856. NewRequest->aor_next = NULL;
  1857. // Set the option request.
  1858. SET_AO_REQUEST(OptionAO, AO_OPTIONS);
  1859. OldRequest = CONTAINING_RECORD(&OptionAO->ao_request,
  1860. AORequest, aor_next);
  1861. while (OldRequest->aor_next != NULL)
  1862. OldRequest = OldRequest->aor_next;
  1863. OldRequest->aor_next = NewRequest;
  1864. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1865. return TDI_PENDING;
  1866. } else
  1867. Status = TDI_NO_RESOURCES;
  1868. }
  1869. } else
  1870. Status = TDI_ADDR_INVALID;
  1871. KeReleaseSpinLock(&OptionAO->ao_lock, OldIrql);
  1872. return Status;
  1873. }
  1874. //* TDISetEvent - Set a handler for a particular event.
  1875. //
  1876. // This is the user API to set an event. It's pretty simple, we just
  1877. // grab the lock on the AddrObj and fill in the event.
  1878. //
  1879. // This routine never pends.
  1880. //
  1881. TDI_STATUS // Returns: TDI_SUCCESS if it works, an error if it doesn't.
  1882. TdiSetEvent(
  1883. PVOID Handle, // Pointer to address object.
  1884. int Type, // Event being set.
  1885. PVOID Handler, // Handler to call for event.
  1886. PVOID Context) // Context to pass to event.
  1887. {
  1888. AddrObj *EventAO;
  1889. KIRQL OldIrql;
  1890. TDI_STATUS Status;
  1891. EventAO = (AddrObj *)Handle;
  1892. CHECK_STRUCT(EventAO, ao);
  1893. if (!AO_VALID(EventAO))
  1894. return TDI_ADDR_INVALID;
  1895. KeAcquireSpinLock(&EventAO->ao_lock, &OldIrql);
  1896. Status = TDI_SUCCESS;
  1897. switch (Type) {
  1898. case TDI_EVENT_CONNECT:
  1899. EventAO->ao_connect = Handler;
  1900. EventAO->ao_conncontext = Context;
  1901. break;
  1902. case TDI_EVENT_DISCONNECT:
  1903. EventAO->ao_disconnect = Handler;
  1904. EventAO->ao_disconncontext = Context;
  1905. break;
  1906. case TDI_EVENT_ERROR:
  1907. EventAO->ao_error = Handler;
  1908. EventAO->ao_errcontext = Context;
  1909. break;
  1910. case TDI_EVENT_RECEIVE:
  1911. EventAO->ao_rcv = Handler;
  1912. EventAO->ao_rcvcontext = Context;
  1913. break;
  1914. case TDI_EVENT_RECEIVE_DATAGRAM:
  1915. EventAO->ao_rcvdg = Handler;
  1916. EventAO->ao_rcvdgcontext = Context;
  1917. break;
  1918. case TDI_EVENT_RECEIVE_EXPEDITED:
  1919. EventAO->ao_exprcv = Handler;
  1920. EventAO->ao_exprcvcontext = Context;
  1921. break;
  1922. case TDI_EVENT_ERROR_EX:
  1923. EventAO->ao_errorex = Handler;
  1924. EventAO->ao_errorexcontext = Context;
  1925. break;
  1926. default:
  1927. Status = TDI_BAD_EVENT_TYPE;
  1928. break;
  1929. }
  1930. KeReleaseSpinLock(&EventAO->ao_lock, OldIrql);
  1931. return Status;
  1932. }
  1933. //* ProcessAORequests - Process pending requests on an AddrObj.
  1934. //
  1935. // This is the delayed request processing routine, called when we've
  1936. // done something that used the busy bit. We examine the pending
  1937. // requests flags, and dispatch the requests appropriately.
  1938. //
  1939. void // Returns: Nothing.
  1940. ProcessAORequests(
  1941. AddrObj *RequestAO) // AddrObj to be processed.
  1942. {
  1943. KIRQL OldIrql;
  1944. AORequest *Request;
  1945. CHECK_STRUCT(RequestAO, ao);
  1946. ASSERT(AO_BUSY(RequestAO));
  1947. ASSERT(RequestAO->ao_usecnt == 0);
  1948. KeAcquireSpinLock(&RequestAO->ao_lock, &OldIrql);
  1949. while (AO_PENDING(RequestAO)) {
  1950. Request = RequestAO->ao_request;
  1951. if (AO_REQUEST(RequestAO, AO_DELETE)) {
  1952. ASSERT(Request != NULL);
  1953. ASSERT(!AO_REQUEST(RequestAO, AO_OPTIONS));
  1954. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  1955. DeleteAO(RequestAO);
  1956. (*Request->aor_rtn)(Request->aor_context, TDI_SUCCESS, 0);
  1957. FreeAORequest(Request);
  1958. return; // Deleted him, so get out.
  1959. }
  1960. // Now handle options request.
  1961. while (AO_REQUEST(RequestAO, AO_OPTIONS)) {
  1962. TDI_STATUS Status;
  1963. // Have an option request.
  1964. Request = RequestAO->ao_request;
  1965. RequestAO->ao_request = Request->aor_next;
  1966. if (RequestAO->ao_request == NULL)
  1967. CLEAR_AO_REQUEST(RequestAO, AO_OPTIONS);
  1968. ASSERT(Request != NULL);
  1969. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  1970. Status = SetAOOptions(RequestAO, Request->aor_id,
  1971. Request->aor_length, Request->aor_buffer);
  1972. (*Request->aor_rtn)(Request->aor_context, Status, 0);
  1973. FreeAORequest(Request);
  1974. KeAcquireSpinLock(&RequestAO->ao_lock, &OldIrql);
  1975. }
  1976. // We've done options, now try sends.
  1977. if (AO_REQUEST(RequestAO, AO_SEND)) {
  1978. DGSendProc SendProc;
  1979. DGSendReq *SendReq;
  1980. // Need to send. Clear the busy flag, bump the send count, and
  1981. // get the send request.
  1982. if (!EMPTYQ(&RequestAO->ao_sendq)) {
  1983. DEQUEUE(&RequestAO->ao_sendq, SendReq, DGSendReq, dsr_q);
  1984. CLEAR_AO_BUSY(RequestAO);
  1985. RequestAO->ao_usecnt++;
  1986. SendProc = RequestAO->ao_dgsend;
  1987. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  1988. (*SendProc)(RequestAO, SendReq);
  1989. KeAcquireSpinLock(&RequestAO->ao_lock, &OldIrql);
  1990. // If there aren't any other pending sends, set the busy bit.
  1991. if (!(--RequestAO->ao_usecnt))
  1992. SET_AO_BUSY(RequestAO);
  1993. else
  1994. break; // Still sending, so get out.
  1995. } else {
  1996. // Had the send request set, but no send! Odd....
  1997. KdBreakPoint();
  1998. CLEAR_AO_REQUEST(RequestAO, AO_SEND);
  1999. }
  2000. }
  2001. }
  2002. // We're done here.
  2003. CLEAR_AO_BUSY(RequestAO);
  2004. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  2005. }
  2006. //* DelayDerefAO - Dereference an AddrObj, and schedule an event.
  2007. //
  2008. // Called when we are done with an address object, and need to
  2009. // derefrence it. We dec the usecount, and if it goes to 0 and
  2010. // if there are pending actions we'll schedule an event to deal
  2011. // with them.
  2012. //
  2013. void // Returns: Nothing.
  2014. DelayDerefAO(
  2015. AddrObj *RequestAO) // AddrObj to be processed.
  2016. {
  2017. KIRQL OldIrql;
  2018. KeAcquireSpinLock(&RequestAO->ao_lock, &OldIrql);
  2019. RequestAO->ao_usecnt--;
  2020. if (!RequestAO->ao_usecnt && !AO_BUSY(RequestAO)) {
  2021. if (AO_PENDING(RequestAO)) {
  2022. SET_AO_BUSY(RequestAO);
  2023. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  2024. ExQueueWorkItem(&RequestAO->ao_workitem, CriticalWorkQueue);
  2025. return;
  2026. }
  2027. }
  2028. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  2029. }
  2030. //* DerefAO - Derefrence an AddrObj.
  2031. //
  2032. // Called when we are done with an address object, and need to
  2033. // derefrence it. We dec the usecount, and if it goes to 0 and
  2034. // if there are pending actions we'll call the process AO handler.
  2035. //
  2036. void // Returns: Nothing.
  2037. DerefAO(
  2038. AddrObj *RequestAO) // AddrObj to be processed.
  2039. {
  2040. KIRQL OldIrql;
  2041. KeAcquireSpinLock(&RequestAO->ao_lock, &OldIrql);
  2042. RequestAO->ao_usecnt--;
  2043. if (!RequestAO->ao_usecnt && !AO_BUSY(RequestAO)) {
  2044. if (AO_PENDING(RequestAO)) {
  2045. SET_AO_BUSY(RequestAO);
  2046. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  2047. ProcessAORequests(RequestAO);
  2048. return;
  2049. }
  2050. }
  2051. KeReleaseSpinLock(&RequestAO->ao_lock, OldIrql);
  2052. }
  2053. #pragma BEGIN_INIT
  2054. //* InitAddr - Initialize the address object stuff.
  2055. //
  2056. // Called during init time to initalize the address object stuff.
  2057. //
  2058. int // Returns: True if we succeed, False if we fail.
  2059. InitAddr()
  2060. {
  2061. uint i;
  2062. KeInitializeSpinLock(&AddrObjTableLock);
  2063. KeInitializeMutex(&AddrSDMutex, FALSE);
  2064. if (MmIsThisAnNtAsSystem()) {
  2065. #if defined(_WIN64)
  2066. AddrObjTableSize = DEFAULT_AO_TABLE_SIZE_AS64;
  2067. #else
  2068. AddrObjTableSize = DEFAULT_AO_TABLE_SIZE_AS;
  2069. #endif
  2070. } else {
  2071. AddrObjTableSize = DEFAULT_AO_TABLE_SIZE_WS;
  2072. }
  2073. AddrObjTable = ExAllocatePool(NonPagedPool,
  2074. AddrObjTableSize * sizeof(AddrObj*));
  2075. if (AddrObjTable == NULL) {
  2076. return FALSE;
  2077. }
  2078. for (i = 0; i < AddrObjTableSize; i++)
  2079. AddrObjTable[i] = NULL;
  2080. LastAO = NULL;
  2081. RtlInitializeBitMap(&PortBitmapTcp, PortBitmapBufferTcp, 1 << 16);
  2082. RtlInitializeBitMap(&PortBitmapUdp, PortBitmapBufferUdp, 1 << 16);
  2083. RtlClearAllBits(&PortBitmapTcp);
  2084. RtlClearAllBits(&PortBitmapUdp);
  2085. return TRUE;
  2086. }
  2087. #pragma END_INIT
  2088. //* AddrUnload
  2089. //
  2090. // Cleanup and prepare the address management code for stack unload.
  2091. //
  2092. void
  2093. AddrUnload(void)
  2094. {
  2095. ExFreePool(AddrObjTable);
  2096. AddrObjTable = NULL;
  2097. return;
  2098. }