Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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