Esempio n. 1
0
PFIB_ENTRY RouterCreateRoute(
    PIP_ADDRESS NetworkAddress,
    PIP_ADDRESS Netmask,
    PIP_ADDRESS RouterAddress,
    PIP_INTERFACE Interface,
    UINT Metric)
/*
 * FUNCTION: Creates a route with IPv4 addresses as parameters
 * ARGUMENTS:
 *     NetworkAddress = Address of network
 *     Netmask        = Netmask of network
 *     RouterAddress  = Address of router to use
 *     NTE            = Pointer to NTE to use
 *     Metric         = Cost of this route
 * RETURNS:
 *     Pointer to FIB entry if the route was created, NULL if not.
 *     The FIB entry references the NTE. The caller is responsible
 *     for providing this reference
 */
{
    KIRQL OldIrql;
    PLIST_ENTRY CurrentEntry;
    PLIST_ENTRY NextEntry;
    PFIB_ENTRY Current;
    PNEIGHBOR_CACHE_ENTRY NCE;

    TcpipAcquireSpinLock(&FIBLock, &OldIrql);

    CurrentEntry = FIBListHead.Flink;
    while (CurrentEntry != &FIBListHead) {
        NextEntry = CurrentEntry->Flink;
	Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);

        NCE   = Current->Router;

	if( AddrIsEqual(NetworkAddress, &Current->NetworkAddress) &&
	    AddrIsEqual(Netmask, &Current->Netmask) ) {
	    TI_DbgPrint(DEBUG_ROUTER,("Attempting to add duplicate route to %s\n", A2S(NetworkAddress)));
	    TcpipReleaseSpinLock(&FIBLock, OldIrql);
	    return NULL;
	}

	CurrentEntry = NextEntry;
    }

    TcpipReleaseSpinLock(&FIBLock, OldIrql);

    /* The NCE references RouterAddress. The NCE is referenced for us */
    NCE = NBFindOrCreateNeighbor(Interface, RouterAddress);

    if (!NCE) {
        /* Not enough free resources */
        return NULL;
    }

    return RouterAddRoute(NetworkAddress, Netmask, NCE, Metric);
}
Esempio n. 2
0
NTSTATUS RouterRemoveRoute(PIP_ADDRESS Target, PIP_ADDRESS Router)
/*
 * FUNCTION: Removes a route from the Forward Information Base (FIB)
 * ARGUMENTS:
 *     Target: The machine or network targeted by the route
 *     Router: The router used to pass the packet to the destination
 *
 * Searches the FIB and removes a route matching the indicated parameters.
 */
{
    KIRQL OldIrql;
    PLIST_ENTRY CurrentEntry;
    PLIST_ENTRY NextEntry;
    PFIB_ENTRY Current;
    BOOLEAN Found = FALSE;
    PNEIGHBOR_CACHE_ENTRY NCE;

    TI_DbgPrint(DEBUG_ROUTER, ("Called\n"));
    TI_DbgPrint(DEBUG_ROUTER, ("Deleting Route From: %s\n", A2S(Router)));
    TI_DbgPrint(DEBUG_ROUTER, ("                 To: %s\n", A2S(Target)));

    TcpipAcquireSpinLock(&FIBLock, &OldIrql);

    RouterDumpRoutes();

    CurrentEntry = FIBListHead.Flink;
    while (CurrentEntry != &FIBListHead) {
        NextEntry = CurrentEntry->Flink;
	Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);

        NCE   = Current->Router;

	if( AddrIsEqual( &Current->NetworkAddress, Target ) &&
	    AddrIsEqual( &NCE->Address, Router ) ) {
	    Found = TRUE;
	    break;
	}

	Current = NULL;
        CurrentEntry = NextEntry;
    }

    if( Found ) {
	TI_DbgPrint(DEBUG_ROUTER, ("Deleting route\n"));
	DestroyFIBE( Current );
    }

    RouterDumpRoutes();

    TcpipReleaseSpinLock(&FIBLock, OldIrql);

    TI_DbgPrint(DEBUG_ROUTER, ("Leaving\n"));

    return Found ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
