/*++ Copyright (c) 1998, Microsoft Corporation Module Name: natarp.c Abstract: This module contains code for the NAT's user-mode proxy-ARP entry management. Proxy-ARP entries are installed on dedicated interfaces which have address-translation enabled. Author: Abolade Gbadegesin (aboladeg) 20-Mar-1998 Revision History: --*/ #include "precomp.h" #pragma hdrstop // // FORWARD DECLARATIONS // VOID NatpCreateProxyArpCallback( ULONG Address, ULONG Mask, PVOID Context ); VOID NatpDeleteProxyArpCallback( ULONG Address, ULONG Mask, PVOID Context ); VOID NatpCreateProxyArpCallback( ULONG Address, ULONG Mask, PVOID Context ) /*++ Routine Description: This routine is invoked to remove a proxy-ARP entry. Arguments: Address - the address to remove Mask - the mask associated with 'Address' Context - context-field holding the entry's interface Return Value: none. --*/ { ULONG Error; DEFINE_MIB_BUFFER(Info, MIB_PROXYARP, Entry); PROFILE("NatpCreateProxyArpCallback"); // // Install an entry for the range, unless the host-portion is 1 bit wide, // in which case the range consists only of an all-zeroes and all-ones host. // The stack will refuse to answer ARP queries for either one, // so adding such a range would be a waste. // Info->dwId = PROXY_ARP; if (~Mask != 1) { Entry->dwAddress = (Address & Mask); Entry->dwMask = Mask; Entry->dwIfIndex = ((PNAT_INTERFACE)Context)->Index; Error = NatSupportFunctions.MIBEntryCreate( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Info ); if (Error) { CHAR MaskString[16]; lstrcpyA(MaskString, INET_NTOA(Mask)); NhTrace( TRACE_FLAG_NAT, "NatpCreateProxyArpCallback: error %d adding %s/%s", Error, INET_NTOA(Address), MaskString ); NhInformationLog( IP_NAT_LOG_UPDATE_ARP_FAILED, Error, "%I%I", Address, Mask ); } } // // If the mask is not all-ones, also install entries for the all-zeroes // and all-ones host-portions of the range; otherwise IP will refuse // to answer ARP queries for these. // if (~Mask) { Entry->dwAddress = (Address & Mask); Entry->dwMask = 0xffffffff; Entry->dwIfIndex = ((PNAT_INTERFACE)Context)->Index; NatSupportFunctions.MIBEntryCreate( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Info ); Entry->dwAddress = (Address | ~Mask); Entry->dwMask = 0xffffffff; Entry->dwIfIndex = ((PNAT_INTERFACE)Context)->Index; NatSupportFunctions.MIBEntryCreate( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Info ); } } // NatpCreateProxyArpCallback VOID NatpDeleteProxyArpCallback( ULONG Address, ULONG Mask, PVOID Context ) /*++ Routine Description: This routine is invoked to remove a proxy-ARP entry. Arguments: Address - the address to remove Mask - the mask associated with 'Address' Context - context-field holding the entry's interface Return Value: none. --*/ { BYTE Buffer[FIELD_OFFSET(MIB_OPAQUE_QUERY, rgdwVarIndex) + 3*sizeof(DWORD)]; ULONG Error; PMIB_OPAQUE_QUERY Query = (PMIB_OPAQUE_QUERY)Buffer; PROFILE("NatpDeleteProxyArpCallback"); Query->dwVarId = PROXY_ARP; Query->rgdwVarIndex[0] = (Address & Mask); Query->rgdwVarIndex[1] = Mask; Query->rgdwVarIndex[2] = ((PNAT_INTERFACE)Context)->Index; Error = NatSupportFunctions.MIBEntryDelete( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Buffer ); if (Error) { CHAR MaskString[16]; lstrcpyA(MaskString, INET_NTOA(Mask)); NhTrace( TRACE_FLAG_NAT, "NatpDeleteProxyArpCallback: error %d deleting %s/%s", Error, INET_NTOA(Address), MaskString ); NhInformationLog( IP_NAT_LOG_UPDATE_ARP_FAILED, Error, "%I%I", Address, Mask ); } // // If the mask is not all-ones, also remove the entries for the all-zeroes // and all-ones host-portions of the range. // if (~Mask) { Query->rgdwVarIndex[0] = (Address & Mask); Query->rgdwVarIndex[1] = 0xffffffff; Query->rgdwVarIndex[2] = ((PNAT_INTERFACE)Context)->Index; NatSupportFunctions.MIBEntryDelete( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Buffer ); Query->rgdwVarIndex[0] = (Address | ~Mask); Query->rgdwVarIndex[1] = 0xffffffff; Query->rgdwVarIndex[2] = ((PNAT_INTERFACE)Context)->Index; NatSupportFunctions.MIBEntryDelete( IPRTRMGR_PID, MIB_INFO_SIZE(MIB_PROXYARP), Buffer ); } } // NatpDeleteProxyArpCallback VOID NatUpdateProxyArp( PNAT_INTERFACE Interfacep, BOOLEAN CreateEntries ) /*++ Routine Description: This routine is invoked to install or remove the proxy-ARP entries corresponding to the address-ranges configured on the given interface. Arguments: Interfacep - the interface on which to operate CreateEntries - TRUE to install entries, FALSE to remove Return Value: none. Environment: Invoked with the interface list locked by the caller. --*/ { ULONG Count; ULONG Error; ULONG i; PIP_NAT_ADDRESS_RANGE Range; PROFILE("NatUpdateProxyArp"); if (!Interfacep->Info || !NatSupportFunctions.MIBEntryCreate || !NatSupportFunctions.MIBEntryDelete ) { return; } // // Locate the address-ranges, if any // Error = MprInfoBlockFind( &Interfacep->Info->Header, IP_NAT_ADDRESS_RANGE_TYPE, NULL, &Count, (PUCHAR*)&Range ); if (Error || NULL == Range) { return; } // // Now go through the ranges, decomposing each one // for (i = 0; i < Count; i++) { DecomposeRange( Range[i].StartAddress, Range[i].EndAddress, MostGeneralMask(Range[i].StartAddress, Range[i].EndAddress), CreateEntries ? NatpCreateProxyArpCallback : NatpDeleteProxyArpCallback, Interfacep ); } } // NatUpdateProxyArp