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.

782 lines
24 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-2000 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //*** iploop.c - IP loopback routines.
  7. //
  8. // This file contains all the routines related to loopback
  9. #include "precomp.h"
  10. #include "iprtdef.h"
  11. #include "iproute.h"
  12. #include "tcpipbuf.h"
  13. #define LOOP_LOOKAHEAD MAX_HDR_SIZE + 8
  14. extern int NumNTE;
  15. extern int NumActiveNTE;
  16. extern Interface *IFList;
  17. extern uint NumIF;
  18. extern BOOLEAN CopyToNdisSafe(PNDIS_BUFFER DestBuf, PNDIS_BUFFER * ppNextBuf,
  19. uchar * SrcBuf, uint Size, uint * StartOffset);
  20. CACHE_LINE_KSPIN_LOCK LoopLock;
  21. PNDIS_PACKET LoopXmitHead = (PNDIS_PACKET) NULL;
  22. PNDIS_PACKET LoopXmitTail = (PNDIS_PACKET) NULL;
  23. CTEEvent LoopXmitEvent;
  24. RouteInterface LoopInterface; // Loopback interface.
  25. uint LoopXmitRtnRunning = 0;
  26. int LoopGetEList(void *Context, TDIEntityID *EntityList, uint *Count);
  27. NetTableEntry *InitLoopback(IPConfigInfo * ConfigInfo);
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE, LoopGetEList)
  30. #pragma alloc_text(INIT, InitLoopback)
  31. #endif // ALLOC_PRAGMA
  32. uint LoopIndex; // Index of loop I/F.
  33. uint LoopInstance = (uint) INVALID_ENTITY_INSTANCE; // I/F instance of loopback I/F.
  34. NetTableEntry *LoopNTE; // Pointer to loopback NTE.
  35. IFEntry LoopIFE; // Loopback IF Entry.
  36. uchar LoopName[] = "MS TCP Loopback interface";
  37. uint LoopEntityType = IF_MIB;
  38. //* LoopSetAffinity - Sets or resets the affinity of a thread.
  39. //
  40. // This routine is used to affinitize the loopback thread upon entry to the
  41. // processor it would be running on at that time and to remove the affinity
  42. // upon exit. This is done in order to assure that receives and receive-
  43. // completions happen on the same processor on the loopback interface.
  44. //
  45. // Entry: SetAffinity - Sets the affinity if TRUE, resets otherwise.
  46. //
  47. // Returns: Nothing.
  48. //
  49. __inline VOID
  50. LoopSetAffinity(BOOLEAN SetAffinity)
  51. {
  52. KAFFINITY affinityMask;
  53. if (KeNumberProcessors == 1) {
  54. return;
  55. }
  56. if (SetAffinity) {
  57. affinityMask = (1 << KeGetCurrentProcessorNumber());
  58. } else {
  59. affinityMask = ((1 << KeNumberProcessors) - 1);
  60. }
  61. ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask,
  62. &affinityMask, sizeof(affinityMask));
  63. }
  64. //* LoopXmitRtn - Loopback xmit event routine.
  65. //
  66. // This is the delayed event routine called for a loopback transmit.
  67. //
  68. // Entry: Event - Pointer to event structure.
  69. // Context - Pointer to loopback NTE
  70. //
  71. // Returns: Nothing.
  72. //
  73. void
  74. LoopXmitRtn(CTEEvent *Event, void *Context)
  75. {
  76. PNDIS_PACKET Packet; // Pointer to packet being transmitted
  77. PNDIS_BUFFER Buffer; // Current NDIS buffer being processed.
  78. uint TotalLength; // Total length of send.
  79. uint LookaheadLength; // Bytes in lookahead.
  80. uint Copied; // Bytes copied so far.
  81. uchar *CopyPtr; // Pointer to buffer being copied into.
  82. uchar *SrcPtr; // Pointer to buffer being copied from.
  83. uint SrcLength; // Length of src buffer.
  84. uchar LookaheadBuffer[LOOP_LOOKAHEAD];
  85. uchar Rcvd = FALSE;
  86. #if !MILLEN
  87. KIRQL OldIrql;
  88. #endif // !MILLEN
  89. UNREFERENCED_PARAMETER(Event);
  90. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  91. //
  92. // Raise IRQL so we can acquire locks at DPC level in the receive code.
  93. // On Windows ME, this is NOT done since receive indications are in the
  94. // context of a global event rather than DPC (in fact due to TDI client
  95. // restrictions, TCP/IP can't indicate up at DPC, so care must be taken).
  96. //
  97. #if !MILLEN
  98. LoopSetAffinity(TRUE);
  99. KeEnterCriticalRegion();
  100. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  101. #endif // !MILLEN
  102. CTEGetLockAtDPC(&LoopLock.Lock);
  103. if (LoopXmitRtnRunning) {
  104. CTEFreeLockFromDPC(&LoopLock.Lock);
  105. #if !MILLEN
  106. KeLowerIrql(OldIrql);
  107. KeLeaveCriticalRegion();
  108. LoopSetAffinity(FALSE);
  109. #endif // !MILLEN
  110. return;
  111. }
  112. LoopXmitRtnRunning = 1;
  113. for (;;) {
  114. Packet = LoopXmitHead; // Get the next packet from the list.
  115. if (Packet != (PNDIS_PACKET) NULL) {
  116. LoopXmitHead = *(PNDIS_PACKET *) Packet->MacReserved;
  117. LoopIFE.if_outqlen--;
  118. CTEFreeLockFromDPC(&LoopLock.Lock);
  119. } else { // Nothing left to do.
  120. LoopXmitRtnRunning = 0;
  121. CTEFreeLockFromDPC(&LoopLock.Lock);
  122. break;
  123. }
  124. // See if the interface is up. If it's not, we can't deliver it.
  125. if (LoopIFE.if_adminstatus == IF_STATUS_UP) {
  126. NdisQueryPacket(Packet, NULL, NULL, &Buffer, &TotalLength);
  127. LoopIFE.if_outoctets += TotalLength;
  128. LoopIFE.if_inoctets += TotalLength;
  129. LookaheadLength = MIN(LOOP_LOOKAHEAD, TotalLength);
  130. Copied = 0;
  131. CopyPtr = LookaheadBuffer;
  132. while (Copied < LookaheadLength) {
  133. uint ThisCopy; // Bytes to copy this time.
  134. ASSERT(Buffer);
  135. TcpipQueryBuffer(Buffer, &SrcPtr, &SrcLength, NormalPagePriority);
  136. if (SrcPtr == NULL) {
  137. IPSendComplete(Context, Packet, NDIS_STATUS_RESOURCES);
  138. CTEGetLockAtDPC(&LoopLock.Lock);
  139. LoopXmitRtnRunning = 0;
  140. LoopIFE.if_indiscards++;
  141. CTEFreeLockFromDPC(&LoopLock.Lock);
  142. #if !MILLEN
  143. KeLowerIrql(OldIrql);
  144. KeLeaveCriticalRegion();
  145. LoopSetAffinity(FALSE);
  146. #endif // !MILLEN
  147. return;
  148. }
  149. ThisCopy = MIN(SrcLength, LookaheadLength - Copied);
  150. RtlCopyMemory(CopyPtr, SrcPtr, ThisCopy);
  151. Copied += ThisCopy;
  152. CopyPtr += ThisCopy;
  153. NdisGetNextBuffer(Buffer, &Buffer);
  154. }
  155. Rcvd = TRUE;
  156. LoopIFE.if_inucastpkts++;
  157. // Call the RcvPacket Handler
  158. IPRcvPacket(Context, LookaheadBuffer, LookaheadLength, TotalLength,
  159. (NDIS_HANDLE) Packet, 0, FALSE, 0, NULL, (PUINT) Packet,
  160. NULL);
  161. } else {
  162. LoopIFE.if_indiscards++;
  163. }
  164. IPSendComplete(Context, Packet, NDIS_STATUS_SUCCESS);
  165. #if !MILLEN
  166. //
  167. // Give other threads a chance to run.
  168. // Block special k mode APC delivery
  169. // so that thread will not be blocked
  170. // in a completion routine
  171. //
  172. KeLowerIrql(OldIrql);
  173. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  174. #endif // !MILLEN
  175. CTEGetLockAtDPC(&LoopLock.Lock);
  176. }
  177. if (Rcvd) {
  178. IPRcvComplete();
  179. }
  180. #if !MILLEN
  181. KeLowerIrql(OldIrql);
  182. KeLeaveCriticalRegion();
  183. LoopSetAffinity(FALSE);
  184. #endif // !MILLEN
  185. }
  186. //** LoopXmit - Transmit a loopback packet.
  187. //
  188. // This is the routine called when we need to transmit a packet to ourselves.
  189. // We put the packet on our loopback list, and schedule an event to deal
  190. // with it.
  191. //
  192. // Entry: Context - Pointer to the loopback NTE.
  193. // Packet - Pointer to packet to be transmitted.
  194. // Dest - Destination addres of packet.
  195. // RCE - Pointer to RCE (should be NULL).
  196. //
  197. // Returns: NDIS_STATUS_PENDING
  198. //
  199. NDIS_STATUS
  200. __stdcall
  201. LoopXmit(void *Context, PNDIS_PACKET *PacketArray, uint NoPackets,
  202. IPAddr Dest, RouteCacheEntry * RCE, void *LinkCtxt)
  203. {
  204. PNDIS_PACKET *PacketPtr;
  205. CTELockHandle Handle;
  206. PNDIS_PACKET Packet = *PacketArray;
  207. UNREFERENCED_PARAMETER(Dest);
  208. UNREFERENCED_PARAMETER(RCE);
  209. UNREFERENCED_PARAMETER(LinkCtxt);
  210. UNREFERENCED_PARAMETER(NoPackets);
  211. ASSERT(NoPackets == 1);
  212. LoopIFE.if_outucastpkts++;
  213. if (LoopIFE.if_adminstatus == IF_STATUS_UP) {
  214. PacketPtr = (PNDIS_PACKET *) Packet->MacReserved;
  215. *PacketPtr = (PNDIS_PACKET) NULL;
  216. CTEGetLock(&LoopLock.Lock, &Handle);
  217. if (LoopXmitHead == (PNDIS_PACKET) NULL) { // Xmit. Q is empty
  218. LoopXmitHead = Packet;
  219. } else { // Xmit. Q is not empty
  220. PacketPtr = (PNDIS_PACKET *) LoopXmitTail->MacReserved;
  221. *PacketPtr = Packet;
  222. }
  223. LoopXmitTail = Packet;
  224. LoopIFE.if_outqlen++;
  225. if (!LoopXmitRtnRunning) {
  226. CTEScheduleDelayedEvent(&LoopXmitEvent, Context);
  227. }
  228. CTEFreeLock(&LoopLock.Lock, Handle);
  229. return NDIS_STATUS_PENDING;
  230. } else {
  231. LoopIFE.if_outdiscards++;
  232. return NDIS_STATUS_SUCCESS;
  233. }
  234. }
  235. //* LoopXfer - Loopback transfer data routine.
  236. //
  237. // Called when we need to transfer data for the loopback net. The input
  238. // TDContext is the original packet.
  239. //
  240. // Entry: Context - Pointer to loopback NTE.
  241. // TDContext - Original packet that was sent.
  242. // Dummy - Unused
  243. // Offset - Offset in frame from which to start copying.
  244. // BytesToCopy - Number of bytes to copy.
  245. // DestPacket - Packet describing buffer to copy into.
  246. // BytesCopied - Place to return bytes copied.
  247. //
  248. // Returns: NDIS_STATUS_SUCCESS
  249. //
  250. NDIS_STATUS
  251. __stdcall
  252. LoopXfer(void *Context, NDIS_HANDLE TDContext, uint Dummy, uint Offset,
  253. uint BytesToCopy, PNDIS_PACKET DestPacket, uint *BytesCopied)
  254. {
  255. PNDIS_BUFFER SrcBuffer; // Current buffer we're copying from.
  256. PNDIS_PACKET SrcPacket = (PNDIS_PACKET) TDContext;
  257. uchar *SrcPtr; // Where we're copying from.
  258. uint SrcLength; // Length of current src buffer.
  259. PNDIS_BUFFER DestBuffer; // Buffer we're copying to.
  260. uchar *DestPtr; // Where we're copying to.
  261. uint DestLength; // Length of current dest. buffer.
  262. uint Copied; // Length we've copied so far.
  263. NDIS_STATUS Status;
  264. UNREFERENCED_PARAMETER(Context);
  265. UNREFERENCED_PARAMETER(Dummy);
  266. // First, skip over Offset bytes in the packet.
  267. NdisQueryPacket(SrcPacket, NULL, NULL, &SrcBuffer, NULL);
  268. ASSERT(SrcBuffer);
  269. TcpipQueryBuffer(SrcBuffer, &SrcPtr, &SrcLength, NormalPagePriority);
  270. if (SrcPtr == NULL) {
  271. return NDIS_STATUS_RESOURCES;
  272. }
  273. while (Offset >= SrcLength) {
  274. Offset -= SrcLength;
  275. NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
  276. ASSERT(SrcBuffer);
  277. TcpipQueryBuffer(SrcBuffer, &SrcPtr, &SrcLength, NormalPagePriority);
  278. if (SrcPtr == NULL) {
  279. return NDIS_STATUS_RESOURCES;
  280. }
  281. }
  282. // Update Src pointer and length.
  283. SrcPtr += Offset;
  284. SrcLength -= Offset;
  285. // Set up the destination pointers and lengths.
  286. NdisQueryPacket(DestPacket, NULL, NULL, &DestBuffer, NULL);
  287. TcpipQueryBuffer(DestBuffer, &DestPtr, &DestLength, NormalPagePriority);
  288. if (DestPtr == NULL) {
  289. return NDIS_STATUS_RESOURCES;
  290. }
  291. Copied = 0;
  292. Status = NDIS_STATUS_SUCCESS;
  293. while (BytesToCopy) {
  294. uint ThisCopy; // What we're copying this time.
  295. ThisCopy = MIN(SrcLength, DestLength);
  296. RtlCopyMemory(DestPtr, SrcPtr, ThisCopy);
  297. Copied += ThisCopy;
  298. DestPtr += ThisCopy;
  299. SrcPtr += ThisCopy;
  300. BytesToCopy -= ThisCopy;
  301. SrcLength -= ThisCopy;
  302. DestLength -= ThisCopy;
  303. if (!SrcLength) { // We've exhausted the source buffer.
  304. NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
  305. if (!SrcBuffer) {
  306. ASSERT(0 == BytesToCopy);
  307. break; // Copy is done.
  308. }
  309. TcpipQueryBuffer(SrcBuffer, &SrcPtr, &SrcLength,
  310. NormalPagePriority);
  311. if (SrcPtr == NULL && BytesToCopy) {
  312. Status = NDIS_STATUS_RESOURCES;
  313. break;
  314. }
  315. }
  316. if (!DestLength) { // We've exhausted the destination buffer.
  317. NdisGetNextBuffer(DestBuffer, &DestBuffer);
  318. if (!DestBuffer) {
  319. ASSERT(0 == BytesToCopy);
  320. break; // Copy is done.
  321. }
  322. TcpipQueryBuffer(DestBuffer, &DestPtr, &DestLength,
  323. NormalPagePriority);
  324. if (DestPtr == NULL && BytesToCopy) {
  325. Status = NDIS_STATUS_RESOURCES;
  326. break;
  327. }
  328. }
  329. }
  330. if (Status == NDIS_STATUS_SUCCESS) {
  331. *BytesCopied = Copied;
  332. }
  333. return Status;
  334. }
  335. //* LoopClose - Loopback close routine.
  336. //
  337. // This is the loopback close routine. It does nothing but return.
  338. //
  339. // Entry: Context - Unused.
  340. //
  341. // Returns: Nothing.
  342. //
  343. void
  344. __stdcall
  345. LoopClose(void *Context)
  346. {
  347. UNREFERENCED_PARAMETER(Context);
  348. }
  349. //* LoopInvalidate - Invalidate an RCE.
  350. //
  351. // The loopback invalidate RCE routine. It also does nothing.
  352. //
  353. // Entry: Context - Unused.
  354. // RCE - Pointer to RCE to be invalidated.
  355. //
  356. // Returns: Nothing.
  357. //
  358. void
  359. __stdcall
  360. LoopInvalidate(void *Context, RouteCacheEntry * RCE)
  361. {
  362. UNREFERENCED_PARAMETER(Context);
  363. UNREFERENCED_PARAMETER(RCE);
  364. }
  365. //* LoopQInfo - Loopback query information handler.
  366. //
  367. // Called when the upper layer wants to query information about the loopback
  368. // interface.
  369. //
  370. // Input: IFContext - Interface context (unused).
  371. // ID - TDIObjectID for object.
  372. // Buffer - Buffer to put data into.
  373. // Size - Pointer to size of buffer. On return, filled with
  374. // bytes copied.
  375. // Context - Pointer to context block.
  376. //
  377. // Returns: Status of attempt to query information.
  378. //
  379. int
  380. __stdcall
  381. LoopQInfo(void *IFContext, TDIObjectID * ID, PNDIS_BUFFER Buffer, uint * Size,
  382. void *Context)
  383. {
  384. uint Offset = 0;
  385. uint BufferSize = *Size;
  386. uint Entity;
  387. uint Instance;
  388. BOOLEAN fStatus;
  389. UNREFERENCED_PARAMETER(IFContext);
  390. UNREFERENCED_PARAMETER(Context);
  391. Entity = ID->toi_entity.tei_entity;
  392. Instance = ID->toi_entity.tei_instance;
  393. // First, make sure it's possibly an ID we can handle.
  394. if (Entity != IF_ENTITY || Instance != LoopInstance) {
  395. return TDI_INVALID_REQUEST;
  396. }
  397. *Size = 0; // In case of an error.
  398. if (ID->toi_type != INFO_TYPE_PROVIDER)
  399. return TDI_INVALID_PARAMETER;
  400. if (ID->toi_class == INFO_CLASS_GENERIC) {
  401. if (ID->toi_id == ENTITY_TYPE_ID) {
  402. // He's trying to see what type we are.
  403. if (BufferSize >= sizeof(uint)) {
  404. fStatus = CopyToNdisSafe(Buffer, NULL,
  405. (uchar *) &LoopEntityType,
  406. sizeof(uint), &Offset);
  407. if (fStatus == FALSE) {
  408. return (TDI_NO_RESOURCES);
  409. }
  410. return TDI_SUCCESS;
  411. } else
  412. return TDI_BUFFER_TOO_SMALL;
  413. }
  414. return TDI_INVALID_PARAMETER;
  415. } else if (ID->toi_class != INFO_CLASS_PROTOCOL)
  416. return TDI_INVALID_PARAMETER;
  417. // If he's asking for MIB statistics, then return them, otherwise fail
  418. // the request.
  419. if (ID->toi_id == IF_MIB_STATS_ID) {
  420. // He's asking for statistics. Make sure his buffer is at least big
  421. // enough to hold the fixed part.
  422. if (BufferSize < IFE_FIXED_SIZE) {
  423. return TDI_BUFFER_TOO_SMALL;
  424. }
  425. // He's got enough to hold the fixed part. Copy our IFE structure
  426. // into his buffer.
  427. fStatus = CopyToNdisSafe(Buffer, &Buffer, (uchar *) & LoopIFE,
  428. IFE_FIXED_SIZE, &Offset);
  429. if (fStatus == TRUE) {
  430. // See if he has room for the descriptor string.
  431. if (BufferSize >= (IFE_FIXED_SIZE + sizeof(LoopName))) {
  432. // He has room. Copy it.
  433. fStatus = CopyToNdisSafe(Buffer, NULL, LoopName,
  434. sizeof(LoopName), &Offset);
  435. if (fStatus == TRUE) {
  436. *Size = IFE_FIXED_SIZE + sizeof(LoopName);
  437. return TDI_SUCCESS;
  438. }
  439. } else {
  440. // Not enough room to copy the desc. string.
  441. *Size = IFE_FIXED_SIZE;
  442. return TDI_BUFFER_OVERFLOW;
  443. }
  444. }
  445. return TDI_NO_RESOURCES;
  446. }
  447. return TDI_INVALID_PARAMETER;
  448. }
  449. //* LoopSetInfo - Loopback set information handler.
  450. //
  451. // The loopback set information handler. We support setting of an I/F admin
  452. // status.
  453. //
  454. // Input: Context - Pointer to I/F to set on.
  455. // ID - The object ID
  456. // Buffer - Pointer to buffer containing value to set.
  457. // Size - Size in bytes of Buffer.
  458. //
  459. // Returns: Status of attempt to set information.
  460. //
  461. int
  462. __stdcall
  463. LoopSetInfo(void *Context, TDIObjectID *ID, void *Buffer, uint Size)
  464. {
  465. IFEntry *IFE = (IFEntry *) Buffer;
  466. uint Entity, Instance, Status;
  467. UNREFERENCED_PARAMETER(Context);
  468. Entity = ID->toi_entity.tei_entity;
  469. Instance = ID->toi_entity.tei_instance;
  470. // First, make sure it's possibly an ID we can handle.
  471. if (Entity != IF_ENTITY || Instance != LoopInstance) {
  472. return TDI_INVALID_REQUEST;
  473. }
  474. if (ID->toi_class != INFO_CLASS_PROTOCOL ||
  475. ID->toi_type != INFO_TYPE_PROVIDER) {
  476. return TDI_INVALID_PARAMETER;
  477. }
  478. // It's for the I/F level, see if it's for the statistics.
  479. if (ID->toi_id == IF_MIB_STATS_ID) {
  480. // It's for the stats. Make sure it's a valid size.
  481. if (Size >= IFE_FIXED_SIZE) {
  482. // It's a valid size. See what he wants to do.
  483. Status = IFE->if_adminstatus;
  484. if (Status == IF_STATUS_UP || Status == IF_STATUS_DOWN)
  485. LoopIFE.if_adminstatus = Status;
  486. else if (Status != IF_STATUS_TESTING)
  487. return TDI_INVALID_PARAMETER;
  488. return TDI_SUCCESS;
  489. } else
  490. return TDI_INVALID_PARAMETER;
  491. }
  492. return TDI_INVALID_PARAMETER;
  493. }
  494. //* LoopAddAddr - Dummy loopback add address routine.
  495. //
  496. // Called at init time when we need to initialize ourselves.
  497. //
  498. uint
  499. __stdcall
  500. LoopAddAddr(void *Context, uint Type, IPAddr Address, IPMask Mask, void *Context2)
  501. {
  502. UNREFERENCED_PARAMETER(Context);
  503. UNREFERENCED_PARAMETER(Type);
  504. UNREFERENCED_PARAMETER(Address);
  505. UNREFERENCED_PARAMETER(Mask);
  506. UNREFERENCED_PARAMETER(Context2);
  507. return TRUE;
  508. }
  509. //* LoopDelAddr - Dummy loopback del address routine.
  510. //
  511. // Called at init time when we need to initialize ourselves.
  512. //
  513. uint
  514. __stdcall
  515. LoopDelAddr(void *Context, uint Type, IPAddr Address, IPMask Mask)
  516. {
  517. UNREFERENCED_PARAMETER(Context);
  518. UNREFERENCED_PARAMETER(Type);
  519. UNREFERENCED_PARAMETER(Address);
  520. UNREFERENCED_PARAMETER(Mask);
  521. return TRUE;
  522. }
  523. #pragma BEGIN_INIT
  524. extern int InitNTE(NetTableEntry *);
  525. extern int InitInterface(NetTableEntry *);
  526. //* LoopGetEList - Get the entity list.
  527. //
  528. // Called at init time to get an entity list. We fill our stuff in and return.
  529. //
  530. // Input: Context - Unused.
  531. // EntityList - Pointer to entity list to be filled in.
  532. // Count - Pointer to number of entries in the list.
  533. //
  534. // Returns Status of attempt to get the info.
  535. //
  536. int
  537. __stdcall
  538. LoopGetEList(void *Context, TDIEntityID *EntityList, uint *Count)
  539. {
  540. uint MyIFBase;
  541. uint i;
  542. TDIEntityID *IFEntity;
  543. UNREFERENCED_PARAMETER(Context);
  544. // Walk down the list, looking for existing IF entities, and
  545. // adjust our base instance accordingly.
  546. MyIFBase = 0;
  547. IFEntity = NULL;
  548. for (i = 0; i < *Count; i++, EntityList++) {
  549. if (EntityList->tei_entity == IF_ENTITY)
  550. // if we are already on the list remember our entity item
  551. // o/w find an instance # for us.
  552. if (EntityList->tei_instance == LoopInstance &&
  553. EntityList->tei_instance != INVALID_ENTITY_INSTANCE) {
  554. IFEntity = EntityList;
  555. break;
  556. } else {
  557. MyIFBase = MAX(MyIFBase, EntityList->tei_instance + 1);
  558. }
  559. }
  560. if (IFEntity == NULL) {
  561. // we are not on the list.
  562. // make sure we have the room for it.
  563. if (*Count >= MAX_TDI_ENTITIES) {
  564. return FALSE;
  565. }
  566. LoopInstance = MyIFBase;
  567. // Now fill it in.
  568. EntityList->tei_entity = IF_ENTITY;
  569. EntityList->tei_instance = MyIFBase;
  570. (*Count)++;
  571. }
  572. return TRUE;
  573. }
  574. //** InitLoopback - Initialize the loopback NTE.
  575. //
  576. // This function initialized the loopback NTE. We set up the the MSS and
  577. // pointer to the various pseudo-link routines, then call InitNTE and return.
  578. //
  579. // Entry: ConfigInfo - Pointer to config. info structure.
  580. //
  581. // Returns: TRUE if we initialized, FALSE if we didn't.
  582. //
  583. NetTableEntry *
  584. InitLoopback(IPConfigInfo * ConfigInfo)
  585. {
  586. LLIPBindInfo ARPInfo;
  587. UNREFERENCED_PARAMETER(ConfigInfo);
  588. LoopNTE = CTEAllocMem(sizeof(NetTableEntry));
  589. if (LoopNTE == NULL)
  590. return LoopNTE;
  591. RtlZeroMemory(LoopNTE, sizeof(NetTableEntry));
  592. RtlZeroMemory(&LoopInterface, sizeof(RouteInterface));
  593. LoopNTE->nte_addr = LOOPBACK_ADDR;
  594. LoopNTE->nte_mask = CLASSA_MASK;
  595. LoopNTE->nte_icmpseq = 1;
  596. LoopNTE->nte_flags = NTE_VALID | NTE_ACTIVE | NTE_PRIMARY;
  597. CTEInitLock(&LoopNTE->nte_lock);
  598. CTEInitLock(&LoopInterface.ri_if.if_lock);
  599. LoopNTE->nte_mss = LOOPBACK_MSS;
  600. LoopNTE->nte_if = (Interface *) & LoopInterface;
  601. LoopInterface.ri_if.if_lcontext = LoopNTE;
  602. LoopInterface.ri_if.if_xmit = LoopXmit;
  603. LoopInterface.ri_if.if_transfer = LoopXfer;
  604. LoopInterface.ri_if.if_close = LoopClose;
  605. LoopInterface.ri_if.if_invalidate = LoopInvalidate;
  606. LoopInterface.ri_if.if_qinfo = LoopQInfo;
  607. LoopInterface.ri_if.if_setinfo = LoopSetInfo;
  608. LoopInterface.ri_if.if_getelist = LoopGetEList;
  609. LoopInterface.ri_if.if_addaddr = LoopAddAddr;
  610. LoopInterface.ri_if.if_deladdr = LoopDelAddr;
  611. LoopInterface.ri_if.if_bcast = IP_LOCAL_BCST;
  612. LoopInterface.ri_if.if_speed = 10000000;
  613. LoopInterface.ri_if.if_mtu = LOOPBACK_MSS;
  614. LoopInterface.ri_if.if_llipflags = LIP_COPY_FLAG;
  615. LOCKED_REFERENCE_IF(&LoopInterface.ri_if);
  616. LoopInterface.ri_if.if_order = MAXLONG;
  617. ARPInfo.lip_mss = LOOPBACK_MSS + sizeof(IPHeader);
  618. ARPInfo.lip_index = LoopIndex;
  619. ARPInfo.lip_close = LoopClose;
  620. ARPInfo.lip_addaddr = LoopAddAddr;
  621. ARPInfo.lip_deladdr = LoopDelAddr;
  622. ARPInfo.lip_flags = LIP_COPY_FLAG;
  623. LoopIndex = NumIF + 1;
  624. LoopInterface.ri_if.if_index = LoopIndex;
  625. CTEInitEvent(&LoopXmitEvent, LoopXmitRtn);
  626. CTEInitLock(&LoopLock.Lock);
  627. LoopIFE.if_index = LoopIndex;
  628. LoopIFE.if_type = IF_TYPE_SOFTWARE_LOOPBACK;
  629. LoopIFE.if_mtu = ARPInfo.lip_mss;
  630. LoopIFE.if_speed = 10000000;
  631. LoopIFE.if_adminstatus = IF_STATUS_UP;
  632. LoopIFE.if_operstatus = IF_OPER_STATUS_OPERATIONAL;
  633. LoopIFE.if_lastchange = GetTimeTicks();
  634. LoopIFE.if_descrlen = sizeof(LoopName);
  635. IFList = (Interface *) & LoopInterface;
  636. NumIF++;
  637. NumNTE++;
  638. if (!InitInterface(LoopNTE))
  639. return NULL;
  640. if (!InitNTE(LoopNTE))
  641. return NULL;
  642. NumActiveNTE++;
  643. return LoopNTE;
  644. }
  645. #pragma END_INIT