ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

arp.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        datalink/arp.c
00005  * PURPOSE:     Address Resolution Protocol routines
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 01/08-2000 Created
00009  */
00010 
00011 #include "precomp.h"
00012 
00013 PNDIS_PACKET PrepareARPPacket(
00014     PIP_INTERFACE IF,
00015     USHORT HardwareType,
00016     USHORT ProtocolType,
00017     UCHAR LinkAddressLength,
00018     UCHAR ProtoAddressLength,
00019     PVOID SenderLinkAddress,
00020     PVOID SenderProtoAddress,
00021     PVOID TargetLinkAddress,
00022     PVOID TargetProtoAddress,
00023     USHORT Opcode)
00024 /*
00025  * FUNCTION: Prepares an ARP packet
00026  * ARGUMENTS:
00027  *     HardwareType       = Hardware type (in network byte order)
00028  *     ProtocolType       = Protocol type (in network byte order)
00029  *     LinkAddressLength  = Length of link address fields
00030  *     ProtoAddressLength = Length of protocol address fields
00031  *     SenderLinkAddress  = Sender's link address
00032  *     SenderProtoAddress = Sender's protocol address
00033  *     TargetLinkAddress  = Target's link address (NULL if don't care)
00034  *     TargetProtoAddress = Target's protocol address
00035  *     Opcode             = ARP opcode (in network byte order)
00036  * RETURNS:
00037  *     Pointer to NDIS packet, NULL if there is not enough free resources
00038  */
00039 {
00040     PNDIS_PACKET NdisPacket;
00041     NDIS_STATUS NdisStatus;
00042     PARP_HEADER Header;
00043     PVOID DataBuffer;
00044     ULONG Size, Contig;
00045 
00046     TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
00047 
00048     /* Prepare ARP packet */
00049     Size = sizeof(ARP_HEADER) +
00050         2 * LinkAddressLength + /* Hardware address length */
00051         2 * ProtoAddressLength; /* Protocol address length */
00052     Size = MAX(Size, IF->MinFrameSize - IF->HeaderSize);
00053 
00054     NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
00055     if( !NT_SUCCESS(NdisStatus) ) return NULL;
00056 
00057     GetDataPtr( NdisPacket, 0, (PCHAR *)&DataBuffer, (PUINT)&Contig );
00058     ASSERT(DataBuffer);
00059 
00060     RtlZeroMemory(DataBuffer, Size);
00061     Header = (PARP_HEADER)((ULONG_PTR)DataBuffer);
00062     Header->HWType       = HardwareType;
00063     Header->ProtoType    = ProtocolType;
00064     Header->HWAddrLen    = LinkAddressLength;
00065     Header->ProtoAddrLen = ProtoAddressLength;
00066     Header->Opcode       = Opcode; /* Already swapped */
00067     DataBuffer = (PVOID)((ULONG_PTR)Header + sizeof(ARP_HEADER));
00068 
00069     /* Our hardware address */
00070     RtlCopyMemory(DataBuffer, SenderLinkAddress, LinkAddressLength);
00071     DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + LinkAddressLength);
00072 
00073     /* Our protocol address */
00074     RtlCopyMemory(DataBuffer, SenderProtoAddress, ProtoAddressLength);
00075 
00076     if (TargetLinkAddress) {
00077         DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + ProtoAddressLength);
00078         /* Target hardware address */
00079         RtlCopyMemory(DataBuffer, TargetLinkAddress, LinkAddressLength);
00080         DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + LinkAddressLength);
00081     } else
00082         /* Don't care about target hardware address */
00083         DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + ProtoAddressLength + LinkAddressLength);
00084 
00085     /* Target protocol address */
00086     RtlCopyMemory(DataBuffer, TargetProtoAddress, ProtoAddressLength);
00087 
00088     return NdisPacket;
00089 }
00090 
00091 
00092 VOID ARPTransmitComplete(
00093     PVOID Context,
00094     PNDIS_PACKET NdisPacket,
00095     NDIS_STATUS NdisStatus)
00096 /*
00097  * FUNCTION: ARP request transmit completion handler
00098  * ARGUMENTS:
00099  *     Context    = Pointer to context information (IP_INTERFACE)
00100  *     Packet     = Pointer to NDIS packet that was sent
00101  *     NdisStatus = NDIS status of operation
00102  * NOTES:
00103  *    This routine is called when an ARP request has been sent
00104  */
00105 {
00106     TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
00107     FreeNdisPacket(NdisPacket);
00108 }
00109 
00110 
00111 BOOLEAN ARPTransmit(PIP_ADDRESS Address, PVOID LinkAddress,
00112                     PIP_INTERFACE Interface)
00113 /*
00114  * FUNCTION: Creates an ARP request and transmits it on a network
00115  * ARGUMENTS:
00116  *     Address = Pointer to IP address to resolve
00117  * RETURNS:
00118  *     TRUE if the request was successfully sent, FALSE if not
00119  */
00120 {
00121     PNDIS_PACKET NdisPacket;
00122     UCHAR ProtoAddrLen;
00123     USHORT ProtoType;
00124 
00125     TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
00126 
00127     /* If Address is NULL then the caller wants an
00128      * gratuitous ARP packet sent */
00129     if (!Address)
00130         Address = &Interface->Unicast;
00131 
00132     switch (Address->Type) {
00133         case IP_ADDRESS_V4:
00134             ProtoType    = (USHORT)ETYPE_IPv4; /* IPv4 */
00135             ProtoAddrLen = 4;                  /* Length of IPv4 address */
00136             break;
00137         case IP_ADDRESS_V6:
00138             ProtoType    = (USHORT)ETYPE_IPv6; /* IPv6 */
00139             ProtoAddrLen = 16;                 /* Length of IPv6 address */
00140             break;
00141         default:
00142         TI_DbgPrint(DEBUG_ARP,("Bad Address Type %x\n", Address->Type));
00143         DbgBreakPoint();
00144             /* Should not happen */
00145             return FALSE;
00146     }
00147 
00148     NdisPacket = PrepareARPPacket(
00149         Interface,
00150         WN2H(0x0001),                    /* FIXME: Ethernet only */
00151         ProtoType,                       /* Protocol type */
00152         (UCHAR)Interface->AddressLength, /* Hardware address length */
00153         (UCHAR)ProtoAddrLen,             /* Protocol address length */
00154         Interface->Address,              /* Sender's (local) hardware address */
00155         &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */
00156         LinkAddress,                     /* Target's (remote) hardware address */
00157         &Address->Address.IPv4Address,   /* Target's (remote) protocol address */
00158         ARP_OPCODE_REQUEST);             /* ARP request */
00159 
00160     if( !NdisPacket ) return FALSE;
00161 
00162     ASSERT_KM_POINTER(NdisPacket);
00163     ASSERT_KM_POINTER(PC(NdisPacket));
00164     PC(NdisPacket)->DLComplete = ARPTransmitComplete;
00165 
00166     TI_DbgPrint(DEBUG_ARP,("Sending ARP Packet\n"));
00167 
00168     (*Interface->Transmit)(Interface->Context, NdisPacket,
00169         0, NULL, LAN_PROTO_ARP);
00170 
00171     return TRUE;
00172 }
00173 
00174 
00175 VOID ARPReceive(
00176     PVOID Context,
00177     PIP_PACKET Packet)
00178 /*
00179  * FUNCTION: Receives an ARP packet
00180  * ARGUMENTS:
00181  *     Context = Pointer to context information (IP_INTERFACE)
00182  *     Packet  = Pointer to packet
00183  */
00184 {
00185     PARP_HEADER Header;
00186     IP_ADDRESS SrcAddress;
00187     IP_ADDRESS DstAddress;
00188     PCHAR SenderHWAddress, SenderProtoAddress, TargetProtoAddress;
00189     PNEIGHBOR_CACHE_ENTRY NCE;
00190     PNDIS_PACKET NdisPacket;
00191     PIP_INTERFACE Interface = (PIP_INTERFACE)Context;
00192     ULONG BytesCopied, DataSize;
00193     PCHAR DataBuffer;
00194     
00195     PAGED_CODE();
00196 
00197     TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
00198 
00199     Packet->Header = ExAllocatePoolWithTag(PagedPool,
00200                                            sizeof(ARP_HEADER),
00201                                            PACKET_BUFFER_TAG);
00202     if (!Packet->Header)
00203     {
00204         TI_DbgPrint(DEBUG_ARP, ("Unable to allocate header buffer\n"));
00205         Packet->Free(Packet);
00206         return;
00207     }
00208     Packet->MappedHeader = FALSE;
00209 
00210     BytesCopied = CopyPacketToBuffer((PCHAR)Packet->Header,
00211                                      Packet->NdisPacket,
00212                                      Packet->Position,
00213                                      sizeof(ARP_HEADER));
00214     if (BytesCopied != sizeof(ARP_HEADER))
00215     {
00216         TI_DbgPrint(DEBUG_ARP, ("Unable to copy in header buffer\n"));
00217         Packet->Free(Packet);
00218         return;
00219     }
00220 
00221     Header = (PARP_HEADER)Packet->Header;
00222 
00223     /* FIXME: Ethernet only */
00224     if (WN2H(Header->HWType) != 1) {
00225         TI_DbgPrint(DEBUG_ARP, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header->HWType)));
00226         Packet->Free(Packet);
00227         return;
00228     }
00229 
00230     /* Check protocol type */
00231     if (Header->ProtoType != ETYPE_IPv4) {
00232         TI_DbgPrint(DEBUG_ARP, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header->ProtoType)));
00233         Packet->Free(Packet);
00234         return;
00235     }
00236 
00237     DataSize = (2 * Header->HWAddrLen) + (2 * Header->ProtoAddrLen);
00238     DataBuffer = ExAllocatePool(PagedPool,
00239                                 DataSize);
00240     if (!DataBuffer)
00241     {
00242         TI_DbgPrint(DEBUG_ARP, ("Unable to allocate data buffer\n"));
00243         Packet->Free(Packet);
00244         return;
00245     }
00246 
00247     BytesCopied = CopyPacketToBuffer(DataBuffer,
00248                                      Packet->NdisPacket,
00249                                      Packet->Position + sizeof(ARP_HEADER),
00250                                      DataSize);
00251     if (BytesCopied != DataSize)
00252     {
00253         TI_DbgPrint(DEBUG_ARP, ("Unable to copy in data buffer\n"));
00254         ExFreePool(DataBuffer);
00255         Packet->Free(Packet);
00256         return;
00257     }
00258 
00259     SenderHWAddress    = (PVOID)(DataBuffer);
00260     SenderProtoAddress = (PVOID)(SenderHWAddress + Header->HWAddrLen);
00261     TargetProtoAddress = (PVOID)(SenderProtoAddress + Header->ProtoAddrLen + Header->HWAddrLen);
00262 
00263     AddrInitIPv4(&DstAddress, *((PULONG)TargetProtoAddress));
00264     if (!AddrIsEqual(&DstAddress, &Interface->Unicast))
00265     {
00266         ExFreePool(DataBuffer);
00267         Packet->Free(Packet);
00268         return;
00269     }
00270 
00271     AddrInitIPv4(&SrcAddress, *((PULONG)SenderProtoAddress));
00272 
00273     /* Check if we know the sender */
00274     NCE = NBLocateNeighbor(&SrcAddress);
00275     if (NCE) {
00276         /* We know the sender. Update the hardware address
00277            and state in our neighbor address cache */
00278         NBUpdateNeighbor(NCE, SenderHWAddress, 0);
00279     } else {
00280         /* The packet had our protocol address as target. The sender
00281            may want to communicate with us soon, so add his address
00282            to our address cache */
00283         NBAddNeighbor(Interface, &SrcAddress, SenderHWAddress,
00284                       Header->HWAddrLen, 0, ARP_COMPLETE_TIMEOUT);
00285     }
00286 
00287     if (Header->Opcode != ARP_OPCODE_REQUEST)
00288     {
00289         ExFreePool(DataBuffer);
00290         Packet->Free(Packet);
00291         return;
00292     }
00293 
00294     /* This is a request for our address. Swap the addresses and
00295        send an ARP reply back to the sender */
00296     NdisPacket = PrepareARPPacket(
00297         Interface,
00298         Header->HWType,                  /* Hardware type */
00299         Header->ProtoType,               /* Protocol type */
00300         (UCHAR)Interface->AddressLength, /* Hardware address length */
00301         (UCHAR)Header->ProtoAddrLen,     /* Protocol address length */
00302         Interface->Address,              /* Sender's (local) hardware address */
00303         &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */
00304         SenderHWAddress,                 /* Target's (remote) hardware address */
00305         SenderProtoAddress,              /* Target's (remote) protocol address */
00306         ARP_OPCODE_REPLY);               /* ARP reply */
00307     if (NdisPacket) {
00308         PC(NdisPacket)->DLComplete = ARPTransmitComplete;
00309         (*Interface->Transmit)(Interface->Context,
00310                                NdisPacket,
00311                                0,
00312                                SenderHWAddress,
00313                                LAN_PROTO_ARP);
00314     }
00315 
00316     ExFreePool(DataBuffer);
00317     Packet->Free(Packet);
00318 }
00319 
00320 /* EOF */

Generated on Sat May 26 2012 04:16:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.