Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenarp.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
1.7.6.1
|