ReactOS 0.4.15-dev-7934-g1dc8d80
arp.c File Reference
#include "precomp.h"
Include dependency graph for arp.c:

Go to the source code of this file.

Functions

PNDIS_PACKET PrepareARPPacket (PIP_INTERFACE IF, USHORT HardwareType, USHORT ProtocolType, UCHAR LinkAddressLength, UCHAR ProtoAddressLength, PVOID SenderLinkAddress, PVOID SenderProtoAddress, PVOID TargetLinkAddress, PVOID TargetProtoAddress, USHORT Opcode)
 
VOID ARPTransmitComplete (PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
 
BOOLEAN ARPTransmit (PIP_ADDRESS Address, PVOID LinkAddress, PIP_INTERFACE Interface)
 
VOID ARPReceive (PVOID Context, PIP_PACKET Packet)
 

Function Documentation

◆ ARPReceive()

VOID ARPReceive ( PVOID  Context,
PIP_PACKET  Packet 
)

Definition at line 175 of file arp.c.

184{
186 IP_ADDRESS SrcAddress;
187 IP_ADDRESS DstAddress;
188 PCHAR SenderHWAddress, SenderProtoAddress, TargetProtoAddress;
190 PNDIS_PACKET NdisPacket;
193 PCHAR DataBuffer;
194
195 PAGED_CODE();
196
197 TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
198
200 sizeof(ARP_HEADER),
202 if (!Packet->Header)
203 {
204 TI_DbgPrint(DEBUG_ARP, ("Unable to allocate header buffer\n"));
205 Packet->Free(Packet);
206 return;
207 }
208 Packet->MappedHeader = FALSE;
209
211 Packet->NdisPacket,
212 Packet->Position,
213 sizeof(ARP_HEADER));
214 if (BytesCopied != sizeof(ARP_HEADER))
215 {
216 TI_DbgPrint(DEBUG_ARP, ("Unable to copy in header buffer\n"));
217 Packet->Free(Packet);
218 return;
219 }
220
221 Header = (PARP_HEADER)Packet->Header;
222
223 /* FIXME: Ethernet only */
224 if (WN2H(Header->HWType) != 1) {
225 TI_DbgPrint(DEBUG_ARP, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header->HWType)));
226 Packet->Free(Packet);
227 return;
228 }
229
230 /* Check protocol type */
231 if (Header->ProtoType != ETYPE_IPv4) {
232 TI_DbgPrint(DEBUG_ARP, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header->ProtoType)));
233 Packet->Free(Packet);
234 return;
235 }
236
237 DataSize = (2 * Header->HWAddrLen) + (2 * Header->ProtoAddrLen);
238 DataBuffer = ExAllocatePool(PagedPool,
239 DataSize);
240 if (!DataBuffer)
241 {
242 TI_DbgPrint(DEBUG_ARP, ("Unable to allocate data buffer\n"));
243 Packet->Free(Packet);
244 return;
245 }
246
247 BytesCopied = CopyPacketToBuffer(DataBuffer,
248 Packet->NdisPacket,
249 Packet->Position + sizeof(ARP_HEADER),
250 DataSize);
251 if (BytesCopied != DataSize)
252 {
253 TI_DbgPrint(DEBUG_ARP, ("Unable to copy in data buffer\n"));
254 ExFreePool(DataBuffer);
255 Packet->Free(Packet);
256 return;
257 }
258
259 SenderHWAddress = (PVOID)(DataBuffer);
260 SenderProtoAddress = (PVOID)(SenderHWAddress + Header->HWAddrLen);
261 TargetProtoAddress = (PVOID)(SenderProtoAddress + Header->ProtoAddrLen + Header->HWAddrLen);
262
263 AddrInitIPv4(&DstAddress, *((PULONG)TargetProtoAddress));
264 if (!AddrIsEqual(&DstAddress, &Interface->Unicast))
265 {
266 ExFreePool(DataBuffer);
267 Packet->Free(Packet);
268 return;
269 }
270
271 AddrInitIPv4(&SrcAddress, *((PULONG)SenderProtoAddress));
272
273 /* Check if we know the sender */
274 NCE = NBLocateNeighbor(&SrcAddress, Interface);
275 if (NCE) {
276 /* We know the sender. Update the hardware address
277 and state in our neighbor address cache */
278 NBUpdateNeighbor(NCE, SenderHWAddress, 0);
279 } else {
280 /* The packet had our protocol address as target. The sender
281 may want to communicate with us soon, so add his address
282 to our address cache */
283 NBAddNeighbor(Interface, &SrcAddress, SenderHWAddress,
284 Header->HWAddrLen, 0, ARP_COMPLETE_TIMEOUT);
285 }
286
287 if (Header->Opcode != ARP_OPCODE_REQUEST)
288 {
289 ExFreePool(DataBuffer);
290 Packet->Free(Packet);
291 return;
292 }
293
294 /* This is a request for our address. Swap the addresses and
295 send an ARP reply back to the sender */
296 NdisPacket = PrepareARPPacket(
297 Interface,
298 Header->HWType, /* Hardware type */
299 Header->ProtoType, /* Protocol type */
300 (UCHAR)Interface->AddressLength, /* Hardware address length */
301 (UCHAR)Header->ProtoAddrLen, /* Protocol address length */
302 Interface->Address, /* Sender's (local) hardware address */
303 &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */
304 SenderHWAddress, /* Target's (remote) hardware address */
305 SenderProtoAddress, /* Target's (remote) protocol address */
306 ARP_OPCODE_REPLY); /* ARP reply */
307 if (NdisPacket) {
308 PC(NdisPacket)->DLComplete = ARPTransmitComplete;
309 (*Interface->Transmit)(Interface->Context,
310 NdisPacket,
311 0,
312 SenderHWAddress,
314 }
315
316 ExFreePool(DataBuffer);
317 Packet->Free(Packet);
318}
#define PAGED_CODE()
#define WN2H(w)
Definition: addrconv.c:35
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
BOOLEAN AddrIsEqual(PIP_ADDRESS Address1, PIP_ADDRESS Address2)
Definition: address.c:221
struct ARP_HEADER * PARP_HEADER
#define ARP_OPCODE_REQUEST
Definition: arp.h:23
#define ARP_OPCODE_REPLY
Definition: arp.h:24
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:172
Definition: Header.h:9
#define FALSE
Definition: types.h:117
#define DEBUG_ARP
Definition: debug.h:25
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
#define PC(Packet)
Definition: ip.h:106
struct _IP_INTERFACE * PIP_INTERFACE
#define PACKET_BUFFER_TAG
Definition: tags.h:27
PNDIS_PACKET PrepareARPPacket(PIP_INTERFACE IF, USHORT HardwareType, USHORT ProtocolType, UCHAR LinkAddressLength, UCHAR ProtoAddressLength, PVOID SenderLinkAddress, PVOID SenderProtoAddress, PVOID TargetLinkAddress, PVOID TargetProtoAddress, USHORT Opcode)
Definition: arp.c:13
VOID ARPTransmitComplete(PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
Definition: arp.c:92
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define ETYPE_IPv4
Definition: lan.h:121
#define LAN_PROTO_ARP
Definition: lan.h:128
if(dx< 0)
Definition: linetemp.h:194
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3171
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(PIP_ADDRESS Address, PIP_INTERFACE Interface)
Definition: neighbor.c:417
PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(PIP_INTERFACE Interface, PIP_ADDRESS Address, PVOID LinkAddress, UINT LinkAddressLength, UCHAR Type, UINT EventTimer)
Definition: neighbor.c:273
#define ARP_COMPLETE_TIMEOUT
Definition: neighbor.h:52
VOID NBUpdateNeighbor(PNEIGHBOR_CACHE_ENTRY NCE, PVOID LinkAddress, UCHAR State)
Definition: neighbor.c:346
Definition: arp.h:10
Definition: ip.h:23
Definition: neighbor.h:28
uint32_t * PULONG
Definition: typedefs.h:59
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE Interface
Definition: wdffdo.h:465
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by LanReceiveWorker().

◆ ARPTransmit()

BOOLEAN ARPTransmit ( PIP_ADDRESS  Address,
PVOID  LinkAddress,
PIP_INTERFACE  Interface 
)

Definition at line 111 of file arp.c.

120{
121 PNDIS_PACKET NdisPacket;
122 UCHAR ProtoAddrLen;
124
125 TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
126
127 /* If Address is NULL then the caller wants an
128 * gratuitous ARP packet sent */
129 if (!Address)
130 Address = &Interface->Unicast;
131
132 switch (Address->Type) {
133 case IP_ADDRESS_V4:
134 ProtoType = (USHORT)ETYPE_IPv4; /* IPv4 */
135 ProtoAddrLen = 4; /* Length of IPv4 address */
136 break;
137 case IP_ADDRESS_V6:
138 ProtoType = (USHORT)ETYPE_IPv6; /* IPv6 */
139 ProtoAddrLen = 16; /* Length of IPv6 address */
140 break;
141 default:
142 TI_DbgPrint(DEBUG_ARP,("Bad Address Type %x\n", Address->Type));
144 /* Should not happen */
145 return FALSE;
146 }
147
148 NdisPacket = PrepareARPPacket(
149 Interface,
150 WN2H(0x0001), /* FIXME: Ethernet only */
151 ProtoType, /* Protocol type */
152 (UCHAR)Interface->AddressLength, /* Hardware address length */
153 (UCHAR)ProtoAddrLen, /* Protocol address length */
154 Interface->Address, /* Sender's (local) hardware address */
155 &Interface->Unicast.Address.IPv4Address,/* Sender's (local) protocol address */
156 LinkAddress, /* Target's (remote) hardware address */
157 &Address->Address.IPv4Address, /* Target's (remote) protocol address */
158 ARP_OPCODE_REQUEST); /* ARP request */
159
160 if( !NdisPacket ) return FALSE;
161
162 ASSERT_KM_POINTER(NdisPacket);
163 ASSERT_KM_POINTER(PC(NdisPacket));
164 PC(NdisPacket)->DLComplete = ARPTransmitComplete;
165
166 TI_DbgPrint(DEBUG_ARP,("Sending ARP Packet\n"));
167
168 (*Interface->Transmit)(Interface->Context, NdisPacket,
169 0, NULL, LAN_PROTO_ARP);
170
171 return TRUE;
172}
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define ASSERT_KM_POINTER(_x)
Definition: debug.h:74
#define IP_ADDRESS_V6
Definition: ip.h:33
#define IP_ADDRESS_V4
Definition: ip.h:32
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define ETYPE_IPv6
Definition: lan.h:122
ProtoType
Definition: netstat.c:29
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68

Referenced by DispTdiQueryIpHwAddress(), IPAddInterfaceRoute(), and NBSendSolicit().

◆ ARPTransmitComplete()

VOID ARPTransmitComplete ( PVOID  Context,
PNDIS_PACKET  NdisPacket,
NDIS_STATUS  NdisStatus 
)

Definition at line 92 of file arp.c.

105{
106 TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
107 FreeNdisPacket(NdisPacket);
108}
#define FreeNdisPacket(x)
Definition: memtrack.h:8

Referenced by ARPReceive(), and ARPTransmit().

◆ PrepareARPPacket()

PNDIS_PACKET PrepareARPPacket ( PIP_INTERFACE  IF,
USHORT  HardwareType,
USHORT  ProtocolType,
UCHAR  LinkAddressLength,
UCHAR  ProtoAddressLength,
PVOID  SenderLinkAddress,
PVOID  SenderProtoAddress,
PVOID  TargetLinkAddress,
PVOID  TargetProtoAddress,
USHORT  Opcode 
)

Definition at line 13 of file arp.c.

39{
40 PNDIS_PACKET NdisPacket;
41 NDIS_STATUS NdisStatus;
43 PVOID DataBuffer;
44 ULONG Size, Contig;
45
46 TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
47
48 /* Prepare ARP packet */
49 Size = sizeof(ARP_HEADER) +
50 2 * LinkAddressLength + /* Hardware address length */
51 2 * ProtoAddressLength; /* Protocol address length */
52 Size = MAX(Size, IF->MinFrameSize - IF->HeaderSize);
53
54 NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
55 if( !NT_SUCCESS(NdisStatus) ) return NULL;
56
57 GetDataPtr( NdisPacket, 0, (PCHAR *)&DataBuffer, (PUINT)&Contig );
58 ASSERT(DataBuffer);
59
60 RtlZeroMemory(DataBuffer, Size);
61 Header = (PARP_HEADER)((ULONG_PTR)DataBuffer);
62 Header->HWType = HardwareType;
63 Header->ProtoType = ProtocolType;
64 Header->HWAddrLen = LinkAddressLength;
65 Header->ProtoAddrLen = ProtoAddressLength;
66 Header->Opcode = Opcode; /* Already swapped */
67 DataBuffer = (PVOID)((ULONG_PTR)Header + sizeof(ARP_HEADER));
68
69 /* Our hardware address */
70 RtlCopyMemory(DataBuffer, SenderLinkAddress, LinkAddressLength);
71 DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + LinkAddressLength);
72
73 /* Our protocol address */
74 RtlCopyMemory(DataBuffer, SenderProtoAddress, ProtoAddressLength);
75
76 if (TargetLinkAddress) {
77 DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + ProtoAddressLength);
78 /* Target hardware address */
79 RtlCopyMemory(DataBuffer, TargetLinkAddress, LinkAddressLength);
80 DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + LinkAddressLength);
81 } else
82 /* Don't care about target hardware address */
83 DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + ProtoAddressLength + LinkAddressLength);
84
85 /* Target protocol address */
86 RtlCopyMemory(DataBuffer, TargetProtoAddress, ProtoAddressLength);
87
88 return NdisPacket;
89}
#define MAX(x, y)
Definition: rdesktop.h:175
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ PVOID _In_ ULONG Opcode
Definition: hubbusif.h:331
void GetDataPtr(PNDIS_PACKET Packet, UINT Offset, PCHAR *DataOut, PUINT Size)
Definition: routines.c:65
#define AllocatePacketWithBuffer(x, y, z)
Definition: memtrack.h:7
#define ASSERT(a)
Definition: mode.c:44
unsigned int * PUINT
Definition: ndis.h:50
int NDIS_STATUS
Definition: ntddndis.h:475
UINT MinFrameSize
Definition: ip.h:156
UINT HeaderSize
Definition: ip.h:155
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by ARPReceive(), and ARPTransmit().