Esempio n. 3
0
BOOLEAN AddrIsBroadcastMatch(
    PIP_ADDRESS UnicastAddress,
    PIP_ADDRESS BroadcastAddress ) {
    IF_LIST_ITER(IF);

    ForEachInterface(IF) {
        if ((AddrIsUnspecified(UnicastAddress) ||
             AddrIsEqual(&IF->Unicast, UnicastAddress)) &&
            (AddrIsEqual(&IF->Broadcast, BroadcastAddress)))
            return TRUE;
    } EndFor(IF);

    return FALSE;
}
Esempio n. 4
0
BOOLEAN AddrReceiveMatch(
   PIP_ADDRESS LocalAddress,
   PIP_ADDRESS RemoteAddress)
{
   if (AddrIsEqual(LocalAddress, RemoteAddress))
   {
       /* Unicast address match */
       return TRUE;
   }

   if (AddrIsBroadcastMatch(LocalAddress, RemoteAddress))
   {
       /* Broadcast address match */
       return TRUE;
   }

   if (AddrIsUnspecified(LocalAddress))
   {
       /* Local address unspecified */
       return TRUE;
   }

   if (AddrIsUnspecified(RemoteAddress))
   {
       /* Remote address unspecified */
       return TRUE;
   }

   return FALSE;
}
Esempio n. 5
0
VOID
NBResetNeighborTimeout(PIP_ADDRESS Address)
{
    KIRQL OldIrql;
    UINT HashValue;
    PNEIGHBOR_CACHE_ENTRY NCE;

    TI_DbgPrint(DEBUG_NCACHE, ("Resetting NCE timout for 0x%s\n", A2S(Address)));

    HashValue  = *(PULONG)(&Address->Address);
    HashValue ^= HashValue >> 16;
    HashValue ^= HashValue >> 8;
    HashValue ^= HashValue >> 4;
    HashValue &= NB_HASHMASK;

    TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);

    for (NCE = NeighborCache[HashValue].Cache;
         NCE != NULL;
         NCE = NCE->Next)
    {
         if (AddrIsEqual(Address, &NCE->Address))
         {
             NCE->EventCount = 0;
             break;
         }
    }

    TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
}
Esempio n. 6
0
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
    PIP_ADDRESS Address)
/*
 * FUNCTION: Locates a neighbor in the neighbor cache
 * ARGUMENTS:
 *   Address = Pointer to IP address
 * RETURNS:
 *   Pointer to NCE, NULL if not found
 * NOTES:
 *   If the NCE is found, it is referenced. The caller is
 *   responsible for dereferencing it again after use
 */
{
    PNEIGHBOR_CACHE_ENTRY NCE;
    UINT HashValue;
    KIRQL OldIrql;

    TI_DbgPrint(DEBUG_NCACHE, ("Called. Address (0x%X).\n", Address));

    HashValue = *(PULONG)&Address->Address;
    HashValue ^= HashValue >> 16;
    HashValue ^= HashValue >> 8;
    HashValue ^= HashValue >> 4;
    HashValue &= NB_HASHMASK;

    TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);

    NCE = NeighborCache[HashValue].Cache;

    while ((NCE) && (!AddrIsEqual(Address, &NCE->Address)))
    {
        NCE = NCE->Next;
    }

    TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);

    TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));

    return NCE;
}
Esempio n. 7
0
PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
  PIP_INTERFACE Interface,
  PIP_ADDRESS Address,
  BOOLEAN NoTimeout)
