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.

7768 lines
281 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. ARP.C - LAN arp module.
  5. Abstract:
  6. This file implements arp framing for IP layer on the upper edge
  7. and interfaces with ndis driver on the lower edge.
  8. Author:
  9. [Environment:]
  10. kernel mode only
  11. [Notes:]
  12. optional-notes
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. //*** arp.c - ARP routines.
  17. //
  18. // This file containes all of the ARP related routines, including
  19. // table lookup, registration, etc.
  20. //
  21. // ARP is architected to support multiple protocols, but for now
  22. // it in only implemented to take one protocol (IP). This is done
  23. // for simplicity and ease of implementation. In the future we may
  24. // split ARP out into a seperate driver.
  25. #include "arp.h"
  26. #include "arpdef.h"
  27. #include "iproute.h"
  28. #include "iprtdef.h"
  29. #include "arpinfo.h"
  30. #include "tcpipbuf.h"
  31. #include "mdlpool.h"
  32. #include "ipifcons.h"
  33. #define NDIS_MAJOR_VERSION 0x4
  34. #define NDIS_MINOR_VERSION 0
  35. #ifndef NDIS_API
  36. #define NDIS_API
  37. #endif
  38. #define PPP_HW_ADDR "DEST"
  39. #define PPP_HW_ADDR_LEN 4
  40. #if DBG
  41. uint fakereset = 0;
  42. #endif
  43. extern void IPReset(void *Context);
  44. UINT cUniAdapters = 0;
  45. extern uint EnableBcastArpReply;
  46. static ulong ARPLookahead = LOOKAHEAD_SIZE;
  47. static const uchar ENetBcst[] = "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x08\x06";
  48. static const uchar TRBcst[] = "\x10\x40\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x82\x70";
  49. static const uchar FDDIBcst[] = "\x57\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00";
  50. static const uchar ARCBcst[] = "\x00\x00\xd5";
  51. ulong TRFunctionalMcast = 0;
  52. //canonical or non-canonical?
  53. static uchar TRMcst[] = "\x10\x40\xc0\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x82\x70";
  54. //#define TR_MCAST_FUNCTIONAL_ADDRESS 0xc00000040000
  55. //canonical form
  56. #define TR_MCAST_FUNCTIONAL_ADDRESS 0x030000200000
  57. static uchar TRNetMcst[] = "\x00\x04\x00\x00";
  58. static const uchar ENetMcst[] = "\x01\x00\x5E\x00\x00\x00";
  59. static const uchar FDDIMcst[] = "\x57\x01\x00\x5E\x00\x00\x00";
  60. static const uchar ARPSNAP[] = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
  61. static const uchar ENetPtrnMsk[] = "\x00\x30";
  62. static const uchar ENetSNAPPtrnMsk[] = "\x00\xC0\x3f";
  63. //static const uchar TRPtrnMsk[] = "\x03\x00";
  64. //static const uchar TRSNAPPtrnMsk[] = "\x03\xC0\x3f";
  65. static const uchar TRPtrnMsk[] = "\x00\x00"; //NO AC/FC bits need to be checked
  66. static const uchar TRSNAPPtrnMsk[] = "\x00\xC0\x3f";
  67. static const uchar FDDIPtrnMsk[] = "\x01\x00";
  68. static const uchar FDDISNAPPtrnMsk[] = "\x01\x70\x1f";
  69. static const uchar ARCPtrnMsk[] = "\x01";
  70. static const uchar ARPPtrnMsk[] = "\x80\x00\x00\x0F";
  71. static const uchar ARCARPPtrnMsk[] = "\x80\xC0\x03";
  72. NDIS_STATUS __stdcall DoWakeupPattern(void *Context,
  73. PNET_PM_WAKEUP_PATTERN_DESC PtrnDesc, ushort protoid,
  74. BOOLEAN AddPattern);
  75. NDIS_STATUS ARPWakeupPattern(ARPInterface *Interface, IPAddr Address,
  76. BOOLEAN AddPattern);
  77. NDIS_STATUS AddrNotifyLink(ARPInterface *Interface);
  78. static WCHAR ARPName[] = TCP_NAME;
  79. NDIS_HANDLE ARPHandle; // Our NDIS protocol handle.
  80. uint ArpCacheLife;
  81. extern uint ArpMinValidCacheLife;
  82. uint sArpAlwaysSourceRoute; // True if we always send ARP requests
  83. uint ArpRetryCount; // retries for arp request with source
  84. // route info on token ring.
  85. uint sIPAlwaysSourceRoute;
  86. extern uchar TrRii;
  87. extern PDRIVER_OBJECT IPDriverObject;
  88. extern DisableTaskOffload;
  89. extern NDIS_STATUS __stdcall IPPnPEvent(void *, PNET_PNP_EVENT PnPEvent);
  90. extern NDIS_STATUS GetIPConfigValue(NDIS_HANDLE Handle, PUNICODE_STRING IPConfig);
  91. extern VOID IPUnload(IN PDRIVER_OBJECT DriverObject);
  92. extern BOOLEAN CopyToNdisSafe(
  93. PNDIS_BUFFER DestBuf,
  94. PNDIS_BUFFER *ppNextBuf,
  95. uchar *SrcBuf,
  96. uint Size,
  97. uint *StartOffset);
  98. extern void NDIS_API ARPSendComplete(NDIS_HANDLE, PNDIS_PACKET, NDIS_STATUS);
  99. extern void IPULUnloadNotify(void);
  100. extern void NotifyOfUnload(void);
  101. extern uint OpenIFConfig(PNDIS_STRING ConfigName, NDIS_HANDLE * Handle);
  102. extern int IsLLInterfaceValueNull(NDIS_HANDLE Handle);
  103. extern void CloseIFConfig(NDIS_HANDLE Handle);
  104. BOOLEAN QueryAndSetOffload(ARPInterface *ai);
  105. ARPTableEntry *CreateARPTableEntry(ARPInterface *Interface, IPAddr Destination,
  106. CTELockHandle *Handle, void *UserArp);
  107. NDIS_STATUS NDIS_API
  108. ARPRcvIndicationNew(NDIS_HANDLE Handle, NDIS_HANDLE Context, void *Header,
  109. uint HeaderSize, void *Data, uint Size, uint TotalSize,
  110. PNDIS_BUFFER pNdisBuffer, PINT pClientCnt);
  111. void
  112. CompleteIPSetNTEAddrRequestDelayed(CTEEvent *WorkerThreadEvent, PVOID Context);
  113. // Tables for bitswapping.
  114. const uchar SwapTableLo[] =
  115. {
  116. 0, // 0
  117. 0x08, // 1
  118. 0x04, // 2
  119. 0x0c, // 3
  120. 0x02, // 4
  121. 0x0a, // 5,
  122. 0x06, // 6,
  123. 0x0e, // 7,
  124. 0x01, // 8,
  125. 0x09, // 9,
  126. 0x05, // 10,
  127. 0x0d, // 11,
  128. 0x03, // 12,
  129. 0x0b, // 13,
  130. 0x07, // 14,
  131. 0x0f // 15
  132. };
  133. const uchar SwapTableHi[] =
  134. {
  135. 0, // 0
  136. 0x80, // 1
  137. 0x40, // 2
  138. 0xc0, // 3
  139. 0x20, // 4
  140. 0xa0, // 5,
  141. 0x60, // 6,
  142. 0xe0, // 7,
  143. 0x10, // 8,
  144. 0x90, // 9,
  145. 0x50, // 10,
  146. 0xd0, // 11,
  147. 0x30, // 12,
  148. 0xb0, // 13,
  149. 0x70, // 14,
  150. 0xf0 // 15
  151. };
  152. // Table of source route maximum I-field lengths for token ring.
  153. const ushort IFieldSize[] =
  154. {
  155. 516,
  156. 1500,
  157. 2052,
  158. 4472,
  159. 8191
  160. };
  161. #define LF_BIT_SHIFT 4
  162. #define MAX_LF_BITS 4
  163. //
  164. // Disposable init or paged code.
  165. //
  166. void FreeARPInterface(ARPInterface * Interface);
  167. void ARPOpen(void *Context);
  168. void NotifyConflictProc(CTEEvent * Event, void *Context);
  169. #ifdef ALLOC_PRAGMA
  170. #pragma alloc_text(INIT, ARPInit)
  171. #pragma alloc_text(PAGE, ARPOpen)
  172. #pragma alloc_text(PAGELK, ARPRegister)
  173. #pragma alloc_text(PAGE, NotifyConflictProc)
  174. #endif // ALLOC_PRAGMA
  175. LIST_ENTRY ArpInterfaceList;
  176. CACHE_LINE_KSPIN_LOCK ArpInterfaceListLock;
  177. HANDLE ArpEnetHeaderPool;
  178. HANDLE ArpAuxHeaderPool;
  179. #define BUFSIZE_ENET_HEADER_POOL sizeof(ENetHeader) + sizeof(ARPHeader)
  180. #define BUFSIZE_AUX_HEADER_POOL ARP_MAX_MEDIA_TR + (2 * sizeof(ARPHeader))
  181. //
  182. // Support Structs for DoNDISRequest (BLOCKING & NON-BLOCKING)
  183. //
  184. typedef struct _RequestBlock {
  185. NDIS_REQUEST Request; // Request structure we'll use
  186. ULONG Blocking; // ? Is this Request Blocking ?
  187. CTEBlockStruc Block; // Structure for blocking on. No longer use
  188. // ai_block since multiple requests can
  189. // occur simultaneously.
  190. // ai_block is now only used for blocking on
  191. // opening and closing the NDIS adapter.
  192. ULONG RefCount; // Reference count (only used for blocking).
  193. // Reference counting is required for Windows ME since KeWaitForSingleObject
  194. // can fail (when the event is NOT set) and we need to protect the memory
  195. // until completion.
  196. } RequestBlock;
  197. // This prototype enables DoNDISRequest to compile without errors
  198. void NDIS_API
  199. ARPRequestComplete(NDIS_HANDLE Handle, PNDIS_REQUEST pRequest,
  200. NDIS_STATUS Status);
  201. //* FillARPControlBlock
  202. //
  203. // A utility routine to transfer a physical address into an ARPControlBlock,
  204. // taking into account different MAC address formats.
  205. //
  206. // Entry:
  207. // Interface - the ARPInterface which identifies the media
  208. // Entry - the ARP entry containing the MAC address
  209. // ArpContB - the control-block to be filled
  210. //
  211. __inline
  212. NDIS_STATUS
  213. FillARPControlBlock(ARPInterface* Interface, ARPTableEntry* Entry,
  214. ARPControlBlock* ArpContB)
  215. {
  216. ENetHeader *EHdr;
  217. TRHeader *TRHdr;
  218. FDDIHeader *FHdr;
  219. ARCNetHeader *AHdr;
  220. uint Size = 0;
  221. NDIS_STATUS Status;
  222. if (Interface->ai_media == NdisMediumArcnet878_2) {
  223. if (!ArpContB->PhyAddrLen) {
  224. return NDIS_STATUS_BUFFER_OVERFLOW;
  225. }
  226. Status = NDIS_STATUS_SUCCESS;
  227. } else if (ArpContB->PhyAddrLen < ARP_802_ADDR_LENGTH) {
  228. Size = ArpContB->PhyAddrLen;
  229. Status = NDIS_STATUS_BUFFER_OVERFLOW;
  230. } else {
  231. Size = ARP_802_ADDR_LENGTH;
  232. Status = NDIS_STATUS_SUCCESS;
  233. }
  234. switch (Interface->ai_media) {
  235. case NdisMedium802_3:
  236. EHdr = (ENetHeader *) Entry->ate_addr;
  237. RtlCopyMemory(ArpContB->PhyAddr, EHdr->eh_daddr, Size);
  238. ArpContB->PhyAddrLen = Size;
  239. break;
  240. case NdisMedium802_5:
  241. TRHdr = (TRHeader *) Entry->ate_addr;
  242. RtlCopyMemory(ArpContB->PhyAddr, TRHdr->tr_daddr, Size);
  243. ArpContB->PhyAddrLen = Size;
  244. break;
  245. case NdisMediumFddi:
  246. FHdr = (FDDIHeader *) Entry->ate_addr;
  247. RtlCopyMemory(ArpContB->PhyAddr, FHdr->fh_daddr, Size);
  248. ArpContB->PhyAddrLen = Size;
  249. break;
  250. case NdisMediumArcnet878_2:
  251. AHdr = (ARCNetHeader *) Entry->ate_addr;
  252. ArpContB->PhyAddr[0] = AHdr->ah_daddr;
  253. ArpContB->PhyAddrLen = 1;
  254. break;
  255. default:
  256. ASSERT(0);
  257. }
  258. return Status;
  259. }
  260. //* DoNDISRequest - Submit a (NON) BLOCKING request to an NDIS driver
  261. //
  262. // This is a utility routine to submit a general request to an NDIS
  263. // driver. The caller specifes the request code (OID), a buffer and
  264. // a length. This routine allocates a request structure, fills it in, &
  265. // submits the request.
  266. //
  267. // If the call is non-blocking, any memory allocated is deallocated
  268. // in ARPRequestComplete. Also as this callback is shared by both
  269. // DoNDISRequest blocking and non-blocking, we suffix the request
  270. // with a ULONG that tells ARPRequestComplete if this request is a
  271. // blocking request or not. If the request is non blocking, then the
  272. // ARPRequestComplete reclaims the memory allocated on the heap
  273. //
  274. // Important:
  275. // Allocate Info, which points to the Information Buffer passed to
  276. // NdisRequest, on the HEAP, if this request does not block. This
  277. // memory is automatically deallocated by ARPRequestComplete
  278. //
  279. // If the call is blocking, the request memory can be allocated on the
  280. // STACK. When we complete the request, the request on the stack
  281. // will automatically get unwound.
  282. //
  283. // Entry:
  284. // Adapter - A pointer to the ARPInterface adapter structure.
  285. // Request - Type of request to be done (Set or Query)
  286. // OID - Value to be set/queried.
  287. // Info - A pointer to the info buffer
  288. // Length - Length of data in the buffer
  289. // Needed - On return, filled in with bytes needed in buffer
  290. // Blocking - Whether NdisRequest is completed synchronously
  291. //
  292. // Exit:
  293. // Status - BLOCKING req - SUCCESS or some NDIS error code
  294. // NON-BLOCKING - SUCCESS, PENDING or some error
  295. //
  296. NDIS_STATUS
  297. DoNDISRequest(ARPInterface * Adapter, NDIS_REQUEST_TYPE RT, NDIS_OID OID,
  298. VOID * Info, UINT Length, UINT * Needed, BOOLEAN Blocking)
  299. {
  300. RequestBlock *pReqBlock;
  301. NDIS_STATUS Status;
  302. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_REQUEST,
  303. (DTEXT("+DoNDISRequest(%x, %x, %x, %x, %d, %x, %x\n"),
  304. Adapter, RT, OID, Info, Length, Needed, Blocking));
  305. if ((Adapter->ai_adminstate == INTERFACE_DOWN) ||
  306. (Adapter->ai_handle == NULL)) {
  307. return NDIS_STATUS_ADAPTER_NOT_READY;
  308. }
  309. // Both blocking and non-blocking requests are allocated from NPP. The
  310. // blocking case is to protect against wait failure.
  311. pReqBlock = CTEAllocMemN(sizeof(RequestBlock), 'NiCT');
  312. if (pReqBlock == NULL) {
  313. return NDIS_STATUS_RESOURCES;
  314. }
  315. if (Blocking) {
  316. // Initialize the structure to block on
  317. CTEInitBlockStruc(&pReqBlock->Block);
  318. // Reference count is initialize to two. One for the completion in
  319. // ARPRequestComplete and one for when the CTEBlock completes.
  320. // N.B. This ensures that we don't touch freed memory if
  321. // the CTEBlock fails on Windows ME.
  322. pReqBlock->RefCount = 2;
  323. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_REQUEST,
  324. (DTEXT("DoNDISRequset block: pReqBlock %x OID %x\n"),
  325. pReqBlock, OID));
  326. } else {
  327. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_REQUEST,
  328. (DTEXT("DoNDISRequest async: pReqBlock %x OID %x\n"),
  329. pReqBlock, OID));
  330. }
  331. // Now fill the request's info buffer (same for BLOCKING & NON-BLOCKING)
  332. pReqBlock->Block.cbs_status = NDIS_STATUS_SUCCESS;
  333. pReqBlock->Request.RequestType = RT;
  334. if (RT == NdisRequestSetInformation) {
  335. pReqBlock->Request.DATA.SET_INFORMATION.Oid = OID;
  336. pReqBlock->Request.DATA.SET_INFORMATION.InformationBuffer = Info;
  337. pReqBlock->Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
  338. } else {
  339. pReqBlock->Request.DATA.QUERY_INFORMATION.Oid = OID;
  340. pReqBlock->Request.DATA.QUERY_INFORMATION.InformationBuffer = Info;
  341. pReqBlock->Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
  342. }
  343. pReqBlock->Blocking = Blocking;
  344. // Submit the request.
  345. if (Adapter->ai_handle != NULL) {
  346. #if MILLEN
  347. // On Millennium, the AOL adapter returns with registers trashed.
  348. // We will work around by saving and restoring registers.
  349. //
  350. _asm {
  351. push esi
  352. push edi
  353. push ebx
  354. }
  355. #endif // MILLEN
  356. NdisRequest(&Status, Adapter->ai_handle, &pReqBlock->Request);
  357. #if MILLEN
  358. _asm {
  359. pop ebx
  360. pop edi
  361. pop esi
  362. }
  363. #endif // MILLEN
  364. } else {
  365. Status = NDIS_STATUS_FAILURE;
  366. }
  367. if (Blocking) {
  368. if (Status == NDIS_STATUS_PENDING) {
  369. CTEBlockTracker Tracker;
  370. Status = (NDIS_STATUS) CTEBlockWithTracker(&pReqBlock->Block,
  371. &Tracker, Adapter);
  372. #if MILLEN
  373. // If Status == -1, it means the wait failed -- due to system reasons.
  374. // Put in a reasonable failure.
  375. if (Status == -1) {
  376. Status = NDIS_STATUS_FAILURE;
  377. }
  378. #endif // MILLEN
  379. } else {
  380. // Since we aren't blocking, remove refcount for ARPRequestComplete.
  381. InterlockedDecrement( (PLONG) &pReqBlock->RefCount);
  382. }
  383. if (Needed != NULL)
  384. *Needed = pReqBlock->Request.DATA.QUERY_INFORMATION.BytesNeeded;
  385. if (InterlockedDecrement( (PLONG) &pReqBlock->RefCount) == 0) {
  386. CTEFreeMem(pReqBlock);
  387. }
  388. } else {
  389. if (Status != NDIS_STATUS_PENDING) {
  390. if (Needed != NULL)
  391. *Needed = pReqBlock->Request.DATA.QUERY_INFORMATION.BytesNeeded;
  392. ARPRequestComplete(Adapter->ai_handle, &pReqBlock->Request, Status);
  393. }
  394. }
  395. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_REQUEST,
  396. (DTEXT("-DoNDISRequest [%x]\n"), Status));
  397. return Status;
  398. }
  399. //* FreeARPBuffer - Free a header and buffer descriptor pair.
  400. //
  401. // Called when we're done with a buffer. We'll free the buffer and the
  402. // buffer descriptor pack to the interface.
  403. //
  404. // Entry: Interface - Interface buffer/bd came frome.
  405. // Buffer - NDIS_BUFFER to be freed.
  406. //
  407. // Returns: Nothing.
  408. //
  409. __inline
  410. VOID
  411. FreeARPBuffer(ARPInterface *Interface, PNDIS_BUFFER Buffer)
  412. {
  413. UNREFERENCED_PARAMETER(Interface);
  414. MdpFree(Buffer);
  415. }
  416. //* GetARPBuffer - Get a buffer and descriptor
  417. //
  418. // Returns a pointer to an NDIS_BUFFER and a pointer to a buffer
  419. // of the specified size.
  420. //
  421. // Entry: Interface - Pointer to ARPInterface structure to allocate buffer from.
  422. // BufPtr - Pointer to where to return buf address.
  423. // Size - Size in bytes of buffer needed.
  424. //
  425. // Returns: Pointer to NDIS_BUFFER if successfull, NULL if not
  426. //
  427. PNDIS_BUFFER
  428. GetARPBufferAtDpcLevel(ARPInterface *Interface, uchar **BufPtr, uchar Size)
  429. {
  430. PNDIS_BUFFER Mdl = NULL;
  431. UNREFERENCED_PARAMETER(Interface);
  432. #if DBG
  433. *BufPtr = NULL;
  434. #endif
  435. UNREFERENCED_PARAMETER(Interface);
  436. if (Size <= BUFSIZE_ENET_HEADER_POOL) {
  437. Mdl = MdpAllocateAtDpcLevel(ArpEnetHeaderPool, BufPtr);
  438. } else if (Size <= BUFSIZE_AUX_HEADER_POOL) {
  439. Mdl = MdpAllocateAtDpcLevel(ArpAuxHeaderPool, BufPtr);
  440. }
  441. if (Mdl) {
  442. NdisAdjustBufferLength(Mdl, Size);
  443. }
  444. return Mdl;
  445. }
  446. #if MILLEN
  447. #define GetARPBuffer GetARPBufferAtDpcLevel
  448. #else
  449. __inline
  450. PNDIS_BUFFER
  451. GetARPBuffer(ARPInterface *Interface, uchar **BufPtr, uchar Size)
  452. {
  453. KIRQL OldIrql;
  454. PNDIS_BUFFER Mdl;
  455. OldIrql = KeRaiseIrqlToDpcLevel();
  456. Mdl = GetARPBufferAtDpcLevel(Interface, BufPtr, Size);
  457. KeLowerIrql(OldIrql);
  458. return Mdl;
  459. }
  460. #endif
  461. //* BitSwap - Bit swap two strings.
  462. //
  463. // A routine to bitswap two strings.
  464. //
  465. // Input: Dest - Destination of swap.
  466. // Src - Src string to be swapped.
  467. // Length - Length in bytes to swap.
  468. //
  469. // Returns: Nothing.
  470. //
  471. void
  472. BitSwap(uchar * Dest, uchar * Src, uint Length)
  473. {
  474. uint i;
  475. uchar Temp, TempSrc;
  476. for (i = 0; i < Length; i++, Dest++, Src++) {
  477. TempSrc = *Src;
  478. Temp = SwapTableLo[TempSrc >> 4] | SwapTableHi[TempSrc & 0x0f];
  479. *Dest = Temp;
  480. }
  481. }
  482. //* SendARPPacket - Build a header, and send a packet.
  483. //
  484. // A utility routine to build and ARP header and send a packet. We assume
  485. // the media specific header has been built.
  486. //
  487. // Entry: Interface - Interface for NDIS drive.
  488. // Packet - Pointer to packet to be sent
  489. // Header - Pointer to header to fill in.
  490. // Opcode - Opcode for packet.
  491. // Address - Source HW address.
  492. // SrcAddr - Address to use as our source h/w address.
  493. // Destination - Destination IP address.
  494. // Src - Source IP address.
  495. // HWType - Hardware type.
  496. // CheckIF - TRUE iff we are to check the I/F status before
  497. // sending.
  498. //
  499. // Returns: NDIS_STATUS of send.
  500. //
  501. NDIS_STATUS
  502. SendARPPacket(ARPInterface * Interface, PNDIS_PACKET Packet, ARPHeader * Header, ushort Opcode,
  503. uchar * Address, uchar * SrcAddr, IPAddr Destination, IPAddr Src,
  504. ushort HWType, uint CheckIF)
  505. {
  506. NDIS_STATUS Status;
  507. PNDIS_BUFFER Buffer;
  508. uint PacketDone;
  509. uchar *AddrPtr;
  510. ulong Proc;
  511. Header->ah_hw = HWType;
  512. Header->ah_pro = net_short(ARP_ETYPE_IP);
  513. Header->ah_hlen = Interface->ai_addrlen;
  514. Header->ah_plen = sizeof(IPAddr);
  515. Header->ah_opcode = Opcode;
  516. AddrPtr = Header->ah_shaddr;
  517. if (SrcAddr == NULL)
  518. SrcAddr = Interface->ai_addr;
  519. RtlCopyMemory(AddrPtr, SrcAddr, Interface->ai_addrlen);
  520. AddrPtr += Interface->ai_addrlen;
  521. *(IPAddr UNALIGNED *) AddrPtr = Src;
  522. AddrPtr += sizeof(IPAddr);
  523. if (Address != (uchar *) NULL)
  524. RtlCopyMemory(AddrPtr, Address, Interface->ai_addrlen);
  525. else
  526. RtlZeroMemory(AddrPtr, Interface->ai_addrlen);
  527. AddrPtr += Interface->ai_addrlen;
  528. *(IPAddr UNALIGNED *) AddrPtr = Destination;
  529. PacketDone = FALSE;
  530. if (!CheckIF || (Interface->ai_operstatus == INTERFACE_UP)) {
  531. Proc = KeGetCurrentProcessorNumber();
  532. Interface->ai_qlen[Proc].ai_qlen++;
  533. NdisSend(&Status, Interface->ai_handle, Packet);
  534. if (Status != NDIS_STATUS_PENDING) {
  535. PacketDone = TRUE;
  536. Interface->ai_qlen[Proc].ai_qlen--;
  537. if (Status == NDIS_STATUS_SUCCESS)
  538. Interface->ai_outoctets += Packet->Private.TotalLength;
  539. else {
  540. if (Status == NDIS_STATUS_RESOURCES)
  541. Interface->ai_outdiscards++;
  542. else
  543. Interface->ai_outerrors++;
  544. }
  545. }
  546. } else {
  547. PacketDone = TRUE;
  548. Status = NDIS_STATUS_ADAPTER_NOT_READY;
  549. }
  550. if (PacketDone) {
  551. NdisUnchainBufferAtFront(Packet, &Buffer);
  552. FreeARPBuffer(Interface, Buffer);
  553. NdisFreePacket(Packet);
  554. }
  555. return Status;
  556. }
  557. //* SendARPRequest - Send an ARP packet
  558. //
  559. // Called when we need to ARP an IP address, or respond to a request. We'll send out
  560. // the packet, and the receiving routines will process the response.
  561. //
  562. // Entry: Interface - Interface to send the request on.
  563. // Destination - The IP address to be ARPed.
  564. // Type - Either RESOLVING_GLOBAL or RESOLVING_LOCAL
  565. // SrcAddr - NULL if we're sending from ourselves, the value
  566. // to use otherwise.
  567. // CheckIF - Flag passed through to SendARPPacket().
  568. //
  569. // Returns: Status of attempt to send ARP request.
  570. //
  571. NDIS_STATUS
  572. SendARPRequest(ARPInterface * Interface, IPAddr Destination, uchar Type,
  573. uchar * SrcAddr, uint CheckIF)
  574. {
  575. uchar *MHeader; // Pointer to media header.
  576. PNDIS_BUFFER Buffer; // NDIS buffer descriptor.
  577. uchar MHeaderSize; // Size of media header.
  578. const uchar *MAddr; // Pointer to media address structure.
  579. uint SAddrOffset; // Offset into media address of source address.
  580. uchar SRFlag = 0; // Source routing flag.
  581. uchar SNAPLength = 0;
  582. const uchar *SNAPAddr; // Address of SNAP header.
  583. PNDIS_PACKET Packet; // Packet for sending.
  584. NDIS_STATUS Status;
  585. ushort HWType;
  586. IPAddr Src;
  587. CTELockHandle Handle;
  588. ARPIPAddr *Addr;
  589. // First, get a source address we can use.
  590. CTEGetLock(&Interface->ai_lock, &Handle);
  591. Addr = &Interface->ai_ipaddr;
  592. Src = NULL_IP_ADDR;
  593. do {
  594. if (!IP_ADDR_EQUAL(Addr->aia_addr, NULL_IP_ADDR)) {
  595. //
  596. // This is a valid address. See if it is the same as the
  597. // target address - i.e. arp'ing for ourselves. If it is,
  598. // we want to use that as our source address.
  599. //
  600. if (IP_ADDR_EQUAL(Addr->aia_addr, Destination)) {
  601. Src = Addr->aia_addr;
  602. break;
  603. }
  604. // See if the target is on this subnet.
  605. if (IP_ADDR_EQUAL(
  606. Addr->aia_addr & Addr->aia_mask,
  607. Destination & Addr->aia_mask
  608. )) {
  609. //
  610. // See if we've already found a suitable candidate on the
  611. // same subnet. If we haven't, we'll use this one.
  612. //
  613. if (!IP_ADDR_EQUAL(
  614. Addr->aia_addr & Addr->aia_mask,
  615. Src & Addr->aia_mask
  616. )) {
  617. Src = Addr->aia_addr;
  618. }
  619. } else {
  620. // He's not on our subnet. If we haven't already found a valid
  621. // address save this one in case we don't find a match for the
  622. // subnet.
  623. if (IP_ADDR_EQUAL(Src, NULL_IP_ADDR)) {
  624. Src = Addr->aia_addr;
  625. }
  626. }
  627. }
  628. Addr = Addr->aia_next;
  629. } while (Addr != NULL);
  630. CTEFreeLock(&Interface->ai_lock, Handle);
  631. // If we didn't find a source address, give up.
  632. if (IP_ADDR_EQUAL(Src, NULL_IP_ADDR))
  633. return NDIS_STATUS_SUCCESS;
  634. NdisAllocatePacket(&Status, &Packet, Interface->ai_ppool);
  635. if (Status != NDIS_STATUS_SUCCESS) {
  636. Interface->ai_outdiscards++;
  637. return Status;
  638. }
  639. ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_owner = PACKET_OWNER_LINK;
  640. (Interface->ai_outpcount[AI_NONUCAST_INDEX])++;
  641. // Figure out what type of media this is, and do the appropriate thing.
  642. switch (Interface->ai_media) {
  643. case NdisMedium802_3:
  644. MHeaderSize = ARP_MAX_MEDIA_ENET;
  645. MAddr = ENetBcst;
  646. if (Interface->ai_snapsize == 0) {
  647. SNAPAddr = (uchar *) NULL;
  648. HWType = net_short(ARP_HW_ENET);
  649. } else {
  650. SNAPLength = sizeof(SNAPHeader);
  651. SNAPAddr = ARPSNAP;
  652. HWType = net_short(ARP_HW_802);
  653. }
  654. SAddrOffset = offsetof(struct ENetHeader, eh_saddr);
  655. break;
  656. case NdisMedium802_5:
  657. // Token ring. We have logic for dealing with the second transmit
  658. // of an arp request.
  659. MAddr = TRBcst;
  660. SAddrOffset = offsetof(struct TRHeader, tr_saddr);
  661. SNAPLength = sizeof(SNAPHeader);
  662. SNAPAddr = ARPSNAP;
  663. MHeaderSize = sizeof(TRHeader);
  664. HWType = net_short(ARP_HW_802);
  665. if (Type == ARP_RESOLVING_GLOBAL) {
  666. MHeaderSize += sizeof(RC);
  667. SRFlag = TR_RII;
  668. }
  669. break;
  670. case NdisMediumFddi:
  671. MHeaderSize = sizeof(FDDIHeader);
  672. MAddr = FDDIBcst;
  673. SNAPAddr = ARPSNAP;
  674. SNAPLength = sizeof(SNAPHeader);
  675. SAddrOffset = offsetof(struct FDDIHeader, fh_saddr);
  676. HWType = net_short(ARP_HW_ENET);
  677. break;
  678. case NdisMediumArcnet878_2:
  679. MHeaderSize = ARP_MAX_MEDIA_ARC;
  680. MAddr = ARCBcst;
  681. SNAPAddr = (uchar *) NULL;
  682. SAddrOffset = offsetof(struct ARCNetHeader, ah_saddr);
  683. HWType = net_short(ARP_HW_ARCNET);
  684. break;
  685. default:
  686. ASSERT(0);
  687. Interface->ai_outerrors++;
  688. return NDIS_STATUS_UNSUPPORTED_MEDIA;
  689. }
  690. if ((Buffer = GetARPBuffer(Interface, &MHeader,
  691. (uchar) (sizeof(ARPHeader) + MHeaderSize + SNAPLength))) == (PNDIS_BUFFER) NULL) {
  692. NdisFreePacket(Packet);
  693. Interface->ai_outdiscards++;
  694. return NDIS_STATUS_RESOURCES;
  695. }
  696. if (Interface->ai_media == NdisMediumArcnet878_2) {
  697. NdisAdjustBufferLength(Buffer, NdisBufferLength(Buffer) - ARCNET_ARPHEADER_ADJUSTMENT);
  698. }
  699. // Copy broadcast address into packet.
  700. RtlCopyMemory(MHeader, MAddr, MHeaderSize);
  701. // Fill in source address.
  702. if (SrcAddr == NULL) {
  703. SrcAddr = Interface->ai_addr;
  704. }
  705. if (Interface->ai_media == NdisMedium802_3 && Interface->ai_snapsize != 0) {
  706. ENetHeader *Hdr = (ENetHeader *) MHeader;
  707. // Using SNAP on ethernet. Adjust the etype to a length.
  708. Hdr->eh_type = net_short(sizeof(ARPHeader) + sizeof(SNAPHeader));
  709. }
  710. RtlCopyMemory(&MHeader[SAddrOffset], SrcAddr, Interface->ai_addrlen);
  711. if ((Interface->ai_media == NdisMedium802_5) && (Type == ARP_RESOLVING_GLOBAL)) {
  712. // Turn on source routing.
  713. MHeader[SAddrOffset] |= SRFlag;
  714. MHeader[SAddrOffset + Interface->ai_addrlen] |= TrRii;
  715. }
  716. // Copy in SNAP header, if any.
  717. RtlCopyMemory(&MHeader[MHeaderSize], SNAPAddr, SNAPLength);
  718. // Media header is filled in. Now do ARP packet itself.
  719. NdisChainBufferAtFront(Packet, Buffer);
  720. return SendARPPacket(Interface, Packet, (ARPHeader *) & MHeader[MHeaderSize + SNAPLength],
  721. net_short(ARP_REQUEST), (uchar *) NULL, SrcAddr, Destination, Src,
  722. HWType, CheckIF);
  723. }
  724. //* SendARPReply - Reply to an ARP request.
  725. //
  726. // Called by our receive packet handler when we need to reply. We build a packet
  727. // and buffer and call SendARPPacket to send it.
  728. //
  729. // Entry: Interface - Pointer to interface to reply on.
  730. // Destination - IPAddress to reply to.
  731. // Src - Source address to reply from.
  732. // HWAddress - Hardware address to reply to.
  733. // SourceRoute - Source Routing information, if any.
  734. // SourceRouteSize - Size in bytes of soure routing.
  735. // UseSNAP - Whether or not to use SNAP for this reply.
  736. //
  737. // Returns: Nothing.
  738. //
  739. void
  740. SendARPReply(ARPInterface * Interface, IPAddr Destination, IPAddr Src, uchar * HWAddress,
  741. RC UNALIGNED * SourceRoute, uint SourceRouteSize, uint UseSNAP)
  742. {
  743. PNDIS_PACKET Packet; // Buffer and packet to be used.
  744. PNDIS_BUFFER Buffer;
  745. uchar *Header; // Pointer to media header.
  746. NDIS_STATUS Status;
  747. uchar Size = 0; // Size of media header buffer.
  748. ushort HWType;
  749. ENetHeader *EH;
  750. FDDIHeader *FH;
  751. ARCNetHeader *AH;
  752. TRHeader *TRH;
  753. // Allocate a packet for this.
  754. NdisAllocatePacket(&Status, &Packet, Interface->ai_ppool);
  755. if (Status != NDIS_STATUS_SUCCESS) {
  756. Interface->ai_outdiscards++;
  757. return;
  758. }
  759. ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_owner = PACKET_OWNER_LINK;
  760. (Interface->ai_outpcount[AI_UCAST_INDEX])++;
  761. Size = Interface->ai_hdrsize;
  762. if (UseSNAP)
  763. Size = Size + (uchar) Interface->ai_snapsize;
  764. if (Interface->ai_media == NdisMedium802_5)
  765. Size = Size + (uchar) SourceRouteSize;
  766. if ((Buffer = GetARPBuffer(Interface, &Header, (uchar) (Size + sizeof(ARPHeader)))) ==
  767. (PNDIS_BUFFER) NULL) {
  768. Interface->ai_outdiscards++;
  769. NdisFreePacket(Packet);
  770. return;
  771. }
  772. // Decide how to build the header based on the media type.
  773. switch (Interface->ai_media) {
  774. case NdisMedium802_3:
  775. EH = (ENetHeader *) Header;
  776. RtlCopyMemory(EH->eh_daddr, HWAddress, ARP_802_ADDR_LENGTH);
  777. RtlCopyMemory(EH->eh_saddr, Interface->ai_addr, ARP_802_ADDR_LENGTH);
  778. if (!UseSNAP) {
  779. EH->eh_type = net_short(ARP_ETYPE_ARP);
  780. HWType = net_short(ARP_HW_ENET);
  781. } else {
  782. // Using SNAP on ethernet.
  783. EH->eh_type = net_short(sizeof(ARPHeader) + sizeof(SNAPHeader));
  784. HWType = net_short(ARP_HW_802);
  785. RtlCopyMemory(Header + sizeof(ENetHeader), ARPSNAP,
  786. sizeof(SNAPHeader));
  787. }
  788. break;
  789. case NdisMedium802_5:
  790. TRH = (TRHeader *) Header;
  791. TRH->tr_ac = ARP_AC;
  792. TRH->tr_fc = ARP_FC;
  793. RtlCopyMemory(TRH->tr_daddr, HWAddress, ARP_802_ADDR_LENGTH);
  794. RtlCopyMemory(TRH->tr_saddr, Interface->ai_addr, ARP_802_ADDR_LENGTH);
  795. if (SourceRouteSize) { // If we have source route info, deal with
  796. // it.
  797. RtlCopyMemory(Header + sizeof(TRHeader), SourceRoute,
  798. SourceRouteSize);
  799. // Convert to directed response.
  800. ((RC *) & Header[sizeof(TRHeader)])->rc_blen &= RC_LENMASK;
  801. ((RC *) & Header[sizeof(TRHeader)])->rc_dlf ^= RC_DIR;
  802. TRH->tr_saddr[0] |= TR_RII;
  803. }
  804. RtlCopyMemory(Header + sizeof(TRHeader) + SourceRouteSize, ARPSNAP,
  805. sizeof(SNAPHeader));
  806. HWType = net_short(ARP_HW_802);
  807. break;
  808. case NdisMediumFddi:
  809. FH = (FDDIHeader *) Header;
  810. FH->fh_pri = ARP_FDDI_PRI;
  811. RtlCopyMemory(FH->fh_daddr, HWAddress, ARP_802_ADDR_LENGTH);
  812. RtlCopyMemory(FH->fh_saddr, Interface->ai_addr, ARP_802_ADDR_LENGTH);
  813. RtlCopyMemory(Header + sizeof(FDDIHeader), ARPSNAP, sizeof(SNAPHeader));
  814. HWType = net_short(ARP_HW_ENET);
  815. break;
  816. case NdisMediumArcnet878_2:
  817. AH = (ARCNetHeader *) Header;
  818. AH->ah_saddr = Interface->ai_addr[0];
  819. AH->ah_daddr = *HWAddress;
  820. AH->ah_prot = ARP_ARCPROT_ARP;
  821. NdisAdjustBufferLength(Buffer, NdisBufferLength(Buffer) - ARCNET_ARPHEADER_ADJUSTMENT);
  822. HWType = net_short(ARP_HW_ARCNET);
  823. break;
  824. default:
  825. ASSERT(0);
  826. Interface->ai_outerrors++;
  827. FreeARPBuffer(Interface, Buffer);
  828. NdisFreePacket(Packet);
  829. return;
  830. }
  831. NdisChainBufferAtFront(Packet, Buffer);
  832. SendARPPacket(Interface, Packet, (ARPHeader *) (Header + Size), net_short(ARP_RESPONSE),
  833. HWAddress, NULL, Destination, Src, HWType, TRUE);
  834. }
  835. //* ARPRemoveRCE - Remove an RCE from the ATE list.
  836. //
  837. // This funtion removes a specified RCE from a given ATE. It assumes the ate_lock
  838. // is held by the caller.
  839. //
  840. // Entry: ATE - ATE from which RCE is to be removed.
  841. // RCE - RCE to be removed.
  842. //
  843. // Returns: Nothing
  844. //
  845. void
  846. ARPRemoveRCE(ARPTableEntry * ATE, RouteCacheEntry * RCE)
  847. {
  848. ARPContext *CurrentAC; // Current ARP Context being checked.
  849. #if DBG
  850. uint Found = FALSE;
  851. #endif
  852. CurrentAC = (ARPContext *) (((char *)&ATE->ate_rce) -
  853. offsetof(struct ARPContext, ac_next));
  854. while (CurrentAC->ac_next != (RouteCacheEntry *) NULL)
  855. if (CurrentAC->ac_next == RCE) {
  856. ARPContext *DummyAC = (ARPContext *) RCE->rce_context;
  857. CurrentAC->ac_next = DummyAC->ac_next;
  858. DummyAC->ac_ate = (ARPTableEntry *) NULL;
  859. DummyAC->ac_next = NULL;
  860. #if DBG
  861. Found = TRUE;
  862. #endif
  863. break;
  864. } else
  865. CurrentAC = (ARPContext *) CurrentAC->ac_next->rce_context;
  866. ASSERT(Found);
  867. }
  868. //* ARPLookup - Look up an entry in the ARP table.
  869. //
  870. // Called to look up an entry in an interface's ARP table. If we find it, we'll
  871. // lock the entry and return a pointer to it, otherwise we return NULL. We
  872. // assume that the caller has the ARP table locked when we are called.
  873. //
  874. // The ARP table entry is structured as a hash table of pointers to
  875. // ARPTableEntrys.After hashing on the IP address, a linear search is done to
  876. // lookup the entry.
  877. //
  878. // If we find the entry, we lock it for the caller. If we don't find
  879. // the entry, we leave the ARP table locked so that the caller may atomically
  880. // insert a new entry without worrying about a duplicate being inserted between
  881. // the time the table was checked and the time the caller went to insert the
  882. // entry.
  883. //
  884. // Entry: Interface - The interface to be searched upon.
  885. // Address - The IP address we're looking up.
  886. //
  887. // Returns: Pointer to ARPTableEntry if found, or NULL if not.
  888. //
  889. ARPTableEntry *
  890. ARPLookup(ARPInterface * Interface, IPAddr Address)
  891. {
  892. int i = ARP_HASH(Address); // Index into hash table.
  893. ARPTableEntry *Current; // Current ARP Table entry being
  894. // examined.
  895. Current = (*Interface->ai_ARPTbl)[i];
  896. while (Current != (ARPTableEntry *) NULL) {
  897. CTEGetLockAtDPC(&Current->ate_lock);
  898. if (IP_ADDR_EQUAL(Current->ate_dest, Address)) { // Found a match.
  899. return Current;
  900. }
  901. CTEFreeLockFromDPC(&Current->ate_lock);
  902. Current = Current->ate_next;
  903. }
  904. // If we got here, we didn't find the entry. Leave the table locked and
  905. // return the handle.
  906. return(ARPTableEntry *) NULL;
  907. }
  908. //* IsBCastOnIF- See it an address is a broadcast address on an interface.
  909. //
  910. // Called to see if a particular address is a broadcast address on an
  911. // interface. We'll check the global, net, and subnet broadcasts. We assume
  912. // the caller holds the lock on the interface.
  913. //
  914. // Entry: Interface - Interface to check.
  915. // Addr - Address to check.
  916. //
  917. // Returns: TRUE if it it a broadcast, FALSE otherwise.
  918. //
  919. uint
  920. IsBCastOnIF(ARPInterface * Interface, IPAddr Addr)
  921. {
  922. IPAddr BCast;
  923. IPMask Mask;
  924. ARPIPAddr *ARPAddr;
  925. IPAddr LocalAddr;
  926. // First get the interface broadcast address.
  927. BCast = Interface->ai_bcast;
  928. // First check for global broadcast.
  929. if (IP_ADDR_EQUAL(BCast, Addr) || CLASSD_ADDR(Addr))
  930. return TRUE;
  931. // Now walk the local addresses, and check for net/subnet bcast on each
  932. // one.
  933. ARPAddr = &Interface->ai_ipaddr;
  934. do {
  935. // See if this one is valid.
  936. LocalAddr = ARPAddr->aia_addr;
  937. if (!IP_ADDR_EQUAL(LocalAddr, NULL_IP_ADDR)) {
  938. // He's valid.
  939. Mask = ARPAddr->aia_mask;
  940. // First check for subnet bcast.
  941. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  942. return TRUE;
  943. // Now check all nets broadcast.
  944. Mask = IPNetMask(LocalAddr);
  945. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  946. return TRUE;
  947. }
  948. ARPAddr = ARPAddr->aia_next;
  949. } while (ARPAddr != NULL);
  950. // If we're here, it's not a broadcast.
  951. return FALSE;
  952. }
  953. //* ARPSendBCast - See if this is a bcast or mcast frame, and send it.
  954. //
  955. // Called when we have a packet to send and we want to see if it's a broadcast
  956. // or multicast frame on this interface. We'll search the local addresses and
  957. // see if we can determine if it is. If it is, we'll send it here. Otherwise
  958. // we return FALSE, and the caller will try to resolve the address.
  959. //
  960. // Entry: Interface - A pointer to an AI structure.
  961. // Dest - Destination of datagram.
  962. // Packet - Packet to be sent.
  963. // Status - Place to return status of send attempt.
  964. //
  965. // Returns: TRUE if is was a bcast or mcast send, FALSE otherwise.
  966. //
  967. uint
  968. ARPSendBCast(ARPInterface * Interface, IPAddr Dest, PNDIS_PACKET Packet,
  969. PNDIS_STATUS Status)
  970. {
  971. uint IsBCast;
  972. CTELockHandle Handle;
  973. PNDIS_BUFFER ARPBuffer; // ARP Header buffer.
  974. uchar *BufAddr; // Address of NDIS buffer
  975. NDIS_STATUS MyStatus;
  976. ENetHeader *Hdr;
  977. FDDIHeader *FHdr;
  978. TRHeader *TRHdr;
  979. SNAPHeader UNALIGNED *SNAPPtr;
  980. RC UNALIGNED *RCPtr;
  981. ARCNetHeader *AHdr;
  982. uint DataLength;
  983. ulong Proc;
  984. // Get the lock, and see if it's a broadcast.
  985. CTEGetLock(&Interface->ai_lock, &Handle);
  986. IsBCast = IsBCastOnIF(Interface, Dest);
  987. CTEFreeLock(&Interface->ai_lock, Handle);
  988. if (IsBCast) {
  989. if (Interface->ai_operstatus == INTERFACE_UP) {
  990. uchar Size;
  991. Size = Interface->ai_hdrsize + Interface->ai_snapsize;
  992. if (Interface->ai_media == NdisMedium802_5)
  993. Size += sizeof(RC);
  994. ARPBuffer = GetARPBuffer(Interface, &BufAddr, Size);
  995. if (ARPBuffer != NULL) {
  996. uint UNALIGNED *Temp;
  997. // Got the buffer we need.
  998. switch (Interface->ai_media) {
  999. case NdisMedium802_3:
  1000. Hdr = (ENetHeader *) BufAddr;
  1001. if (!CLASSD_ADDR(Dest))
  1002. RtlCopyMemory(Hdr, ENetBcst, ARP_802_ADDR_LENGTH);
  1003. else {
  1004. RtlCopyMemory(Hdr, ENetMcst, ARP_802_ADDR_LENGTH);
  1005. Temp = (uint UNALIGNED *) & Hdr->eh_daddr[2];
  1006. *Temp |= (Dest & ARP_MCAST_MASK);
  1007. }
  1008. RtlCopyMemory(Hdr->eh_saddr, Interface->ai_addr,
  1009. ARP_802_ADDR_LENGTH);
  1010. if (Interface->ai_snapsize == 0) {
  1011. // No snap on this interface, so just use ETypr.
  1012. Hdr->eh_type = net_short(ARP_ETYPE_IP);
  1013. } else {
  1014. ushort ShortDataLength;
  1015. // We're using SNAP. Find the size of the packet.
  1016. NdisQueryPacket(Packet, NULL, NULL, NULL,
  1017. &DataLength);
  1018. ShortDataLength = (ushort) (DataLength +
  1019. sizeof(SNAPHeader));
  1020. Hdr->eh_type = net_short(ShortDataLength);
  1021. SNAPPtr = (SNAPHeader UNALIGNED *)
  1022. (BufAddr + sizeof(ENetHeader));
  1023. RtlCopyMemory(SNAPPtr, ARPSNAP, sizeof(SNAPHeader));
  1024. SNAPPtr->sh_etype = net_short(ARP_ETYPE_IP);
  1025. }
  1026. break;
  1027. case NdisMedium802_5:
  1028. // This is token ring. We'll have to mess around with
  1029. // source routing.
  1030. // for multicast - see RFC 1469.
  1031. // Handle RFC 1469.
  1032. if (!CLASSD_ADDR(Dest) || (!TRFunctionalMcast)) {
  1033. TRHdr = (TRHeader *) BufAddr;
  1034. RtlCopyMemory(TRHdr, TRBcst, offsetof(TRHeader, tr_saddr));
  1035. RtlCopyMemory(TRHdr->tr_saddr, Interface->ai_addr,
  1036. ARP_802_ADDR_LENGTH);
  1037. } else {
  1038. TRHdr = (TRHeader *) BufAddr;
  1039. RtlCopyMemory(TRHdr, TRMcst, offsetof(TRHeader, tr_saddr));
  1040. RtlCopyMemory(TRHdr->tr_saddr, Interface->ai_addr,
  1041. ARP_802_ADDR_LENGTH);
  1042. }
  1043. if (sIPAlwaysSourceRoute) {
  1044. TRHdr->tr_saddr[0] |= TR_RII;
  1045. RCPtr = (RC UNALIGNED *) ((uchar *) TRHdr + sizeof(TRHeader));
  1046. RCPtr->rc_blen = TrRii | RC_LEN;
  1047. RCPtr->rc_dlf = RC_BCST_LEN;
  1048. SNAPPtr = (SNAPHeader UNALIGNED *) ((uchar *) RCPtr + sizeof(RC));
  1049. } else {
  1050. //
  1051. // Adjust the size of the buffer to account for the
  1052. // fact that we don't have the RC field.
  1053. //
  1054. NdisAdjustBufferLength(ARPBuffer, (Size - sizeof(RC)));
  1055. SNAPPtr = (SNAPHeader UNALIGNED *) ((uchar *) TRHdr + sizeof(TRHeader));
  1056. }
  1057. RtlCopyMemory(SNAPPtr, ARPSNAP, sizeof(SNAPHeader));
  1058. SNAPPtr->sh_etype = net_short(ARP_ETYPE_IP);
  1059. break;
  1060. case NdisMediumFddi:
  1061. FHdr = (FDDIHeader *) BufAddr;
  1062. if (!CLASSD_ADDR(Dest))
  1063. RtlCopyMemory(FHdr, FDDIBcst,
  1064. offsetof(FDDIHeader, fh_saddr));
  1065. else {
  1066. RtlCopyMemory(FHdr, FDDIMcst,
  1067. offsetof(FDDIHeader, fh_saddr));
  1068. Temp = (uint UNALIGNED *) & FHdr->fh_daddr[2];
  1069. *Temp |= (Dest & ARP_MCAST_MASK);
  1070. }
  1071. RtlCopyMemory(FHdr->fh_saddr, Interface->ai_addr,
  1072. ARP_802_ADDR_LENGTH);
  1073. SNAPPtr = (SNAPHeader UNALIGNED *) (BufAddr + sizeof(FDDIHeader));
  1074. RtlCopyMemory(SNAPPtr, ARPSNAP, sizeof(SNAPHeader));
  1075. SNAPPtr->sh_etype = net_short(ARP_ETYPE_IP);
  1076. break;
  1077. case NdisMediumArcnet878_2:
  1078. AHdr = (ARCNetHeader *) BufAddr;
  1079. AHdr->ah_saddr = Interface->ai_addr[0];
  1080. AHdr->ah_daddr = 0;
  1081. AHdr->ah_prot = ARP_ARCPROT_IP;
  1082. break;
  1083. default:
  1084. ASSERT(0);
  1085. *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  1086. FreeARPBuffer(Interface, ARPBuffer);
  1087. return FALSE;
  1088. }
  1089. (Interface->ai_outpcount[AI_NONUCAST_INDEX])++;
  1090. Proc = KeGetCurrentProcessorNumber();
  1091. Interface->ai_qlen[Proc].ai_qlen++;
  1092. NdisChainBufferAtFront(Packet, ARPBuffer);
  1093. NdisSend(&MyStatus, Interface->ai_handle, Packet);
  1094. *Status = MyStatus;
  1095. if (MyStatus != NDIS_STATUS_PENDING) { // Send finished
  1096. // immediately.
  1097. if (MyStatus == NDIS_STATUS_SUCCESS) {
  1098. Interface->ai_outoctets += Packet->Private.TotalLength;
  1099. } else {
  1100. if (MyStatus == NDIS_STATUS_RESOURCES)
  1101. Interface->ai_outdiscards++;
  1102. else
  1103. Interface->ai_outerrors++;
  1104. }
  1105. Proc = KeGetCurrentProcessorNumber();
  1106. Interface->ai_qlen[Proc].ai_qlen--;
  1107. NdisUnchainBufferAtFront(Packet, &ARPBuffer);
  1108. FreeARPBuffer(Interface, ARPBuffer);
  1109. }
  1110. } else
  1111. *Status = NDIS_STATUS_RESOURCES;
  1112. } else
  1113. *Status = NDIS_STATUS_ADAPTER_NOT_READY;
  1114. return TRUE;
  1115. } else
  1116. return FALSE;
  1117. }
  1118. //* ARPResolveIP - resolves IP address
  1119. //
  1120. // Called by IP layer when it needs to find physical address of the host
  1121. // given the interface and dest IP address
  1122. // Entry: Interface - A pointer to the AI structure.
  1123. // ArpControlBlock - A pointer to the BufDesc chain to be sent.
  1124. //
  1125. // Returns: Status.
  1126. //
  1127. NDIS_STATUS
  1128. ARPResolveIP(void *Context, IPAddr Destination, void *ArpControlBlock)
  1129. {
  1130. ARPInterface *ai = (ARPInterface *) Context; // Set up as AI pointer.
  1131. ARPControlBlock *ArpContB = (ARPControlBlock *) ArpControlBlock;
  1132. ARPTableEntry *entry; // Pointer to ARP tbl. entry
  1133. CTELockHandle Handle; // Lock handle
  1134. NDIS_STATUS Status;
  1135. uchar ate_state;
  1136. CTEGetLock(&ai->ai_ARPTblLock, &Handle);
  1137. // Check if we already got the mapping.
  1138. if ((entry = ARPLookup(ai, Destination)) != NULL) {
  1139. // Found a matching entry. ARPLookup returns with the ATE lock held.
  1140. if (entry->ate_state != ARP_GOOD) {
  1141. Status = NDIS_STATUS_FAILURE;
  1142. } else {
  1143. Status = FillARPControlBlock(ai, entry, ArpContB);
  1144. }
  1145. CTEFreeLockFromDPC(&entry->ate_lock);
  1146. CTEFreeLock(&ai->ai_ARPTblLock, Handle);
  1147. return Status;
  1148. }
  1149. // We need to send arp request.
  1150. CTEFreeLock(&ai->ai_ARPTblLock, Handle);
  1151. entry = CreateARPTableEntry(ai, Destination, &Handle, ArpContB);
  1152. if (entry != NULL) {
  1153. if (entry->ate_state <= ARP_RESOLVING) { // Newly created entry.
  1154. // Someone else could have raced in and created the entry between
  1155. // the time we free the lock and the time we called
  1156. // CreateARPTableEntry(). We check this by looking at the packet
  1157. // on the entry. If there is no old packet we'll ARP. If there is,
  1158. // we'll call ARPSendData to figure out what to do.
  1159. if (entry->ate_packet == NULL) {
  1160. ate_state = entry->ate_state;
  1161. CTEFreeLock(&entry->ate_lock, Handle);
  1162. SendARPRequest(ai, Destination, ate_state, NULL, TRUE);
  1163. // We don't know the state of the entry - we've freed the lock
  1164. // and yielded, and it could conceivably have timed out by now,
  1165. // or SendARPRequest could have failed, etc. We could take the
  1166. // lock, check the status from SendARPRequest, see if it's
  1167. // still the same packet, and then make a decision on the
  1168. // return value, but it's easiest just to return pending. If
  1169. // SendARPRequest failed, the entry will time out anyway.
  1170. return NDIS_STATUS_PENDING;
  1171. } else {
  1172. CTEFreeLock(&entry->ate_lock, Handle);
  1173. return NDIS_STATUS_PENDING;
  1174. }
  1175. } else if (entry->ate_state == ARP_GOOD) { // Yow! A valid entry.
  1176. Status = FillARPControlBlock(ai, entry, ArpContB);
  1177. //remove ArpContB from ate_resolveonly queue.
  1178. if (entry->ate_resolveonly) {
  1179. ARPControlBlock *TmpArpContB, *PrvArpContB = NULL;
  1180. TmpArpContB = entry->ate_resolveonly;
  1181. while (TmpArpContB && (ArpContB != TmpArpContB)) {
  1182. PrvArpContB = TmpArpContB;
  1183. TmpArpContB = TmpArpContB->next;
  1184. }
  1185. if (TmpArpContB == ArpContB) {
  1186. if (PrvArpContB) {
  1187. PrvArpContB->next = ArpContB->next;
  1188. } else {
  1189. entry->ate_resolveonly = NULL;
  1190. }
  1191. }
  1192. }
  1193. CTEFreeLock(&entry->ate_lock, Handle);
  1194. return Status;
  1195. } else { // An invalid entry!
  1196. CTEFreeLock(&entry->ate_lock, Handle);
  1197. return NDIS_STATUS_RESOURCES;
  1198. }
  1199. } else { // Couldn't create an entry.
  1200. return NDIS_STATUS_RESOURCES;
  1201. }
  1202. }
  1203. //* ARPSendData - Send a frame to a specific destination address.
  1204. //
  1205. // Called when we need to send a frame to a particular address, after the
  1206. // ATE has been looked up. We take in an ATE and a packet, validate the state of the
  1207. // ATE, and either send or ARP for the address if it's not done resolving. We assume
  1208. // the lock on the ATE is held where we're called, and we'll free it before returning.
  1209. //
  1210. // Entry: Interface - A pointer to the AI structure.
  1211. // Packet - A pointer to the BufDesc chain to be sent.
  1212. // entry - A pointer to the ATE for the send.
  1213. // lhandle - Pointer to a lock handle for the ATE.
  1214. //
  1215. // Returns: Status of the transmit - success, an error, or pending.
  1216. //
  1217. NDIS_STATUS
  1218. ARPSendData(ARPInterface * Interface, PNDIS_PACKET Packet, ARPTableEntry * entry,
  1219. CTELockHandle lhandle)
  1220. {
  1221. PNDIS_BUFFER ARPBuffer = NULL; // ARP Header buffer.
  1222. uchar *BufAddr = NULL; // Address of NDIS buffer
  1223. NDIS_STATUS Status; // Status of send.
  1224. ulong Proc;
  1225. #if BACK_FILL
  1226. PMDL TmpMdl = NULL;
  1227. #endif
  1228. if (Interface->ai_operstatus == INTERFACE_UP) {
  1229. if (entry->ate_state == ARP_GOOD) { // Entry is valid
  1230. entry->ate_useticks = ArpCacheLife;
  1231. #if BACK_FILL
  1232. if (Interface->ai_media == NdisMedium802_3) {
  1233. NdisQueryPacket(Packet, NULL, NULL, &TmpMdl, NULL);
  1234. if (TmpMdl->MdlFlags & MDL_NETWORK_HEADER) {
  1235. TmpMdl->MappedSystemVa = (PVOID) (((ULONG_PTR)
  1236. TmpMdl->MappedSystemVa) -
  1237. entry->ate_addrlength);
  1238. TmpMdl->ByteOffset -= entry->ate_addrlength;
  1239. TmpMdl->ByteCount += entry->ate_addrlength;
  1240. ARPBuffer = (PNDIS_BUFFER) TmpMdl;
  1241. BufAddr = TmpMdl->MappedSystemVa;
  1242. } else {
  1243. TmpMdl = NULL;
  1244. }
  1245. }
  1246. if (ARPBuffer == (PNDIS_BUFFER) NULL) {
  1247. ARPBuffer = GetARPBufferAtDpcLevel(Interface, &BufAddr,
  1248. entry->ate_addrlength);
  1249. }
  1250. #else
  1251. ARPBuffer = GetARPBufferAtDpcLevel(Interface, &BufAddr,
  1252. entry->ate_addrlength);
  1253. #endif
  1254. if (ARPBuffer != (PNDIS_BUFFER) NULL) {
  1255. // Everything's in good shape, copy header and send packet.
  1256. (Interface->ai_outpcount[AI_UCAST_INDEX])++;
  1257. Proc = KeGetCurrentProcessorNumber();
  1258. Interface->ai_qlen[Proc].ai_qlen++;
  1259. RtlCopyMemory(BufAddr, entry->ate_addr, entry->ate_addrlength);
  1260. // If we're on Ethernet, see if we're using SNAP here.
  1261. if (Interface->ai_media == NdisMedium802_3 &&
  1262. entry->ate_addrlength != sizeof(ENetHeader)) {
  1263. ENetHeader *Header;
  1264. uint DataSize;
  1265. ushort ShortDataSize;
  1266. // We're apparently using SNAP on Ethernet. Query the
  1267. // packet for the size, and set the length properly.
  1268. NdisQueryPacket(Packet, NULL, NULL, NULL, &DataSize);
  1269. #if BACK_FILL
  1270. if (!TmpMdl) {
  1271. ShortDataSize = (ushort) (DataSize + sizeof(SNAPHeader));
  1272. } else {
  1273. ShortDataSize = (ushort) (DataSize - entry->ate_addrlength + sizeof(SNAPHeader));
  1274. }
  1275. #else // BACK_FILL
  1276. ShortDataSize = (ushort) (DataSize + sizeof(SNAPHeader));
  1277. #endif // !BACK_FILL
  1278. Header = (ENetHeader *) BufAddr;
  1279. Header->eh_type = net_short(ShortDataSize);
  1280. // In case backfill is enabled, we need to remember that
  1281. // a SNAP header was appended to the Ethernet header
  1282. // so we can restore the correct offsets in the MDL.
  1283. ((PacketContext*)
  1284. Packet->ProtocolReserved)->pc_common.pc_flags |=
  1285. PACKET_FLAG_SNAP;
  1286. } else
  1287. ((PacketContext*)
  1288. Packet->ProtocolReserved)->pc_common.pc_flags &=
  1289. ~PACKET_FLAG_SNAP;
  1290. CTEFreeLock(&entry->ate_lock, lhandle);
  1291. #if BACK_FILL
  1292. if (TmpMdl == NULL) {
  1293. NdisChainBufferAtFront(Packet, ARPBuffer);
  1294. }
  1295. #else
  1296. NdisChainBufferAtFront(Packet, ARPBuffer);
  1297. #endif
  1298. NdisSend(&Status, Interface->ai_handle, Packet);
  1299. if (Status != NDIS_STATUS_PENDING) { // Send finished
  1300. // immediately.
  1301. if (Status == NDIS_STATUS_SUCCESS) {
  1302. Interface->ai_outoctets += Packet->Private.TotalLength;
  1303. } else {
  1304. if (Status == NDIS_STATUS_RESOURCES)
  1305. Interface->ai_outdiscards++;
  1306. else
  1307. Interface->ai_outerrors++;
  1308. }
  1309. Proc = KeGetCurrentProcessorNumber();
  1310. Interface->ai_qlen[Proc].ai_qlen--;
  1311. #if BACK_FILL
  1312. if (TmpMdl == NULL) {
  1313. NdisUnchainBufferAtFront(Packet, &ARPBuffer);
  1314. FreeARPBuffer(Interface, ARPBuffer);
  1315. } else {
  1316. uint HdrSize;
  1317. HdrSize = sizeof(ENetHeader);
  1318. if (((PacketContext *)
  1319. Packet->ProtocolReserved)->pc_common.pc_flags &
  1320. PACKET_FLAG_SNAP)
  1321. HdrSize += Interface->ai_snapsize;
  1322. TmpMdl->MappedSystemVa = (PVOID) (((ULONG_PTR)
  1323. TmpMdl->MappedSystemVa) +
  1324. HdrSize);
  1325. TmpMdl->ByteOffset += HdrSize;
  1326. TmpMdl->ByteCount -= HdrSize;
  1327. }
  1328. #else
  1329. NdisUnchainBufferAtFront(Packet, &ARPBuffer);
  1330. FreeARPBuffer(Interface, ARPBuffer);
  1331. #endif
  1332. }
  1333. return Status;
  1334. } else { // No buffer, free lock and return.
  1335. CTEFreeLock(&entry->ate_lock, lhandle);
  1336. Interface->ai_outdiscards++;
  1337. return NDIS_STATUS_RESOURCES;
  1338. }
  1339. }
  1340. // The IP addresses match, but the state of the ARP entry indicates
  1341. // it's not valid. If the address is marked as resolving, we'll replace
  1342. // the current cached packet with this one. If it's been more than
  1343. // ARP_FLOOD_RATE ms. since we last sent an ARP request, we'll send
  1344. // another one now.
  1345. if (entry->ate_state <= ARP_RESOLVING) {
  1346. PNDIS_PACKET OldPacket = entry->ate_packet;
  1347. ulong Now = CTESystemUpTime();
  1348. entry->ate_packet = Packet;
  1349. if ((Now - entry->ate_valid) > ARP_FLOOD_RATE) {
  1350. IPAddr Dest = entry->ate_dest;
  1351. entry->ate_valid = Now;
  1352. entry->ate_state = ARP_RESOLVING_GLOBAL; // We've done this
  1353. // at least once.
  1354. CTEFreeLock(&entry->ate_lock, lhandle);
  1355. SendARPRequest(Interface, Dest, ARP_RESOLVING_GLOBAL,
  1356. NULL, TRUE); // Send a request.
  1357. } else
  1358. CTEFreeLock(&entry->ate_lock, lhandle);
  1359. if (OldPacket)
  1360. IPSendComplete(Interface->ai_context, OldPacket,
  1361. NDIS_STATUS_SUCCESS);
  1362. return NDIS_STATUS_PENDING;
  1363. } else {
  1364. ASSERT(0);
  1365. CTEFreeLock(&entry->ate_lock, lhandle);
  1366. Interface->ai_outerrors++;
  1367. return NDIS_STATUS_INVALID_PACKET;
  1368. }
  1369. } else {
  1370. // Adapter is down. Just return the error.
  1371. CTEFreeLock(&entry->ate_lock, lhandle);
  1372. return NDIS_STATUS_ADAPTER_NOT_READY;
  1373. }
  1374. }
  1375. //* CreateARPTableEntry - Create a new entry in the ARP table.
  1376. //
  1377. // A function to put an entry into the ARP table. We allocate memory if we
  1378. // need to.
  1379. //
  1380. // The first thing to do is get the lock on the ARP table, and see if the
  1381. // entry already exists. If it does, we're done. Otherwise we need to
  1382. // allocate memory and create a new entry.
  1383. //
  1384. // Entry: Interface - Interface for ARP table.
  1385. // Destination - Destination address to be mapped.
  1386. // Handle - Pointer to lock handle for entry.
  1387. //
  1388. // Returns: Pointer to newly created entry.
  1389. //
  1390. ARPTableEntry *
  1391. CreateARPTableEntry(ARPInterface * Interface, IPAddr Destination,
  1392. CTELockHandle * Handle, void *UserArp)
  1393. {
  1394. ARPTableEntry *NewEntry, *Entry;
  1395. CTELockHandle TableHandle;
  1396. int i = ARP_HASH(Destination);
  1397. int Size;
  1398. // First look for it, and if we don't find it return try to create one.
  1399. CTEGetLock(&Interface->ai_ARPTblLock, &TableHandle);
  1400. if ((Entry = ARPLookup(Interface, Destination)) != NULL) {
  1401. CTEFreeLockFromDPC(&Interface->ai_ARPTblLock);
  1402. *Handle = TableHandle;
  1403. // if we are using arp api entry, turn off the
  1404. // userarp flag so that handle arp need not free it.
  1405. if (!UserArp && Entry->ate_userarp) {
  1406. Entry->ate_userarp = 0;
  1407. }
  1408. if (UserArp) {
  1409. if (Entry->ate_resolveonly) {
  1410. // chain the current request at the end of the new
  1411. // before using the new request as the head.
  1412. //
  1413. ((ARPControlBlock *)UserArp)->next = Entry->ate_resolveonly;
  1414. }
  1415. // link the new request.
  1416. //
  1417. Entry->ate_resolveonly = (ARPControlBlock *)UserArp;
  1418. }
  1419. return Entry;
  1420. }
  1421. // Allocate memory for the entry. If we can't, fail the request.
  1422. Size = sizeof(ARPTableEntry) - 1 +
  1423. (Interface->ai_media == NdisMedium802_5 ?
  1424. ARP_MAX_MEDIA_TR : (Interface->ai_hdrsize +
  1425. Interface->ai_snapsize));
  1426. if ((NewEntry = CTEAllocMemN(Size, 'QiCT')) == (ARPTableEntry *) NULL) {
  1427. CTEFreeLock(&Interface->ai_ARPTblLock, TableHandle);
  1428. return (ARPTableEntry *) NULL;
  1429. }
  1430. RtlZeroMemory(NewEntry, Size);
  1431. NewEntry->ate_dest = Destination;
  1432. if (Interface->ai_media != NdisMedium802_5 || sArpAlwaysSourceRoute) {
  1433. NewEntry->ate_state = ARP_RESOLVING_GLOBAL;
  1434. } else {
  1435. NewEntry->ate_state = ARP_RESOLVING_LOCAL;
  1436. }
  1437. if (UserArp) {
  1438. NewEntry->ate_userarp = 1;
  1439. }
  1440. NewEntry->ate_resolveonly = (ARPControlBlock *)UserArp;
  1441. NewEntry->ate_valid = CTESystemUpTime();
  1442. NewEntry->ate_useticks = ArpCacheLife;
  1443. CTEInitLock(&NewEntry->ate_lock);
  1444. // Entry does not exist. Insert the new entry into the table at the
  1445. // appropriate spot.
  1446. //
  1447. NewEntry->ate_next = (*Interface->ai_ARPTbl)[i];
  1448. (*Interface->ai_ARPTbl)[i] = NewEntry;
  1449. Interface->ai_count++;
  1450. CTEGetLockAtDPC(&NewEntry->ate_lock);
  1451. CTEFreeLockFromDPC(&Interface->ai_ARPTblLock);
  1452. *Handle = TableHandle;
  1453. return NewEntry;
  1454. }
  1455. //* ARPTransmit - Send a frame.
  1456. //
  1457. // The main ARP transmit routine, called by the upper layer. This routine
  1458. // takes as input a buf desc chain, RCE, and size. We validate the cached
  1459. // information in the RCE. If it is valid, we use it to send the frame.
  1460. // Otherwise we do a table lookup. If we find it in the table, we'll update
  1461. // the RCE and continue. Otherwise we'll queue the packet and start an ARP
  1462. // resolution.
  1463. //
  1464. // Entry: Context - A pointer to the AI structure.
  1465. // Packet - A pointer to the BufDesc chain to be sent.
  1466. // Destination - IP address of destination we're trying to reach,
  1467. // RCE - A pointer to an RCE which may have cached information.
  1468. //
  1469. // Returns: Status of the transmit - success, an error, or pending.
  1470. //
  1471. NDIS_STATUS
  1472. __stdcall
  1473. ARPTransmit(void *Context, PNDIS_PACKET * PacketArray, uint NumberOfPackets,
  1474. IPAddr Destination, RouteCacheEntry * RCE, void *LinkCtxt)
  1475. {
  1476. ARPInterface *ai = (ARPInterface *) Context; // Set up as AI pointer.
  1477. ARPContext *ac = NULL; // ARP context pointer.
  1478. ARPTableEntry *entry; // Pointer to ARP tbl. entry
  1479. CTELockHandle Handle; // Lock handle
  1480. NDIS_STATUS Status;
  1481. PNDIS_PACKET Packet = *PacketArray;
  1482. //
  1483. // For now, we get only one packet...
  1484. //
  1485. DBG_UNREFERENCED_PARAMETER(NumberOfPackets);
  1486. UNREFERENCED_PARAMETER(LinkCtxt);
  1487. ASSERT(NumberOfPackets == 1);
  1488. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_TX,
  1489. (DTEXT("+ARPTransmit(%x, %x, %d, %x, %x, %x)\n"),
  1490. Context, PacketArray, NumberOfPackets,
  1491. Destination, RCE, LinkCtxt));
  1492. if (ai->ai_operstatus != INTERFACE_UP) {
  1493. return NDIS_STATUS_ADAPTER_NOT_READY;
  1494. }
  1495. CTEGetLock(&ai->ai_ARPTblLock, &Handle);
  1496. if (RCE != (RouteCacheEntry *) NULL) { // Have a valid RCE.
  1497. ac = (ARPContext *) RCE->rce_context; // Get pointer to context
  1498. entry = ac->ac_ate;
  1499. if (entry != (ARPTableEntry *) NULL) { // Have a valid ATE.
  1500. CTEGetLockAtDPC(&entry->ate_lock); // Lock this structure
  1501. if (IP_ADDR_EQUAL(entry->ate_dest, Destination)) {
  1502. uint refresh,status;
  1503. uchar state = entry->ate_state;
  1504. refresh= entry->ate_refresh;
  1505. CTEFreeLockFromDPC(&ai->ai_ARPTblLock);
  1506. status = ARPSendData(ai, Packet, entry, Handle); // Send the data
  1507. if (refresh) {
  1508. if (sArpAlwaysSourceRoute) {
  1509. //
  1510. // If Always source route is on,
  1511. // the state should ve resolving_global
  1512. // so that SendArpRequest will send SR
  1513. // header in case of 802.5.
  1514. //
  1515. state = ARP_RESOLVING_GLOBAL;
  1516. }
  1517. SendARPRequest(ai, Destination, state, NULL, TRUE);
  1518. }
  1519. return status;
  1520. }
  1521. // We have an RCE that identifies the wrong ATE. We'll free it from
  1522. // this list and try and find an ATE that is valid.
  1523. ARPRemoveRCE(entry, RCE);
  1524. CTEFreeLockFromDPC(&entry->ate_lock);
  1525. // Fall through to 'no valid entry' code.
  1526. }
  1527. }
  1528. // Here we have no valid ATE, either because the RCE is NULL or the ATE
  1529. // specified by the RCE was invalid. We'll try and find one in the table. If
  1530. // we find one, we'll fill in this RCE and send the packet. Otherwise we'll
  1531. // try to create one. At this point we hold the lock on the ARP table.
  1532. if ((entry = ARPLookup(ai, Destination)) != (ARPTableEntry *) NULL) {
  1533. // Found a matching entry. ARPLookup returns with the ATE lock held.
  1534. if (RCE != (RouteCacheEntry *) NULL) {
  1535. ac->ac_next = entry->ate_rce; // Fill in context for next time.
  1536. entry->ate_rce = RCE;
  1537. ac->ac_ate = entry;
  1538. }
  1539. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_TX,
  1540. (DTEXT("ARPTx: ATE %x - calling ARPSendData\n"), entry));
  1541. CTEFreeLockFromDPC(&ai->ai_ARPTblLock);
  1542. return ARPSendData(ai, Packet, entry, Handle);
  1543. }
  1544. // No valid entry in the ARP table. First we'll see if we're sending to a
  1545. // broadcast address or multicast address. If not, we'll try to create
  1546. // an entry in the table and get an ARP resolution going. ARPLookup returns
  1547. // with the table lock held when it fails, we'll free it here.
  1548. CTEFreeLock(&ai->ai_ARPTblLock, Handle);
  1549. if (ARPSendBCast(ai, Destination, Packet, &Status)) {
  1550. return Status;
  1551. }
  1552. entry = CreateARPTableEntry(ai, Destination, &Handle, 0);
  1553. if (entry != NULL) {
  1554. if (entry->ate_state <= ARP_RESOLVING) { // Newly created entry.
  1555. uchar state = entry->ate_state;
  1556. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_TX,
  1557. (DTEXT("ARPTx: Created ATE %x\n"), entry));
  1558. // Someone else could have raced in and created the entry between
  1559. // the time we free the lock and the time we called
  1560. // CreateARPTableEntry(). We check this by looking at the packet
  1561. // on the entry. If there is no old packet we'll ARP. If there is,
  1562. // we'll call ARPSendData to figure out what to do.
  1563. if (entry->ate_packet == NULL) {
  1564. entry->ate_packet = Packet;
  1565. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_TX,
  1566. (DTEXT("ARPTx: ATE %x - calling SendARPRequest\n"), entry));
  1567. CTEFreeLock(&entry->ate_lock, Handle);
  1568. SendARPRequest(ai, Destination, state, NULL, TRUE);
  1569. // We don't know the state of the entry - we've freed the lock
  1570. // and yielded, and it could conceivably have timed out by now,
  1571. // or SendARPRequest could have failed, etc. We could take the
  1572. // lock, check the status from SendARPRequest, see if it's
  1573. // still the same packet, and then make a decision on the
  1574. // return value, but it's easiest just to return pending. If
  1575. // SendARPRequest failed, the entry will time out anyway.
  1576. return NDIS_STATUS_PENDING;
  1577. } else {
  1578. return ARPSendData(ai, Packet, entry, Handle);
  1579. }
  1580. } else if (entry->ate_state == ARP_GOOD) { // Yow! A valid entry.
  1581. return ARPSendData(ai, Packet, entry, Handle);
  1582. } else { // An invalid entry!
  1583. CTEFreeLock(&entry->ate_lock, Handle);
  1584. return NDIS_STATUS_RESOURCES;
  1585. }
  1586. } else { // Couldn't create an entry.
  1587. DEBUGMSG(DBG_ERROR && DBG_ARP,
  1588. (DTEXT("ARPTx: Failed to create ATE.\n")));
  1589. return NDIS_STATUS_RESOURCES;
  1590. }
  1591. }
  1592. //* RemoveARPTableEntry - Delete an entry from the ARP table.
  1593. //
  1594. // This is a simple utility function to delete an entry from the ATP table. We
  1595. // assume locks are held on both the table and the entry.
  1596. //
  1597. // Entry: Previous - The entry immediately before the one to be deleted.
  1598. // Entry - The entry to be deleted.
  1599. //
  1600. // Returns: Nothing.
  1601. //
  1602. void
  1603. RemoveARPTableEntry(ARPTableEntry * Previous, ARPTableEntry * Entry)
  1604. {
  1605. RouteCacheEntry *RCE; // Pointer to route cache entry
  1606. ARPContext *AC;
  1607. RCE = Entry->ate_rce;
  1608. // Loop through and invalidate all RCEs on this ATE.
  1609. while (RCE != (RouteCacheEntry *) NULL) {
  1610. AC = (ARPContext *) RCE->rce_context;
  1611. AC->ac_ate = (ARPTableEntry *) NULL;
  1612. RCE = AC->ac_next;
  1613. }
  1614. // Splice this guy out of the list.
  1615. Previous->ate_next = Entry->ate_next;
  1616. }
  1617. //* ARPFlushATE - removes ARP Table entry for given dest address
  1618. //
  1619. // Called by IP layer when it needs to flush the link layer address from arp
  1620. // cache
  1621. // Entry: Interface - A pointer to the AI structure.
  1622. // Destination - Destination Address whose Xlation needs to be removed
  1623. //
  1624. // Returns: TRUE if the entry was found and flushed, FALSE otherwise
  1625. //
  1626. BOOLEAN
  1627. ARPFlushATE(void *Context, IPAddr Address)
  1628. {
  1629. ARPInterface *ai = (ARPInterface *) Context;
  1630. CTELockHandle lhandle, tlhandle;
  1631. ARPTable *Table;
  1632. ARPTableEntry *Current, *Previous;
  1633. int i = ARP_HASH(Address);
  1634. PNDIS_PACKET OldPacket = NULL;
  1635. CTEGetLock(&ai->ai_ARPTblLock, &tlhandle);
  1636. Table = ai->ai_ARPTbl;
  1637. Current = (*Table)[i];
  1638. Previous = (ARPTableEntry *) ((uchar *) & ((*Table)[i]) - offsetof(struct ARPTableEntry, ate_next));
  1639. while (Current != (ARPTableEntry *) NULL) {
  1640. CTEGetLock(&Current->ate_lock, &lhandle);
  1641. if (IP_ADDR_EQUAL(Current->ate_dest, Address)) { // Found a match.
  1642. if (Current->ate_resolveonly) {
  1643. ARPControlBlock *ArpContB, *TmpArpContB;
  1644. ArpContB = Current->ate_resolveonly;
  1645. while (ArpContB) {
  1646. ArpRtn rtn;
  1647. rtn = (ArpRtn) ArpContB->CompletionRtn;
  1648. ArpContB->status = (ULONG) STATUS_UNSUCCESSFUL;
  1649. TmpArpContB = ArpContB->next;
  1650. (*rtn) (ArpContB, (IP_STATUS) STATUS_UNSUCCESSFUL);
  1651. ArpContB = TmpArpContB;
  1652. }
  1653. Current->ate_resolveonly = NULL;
  1654. }
  1655. RemoveARPTableEntry(Previous, Current);
  1656. CTEFreeLock(&Current->ate_lock, lhandle);
  1657. OldPacket = Current->ate_packet;
  1658. CTEFreeLock(&ai->ai_ARPTblLock, tlhandle);
  1659. if (OldPacket) {
  1660. IPSendComplete(ai->ai_context, OldPacket, NDIS_STATUS_SUCCESS);
  1661. }
  1662. CTEFreeMem(Current);
  1663. return TRUE;
  1664. }
  1665. CTEFreeLock(&Current->ate_lock, lhandle);
  1666. Previous = Current;
  1667. Current = Current->ate_next;
  1668. }
  1669. CTEFreeLock(&ai->ai_ARPTblLock, tlhandle);
  1670. return FALSE;
  1671. }
  1672. //* ARPFlushAllATE - removes all ARP Table entries.
  1673. //
  1674. // Entry: Interface - A pointer to the AI structure.
  1675. //
  1676. // Returns: None
  1677. //
  1678. void
  1679. ARPFlushAllATE(void *Context)
  1680. {
  1681. ARPInterface *ai = (ARPInterface *) Context;
  1682. CTELockHandle tlhandle;
  1683. ARPTable *Table;
  1684. int i;
  1685. ARPTableEntry *ATE;
  1686. PNDIS_PACKET PList = (PNDIS_PACKET) NULL;
  1687. CTEGetLock(&ai->ai_ARPTblLock, &tlhandle);
  1688. Table = ai->ai_ARPTbl;
  1689. if (Table != NULL) {
  1690. for (i = 0; i < ARP_TABLE_SIZE; i++) {
  1691. while ((*Table)[i] != NULL) {
  1692. ATE = (*Table)[i];
  1693. if (ATE->ate_resolveonly) {
  1694. ARPControlBlock *ArpContB, *TmpArpContB;
  1695. ArpContB = ATE->ate_resolveonly;
  1696. while (ArpContB) {
  1697. ArpRtn rtn;
  1698. rtn = (ArpRtn) ArpContB->CompletionRtn;
  1699. ArpContB->status = (ULONG) STATUS_UNSUCCESSFUL;
  1700. TmpArpContB = ArpContB->next;
  1701. (*rtn) (ArpContB, (IP_STATUS) STATUS_UNSUCCESSFUL);
  1702. ArpContB = TmpArpContB;
  1703. }
  1704. ATE->ate_resolveonly = NULL;
  1705. }
  1706. // Acquire ate_lock to ensure exclusive access to the ATE.
  1707. CTEGetLockAtDPC(&ATE->ate_lock);
  1708. RemoveARPTableEntry(STRUCT_OF(ARPTableEntry, &((*Table)[i]), ate_next),
  1709. ATE);
  1710. CTEFreeLockFromDPC(&ATE->ate_lock);
  1711. if (ATE->ate_packet) {
  1712. ((PacketContext *) ATE->ate_packet->ProtocolReserved)->pc_common.pc_link = PList;
  1713. PList = ATE->ate_packet;
  1714. }
  1715. CTEFreeMem(ATE);
  1716. }
  1717. }
  1718. }
  1719. CTEFreeLock(&ai->ai_ARPTblLock, tlhandle);
  1720. while (PList != (PNDIS_PACKET) NULL) {
  1721. PNDIS_PACKET Packet = PList;
  1722. PList = ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_link;
  1723. IPSendComplete(ai->ai_context, Packet, NDIS_STATUS_SUCCESS);
  1724. }
  1725. }
  1726. //* ARPXferData - Transfer data on behalf on an upper later protocol.
  1727. //
  1728. // This routine is called by the upper layer when it needs to transfer data
  1729. // from an NDIS driver. We just map his call down.
  1730. //
  1731. // Entry: Context - Context value we gave to IP (really a pointer to an AI).
  1732. // MACContext - Context value MAC gave us on a receive.
  1733. // MyOffset - Packet offset we gave to the protocol earlier.
  1734. // ByteOffset - Byte offset into packet protocol wants transferred.
  1735. // BytesWanted - Number of bytes to transfer.
  1736. // Packet - Pointer to packet to be used for transferring.
  1737. // Transferred - Pointer to where to return bytes transferred.
  1738. //
  1739. // Returns: NDIS_STATUS of command.
  1740. //
  1741. NDIS_STATUS
  1742. __stdcall
  1743. ARPXferData(void *Context, NDIS_HANDLE MACContext, uint MyOffset,
  1744. uint ByteOffset, uint BytesWanted, PNDIS_PACKET Packet, uint * Transferred)
  1745. {
  1746. ARPInterface *Interface = (ARPInterface *) Context;
  1747. NDIS_STATUS Status;
  1748. NdisTransferData(&Status, Interface->ai_handle, MACContext, ByteOffset + MyOffset,
  1749. BytesWanted, Packet, Transferred);
  1750. return Status;
  1751. }
  1752. //* ARPUpdateOperStatus - Update the OperStatus and LastChange values.
  1753. //
  1754. // Called whenever ai_adminstate or ai_mediastatus changes, to preserve
  1755. // the invariant that ai_operstatus should only be up if the admin
  1756. // status is up and media sense is present.
  1757. //
  1758. // Entry: Interface - Interface to update.
  1759. //
  1760. // Returns: Nothing.
  1761. //
  1762. __inline
  1763. void
  1764. ARPUpdateOperStatus(ARPInterface *Interface)
  1765. {
  1766. uchar NewOperStatus;
  1767. if (Interface->ai_operstatus == INTERFACE_UNINIT) {
  1768. return;
  1769. }
  1770. if ((Interface->ai_adminstate == IF_STATUS_DOWN) ||
  1771. (Interface->ai_mediastatus == FALSE)) {
  1772. NewOperStatus = INTERFACE_DOWN;
  1773. } else {
  1774. NewOperStatus = INTERFACE_UP;
  1775. }
  1776. if (Interface->ai_operstatus != NewOperStatus) {
  1777. Interface->ai_operstatus = NewOperStatus;
  1778. Interface->ai_lastchange = GetTimeTicks();
  1779. }
  1780. }
  1781. //* ARPClose - Close an adapter.
  1782. //
  1783. // Called by IP when it wants to close an adapter, presumably due to an error condition.
  1784. // We'll close the adapter, but we won't free any memory.
  1785. //
  1786. // Entry: Context - Context value we gave him earlier.
  1787. //
  1788. // Returns: Nothing.
  1789. //
  1790. void
  1791. __stdcall
  1792. ARPClose(void *Context)
  1793. {
  1794. ARPInterface *Interface = (ARPInterface *) Context;
  1795. NDIS_STATUS Status;
  1796. CTELockHandle LockHandle;
  1797. NDIS_HANDLE Handle;
  1798. Interface->ai_mediastatus = FALSE;
  1799. ARPUpdateOperStatus(Interface);
  1800. //
  1801. // Mark the interface as going away so it will disappear from the
  1802. // entity list.
  1803. //
  1804. Interface->ai_operstatus = INTERFACE_UNINIT;
  1805. CTEInitBlockStruc(&Interface->ai_block);
  1806. CTEGetLock(&Interface->ai_lock, &LockHandle);
  1807. if (Interface->ai_handle != (NDIS_HANDLE) NULL) {
  1808. Handle = Interface->ai_handle;
  1809. CTEFreeLock(&Interface->ai_lock, LockHandle);
  1810. NdisCloseAdapter(&Status, Handle);
  1811. if (Status == NDIS_STATUS_PENDING) {
  1812. Status = CTEBlock(&Interface->ai_block);
  1813. }
  1814. Interface->ai_handle = NULL;
  1815. } else {
  1816. CTEFreeLock(&Interface->ai_lock, LockHandle);
  1817. }
  1818. }
  1819. //* ARPInvalidate - Notification that an RCE is invalid.
  1820. //
  1821. // Called by IP when an RCE is closed or otherwise invalidated. We look up
  1822. // the ATE for the specified RCE, and then remove the RCE from the ATE list.
  1823. //
  1824. // Entry: Context - Context value we gave him earlier.
  1825. // RCE - RCE to be invalidated
  1826. //
  1827. // Returns: Nothing.
  1828. //
  1829. void
  1830. __stdcall
  1831. ARPInvalidate(void *Context, RouteCacheEntry *RCE)
  1832. {
  1833. ARPInterface *Interface = (ARPInterface *) Context;
  1834. ARPTableEntry *ATE;
  1835. CTELockHandle Handle;
  1836. ARPContext *AC = (ARPContext *) RCE->rce_context;
  1837. CTEGetLock(&Interface->ai_ARPTblLock, &Handle);
  1838. #if DBG
  1839. if (!(RCE->rce_flags & RCE_CONNECTED)) {
  1840. ARPTableEntry *tmpATE;
  1841. ATE = ARPLookup(Interface, RCE->rce_dest);
  1842. if (ATE != NULL) {
  1843. tmpATE = ATE;
  1844. while (ATE) {
  1845. if (ATE->ate_rce == RCE) {
  1846. DbgBreakPoint();
  1847. }
  1848. ATE = ATE->ate_next;
  1849. }
  1850. CTEFreeLockFromDPC(&Interface->ai_ARPTblLock);
  1851. CTEFreeLock(&tmpATE->ate_lock, Handle);
  1852. return;
  1853. }
  1854. }
  1855. #endif
  1856. if ((ATE = AC->ac_ate) == (ARPTableEntry *) NULL) {
  1857. CTEFreeLock(&Interface->ai_ARPTblLock, Handle); // No matching ATE.
  1858. return;
  1859. }
  1860. CTEGetLockAtDPC(&ATE->ate_lock);
  1861. ARPRemoveRCE(ATE, RCE);
  1862. RtlZeroMemory(RCE->rce_context, RCE_CONTEXT_SIZE);
  1863. CTEFreeLockFromDPC(&Interface->ai_ARPTblLock);
  1864. CTEFreeLock(&ATE->ate_lock, Handle);
  1865. }
  1866. //* ARPSetMCastList - Set the multicast address list for the adapter.
  1867. //
  1868. // Called to try and set the multicast reception list for the adapter.
  1869. // We allocate a buffer big enough to hold the new address list, and format
  1870. // the address list into the buffer. Then we submit the NDIS request to set
  1871. // the list. If we can't set the list because the multicast address list is
  1872. // full we'll put the card into all multicast mode.
  1873. //
  1874. // Input: Interface - Interface on which to set list.
  1875. //
  1876. // Returns: NDIS_STATUS of attempt.
  1877. //
  1878. NDIS_STATUS
  1879. ARPSetMCastList(ARPInterface * Interface)
  1880. {
  1881. CTELockHandle Handle;
  1882. uchar *MCastBuffer, *CurrentPtr;
  1883. uint MCastSize;
  1884. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1885. uint i;
  1886. ARPMCastAddr *AddrPtr;
  1887. IPAddr UNALIGNED *Temp;
  1888. CTEGetLock(&Interface->ai_lock, &Handle);
  1889. MCastSize = Interface->ai_mcastcnt * ARP_802_ADDR_LENGTH;
  1890. if (MCastSize != 0)
  1891. MCastBuffer = CTEAllocMemN(MCastSize, 'RiCT');
  1892. else
  1893. MCastBuffer = NULL;
  1894. if (MCastBuffer != NULL || MCastSize == 0) {
  1895. // Got the buffer. Loop through, building the list.
  1896. AddrPtr = Interface->ai_mcast;
  1897. CurrentPtr = MCastBuffer;
  1898. for (i = 0; i < Interface->ai_mcastcnt; i++) {
  1899. ASSERT(AddrPtr != NULL);
  1900. if (Interface->ai_media == NdisMedium802_3) {
  1901. RtlCopyMemory(CurrentPtr, ENetMcst, ARP_802_ADDR_LENGTH);
  1902. Temp = (IPAddr UNALIGNED *) (CurrentPtr + 2);
  1903. *Temp |= AddrPtr->ama_addr;
  1904. } else if ((Interface->ai_media == NdisMedium802_5) & TRFunctionalMcast) {
  1905. RtlCopyMemory(CurrentPtr, TRNetMcst, ARP_802_ADDR_LENGTH - 2);
  1906. MCastSize = 4;
  1907. } else if (Interface->ai_media == NdisMediumFddi) {
  1908. RtlCopyMemory(CurrentPtr, ((FDDIHeader *) FDDIMcst)->fh_daddr,
  1909. ARP_802_ADDR_LENGTH);
  1910. Temp = (IPAddr UNALIGNED *) (CurrentPtr + 2);
  1911. *Temp |= AddrPtr->ama_addr;
  1912. } else
  1913. ASSERT(0);
  1914. CurrentPtr += ARP_802_ADDR_LENGTH;
  1915. AddrPtr = AddrPtr->ama_next;
  1916. }
  1917. CTEFreeLock(&Interface->ai_lock, Handle);
  1918. // We're built the list. Now give it to the driver to handle.
  1919. if (Interface->ai_media == NdisMedium802_3) {
  1920. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1921. OID_802_3_MULTICAST_LIST, MCastBuffer, MCastSize, NULL, TRUE);
  1922. } else if ((Interface->ai_media == NdisMedium802_5) & TRFunctionalMcast) {
  1923. if (!(Interface->ai_pfilter & NDIS_PACKET_TYPE_FUNCTIONAL)) {
  1924. Interface->ai_pfilter |= NDIS_PACKET_TYPE_FUNCTIONAL;
  1925. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1926. OID_GEN_CURRENT_PACKET_FILTER,
  1927. &Interface->ai_pfilter,
  1928. sizeof(uint), NULL, TRUE);
  1929. }
  1930. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1931. OID_802_5_CURRENT_FUNCTIONAL, MCastBuffer, MCastSize, NULL,
  1932. TRUE);
  1933. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1934. "SetMcast after OID-- TR mcast address on %x status %x\n",
  1935. Interface, Status));
  1936. } else if (Interface->ai_media == NdisMediumFddi) {
  1937. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1938. OID_FDDI_LONG_MULTICAST_LIST, MCastBuffer, MCastSize, NULL,
  1939. TRUE);
  1940. } else
  1941. ASSERT(0);
  1942. if (MCastBuffer != NULL) {
  1943. CTEFreeMem(MCastBuffer);
  1944. }
  1945. if (Status == NDIS_STATUS_MULTICAST_FULL) {
  1946. // Multicast list is full. Try to set the filter to all multicasts.
  1947. Interface->ai_pfilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
  1948. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1949. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  1950. sizeof(uint), NULL, TRUE);
  1951. }
  1952. } else {
  1953. CTEFreeLock(&Interface->ai_lock, Handle);
  1954. Status = NDIS_STATUS_RESOURCES;
  1955. }
  1956. return Status;
  1957. }
  1958. //* ARPFindMCast - Find a multicast address structure on our list.
  1959. //
  1960. // Called as a utility to find a multicast address structure. If we find
  1961. // it, we return a pointer to it and it's predecessor. Otherwise we return
  1962. // NULL. We assume the caller holds the lock on the interface already.
  1963. //
  1964. // Input: Interface - Interface to search.
  1965. // Addr - Addr to find.
  1966. // Prev - Where to return previous pointer.
  1967. //
  1968. // Returns: Pointer if we find one, NULL otherwise.
  1969. //
  1970. ARPMCastAddr *
  1971. ARPFindMCast(ARPInterface * Interface, IPAddr Addr, ARPMCastAddr ** Prev)
  1972. {
  1973. ARPMCastAddr *AddrPtr, *PrevPtr;
  1974. PrevPtr = STRUCT_OF(ARPMCastAddr, &Interface->ai_mcast, ama_next);
  1975. AddrPtr = PrevPtr->ama_next;
  1976. while (AddrPtr != NULL) {
  1977. if (IP_ADDR_EQUAL(AddrPtr->ama_addr, Addr))
  1978. break;
  1979. else {
  1980. PrevPtr = AddrPtr;
  1981. AddrPtr = PrevPtr->ama_next;
  1982. }
  1983. }
  1984. *Prev = PrevPtr;
  1985. return AddrPtr;
  1986. }
  1987. //* ARPDelMCast - Delete a multicast address.
  1988. //
  1989. // Called when we want to delete a multicast address. We look for a matching
  1990. // (masked) address. If we find one, we'll dec. the reference count and if
  1991. // it goes to 0 we'll pull him from the list and reset the multicast list.
  1992. //
  1993. // Input: Interface - Interface on which to act.
  1994. // Addr - Address to be deleted.
  1995. //
  1996. // Returns: TRUE if it worked, FALSE otherwise.
  1997. //
  1998. uint
  1999. ARPDelMCast(ARPInterface * Interface, IPAddr Addr)
  2000. {
  2001. ARPMCastAddr *AddrPtr, *PrevPtr;
  2002. CTELockHandle Handle;
  2003. uint Status = TRUE;
  2004. // When we support TR (RFC 1469) fully we'll need to change this.
  2005. if (Interface->ai_media == NdisMedium802_3 ||
  2006. Interface->ai_media == NdisMediumFddi ||
  2007. (Interface->ai_media == NdisMedium802_5 && TRFunctionalMcast)) {
  2008. // This is an interface that supports mcast addresses.
  2009. Addr &= ARP_MCAST_MASK;
  2010. CTEGetLock(&Interface->ai_lock, &Handle);
  2011. AddrPtr = ARPFindMCast(Interface, Addr, &PrevPtr);
  2012. if (AddrPtr != NULL) {
  2013. // We found one. Dec. his refcnt, and if it's 0 delete him.
  2014. (AddrPtr->ama_refcnt)--;
  2015. if (AddrPtr->ama_refcnt == 0) {
  2016. // He's done.
  2017. PrevPtr->ama_next = AddrPtr->ama_next;
  2018. (Interface->ai_mcastcnt)--;
  2019. CTEFreeLock(&Interface->ai_lock, Handle);
  2020. CTEFreeMem(AddrPtr);
  2021. ARPSetMCastList(Interface);
  2022. CTEGetLock(&Interface->ai_lock, &Handle);
  2023. }
  2024. } else
  2025. Status = FALSE;
  2026. CTEFreeLock(&Interface->ai_lock, Handle);
  2027. }
  2028. return Status;
  2029. }
  2030. //* ARPAddMCast - Add a multicast address.
  2031. //
  2032. // Called when we want to start receiving a multicast address. We'll mask
  2033. // the address and look it up in our address list. If we find it, we'll just
  2034. // bump the reference count. Otherwise we'll try to create one and put him
  2035. // on the list. In that case we'll need to set the multicast address list for
  2036. // the adapter.
  2037. //
  2038. // Input: Interface - Interface to set on.
  2039. // Addr - Address to set.
  2040. //
  2041. // Returns: TRUE if we succeed, FALSE if we fail.
  2042. //
  2043. uint
  2044. ARPAddMCast(ARPInterface * Interface, IPAddr Addr)
  2045. {
  2046. ARPMCastAddr *AddrPtr, *PrevPtr;
  2047. CTELockHandle Handle;
  2048. uint Status = TRUE;
  2049. if (Interface->ai_operstatus != INTERFACE_UP) {
  2050. return FALSE;
  2051. }
  2052. // Currently we don't do anything with token ring, since we send
  2053. // all mcasts as TR broadcasts. When we comply with RFC 1469 we'll need to
  2054. // fix this.
  2055. if ((Interface->ai_media == NdisMedium802_3) ||
  2056. (Interface->ai_media == NdisMediumFddi) ||
  2057. ((Interface->ai_media == NdisMedium802_5) && TRFunctionalMcast)) {
  2058. Addr &= ARP_MCAST_MASK;
  2059. CTEGetLock(&Interface->ai_lock, &Handle);
  2060. AddrPtr = ARPFindMCast(Interface, Addr, &PrevPtr);
  2061. if (AddrPtr != NULL) {
  2062. // We found one, just bump refcnt.
  2063. (AddrPtr->ama_refcnt)++;
  2064. } else {
  2065. // Didn't find one. Allocate space for one, link him in, and
  2066. // try to set the list.
  2067. AddrPtr = CTEAllocMemN(sizeof(ARPMCastAddr), 'SiCT');
  2068. if (AddrPtr != NULL) {
  2069. // Got one. Link him in.
  2070. AddrPtr->ama_addr = Addr;
  2071. AddrPtr->ama_refcnt = 1;
  2072. AddrPtr->ama_next = Interface->ai_mcast;
  2073. Interface->ai_mcast = AddrPtr;
  2074. (Interface->ai_mcastcnt)++;
  2075. CTEFreeLock(&Interface->ai_lock, Handle);
  2076. // Now try to set the list.
  2077. if (ARPSetMCastList(Interface) != NDIS_STATUS_SUCCESS) {
  2078. // Couldn't set the list. Call the delete routine to delete
  2079. // the address we just tried to set.
  2080. Status = ARPDelMCast(Interface, Addr);
  2081. ASSERT(Status);
  2082. Status = FALSE;
  2083. }
  2084. CTEGetLock(&Interface->ai_lock, &Handle);
  2085. } else
  2086. Status = FALSE; // Couldn't get memory.
  2087. }
  2088. // We've done out best. Free the lock and return.
  2089. CTEFreeLock(&Interface->ai_lock, Handle);
  2090. }
  2091. return Status;
  2092. }
  2093. //* ARPAddAddr - Add an address to the ARP table.
  2094. //
  2095. // This routine is called by IP to add an address as a local address, or
  2096. // or specify the broadcast address for this interface.
  2097. //
  2098. // Entry: Context - Context we gave IP earlier (really an ARPInterface ptr)
  2099. // Type - Type of address (local, p-arp, multicast, or
  2100. // broadcast).
  2101. // Address - Broadcast IP address to be added.
  2102. // Mask - Mask for address.
  2103. //
  2104. // Returns: 0 if we failed, non-zero otherwise
  2105. //
  2106. uint
  2107. __stdcall
  2108. ARPAddAddr(void *Context, uint Type, IPAddr Address, IPMask Mask, void *Context2)
  2109. {
  2110. ARPInterface *Interface = (ARPInterface *) Context;
  2111. CTELockHandle Handle;
  2112. if (Type != LLIP_ADDR_LOCAL && Type != LLIP_ADDR_PARP) {
  2113. // Not a local address, must be broadcast or multicast.
  2114. if (Type == LLIP_ADDR_BCAST) {
  2115. Interface->ai_bcast = Address;
  2116. return TRUE;
  2117. } else if (Type == LLIP_ADDR_MCAST) {
  2118. return ARPAddMCast(Interface, Address);
  2119. } else
  2120. return FALSE;
  2121. } else { // This is a local address.
  2122. CTEGetLock(&Interface->ai_lock, &Handle);
  2123. if (Type != LLIP_ADDR_PARP) {
  2124. uint RetStatus = FALSE;
  2125. uint ArpForSelf = FALSE;
  2126. if (IP_ADDR_EQUAL(Interface->ai_ipaddr.aia_addr, 0)) {
  2127. Interface->ai_ipaddr.aia_addr = Address;
  2128. Interface->ai_ipaddr.aia_mask = Mask;
  2129. Interface->ai_ipaddr.aia_age = ArpRetryCount;
  2130. if (Interface->ai_operstatus == INTERFACE_UP) {
  2131. // When ArpRetryCount is 0, we'll return immediately
  2132. // below, so don't save completion context
  2133. Interface->ai_ipaddr.aia_context = (ArpRetryCount > 0)?
  2134. Context2 : NULL;
  2135. ArpForSelf = TRUE;
  2136. } else {
  2137. Interface->ai_ipaddr.aia_context = NULL;
  2138. }
  2139. RetStatus = TRUE;
  2140. } else {
  2141. ARPIPAddr *NewAddr;
  2142. NewAddr = CTEAllocMemNBoot(sizeof(ARPIPAddr), 'TiCT');
  2143. if (NewAddr != (ARPIPAddr *) NULL) {
  2144. NewAddr->aia_addr = Address;
  2145. NewAddr->aia_mask = Mask;
  2146. NewAddr->aia_age = ArpRetryCount;
  2147. NewAddr->aia_next = Interface->ai_ipaddr.aia_next;
  2148. if (Interface->ai_operstatus == INTERFACE_UP) {
  2149. // When ArpRetryCount is 0, we'll return immediately
  2150. // below, so don't save completion context
  2151. NewAddr->aia_context = (ArpRetryCount > 0)?
  2152. Context2 : NULL;
  2153. ArpForSelf = TRUE;
  2154. } else {
  2155. NewAddr->aia_context = NULL;
  2156. }
  2157. Interface->ai_ipaddr.aia_next = NewAddr;
  2158. RetStatus = TRUE;
  2159. }
  2160. }
  2161. if (RetStatus) {
  2162. Interface->ai_ipaddrcnt++;
  2163. if (Interface->ai_telladdrchng) {
  2164. CTEFreeLock(&Interface->ai_lock, Handle);
  2165. AddrNotifyLink(Interface);
  2166. } else {
  2167. CTEFreeLock(&Interface->ai_lock, Handle);
  2168. }
  2169. } else {
  2170. CTEFreeLock(&Interface->ai_lock, Handle);
  2171. }
  2172. // add wakeup pattern for this address, if the address is in
  2173. // conflict ip will turn around and delete the address thus
  2174. // deleting the wakeup pattern.
  2175. ARPWakeupPattern(Interface, Address, TRUE);
  2176. // ARP for the address we've added, to see it it already exists.
  2177. if (RetStatus == TRUE && ArpForSelf == TRUE) {
  2178. if (ArpRetryCount) {
  2179. SendARPRequest(Interface, Address, ARP_RESOLVING_GLOBAL,
  2180. NULL, TRUE);
  2181. return IP_PENDING;
  2182. } else {
  2183. return TRUE;
  2184. }
  2185. }
  2186. return RetStatus;
  2187. } else if (Type == LLIP_ADDR_PARP) {
  2188. ARPPArpAddr *NewPArp, *TmpPArp;
  2189. // He's adding a proxy arp address.
  2190. // Don't allow to add duplicate proxy arp entries
  2191. TmpPArp = Interface->ai_parpaddr;
  2192. while (TmpPArp) {
  2193. if (IP_ADDR_EQUAL(TmpPArp->apa_addr, Address) && IP_ADDR_EQUAL(TmpPArp->apa_mask, Mask)) {
  2194. CTEFreeLock(&Interface->ai_lock, Handle);
  2195. return FALSE;
  2196. }
  2197. TmpPArp = TmpPArp->apa_next;
  2198. }
  2199. NewPArp = CTEAllocMemN(sizeof(ARPPArpAddr), 'UiCT');
  2200. if (NewPArp != NULL) {
  2201. NewPArp->apa_addr = Address;
  2202. NewPArp->apa_mask = Mask;
  2203. NewPArp->apa_next = Interface->ai_parpaddr;
  2204. Interface->ai_parpaddr = NewPArp;
  2205. Interface->ai_parpcount++;
  2206. CTEFreeLock(&Interface->ai_lock, Handle);
  2207. return TRUE;
  2208. }
  2209. CTEFreeLock(&Interface->ai_lock, Handle);
  2210. }
  2211. return FALSE;
  2212. }
  2213. }
  2214. //* ARPDeleteAddr - Delete a local or proxy address.
  2215. //
  2216. // Called to delete a local or proxy address.
  2217. //
  2218. // Entry: Context - An ARPInterface pointer.
  2219. // Type - Type of address (local or p-arp).
  2220. // Address - IP address to be deleted.
  2221. // Mask - Mask for address. Used only for deleting proxy-ARP
  2222. // entries.
  2223. //
  2224. // Returns: 0 if we failed, non-zero otherwise
  2225. //
  2226. uint
  2227. __stdcall
  2228. ARPDeleteAddr(void *Context, uint Type, IPAddr Address, IPMask Mask)
  2229. {
  2230. ARPInterface *Interface = (ARPInterface *) Context;
  2231. CTELockHandle Handle;
  2232. ARPIPAddr *DelAddr, *PrevAddr;
  2233. ARPPArpAddr *DelPAddr, *PrevPAddr;
  2234. SetAddrControl *SAC;
  2235. AddAddrNotifyEvent *DelayedEvent;
  2236. if (Type == LLIP_ADDR_LOCAL) {
  2237. CTEGetLock(&Interface->ai_lock, &Handle);
  2238. if (IP_ADDR_EQUAL(Interface->ai_ipaddr.aia_addr, Address)) {
  2239. IPAddr IpAddress;
  2240. ARPIPAddr *Addr;
  2241. Addr = &Interface->ai_ipaddr;
  2242. IpAddress = Addr->aia_addr;
  2243. Interface->ai_ipaddr.aia_addr = NULL_IP_ADDR;
  2244. Interface->ai_ipaddrcnt--;
  2245. if (Interface->ai_telladdrchng) {
  2246. CTEFreeLock(&Interface->ai_lock, Handle);
  2247. AddrNotifyLink(Interface);
  2248. CTEGetLock(&Interface->ai_lock, &Handle);
  2249. }
  2250. // if the address is deleted before the add completes, complete the add here
  2251. // Doing this will complete the irp and also decrements the refcount on the interface
  2252. if (Addr->aia_context != NULL) {
  2253. SAC = (SetAddrControl *) Addr->aia_context;
  2254. Addr->aia_context = NULL;
  2255. CTEFreeLock(&Interface->ai_lock, Handle);
  2256. // We cannot call completion routine at timer DPC
  2257. // because completion routine will need to notify
  2258. // TDI clients and that could take long time.
  2259. DelayedEvent = CTEAllocMemNBoot(sizeof(AddAddrNotifyEvent), 'ViCT');
  2260. if (DelayedEvent) {
  2261. DelayedEvent->SAC = SAC;
  2262. DelayedEvent->Address = IpAddress;
  2263. DelayedEvent->Status = IP_SUCCESS;
  2264. CTEInitEvent(&DelayedEvent->Event, CompleteIPSetNTEAddrRequestDelayed);
  2265. CTEScheduleDelayedEvent(&DelayedEvent->Event, DelayedEvent);
  2266. } else {
  2267. ASSERT(FALSE);
  2268. return FALSE;
  2269. }
  2270. } else {
  2271. CTEFreeLock(&Interface->ai_lock, Handle);
  2272. }
  2273. ARPWakeupPattern(Interface, Address, FALSE);
  2274. return TRUE;
  2275. } else {
  2276. PrevAddr = STRUCT_OF(ARPIPAddr, &Interface->ai_ipaddr, aia_next);
  2277. DelAddr = PrevAddr->aia_next;
  2278. while (DelAddr != NULL)
  2279. if (IP_ADDR_EQUAL(DelAddr->aia_addr, Address))
  2280. break;
  2281. else {
  2282. PrevAddr = DelAddr;
  2283. DelAddr = DelAddr->aia_next;
  2284. }
  2285. if (DelAddr != NULL) {
  2286. PrevAddr->aia_next = DelAddr->aia_next;
  2287. if (DelAddr->aia_next &&
  2288. DelAddr->aia_next->aia_age == ARPADDR_MARKER) {
  2289. DelAddr->aia_next->aia_context = (PVOID) PrevAddr;
  2290. }
  2291. Interface->ai_ipaddrcnt--;
  2292. if (Interface->ai_telladdrchng) {
  2293. CTEFreeLock(&Interface->ai_lock, Handle);
  2294. AddrNotifyLink(Interface);
  2295. } else {
  2296. CTEFreeLock(&Interface->ai_lock, Handle);
  2297. }
  2298. if (DelAddr->aia_context != NULL) {
  2299. SAC = (SetAddrControl *) DelAddr->aia_context;
  2300. DelAddr->aia_context = NULL;
  2301. DelayedEvent = CTEAllocMemNBoot(sizeof(AddAddrNotifyEvent), 'ViCT');
  2302. if (DelayedEvent) {
  2303. DelayedEvent->SAC = SAC;
  2304. DelayedEvent->Address = DelAddr->aia_addr;
  2305. DelayedEvent->Status = IP_SUCCESS;
  2306. CTEInitEvent(&DelayedEvent->Event, CompleteIPSetNTEAddrRequestDelayed);
  2307. CTEScheduleDelayedEvent(&DelayedEvent->Event, DelayedEvent);
  2308. } else {
  2309. ASSERT(FALSE);
  2310. return FALSE;
  2311. }
  2312. }
  2313. CTEFreeMem(DelAddr);
  2314. ARPWakeupPattern(Interface, Address, FALSE);
  2315. } else {
  2316. CTEFreeLock(&Interface->ai_lock, Handle);
  2317. }
  2318. return(DelAddr != NULL);
  2319. }
  2320. } else if (Type == LLIP_ADDR_PARP) {
  2321. CTEGetLock(&Interface->ai_lock, &Handle);
  2322. PrevPAddr = STRUCT_OF(ARPPArpAddr, &Interface->ai_parpaddr, apa_next);
  2323. DelPAddr = PrevPAddr->apa_next;
  2324. while (DelPAddr != NULL)
  2325. if (IP_ADDR_EQUAL(DelPAddr->apa_addr, Address) &&
  2326. DelPAddr->apa_mask == Mask)
  2327. break;
  2328. else {
  2329. PrevPAddr = DelPAddr;
  2330. DelPAddr = DelPAddr->apa_next;
  2331. }
  2332. if (DelPAddr != NULL) {
  2333. PrevPAddr->apa_next = DelPAddr->apa_next;
  2334. Interface->ai_parpcount--;
  2335. CTEFreeMem(DelPAddr);
  2336. }
  2337. CTEFreeLock(&Interface->ai_lock, Handle);
  2338. return(DelPAddr != NULL);
  2339. } else if (Type == LLIP_ADDR_MCAST)
  2340. return ARPDelMCast(Interface, Address);
  2341. else
  2342. return FALSE;
  2343. }
  2344. //*AddrNotifyLink - Notify link layer of Network Address changes
  2345. //
  2346. // Called when address are added/deleted on an interface
  2347. //
  2348. // Entry: Interface - ARPinterface pointer
  2349. //
  2350. // returns: NDIS_STATUS.Also sets ai_telladdrchng if status is failure
  2351. // when this happens caller can check and see if next addr notification
  2352. // need to be done or not.
  2353. //
  2354. NDIS_STATUS
  2355. AddrNotifyLink(ARPInterface * Interface)
  2356. {
  2357. PNETWORK_ADDRESS_LIST AddressList;
  2358. NETWORK_ADDRESS UNALIGNED *Address;
  2359. int i = 0, size, count;
  2360. ARPIPAddr *addrlist;
  2361. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  2362. CTELockHandle Handle;
  2363. CTEGetLock(&Interface->ai_lock, &Handle);
  2364. size = Interface->ai_ipaddrcnt * (sizeof(NETWORK_ADDRESS_IP) +
  2365. FIELD_OFFSET(NETWORK_ADDRESS, Address)) +
  2366. FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
  2367. AddressList = CTEAllocMemN(size, 'WiCT');
  2368. if (AddressList) {
  2369. addrlist = &Interface->ai_ipaddr;
  2370. count = Interface->ai_ipaddrcnt;
  2371. AddressList->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  2372. while (addrlist && count) {
  2373. NETWORK_ADDRESS_IP UNALIGNED *tmpIPAddr;
  2374. uchar *Address0;
  2375. //
  2376. // Skip if this is a Marker.
  2377. //
  2378. if (addrlist->aia_age != ARPADDR_MARKER) {
  2379. Address0 = (uchar *) & AddressList->Address[0];
  2380. Address = (PNETWORK_ADDRESS) (Address0 + i * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IP)));
  2381. tmpIPAddr = (PNETWORK_ADDRESS_IP) & Address->Address[0];
  2382. Address->AddressLength = sizeof(NETWORK_ADDRESS_IP);
  2383. Address->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  2384. RtlCopyMemory(&tmpIPAddr->in_addr, &addrlist->aia_addr, sizeof(IPAddr));
  2385. count--;
  2386. i++;
  2387. }
  2388. addrlist = addrlist->aia_next;
  2389. }
  2390. CTEFreeLock(&Interface->ai_lock, Handle);
  2391. AddressList->AddressCount = i;
  2392. status = DoNDISRequest(Interface,
  2393. NdisRequestSetInformation,
  2394. OID_GEN_NETWORK_LAYER_ADDRESSES,
  2395. AddressList,
  2396. size,
  2397. NULL, TRUE);
  2398. if (status != NDIS_STATUS_SUCCESS) {
  2399. CTEGetLock(&Interface->ai_lock, &Handle);
  2400. Interface->ai_telladdrchng = 0;
  2401. CTEFreeLock(&Interface->ai_lock, Handle);
  2402. }
  2403. CTEFreeMem(AddressList);
  2404. } else {
  2405. CTEFreeLock(&Interface->ai_lock, Handle);
  2406. status = NDIS_STATUS_RESOURCES;
  2407. }
  2408. return status;
  2409. }
  2410. #if !MILLEN
  2411. //* ARPCancelPackets
  2412. //
  2413. // Entry: Context - Pointer to the ARPInterface
  2414. // ID - Pattern that need to be passed down to ndis
  2415. //
  2416. // Returns: Nothing
  2417. //
  2418. VOID
  2419. __stdcall
  2420. ARPCancelPackets(void *Context, void *ID)
  2421. {
  2422. ARPInterface *Interface = (ARPInterface *) Context;
  2423. NdisCancelSendPackets(Interface->ai_handle,ID);
  2424. }
  2425. #endif
  2426. //* DoWakeupPattern - Adds and removes wakeup pattern.
  2427. //
  2428. // Entry: Context - Pointer to the ARPInterface
  2429. // PtrnDesc - Pattern buffer(s) of high level protocol
  2430. // protoid - the proto type used in ethernet or snap type fields.
  2431. // AddPattern - TRUE if pattern is to be added, FALSE if it is to be removed.
  2432. //
  2433. // Returns: Nothing.
  2434. //
  2435. NDIS_STATUS
  2436. __stdcall
  2437. DoWakeupPattern(void *Context, PNET_PM_WAKEUP_PATTERN_DESC PtrnDesc, ushort protoid, BOOLEAN AddPattern)
  2438. {
  2439. ARPInterface *Interface = (ARPInterface *) Context;
  2440. uint PtrnLen;
  2441. uint PtrnBufferLen;
  2442. uint MaskLen;
  2443. PNET_PM_WAKEUP_PATTERN_DESC CurPtrnDesc;
  2444. uchar *NextMask, *NextPtrn;
  2445. const uchar *MMask;
  2446. uint MMaskLength;
  2447. uchar NextMaskBit;
  2448. uchar *Buffer;
  2449. PNDIS_PM_PACKET_PATTERN PtrnBuffer;
  2450. NDIS_STATUS Status;
  2451. //
  2452. // First find the total length of the pattern.
  2453. // Pattern starts right at MacHeader.
  2454. //
  2455. // First add the media portion of the header.
  2456. //
  2457. PtrnLen = Interface->ai_hdrsize + Interface->ai_snapsize;
  2458. // now add the high level proto pattern size.
  2459. CurPtrnDesc = PtrnDesc;
  2460. while (CurPtrnDesc != (PNET_PM_WAKEUP_PATTERN_DESC) NULL) {
  2461. PtrnLen += CurPtrnDesc->PtrnLen;
  2462. CurPtrnDesc = CurPtrnDesc->Next;
  2463. }
  2464. // length of the mask: every byte of pattern requires
  2465. // one bit of the mask.
  2466. MaskLen = GetWakeupPatternMaskLength(PtrnLen);
  2467. // total length of the pattern buffer to be given to ndis.
  2468. PtrnBufferLen = sizeof(NDIS_PM_PACKET_PATTERN) + PtrnLen + MaskLen;
  2469. if ((Buffer = CTEAllocMemN(PtrnBufferLen, 'XiCT')) == (uchar *) NULL) {
  2470. return NDIS_STATUS_RESOURCES;
  2471. }
  2472. RtlZeroMemory(Buffer, PtrnBufferLen);
  2473. PtrnBuffer = (PNDIS_PM_PACKET_PATTERN) Buffer;
  2474. PtrnBuffer->PatternSize = PtrnLen;
  2475. NextMask = Buffer + sizeof(NDIS_PM_PACKET_PATTERN);
  2476. NextPtrn = NextMask + MaskLen;
  2477. PtrnBuffer->MaskSize = MaskLen;
  2478. PtrnBuffer->PatternOffset =
  2479. (ULONG) ((ULONG_PTR) NextPtrn - (ULONG_PTR) PtrnBuffer);
  2480. // Figure out what type of media this is, and do the appropriate thing.
  2481. switch (Interface->ai_media) {
  2482. case NdisMedium802_3:
  2483. if (Interface->ai_snapsize == 0) {
  2484. ENetHeader UNALIGNED *Hdr = (ENetHeader UNALIGNED *) NextPtrn;
  2485. Hdr->eh_type = net_short(protoid);
  2486. MMask = ENetPtrnMsk;
  2487. } else {
  2488. MMask = ENetSNAPPtrnMsk;
  2489. }
  2490. break;
  2491. case NdisMedium802_5:
  2492. if (Interface->ai_snapsize == 0) {
  2493. MMask = TRPtrnMsk;
  2494. } else {
  2495. MMask = TRSNAPPtrnMsk;
  2496. }
  2497. break;
  2498. case NdisMediumFddi:
  2499. if (Interface->ai_snapsize == 0) {
  2500. MMask = FDDIPtrnMsk;
  2501. } else {
  2502. MMask = FDDISNAPPtrnMsk;
  2503. }
  2504. break;
  2505. case NdisMediumArcnet878_2:
  2506. MMask = ARCPtrnMsk;
  2507. break;
  2508. default:
  2509. ASSERT(0);
  2510. Interface->ai_outerrors++;
  2511. CTEFreeMem(Buffer);
  2512. return NDIS_STATUS_UNSUPPORTED_MEDIA;
  2513. }
  2514. NextPtrn += Interface->ai_hdrsize;
  2515. // Copy in SNAP header, if any.
  2516. if (Interface->ai_snapsize) {
  2517. SNAPHeader UNALIGNED *SNAPPtr = (SNAPHeader UNALIGNED *) NextPtrn;
  2518. RtlCopyMemory(SNAPPtr, ARPSNAP, Interface->ai_snapsize);
  2519. SNAPPtr->sh_etype = net_short(protoid);
  2520. NextPtrn += Interface->ai_snapsize;
  2521. }
  2522. //
  2523. MMaskLength = (Interface->ai_snapsize + Interface->ai_hdrsize - 1) / 8 + 1;
  2524. // copy the mask for media part
  2525. RtlCopyMemory(NextMask, MMask, MMaskLength);
  2526. NextMaskBit = (Interface->ai_hdrsize + Interface->ai_snapsize) % 8;
  2527. NextMask = NextMask + (Interface->ai_hdrsize + Interface->ai_snapsize) / 8;
  2528. // copy the pattern and mask of high level proto.
  2529. CurPtrnDesc = PtrnDesc;
  2530. while (CurPtrnDesc) {
  2531. uint CopyBits = CurPtrnDesc->PtrnLen;
  2532. uchar *SrcMask = CurPtrnDesc->Mask;
  2533. uchar SrcMaskBit = 0;
  2534. RtlCopyMemory(NextPtrn, CurPtrnDesc->Ptrn, CurPtrnDesc->PtrnLen);
  2535. NextPtrn += CurPtrnDesc->PtrnLen;
  2536. while (CopyBits--) {
  2537. *NextMask |= ((*SrcMask & (0x1 << SrcMaskBit)) ? (0x1 << NextMaskBit) : 0);
  2538. if ((NextMaskBit = ((NextMaskBit + 1) % 8)) == 0) {
  2539. NextMask++;
  2540. }
  2541. if ((SrcMaskBit = ((SrcMaskBit + 1) % 8)) == 0) {
  2542. SrcMask++;
  2543. }
  2544. }
  2545. CurPtrnDesc = CurPtrnDesc->Next;
  2546. }
  2547. // now tell ndis to set or remove the pattern.
  2548. Status = DoNDISRequest(
  2549. Interface,
  2550. NdisRequestSetInformation,
  2551. AddPattern ? OID_PNP_ADD_WAKE_UP_PATTERN : OID_PNP_REMOVE_WAKE_UP_PATTERN,
  2552. PtrnBuffer,
  2553. PtrnBufferLen,
  2554. NULL, TRUE);
  2555. CTEFreeMem(Buffer);
  2556. return Status;
  2557. }
  2558. //* ARPWakeupPattern - add or remove ARP wakeup pattern.
  2559. //
  2560. // Entry: Interface - Pointer to the ARPInterface
  2561. // Addr - IPAddr for which we need to set ARP pattern filter.
  2562. //
  2563. // Returns: Nothing.
  2564. //
  2565. NDIS_STATUS
  2566. ARPWakeupPattern(ARPInterface * Interface, IPAddr Addr, BOOLEAN AddPattern)
  2567. {
  2568. PNET_PM_WAKEUP_PATTERN_DESC PtrnDesc;
  2569. uint PtrnLen;
  2570. uint MaskLen;
  2571. const uchar *PtrnMask;
  2572. NDIS_STATUS Status;
  2573. //
  2574. // create high level proto (ARP here) pattern descriptor.
  2575. //
  2576. // len of pattern.
  2577. PtrnLen = sizeof(ARPHeader);
  2578. // adjust for Arcnet.
  2579. if (Interface->ai_media == NdisMediumArcnet878_2) {
  2580. PtrnLen -= ARCNET_ARPHEADER_ADJUSTMENT;
  2581. PtrnMask = ARCARPPtrnMsk;
  2582. } else {
  2583. PtrnMask = ARPPtrnMsk;
  2584. }
  2585. // masklen = 1 bit per every byte of pattern.
  2586. MaskLen = GetWakeupPatternMaskLength(PtrnLen);
  2587. if ((PtrnDesc = CTEAllocMemN(sizeof(NET_PM_WAKEUP_PATTERN_DESC) + PtrnLen + MaskLen, 'YiCT')) != (PNET_PM_WAKEUP_PATTERN_DESC) NULL) {
  2588. ARPHeader UNALIGNED *Hdr;
  2589. uchar *IPAddrPtr;
  2590. RtlZeroMemory(PtrnDesc, sizeof(NET_PM_WAKEUP_PATTERN_DESC) + PtrnLen + MaskLen);
  2591. // set the ptrn and mask pointers in the buffer.
  2592. PtrnDesc->PtrnLen = (USHORT) PtrnLen;
  2593. PtrnDesc->Ptrn = (uchar *) PtrnDesc + sizeof(NET_PM_WAKEUP_PATTERN_DESC);
  2594. PtrnDesc->Mask = (uchar *) PtrnDesc + sizeof(NET_PM_WAKEUP_PATTERN_DESC) + PtrnLen;
  2595. // we need to wakeup on ARP request for our IPAddr.
  2596. // so set the opcode and dest ip addr fields of ARP.
  2597. Hdr = (ARPHeader UNALIGNED *) PtrnDesc->Ptrn;
  2598. Hdr->ah_opcode = net_short(ARP_REQUEST);
  2599. IPAddrPtr = Hdr->ah_shaddr + Interface->ai_addrlen + sizeof(IPAddr) + Interface->ai_addrlen;
  2600. *(IPAddr UNALIGNED *) IPAddrPtr = Addr;
  2601. RtlCopyMemory(PtrnDesc->Mask, PtrnMask, MaskLen);
  2602. // give it to ndis.
  2603. Status = DoWakeupPattern(
  2604. Interface,
  2605. PtrnDesc,
  2606. ARP_ETYPE_ARP,
  2607. AddPattern);
  2608. // free the ptrn desc.
  2609. CTEFreeMem(PtrnDesc);
  2610. //now add wakeup pattren for directed mac address
  2611. {
  2612. uint PtrnBufferLen;
  2613. PNDIS_PM_PACKET_PATTERN PtrnBuffer;
  2614. uchar *Buffer;
  2615. PtrnLen = ARP_802_ADDR_LENGTH; //eth dest address
  2616. MaskLen = 1; //1 byte, needs 6 bits, 1 bit/byte
  2617. PtrnBufferLen = sizeof(NDIS_PM_PACKET_PATTERN) + PtrnLen + MaskLen;
  2618. Buffer = CTEAllocMem(PtrnBufferLen);
  2619. if (Buffer) {
  2620. RtlZeroMemory(Buffer, PtrnBufferLen);
  2621. PtrnBuffer = (PNDIS_PM_PACKET_PATTERN) Buffer;
  2622. PtrnBuffer->PatternSize = PtrnLen;
  2623. PtrnBuffer->MaskSize = MaskLen;
  2624. PtrnBuffer->PatternOffset = sizeof(NDIS_PM_PACKET_PATTERN) + 1;
  2625. *(Buffer + sizeof(NDIS_PM_PACKET_PATTERN)) = 0x3F;
  2626. RtlCopyMemory(Buffer + sizeof(NDIS_PM_PACKET_PATTERN) + 1, Interface->ai_addr, ARP_802_ADDR_LENGTH);
  2627. Status = DoNDISRequest(
  2628. Interface,
  2629. NdisRequestSetInformation,
  2630. AddPattern ? OID_PNP_ADD_WAKE_UP_PATTERN : OID_PNP_REMOVE_WAKE_UP_PATTERN,
  2631. PtrnBuffer,
  2632. PtrnBufferLen,
  2633. NULL, TRUE);
  2634. CTEFreeMem(Buffer);
  2635. }
  2636. }
  2637. return Status;
  2638. }
  2639. return IP_NO_RESOURCES;
  2640. }
  2641. //** CompleteIPSetNTEAddrRequestDelayed -
  2642. //
  2643. // calls CompleteIPSetNTEAddrRequest on a delayed worker thread
  2644. //
  2645. // Entry:
  2646. // Context - pointer to the control block
  2647. // Exit:
  2648. // None.
  2649. //
  2650. void
  2651. CompleteIPSetNTEAddrRequestDelayed(CTEEvent * WorkerThreadEvent, PVOID Context)
  2652. {
  2653. AddAddrNotifyEvent *DelayedEvent;
  2654. SetAddrControl *SAC;
  2655. IPAddr Address;
  2656. IP_STATUS Status;
  2657. UNREFERENCED_PARAMETER(WorkerThreadEvent);
  2658. DelayedEvent = (AddAddrNotifyEvent *) Context;
  2659. SAC = DelayedEvent->SAC; // the client context block;
  2660. Address = DelayedEvent->Address; // The address for which SetNTEAddr was called for.
  2661. Status = DelayedEvent->Status;
  2662. // Free the worker thread event.
  2663. CTEFreeMem(Context);
  2664. IPAddAddrComplete(Address, SAC, Status);
  2665. }
  2666. #if FFP_SUPPORT
  2667. //* ARPReclaimRequestMem - Post processing upon request completion
  2668. //
  2669. // Called upon completion of NDIS requests that originate at ARP
  2670. //
  2671. // Input: pRequestInfo - Points to request IP sends ARP
  2672. //
  2673. // Returns: None
  2674. //
  2675. void
  2676. ARPReclaimRequestMem(PVOID pRequestInfo)
  2677. {
  2678. // Decrement ref count, and reclaim memory if it drops to zero
  2679. if (InterlockedDecrement( (PLONG)
  2680. &((ReqInfoBlock *) pRequestInfo)->RequestRefs) == 0) {
  2681. // TCPTRACE(("ARPReclaimRequestMem: Freeing mem at pReqInfo = %08X\n",
  2682. // pRequestInfo));
  2683. CTEFreeMem(pRequestInfo);
  2684. }
  2685. }
  2686. #endif // if FFP_SUPPORT
  2687. //* ARPTimeout - ARP timeout routine.
  2688. //
  2689. // This is the timeout routine that is called periodically. We scan the ARP table, looking
  2690. // for invalid entries that can be removed.
  2691. //
  2692. // Entry: Timer - Pointer to the timer that just fired.
  2693. // Context - Pointer to the interface to be timed out.
  2694. //
  2695. // Returns: Nothing.
  2696. //
  2697. void
  2698. ARPTimeout(CTEEvent * Timer, void *Context)
  2699. {
  2700. ARPInterface *Interface = (ARPInterface *) Context; // Our interface.
  2701. ARPTable *Table;
  2702. ARPTableEntry *Current, *Previous;
  2703. int i; // Index variable.
  2704. ulong Now = CTESystemUpTime(), ValidTime;
  2705. CTELockHandle tblhandle;
  2706. uchar Deleted;
  2707. PNDIS_PACKET PList = (PNDIS_PACKET) NULL;
  2708. ARPIPAddr *Addr;
  2709. ARPIPAddr Marker;
  2710. UNREFERENCED_PARAMETER(Timer);
  2711. // Walk down the list of addresses, decrementing the age.
  2712. CTEGetLock(&Interface->ai_lock, &tblhandle);
  2713. if (Interface->ai_conflict && !(--Interface->ai_delay)) {
  2714. ARPNotifyStruct *NotifyStruct = Interface->ai_conflict;
  2715. CTEScheduleDelayedEvent(&NotifyStruct->ans_event, NotifyStruct);
  2716. Interface->ai_conflict = NULL;
  2717. }
  2718. Addr = &Interface->ai_ipaddr;
  2719. //
  2720. // Marker is used to track the next addr to be processed
  2721. // in the ipaddr list. Initialize it so that its aia_age is
  2722. // OLD_LOCAL, and aia_addr is NULL_IP_ADDR. The places where
  2723. // address list is scanned will skip ARPIPAddr with NULL_IP_ADDR
  2724. // and in ARPDeleteAddr, if an addr element before the marker is
  2725. // removed, Marker's aia_context will be changed to its prev element.
  2726. //
  2727. Marker.aia_addr = NULL_IP_ADDR;
  2728. do {
  2729. if (Addr->aia_age != ARPADDR_OLD_LOCAL) {
  2730. IPAddr IpAddress;
  2731. (Addr->aia_age)--;
  2732. //
  2733. // Insert Marker after this Addr
  2734. // Marker's aia_context is used as blink
  2735. //
  2736. Marker.aia_age = ARPADDR_MARKER;
  2737. Marker.aia_next = Addr->aia_next;
  2738. Marker.aia_context = Addr;
  2739. Addr->aia_next = &Marker;
  2740. if (Addr->aia_age == ARPADDR_OLD_LOCAL) {
  2741. if (Addr->aia_context != NULL) {
  2742. SetAddrControl *SAC;
  2743. AddAddrNotifyEvent *DelayedEvent;
  2744. SAC = (SetAddrControl *) Addr->aia_context;
  2745. Addr->aia_context = NULL;
  2746. IpAddress = Addr->aia_addr;
  2747. CTEFreeLock(&Interface->ai_lock, tblhandle);
  2748. // We cannot call completion routine at timer DPC
  2749. // because completion routine will need to notify
  2750. // TDI clients and that could take long time.
  2751. DelayedEvent = CTEAllocMemNBoot(sizeof(AddAddrNotifyEvent), 'ZiCT');
  2752. if (DelayedEvent) {
  2753. DelayedEvent->SAC = SAC;
  2754. DelayedEvent->Address = IpAddress;
  2755. DelayedEvent->Status = IP_SUCCESS;
  2756. CTEInitEvent(&DelayedEvent->Event, CompleteIPSetNTEAddrRequestDelayed);
  2757. CTEScheduleDelayedEvent(&DelayedEvent->Event, DelayedEvent);
  2758. }
  2759. CTEGetLock(&Interface->ai_lock, &tblhandle);
  2760. }
  2761. } else {
  2762. IpAddress = Addr->aia_addr;
  2763. CTEFreeLock(&Interface->ai_lock, tblhandle);
  2764. SendARPRequest(Interface, IpAddress, ARP_RESOLVING_GLOBAL,
  2765. NULL, TRUE);
  2766. CTEGetLock(&Interface->ai_lock, &tblhandle);
  2767. }
  2768. //
  2769. // We are done scanning the list
  2770. // Remove the Marker
  2771. //
  2772. Addr = Marker.aia_next;
  2773. ((ARPIPAddr *)(Marker.aia_context))->aia_next = Marker.aia_next;
  2774. } else {
  2775. Addr = Addr->aia_next;
  2776. }
  2777. } while (Addr != NULL);
  2778. CTEFreeLock(&Interface->ai_lock, tblhandle);
  2779. // Loop through the ARP table for this interface, and delete stale entries.
  2780. CTEGetLock(&Interface->ai_ARPTblLock, &tblhandle);
  2781. Table = Interface->ai_ARPTbl;
  2782. for (i = 0; i < ARP_TABLE_SIZE; i++) {
  2783. Previous = (ARPTableEntry *) ((uchar *) & ((*Table)[i]) - offsetof(struct ARPTableEntry, ate_next));
  2784. Current = (*Table)[i];
  2785. while (Current != (ARPTableEntry *) NULL) {
  2786. CTEGetLockAtDPC(&Current->ate_lock);
  2787. Deleted = 0;
  2788. //Delete the entry if it was used for api purpose
  2789. if (Current->ate_resolveonly) {
  2790. ARPControlBlock *ArpContB, *tmpArpContB;
  2791. PNDIS_PACKET Packet = Current->ate_packet;
  2792. ArpContB = Current->ate_resolveonly;
  2793. ASSERT(Current->ate_resolveonly != NULL);
  2794. while (ArpContB) {
  2795. ArpRtn rtn;
  2796. //Complete the pending request
  2797. rtn = (ArpRtn) ArpContB->CompletionRtn;
  2798. ArpContB->status = 0;
  2799. tmpArpContB = ArpContB->next;
  2800. (*rtn) (ArpContB, (IP_STATUS) STATUS_UNSUCCESSFUL);
  2801. ArpContB = tmpArpContB;
  2802. }
  2803. Current->ate_resolveonly = NULL;
  2804. if (Packet != (PNDIS_PACKET) NULL) {
  2805. ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_link = PList;
  2806. PList = Packet;
  2807. }
  2808. RemoveARPTableEntry(Previous, Current);
  2809. Interface->ai_count--;
  2810. Deleted = 1;
  2811. goto doneapi;
  2812. }
  2813. if (Current->ate_state == ARP_GOOD) {
  2814. //
  2815. // The ARP entry is valid for ARP_VALID_TIMEOUT by default.
  2816. // If a cache life greater than ARP_VALID_TIMEOUT has been
  2817. // configured, we'll make the entry valid for that time.
  2818. //
  2819. ValidTime = ArpCacheLife * ARP_TIMER_TIME;
  2820. if (ValidTime < (ArpMinValidCacheLife * 1000)) {
  2821. ValidTime = (ArpMinValidCacheLife * 1000);
  2822. }
  2823. } else {
  2824. ValidTime = ARP_RESOLVE_TIMEOUT;
  2825. }
  2826. if (Current->ate_valid != ALWAYS_VALID &&
  2827. (((Now - Current->ate_valid) > ValidTime) ||
  2828. (Current->ate_state == ARP_GOOD &&
  2829. !(--(Current->ate_useticks))))) {
  2830. if (Current->ate_state != ARP_RESOLVING_LOCAL) {
  2831. // Really need to delete this guy.
  2832. PNDIS_PACKET Packet = Current->ate_packet;
  2833. if (((Now - Current->ate_valid) > ValidTime) && Current->ate_refresh) {
  2834. DEBUGMSG(DBG_INFO && DBG_ARP,
  2835. (DTEXT("ARPTimeout: Expiring ATE %x\n"), Current));
  2836. if (Packet != (PNDIS_PACKET) NULL) {
  2837. ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_link
  2838. = PList;
  2839. PList = Packet;
  2840. }
  2841. RemoveARPTableEntry(Previous, Current);
  2842. Interface->ai_count--;
  2843. Deleted = 1;
  2844. } else {
  2845. //Just try to validate this again.
  2846. Current->ate_valid = Now + ARP_REFRESH_TIME;
  2847. Current->ate_refresh=TRUE;
  2848. }
  2849. } else {
  2850. IPAddr Dest = Current->ate_dest;
  2851. // This entry is only resoving locally, presumably this is
  2852. // token ring. We'll need to transmit a 'global' resolution
  2853. // now.
  2854. ASSERT(Interface->ai_media == NdisMedium802_5);
  2855. Now = CTESystemUpTime();
  2856. Current->ate_valid = Now;
  2857. Current->ate_state = ARP_RESOLVING_GLOBAL;
  2858. CTEFreeLockFromDPC(&Current->ate_lock);
  2859. CTEFreeLock(&Interface->ai_ARPTblLock, tblhandle);
  2860. // Send a global request.
  2861. SendARPRequest(Interface, Dest, ARP_RESOLVING_GLOBAL,
  2862. NULL, TRUE);
  2863. CTEGetLock(&Interface->ai_ARPTblLock, &tblhandle);
  2864. // Since we've freed the locks, we need to start over from
  2865. // the start of this chain.
  2866. Previous = STRUCT_OF(ARPTableEntry, &((*Table)[i]),
  2867. ate_next);
  2868. Current = (*Table)[i];
  2869. continue;
  2870. }
  2871. }
  2872. doneapi:
  2873. // If we deleted the entry, leave the previous pointer alone,
  2874. // advance the current pointer, and free the memory. Otherwise
  2875. // move both pointers forward. We can free the entry lock now
  2876. // because the next pointers are protected by the table lock, and
  2877. // we've removed it from the list so nobody else should
  2878. // find it anyway.
  2879. CTEFreeLockFromDPC(&Current->ate_lock);
  2880. if (Deleted) {
  2881. ARPTableEntry *Temp = Current;
  2882. Current = Current->ate_next;
  2883. CTEFreeMem(Temp);
  2884. } else {
  2885. Previous = Current;
  2886. Current = Current->ate_next;
  2887. }
  2888. }
  2889. }
  2890. CTEFreeLock(&Interface->ai_ARPTblLock, tblhandle);
  2891. while (PList != (PNDIS_PACKET) NULL) {
  2892. PNDIS_PACKET Packet = PList;
  2893. PList = ((PacketContext *) Packet->ProtocolReserved)->pc_common.pc_link;
  2894. IPSendComplete(Interface->ai_context, Packet, NDIS_STATUS_SUCCESS);
  2895. }
  2896. //
  2897. // Dont requeue if interface is going down and we need to stop the timer
  2898. //
  2899. if (Interface->ai_stoptimer) {
  2900. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARP interface %lx is down - dont requeue the timer - signal the waiter\n", Interface));
  2901. Interface->ai_timerstarted = FALSE;
  2902. CTESignal(&Interface->ai_timerblock, NDIS_STATUS_SUCCESS);
  2903. } else {
  2904. CTEStartTimer(&Interface->ai_timer, ARP_TIMER_TIME, ARPTimeout, Interface);
  2905. }
  2906. #if FFP_SUPPORT
  2907. // Flush Processing - This can be done after starting the timer
  2908. CTEGetLock(&Interface->ai_lock, &tblhandle);
  2909. // If FFP supported on this interface & it is time to do a flush
  2910. if ((Interface->ai_ffpversion) &&
  2911. (++Interface->ai_ffplastflush >= FFP_ARP_FLUSH_INTERVAL)) {
  2912. ReqInfoBlock *pRequestInfo;
  2913. FFPFlushParams *pFlushInfo;
  2914. TCPTRACE(("ARPTimeout: Sending a FFP flush to ARPInterface %08X\n",
  2915. Interface));
  2916. // Allocate the request block - For General and Request Specific Parts
  2917. pRequestInfo = CTEAllocMemN(sizeof(ReqInfoBlock) + sizeof(FFPFlushParams), '0ICT');
  2918. // TCPTRACE(("ARPTimeout: Allocated mem at pReqInfo = %08X\n",
  2919. // pRequestInfo));
  2920. if (pRequestInfo != NULL) {
  2921. // Prepare the params for the request [Part common to all requests]
  2922. pRequestInfo->RequestType = OID_FFP_FLUSH;
  2923. pRequestInfo->ReqCompleteCallback = ARPReclaimRequestMem;
  2924. // Prepare the params for the request [Part specific to this request]
  2925. pRequestInfo->RequestLength = sizeof(FFPFlushParams);
  2926. // Flush all caches that FFP keeps - just a safe reset of FFP state
  2927. pFlushInfo = (FFPFlushParams *) pRequestInfo->RequestInfo;
  2928. pFlushInfo->NdisProtocolType = NDIS_PROTOCOL_ID_TCP_IP;
  2929. // Assign the ref count to 1 => Used for just a single request
  2930. pRequestInfo->RequestRefs = 1;
  2931. DoNDISRequest(Interface, NdisRequestSetInformation, OID_FFP_FLUSH,
  2932. pFlushInfo, sizeof(FFPFlushParams), NULL, FALSE);
  2933. // Reset the number of timer ticks since the last FFP request
  2934. Interface->ai_ffplastflush = 0;
  2935. } else {
  2936. TCPTRACE(("Error: Unable to allocate memory for NdisRequest\n"));
  2937. }
  2938. }
  2939. #if DBG
  2940. if (fakereset) {
  2941. NDIS_STATUS Status;
  2942. NdisReset(&Status, Interface->ai_handle);
  2943. KdPrint(("fakereset: %x\n", Status));
  2944. }
  2945. #endif
  2946. CTEFreeLock(&Interface->ai_lock, tblhandle);
  2947. #endif // if FFP_SUPPORT
  2948. }
  2949. //* IsLocalAddr - Return info. about local status of address.
  2950. //
  2951. // Called when we need info. about whether or not a particular address is
  2952. // local. We return info about whether or not it is, and if it is how old
  2953. // it is.
  2954. //
  2955. // Entry: Interface - Pointer to interface structure to be searched.
  2956. // Address - Address in question.
  2957. //
  2958. // Returns: ARPADDR_*, for how old it is.
  2959. //
  2960. //
  2961. uint
  2962. IsLocalAddr(ARPInterface * Interface, IPAddr Address)
  2963. {
  2964. CTELockHandle Handle;
  2965. ARPIPAddr *CurrentAddr;
  2966. uint Age;
  2967. // If we are asking about the null ip address, we don't want to consider
  2968. // it as a true local address.
  2969. //
  2970. if (IP_ADDR_EQUAL(Address, NULL_IP_ADDR)) {
  2971. return ARPADDR_NOT_LOCAL;
  2972. }
  2973. CTEGetLock(&Interface->ai_lock, &Handle);
  2974. CurrentAddr = &Interface->ai_ipaddr;
  2975. Age = ARPADDR_NOT_LOCAL;
  2976. do {
  2977. if (CurrentAddr->aia_addr == Address) {
  2978. Age = CurrentAddr->aia_age;
  2979. break;
  2980. }
  2981. CurrentAddr = CurrentAddr->aia_next;
  2982. } while (CurrentAddr != NULL);
  2983. CTEFreeLock(&Interface->ai_lock, Handle);
  2984. return Age;
  2985. }
  2986. //* ARPLocalAddr - Determine whether or not a given address if local.
  2987. //
  2988. // This routine is called when we receive an incoming packet and need to
  2989. // determine whether or not it's local. We look up the provided address on
  2990. // the specified interface.
  2991. //
  2992. // Entry: Interface - Pointer to interface structure to be searched.
  2993. // Address - Address in question.
  2994. //
  2995. // Returns: TRUE if it is a local address, FALSE if it's not.
  2996. //
  2997. uchar
  2998. ARPLocalAddr(ARPInterface * Interface, IPAddr Address)
  2999. {
  3000. CTELockHandle Handle;
  3001. ARPPArpAddr *CurrentPArp;
  3002. IPMask Mask, NetMask;
  3003. IPAddr MatchAddress;
  3004. // First, see if he's a local (not-proxy) address.
  3005. if (IsLocalAddr(Interface, Address) != ARPADDR_NOT_LOCAL)
  3006. return TRUE;
  3007. CTEGetLock(&Interface->ai_lock, &Handle);
  3008. // Didn't find him in out local address list. See if he exists on our
  3009. // proxy ARP list.
  3010. for (CurrentPArp = Interface->ai_parpaddr; CurrentPArp != NULL;
  3011. CurrentPArp = CurrentPArp->apa_next) {
  3012. // See if this guy matches.
  3013. Mask = CurrentPArp->apa_mask;
  3014. MatchAddress = Address & Mask;
  3015. if (IP_ADDR_EQUAL(CurrentPArp->apa_addr, MatchAddress)) {
  3016. // He matches. We need to make a few more checks to make sure
  3017. // we don't reply to a broadcast address.
  3018. if (Mask == HOST_MASK) {
  3019. // We're matching the whole address, so it's OK.
  3020. CTEFreeLock(&Interface->ai_lock, Handle);
  3021. return TRUE;
  3022. }
  3023. // See if the non-mask part it all-zeros. Since the mask presumably
  3024. // covers a subnet, this trick will prevent us from replying to
  3025. // a zero host part.
  3026. if (IP_ADDR_EQUAL(MatchAddress, Address))
  3027. continue;
  3028. // See if the host part is all ones.
  3029. if (IP_ADDR_EQUAL(Address, MatchAddress | (IP_LOCAL_BCST & ~Mask)))
  3030. continue;
  3031. // If the mask we were given is not the net mask for this address,
  3032. // we'll need to repeat the above checks.
  3033. NetMask = IPNetMask(Address);
  3034. if (NetMask != Mask) {
  3035. MatchAddress = Address & NetMask;
  3036. if (IP_ADDR_EQUAL(MatchAddress, Address))
  3037. continue;
  3038. if (IP_ADDR_EQUAL(Address, MatchAddress |
  3039. (IP_LOCAL_BCST & ~NetMask)))
  3040. continue;
  3041. }
  3042. // If we get to this point we've passed all the tests, so it's
  3043. // local.
  3044. CTEFreeLock(&Interface->ai_lock, Handle);
  3045. return TRUE;
  3046. }
  3047. }
  3048. CTEFreeLock(&Interface->ai_lock, Handle);
  3049. return FALSE;
  3050. }
  3051. //* NotifyConflictProc - Notify the user of an address conflict.
  3052. //
  3053. // Called when we need to notify the user of an address conflict. The
  3054. // exact mechanism is system dependent, but generally involves a popup.
  3055. //
  3056. // Input: Event - Event that fired.
  3057. // Context - Pointer to ARPNotifyStructure.
  3058. //
  3059. // Returns: Nothing.
  3060. //
  3061. void
  3062. NotifyConflictProc(CTEEvent * Event, void *Context)
  3063. {
  3064. #if MILLEN
  3065. //
  3066. // Call into VIP to VIP_NotifyConflicProc. This will schedule an Appy
  3067. // event, etc. This is a little sleazy, but we do an INT 20, give the
  3068. // appropriate index into service table and VIP VxD ID.
  3069. //
  3070. // void VIP_NotifyConflictProc(CTEEvent *Event, void *Context);
  3071. // Event is unused.
  3072. //
  3073. _asm {
  3074. push Context
  3075. push Context
  3076. _emit 0xcd
  3077. _emit 0x20
  3078. _emit 0x15 // VIP_NotifyConflictProc (Low)
  3079. _emit 0x00 // VIP_NotifyConflictProc (High)
  3080. _emit 0x89 // VIP VxD ID (Low)
  3081. _emit 0x04 // VIP VxD ID (High)
  3082. add esp,8
  3083. }
  3084. #else // MILLEN
  3085. ARPNotifyStruct *NotifyStruct = (ARPNotifyStruct *) Context;
  3086. PWCHAR stringList[2];
  3087. uchar IPAddrBuffer[(sizeof(IPAddr) * 4)];
  3088. uchar HWAddrBuffer[(ARP_802_ADDR_LENGTH * 3)];
  3089. WCHAR unicodeIPAddrBuffer[((sizeof(IPAddr) * 4) + 1)];
  3090. WCHAR unicodeHWAddrBuffer[(ARP_802_ADDR_LENGTH * 3)];
  3091. uint i;
  3092. uint IPAddrCharCount;
  3093. UNICODE_STRING unicodeString;
  3094. ANSI_STRING ansiString;
  3095. PAGED_CODE();
  3096. UNREFERENCED_PARAMETER(Event);
  3097. //
  3098. // Convert the IP address into a string.
  3099. //
  3100. IPAddrCharCount = 0;
  3101. for (i = 0; i < sizeof(IPAddr); i++) {
  3102. uint CurrentByte;
  3103. CurrentByte = NotifyStruct->ans_addr & 0xff;
  3104. if (CurrentByte > 99) {
  3105. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 100) + '0';
  3106. CurrentByte %= 100;
  3107. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 10) + '0';
  3108. CurrentByte %= 10;
  3109. } else if (CurrentByte > 9) {
  3110. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 10) + '0';
  3111. CurrentByte %= 10;
  3112. }
  3113. IPAddrBuffer[IPAddrCharCount++] = (uchar)CurrentByte + '0';
  3114. if (i != (sizeof(IPAddr) - 1))
  3115. IPAddrBuffer[IPAddrCharCount++] = '.';
  3116. NotifyStruct->ans_addr >>= 8;
  3117. }
  3118. //
  3119. // Convert the hardware address into a string.
  3120. //
  3121. for (i = 0; i < NotifyStruct->ans_hwaddrlen; i++) {
  3122. uchar CurrentHalf;
  3123. CurrentHalf = NotifyStruct->ans_hwaddr[i] >> 4;
  3124. HWAddrBuffer[i * 3] = (uchar) (CurrentHalf < 10 ? CurrentHalf + '0' :
  3125. (CurrentHalf - 10) + 'A');
  3126. CurrentHalf = NotifyStruct->ans_hwaddr[i] & 0x0f;
  3127. HWAddrBuffer[(i * 3) + 1] = (uchar) (CurrentHalf < 10 ? CurrentHalf + '0' :
  3128. (CurrentHalf - 10) + 'A');
  3129. if (i != (NotifyStruct->ans_hwaddrlen - 1))
  3130. HWAddrBuffer[(i * 3) + 2] = ':';
  3131. }
  3132. //
  3133. // Unicode the strings.
  3134. //
  3135. *unicodeIPAddrBuffer = *unicodeHWAddrBuffer = UNICODE_NULL;
  3136. unicodeString.Buffer = unicodeIPAddrBuffer;
  3137. unicodeString.Length = 0;
  3138. unicodeString.MaximumLength = sizeof(WCHAR) * ((sizeof(IPAddr) * 4) + 1);
  3139. ansiString.Buffer = (PCHAR) IPAddrBuffer;
  3140. ansiString.Length = (USHORT) IPAddrCharCount;
  3141. ansiString.MaximumLength = (USHORT) IPAddrCharCount;
  3142. RtlAnsiStringToUnicodeString(
  3143. &unicodeString,
  3144. &ansiString,
  3145. FALSE
  3146. );
  3147. stringList[0] = unicodeIPAddrBuffer;
  3148. unicodeString.Buffer = unicodeHWAddrBuffer;
  3149. unicodeString.Length = 0;
  3150. unicodeString.MaximumLength = sizeof(WCHAR) * (ARP_802_ADDR_LENGTH * 3);
  3151. ansiString.Buffer = (PCHAR) HWAddrBuffer;
  3152. ansiString.Length = (ushort) ((NotifyStruct->ans_hwaddrlen * 3) - 1);
  3153. ansiString.MaximumLength = (ushort)(NotifyStruct->ans_hwaddrlen * 3);
  3154. RtlAnsiStringToUnicodeString(
  3155. &unicodeString,
  3156. &ansiString,
  3157. FALSE
  3158. );
  3159. stringList[1] = unicodeHWAddrBuffer;
  3160. //
  3161. // Kick off a popup and log an event.
  3162. //
  3163. if (NotifyStruct->ans_shutoff) {
  3164. CTELogEvent(
  3165. IPDriverObject,
  3166. EVENT_TCPIP_ADDRESS_CONFLICT1,
  3167. 0,
  3168. 2,
  3169. stringList,
  3170. 0,
  3171. NULL
  3172. );
  3173. IoRaiseInformationalHardError(
  3174. STATUS_IP_ADDRESS_CONFLICT1,
  3175. NULL,
  3176. NULL
  3177. );
  3178. } else {
  3179. CTELogEvent(
  3180. IPDriverObject,
  3181. EVENT_TCPIP_ADDRESS_CONFLICT2,
  3182. 0,
  3183. 2,
  3184. stringList,
  3185. 0,
  3186. NULL
  3187. );
  3188. IoRaiseInformationalHardError(
  3189. STATUS_IP_ADDRESS_CONFLICT2,
  3190. NULL,
  3191. NULL
  3192. );
  3193. }
  3194. CTEFreeMem(NotifyStruct);
  3195. #endif // !MILLEN
  3196. return;
  3197. }
  3198. //* DebugConflictProc - Prints some debugging info in case of addr conflicts
  3199. // Prints the ip and hw addr of the guy causing the conflict
  3200. // Context - Pointer to ARPNotifyStructure.
  3201. //
  3202. // Returns: Nothing.
  3203. //
  3204. void
  3205. DebugConflictProc(void *Context)
  3206. {
  3207. ARPNotifyStruct *NotifyStruct = (ARPNotifyStruct *) Context;
  3208. uchar IPAddrBuffer[(sizeof(IPAddr) * 4)];
  3209. uchar HWAddrBuffer[(ARP_802_ADDR_LENGTH * 3)];
  3210. uint i;
  3211. uint IPAddrCharCount;
  3212. IPAddr ans_addr;
  3213. //
  3214. // Save the IP address in case we need it later, then convert into
  3215. // a string.
  3216. //
  3217. ans_addr = NotifyStruct->ans_addr;
  3218. IPAddrCharCount = 0;
  3219. for (i = 0; i < sizeof(IPAddr); i++) {
  3220. uint CurrentByte;
  3221. CurrentByte = NotifyStruct->ans_addr & 0xff;
  3222. if (CurrentByte > 99) {
  3223. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 100) + '0';
  3224. CurrentByte %= 100;
  3225. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 10) + '0';
  3226. CurrentByte %= 10;
  3227. } else if (CurrentByte > 9) {
  3228. IPAddrBuffer[IPAddrCharCount++] = (uchar)(CurrentByte / 10) + '0';
  3229. CurrentByte %= 10;
  3230. }
  3231. IPAddrBuffer[IPAddrCharCount++] = (uchar) (CurrentByte) + '0';
  3232. if (i != (sizeof(IPAddr) - 1))
  3233. IPAddrBuffer[IPAddrCharCount++] = '.';
  3234. NotifyStruct->ans_addr >>= 8;
  3235. }
  3236. IPAddrBuffer[IPAddrCharCount] = '\0';
  3237. //
  3238. // Convert the hardware address into a string.
  3239. //
  3240. for (i = 0; i < NotifyStruct->ans_hwaddrlen; i++) {
  3241. uchar CurrentHalf;
  3242. CurrentHalf = NotifyStruct->ans_hwaddr[i] >> 4;
  3243. HWAddrBuffer[i * 3] = (uchar) (CurrentHalf < 10 ? CurrentHalf + '0' :
  3244. (CurrentHalf - 10) + 'A');
  3245. CurrentHalf = NotifyStruct->ans_hwaddr[i] & 0x0f;
  3246. HWAddrBuffer[(i * 3) + 1] = (uchar) (CurrentHalf < 10 ? CurrentHalf + '0' :
  3247. (CurrentHalf - 10) + 'A');
  3248. if (i != (NotifyStruct->ans_hwaddrlen - 1))
  3249. HWAddrBuffer[(i * 3) + 2] = ':';
  3250. }
  3251. HWAddrBuffer[((NotifyStruct->ans_hwaddrlen * 3) - 1)] = '\0';
  3252. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  3253. "TCPIP: Address Conflict: IPAddr %s HWAddr %s \n",
  3254. IPAddrBuffer, HWAddrBuffer));
  3255. return;
  3256. }
  3257. //* HandleARPPacket - Process an incoming ARP packet.
  3258. //
  3259. // This is the main routine to process an incoming ARP packet. We look at
  3260. // all ARP frames, and update our cache entry for the source address if one
  3261. // exists. Else, if we are the target we create an entry if one doesn't
  3262. // exist. Finally, we'll handle the opcode, responding if this is a request
  3263. // or sending pending packets if this is a response.
  3264. //
  3265. // Entry: Interface - Pointer to interface structure for this adapter.
  3266. // Header - Pointer to header buffer.
  3267. // HeaderSize - Size of header buffer.
  3268. // ARPHdr - ARP packet header.
  3269. // ARPHdrSize - Size of ARP header.
  3270. // ProtOffset - Offset into original data field of arp header.
  3271. // Will be non-zero if we're using SNAP.
  3272. //
  3273. // Returns: An NDIS_STATUS value to be returned to the NDIS driver.
  3274. //
  3275. NDIS_STATUS
  3276. HandleARPPacket(ARPInterface * Interface, void *Header, uint HeaderSize,
  3277. ARPHeader UNALIGNED * ARPHdr, uint ARPHdrSize, uint ProtOffset)
  3278. {
  3279. ARPTableEntry *Entry; // Entry in ARP table
  3280. CTELockHandle LHandle = DISPATCH_LEVEL, TableHandle;
  3281. RC UNALIGNED *SourceRoute = (RC UNALIGNED *) NULL; // Pointer to Source Route info, if any.
  3282. uint SourceRouteSize = 0;
  3283. ulong Now = CTESystemUpTime();
  3284. uchar LocalAddr;
  3285. uint LocalAddrAge;
  3286. uchar *SHAddr, *DHAddr;
  3287. IPAddr UNALIGNED *SPAddr, *DPAddr;
  3288. ENetHeader *ENetHdr;
  3289. TRHeader *TRHdr;
  3290. FDDIHeader *FHdr;
  3291. ARCNetHeader *AHdr;
  3292. ushort MaxMTU;
  3293. uint UseSNAP;
  3294. SetAddrControl *SAC=NULL;
  3295. ARPIPAddr *CurrentAddr;
  3296. AddAddrNotifyEvent *DelayedEvent;
  3297. uint NUCast;
  3298. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_RX,
  3299. (DTEXT("+HandleARPPacket(%x, %x, %d, %x, %d, %d)\n"),
  3300. Interface, Header, HeaderSize, ARPHdr, ARPHdrSize, ProtOffset));
  3301. // Validate the opcode
  3302. //
  3303. if ((ARPHdr->ah_opcode != net_short(ARP_REQUEST)) &&
  3304. (ARPHdr->ah_opcode != net_short(ARP_RESPONSE))) {
  3305. return NDIS_STATUS_NOT_RECOGNIZED;
  3306. }
  3307. // We examine all ARP frames. If we find the source address in the ARP table, we'll
  3308. // update the hardware address and set the state to valid. If we're the
  3309. // target and he's not in the table, we'll add him. Otherwise if we're the
  3310. // target and this is a response we'll send any pending packets to him.
  3311. if (Interface->ai_media != NdisMediumArcnet878_2) {
  3312. if (ARPHdrSize < sizeof(ARPHeader))
  3313. return NDIS_STATUS_NOT_RECOGNIZED; // Frame is too small.
  3314. if (ARPHdr->ah_hw != net_short(ARP_HW_ENET) &&
  3315. ARPHdr->ah_hw != net_short(ARP_HW_802))
  3316. return NDIS_STATUS_NOT_RECOGNIZED; // Wrong HW type
  3317. if (ARPHdr->ah_hlen != ARP_802_ADDR_LENGTH)
  3318. return NDIS_STATUS_NOT_RECOGNIZED; // Wrong address length.
  3319. if (Interface->ai_media == NdisMedium802_3 && Interface->ai_snapsize == 0)
  3320. UseSNAP = FALSE;
  3321. else
  3322. UseSNAP = (ProtOffset != 0);
  3323. // Figure out SR size on TR.
  3324. if (Interface->ai_media == NdisMedium802_5) {
  3325. // Check for source route information. SR is present if the header
  3326. // size is greater than the standard TR header size. If the SR is
  3327. // only an RC field, we ignore it because it came from the same
  3328. // ring which is the same as no SR.
  3329. if ((HeaderSize - sizeof(TRHeader)) > sizeof(RC)) {
  3330. SourceRouteSize = HeaderSize - sizeof(TRHeader);
  3331. SourceRoute = (RC UNALIGNED *) ((uchar *) Header +
  3332. sizeof(TRHeader));
  3333. }
  3334. }
  3335. SHAddr = ARPHdr->ah_shaddr;
  3336. SPAddr = (IPAddr UNALIGNED *) & ARPHdr->ah_spaddr;
  3337. DHAddr = ARPHdr->ah_dhaddr;
  3338. DPAddr = (IPAddr UNALIGNED *) & ARPHdr->ah_dpaddr;
  3339. } else {
  3340. if (ARPHdrSize < (sizeof(ARPHeader) - ARCNET_ARPHEADER_ADJUSTMENT))
  3341. return NDIS_STATUS_NOT_RECOGNIZED; // Frame is too small.
  3342. if (ARPHdr->ah_hw != net_short(ARP_HW_ARCNET))
  3343. return NDIS_STATUS_NOT_RECOGNIZED; // Wrong HW type
  3344. if (ARPHdr->ah_hlen != 1)
  3345. return NDIS_STATUS_NOT_RECOGNIZED; // Wrong address length.
  3346. UseSNAP = FALSE;
  3347. SHAddr = ARPHdr->ah_shaddr;
  3348. SPAddr = (IPAddr UNALIGNED *) (SHAddr + 1);
  3349. DHAddr = (uchar *) SPAddr + sizeof(IPAddr);
  3350. DPAddr = (IPAddr UNALIGNED *) (DHAddr + 1);
  3351. }
  3352. if (ARPHdr->ah_pro != net_short(ARP_ETYPE_IP))
  3353. return NDIS_STATUS_NOT_RECOGNIZED; // Unsupported protocol type.
  3354. if (ARPHdr->ah_plen != sizeof(IPAddr))
  3355. return NDIS_STATUS_NOT_RECOGNIZED;
  3356. LocalAddrAge = ARPADDR_NOT_LOCAL;
  3357. // First, let's see if we have an address conflict.
  3358. //
  3359. LocalAddrAge = IsLocalAddr(Interface, *SPAddr);
  3360. if (LocalAddrAge != ARPADDR_NOT_LOCAL) {
  3361. // The source IP address is one of ours. See if the source h/w address
  3362. // is ours also.
  3363. if (ARPHdr->ah_hlen != Interface->ai_addrlen ||
  3364. CTEMemCmp(SHAddr, Interface->ai_addr, Interface->ai_addrlen) != 0) {
  3365. uint Shutoff = FALSE;
  3366. BOOLEAN PopUP = TRUE;
  3367. ARPNotifyStruct *NotifyStruct;
  3368. // This isn't from us; we must have an address conflict somewhere.
  3369. // We always log an error about this. If what triggered this is a
  3370. // response and the address in conflict is young, we'll turn off
  3371. // the interface.
  3372. if (LocalAddrAge != ARPADDR_OLD_LOCAL &&
  3373. ARPHdr->ah_opcode == net_short(ARP_RESPONSE)) {
  3374. // Send an arp request with the owner's address to reset the
  3375. // caches.
  3376. CTEGetLock(&Interface->ai_lock, &LHandle);
  3377. // now find the address that is in conflict and get the
  3378. // corresponding client context.
  3379. CurrentAddr = &Interface->ai_ipaddr;
  3380. do {
  3381. if (CurrentAddr->aia_addr == *SPAddr) {
  3382. SAC = (SetAddrControl *) CurrentAddr->aia_context;
  3383. CurrentAddr->aia_context = NULL;
  3384. break;
  3385. }
  3386. CurrentAddr = CurrentAddr->aia_next;
  3387. } while (CurrentAddr != NULL);
  3388. CTEFreeLock(&Interface->ai_lock, LHandle);
  3389. SendARPRequest(Interface, *SPAddr, ARP_RESOLVING_GLOBAL,
  3390. SHAddr, FALSE); // Send a request.
  3391. Shutoff = TRUE;
  3392. // Display the debug information for remote boot/install.
  3393. // This code should be kept.
  3394. {
  3395. ARPNotifyStruct *DebugNotifyStruct;
  3396. DebugNotifyStruct = CTEAllocMemN(offsetof(ARPNotifyStruct, ans_hwaddr) +
  3397. ARPHdr->ah_hlen, '1ICT');
  3398. if (DebugNotifyStruct != NULL) {
  3399. DebugNotifyStruct->ans_addr = *SPAddr;
  3400. DebugNotifyStruct->ans_shutoff = Shutoff;
  3401. DebugNotifyStruct->ans_hwaddrlen = (uint) ARPHdr->ah_hlen;
  3402. RtlCopyMemory(DebugNotifyStruct->ans_hwaddr, SHAddr,
  3403. ARPHdr->ah_hlen);
  3404. DebugConflictProc(DebugNotifyStruct);
  3405. CTEFreeMem(DebugNotifyStruct);
  3406. }
  3407. }
  3408. if ((SAC != NULL) && !SAC->StaticAddr) {
  3409. // This is a dhcp adapter.
  3410. // Don't display a warning dialog in this case - DHCP will
  3411. // alert the user
  3412. //
  3413. PopUP = FALSE;
  3414. }
  3415. // We cannot call completion routine at this time
  3416. // because completion routine calls back into arp to
  3417. // reset the address and that may go down into ndis.
  3418. DelayedEvent = CTEAllocMemN(sizeof(AddAddrNotifyEvent), '2ICT');
  3419. if (DelayedEvent) {
  3420. DelayedEvent->SAC = SAC;
  3421. DelayedEvent->Address = *SPAddr;
  3422. DelayedEvent->Status = IP_DUPLICATE_ADDRESS;
  3423. CTEInitEvent(&DelayedEvent->Event, CompleteIPSetNTEAddrRequestDelayed);
  3424. CTEScheduleDelayedEvent(&DelayedEvent->Event, DelayedEvent);
  3425. } else {
  3426. ASSERT(FALSE);
  3427. }
  3428. if (!PopUP) {
  3429. goto no_dialog;
  3430. }
  3431. } else {
  3432. if (ARPHdr->ah_opcode == net_short(ARP_REQUEST) &&
  3433. (IsLocalAddr(Interface, *DPAddr) == ARPADDR_OLD_LOCAL)) {
  3434. // Send a response for gratuitous ARP.
  3435. SendARPReply(Interface, *SPAddr, *DPAddr, SHAddr,
  3436. SourceRoute, SourceRouteSize, UseSNAP);
  3437. Shutoff = FALSE;
  3438. } else if (LocalAddrAge != ARPADDR_OLD_LOCAL) {
  3439. // our address is still young. we dont need to put the
  3440. // warning popup as it will be done by the code that
  3441. // checks for arp response in above if portion of the code.
  3442. goto no_dialog;
  3443. }
  3444. // Else. We have an old local address and received an ARP for
  3445. // a third address. Fall through and indicate address
  3446. // conflict.
  3447. }
  3448. // Now allocate a structure, and schedule an event to notify
  3449. // the user.
  3450. NotifyStruct = CTEAllocMemN(offsetof(ARPNotifyStruct, ans_hwaddr) +
  3451. ARPHdr->ah_hlen, '3ICT');
  3452. if (NotifyStruct != NULL) {
  3453. NotifyStruct->ans_addr = *SPAddr;
  3454. NotifyStruct->ans_shutoff = Shutoff;
  3455. NotifyStruct->ans_hwaddrlen = (uint) ARPHdr->ah_hlen;
  3456. RtlCopyMemory(NotifyStruct->ans_hwaddr, SHAddr,
  3457. ARPHdr->ah_hlen);
  3458. CTEInitEvent(&NotifyStruct->ans_event, NotifyConflictProc);
  3459. if (Shutoff) {
  3460. // Delay notification for few seconds.
  3461. Interface->ai_conflict = NotifyStruct;
  3462. #if MILLEN
  3463. Interface->ai_delay = 5;
  3464. #else
  3465. Interface->ai_delay = 90; // delay 3 seconds.
  3466. #endif
  3467. } else
  3468. CTEScheduleDelayedEvent(&NotifyStruct->ans_event, NotifyStruct);
  3469. }
  3470. no_dialog:
  3471. ;
  3472. }
  3473. return NDIS_STATUS_NOT_RECOGNIZED;
  3474. }
  3475. if (!EnableBcastArpReply) {
  3476. // Check for bogus arp entry
  3477. NUCast = ((*(SHAddr) &
  3478. Interface->ai_bcastmask) == Interface->ai_bcastval) ?
  3479. AI_NONUCAST_INDEX : AI_UCAST_INDEX;
  3480. if (NUCast == AI_NONUCAST_INDEX) {
  3481. return NDIS_STATUS_NOT_RECOGNIZED;
  3482. }
  3483. }
  3484. CTEGetLock(&Interface->ai_ARPTblLock, &TableHandle);
  3485. MaxMTU = Interface->ai_mtu;
  3486. LocalAddr = ARPLocalAddr(Interface, *DPAddr);
  3487. // If the sender's address is not remote (i.e. multicast, broadcast,
  3488. // local, or just invalid), We don't want to create an entry for it or
  3489. // bother looking it up.
  3490. //
  3491. if ((DEST_REMOTE == GetAddrType(*SPAddr))) {
  3492. Entry = ARPLookup(Interface, *SPAddr);
  3493. if (Entry == (ARPTableEntry *) NULL) {
  3494. // Didn't find him, create one if it's for us. The call to ARPLookup
  3495. // returned with the ARPTblLock held, so we need to free it.
  3496. CTEFreeLock(&Interface->ai_ARPTblLock, TableHandle);
  3497. if (LocalAddr) {
  3498. // If this was an ARP request, we need to create a new
  3499. // entry for the source info. If this was a reply, it was
  3500. // unsolicited and we don't create an entry.
  3501. //
  3502. if (ARPHdr->ah_opcode != net_short(ARP_RESPONSE)) {
  3503. Entry = CreateARPTableEntry(Interface, *SPAddr, &LHandle, 0);
  3504. }
  3505. } else {
  3506. return NDIS_STATUS_NOT_RECOGNIZED; // Not in our table, and not for us.
  3507. }
  3508. } else {
  3509. //if this is for userarp, make sure that it is out of the table
  3510. //while we still have the arp table lock.
  3511. if (Entry->ate_userarp) {
  3512. ARPTable *Table;
  3513. ARPTableEntry *PrevATE, *CurrentATE;
  3514. uint Index = ARP_HASH(*SPAddr);
  3515. Table = Interface->ai_ARPTbl;
  3516. PrevATE = STRUCT_OF(ARPTableEntry, &((*Table)[Index]), ate_next);
  3517. CurrentATE = PrevATE;
  3518. while (CurrentATE != (ARPTableEntry *) NULL) {
  3519. if (CurrentATE == Entry) {
  3520. break;
  3521. }
  3522. PrevATE = CurrentATE;
  3523. CurrentATE = CurrentATE->ate_next;
  3524. }
  3525. if (CurrentATE != NULL) {
  3526. RemoveARPTableEntry(PrevATE, CurrentATE);
  3527. Interface->ai_count--;
  3528. }
  3529. }
  3530. CTEFreeLockFromDPC(&Interface->ai_ARPTblLock);
  3531. LHandle = TableHandle;
  3532. }
  3533. } else { // Source address was invalid for an Arp table entry.
  3534. CTEFreeLock(&Interface->ai_ARPTblLock, TableHandle);
  3535. Entry = NULL;
  3536. }
  3537. // At this point, entry should be valid and we hold the lock on the entry
  3538. // in LHandle or entry is NULL.
  3539. if (Entry != (ARPTableEntry *) NULL) {
  3540. PNDIS_PACKET Packet; // Packet to be sent.
  3541. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_RX,
  3542. (DTEXT("HandleARPPacket: resolving addr for ATE %x\n"), Entry));
  3543. Entry->ate_refresh = FALSE;
  3544. // If the entry is already static, we'll want to leave it as static.
  3545. if (Entry->ate_valid != ALWAYS_VALID) {
  3546. // OK, we have an entry to use, and hold the lock on it. Fill in the
  3547. // required fields.
  3548. switch (Interface->ai_media) {
  3549. case NdisMedium802_3:
  3550. // This is an Ethernet.
  3551. ENetHdr = (ENetHeader *) Entry->ate_addr;
  3552. RtlCopyMemory(ENetHdr->eh_daddr, SHAddr, ARP_802_ADDR_LENGTH);
  3553. RtlCopyMemory(ENetHdr->eh_saddr, Interface->ai_addr,
  3554. ARP_802_ADDR_LENGTH);
  3555. ENetHdr->eh_type = net_short(ARP_ETYPE_IP);
  3556. // If we're using SNAP on this entry, copy in the SNAP header.
  3557. if (UseSNAP) {
  3558. RtlCopyMemory(&Entry->ate_addr[sizeof(ENetHeader)], ARPSNAP,
  3559. sizeof(SNAPHeader));
  3560. Entry->ate_addrlength = (uchar) (sizeof(ENetHeader) +
  3561. sizeof(SNAPHeader));
  3562. *(ushort UNALIGNED *) & Entry->ate_addr[Entry->ate_addrlength - 2] =
  3563. net_short(ARP_ETYPE_IP);
  3564. } else
  3565. Entry->ate_addrlength = sizeof(ENetHeader);
  3566. Entry->ate_state = ARP_GOOD;
  3567. Entry->ate_valid = Now; // Mark last time he was
  3568. // valid.
  3569. Entry->ate_useticks = ArpCacheLife;
  3570. break;
  3571. case NdisMedium802_5:
  3572. // This is TR.
  3573. // For token ring we have to deal with source routing. There's
  3574. // a special case to handle multiple responses for an all-routes
  3575. // request - if the entry is currently good and we knew it was
  3576. // valid recently, we won't update the entry.
  3577. if (Entry->ate_state != ARP_GOOD ||
  3578. (Now - Entry->ate_valid) > ARP_RESOLVE_TIMEOUT) {
  3579. TRHdr = (TRHeader *) Entry->ate_addr;
  3580. // We need to update a TR entry.
  3581. TRHdr->tr_ac = ARP_AC;
  3582. TRHdr->tr_fc = ARP_FC;
  3583. RtlCopyMemory(TRHdr->tr_daddr, SHAddr, ARP_802_ADDR_LENGTH);
  3584. RtlCopyMemory(TRHdr->tr_saddr, Interface->ai_addr,
  3585. ARP_802_ADDR_LENGTH);
  3586. if (SourceRoute != (RC UNALIGNED *) NULL) {
  3587. uchar MaxIFieldBits;
  3588. // We have source routing information.
  3589. RtlCopyMemory(&Entry->ate_addr[sizeof(TRHeader)],
  3590. SourceRoute, SourceRouteSize);
  3591. MaxIFieldBits = (SourceRoute->rc_dlf & RC_LF_MASK) >>
  3592. LF_BIT_SHIFT;
  3593. MaxIFieldBits = MIN(MaxIFieldBits, MAX_LF_BITS);
  3594. MaxMTU = IFieldSize[MaxIFieldBits];
  3595. // The new MTU we've computed is the max I-field size,
  3596. // which doesn't include source routing info but
  3597. // does include SNAP info. Subtract off the SNAP size.
  3598. MaxMTU -= sizeof(SNAPHeader);
  3599. TRHdr->tr_saddr[0] |= TR_RII;
  3600. (*(RC UNALIGNED *) & Entry->ate_addr[sizeof(TRHeader)]).rc_dlf ^=
  3601. RC_DIR;
  3602. // Make sure it's non-broadcast.
  3603. (*(RC UNALIGNED *) & Entry->ate_addr[sizeof(TRHeader)]).rc_blen &=
  3604. RC_LENMASK;
  3605. }
  3606. RtlCopyMemory(&Entry->ate_addr[sizeof(TRHeader) + SourceRouteSize],
  3607. ARPSNAP, sizeof(SNAPHeader));
  3608. Entry->ate_state = ARP_GOOD;
  3609. Entry->ate_valid = Now;
  3610. Entry->ate_useticks = ArpCacheLife;
  3611. Entry->ate_addrlength = (uchar) (sizeof(TRHeader) +
  3612. SourceRouteSize + sizeof(SNAPHeader));
  3613. *(ushort *) & Entry->ate_addr[Entry->ate_addrlength - 2] =
  3614. net_short(ARP_ETYPE_IP);
  3615. }
  3616. break;
  3617. case NdisMediumFddi:
  3618. FHdr = (FDDIHeader *) Entry->ate_addr;
  3619. FHdr->fh_pri = ARP_FDDI_PRI;
  3620. RtlCopyMemory(FHdr->fh_daddr, SHAddr, ARP_802_ADDR_LENGTH);
  3621. RtlCopyMemory(FHdr->fh_saddr, Interface->ai_addr,
  3622. ARP_802_ADDR_LENGTH);
  3623. RtlCopyMemory(&Entry->ate_addr[sizeof(FDDIHeader)], ARPSNAP,
  3624. sizeof(SNAPHeader));
  3625. Entry->ate_addrlength = (uchar) (sizeof(FDDIHeader) +
  3626. sizeof(SNAPHeader));
  3627. *(ushort UNALIGNED *) & Entry->ate_addr[Entry->ate_addrlength - 2] =
  3628. net_short(ARP_ETYPE_IP);
  3629. Entry->ate_state = ARP_GOOD;
  3630. Entry->ate_valid = Now; // Mark last time he was
  3631. // valid.
  3632. Entry->ate_useticks = ArpCacheLife;
  3633. break;
  3634. case NdisMediumArcnet878_2:
  3635. AHdr = (ARCNetHeader *) Entry->ate_addr;
  3636. AHdr->ah_saddr = Interface->ai_addr[0];
  3637. AHdr->ah_daddr = *SHAddr;
  3638. AHdr->ah_prot = ARP_ARCPROT_IP;
  3639. Entry->ate_addrlength = sizeof(ARCNetHeader);
  3640. Entry->ate_state = ARP_GOOD;
  3641. Entry->ate_valid = Now; // Mark last time he was
  3642. // valid.
  3643. break;
  3644. default:
  3645. ASSERT(0);
  3646. break;
  3647. }
  3648. }
  3649. if (Entry->ate_resolveonly) {
  3650. ARPControlBlock *ArpContB, *TmpArpContB;
  3651. ArpContB = Entry->ate_resolveonly;
  3652. ASSERT(Entry->ate_resolveonly != NULL);
  3653. while (ArpContB) {
  3654. ArpRtn rtn;
  3655. rtn = (ArpRtn) ArpContB->CompletionRtn;
  3656. ArpContB->status = FillARPControlBlock(Interface, Entry,
  3657. ArpContB);
  3658. TmpArpContB = ArpContB->next;
  3659. (*rtn) (ArpContB, STATUS_SUCCESS);
  3660. ArpContB = TmpArpContB;
  3661. }
  3662. Entry->ate_resolveonly = NULL;
  3663. if (Entry->ate_userarp) {
  3664. PNDIS_PACKET OldPacket = NULL;
  3665. OldPacket = Entry->ate_packet;
  3666. CTEFreeLock(&Entry->ate_lock, LHandle);
  3667. CTEFreeMem(Entry);
  3668. if (OldPacket) {
  3669. IPSendComplete(Interface->ai_context, OldPacket,
  3670. NDIS_STATUS_SUCCESS);
  3671. }
  3672. } else {
  3673. CTEFreeLock(&Entry->ate_lock, LHandle);
  3674. }
  3675. return NDIS_STATUS_SUCCESS;
  3676. }
  3677. // At this point we've updated the entry, and we still hold the lock
  3678. // on it. If we have a packet that was pending to be sent, send it now.
  3679. // Otherwise just free the lock.
  3680. Packet = Entry->ate_packet;
  3681. if (Packet != NULL) {
  3682. // We have a packet to send.
  3683. ASSERT(Entry->ate_state == ARP_GOOD);
  3684. Entry->ate_packet = NULL;
  3685. DEBUGMSG(DBG_INFO && DBG_ARP && DBG_TX,
  3686. (DTEXT("ARPHandlePacket: Sending packet %x after resolving ATE %x\n"),
  3687. Packet, Entry));
  3688. if (ARPSendData(Interface, Packet, Entry, LHandle) != NDIS_STATUS_PENDING) {
  3689. IPSendComplete(Interface->ai_context, Packet, NDIS_STATUS_SUCCESS);
  3690. }
  3691. } else {
  3692. CTEFreeLock(&Entry->ate_lock, LHandle);
  3693. }
  3694. }
  3695. // See if the MTU is less than our local one. This should only happen
  3696. // in the case of token ring source routing.
  3697. if (MaxMTU < Interface->ai_mtu) {
  3698. LLIPAddrMTUChange LAM;
  3699. LAM.lam_mtu = MaxMTU;
  3700. LAM.lam_addr = *SPAddr;
  3701. // It is less. Notify IP.
  3702. ASSERT(Interface->ai_media == NdisMedium802_5);
  3703. IPStatus(Interface->ai_context, LLIP_STATUS_ADDR_MTU_CHANGE,
  3704. &LAM, sizeof(LLIPAddrMTUChange), NULL);
  3705. }
  3706. // At this point we've updated the entry (if we had one), and we've freed
  3707. // all locks. If it's for a local address and it's a request, reply to
  3708. // it.
  3709. if (LocalAddr) { // It's for us.
  3710. if (ARPHdr->ah_opcode == net_short(ARP_REQUEST)) {
  3711. // It's a request, and we need to respond.
  3712. SendARPReply(Interface, *SPAddr, *DPAddr,
  3713. SHAddr, SourceRoute, SourceRouteSize, UseSNAP);
  3714. }
  3715. }
  3716. return NDIS_STATUS_SUCCESS;
  3717. }
  3718. //* InitAdapter - Initialize an adapter.
  3719. //
  3720. // Called when an adapter is open to finish initialization. We set
  3721. // up our lookahead size and packet filter, and we're ready to go.
  3722. //
  3723. // Entry:
  3724. // adapter - Pointer to an adapter structure for the adapter to be
  3725. // initialized.
  3726. //
  3727. // Exit: Nothing
  3728. //
  3729. void
  3730. InitAdapter(ARPInterface * Adapter)
  3731. {
  3732. NDIS_STATUS Status;
  3733. CTELockHandle Handle;
  3734. ARPIPAddr *Addr, *OldAddr;
  3735. if ((Status = DoNDISRequest(Adapter, NdisRequestSetInformation,
  3736. OID_GEN_CURRENT_LOOKAHEAD, &ARPLookahead, sizeof(ARPLookahead),
  3737. NULL, TRUE)) != NDIS_STATUS_SUCCESS) {
  3738. Adapter->ai_operstatus = INTERFACE_UNINIT;
  3739. return;
  3740. }
  3741. if ((Status = DoNDISRequest(Adapter, NdisRequestSetInformation,
  3742. OID_GEN_CURRENT_PACKET_FILTER, &Adapter->ai_pfilter, sizeof(uint),
  3743. NULL, TRUE)) == NDIS_STATUS_SUCCESS) {
  3744. uint MediaStatus;
  3745. Adapter->ai_adminstate = IF_STATUS_UP;
  3746. Adapter->ai_mediastatus = TRUE;
  3747. if ((Status = DoNDISRequest(Adapter, NdisRequestQueryInformation,
  3748. OID_GEN_MEDIA_CONNECT_STATUS, &MediaStatus, sizeof(MediaStatus),
  3749. NULL, TRUE)) == NDIS_STATUS_SUCCESS) {
  3750. if (MediaStatus == NdisMediaStateDisconnected) {
  3751. Adapter->ai_mediastatus = FALSE;
  3752. }
  3753. }
  3754. ARPUpdateOperStatus(Adapter);
  3755. // Now walk through any addresses we have and ARP for them , only when ArpRetryCount != 0.
  3756. if (ArpRetryCount) {
  3757. CTEGetLock(&Adapter->ai_lock, &Handle);
  3758. OldAddr = NULL;
  3759. Addr = &Adapter->ai_ipaddr;
  3760. do {
  3761. if (!IP_ADDR_EQUAL(Addr->aia_addr, NULL_IP_ADDR)) {
  3762. IPAddr Address = Addr->aia_addr;
  3763. Addr->aia_age = ArpRetryCount;
  3764. CTEFreeLock(&Adapter->ai_lock, Handle);
  3765. OldAddr = Addr;
  3766. SendARPRequest(Adapter, Address, ARP_RESOLVING_GLOBAL,
  3767. NULL, TRUE);
  3768. CTEGetLock(&Adapter->ai_lock, &Handle);
  3769. Addr = &Adapter->ai_ipaddr;
  3770. while (Addr != OldAddr && Addr != NULL) {
  3771. Addr = Addr->aia_next;
  3772. }
  3773. if (Addr != NULL) {
  3774. Addr = Addr->aia_next;
  3775. }
  3776. } else {
  3777. Addr = Addr->aia_next;
  3778. }
  3779. } while (Addr != NULL);
  3780. CTEFreeLock(&Adapter->ai_lock, Handle);
  3781. }
  3782. } else {
  3783. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_ERROR_LEVEL,
  3784. "**InitAdapter setting FAILED\n"));
  3785. Adapter->ai_operstatus = INTERFACE_UNINIT;
  3786. }
  3787. }
  3788. //** ARPOAComplete - ARP Open adapter complete handler.
  3789. //
  3790. // This routine is called by the NDIS driver when an open adapter
  3791. // call completes. Presumably somebody is blocked waiting for this, so
  3792. // we'll wake him up now.
  3793. //
  3794. // Entry:
  3795. // Handle - The binding handle we specified (really a pointer to an AI).
  3796. // Status - Final status of command.
  3797. // ErrorStatus - Final error status.
  3798. //
  3799. // Exit: Nothing.
  3800. //
  3801. void NDIS_API
  3802. ARPOAComplete(NDIS_HANDLE Handle, NDIS_STATUS Status, NDIS_STATUS ErrorStatus)
  3803. {
  3804. ARPInterface *ai = (ARPInterface *) Handle; // For compiler.
  3805. UNREFERENCED_PARAMETER(ErrorStatus);
  3806. CTESignal(&ai->ai_block, (uint) Status); // Wake him up, and return status.
  3807. }
  3808. //** ARPCAComplete - ARP close adapter complete handler.
  3809. //
  3810. // This routine is called by the NDIS driver when a close adapter
  3811. // call completes.
  3812. //
  3813. // Entry:
  3814. // Handle - The binding handle we specified (really a pointer to an AI).
  3815. // Status - Final status of command.
  3816. //
  3817. // Exit: Nothing.
  3818. //
  3819. void NDIS_API
  3820. ARPCAComplete(NDIS_HANDLE Handle, NDIS_STATUS Status)
  3821. {
  3822. ARPInterface *ai = (ARPInterface *) Handle; // For compiler.
  3823. CTESignal(&ai->ai_block, (uint) Status); // Wake him up, and return status.
  3824. }
  3825. //** ARPSendComplete - ARP send complete handler.
  3826. //
  3827. // This routine is called by the NDIS driver when a send completes.
  3828. // This is a pretty time critical operation, we need to get through here
  3829. // quickly. We'll strip our buffer off and put it back, and call the upper
  3830. // later send complete handler.
  3831. //
  3832. // Entry:
  3833. // Handle - The binding handle we specified (really a pointer to an AI).
  3834. // Packet - A pointer to the packet that was sent.
  3835. // Status - Final status of command.
  3836. //
  3837. // Exit: Nothing.
  3838. //
  3839. void NDIS_API
  3840. ARPSendComplete(NDIS_HANDLE Handle, PNDIS_PACKET Packet, NDIS_STATUS Status)
  3841. {
  3842. ARPInterface *Interface = (ARPInterface *) Handle;
  3843. PacketContext *PC = (PacketContext *) Packet->ProtocolReserved;
  3844. PNDIS_BUFFER Buffer;
  3845. uint DataLength;
  3846. ulong Proc;
  3847. Proc = KeGetCurrentProcessorNumber();
  3848. Interface->ai_qlen[Proc].ai_qlen--;
  3849. if (Status == NDIS_STATUS_SUCCESS) {
  3850. DataLength = Packet->Private.TotalLength;
  3851. if (!(Packet->Private.ValidCounts)) {
  3852. NdisQueryPacket(Packet, NULL, NULL, NULL,&DataLength);
  3853. }
  3854. Interface->ai_outoctets += DataLength;
  3855. } else {
  3856. if (Status == NDIS_STATUS_RESOURCES)
  3857. Interface->ai_outdiscards++;
  3858. else
  3859. Interface->ai_outerrors++;
  3860. }
  3861. #if BACK_FILL
  3862. // Get first buffer on packet.
  3863. if (Interface->ai_media == NdisMedium802_3) {
  3864. PMDL TmpMdl = NULL;
  3865. uint HdrSize;
  3866. NdisQueryPacket(Packet, NULL, NULL, &TmpMdl, NULL);
  3867. if (TmpMdl->MdlFlags & MDL_NETWORK_HEADER) {
  3868. HdrSize = sizeof(ENetHeader);
  3869. if (((PacketContext*)
  3870. Packet->ProtocolReserved)->pc_common.pc_flags &
  3871. PACKET_FLAG_SNAP)
  3872. HdrSize += Interface->ai_snapsize;
  3873. TmpMdl->MappedSystemVa = (PVOID) (((ULONG_PTR)
  3874. TmpMdl->MappedSystemVa) +
  3875. HdrSize);
  3876. TmpMdl->ByteOffset += HdrSize;
  3877. TmpMdl->ByteCount -= HdrSize;
  3878. } else {
  3879. NdisUnchainBufferAtFront(Packet, &Buffer);
  3880. FreeARPBuffer(Interface, Buffer); // Free it up.
  3881. }
  3882. } else {
  3883. NdisUnchainBufferAtFront(Packet, &Buffer);
  3884. FreeARPBuffer(Interface, Buffer); // Free it up.
  3885. }
  3886. #else
  3887. // Get first buffer on packet.
  3888. NdisUnchainBufferAtFront(Packet, &Buffer);
  3889. ASSERT(Buffer);
  3890. FreeARPBuffer(Interface, Buffer); // Free it up.
  3891. #endif
  3892. if (PC->pc_common.pc_owner != PACKET_OWNER_LINK) { // We don't own this one.
  3893. IPSendComplete(Interface->ai_context, Packet, Status);
  3894. return;
  3895. }
  3896. // This packet belongs to us, so free it.
  3897. NdisFreePacket(Packet);
  3898. }
  3899. //** ARPTDComplete - ARP transfer data complete handler.
  3900. //
  3901. // This routine is called by the NDIS driver when a transfer data
  3902. // call completes. Since we never transfer data ourselves, this must be
  3903. // from the upper layer. We'll just call his routine and let him deal
  3904. // with it.
  3905. //
  3906. // Entry:
  3907. // Handle - The binding handle we specified (really a pointer to an AI).
  3908. // Packet - A pointer to the packet used for the TD.
  3909. // Status - Final status of command.
  3910. // BytesCopied - Count of bytes copied.
  3911. //
  3912. // Exit: Nothing.
  3913. //
  3914. void NDIS_API
  3915. ARPTDComplete(NDIS_HANDLE Handle, PNDIS_PACKET Packet, NDIS_STATUS Status,
  3916. uint BytesCopied)
  3917. {
  3918. ARPInterface *ai = (ARPInterface *) Handle;
  3919. IPTDComplete(ai->ai_context, Packet, Status, BytesCopied);
  3920. }
  3921. //** ARPResetComplete - ARP reset complete handler.
  3922. //
  3923. // This routine is called by the NDIS driver when a reset completes.
  3924. //
  3925. // Entry:
  3926. // Handle - The binding handle we specified (really a pointer to an AI).
  3927. // Status - Final status of command.
  3928. //
  3929. // Exit: Nothing.
  3930. //
  3931. void NDIS_API
  3932. ARPResetComplete(NDIS_HANDLE Handle, NDIS_STATUS Status)
  3933. {
  3934. ARPInterface *ai = (ARPInterface *) Handle;
  3935. UNREFERENCED_PARAMETER(Status);
  3936. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ArpResetComplete on %x\n", ai->ai_context));
  3937. IPReset(ai->ai_context);
  3938. }
  3939. //** ARPRequestComplete - ARP request complete handler.
  3940. //
  3941. // This routine is called by the NDIS driver when a general request
  3942. // completes. If ARP blocks on a request, we'll just give a wake up
  3943. // to whoever's blocked on this request. Else if it is a non-blocking
  3944. // request, we extract the request complete callback fn in the request
  3945. // call it, and then deallocate the request block (that is on the heap)
  3946. //
  3947. // Entry:
  3948. // Handle - The binding handle we specified (really a pointer to an AI).
  3949. // Request - A pointer to the request that completed.
  3950. // Status - Final status of command.
  3951. //
  3952. // Exit: Nothing.
  3953. //
  3954. void NDIS_API
  3955. ARPRequestComplete(NDIS_HANDLE Handle, PNDIS_REQUEST pRequest,
  3956. NDIS_STATUS Status)
  3957. {
  3958. RequestBlock *rb = STRUCT_OF(RequestBlock, pRequest, Request);
  3959. DBG_UNREFERENCED_PARAMETER(Handle);
  3960. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_REQUEST,
  3961. (DTEXT("+ARPRequestComplete(%x, %x, %x) RequestBlock %x\n"),
  3962. Handle, pRequest, Status, rb));
  3963. if (rb->Blocking) {
  3964. // Request through BLOCKING DoNDISRequest
  3965. // Signal the blocked guy here
  3966. CTESignal(&rb->Block, (uint) Status);
  3967. if (InterlockedDecrement( (PLONG) &rb->RefCount) == 0) {
  3968. CTEFreeMem(rb);
  3969. }
  3970. } else {
  3971. ReqInfoBlock *rib;
  3972. RCCALL reqcallback;
  3973. // Request through NON-BLOCKING DoNDISRequest
  3974. // Extract the callback fn pointer & params
  3975. if (pRequest->RequestType == NdisRequestSetInformation)
  3976. rib = STRUCT_OF(ReqInfoBlock,
  3977. pRequest->DATA.SET_INFORMATION.InformationBuffer,
  3978. RequestInfo);
  3979. else
  3980. rib = STRUCT_OF(ReqInfoBlock,
  3981. pRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  3982. RequestInfo);
  3983. reqcallback = rib->ReqCompleteCallback;
  3984. if (reqcallback)
  3985. reqcallback(rib);
  3986. // Free ARP memory associated with request
  3987. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPRequestComplete: Freeing mem at pRequest = %08X\n", rb));
  3988. CTEFreeMem(rb);
  3989. }
  3990. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_REQUEST,
  3991. (DTEXT("-ARPRequestComplete [%x]\n"), Status));
  3992. }
  3993. //** ARPRcv - ARP receive data handler.
  3994. //
  3995. // This routine is called when data arrives from the NDIS driver.
  3996. //
  3997. // Entry:
  3998. // Handle - The binding handle we specified (really a pointer to an AI).
  3999. // Context - NDIS context to be used for TD.
  4000. // Header - Pointer to header
  4001. // HeaderSize - Size of header
  4002. // Data - Pointer to buffer of received data
  4003. // Size - Byte count of data in buffer.
  4004. // TotalSize - Byte count of total packet size.
  4005. //
  4006. // Exit: Status indicating whether or not we took the packet.
  4007. //
  4008. NDIS_STATUS NDIS_API
  4009. ARPRcv(NDIS_HANDLE Handle, NDIS_HANDLE Context, void *Header, uint HeaderSize,
  4010. void *Data, uint Size, uint TotalSize)
  4011. {
  4012. ARPInterface *Interface = Handle;
  4013. NDIS_STATUS status;
  4014. PINT OrigPacket = NULL;
  4015. //get the original packet (if any)
  4016. //this is required to make task offload work
  4017. //note: We shall hack the pClientCount Field
  4018. //to point to the packet as a short term solution
  4019. //to avoid changing all atm - ip interface changes
  4020. if (Interface->ai_OffloadFlags || Interface->ai_IPSecOffloadFlags) {
  4021. OrigPacket = (PINT) NdisGetReceivedPacket(Interface->ai_handle, Context);
  4022. }
  4023. //Call the new interface with null mdl and context pointers
  4024. status = ARPRcvIndicationNew(Handle, Context, Header, HeaderSize,
  4025. Data, Size, TotalSize, NULL, OrigPacket);
  4026. return status;
  4027. }
  4028. //** ARPRcvPacket - ARP receive data handler.
  4029. //
  4030. // This routine is called when data arrives from the NDIS driver.
  4031. //
  4032. // Entry:
  4033. // Handle - The binding handle we specified (really a pointer to an AI).
  4034. // Packet - Contains the incoming frame
  4035. //
  4036. // Returns number of upper layer folks latching on to this frame
  4037. //
  4038. //
  4039. INT
  4040. ARPRcvPacket(NDIS_HANDLE Handle, PNDIS_PACKET Packet)
  4041. {
  4042. UINT HeaderBufferSize = NDIS_GET_PACKET_HEADER_SIZE(Packet);
  4043. UINT firstbufferLength, bufferLength, LookAheadBufferSize;
  4044. PNDIS_BUFFER pFirstBuffer;
  4045. PUCHAR headerBuffer;
  4046. NTSTATUS ntStatus;
  4047. INT ClientCnt = 0;
  4048. //
  4049. // Query the number of buffers, the first MDL's descriptor and the packet length
  4050. //
  4051. NdisGetFirstBufferFromPacket(Packet, // packet
  4052. &pFirstBuffer, // first buffer descriptor
  4053. &headerBuffer, // ptr to the start of packet
  4054. &firstbufferLength, // length of the header+lookahead
  4055. &bufferLength); // length of the bytes in the buffers
  4056. //
  4057. // ReceiveContext is the packet itself
  4058. //
  4059. LookAheadBufferSize = firstbufferLength - HeaderBufferSize;
  4060. ntStatus = ARPRcvIndicationNew(Handle, Packet, headerBuffer,
  4061. HeaderBufferSize,
  4062. headerBuffer + HeaderBufferSize, // LookaheadBuffer
  4063. LookAheadBufferSize, // LookaheadBufferSize
  4064. bufferLength - HeaderBufferSize, // PacketSize - since
  4065. // the whole packet is
  4066. // indicated
  4067. pFirstBuffer, // pMdl
  4068. &ClientCnt // tdi client count
  4069. );
  4070. return ClientCnt;
  4071. }
  4072. //** ARPRcvIndicationNew - ARP receive data handler.
  4073. //
  4074. // This routine is called when data arrives from the NDIS driver.
  4075. //
  4076. // Entry:
  4077. // Handle - The binding handle we specified (really a pointer to an AI).
  4078. // Context - NDIS context to be used for TD.
  4079. // Header - Pointer to header
  4080. // HeaderSize - Size of header
  4081. // Data - Pointer to buffer of received data
  4082. // Size - Byte count of data in buffer.
  4083. // TotalSize - Byte count of total packet size.
  4084. // pMdl - NDIS_BUFFER of incoming frame
  4085. // pClientCnt address to return the clinet counts
  4086. //
  4087. // Exit: Status indicating whether or not we took the packet.
  4088. //
  4089. NDIS_STATUS NDIS_API
  4090. ARPRcvIndicationNew(NDIS_HANDLE Handle, NDIS_HANDLE Context, void *Header,
  4091. uint HeaderSize, void *Data, uint Size, uint TotalSize,
  4092. PNDIS_BUFFER pNdisBuffer, PINT pClientCnt)
  4093. {
  4094. ARPInterface *Interface = Handle; // Interface for this driver.
  4095. ENetHeader UNALIGNED *EHdr = (ENetHeader UNALIGNED *) Header;
  4096. SNAPHeader UNALIGNED *SNAPHdr;
  4097. ushort type; // Protocol type
  4098. uint ProtOffset; // Offset in Data to non-media info.
  4099. uint NUCast; // TRUE if the frame is not a unicast frame.
  4100. if ((Interface->ai_operstatus == INTERFACE_UP) &&
  4101. HeaderSize >= (uint) Interface->ai_hdrsize) {
  4102. // Per RFC 1213 and its successors, the inoctets count includes
  4103. // the MAC header bytes.
  4104. Interface->ai_inoctets += HeaderSize + TotalSize;
  4105. NUCast = ((*((uchar UNALIGNED *) EHdr + Interface->ai_bcastoff) &
  4106. Interface->ai_bcastmask) == Interface->ai_bcastval) ?
  4107. AI_NONUCAST_INDEX : AI_UCAST_INDEX;
  4108. if ((Interface->ai_promiscuous) && (!NUCast)) { // AI_UCAST_INDEX = 0
  4109. switch (Interface->ai_media) {
  4110. case NdisMedium802_3:{
  4111. // Enet
  4112. if (Interface->ai_addrlen != ARP_802_ADDR_LENGTH ||
  4113. CTEMemCmp(EHdr->eh_daddr, Interface->ai_addr, ARP_802_ADDR_LENGTH) != 0) {
  4114. NUCast = AI_PROMIS_INDEX;
  4115. }
  4116. break;
  4117. }
  4118. case NdisMedium802_5:{
  4119. // token ring
  4120. TRHeader UNALIGNED *THdr = (TRHeader UNALIGNED *) Header;
  4121. if (Interface->ai_addrlen != ARP_802_ADDR_LENGTH ||
  4122. CTEMemCmp(THdr->tr_daddr, Interface->ai_addr, ARP_802_ADDR_LENGTH) != 0) {
  4123. NUCast = AI_PROMIS_INDEX;
  4124. }
  4125. break;
  4126. }
  4127. case NdisMediumFddi:{
  4128. // FDDI
  4129. FDDIHeader UNALIGNED *FHdr = (FDDIHeader UNALIGNED *) Header;
  4130. if (Interface->ai_addrlen != ARP_802_ADDR_LENGTH ||
  4131. CTEMemCmp(FHdr->fh_daddr, Interface->ai_addr, ARP_802_ADDR_LENGTH) != 0) {
  4132. NUCast = AI_PROMIS_INDEX;
  4133. }
  4134. break;
  4135. }
  4136. case NdisMediumArcnet878_2:{
  4137. // ArcNet
  4138. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_RX,
  4139. (DTEXT("-ARPRcvIndicationNew [NOT_RECOGNIZED]\n")));
  4140. return NDIS_STATUS_NOT_RECOGNIZED;
  4141. break;
  4142. }
  4143. default:
  4144. ASSERT(0);
  4145. Interface->ai_outerrors++;
  4146. DEBUGMSG(DBG_TRACE && DBG_ARP && DBG_RX,
  4147. (DTEXT("-ARPRcvIndicationNew [UNSUPPORTED_MEDIA]\n")));
  4148. return NDIS_STATUS_UNSUPPORTED_MEDIA;
  4149. }
  4150. }
  4151. if ((Interface->ai_media == NdisMedium802_3) &&
  4152. (type = net_short(EHdr->eh_type)) >= MIN_ETYPE) {
  4153. ProtOffset = 0;
  4154. } else if (Interface->ai_media != NdisMediumArcnet878_2) {
  4155. SNAPHdr = (SNAPHeader UNALIGNED *) Data;
  4156. if (Size >= sizeof(SNAPHeader) &&
  4157. SNAPHdr->sh_dsap == SNAP_SAP &&
  4158. SNAPHdr->sh_ssap == SNAP_SAP &&
  4159. SNAPHdr->sh_ctl == SNAP_UI) {
  4160. type = net_short(SNAPHdr->sh_etype);
  4161. ProtOffset = sizeof(SNAPHeader);
  4162. } else {
  4163. //handle XID/TEST here.
  4164. Interface->ai_uknprotos++;
  4165. return NDIS_STATUS_NOT_RECOGNIZED;
  4166. }
  4167. } else {
  4168. ARCNetHeader UNALIGNED *AH = (ARCNetHeader UNALIGNED *) Header;
  4169. ProtOffset = 0;
  4170. if (AH->ah_prot == ARP_ARCPROT_IP)
  4171. type = ARP_ETYPE_IP;
  4172. else if (AH->ah_prot == ARP_ARCPROT_ARP)
  4173. type = ARP_ETYPE_ARP;
  4174. else
  4175. type = 0;
  4176. }
  4177. if (type == ARP_ETYPE_IP) {
  4178. (Interface->ai_inpcount[NUCast])++;
  4179. ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL);
  4180. IPRcvPacket(Interface->ai_context, (uchar *) Data + ProtOffset,
  4181. Size - ProtOffset, TotalSize - ProtOffset, Context, ProtOffset,
  4182. NUCast, HeaderSize, pNdisBuffer, (PUINT) pClientCnt, NULL);
  4183. return NDIS_STATUS_SUCCESS;
  4184. } else {
  4185. if (type == ARP_ETYPE_ARP) {
  4186. (Interface->ai_inpcount[NUCast])++;
  4187. return HandleARPPacket(Interface, Header, HeaderSize,
  4188. (ARPHeader *) ((uchar *) Data + ProtOffset), Size - ProtOffset,
  4189. ProtOffset);
  4190. } else {
  4191. Interface->ai_uknprotos++;
  4192. return NDIS_STATUS_NOT_RECOGNIZED;
  4193. }
  4194. }
  4195. } else {
  4196. // Interface is marked as down.
  4197. return NDIS_STATUS_NOT_RECOGNIZED;
  4198. }
  4199. }
  4200. //** ARPRcvComplete - ARP receive complete handler.
  4201. //
  4202. // This routine is called by the NDIS driver after some number of
  4203. // receives. In some sense, it indicates 'idle time'.
  4204. //
  4205. // Entry:
  4206. // Handle - The binding handle we specified (really a pointer to an AI).
  4207. //
  4208. // Exit: Nothing.
  4209. //
  4210. void NDIS_API
  4211. ARPRcvComplete(NDIS_HANDLE Handle)
  4212. {
  4213. UNREFERENCED_PARAMETER(Handle);
  4214. IPRcvComplete();
  4215. }
  4216. //** ARPStatus - ARP status handler.
  4217. //
  4218. // Called by the NDIS driver when some sort of status change occurs.
  4219. // We take action depending on the type of status.
  4220. //
  4221. // Entry:
  4222. // Handle - The binding handle we specified (really a pointer to an AI).
  4223. // GStatus - General type of status that caused the call.
  4224. // Status - Pointer to a buffer of status specific information.
  4225. // StatusSize - Size of the status buffer.
  4226. //
  4227. // Exit: Nothing.
  4228. //
  4229. void NDIS_API
  4230. ARPStatus(NDIS_HANDLE Handle, NDIS_STATUS GStatus, void *Status, uint
  4231. StatusSize)
  4232. {
  4233. ARPInterface *ai = (ARPInterface *) Handle;
  4234. //
  4235. // ndis calls this sometimes even before ip interface is created.
  4236. //
  4237. if ((ai->ai_context) && (ai->ai_operstatus != INTERFACE_INIT)) {
  4238. IPStatus(ai->ai_context, GStatus, Status, StatusSize, NULL);
  4239. switch (GStatus) {
  4240. //reflect media connect/disconnect status in
  4241. //operstatus for query purpose
  4242. case NDIS_STATUS_MEDIA_CONNECT:
  4243. ai->ai_mediastatus = TRUE;
  4244. ARPUpdateOperStatus(ai);
  4245. break;
  4246. case NDIS_STATUS_MEDIA_DISCONNECT:
  4247. ai->ai_mediastatus = FALSE;
  4248. ARPUpdateOperStatus(ai);
  4249. break;
  4250. default:
  4251. break;
  4252. }
  4253. }
  4254. }
  4255. //** ARPStatusComplete - ARP status complete handler.
  4256. //
  4257. // A routine called by the NDIS driver so that we can do postprocessing
  4258. // after a status event.
  4259. //
  4260. // Entry:
  4261. // Handle - The binding handle we specified (really a pointer to an AI).
  4262. //
  4263. // Exit: Nothing.
  4264. //
  4265. void NDIS_API
  4266. ARPStatusComplete(NDIS_HANDLE Handle)
  4267. {
  4268. UNREFERENCED_PARAMETER(Handle);
  4269. }
  4270. //** ARPPnPEvent - ARP PnPEvent handler.
  4271. //
  4272. // Called by the NDIS driver when PnP or PM events occurs.
  4273. //
  4274. // Entry:
  4275. // Handle - The binding handle we specified (really a pointer to an AI).
  4276. // NetPnPEvent - This is a pointer to a NET_PNP_EVENT that describes
  4277. // the PnP indication.
  4278. //
  4279. // Exit:
  4280. // Just call into IP and return status.
  4281. //
  4282. NDIS_STATUS
  4283. ARPPnPEvent(NDIS_HANDLE Handle, PNET_PNP_EVENT NetPnPEvent)
  4284. {
  4285. ARPInterface *ai = (ARPInterface *) Handle;
  4286. //
  4287. // ndis can calls this sometimes even before ip interface is created.
  4288. //
  4289. if (ai && !ai->ai_context) {
  4290. return STATUS_SUCCESS;
  4291. } else {
  4292. return IPPnPEvent(ai ? ai->ai_context : NULL, NetPnPEvent);
  4293. }
  4294. }
  4295. //** ARPSetNdisRequest - ARP Ndisrequest handler.
  4296. //
  4297. // Called by the upper driver to set the packet filter for the interface.
  4298. //
  4299. // Entry:
  4300. // Context - Context value we gave to IP (really a pointer to an AI).
  4301. // OID - Object ID to set/unset
  4302. // On - Set_if, clear_if or clear_card
  4303. //
  4304. // Exit:
  4305. // returns status.
  4306. //
  4307. NDIS_STATUS
  4308. __stdcall
  4309. ARPSetNdisRequest(void *Context, NDIS_OID OID, uint On)
  4310. {
  4311. int Status;
  4312. ARPInterface *Interface = (ARPInterface *) Context;
  4313. if (On == SET_IF) {
  4314. Interface->ai_pfilter |= OID;
  4315. if (OID == NDIS_PACKET_TYPE_PROMISCUOUS) {
  4316. Interface->ai_promiscuous = 1;
  4317. }
  4318. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  4319. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  4320. sizeof(uint), NULL, TRUE);
  4321. } else { // turn off
  4322. Interface->ai_pfilter &= ~(OID);
  4323. if (OID == NDIS_PACKET_TYPE_PROMISCUOUS) {
  4324. Interface->ai_promiscuous = 0;
  4325. }
  4326. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  4327. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  4328. sizeof(uint), NULL, TRUE);
  4329. }
  4330. return Status;
  4331. }
  4332. //** ARPPnPComplete - ARP PnP complete handler.
  4333. //
  4334. // Called by the upper driver to do the post processing of pnp event.
  4335. //
  4336. // Entry:
  4337. // Context - Context value we gave to IP (really a pointer to an AI).
  4338. // Status - Status code of the pnp operation.
  4339. // NetPnPEvent - This is a pointer to a NET_PNP_EVENT that describes
  4340. // the PnP indication.
  4341. //
  4342. // Exit:
  4343. // returns nothing.
  4344. //
  4345. void
  4346. __stdcall
  4347. ARPPnPComplete(void *Context, NDIS_STATUS Status, PNET_PNP_EVENT NetPnPEvent)
  4348. {
  4349. ARPInterface *Interface = (ARPInterface *) Context;
  4350. NdisCompletePnPEvent(Status, (Interface ? Interface->ai_handle : NULL), NetPnPEvent);
  4351. }
  4352. extern void NDIS_API ARPBindAdapter(PNDIS_STATUS RetStatus,
  4353. NDIS_HANDLE BindContext,
  4354. PNDIS_STRING AdapterName,
  4355. PVOID SS1, PVOID SS2);
  4356. extern void NDIS_API ARPUnbindAdapter(PNDIS_STATUS RetStatus,
  4357. NDIS_HANDLE ProtBindContext,
  4358. NDIS_HANDLE UnbindContext);
  4359. extern void NDIS_API ARPUnloadProtocol(void);
  4360. extern void ArpUnload(PDRIVER_OBJECT);
  4361. //* ARPReadNext - Read the next entry in the ARP table.
  4362. //
  4363. // Called by the GetInfo code to read the next ATE in the table. We assume
  4364. // the context passed in is valid, and the caller has the ARP TableLock.
  4365. //
  4366. // Input: Context - Pointer to a IPNMEContext.
  4367. // Interface - Pointer to interface for table to read on.
  4368. // Buffer - Pointer to an IPNetToMediaEntry structure.
  4369. //
  4370. // Returns: TRUE if more data is available to be read, FALSE is not.
  4371. //
  4372. uint
  4373. ARPReadNext(void *Context, ARPInterface * Interface, void *Buffer)
  4374. {
  4375. IPNMEContext *NMContext = (IPNMEContext *) Context;
  4376. IPNetToMediaEntry *IPNMEntry = (IPNetToMediaEntry *) Buffer;
  4377. CTELockHandle Handle;
  4378. ARPTableEntry *CurrentATE;
  4379. uint i;
  4380. ARPTable *Table = Interface->ai_ARPTbl;
  4381. uint AddrOffset;
  4382. CurrentATE = NMContext->inc_entry;
  4383. // Fill in the buffer.
  4384. CTEGetLock(&CurrentATE->ate_lock, &Handle);
  4385. IPNMEntry->inme_index = Interface->ai_index;
  4386. IPNMEntry->inme_physaddrlen = Interface->ai_addrlen;
  4387. switch (Interface->ai_media) {
  4388. case NdisMedium802_3:
  4389. AddrOffset = 0;
  4390. break;
  4391. case NdisMedium802_5:
  4392. AddrOffset = offsetof(struct TRHeader, tr_daddr);
  4393. break;
  4394. case NdisMediumFddi:
  4395. AddrOffset = offsetof(struct FDDIHeader, fh_daddr);
  4396. break;
  4397. case NdisMediumArcnet878_2:
  4398. AddrOffset = offsetof(struct ARCNetHeader, ah_daddr);
  4399. break;
  4400. default:
  4401. AddrOffset = 0;
  4402. break;
  4403. }
  4404. RtlCopyMemory(IPNMEntry->inme_physaddr, &CurrentATE->ate_addr[AddrOffset],
  4405. Interface->ai_addrlen);
  4406. IPNMEntry->inme_addr = CurrentATE->ate_dest;
  4407. if (CurrentATE->ate_state == ARP_GOOD)
  4408. IPNMEntry->inme_type = (CurrentATE->ate_valid == ALWAYS_VALID ?
  4409. INME_TYPE_STATIC : INME_TYPE_DYNAMIC);
  4410. else
  4411. IPNMEntry->inme_type = INME_TYPE_INVALID;
  4412. CTEFreeLock(&CurrentATE->ate_lock, Handle);
  4413. // We've filled it in. Now update the context.
  4414. if (CurrentATE->ate_next != NULL) {
  4415. NMContext->inc_entry = CurrentATE->ate_next;
  4416. return TRUE;
  4417. } else {
  4418. // The next ATE is NULL. Loop through the ARP Table looking for a new
  4419. // one.
  4420. i = NMContext->inc_index + 1;
  4421. while (i < ARP_TABLE_SIZE) {
  4422. if ((*Table)[i] != NULL) {
  4423. NMContext->inc_entry = (*Table)[i];
  4424. NMContext->inc_index = i;
  4425. return TRUE;
  4426. break;
  4427. } else
  4428. i++;
  4429. }
  4430. NMContext->inc_index = 0;
  4431. NMContext->inc_entry = NULL;
  4432. return FALSE;
  4433. }
  4434. }
  4435. //* ARPValidateContext - Validate the context for reading an ARP table.
  4436. //
  4437. // Called to start reading an ARP table sequentially. We take in
  4438. // a context, and if the values are 0 we return information about the
  4439. // first route in the table. Otherwise we make sure that the context value
  4440. // is valid, and if it is we return TRUE.
  4441. // We assume the caller holds the ARPInterface lock.
  4442. //
  4443. // Input: Context - Pointer to a RouteEntryContext.
  4444. // Interface - Pointer to an interface
  4445. // Valid - Where to return information about context being
  4446. // valid.
  4447. //
  4448. // Returns: TRUE if more data to be read in table, FALSE if not. *Valid set
  4449. // to TRUE if input context is valid
  4450. //
  4451. uint
  4452. ARPValidateContext(void *Context, ARPInterface * Interface, uint * Valid)
  4453. {
  4454. IPNMEContext *NMContext = (IPNMEContext *) Context;
  4455. uint i;
  4456. ARPTableEntry *TargetATE;
  4457. ARPTableEntry *CurrentATE;
  4458. ARPTable *Table = Interface->ai_ARPTbl;
  4459. i = NMContext->inc_index;
  4460. TargetATE = NMContext->inc_entry;
  4461. // If the context values are 0 and NULL, we're starting from the beginning.
  4462. if (i == 0 && TargetATE == NULL) {
  4463. *Valid = TRUE;
  4464. do {
  4465. if ((CurrentATE = (*Table)[i]) != NULL) {
  4466. break;
  4467. }
  4468. i++;
  4469. } while (i < ARP_TABLE_SIZE);
  4470. if (CurrentATE != NULL) {
  4471. NMContext->inc_index = i;
  4472. NMContext->inc_entry = CurrentATE;
  4473. return TRUE;
  4474. } else
  4475. return FALSE;
  4476. } else {
  4477. // We've been given a context. We just need to make sure that it's
  4478. // valid.
  4479. if (i < ARP_TABLE_SIZE) {
  4480. CurrentATE = (*Table)[i];
  4481. while (CurrentATE != NULL) {
  4482. if (CurrentATE == TargetATE) {
  4483. *Valid = TRUE;
  4484. return TRUE;
  4485. break;
  4486. } else {
  4487. CurrentATE = CurrentATE->ate_next;
  4488. }
  4489. }
  4490. }
  4491. // If we get here, we didn't find the matching ATE.
  4492. *Valid = FALSE;
  4493. return FALSE;
  4494. }
  4495. }
  4496. #define IFE_FIXED_SIZE offsetof(struct IFEntry, if_descr)
  4497. //* ARPQueryInfo - ARP query information handler.
  4498. //
  4499. // Called to query information about the ARP table or statistics about the
  4500. // actual interface.
  4501. //
  4502. // Input: IFContext - Interface context (pointer to an ARPInterface).
  4503. // ID - TDIObjectID for object.
  4504. // Buffer - Buffer to put data into.
  4505. // Size - Pointer to size of buffer. On return, filled with
  4506. // bytes copied.
  4507. // Context - Pointer to context block.
  4508. //
  4509. // Returns: Status of attempt to query information.
  4510. //
  4511. int
  4512. __stdcall
  4513. ARPQueryInfo(void *IFContext, TDIObjectID * ID, PNDIS_BUFFER Buffer, uint * Size,
  4514. void *Context)
  4515. {
  4516. ARPInterface *AI = (ARPInterface *) IFContext;
  4517. uint Offset = 0;
  4518. uint BufferSize = *Size;
  4519. CTELockHandle Handle;
  4520. uint ContextValid, DataLeft;
  4521. uint BytesCopied = 0;
  4522. uchar InfoBuff[sizeof(IFEntry)];
  4523. uint Entity;
  4524. uint Instance;
  4525. BOOLEAN fStatus;
  4526. long QueueLength = 0;
  4527. uint i;
  4528. DEBUGMSG(DBG_TRACE && DBG_QUERYINFO,
  4529. (DTEXT("+ARPQueryInfo(%x, %x, %x, %x, %x)\n"),
  4530. IFContext, ID, Buffer, Size, Context));
  4531. Entity = ID->toi_entity.tei_entity;
  4532. Instance = ID->toi_entity.tei_instance;
  4533. // TCPTRACE(("ARPQueryInfo: AI %lx, Instance %lx, ai_atinst %lx, ai_ifinst %lx\n",
  4534. // AI, Instance, AI->ai_atinst, AI->ai_ifinst ));
  4535. // First, make sure it's possibly an ID we can handle.
  4536. if ((Entity != AT_ENTITY || Instance != AI->ai_atinst) &&
  4537. (Entity != IF_ENTITY || Instance != AI->ai_ifinst)) {
  4538. return TDI_INVALID_REQUEST;
  4539. }
  4540. *Size = 0; // In case of an error.
  4541. if (ID->toi_type != INFO_TYPE_PROVIDER)
  4542. return TDI_INVALID_PARAMETER;
  4543. if (ID->toi_class == INFO_CLASS_GENERIC) {
  4544. if (ID->toi_id == ENTITY_TYPE_ID) {
  4545. // He's trying to see what type we are.
  4546. if (BufferSize >= sizeof(uint)) {
  4547. *(uint *) & InfoBuff[0] = (Entity == AT_ENTITY) ? AT_ARP :
  4548. IF_MIB;
  4549. fStatus = CopyToNdisSafe(Buffer, NULL, InfoBuff, sizeof(uint), &Offset);
  4550. if (fStatus == FALSE) {
  4551. return TDI_NO_RESOURCES;
  4552. }
  4553. *Size = sizeof(uint);
  4554. return TDI_SUCCESS;
  4555. } else
  4556. return TDI_BUFFER_TOO_SMALL;
  4557. }
  4558. return TDI_INVALID_PARAMETER;
  4559. }
  4560. // Might be able to handle this.
  4561. if (Entity == AT_ENTITY) {
  4562. // It's an address translation object. It could be a MIB object or
  4563. // an implementation specific object (the generic objects were handled
  4564. // above).
  4565. if (ID->toi_class == INFO_CLASS_IMPLEMENTATION) {
  4566. ARPPArpAddr *PArpAddr;
  4567. // It's an implementation specific ID. The only ones we handle
  4568. // are the PARP_COUNT_ID and the PARP_ENTRY ID.
  4569. if (ID->toi_id == AT_ARP_PARP_COUNT_ID) {
  4570. // He wants to know the count. Just return that to him.
  4571. if (BufferSize >= sizeof(uint)) {
  4572. CTEGetLock(&AI->ai_lock, &Handle);
  4573. fStatus = CopyToNdisSafe(Buffer, NULL, (uchar *) & AI->ai_parpcount,
  4574. sizeof(uint), &Offset);
  4575. CTEFreeLock(&AI->ai_lock, Handle);
  4576. if (fStatus == FALSE) {
  4577. return TDI_NO_RESOURCES;
  4578. }
  4579. *Size = sizeof(uint);
  4580. return TDI_SUCCESS;
  4581. } else
  4582. return TDI_BUFFER_TOO_SMALL;
  4583. }
  4584. if (ID->toi_id != AT_ARP_PARP_ENTRY_ID)
  4585. return TDI_INVALID_PARAMETER;
  4586. // It's for Proxy ARP entries. The context should be either NULL
  4587. // or a pointer to the next one to be read.
  4588. CTEGetLock(&AI->ai_lock, &Handle);
  4589. PArpAddr = *(ARPPArpAddr **) Context;
  4590. if (PArpAddr != NULL) {
  4591. ARPPArpAddr *CurrentPARP;
  4592. // Loop through the P-ARP addresses on the interface, and
  4593. // see if we can find this one.
  4594. CurrentPARP = AI->ai_parpaddr;
  4595. while (CurrentPARP != NULL) {
  4596. if (CurrentPARP == PArpAddr)
  4597. break;
  4598. else
  4599. CurrentPARP = CurrentPARP->apa_next;
  4600. }
  4601. // If we found a match, PARPAddr points to where to begin
  4602. // reading. Otherwise, fail the request.
  4603. if (CurrentPARP == NULL) {
  4604. // Didn't find a match, so fail the request.
  4605. CTEFreeLock(&AI->ai_lock, Handle);
  4606. return TDI_INVALID_PARAMETER;
  4607. }
  4608. } else
  4609. PArpAddr = AI->ai_parpaddr;
  4610. // PARPAddr points to the next entry to put in the buffer, if
  4611. // there is one.
  4612. while (PArpAddr != NULL) {
  4613. if ((int)(BufferSize - BytesCopied) >=
  4614. (int)sizeof(ProxyArpEntry)) {
  4615. ProxyArpEntry *TempPArp;
  4616. TempPArp = (ProxyArpEntry *) InfoBuff;
  4617. TempPArp->pae_status = PAE_STATUS_VALID;
  4618. TempPArp->pae_addr = PArpAddr->apa_addr;
  4619. TempPArp->pae_mask = PArpAddr->apa_mask;
  4620. BytesCopied += sizeof(ProxyArpEntry);
  4621. fStatus = CopyToNdisSafe(Buffer, &Buffer, (uchar *) TempPArp,
  4622. sizeof(ProxyArpEntry), &Offset);
  4623. if (fStatus == FALSE) {
  4624. CTEFreeLock(&AI->ai_lock, Handle);
  4625. return TDI_NO_RESOURCES;
  4626. }
  4627. PArpAddr = PArpAddr->apa_next;
  4628. } else
  4629. break;
  4630. }
  4631. // We're done copying. Free the lock and return the correct
  4632. // status.
  4633. CTEFreeLock(&AI->ai_lock, Handle);
  4634. *Size = BytesCopied;
  4635. **(ARPPArpAddr ***) & Context = PArpAddr;
  4636. return(PArpAddr == NULL) ? TDI_SUCCESS : TDI_BUFFER_OVERFLOW;
  4637. }
  4638. if (ID->toi_id == AT_MIB_ADDRXLAT_INFO_ID) {
  4639. AddrXlatInfo *AXI;
  4640. // It's for the count. Just return the number of entries in the
  4641. // table.
  4642. if (BufferSize >= sizeof(AddrXlatInfo)) {
  4643. *Size = sizeof(AddrXlatInfo);
  4644. AXI = (AddrXlatInfo *) InfoBuff;
  4645. AXI->axi_count = AI->ai_count;
  4646. AXI->axi_index = AI->ai_index;
  4647. fStatus = CopyToNdisSafe(Buffer, NULL, (uchar *) AXI, sizeof(AddrXlatInfo),
  4648. &Offset);
  4649. if (fStatus == FALSE) {
  4650. return TDI_NO_RESOURCES;
  4651. }
  4652. *Size = sizeof(AddrXlatInfo);
  4653. return TDI_SUCCESS;
  4654. } else
  4655. return TDI_BUFFER_TOO_SMALL;
  4656. }
  4657. if (ID->toi_id == AT_MIB_ADDRXLAT_ENTRY_ID) {
  4658. // He's trying to read the table.
  4659. // Make sure we have a valid context.
  4660. CTEGetLock(&AI->ai_ARPTblLock, &Handle);
  4661. DataLeft = ARPValidateContext(Context, AI, &ContextValid);
  4662. // If the context is valid, we'll continue trying to read.
  4663. if (!ContextValid) {
  4664. CTEFreeLock(&AI->ai_ARPTblLock, Handle);
  4665. return TDI_INVALID_PARAMETER;
  4666. }
  4667. while (DataLeft) {
  4668. // The invariant here is that there is data in the table to
  4669. // read. We may or may not have room for it. So DataLeft
  4670. // is TRUE, and BufferSize - BytesCopied is the room left
  4671. // in the buffer.
  4672. if ((int)(BufferSize - BytesCopied) >=
  4673. (int)sizeof(IPNetToMediaEntry)) {
  4674. DataLeft = ARPReadNext(Context, AI, InfoBuff);
  4675. BytesCopied += sizeof(IPNetToMediaEntry);
  4676. fStatus = CopyToNdisSafe(Buffer, &Buffer, InfoBuff,
  4677. sizeof(IPNetToMediaEntry), &Offset);
  4678. if (fStatus == FALSE) {
  4679. CTEFreeLock(&AI->ai_ARPTblLock, Handle);
  4680. return(TDI_NO_RESOURCES);
  4681. }
  4682. } else
  4683. break;
  4684. }
  4685. *Size = BytesCopied;
  4686. CTEFreeLock(&AI->ai_ARPTblLock, Handle);
  4687. return(!DataLeft ? TDI_SUCCESS : TDI_BUFFER_OVERFLOW);
  4688. }
  4689. return TDI_INVALID_PARAMETER;
  4690. }
  4691. if (ID->toi_class != INFO_CLASS_PROTOCOL)
  4692. return TDI_INVALID_PARAMETER;
  4693. // He must be asking for interface level information. See if we support
  4694. // what he's asking for.
  4695. if (ID->toi_id == IF_MIB_STATS_ID) {
  4696. IFEntry *IFE = (IFEntry *) InfoBuff;
  4697. uint speed;
  4698. // He's asking for statistics. Make sure his buffer is at least big
  4699. // enough to hold the fixed part.
  4700. if (BufferSize < IFE_FIXED_SIZE) {
  4701. return TDI_BUFFER_TOO_SMALL;
  4702. }
  4703. // He's got enough to hold the fixed part. Build the IFEntry structure,
  4704. // and copy it to his buffer.
  4705. IFE->if_index = AI->ai_index;
  4706. switch (AI->ai_media) {
  4707. case NdisMedium802_3:
  4708. IFE->if_type = IF_TYPE_ETHERNET_CSMACD;
  4709. break;
  4710. case NdisMedium802_5:
  4711. IFE->if_type = IF_TYPE_ISO88025_TOKENRING;
  4712. break;
  4713. case NdisMediumFddi:
  4714. IFE->if_type = IF_TYPE_FDDI;
  4715. break;
  4716. case NdisMediumArcnet878_2:
  4717. default:
  4718. IFE->if_type = IF_TYPE_OTHER;
  4719. break;
  4720. }
  4721. IFE->if_mtu = AI->ai_mtu;
  4722. // Some adapters support dynamic speed settings and causes this
  4723. // query to return a different speed from the Networks Connection
  4724. // folder. Therefore, we will requery the speed of the
  4725. // interface. Should we update the ai_speed? Anf if so, do we update
  4726. // if_speed as well?
  4727. IFE->if_speed = AI->ai_speed;
  4728. if (AI->ai_mediastatus == TRUE) {
  4729. if (DoNDISRequest(
  4730. AI,
  4731. NdisRequestQueryInformation,
  4732. OID_GEN_LINK_SPEED,
  4733. &speed,
  4734. sizeof(speed),
  4735. NULL,
  4736. TRUE) == NDIS_STATUS_SUCCESS) {
  4737. // Update to real value we want to return.
  4738. speed *= 100L;
  4739. IFE->if_speed = speed;
  4740. } else {
  4741. // Should we fail, or just update with known speed.
  4742. IFE->if_speed = AI->ai_speed;
  4743. }
  4744. }
  4745. IFE->if_physaddrlen = AI->ai_addrlen;
  4746. RtlCopyMemory(IFE->if_physaddr, AI->ai_addr, AI->ai_addrlen);
  4747. IFE->if_adminstatus = (uint) AI->ai_adminstate;
  4748. if (AI->ai_operstatus == INTERFACE_UP) {
  4749. IFE->if_operstatus = IF_OPER_STATUS_OPERATIONAL;
  4750. } else {
  4751. // DOWN,INIT, and UNINIT all count as non-operational
  4752. IFE->if_operstatus = IF_OPER_STATUS_NON_OPERATIONAL;
  4753. }
  4754. IFE->if_lastchange = AI->ai_lastchange;
  4755. IFE->if_inoctets = AI->ai_inoctets;
  4756. IFE->if_inucastpkts = AI->ai_inpcount[AI_UCAST_INDEX] + AI->ai_inpcount[AI_PROMIS_INDEX];
  4757. IFE->if_innucastpkts = AI->ai_inpcount[AI_NONUCAST_INDEX];
  4758. IFE->if_indiscards = AI->ai_indiscards;
  4759. IFE->if_inerrors = AI->ai_inerrors;
  4760. IFE->if_inunknownprotos = AI->ai_uknprotos;
  4761. IFE->if_outoctets = AI->ai_outoctets;
  4762. IFE->if_outucastpkts = AI->ai_outpcount[AI_UCAST_INDEX];
  4763. IFE->if_outnucastpkts = AI->ai_outpcount[AI_NONUCAST_INDEX];
  4764. IFE->if_outdiscards = AI->ai_outdiscards;
  4765. IFE->if_outerrors = AI->ai_outerrors;
  4766. for (i=0; i < (uint)KeNumberProcessors; i++) {
  4767. QueueLength += AI->ai_qlen[i].ai_qlen;
  4768. }
  4769. IFE->if_outqlen = max(0, QueueLength);
  4770. IFE->if_descrlen = AI->ai_desclen;
  4771. #if FFP_SUPPORT
  4772. // If FFP enabled on this interface, adjust IF stats for FFP'd packets
  4773. if (AI->ai_ffpversion) {
  4774. FFPAdapterStats IFStatsInfo =
  4775. {
  4776. NDIS_PROTOCOL_ID_TCP_IP,
  4777. 0, 0, 0, 0, 0, 0, 0, 0
  4778. };
  4779. // Update ARP SNMP vars to account for FFP'd packets
  4780. if (DoNDISRequest(AI, NdisRequestQueryInformation, OID_FFP_ADAPTER_STATS,
  4781. &IFStatsInfo, sizeof(FFPAdapterStats), NULL, TRUE)
  4782. == NDIS_STATUS_SUCCESS) {
  4783. // Compensate 'inoctets' for packets not seen due to FFP
  4784. IFE->if_inoctets += IFStatsInfo.InOctetsForwarded;
  4785. IFE->if_inoctets += IFStatsInfo.InOctetsDiscarded;
  4786. // Compensate 'inucastpkts' for packets not seen due to FFP
  4787. // Assume all FFP fwded/dropped pkts came in as Eth Unicasts
  4788. // A check to see if it is a ucast or an mcast would slow FFP
  4789. IFE->if_inucastpkts += IFStatsInfo.InPacketsForwarded;
  4790. IFE->if_inucastpkts += IFStatsInfo.InPacketsDiscarded;
  4791. // Compensate 'outoctets' for packets not seen due to FFP
  4792. IFE->if_outoctets += IFStatsInfo.OutOctetsForwarded;
  4793. // Compensate 'outucastpkts' for packets not seen due to FFP
  4794. // Assume all FFP fwded are sent as Ethernet Unicasts
  4795. // A check to see if it is a ucast or an mcast would slow FFP
  4796. IFE->if_outucastpkts += IFStatsInfo.OutPacketsForwarded;
  4797. }
  4798. }
  4799. #endif // if FFP_SUPPORT
  4800. fStatus = CopyToNdisSafe(Buffer, &Buffer, (uchar *) IFE, IFE_FIXED_SIZE, &Offset);
  4801. if (fStatus == FALSE) {
  4802. return TDI_NO_RESOURCES;
  4803. }
  4804. // See if he has room for the descriptor string.
  4805. if (BufferSize >= (IFE_FIXED_SIZE + AI->ai_desclen)) {
  4806. // He has room. Copy it.
  4807. if (AI->ai_desclen != 0) {
  4808. fStatus = CopyToNdisSafe( Buffer, NULL, (PUCHAR) AI->ai_desc,
  4809. AI->ai_desclen, &Offset);
  4810. }
  4811. if (fStatus == FALSE) {
  4812. return TDI_NO_RESOURCES;
  4813. }
  4814. *Size = IFE_FIXED_SIZE + AI->ai_desclen;
  4815. return TDI_SUCCESS;
  4816. } else {
  4817. // Not enough room to copy the desc. string.
  4818. *Size = IFE_FIXED_SIZE;
  4819. return TDI_BUFFER_OVERFLOW;
  4820. }
  4821. } else if (ID->toi_id == IF_FRIENDLY_NAME_ID) {
  4822. int Status;
  4823. PNDIS_BUFFER NextBuffer;
  4824. NDIS_STRING NdisString;
  4825. // This is a query for the adapter's friendly name.
  4826. // We'll convert this to an OID_GEN_FRIENDLY_NAME query for NDIS,
  4827. // and transfer the resulting UNICODE_STRING to the caller's buffer
  4828. // as a nul-terminated Unicode string.
  4829. if (NdisQueryAdapterInstanceName(&NdisString, AI->ai_handle) ==
  4830. NDIS_STATUS_SUCCESS) {
  4831. // Verify that the buffer is large enough for the string we just
  4832. // retrieved and, if so, attempt to copy the string to the
  4833. // caller's buffer. If that succeeds, nul-terminate the resulting
  4834. // string.
  4835. if (BufferSize >= (NdisString.Length + 1) * sizeof(WCHAR)) {
  4836. fStatus = CopyToNdisSafe(Buffer, &NextBuffer,
  4837. (uchar *)NdisString.Buffer,
  4838. NdisString.Length, &Offset);
  4839. if (fStatus) {
  4840. WCHAR Nul = L'\0';
  4841. fStatus = CopyToNdisSafe(Buffer, &NextBuffer, (uchar *)&Nul,
  4842. sizeof(Nul), &Offset);
  4843. if (fStatus) {
  4844. *Size = NdisString.Length + sizeof(Nul);
  4845. Status = TDI_SUCCESS;
  4846. } else
  4847. Status = TDI_NO_RESOURCES;
  4848. } else
  4849. Status = TDI_NO_RESOURCES;
  4850. } else
  4851. Status = TDI_BUFFER_OVERFLOW;
  4852. NdisFreeString(NdisString);
  4853. return Status;
  4854. } else
  4855. return TDI_NO_RESOURCES;
  4856. } else if (ID->toi_id == IF_QUERY_SET_OFFLOAD_ID) {
  4857. IFOffloadCapability IFOC;
  4858. if (BufferSize < sizeof(IFOC)) {
  4859. return TDI_BUFFER_TOO_SMALL;
  4860. }
  4861. if (QueryAndSetOffload(AI)) {
  4862. IFOC.ifoc_OffloadFlags = AI->ai_OffloadFlags;
  4863. IFOC.ifoc_IPSecOffloadFlags = AI->ai_IPSecOffloadFlags;
  4864. if (CopyToNdisSafe(Buffer, NULL, (uchar*)&IFOC, sizeof(IFOC),
  4865. &Offset)) {
  4866. return TDI_SUCCESS;
  4867. }
  4868. }
  4869. return TDI_NO_RESOURCES;
  4870. }
  4871. return TDI_INVALID_PARAMETER;
  4872. }
  4873. //* ARPSetInfo - ARP set information handler.
  4874. //
  4875. // The ARP set information handler. We support setting of an I/F admin
  4876. // status, and setting/deleting of ARP table entries.
  4877. //
  4878. // Input: Context - Pointer to I/F to set on.
  4879. // ID - The object ID
  4880. // Buffer - Pointer to buffer containing value to set.
  4881. // Size - Size in bytes of Buffer.
  4882. //
  4883. // Returns: Status of attempt to set information.
  4884. //
  4885. int
  4886. __stdcall
  4887. ARPSetInfo(void *Context, TDIObjectID * ID, void *Buffer, uint Size)
  4888. {
  4889. ARPInterface *Interface = (ARPInterface *) Context;
  4890. CTELockHandle Handle, EntryHandle;
  4891. int Status;
  4892. IFEntry UNALIGNED *IFE = (IFEntry UNALIGNED *) Buffer;
  4893. IPNetToMediaEntry UNALIGNED *IPNME;
  4894. ARPTableEntry *PrevATE, *CurrentATE;
  4895. ARPTable *Table;
  4896. ENetHeader *Header;
  4897. uint Entity, Instance;
  4898. PNDIS_PACKET Packet;
  4899. Entity = ID->toi_entity.tei_entity;
  4900. Instance = ID->toi_entity.tei_instance;
  4901. // First, make sure it's possibly an ID we can handle.
  4902. if ((Entity != AT_ENTITY || Instance != Interface->ai_atinst) &&
  4903. (Entity != IF_ENTITY || Instance != Interface->ai_ifinst)) {
  4904. return TDI_INVALID_REQUEST;
  4905. }
  4906. if (ID->toi_type != INFO_TYPE_PROVIDER) {
  4907. return TDI_INVALID_PARAMETER;
  4908. }
  4909. // Might be able to handle this.
  4910. if (Entity == IF_ENTITY) {
  4911. // It's for the I/F level, see if it's for the statistics.
  4912. if (ID->toi_class != INFO_CLASS_PROTOCOL)
  4913. return TDI_INVALID_PARAMETER;
  4914. if (ID->toi_id == IF_MIB_STATS_ID) {
  4915. // It's for the stats. Make sure it's a valid size.
  4916. if (Size >= IFE_FIXED_SIZE) {
  4917. // It's a valid size. See what he wants to do.
  4918. CTEGetLock(&Interface->ai_lock, &Handle);
  4919. switch (IFE->if_adminstatus) {
  4920. case IF_STATUS_UP:
  4921. // He's marking it up. If the operational state is
  4922. // alse up, mark the whole interface as up.
  4923. Interface->ai_adminstate = IF_STATUS_UP;
  4924. ARPUpdateOperStatus(Interface);
  4925. Status = TDI_SUCCESS;
  4926. break;
  4927. case IF_STATUS_DOWN:
  4928. // He's taking it down. Mark both the admin state and
  4929. // the interface state down.
  4930. Interface->ai_adminstate = IF_STATUS_DOWN;
  4931. ARPUpdateOperStatus(Interface);
  4932. Status = TDI_SUCCESS;
  4933. break;
  4934. case IF_STATUS_TESTING:
  4935. // He's trying to cause up to do testing, which we
  4936. // don't support. Just return success.
  4937. Status = TDI_SUCCESS;
  4938. break;
  4939. default:
  4940. Status = TDI_INVALID_PARAMETER;
  4941. break;
  4942. }
  4943. CTEFreeLock(&Interface->ai_lock, Handle);
  4944. return Status;
  4945. } else
  4946. return TDI_INVALID_PARAMETER;
  4947. } else {
  4948. return TDI_INVALID_PARAMETER;
  4949. }
  4950. }
  4951. // Not for the interface level. See if it's an implementation or protocol
  4952. // class.
  4953. if (ID->toi_class == INFO_CLASS_IMPLEMENTATION) {
  4954. ProxyArpEntry UNALIGNED *PArpEntry;
  4955. ARPIPAddr *Addr;
  4956. IPAddr AddAddr;
  4957. IPMask Mask;
  4958. // It's for the implementation. It should be the proxy-ARP ID.
  4959. if (ID->toi_id != AT_ARP_PARP_ENTRY_ID || Size < sizeof(ProxyArpEntry))
  4960. return TDI_INVALID_PARAMETER;
  4961. PArpEntry = (ProxyArpEntry UNALIGNED *) Buffer;
  4962. AddAddr = PArpEntry->pae_addr;
  4963. Mask = PArpEntry->pae_mask;
  4964. // See if he's trying to add or delete a proxy arp entry.
  4965. if (PArpEntry->pae_status == PAE_STATUS_VALID) {
  4966. // We're trying to add an entry. We won't allow an entry
  4967. // to be added that we believe to be invalid or conflicting
  4968. // with our local addresses.
  4969. if (!VALID_MASK(Mask))
  4970. return TDI_INVALID_PARAMETER;
  4971. if (!IP_ADDR_EQUAL(AddAddr & Mask, AddAddr) ||
  4972. IP_ADDR_EQUAL(AddAddr, NULL_IP_ADDR) ||
  4973. IP_ADDR_EQUAL(AddAddr, IP_LOCAL_BCST) ||
  4974. IP_LOOPBACK(AddAddr) ||
  4975. CLASSD_ADDR(AddAddr) ||
  4976. CLASSE_ADDR(AddAddr))
  4977. return TDI_INVALID_PARAMETER;
  4978. // Walk through the list of addresses on the interface, and see
  4979. // if they would match the AddAddr. If so, fail the request.
  4980. CTEGetLock(&Interface->ai_lock, &Handle);
  4981. if (IsBCastOnIF(Interface, AddAddr & Mask)) {
  4982. CTEFreeLock(&Interface->ai_lock, Handle);
  4983. return TDI_INVALID_PARAMETER;
  4984. }
  4985. Addr = &Interface->ai_ipaddr;
  4986. do {
  4987. if (!IP_ADDR_EQUAL(Addr->aia_addr, NULL_IP_ADDR)) {
  4988. if (IP_ADDR_EQUAL(Addr->aia_addr & Mask, AddAddr))
  4989. break;
  4990. }
  4991. Addr = Addr->aia_next;
  4992. } while (Addr != NULL);
  4993. CTEFreeLock(&Interface->ai_lock, Handle);
  4994. if (Addr != NULL)
  4995. return TDI_INVALID_PARAMETER;
  4996. // At this point, we believe we're ok. Try to add the address.
  4997. if (ARPAddAddr(Interface, LLIP_ADDR_PARP, AddAddr, Mask, NULL))
  4998. return TDI_SUCCESS;
  4999. else
  5000. return TDI_NO_RESOURCES;
  5001. } else {
  5002. if (PArpEntry->pae_status == PAE_STATUS_INVALID) {
  5003. // He's trying to delete a proxy ARP address.
  5004. if (ARPDeleteAddr(Interface, LLIP_ADDR_PARP, AddAddr, Mask))
  5005. return TDI_SUCCESS;
  5006. }
  5007. return TDI_INVALID_PARAMETER;
  5008. }
  5009. }
  5010. if (ID->toi_class != INFO_CLASS_PROTOCOL) {
  5011. return TDI_INVALID_PARAMETER;
  5012. }
  5013. if (ID->toi_id == AT_MIB_ADDRXLAT_ENTRY_ID &&
  5014. Size >= sizeof(IPNetToMediaEntry)) {
  5015. // He does want to set an ARP table entry. See if he's trying to
  5016. // create or delete one.
  5017. IPNME = (IPNetToMediaEntry UNALIGNED *) Buffer;
  5018. if (IPNME->inme_type == INME_TYPE_INVALID) {
  5019. uint Index = ARP_HASH(IPNME->inme_addr);
  5020. // We're trying to delete an entry. See if we can find it,
  5021. // and then delete it.
  5022. CTEGetLock(&Interface->ai_ARPTblLock, &Handle);
  5023. Table = Interface->ai_ARPTbl;
  5024. PrevATE = STRUCT_OF(ARPTableEntry, &((*Table)[Index]), ate_next);
  5025. CurrentATE = (*Table)[Index];
  5026. while (CurrentATE != (ARPTableEntry *) NULL) {
  5027. if (CurrentATE->ate_dest == IPNME->inme_addr) {
  5028. // Found him. Break out of the loop.
  5029. break;
  5030. } else {
  5031. PrevATE = CurrentATE;
  5032. CurrentATE = CurrentATE->ate_next;
  5033. }
  5034. }
  5035. if (CurrentATE != NULL) {
  5036. CTEGetLock(&CurrentATE->ate_lock, &EntryHandle);
  5037. if (CurrentATE->ate_resolveonly) {
  5038. ARPControlBlock *ArpContB, *TmpArpContB;
  5039. ArpContB = CurrentATE->ate_resolveonly;
  5040. while (ArpContB) {
  5041. ArpRtn rtn;
  5042. rtn = (ArpRtn) ArpContB->CompletionRtn;
  5043. ArpContB->status = (IP_STATUS) STATUS_UNSUCCESSFUL;
  5044. TmpArpContB = ArpContB->next;
  5045. (*rtn) (ArpContB, (IP_STATUS) STATUS_UNSUCCESSFUL);
  5046. ArpContB = TmpArpContB;
  5047. }
  5048. CurrentATE->ate_resolveonly = NULL;
  5049. }
  5050. RemoveARPTableEntry(PrevATE, CurrentATE);
  5051. Interface->ai_count--;
  5052. CTEFreeLockFromDPC(&CurrentATE->ate_lock);
  5053. CTEFreeLock(&Interface->ai_ARPTblLock, Handle);
  5054. if (CurrentATE->ate_packet != NULL) {
  5055. IPSendComplete(Interface->ai_context,
  5056. CurrentATE->ate_packet, NDIS_STATUS_SUCCESS);
  5057. }
  5058. CTEFreeMem(CurrentATE);
  5059. return TDI_SUCCESS;
  5060. } else
  5061. Status = TDI_INVALID_PARAMETER;
  5062. CTEFreeLock(&Interface->ai_ARPTblLock, Handle);
  5063. return Status;
  5064. }
  5065. // We're not trying to delete. See if we're trying to create.
  5066. if (IPNME->inme_type != INME_TYPE_DYNAMIC &&
  5067. IPNME->inme_type != INME_TYPE_STATIC) {
  5068. // Not creating, return an error.
  5069. return TDI_INVALID_PARAMETER;
  5070. }
  5071. // Make sure he's trying to create a valid address.
  5072. if (IPNME->inme_physaddrlen != Interface->ai_addrlen)
  5073. return TDI_INVALID_PARAMETER;
  5074. // We're trying to create an entry. Call CreateARPTableEntry to create
  5075. // one, and fill it in.
  5076. CurrentATE = CreateARPTableEntry(Interface, IPNME->inme_addr, &Handle, 0);
  5077. if (CurrentATE == NULL) {
  5078. return TDI_NO_RESOURCES;
  5079. }
  5080. // We've created or found an entry. Fill it in.
  5081. Header = (ENetHeader *) CurrentATE->ate_addr;
  5082. switch (Interface->ai_media) {
  5083. case NdisMedium802_5:
  5084. {
  5085. TRHeader *Temp = (TRHeader *) Header;
  5086. // Fill in the TR specific parts, and set the length to the
  5087. // size of a TR header.
  5088. Temp->tr_ac = ARP_AC;
  5089. Temp->tr_fc = ARP_FC;
  5090. RtlCopyMemory(&Temp->tr_saddr[ARP_802_ADDR_LENGTH], ARPSNAP,
  5091. sizeof(SNAPHeader));
  5092. Header = (ENetHeader *) & Temp->tr_daddr;
  5093. CurrentATE->ate_addrlength = sizeof(TRHeader) +
  5094. sizeof(SNAPHeader);
  5095. }
  5096. break;
  5097. case NdisMedium802_3:
  5098. CurrentATE->ate_addrlength = sizeof(ENetHeader);
  5099. break;
  5100. case NdisMediumFddi:
  5101. {
  5102. FDDIHeader *Temp = (FDDIHeader *) Header;
  5103. Temp->fh_pri = ARP_FDDI_PRI;
  5104. RtlCopyMemory(&Temp->fh_saddr[ARP_802_ADDR_LENGTH], ARPSNAP,
  5105. sizeof(SNAPHeader));
  5106. Header = (ENetHeader *) & Temp->fh_daddr;
  5107. CurrentATE->ate_addrlength = sizeof(FDDIHeader) +
  5108. sizeof(SNAPHeader);
  5109. }
  5110. break;
  5111. case NdisMediumArcnet878_2:
  5112. {
  5113. ARCNetHeader *Temp = (ARCNetHeader *) Header;
  5114. Temp->ah_saddr = Interface->ai_addr[0];
  5115. Temp->ah_daddr = IPNME->inme_physaddr[0];
  5116. Temp->ah_prot = ARP_ARCPROT_IP;
  5117. CurrentATE->ate_addrlength = sizeof(ARCNetHeader);
  5118. }
  5119. break;
  5120. default:
  5121. ASSERT(0);
  5122. break;
  5123. }
  5124. // Copy in the source and destination addresses.
  5125. if (Interface->ai_media != NdisMediumArcnet878_2) {
  5126. RtlCopyMemory(Header->eh_daddr, IPNME->inme_physaddr,
  5127. ARP_802_ADDR_LENGTH);
  5128. RtlCopyMemory(Header->eh_saddr, Interface->ai_addr,
  5129. ARP_802_ADDR_LENGTH);
  5130. // Now fill in the Ethertype.
  5131. *(ushort *) & CurrentATE->ate_addr[CurrentATE->ate_addrlength - 2] =
  5132. net_short(ARP_ETYPE_IP);
  5133. }
  5134. // If he's creating a static entry, mark it as always valid. Otherwise
  5135. // mark him as valid now.
  5136. if (IPNME->inme_type == INME_TYPE_STATIC)
  5137. CurrentATE->ate_valid = ALWAYS_VALID;
  5138. else
  5139. CurrentATE->ate_valid = CTESystemUpTime();
  5140. CurrentATE->ate_state = ARP_GOOD;
  5141. Packet = CurrentATE->ate_packet;
  5142. CurrentATE->ate_packet = NULL;
  5143. CTEFreeLock(&CurrentATE->ate_lock, Handle);
  5144. if (Packet) {
  5145. IPSendComplete(Interface->ai_context, Packet, NDIS_STATUS_SUCCESS);
  5146. }
  5147. return TDI_SUCCESS;
  5148. }
  5149. return TDI_INVALID_PARAMETER;
  5150. }
  5151. #pragma BEGIN_INIT
  5152. //** ARPInit - Initialize the ARP module.
  5153. //
  5154. // This functions intializes all of the ARP module, including allocating
  5155. // the ARP table and any other necessary data structures.
  5156. //
  5157. // Entry: nothing.
  5158. //
  5159. // Exit: Returns 0 if we fail to init., !0 if we succeed.
  5160. //
  5161. int
  5162. ARPInit()
  5163. {
  5164. NDIS_STATUS Status; // Status for NDIS calls.
  5165. NDIS_PROTOCOL_CHARACTERISTICS Characteristics;
  5166. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("+ARPInit()\n")));
  5167. RtlZeroMemory(&Characteristics, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  5168. Characteristics.MajorNdisVersion = NDIS_MAJOR_VERSION;
  5169. Characteristics.MinorNdisVersion = NDIS_MINOR_VERSION;
  5170. Characteristics.OpenAdapterCompleteHandler = ARPOAComplete;
  5171. Characteristics.CloseAdapterCompleteHandler = ARPCAComplete;
  5172. Characteristics.SendCompleteHandler = ARPSendComplete;
  5173. Characteristics.TransferDataCompleteHandler = ARPTDComplete;
  5174. Characteristics.ResetCompleteHandler = ARPResetComplete;
  5175. Characteristics.RequestCompleteHandler = ARPRequestComplete;
  5176. Characteristics.ReceiveHandler = ARPRcv,
  5177. Characteristics.ReceiveCompleteHandler = ARPRcvComplete;
  5178. Characteristics.StatusHandler = ARPStatus;
  5179. Characteristics.StatusCompleteHandler = ARPStatusComplete;
  5180. //
  5181. // Re-direct to IP since IP now binds to NDIS.
  5182. //
  5183. Characteristics.BindAdapterHandler = IPBindAdapter; // ARPBindAdapter;
  5184. Characteristics.UnbindAdapterHandler = ARPUnbindAdapter;
  5185. Characteristics.PnPEventHandler = ARPPnPEvent;
  5186. #if MILLEN
  5187. Characteristics.UnloadHandler = ARPUnloadProtocol;
  5188. #endif // MILLEN
  5189. RtlInitUnicodeString(&(Characteristics.Name), ARPName);
  5190. Characteristics.ReceivePacketHandler = ARPRcvPacket;
  5191. DEBUGMSG(DBG_INFO && DBG_INIT,
  5192. (DTEXT("ARPInit: Calling NdisRegisterProtocol %d:%d %ws\n"),
  5193. NDIS_MAJOR_VERSION, NDIS_MINOR_VERSION, ARPName));
  5194. NdisRegisterProtocol(&Status, &ARPHandle, (NDIS_PROTOCOL_CHARACTERISTICS *)
  5195. & Characteristics, sizeof(Characteristics));
  5196. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-ARPInit [%x]\n"), Status));
  5197. if (Status == NDIS_STATUS_SUCCESS) {
  5198. return(1);
  5199. } else {
  5200. return(0);
  5201. }
  5202. }
  5203. //* FreeARPInterface - Free an ARP interface
  5204. //
  5205. // Called in the event of some sort of initialization failure. We free all
  5206. // the memory associated with an ARP interface.
  5207. //
  5208. // Entry: Interface - Pointer to interface structure to be freed.
  5209. //
  5210. // Returns: Nothing.
  5211. //
  5212. void
  5213. FreeARPInterface(ARPInterface *Interface)
  5214. {
  5215. NDIS_STATUS Status;
  5216. ARPTable *Table; // ARP table.
  5217. uint i; // Index variable.
  5218. ARPTableEntry *ATE;
  5219. CTELockHandle LockHandle;
  5220. NDIS_HANDLE Handle;
  5221. if (Interface->ai_timerstarted &&
  5222. !CTEStopTimer(&Interface->ai_timer)) {
  5223. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop ai_timer - waiting for event\n"));
  5224. (VOID) CTEBlock(&Interface->ai_timerblock);
  5225. KeClearEvent(&Interface->ai_timerblock.cbs_event);
  5226. }
  5227. // If we're bound to the adapter, close it now.
  5228. CTEInitBlockStruc(&Interface->ai_block);
  5229. CTEGetLock(&Interface->ai_lock, &LockHandle);
  5230. if (Interface->ai_handle != (NDIS_HANDLE) NULL) {
  5231. Handle = Interface->ai_handle;
  5232. Interface->ai_handle = NULL;
  5233. CTEFreeLock(&Interface->ai_lock, LockHandle);
  5234. NdisCloseAdapter(&Status, Handle);
  5235. if (Status == NDIS_STATUS_PENDING)
  5236. Status = CTEBlock(&Interface->ai_block);
  5237. } else {
  5238. CTEFreeLock(&Interface->ai_lock, LockHandle);
  5239. }
  5240. // First free any outstanding ARP table entries.
  5241. Table = Interface->ai_ARPTbl;
  5242. if (Table != NULL) {
  5243. for (i = 0; i < ARP_TABLE_SIZE; i++) {
  5244. while ((*Table)[i] != NULL) {
  5245. ATE = (*Table)[i];
  5246. if (ATE->ate_resolveonly) {
  5247. ARPControlBlock *ArpContB, *TmpArpContB;
  5248. ArpContB = ATE->ate_resolveonly;
  5249. while (ArpContB) {
  5250. ArpRtn rtn;
  5251. rtn = (ArpRtn) ArpContB->CompletionRtn;
  5252. ArpContB->status = (IP_STATUS) STATUS_UNSUCCESSFUL;
  5253. TmpArpContB = ArpContB->next;
  5254. (*rtn) (ArpContB, (IP_STATUS) STATUS_UNSUCCESSFUL);
  5255. ArpContB = TmpArpContB;
  5256. }
  5257. ATE->ate_resolveonly = NULL;
  5258. }
  5259. RemoveARPTableEntry(STRUCT_OF(ARPTableEntry, &((*Table)[i]),
  5260. ate_next), ATE);
  5261. if (ATE->ate_packet) {
  5262. IPSendComplete(Interface->ai_context, ATE->ate_packet,
  5263. NDIS_STATUS_SUCCESS);
  5264. }
  5265. CTEFreeMem(ATE);
  5266. }
  5267. }
  5268. CTEFreeMem(Table);
  5269. }
  5270. Interface->ai_ARPTbl = NULL;
  5271. if (Interface->ai_ppool != (NDIS_HANDLE) NULL)
  5272. NdisFreePacketPool(Interface->ai_ppool);
  5273. if (Interface->ai_qlen) {
  5274. CTEFreeMem(Interface->ai_qlen);
  5275. }
  5276. if (Interface->ai_devicename.Buffer != NULL) {
  5277. CTEFreeMem(Interface->ai_devicename.Buffer);
  5278. }
  5279. if (Interface->ai_desc) {
  5280. CTEFreeMem(Interface->ai_desc);
  5281. }
  5282. // Free the interface itself.
  5283. CTEFreeMem(Interface);
  5284. }
  5285. //** ARPOpen - Open an adapter for reception.
  5286. //
  5287. // This routine is called when the upper layer is done initializing and wishes to
  5288. // begin receiveing packets. The adapter is actually 'open', we just call InitAdapter
  5289. // to set the packet filter and lookahead size.
  5290. //
  5291. // Input: Context - Interface pointer we gave to IP earlier.
  5292. //
  5293. // Returns: Nothing
  5294. //
  5295. void
  5296. __stdcall
  5297. ARPOpen(void *Context)
  5298. {
  5299. ARPInterface *Interface = (ARPInterface *) Context;
  5300. InitAdapter(Interface); // Set the packet filter - we'll begin receiving.
  5301. }
  5302. //* ARPGetEList - Get the entity list.
  5303. //
  5304. // Called at init time to get an entity list. We fill our stuff in, and
  5305. // then call the interfaces below us to allow them to do the same.
  5306. //
  5307. // Input: EntityList - Pointer to entity list to be filled in.
  5308. // Count - Pointer to number of entries in the list.
  5309. //
  5310. // Returns Status of attempt to get the info.
  5311. //
  5312. int
  5313. __stdcall
  5314. ARPGetEList(void *Context, TDIEntityID * EList, uint * Count)
  5315. {
  5316. ARPInterface *Interface = (ARPInterface *) Context;
  5317. uint MyATBase;
  5318. uint MyIFBase;
  5319. uint i;
  5320. TDIEntityID *ATEntity, *IFEntity;
  5321. TDIEntityID *EntityList;
  5322. // Walk down the list, looking for existing AT or IF entities, and
  5323. // adjust our base instance accordingly.
  5324. // if we are already on the list then do nothing.
  5325. // if we are going away, mark our entry invalid.
  5326. EntityList = EList;
  5327. MyATBase = 0;
  5328. MyIFBase = 0;
  5329. ATEntity = NULL;
  5330. IFEntity = NULL;
  5331. for (i = 0; i < *Count; i++, EntityList++) {
  5332. if (EntityList->tei_entity == AT_ENTITY) {
  5333. // if we are already on the list remember our entity item
  5334. // o/w find an instance # for us.
  5335. if (EntityList->tei_instance == Interface->ai_atinst &&
  5336. EntityList->tei_instance != INVALID_ENTITY_INSTANCE) {
  5337. ATEntity = EntityList;
  5338. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - Found our interface %lx at_atinst %lx\n",Interface, Interface->ai_atinst));
  5339. } else {
  5340. MyATBase = MAX(MyATBase, EntityList->tei_instance + 1);
  5341. }
  5342. } else {
  5343. if (EntityList->tei_entity == IF_ENTITY)
  5344. // if we are already on the list remember our entity item
  5345. // o/w find an instance # for us.
  5346. if (EntityList->tei_instance == Interface->ai_ifinst &&
  5347. EntityList->tei_instance != INVALID_ENTITY_INSTANCE) {
  5348. IFEntity = EntityList;
  5349. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - Found our interface %lx ai_ifinst %lx\n",Interface, Interface->ai_ifinst));
  5350. } else {
  5351. MyIFBase = MAX(MyIFBase, EntityList->tei_instance + 1);
  5352. }
  5353. }
  5354. if (ATEntity && IFEntity) {
  5355. break;
  5356. }
  5357. }
  5358. if (ATEntity) {
  5359. // we are already on the list.
  5360. // are we going away?
  5361. if (Interface->ai_operstatus == INTERFACE_UNINIT) {
  5362. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - our interface %lx atinst %lx going away \n",Interface, Interface->ai_atinst));
  5363. ATEntity->tei_instance = (ULONG) INVALID_ENTITY_INSTANCE;
  5364. }
  5365. } else {
  5366. // we are not on the list.
  5367. // insert ourself iff we are not going away.
  5368. if (Interface->ai_operstatus != INTERFACE_UNINIT) {
  5369. // make sure we have the room for it.
  5370. if (*Count >= MAX_TDI_ENTITIES) {
  5371. return FALSE;
  5372. }
  5373. Interface->ai_atinst = MyATBase;
  5374. ATEntity = &EList[*Count];
  5375. ATEntity->tei_entity = AT_ENTITY;
  5376. ATEntity->tei_instance = MyATBase;
  5377. (*Count)++;
  5378. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - adding interface %lx atinst %lx \n",Interface, Interface->ai_atinst));
  5379. }
  5380. }
  5381. if (IFEntity) {
  5382. // we are already on the list.
  5383. // are we going away?
  5384. if (Interface->ai_operstatus == INTERFACE_UNINIT) {
  5385. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - our interface %lx ifinst %lx going away \n",Interface, Interface->ai_ifinst));
  5386. IFEntity->tei_instance = (ULONG) INVALID_ENTITY_INSTANCE;
  5387. }
  5388. } else {
  5389. // we are not on the list.
  5390. // insert ourself iff we are not going away.
  5391. if (Interface->ai_operstatus != INTERFACE_UNINIT) {
  5392. // make sure we have the room for it.
  5393. if (*Count >= MAX_TDI_ENTITIES) {
  5394. return FALSE;
  5395. }
  5396. Interface->ai_ifinst = MyIFBase;
  5397. IFEntity = &EList[*Count];
  5398. IFEntity->tei_entity = IF_ENTITY;
  5399. IFEntity->tei_instance = MyIFBase;
  5400. (*Count)++;
  5401. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetElist - adding interface %lx ifinst %lx \n",Interface, Interface->ai_ifinst));
  5402. }
  5403. }
  5404. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ARPGetEList: arp interface %lx, ai_atinst %lx, ai_ifinst %lx, total %lx\n",
  5405. // Interface, Interface->ai_atinst, Interface->ai_ifinst, *Count));
  5406. return TRUE;
  5407. }
  5408. extern uint UseEtherSNAP(PNDIS_STRING Name);
  5409. extern void GetAlwaysSourceRoute(uint * pArpAlwaysSourceRoute, uint * pIPAlwaysSourceRoute);
  5410. extern uint GetArpCacheLife(void);
  5411. extern uint GetArpRetryCount(void);
  5412. //** InitTaskOffloadHeader - Initializes the task offload header wrt version
  5413. // and encapsulation, etc.
  5414. //
  5415. // All task offload header structure members are initialized.
  5416. //
  5417. // Input:
  5418. // ai - ARPInterface for which we are initializing
  5419. // the task offload header.
  5420. // TaskOffloadHeader - Pointer to task offload header to initialize.
  5421. // Returns:
  5422. // None.
  5423. //
  5424. VOID
  5425. InitTaskOffloadHeader(ARPInterface *ai,
  5426. PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader)
  5427. {
  5428. TaskOffloadHeader->Version = NDIS_TASK_OFFLOAD_VERSION;
  5429. TaskOffloadHeader->Size = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  5430. TaskOffloadHeader->EncapsulationFormat.Flags.FixedHeaderSize = 1;
  5431. TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize = ai->ai_hdrsize;
  5432. TaskOffloadHeader->OffsetFirstTask = 0;
  5433. if (ai->ai_media == NdisMedium802_3) {
  5434. if (ai->ai_snapsize) {
  5435. TaskOffloadHeader->EncapsulationFormat.Encapsulation = LLC_SNAP_ROUTED_Encapsulation;
  5436. TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize += ai->ai_snapsize;
  5437. } else {
  5438. TaskOffloadHeader->EncapsulationFormat.Encapsulation = IEEE_802_3_Encapsulation;
  5439. }
  5440. } else if (ai->ai_media == NdisMedium802_5) {
  5441. TaskOffloadHeader->EncapsulationFormat.Encapsulation = IEEE_802_5_Encapsulation;
  5442. } else {
  5443. TaskOffloadHeader->EncapsulationFormat.Encapsulation = UNSPECIFIED_Encapsulation;
  5444. }
  5445. return;
  5446. }
  5447. //**SetOffload - Set offload capabilities
  5448. //
  5449. //
  5450. // All task offload header structure members are initialized.
  5451. //
  5452. // Input:
  5453. // ai - ARPInterface for which we are initializing
  5454. // the task offload header.
  5455. // TaskOffloadHeader - Pointer to task offload header to initialize.
  5456. // Bufsize - length of task offload buffer allocated by teh caller
  5457. //
  5458. // Returns:
  5459. // TRUE - successfully set the offload capability
  5460. // FALSE - failure case
  5461. //
  5462. BOOLEAN
  5463. SetOffload(ARPInterface *ai,PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader,uint BufSize)
  5464. {
  5465. PNDIS_TASK_OFFLOAD tmpoffload;
  5466. PNDIS_TASK_OFFLOAD TaskOffload, NextTaskOffLoad, LastTaskOffload;
  5467. NDIS_TASK_IPSEC ipsecCaps;
  5468. uint TotalLength;
  5469. NDIS_STATUS Status;
  5470. uint PrevOffLoad=ai->ai_OffloadFlags;
  5471. uint PrevIPSecOffLoad=ai->ai_IPSecOffloadFlags;
  5472. //Parse the buffer for Checksum and tcplargesend offload capabilities
  5473. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Something to Offload. offload buffer size %x\n", BufSize));
  5474. ASSERT(TaskOffloadHeader->OffsetFirstTask == sizeof(NDIS_TASK_OFFLOAD_HEADER));
  5475. TaskOffload = tmpoffload = (NDIS_TASK_OFFLOAD *) ((uchar *) TaskOffloadHeader + TaskOffloadHeader->OffsetFirstTask);
  5476. if (BufSize >= (TaskOffloadHeader->OffsetFirstTask + sizeof(NDIS_TASK_OFFLOAD))) {
  5477. while (tmpoffload) {
  5478. if (tmpoffload->Task == TcpIpChecksumNdisTask) {
  5479. //Okay we this adapter supports checksum offload
  5480. //check if tcp and/or ip chksums bits are present
  5481. PNDIS_TASK_TCP_IP_CHECKSUM ChecksumInfo;
  5482. ChecksumInfo = (PNDIS_TASK_TCP_IP_CHECKSUM) & tmpoffload->TaskBuffer[0];
  5483. //if (ChecksumInfo->V4Transmit.V4Checksum) {
  5484. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"V4 Checksum offload\n"));
  5485. if (ChecksumInfo->V4Transmit.TcpChecksum) {
  5486. ai->ai_OffloadFlags |= TCP_XMT_CHECKSUM_OFFLOAD;
  5487. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," Tcp Checksum offload\n"));
  5488. }
  5489. if (ChecksumInfo->V4Transmit.IpChecksum) {
  5490. ai->ai_OffloadFlags |= IP_XMT_CHECKSUM_OFFLOAD;
  5491. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," IP xmt Checksum offload\n"));
  5492. }
  5493. if (ChecksumInfo->V4Receive.TcpChecksum) {
  5494. ai->ai_OffloadFlags |= TCP_RCV_CHECKSUM_OFFLOAD;
  5495. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," Tcp Rcv Checksum offload\n"));
  5496. }
  5497. if (ChecksumInfo->V4Receive.IpChecksum) {
  5498. ai->ai_OffloadFlags |= IP_RCV_CHECKSUM_OFFLOAD;
  5499. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," IP rcv Checksum offload\n"));
  5500. }
  5501. if (ChecksumInfo->V4Transmit.IpOptionsSupported) {
  5502. ai->ai_OffloadFlags |= IP_CHECKSUM_OPT_OFFLOAD;
  5503. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," IP Checksum xmt options offload\n"));
  5504. }
  5505. if (ChecksumInfo->V4Transmit.TcpOptionsSupported) {
  5506. ai->ai_OffloadFlags |= TCP_CHECKSUM_OPT_OFFLOAD;
  5507. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," TCP Checksum xmt options offload\n"));
  5508. }
  5509. } else if ((tmpoffload->Task == TcpLargeSendNdisTask) && (ai->ai_snapsize == 0)) {
  5510. PNDIS_TASK_TCP_LARGE_SEND TcpLargeSend, in_LargeSend = (PNDIS_TASK_TCP_LARGE_SEND) & tmpoffload->TaskBuffer[0];
  5511. TcpLargeSend = &ai->ai_TcpLargeSend;
  5512. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," Tcp large send!! \n"));
  5513. TcpLargeSend->MaxOffLoadSize = in_LargeSend->MaxOffLoadSize;
  5514. TcpLargeSend->MinSegmentCount = in_LargeSend->MinSegmentCount;
  5515. //
  5516. // If MaxOffLoadSize is zero, reject this request.
  5517. //
  5518. if (TcpLargeSend->MaxOffLoadSize) {
  5519. ai->ai_OffloadFlags |= TCP_LARGE_SEND_OFFLOAD;
  5520. // no tcp or ip options when doing large send
  5521. // Need to reevaluate this as we turn on Time stamp option.
  5522. if (in_LargeSend->TcpOptions) {
  5523. ai->ai_OffloadFlags |= TCP_LARGE_SEND_TCPOPT_OFFLOAD;
  5524. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," TCP largesend options offload\n"));
  5525. }
  5526. if (in_LargeSend->IpOptions) {
  5527. ai->ai_OffloadFlags |= TCP_LARGE_SEND_IPOPT_OFFLOAD;
  5528. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL," IP largesend options offload\n"));
  5529. }
  5530. }
  5531. } else if (tmpoffload->Task == IpSecNdisTask) {
  5532. PNDIS_TASK_IPSEC pIPSecCaps = (PNDIS_TASK_IPSEC) & tmpoffload->TaskBuffer[0];
  5533. //
  5534. // Save off the capabilities for setting them later.
  5535. //
  5536. ipsecCaps = *pIPSecCaps;
  5537. //
  5538. // CryptoOnly is assumed if we have IpSecNdisTask
  5539. //
  5540. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_CRYPTO_ONLY;
  5541. //
  5542. // Do Support first
  5543. //
  5544. if (pIPSecCaps->Supported.AH_ESP_COMBINED) {
  5545. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_ESP;
  5546. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"AH_ESP\n"));
  5547. }
  5548. if (pIPSecCaps->Supported.TRANSPORT_TUNNEL_COMBINED) {
  5549. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_TUNNEL;
  5550. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TPT_TUNNEL\n"));
  5551. }
  5552. if (pIPSecCaps->Supported.V4_OPTIONS) {
  5553. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_V4_OPTIONS;
  5554. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"V4_OPTIONS\n"));
  5555. }
  5556. if (pIPSecCaps->Supported.RESERVED) {
  5557. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPT_UDPESP_ENCAPTYPE_IKE) {
  5558. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_UDPESP_IKE;
  5559. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_UDPESP_IKE\n"));
  5560. }
  5561. if (pIPSecCaps->Supported.RESERVED & IPSEC_TUN_UDPESP_ENCAPTYPE_IKE) {
  5562. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TUNNEL_UDPESP_IKE;
  5563. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TUNNEL_UDPESP_IKE\n"));
  5564. }
  5565. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPTOVERTUN_UDPESP_ENCAPTYPE_IKE) {
  5566. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_IKE;
  5567. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_IKE\n"));
  5568. }
  5569. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPT_UDPESP_OVER_PURE_TUN_ENCAPTYPE_IKE) {
  5570. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_IKE;
  5571. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_IKE\n"));
  5572. }
  5573. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPT_UDPESP_ENCAPTYPE_OTHER) {
  5574. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_UDPESP_OTHER;
  5575. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_UDPESP_OTHER\n"));
  5576. }
  5577. if (pIPSecCaps->Supported.RESERVED & IPSEC_TUN_UDPESP_ENCAPTYPE_OTHER) {
  5578. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TUNNEL_UDPESP_OTHER;
  5579. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TUNNEL_UDPESP_OTHER\n"));
  5580. }
  5581. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPTOVERTUN_UDPESP_ENCAPTYPE_OTHER) {
  5582. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_OTHER;
  5583. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_OTHER\n"));
  5584. }
  5585. if (pIPSecCaps->Supported.RESERVED & IPSEC_TPT_UDPESP_OVER_PURE_TUN_ENCAPTYPE_OTHER) {
  5586. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_OTHER;
  5587. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_OTHER\n"));
  5588. }
  5589. }
  5590. //
  5591. // Do V4AH next
  5592. //
  5593. if (pIPSecCaps->V4AH.MD5) {
  5594. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_MD5;
  5595. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"MD5\n"));
  5596. }
  5597. if (pIPSecCaps->V4AH.SHA_1) {
  5598. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_SHA_1;
  5599. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"SHA\n"));
  5600. }
  5601. if (pIPSecCaps->V4AH.Transport) {
  5602. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_TPT;
  5603. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"AH_TRANSPORT\n"));
  5604. }
  5605. if (pIPSecCaps->V4AH.Tunnel) {
  5606. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_TUNNEL;
  5607. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"AH_TUNNEL\n"));
  5608. }
  5609. if (pIPSecCaps->V4AH.Send) {
  5610. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_XMT;
  5611. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"AH_XMT\n"));
  5612. }
  5613. if (pIPSecCaps->V4AH.Receive) {
  5614. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_AH_RCV;
  5615. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"AH_RCV\n"));
  5616. }
  5617. //
  5618. // Do V4ESP next
  5619. //
  5620. if (pIPSecCaps->V4ESP.DES) {
  5621. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_DES;
  5622. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_DES\n"));
  5623. }
  5624. if (pIPSecCaps->V4ESP.RESERVED) {
  5625. pIPSecCaps->V4ESP.RESERVED = 0;
  5626. //ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_DES_40;
  5627. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_DES_40\n"));
  5628. }
  5629. if (pIPSecCaps->V4ESP.TRIPLE_DES) {
  5630. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_3_DES;
  5631. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_3_DES\n"));
  5632. }
  5633. if (pIPSecCaps->V4ESP.NULL_ESP) {
  5634. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_NONE;
  5635. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_NONE\n"));
  5636. }
  5637. if (pIPSecCaps->V4ESP.Transport) {
  5638. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_TPT;
  5639. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_TRANSPORT\n"));
  5640. }
  5641. if (pIPSecCaps->V4ESP.Tunnel) {
  5642. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_TUNNEL;
  5643. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_TUNNEL\n"));
  5644. }
  5645. if (pIPSecCaps->V4ESP.Send) {
  5646. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_XMT;
  5647. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_XMT\n"));
  5648. }
  5649. if (pIPSecCaps->V4ESP.Receive) {
  5650. ai->ai_IPSecOffloadFlags |= IPSEC_OFFLOAD_ESP_RCV;
  5651. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"ESP_RCV\n"));
  5652. }
  5653. }
  5654. // Point to the next offload structure
  5655. if (tmpoffload->OffsetNextTask) {
  5656. tmpoffload = (PNDIS_TASK_OFFLOAD)
  5657. ((PUCHAR) tmpoffload + tmpoffload->OffsetNextTask);
  5658. } else {
  5659. tmpoffload = NULL;
  5660. }
  5661. } //while
  5662. } else { //if BufSize is not okay
  5663. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"response of task offload does not have sufficient space even for 1 offload task!!\n"));
  5664. return FALSE;
  5665. }
  5666. // Enable the capabilities by setting them.
  5667. if (PrevOffLoad) {
  5668. ai->ai_OffloadFlags &= PrevOffLoad;
  5669. }
  5670. if (PrevIPSecOffLoad) {
  5671. ai->ai_IPSecOffloadFlags &= PrevIPSecOffLoad;
  5672. }
  5673. TaskOffload->Task = 0;
  5674. TaskOffload->OffsetNextTask = 0;
  5675. NextTaskOffLoad = LastTaskOffload = TaskOffload;
  5676. TotalLength = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  5677. if ((ai->ai_OffloadFlags & TCP_XMT_CHECKSUM_OFFLOAD) ||
  5678. (ai->ai_OffloadFlags & IP_XMT_CHECKSUM_OFFLOAD) ||
  5679. (ai->ai_OffloadFlags & TCP_RCV_CHECKSUM_OFFLOAD) ||
  5680. (ai->ai_OffloadFlags & IP_RCV_CHECKSUM_OFFLOAD)) {
  5681. PNDIS_TASK_TCP_IP_CHECKSUM ChksumBuf = (PNDIS_TASK_TCP_IP_CHECKSUM) & NextTaskOffLoad->TaskBuffer[0];
  5682. NextTaskOffLoad->Task = TcpIpChecksumNdisTask;
  5683. NextTaskOffLoad->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  5684. NextTaskOffLoad->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
  5685. NextTaskOffLoad->TaskBufferLength;
  5686. TotalLength += NextTaskOffLoad->OffsetNextTask;
  5687. RtlZeroMemory(ChksumBuf, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
  5688. if (ai->ai_OffloadFlags & TCP_XMT_CHECKSUM_OFFLOAD) {
  5689. ChksumBuf->V4Transmit.TcpChecksum = 1;
  5690. }
  5691. if (ai->ai_OffloadFlags & IP_XMT_CHECKSUM_OFFLOAD) {
  5692. ChksumBuf->V4Transmit.IpChecksum = 1;
  5693. }
  5694. if (ai->ai_OffloadFlags & TCP_RCV_CHECKSUM_OFFLOAD) {
  5695. ChksumBuf->V4Receive.TcpChecksum = 1;
  5696. }
  5697. if (ai->ai_OffloadFlags & IP_RCV_CHECKSUM_OFFLOAD) {
  5698. ChksumBuf->V4Receive.IpChecksum = 1;
  5699. }
  5700. //
  5701. // Enable Options capability if present.
  5702. //
  5703. if (ai->ai_OffloadFlags & IP_CHECKSUM_OPT_OFFLOAD) {
  5704. ChksumBuf->V4Transmit.IpOptionsSupported = 1;
  5705. }
  5706. if (ai->ai_OffloadFlags & TCP_CHECKSUM_OPT_OFFLOAD) {
  5707. ChksumBuf->V4Transmit.TcpOptionsSupported = 1;
  5708. }
  5709. LastTaskOffload = NextTaskOffLoad;
  5710. NextTaskOffLoad = (PNDIS_TASK_OFFLOAD)
  5711. ((PUCHAR) NextTaskOffLoad + NextTaskOffLoad->OffsetNextTask);
  5712. }
  5713. if (ai->ai_OffloadFlags & TCP_LARGE_SEND_OFFLOAD) {
  5714. PNDIS_TASK_TCP_LARGE_SEND TcpLargeSend, out_LargeSend = (PNDIS_TASK_TCP_LARGE_SEND) & NextTaskOffLoad->TaskBuffer[0];
  5715. NextTaskOffLoad->Task = TcpLargeSendNdisTask;
  5716. NextTaskOffLoad->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
  5717. NextTaskOffLoad->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + NextTaskOffLoad->TaskBufferLength;
  5718. TotalLength += NextTaskOffLoad->OffsetNextTask;
  5719. //(uchar)TaskOffload + sizeof(NDIS_TASK_OFFLOAD) + NextTaskOffload->TaskBufferLength;
  5720. TcpLargeSend = &ai->ai_TcpLargeSend;
  5721. RtlZeroMemory(out_LargeSend, sizeof(NDIS_TASK_TCP_LARGE_SEND));
  5722. out_LargeSend->MaxOffLoadSize = TcpLargeSend->MaxOffLoadSize;
  5723. out_LargeSend->MinSegmentCount = TcpLargeSend->MinSegmentCount;
  5724. if (ai->ai_OffloadFlags & TCP_LARGE_SEND_TCPOPT_OFFLOAD) {
  5725. out_LargeSend->TcpOptions = 1;
  5726. }
  5727. if (ai->ai_OffloadFlags & TCP_LARGE_SEND_IPOPT_OFFLOAD) {
  5728. out_LargeSend->IpOptions = 1;
  5729. }
  5730. LastTaskOffload = NextTaskOffLoad;
  5731. NextTaskOffLoad = (PNDIS_TASK_OFFLOAD)
  5732. ((PUCHAR) NextTaskOffLoad + NextTaskOffLoad->OffsetNextTask);
  5733. }
  5734. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_CRYPTO_ONLY) {
  5735. PNDIS_TASK_IPSEC pIPSecCaps = (PNDIS_TASK_IPSEC) & NextTaskOffLoad->TaskBuffer[0];
  5736. //
  5737. // plunk down the advertised capabilities
  5738. //
  5739. RtlZeroMemory(pIPSecCaps, sizeof(NDIS_TASK_IPSEC));
  5740. NextTaskOffLoad->Task = IpSecNdisTask;
  5741. NextTaskOffLoad->TaskBufferLength = sizeof(NDIS_TASK_IPSEC);
  5742. NextTaskOffLoad->OffsetNextTask = (FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + NextTaskOffLoad->TaskBufferLength);
  5743. TotalLength += NextTaskOffLoad->OffsetNextTask;
  5744. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_ESP) {
  5745. pIPSecCaps->Supported.AH_ESP_COMBINED = 1;
  5746. }
  5747. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_TUNNEL) {
  5748. pIPSecCaps->Supported.TRANSPORT_TUNNEL_COMBINED = 1;
  5749. }
  5750. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_V4_OPTIONS) {
  5751. pIPSecCaps->Supported.V4_OPTIONS = 1;
  5752. }
  5753. pIPSecCaps->Supported.RESERVED = 0;
  5754. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_UDPESP_IKE) {
  5755. pIPSecCaps->Supported.RESERVED |= IPSEC_TPT_UDPESP_ENCAPTYPE_IKE;
  5756. }
  5757. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TUNNEL_UDPESP_IKE) {
  5758. pIPSecCaps->Supported.RESERVED |= IPSEC_TUN_UDPESP_ENCAPTYPE_IKE;
  5759. }
  5760. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_IKE) {
  5761. pIPSecCaps->Supported.RESERVED |= IPSEC_TPTOVERTUN_UDPESP_ENCAPTYPE_IKE;
  5762. }
  5763. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_IKE) {
  5764. pIPSecCaps->Supported.RESERVED |= IPSEC_TPT_UDPESP_OVER_PURE_TUN_ENCAPTYPE_IKE;
  5765. }
  5766. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_UDPESP_OTHER) {
  5767. pIPSecCaps->Supported.RESERVED |= IPSEC_TPT_UDPESP_ENCAPTYPE_OTHER;
  5768. }
  5769. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TUNNEL_UDPESP_OTHER) {
  5770. pIPSecCaps->Supported.RESERVED |= IPSEC_TUN_UDPESP_ENCAPTYPE_OTHER;
  5771. }
  5772. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_OVER_TUNNEL_UDPESP_OTHER) {
  5773. pIPSecCaps->Supported.RESERVED |= IPSEC_TPTOVERTUN_UDPESP_ENCAPTYPE_OTHER;
  5774. }
  5775. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_UDPESP_OVER_PURE_TUNNEL_OTHER) {
  5776. pIPSecCaps->Supported.RESERVED |= IPSEC_TPT_UDPESP_OVER_PURE_TUN_ENCAPTYPE_OTHER;
  5777. }
  5778. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_MD5) {
  5779. pIPSecCaps->V4AH.MD5 = 1;
  5780. }
  5781. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_SHA_1) {
  5782. pIPSecCaps->V4AH.SHA_1 = 1;
  5783. }
  5784. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TPT) {
  5785. pIPSecCaps->V4AH.Transport = 1;
  5786. }
  5787. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TUNNEL) {
  5788. pIPSecCaps->V4AH.Tunnel = 1;
  5789. }
  5790. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_XMT) {
  5791. pIPSecCaps->V4AH.Send = 1;
  5792. }
  5793. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_RCV) {
  5794. pIPSecCaps->V4AH.Receive = 1;
  5795. }
  5796. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_DES) {
  5797. pIPSecCaps->V4ESP.DES = 1;
  5798. }
  5799. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_3_DES) {
  5800. pIPSecCaps->V4ESP.TRIPLE_DES = 1;
  5801. }
  5802. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_NONE) {
  5803. pIPSecCaps->V4ESP.NULL_ESP = 1;
  5804. }
  5805. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TPT) {
  5806. pIPSecCaps->V4ESP.Transport = 1;
  5807. }
  5808. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TUNNEL) {
  5809. pIPSecCaps->V4ESP.Tunnel = 1;
  5810. }
  5811. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_XMT) {
  5812. pIPSecCaps->V4ESP.Send = 1;
  5813. }
  5814. if (ai->ai_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_RCV) {
  5815. pIPSecCaps->V4ESP.Receive = 1;
  5816. }
  5817. LastTaskOffload = NextTaskOffLoad;
  5818. NextTaskOffLoad = (PNDIS_TASK_OFFLOAD)
  5819. ((PUCHAR) NextTaskOffLoad + NextTaskOffLoad->OffsetNextTask);
  5820. }
  5821. LastTaskOffload->OffsetNextTask = 0;
  5822. // Okay, lets set this now.
  5823. Status = DoNDISRequest(ai, NdisRequestSetInformation,
  5824. OID_TCP_TASK_OFFLOAD, TaskOffloadHeader, TotalLength,
  5825. NULL, TRUE);
  5826. if (Status != NDIS_STATUS_SUCCESS) {
  5827. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  5828. "Failed to enable indicated offload capabilities!!\n"));
  5829. ai->ai_OffloadFlags = 0;
  5830. ai->ai_IPSecOffloadFlags = 0;
  5831. }
  5832. return TRUE;
  5833. }
  5834. //**QueryOffload - Query offload capabilities
  5835. //
  5836. // Input:
  5837. // ai - ARPInterface for which we are initializing
  5838. // the task offload header.
  5839. // Returns:
  5840. // TRUE/FALSE - Success/Failure to query/set
  5841. //
  5842. BOOLEAN
  5843. QueryAndSetOffload(ARPInterface *ai)
  5844. {
  5845. PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader;
  5846. NDIS_STATUS Status;
  5847. BOOLEAN stat;
  5848. uint Needed = 0;
  5849. uchar *buffer;
  5850. // Query and set checksum capability
  5851. TaskOffloadHeader = CTEAllocMemNBoot(sizeof(NDIS_TASK_OFFLOAD_HEADER), '8ICT');
  5852. Status = STATUS_BUFFER_OVERFLOW;
  5853. if (TaskOffloadHeader) {
  5854. InitTaskOffloadHeader(ai, TaskOffloadHeader);
  5855. Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  5856. OID_TCP_TASK_OFFLOAD, TaskOffloadHeader,
  5857. sizeof(NDIS_TASK_OFFLOAD_HEADER),
  5858. &Needed, TRUE);
  5859. // Need to initialize Needed to the real size of the buffer. The NDIS
  5860. // call may not init on success.
  5861. if (Status == NDIS_STATUS_SUCCESS) {
  5862. Needed = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  5863. } else if ((Status == NDIS_STATUS_INVALID_LENGTH) ||
  5864. (Status == NDIS_STATUS_BUFFER_TOO_SHORT)) {
  5865. // We know the size we need. Allocate a buffer.
  5866. ASSERT(Needed >= sizeof(NDIS_TASK_OFFLOAD_HEADER));
  5867. buffer = CTEAllocMemNBoot(Needed, '9ICT');
  5868. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  5869. "Calling OID_TCP_TASK_OFFLOAD with %d bytes\n", Needed));
  5870. if (buffer != NULL) {
  5871. CTEFreeMem(TaskOffloadHeader);
  5872. TaskOffloadHeader = (PNDIS_TASK_OFFLOAD_HEADER) buffer;
  5873. InitTaskOffloadHeader(ai, TaskOffloadHeader);
  5874. Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  5875. OID_TCP_TASK_OFFLOAD, buffer, Needed, NULL, TRUE);
  5876. }
  5877. }
  5878. }
  5879. if ((Status != NDIS_STATUS_SUCCESS)
  5880. || (TaskOffloadHeader && TaskOffloadHeader->OffsetFirstTask == 0)) {
  5881. //Make sure that the flag is null.
  5882. ai->ai_OffloadFlags = 0;
  5883. ai->ai_IPSecOffloadFlags = 0;
  5884. if (TaskOffloadHeader) {
  5885. CTEFreeMem(TaskOffloadHeader);
  5886. }
  5887. return FALSE;
  5888. }
  5889. if (TaskOffloadHeader) {
  5890. stat = SetOffload(ai, TaskOffloadHeader, Needed);
  5891. CTEFreeMem(TaskOffloadHeader);
  5892. return stat;
  5893. }
  5894. return FALSE;
  5895. }
  5896. //** ARPRegister - Register a protocol with the ARP module.
  5897. //
  5898. // We register a protocol for ARP processing. We also open the
  5899. // NDIS adapter here.
  5900. //
  5901. // Note that much of the information passed in here is unused, as
  5902. // ARP currently only works with IP.
  5903. //
  5904. // Entry:
  5905. // Adapter - Name of the adapter to bind to.
  5906. // IPContext - Value to be passed to IP on upcalls.
  5907. //
  5908. int
  5909. ARPRegister(PNDIS_STRING Adapter, uint *Flags, struct ARPInterface **Interface)
  5910. {
  5911. ARPInterface *ai; // Pointer to interface struct. for this interface.
  5912. NDIS_STATUS Status, OpenStatus; // Status values.
  5913. uint i = 0; // Medium index.
  5914. NDIS_MEDIUM MediaArray[MAX_MEDIA];
  5915. uint mss;
  5916. uint speed;
  5917. uint MacOpts;
  5918. uchar bcastmask, bcastval, bcastoff, addrlen, hdrsize, snapsize;
  5919. uint OID;
  5920. uint PF;
  5921. TRANSPORT_HEADER_OFFSET IPHdrOffset;
  5922. CTELockHandle LockHandle;
  5923. UINT MediaType;
  5924. NDIS_STRING NdisString;
  5925. DEBUGMSG(DBG_TRACE && DBG_PNP,
  5926. (DTEXT("+ARPRegister(%x, %x, %x)\n"),
  5927. Adapter, Flags, Interface));
  5928. if ((ai = CTEAllocMemNBoot(sizeof(ARPInterface), '4ICT')) == (ARPInterface *) NULL)
  5929. return FALSE; // Couldn't allocate memory for this one.
  5930. *Interface = ai;
  5931. RtlZeroMemory(ai, sizeof(ARPInterface));
  5932. CTEInitTimer(&ai->ai_timer);
  5933. ai->ai_timerstarted = FALSE;
  5934. ai->ai_stoptimer = FALSE;
  5935. MediaArray[MEDIA_DIX] = NdisMedium802_3;
  5936. MediaArray[MEDIA_TR] = NdisMedium802_5;
  5937. MediaArray[MEDIA_FDDI] = NdisMediumFddi;
  5938. MediaArray[MEDIA_ARCNET] = NdisMediumArcnet878_2;
  5939. // Initialize this adapter interface structure.
  5940. ai->ai_operstatus = INTERFACE_INIT;
  5941. ai->ai_adminstate = IF_STATUS_UNKNOWN;
  5942. ai->ai_mediastatus = FALSE;
  5943. ai->ai_lastchange = GetTimeTicks();
  5944. ai->ai_bcast = IP_LOCAL_BCST;
  5945. ai->ai_atinst = ai->ai_ifinst = (UINT)INVALID_ENTITY_INSTANCE;
  5946. ai->ai_telladdrchng = 1; //Initially let us do try to do network layer address stuff
  5947. // Initialize the locks.
  5948. CTEInitLock(&ai->ai_lock);
  5949. CTEInitLock(&ai->ai_ARPTblLock);
  5950. GetAlwaysSourceRoute(&sArpAlwaysSourceRoute, &sIPAlwaysSourceRoute);
  5951. ArpCacheLife = GetArpCacheLife();
  5952. if (!ArpCacheLife) {
  5953. ArpCacheLife = 1;
  5954. }
  5955. ArpCacheLife = (ArpCacheLife * 1000L) / ARP_TIMER_TIME;
  5956. ArpRetryCount = GetArpRetryCount();
  5957. if (!ArpMinValidCacheLife) {
  5958. ArpMinValidCacheLife = 1;
  5959. }
  5960. // Allocate the buffer and packet pools.
  5961. NdisAllocatePacketPoolEx(&Status, &ai->ai_ppool,
  5962. ARP_DEFAULT_PACKETS, ARP_DEFAULT_PACKETS * 1000,
  5963. sizeof(struct PCCommon));
  5964. if (Status != NDIS_STATUS_SUCCESS) {
  5965. FreeARPInterface(ai);
  5966. return FALSE;
  5967. }
  5968. // Allocate the ARP table
  5969. ai->ai_ARPTbl = (ARPTable *) CTEAllocMemNBoot(ARP_TABLE_SIZE * sizeof(ARPTableEntry*), '5ICT');
  5970. if (ai->ai_ARPTbl == (ARPTable *) NULL) {
  5971. FreeARPInterface(ai);
  5972. return FALSE;
  5973. }
  5974. //
  5975. // NULL out the pointers
  5976. //
  5977. RtlZeroMemory(ai->ai_ARPTbl, ARP_TABLE_SIZE * sizeof(ARPTableEntry *));
  5978. // Allocate the Counters Structure with best effort in avoiding false sharing
  5979. ai->ai_qlen = CTEAllocMem(KeNumberProcessors * sizeof(PP_AI_COUNTERS));
  5980. if (ai->ai_qlen == (PPP_AI_COUNTERS) NULL) {
  5981. FreeARPInterface(ai);
  5982. return FALSE;
  5983. }
  5984. RtlZeroMemory(ai->ai_qlen, KeNumberProcessors * sizeof(PP_AI_COUNTERS));
  5985. CTEInitBlockStruc(&ai->ai_block);
  5986. DEBUGMSG(DBG_INFO && DBG_PNP,
  5987. (DTEXT("ARPRegister calling NdisOpenAdapter\n")));
  5988. // Open the NDIS adapter.
  5989. NdisOpenAdapter(&Status, &OpenStatus, &ai->ai_handle, &i, MediaArray,
  5990. MAX_MEDIA, ARPHandle, ai, Adapter, 0, NULL);
  5991. // Block for open to complete.
  5992. if (Status == NDIS_STATUS_PENDING)
  5993. Status = (NDIS_STATUS) CTEBlock(&ai->ai_block);
  5994. ai->ai_media = MediaArray[i]; // Fill in media type.
  5995. // Open adapter completed. If it succeeded, we'll finish our intialization.
  5996. // If it failed, bail out now.
  5997. if (Status != NDIS_STATUS_SUCCESS) {
  5998. ai->ai_handle = NULL;
  5999. FreeARPInterface(ai);
  6000. return FALSE;
  6001. }
  6002. #if FFP_SUPPORT
  6003. // Store NIC driver handle
  6004. NdisGetDriverHandle(ai->ai_handle, &ai->ai_driver);
  6005. #endif
  6006. // Read the local address.
  6007. switch (ai->ai_media) {
  6008. case NdisMedium802_3:
  6009. addrlen = ARP_802_ADDR_LENGTH;
  6010. bcastmask = ENET_BCAST_MASK;
  6011. bcastval = ENET_BCAST_VAL;
  6012. bcastoff = ENET_BCAST_OFF;
  6013. OID = OID_802_3_CURRENT_ADDRESS;
  6014. hdrsize = sizeof(ENetHeader);
  6015. if (!UseEtherSNAP(Adapter)) {
  6016. snapsize = 0;
  6017. } else {
  6018. snapsize = sizeof(SNAPHeader);
  6019. }
  6020. PF = NDIS_PACKET_TYPE_BROADCAST | \
  6021. NDIS_PACKET_TYPE_DIRECTED | \
  6022. NDIS_PACKET_TYPE_MULTICAST;
  6023. ai->ai_mediatype = IF_TYPE_IS088023_CSMACD;
  6024. break;
  6025. case NdisMedium802_5:
  6026. addrlen = ARP_802_ADDR_LENGTH;
  6027. bcastmask = TR_BCAST_MASK;
  6028. bcastval = TR_BCAST_VAL;
  6029. bcastoff = TR_BCAST_OFF;
  6030. OID = OID_802_5_CURRENT_ADDRESS;
  6031. hdrsize = sizeof(TRHeader);
  6032. snapsize = sizeof(SNAPHeader);
  6033. PF = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED;
  6034. ai->ai_mediatype = IF_TYPE_ISO88025_TOKENRING;
  6035. break;
  6036. case NdisMediumFddi:
  6037. addrlen = ARP_802_ADDR_LENGTH;
  6038. bcastmask = FDDI_BCAST_MASK;
  6039. bcastval = FDDI_BCAST_VAL;
  6040. bcastoff = FDDI_BCAST_OFF;
  6041. OID = OID_FDDI_LONG_CURRENT_ADDR;
  6042. hdrsize = sizeof(FDDIHeader);
  6043. snapsize = sizeof(SNAPHeader);
  6044. PF = NDIS_PACKET_TYPE_BROADCAST | \
  6045. NDIS_PACKET_TYPE_DIRECTED | \
  6046. NDIS_PACKET_TYPE_MULTICAST;
  6047. ai->ai_mediatype = IF_TYPE_FDDI;
  6048. break;
  6049. case NdisMediumArcnet878_2:
  6050. addrlen = 1;
  6051. bcastmask = ARC_BCAST_MASK;
  6052. bcastval = ARC_BCAST_VAL;
  6053. bcastoff = ARC_BCAST_OFF;
  6054. OID = OID_ARCNET_CURRENT_ADDRESS;
  6055. hdrsize = sizeof(ARCNetHeader);
  6056. snapsize = 0;
  6057. PF = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED;
  6058. ai->ai_mediatype = IF_TYPE_ARCNET;
  6059. break;
  6060. default:
  6061. ASSERT(0);
  6062. FreeARPInterface(ai);
  6063. return FALSE;
  6064. }
  6065. ai->ai_bcastmask = bcastmask;
  6066. ai->ai_bcastval = bcastval;
  6067. ai->ai_bcastoff = bcastoff;
  6068. ai->ai_addrlen = addrlen;
  6069. ai->ai_hdrsize = hdrsize;
  6070. ai->ai_snapsize = snapsize;
  6071. ai->ai_pfilter = PF;
  6072. Status = DoNDISRequest(ai, NdisRequestQueryInformation, OID,
  6073. ai->ai_addr, addrlen, NULL, TRUE);
  6074. if (Status != NDIS_STATUS_SUCCESS) {
  6075. FreeARPInterface(ai);
  6076. return FALSE;
  6077. }
  6078. // Read the maximum frame size.
  6079. if ((Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  6080. OID_GEN_MAXIMUM_FRAME_SIZE, &mss, sizeof(mss), NULL, TRUE)) != NDIS_STATUS_SUCCESS) {
  6081. FreeARPInterface(ai);
  6082. return FALSE;
  6083. }
  6084. // If this is token ring, figure out the RC len stuff now.
  6085. mss -= (uint) ai->ai_snapsize;
  6086. if (ai->ai_media == NdisMedium802_5) {
  6087. mss -= (sizeof(RC) + (ARP_MAX_RD * sizeof(ushort)));
  6088. } else {
  6089. if (ai->ai_media == NdisMediumFddi) {
  6090. mss = MIN(mss, ARP_FDDI_MSS);
  6091. }
  6092. }
  6093. ai->ai_mtu = (ushort) mss;
  6094. // Read the speed for local purposes.
  6095. if ((Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  6096. OID_GEN_LINK_SPEED, &speed, sizeof(speed), NULL, TRUE)) == NDIS_STATUS_SUCCESS) {
  6097. ai->ai_speed = speed * 100L;
  6098. }
  6099. // Read and save the options.
  6100. Status = DoNDISRequest(ai, NdisRequestQueryInformation, OID_GEN_MAC_OPTIONS,
  6101. &MacOpts, sizeof(MacOpts), NULL, TRUE);
  6102. if (Status != NDIS_STATUS_SUCCESS) {
  6103. *Flags = 0;
  6104. } else {
  6105. *Flags = (MacOpts & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) ? LIP_COPY_FLAG : 0;
  6106. }
  6107. if (CTEMemCmp(ai->ai_addr, PPP_HW_ADDR, PPP_HW_ADDR_LEN) == 0) {
  6108. *Flags = *Flags | LIP_P2P_FLAG;
  6109. }
  6110. //
  6111. // Query the media capability to determine if it is a uni-directional adapter.
  6112. //
  6113. Status = DoNDISRequest(
  6114. ai,
  6115. NdisRequestQueryInformation,
  6116. OID_GEN_MEDIA_CAPABILITIES,
  6117. &MediaType,
  6118. sizeof(MediaType),
  6119. NULL,
  6120. TRUE); // Blocking.
  6121. if (Status == NDIS_STATUS_SUCCESS) {
  6122. // Bit field of Rx and Tx. If only Rx, set uni flag.
  6123. if (MediaType == NDIS_MEDIA_CAP_RECEIVE) {
  6124. DEBUGMSG(DBG_WARN,
  6125. (DTEXT("ARPRegister: ai %x: MEDIA_CAP_RX -> UniAdapter!!\n"), ai));
  6126. *Flags |= LIP_UNI_FLAG;
  6127. InterlockedIncrement( (PLONG) &cUniAdapters);
  6128. }
  6129. }
  6130. // Read and store the vendor description string.
  6131. Status = NdisQueryAdapterInstanceName(&NdisString, ai->ai_handle);
  6132. if (Status == NDIS_STATUS_SUCCESS) {
  6133. ANSI_STRING AnsiString;
  6134. // Convert the string to ANSI, and use the new ANSI string's buffer
  6135. // to store the description in the ARP interface.
  6136. // N.B. The conversion results in a nul-terminated string.
  6137. Status = RtlUnicodeStringToAnsiString(&AnsiString, &NdisString, TRUE);
  6138. if (Status == STATUS_SUCCESS) {
  6139. ai->ai_desc = AnsiString.Buffer;
  6140. ai->ai_desclen = (uint)strlen(AnsiString.Buffer) + 1;
  6141. }
  6142. NdisFreeString(NdisString);
  6143. }
  6144. if (!ArpEnetHeaderPool || !ArpAuxHeaderPool) {
  6145. PVOID SectionHandle;
  6146. // Allocate our small and big buffer pools. Take the interface list
  6147. // lock simply to protect creating of the buffer pools if we haven't
  6148. // already done so. We could have used our own lock, but the interface
  6149. // list lock is global, and not already used in this path.
  6150. //
  6151. // This routine is in pageable memory. Since getting the lock
  6152. // requires writable access to LockHandle at DISPATCH, we need to
  6153. // lock this code in.
  6154. //
  6155. SectionHandle = MmLockPagableCodeSection(ARPRegister);
  6156. CTEGetLock(&ArpInterfaceListLock.Lock, &LockHandle);
  6157. if (!ArpEnetHeaderPool) {
  6158. ArpEnetHeaderPool = MdpCreatePool(BUFSIZE_ENET_HEADER_POOL, 'ehCT');
  6159. }
  6160. if (!ArpAuxHeaderPool) {
  6161. ArpAuxHeaderPool = MdpCreatePool(BUFSIZE_AUX_HEADER_POOL, 'ahCT');
  6162. }
  6163. CTEFreeLock(&ArpInterfaceListLock.Lock, LockHandle);
  6164. MmUnlockPagableImageSection(SectionHandle);
  6165. if (!ArpAuxHeaderPool || !ArpEnetHeaderPool) {
  6166. FreeARPInterface(ai);
  6167. return FALSE;
  6168. }
  6169. }
  6170. ai->ai_promiscuous = 0;
  6171. #if FFP_SUPPORT
  6172. {
  6173. FFPVersionParams Version =
  6174. {
  6175. NDIS_PROTOCOL_ID_TCP_IP, 0
  6176. };
  6177. // Initialize all FFP Handling Variables
  6178. ai->ai_ffpversion = 0;
  6179. ai->ai_ffplastflush = 0;
  6180. // Query FFP Handling capabilities
  6181. Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  6182. OID_FFP_SUPPORT, &Version, sizeof(FFPVersionParams), NULL, TRUE);
  6183. // Non-Zero Value indicates FFP support
  6184. if (Version.FFPVersion) {
  6185. // Set the FFP startup parameters
  6186. FFPSupportParams Info;
  6187. Info.NdisProtocolType = NDIS_PROTOCOL_ID_TCP_IP;
  6188. Info.FastForwardingCacheSize = FFPRegFastForwardingCacheSize;
  6189. Info.FFPControlFlags = FFPRegControlFlags;
  6190. // But store away the version first
  6191. ai->ai_ffpversion = Version.FFPVersion;
  6192. DoNDISRequest(ai, NdisRequestSetInformation,
  6193. OID_FFP_SUPPORT, &Info, sizeof(FFPSupportParams), NULL, TRUE);
  6194. TCPTRACE(("Setting FFP capabilities: Cache Size = %lu, Flags = %08x\n",
  6195. Info.FastForwardingCacheSize,
  6196. Info.FFPControlFlags));
  6197. }
  6198. }
  6199. #endif // if FFP_SUPPORT
  6200. ai->ai_OffloadFlags = 0;
  6201. ai->ai_IPSecOffloadFlags = 0;
  6202. if (DisableTaskOffload) {
  6203. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Taskoffload disabled\n"));
  6204. } else {
  6205. if(!QueryAndSetOffload(ai)){
  6206. DEBUGMSG(DBG_ERROR, (DTEXT("ARP: Query and set offload failed.\n")));
  6207. }
  6208. }
  6209. // query the wakeup capabilities.
  6210. Status = DoNDISRequest(
  6211. ai,
  6212. NdisRequestQueryInformation,
  6213. OID_PNP_CAPABILITIES,
  6214. &ai->ai_wakeupcap,
  6215. sizeof(NDIS_PNP_CAPABILITIES),
  6216. NULL, TRUE);
  6217. if (Status == NDIS_STATUS_SUCCESS) {
  6218. uint wakeup = NDIS_PNP_WAKE_UP_PATTERN_MATCH;
  6219. // enable wakeup capabilities.
  6220. Status = DoNDISRequest(
  6221. ai,
  6222. NdisRequestSetInformation,
  6223. OID_PNP_ENABLE_WAKE_UP,
  6224. &wakeup,
  6225. sizeof(wakeup),
  6226. NULL, TRUE);
  6227. if (Status != NDIS_STATUS_SUCCESS) {
  6228. ai->ai_wakeupcap.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
  6229. }
  6230. }
  6231. // Store the device name, we need to pass this to our TDI clients when
  6232. // we do the PNP notification.
  6233. if ((ai->ai_devicename.Buffer = CTEAllocMemNBoot(Adapter->MaximumLength, 'aICT')) == NULL) {
  6234. FreeARPInterface(ai);
  6235. return FALSE;
  6236. }
  6237. RtlCopyMemory(ai->ai_devicename.Buffer, Adapter->Buffer, Adapter->MaximumLength);
  6238. ai->ai_devicename.Length = Adapter->Length;
  6239. ai->ai_devicename.MaximumLength = Adapter->MaximumLength;
  6240. ai->ai_timerstarted = TRUE;
  6241. IPHdrOffset.HeaderOffset = ai->ai_snapsize + ai->ai_hdrsize;
  6242. IPHdrOffset.ProtocolType = NDIS_PROTOCOL_ID_TCP_IP;
  6243. Status = DoNDISRequest(ai, NdisRequestSetInformation, OID_GEN_TRANSPORT_HEADER_OFFSET,
  6244. &IPHdrOffset, sizeof(TRANSPORT_HEADER_OFFSET), NULL, TRUE);
  6245. // Everything's set up, so get the ARP timer running.
  6246. CTEStartTimer(&ai->ai_timer, ARP_TIMER_TIME, ARPTimeout, ai);
  6247. return TRUE;
  6248. }
  6249. #pragma END_INIT
  6250. //* ARPDynRegister - Dynamically register IP.
  6251. //
  6252. // Called by IP when he's about done binding to register with us. Since we
  6253. // call him directly, we don't save his info here. We do keep his context
  6254. // and index number.
  6255. //
  6256. // Input: See ARPRegister
  6257. //
  6258. // Returns: Nothing.
  6259. //
  6260. int
  6261. __stdcall
  6262. ARPDynRegister(
  6263. IN PNDIS_STRING Adapter,
  6264. IN void *IPContext,
  6265. IN struct _IP_HANDLERS *IpHandlers,
  6266. OUT struct LLIPBindInfo *Info,
  6267. IN uint NumIFBound)
  6268. {
  6269. ARPInterface *Interface = (ARPInterface *) Info->lip_context;
  6270. UNREFERENCED_PARAMETER(Adapter);
  6271. UNREFERENCED_PARAMETER(IpHandlers);
  6272. Interface->ai_context = IPContext;
  6273. Interface->ai_index = NumIFBound;
  6274. // TCPTRACE(("Arp Interface %lx ai_context %lx ai_index %lx\n",Interface, Interface->ai_context, Interface->ai_index));
  6275. return TRUE;
  6276. }
  6277. //* ARPBindAdapter - Bind and initialize an adapter.
  6278. //
  6279. // Called in a PNP environment to initialize and bind an adapter. We open
  6280. // the adapter and get it running, and then we call up to IP to tell him
  6281. // about it. IP will initialize, and if all goes well call us back to start
  6282. // receiving.
  6283. //
  6284. // Input: RetStatus - Where to return the status of this call.
  6285. // BindContext - Handle to use for calling BindAdapterComplete.
  6286. // AdapterName - Pointer to name of adapter.
  6287. // SS1 - System specific 1 parameter.
  6288. // SS2 - System specific 2 parameter.
  6289. //
  6290. // Returns: Nothing.
  6291. //
  6292. void NDIS_API
  6293. ARPBindAdapter(PNDIS_STATUS RetStatus, NDIS_HANDLE BindContext,
  6294. PNDIS_STRING AdapterName, PVOID SS1, PVOID SS2)
  6295. {
  6296. uint Flags; // MAC binding flags.
  6297. ARPInterface *Interface; // Newly created interface.
  6298. IP_STATUS Status; // State of IPAddInterface call.
  6299. LLIPBindInfo BindInfo; // Binding information for IP.
  6300. NDIS_HANDLE Handle;
  6301. NDIS_STRING IPConfigName;
  6302. DBG_UNREFERENCED_PARAMETER(BindContext);
  6303. DEBUGMSG(DBG_TRACE && DBG_PNP,
  6304. (DTEXT("+ARPBindAdapter(%x, %x, %x, %x, %x)\n"),
  6305. RetStatus, BindContext, AdapterName, SS1, SS2));
  6306. if (!OpenIFConfig(SS1, &Handle)) {
  6307. *RetStatus = NDIS_STATUS_FAILURE;
  6308. DEBUGMSG(DBG_ERROR && DBG_PNP, (DTEXT("ARPBindAdapter: Open failure\n")));
  6309. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-ARPBindAdapter [%x]\n"), *RetStatus));
  6310. return;
  6311. }
  6312. #if !MILLEN
  6313. if ((*RetStatus = GetIPConfigValue(Handle, &IPConfigName)) != NDIS_STATUS_SUCCESS) {
  6314. CloseIFConfig(Handle);
  6315. DEBUGMSG(DBG_ERROR && DBG_PNP, (DTEXT("ARPBindAdapter: GetIPConfigValue failure\n")));
  6316. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-ARPBindAdapter [%x]\n"), *RetStatus));
  6317. return;
  6318. }
  6319. #endif // !MILLEN
  6320. CloseIFConfig(Handle);
  6321. // First, open the adapter and get the info.
  6322. if (!ARPRegister(AdapterName, &Flags, &Interface)) {
  6323. #if !MILLEN
  6324. CTEFreeMem(IPConfigName.Buffer);
  6325. #endif // !MILLEN
  6326. *RetStatus = NDIS_STATUS_FAILURE;
  6327. DEBUGMSG(DBG_ERROR && DBG_PNP, (DTEXT("ARPBindAdapter: ARPRegister failure\n")));
  6328. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-ARPBindAdapter [%x]\n"), *RetStatus));
  6329. return;
  6330. }
  6331. // OK, we're opened the adapter. Call IP to tell him about it.
  6332. BindInfo.lip_context = Interface;
  6333. BindInfo.lip_transmit = ARPTransmit;
  6334. BindInfo.lip_transfer = ARPXferData;
  6335. BindInfo.lip_close = ARPClose;
  6336. BindInfo.lip_addaddr = ARPAddAddr;
  6337. BindInfo.lip_deladdr = ARPDeleteAddr;
  6338. BindInfo.lip_invalidate = ARPInvalidate;
  6339. BindInfo.lip_open = ARPOpen;
  6340. BindInfo.lip_qinfo = ARPQueryInfo;
  6341. BindInfo.lip_setinfo = ARPSetInfo;
  6342. BindInfo.lip_getelist = ARPGetEList;
  6343. BindInfo.lip_dondisreq = DoNDISRequest;
  6344. BindInfo.lip_mss = Interface->ai_mtu;
  6345. BindInfo.lip_speed = Interface->ai_speed;
  6346. BindInfo.lip_flags = Flags;
  6347. BindInfo.lip_addrlen = Interface->ai_addrlen;
  6348. BindInfo.lip_addr = Interface->ai_addr;
  6349. BindInfo.lip_dowakeupptrn = DoWakeupPattern;
  6350. BindInfo.lip_pnpcomplete = ARPPnPComplete;
  6351. BindInfo.lip_setndisrequest = ARPSetNdisRequest;
  6352. BindInfo.lip_arpresolveip = ARPResolveIP;
  6353. BindInfo.lip_arpflushate = ARPFlushATE;
  6354. BindInfo.lip_arpflushallate = ARPFlushAllATE;
  6355. #if !MILLEN
  6356. BindInfo.lip_cancelpackets = ARPCancelPackets;
  6357. #endif
  6358. #if FFP_SUPPORT
  6359. // NDIS Driver Handle, FFP Version are passed up
  6360. // [ Non zero version implies FFP Support exists ]
  6361. BindInfo.lip_ffpversion = Interface->ai_ffpversion;
  6362. BindInfo.lip_ffpdriver = (ULONG_PTR) Interface->ai_driver;
  6363. #endif
  6364. //Interface capability is passed on to IP via BindInfo
  6365. BindInfo.lip_OffloadFlags = Interface->ai_OffloadFlags;
  6366. BindInfo.lip_IPSecOffloadFlags = Interface->ai_IPSecOffloadFlags;
  6367. BindInfo.lip_MaxOffLoadSize = (uint) Interface->ai_TcpLargeSend.MaxOffLoadSize;
  6368. BindInfo.lip_MaxSegments = (uint) Interface->ai_TcpLargeSend.MinSegmentCount;
  6369. BindInfo.lip_closelink = NULL;
  6370. BindInfo.lip_pnpcap = Interface->ai_wakeupcap.Flags;
  6371. DEBUGMSG(DBG_INFO && DBG_PNP,
  6372. (DTEXT("ARPBindAdapter calling IPAddInterface.\n")));
  6373. Status = IPAddInterface(AdapterName,
  6374. NULL,
  6375. #if MILLEN
  6376. (PNDIS_STRING) SS1,
  6377. #else // MILLEN
  6378. (PNDIS_STRING) & IPConfigName,
  6379. #endif // !MILLEN
  6380. SS2,
  6381. Interface,
  6382. ARPDynRegister,
  6383. &BindInfo,
  6384. 0,
  6385. Interface->ai_mediatype,
  6386. IF_ACCESS_BROADCAST,
  6387. IF_CONNECTION_DEDICATED);
  6388. #if !MILLEN
  6389. CTEFreeMem(IPConfigName.Buffer);
  6390. #endif // !MILLEN
  6391. if (Status != IP_SUCCESS) {
  6392. // Need to close the binding. FreeARPInterface will do that, as well
  6393. // as freeing resources.
  6394. DEBUGMSG(DBG_ERROR && DBG_PNP,
  6395. (DTEXT("ARPBindAdapter: IPAddInterface failure %x\n"), Status));
  6396. FreeARPInterface(Interface);
  6397. *RetStatus = NDIS_STATUS_FAILURE;
  6398. } else {
  6399. //
  6400. // Insert into ARP IF list
  6401. //
  6402. ExInterlockedInsertTailList(&ArpInterfaceList,
  6403. &Interface->ai_linkage,
  6404. &ArpInterfaceListLock.Lock);
  6405. *RetStatus = NDIS_STATUS_SUCCESS;
  6406. }
  6407. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-ARPBindAdapter [%x]\n"), *RetStatus));
  6408. }
  6409. //* ARPUnbindAdapter - Unbind from an adapter.
  6410. //
  6411. // Called when we need to unbind from an adapter. We'll call up to IP to tell
  6412. // him. When he's done, we'll free our memory and return.
  6413. //
  6414. // Input: RetStatus - Where to return status from call.
  6415. // ProtBindContext - The context we gave NDIS earlier - really a
  6416. // pointer to an ARPInterface structure.
  6417. // UnbindContext - Context for completeing this request.
  6418. //
  6419. // Returns: Nothing.
  6420. //
  6421. void NDIS_API
  6422. ARPUnbindAdapter(PNDIS_STATUS RetStatus, NDIS_HANDLE ProtBindContext,
  6423. NDIS_HANDLE UnbindContext)
  6424. {
  6425. ARPInterface *Interface = (ARPInterface *) ProtBindContext;
  6426. NDIS_STATUS Status; // Status of close call.
  6427. CTELockHandle LockHandle;
  6428. // Shut him up, so we don't get any more frames.
  6429. Interface->ai_pfilter = 0;
  6430. if (Interface->ai_handle != NULL) {
  6431. DoNDISRequest(Interface, NdisRequestSetInformation,
  6432. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter, sizeof(uint),
  6433. NULL, TRUE);
  6434. }
  6435. CTEInitBlockStrucEx(&Interface->ai_timerblock);
  6436. Interface->ai_stoptimer = TRUE;
  6437. // Mark him as down.
  6438. Interface->ai_adminstate = IF_STATUS_DOWN;
  6439. ARPUpdateOperStatus(Interface);
  6440. // Mark the interface as going away so it will disappear from the
  6441. // entity list.
  6442. Interface->ai_operstatus = INTERFACE_UNINIT;
  6443. #if FFP_SUPPORT
  6444. // Stop FFP on this interface
  6445. Interface->ai_ffpversion = 0;
  6446. #endif
  6447. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Flushing all ates %x\n", Interface));
  6448. ARPFlushAllATE(Interface);
  6449. // Now tell IP he's gone. We need to make sure that we don't tell him twice.
  6450. // To do this we set the context to NULL after we tell him the first time,
  6451. // and we check to make sure it's non-NULL before notifying him.
  6452. if (Interface->ai_context != NULL) {
  6453. IPDelInterface(Interface->ai_context, TRUE);
  6454. Interface->ai_context = NULL;
  6455. }
  6456. // Finally, close him. We do this here so we can return a valid status.
  6457. CTEGetLock(&Interface->ai_lock, &LockHandle);
  6458. if (Interface->ai_handle != NULL) {
  6459. NDIS_HANDLE Handle = Interface->ai_handle;
  6460. CTEFreeLock(&Interface->ai_lock, LockHandle);
  6461. CTEInitBlockStruc(&Interface->ai_block);
  6462. NdisCloseAdapter(&Status, Handle);
  6463. // Block for close to complete.
  6464. if (Status == NDIS_STATUS_PENDING) {
  6465. Status = (NDIS_STATUS) CTEBlock(&Interface->ai_block);
  6466. }
  6467. Interface->ai_handle = NULL;
  6468. } else {
  6469. CTEFreeLock(&Interface->ai_lock, LockHandle);
  6470. Status = NDIS_STATUS_SUCCESS;
  6471. }
  6472. //Check if are called from ARPUnload
  6473. if ((ARPInterface *) UnbindContext != Interface) {
  6474. CTELockHandle Handle;
  6475. //No. Acquire lock and remove entry.
  6476. CTEGetLock(&ArpInterfaceListLock.Lock, &Handle);
  6477. RemoveEntryList(&Interface->ai_linkage);
  6478. CTEFreeLock(&ArpInterfaceListLock.Lock, Handle);
  6479. }
  6480. *RetStatus = Status;
  6481. if (Status == NDIS_STATUS_SUCCESS) {
  6482. FreeARPInterface(Interface);
  6483. }
  6484. }
  6485. extern ulong VIPTerminate;
  6486. //* ARPUnloadProtocol - Unload.
  6487. //
  6488. // Called when we need to unload. All we do is call up to IP, and return.
  6489. //
  6490. // Input: Nothing.
  6491. //
  6492. // Returns: Nothing.
  6493. //
  6494. void NDIS_API
  6495. ARPUnloadProtocol(void)
  6496. {
  6497. #if MILLEN
  6498. DEBUGMSG(1, (DTEXT("ARPUnloadProtocol called! What to do???\n")));
  6499. #endif // MILLEN
  6500. }
  6501. VOID
  6502. ArpUnload(IN PDRIVER_OBJECT DriverObject)
  6503. /*++
  6504. Routine Description:
  6505. This routine unloads the TCPIP stack.
  6506. It unbinds from any NDIS drivers that are open and frees all resources
  6507. associated with the transport. The I/O system will not call us until
  6508. nobody above has IPX open.
  6509. NOTE: Also, since other ARP modules depend on IP, they are unloaded before
  6510. out unload handler is called. We concern ourselves with the LAN arp
  6511. only at this point
  6512. Arguments:
  6513. DriverObject - Pointer to driver object created by the system.
  6514. Return Value:
  6515. None. When the function returns, the driver is unloaded.
  6516. --*/
  6517. {
  6518. PLIST_ENTRY pEntry;
  6519. CTELockHandle LockHandle;
  6520. NDIS_STATUS status;
  6521. ARPInterface *Interface;
  6522. //
  6523. // Walk the list of opened ARP interfaces, issuing
  6524. // PnP deletes on each in turn.
  6525. //
  6526. CTEGetLock(&ArpInterfaceListLock.Lock, &LockHandle);
  6527. while(!IsListEmpty(&ArpInterfaceList)) {
  6528. pEntry = ArpInterfaceList.Flink;
  6529. Interface = STRUCT_OF(ARPInterface, pEntry, ai_linkage);
  6530. RemoveEntryList(&Interface->ai_linkage);
  6531. CTEFreeLock(&ArpInterfaceListLock.Lock, LockHandle);
  6532. // KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Issuing unbind on %lx\n", Interface));
  6533. ARPUnbindAdapter(&status, Interface, Interface);
  6534. CTEGetLock(&ArpInterfaceListLock.Lock, &LockHandle);
  6535. }
  6536. CTEFreeLock(&ArpInterfaceListLock.Lock, LockHandle);
  6537. MdpDestroyPool(ArpEnetHeaderPool);
  6538. MdpDestroyPool(ArpAuxHeaderPool);
  6539. //
  6540. // Deal with any residual events/timers
  6541. // Only one timer sits at this layer: ai_timer, which is stopped
  6542. // on the unbind above.
  6543. //
  6544. //
  6545. // call into IP so it can cleanup.
  6546. //
  6547. IPUnload(DriverObject);
  6548. }