/*
 * FUNCTION: Tries to find a neighbor and if unsuccesful, creates a new NCE
 * ARGUMENTS:
 *   Interface = Pointer to interface to use (in case NCE is not found)
 *   Address   = Pointer to IP address
 * RETURNS:
 *   Pointer to NCE, NULL if there is not enough free resources
 * NOTES:
 *   The NCE is referenced if found or created. The caller is
 *   responsible for dereferencing it again after use
 */
{
  PNEIGHBOR_CACHE_ENTRY NCE;

  TI_DbgPrint(DEBUG_NCACHE, ("Called. Interface (0x%X)  Address (0x%X).\n", Interface, Address));

  NCE = NBLocateNeighbor(Address, Interface);
  if (NCE == NULL)
    {
        TI_DbgPrint(MID_TRACE,("BCAST: %s\n", A2S(&Interface->Broadcast)));
        if( AddrIsEqual(Address, &Interface->Broadcast) ||
            AddrIsUnspecified(Address) ) {
            TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n"));
            NCE = NBAddNeighbor(Interface, Address, NULL,
                                Interface->AddressLength, NUD_PERMANENT, 0);
        } else {
            NCE = NBAddNeighbor(Interface, Address, NULL,
                                Interface->AddressLength, NUD_INCOMPLETE, NoTimeout ? 0 : ARP_INCOMPLETE_TIMEOUT);
            if (!NCE) return NULL;
            NBSendSolicit(NCE);
        }
    }

  return NCE;
}
Esempio n. 8
0
ULONG NBCopyNeighbors
(PIP_INTERFACE Interface,
 PIPARP_ENTRY ArpTable)
{
  PNEIGHBOR_CACHE_ENTRY CurNCE;
  KIRQL OldIrql;
  UINT Size = 0, i;

  for (i = 0; i <= NB_HASHMASK; i++) {
      TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
      for( CurNCE = NeighborCache[i].Cache;
	   CurNCE;
	   CurNCE = CurNCE->Next ) {
	  if( CurNCE->Interface == Interface &&
              !AddrIsEqual( &CurNCE->Address, &CurNCE->Interface->Unicast ) ) {
	      if( ArpTable ) {
		  ArpTable[Size].Index = Interface->Index;
		  ArpTable[Size].AddrSize = CurNCE->LinkAddressLength;
		  RtlCopyMemory
		      (ArpTable[Size].PhysAddr, 
		       CurNCE->LinkAddress,
		       CurNCE->LinkAddressLength);
		  ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address;
		  if( CurNCE->State & NUD_PERMANENT )
		      ArpTable[Size].Type = ARP_ENTRY_STATIC;
		  else if( CurNCE->State & NUD_INCOMPLETE )
		      ArpTable[Size].Type = ARP_ENTRY_INVALID;
		  else
		      ArpTable[Size].Type = ARP_ENTRY_DYNAMIC;
	      }
	      Size++;
	  }
      }
      TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
  }
  
  return Size;
}
Esempio n. 9
0
File: arp.c Progetto: GYGit/reactos
VOID ARPReceive(
    PVOID Context,
    PIP_PACKET Packet)
/*
 * FUNCTION: Receives an ARP packet
 * ARGUMENTS:
 *     Context = Pointer to context information (IP_INTERFACE)
 *     Packet  = Pointer to packet
 */
{
    PARP_HEADER Header;
    IP_ADDRESS SrcAddress;
    IP_ADDRESS DstAddress;
    PCHAR SenderHWAddress, SenderProtoAddress, TargetProtoAddress;
    PNEIGHBOR_CACHE_ENTRY NCE;
    PNDIS_PACKET NdisPacket;
    PIP_INTERFACE Interface = (PIP_INTERFACE)Context;
    ULONG BytesCopied, DataSize;
    PCHAR DataBuffer;
    
    PAGED_CODE();

    TI_DbgPrint(DEBUG_ARP, ("Called.\n"));

    Packet->Header = ExAllocatePoolWithTag(PagedPool,
                                           sizeof(ARP_HEADER),
                                           PACKET_BUFFER_TAG);
    if (!Packet->Header)
    {
        TI_DbgPrint(DEBUG_ARP, ("Unable to allocate header buffer\n"));
        Packet->Free(Packet);
        return;
    }
    Packet->MappedHeader = FALSE;

    BytesCopied = CopyPacketToBuffer((PCHAR)Packet->Header,
                                     Packet->NdisPacket,
                                     Packet->Position,
                                     sizeof(ARP_HEADER));
    if (BytesCopied != sizeof(ARP_HEADER))
    {
        TI_DbgPrint(DEBUG_ARP, ("Unable to copy in header buffer\n"));
        Packet->Free(Packet);
        return;
    }

    Header = (PARP_HEADER)Packet->Header;

    /* FIXME: Ethernet only */
    if (WN2H(Header->HWType) != 1) {
        TI_DbgPrint(DEBUG_ARP, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header->HWType)));
        Packet->Free(Packet);
        return;
    }

    /* Check protocol type */
    if (Header->ProtoType != ETYPE_IPv4) {
        TI_DbgPrint(DEBUG_ARP, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header->ProtoType)));
        Packet->Free(Packet);
        return;
    }

    DataSize = (2 * Header->HWAddrLen) + (2 * Header->ProtoAddrLen);
    DataBuffer = ExAllocatePool(PagedPool,
                                DataSize);
    if (!DataBuffer)
    {
        TI_DbgPrint(DEBUG_ARP, ("Unable to allocate data buffer\n"));
        Packet->Free(Packet);
        return;
    }

    BytesCopied = CopyPacketToBuffer(DataBuffer,
                                     Packet->NdisPacket,
                                     Packet->Position + sizeof(ARP_HEADER),
                                     DataSize);
    if (BytesCopied != DataSize)
    {
        TI_DbgPrint(DEBUG_ARP, ("Unable to copy in data buffer\n"));
        ExFreePool(DataBuffer);
        Packet->Free(Packet);
        return;
    }

    SenderHWAddress    = (PVOID)(DataBuffer);
    SenderProtoAddress = (PVOID)(SenderHWAddress + Header->HWAddrLen);
    TargetProtoAddress = (PVOID)(SenderProtoAddress + Header->ProtoAddrLen + Header->HWAddrLen);

    AddrInitIPv4(&DstAddress, *((PULONG)TargetProtoAddress));
    if (!AddrIsEqual(&DstAddress, &Interface->Unicast))
    {
        ExFreePool(DataBuffer);
        Packet->Free(Packet);
        return;
    }

    AddrInitIPv4(&SrcAddress, *((PULONG)SenderProtoAddress));

    /* Check if we know the sender */
    NCE = NBLocateNeighbor(&SrcAddress, Interface);
    if (NCE) {
        /* We know the sender. Update the hardware address
           and state in our neighbor address cache */
        NBUpdateNeighbor(NCE, SenderHWAddress, 0);
    } else {
        /* The packet had our protocol address as target. The sender
           may want to communicate with us soon, so add his address
           to our address cache */
        NBAddNeighbor(Interface, &SrcAddress, SenderHWAddress,
                      Header->HWAddrLen, 0, ARP_COMPLETE_TIMEOUT);
    }

    if (Header->Opcode != ARP_OPCODE_REQUEST)
    {
        ExFreePool(DataBuffer);
        Packet->Free(Packet);
        return;
    }

    /* This is a request for our address. Swap the addresses and
       send an ARP reply back to the sender */
    NdisPacket = PrepareARPPacket(
        Interface,
        Header->HWType,                  /* Hardware type */
        Header->ProtoType,               /* Protocol type */
        (UCHAR)Interface->AddressLength, /* Hardware address length */
        (UCHAR)Header->ProtoAddrLen,     /* Protocol address length */
        Interface->Address,              /* Sender's (local) hardware address */
        &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */
        SenderHWAddress,                 /* Target's (remote) hardware address */
        SenderProtoAddress,              /* Target's (remote) protocol address */
        ARP_OPCODE_REPLY);               /* ARP reply */
    if (NdisPacket) {
        PC(NdisPacket)->DLComplete = ARPTransmitComplete;
        (*Interface->Transmit)(Interface->Context,
                               NdisPacket,
                               0,
                               SenderHWAddress,
                               LAN_PROTO_ARP);
    }

    ExFreePool(DataBuffer);
    Packet->Free(Packet);
}
Esempio n. 10
0
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
  PIP_ADDRESS Address,
  PIP_INTERFACE Interface)
/*
 * FUNCTION: Locates a neighbor in the neighbor cache
 * ARGUMENTS:
 *   Address = Pointer to IP address
 *   Interface = Pointer to IP interface
 * RETURNS:
 *   Pointer to NCE, NULL if not found
 * NOTES:
 *   If the NCE is found, it is referenced. The caller is
 *   responsible for dereferencing it again after use
 */
{
  PNEIGHBOR_CACHE_ENTRY NCE;
  UINT HashValue;
  KIRQL OldIrql;
  PIP_INTERFACE FirstInterface;

  TI_DbgPrint(DEBUG_NCACHE, ("Called. Address (0x%X).\n", Address));

  HashValue = *(PULONG)&Address->Address;
  HashValue ^= HashValue >> 16;
  HashValue ^= HashValue >> 8;
  HashValue ^= HashValue >> 4;
  HashValue &= NB_HASHMASK;

  TcpipAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql);

  /* If there's no adapter specified, we'll look for a match on
   * each one. */
  if (Interface == NULL)
  {
      FirstInterface = GetDefaultInterface();
      Interface = FirstInterface;
  }
  else
  {
      FirstInterface = NULL;
  }

  do
  {
      NCE = NeighborCache[HashValue].Cache;
      while (NCE != NULL)
      {
         if (NCE->Interface == Interface &&
             AddrIsEqual(Address, &NCE->Address))
         {
             break;
         }
 
         NCE = NCE->Next;
      }
      
      if (NCE != NULL)
          break;
  }
  while ((FirstInterface != NULL) &&
         ((Interface = GetDefaultInterface()) != FirstInterface));

  if ((NCE == NULL) && (FirstInterface != NULL))
  {
      /* This time we'll even match loopback NCEs */
      NCE = NeighborCache[HashValue].Cache;
      while (NCE != NULL)
      {
         if (AddrIsEqual(Address, &NCE->Address))
         {
             break;
         }

         NCE = NCE->Next;
      }
  }

  TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);

  TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));

  return NCE;
}