2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
5 * PURPOSE: Address Resolution Protocol routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 PNDIS_PACKET
PrepareARPPacket(
16 UCHAR LinkAddressLength
,
17 UCHAR ProtoAddressLength
,
18 PVOID SenderLinkAddress
,
19 PVOID SenderProtoAddress
,
20 PVOID TargetLinkAddress
,
21 PVOID TargetProtoAddress
,
24 * FUNCTION: Prepares an ARP packet
26 * HardwareType = Hardware type (in network byte order)
27 * ProtocolType = Protocol type (in network byte order)
28 * LinkAddressLength = Length of link address fields
29 * ProtoAddressLength = Length of protocol address fields
30 * SenderLinkAddress = Sender's link address
31 * SenderProtoAddress = Sender's protocol address
32 * TargetLinkAddress = Target's link address (NULL if don't care)
33 * TargetProtoAddress = Target's protocol address
34 * Opcode = ARP opcode (in network byte order)
36 * Pointer to NDIS packet, NULL if there is not enough free resources
39 PNDIS_PACKET NdisPacket
;
40 NDIS_STATUS NdisStatus
;
45 TI_DbgPrint(DEBUG_ARP
, ("Called.\n"));
47 /* Prepare ARP packet */
48 Size
= MaxLLHeaderSize
+
50 2 * LinkAddressLength
+ /* Hardware address length */
51 2 * ProtoAddressLength
; /* Protocol address length */
52 Size
= MAX(Size
, MinLLFrameSize
);
54 NdisStatus
= AllocatePacketWithBuffer( &NdisPacket
, NULL
, Size
);
55 if( !NT_SUCCESS(NdisStatus
) ) return NULL
;
57 GetDataPtr( NdisPacket
, 0, (PCHAR
*)&DataBuffer
, (PUINT
)&Contig
);
59 RtlZeroMemory(DataBuffer
, Size
);
60 Header
= (PARP_HEADER
)((ULONG_PTR
)DataBuffer
+ MaxLLHeaderSize
);
61 Header
->HWType
= HardwareType
;
62 Header
->ProtoType
= ProtocolType
;
63 Header
->HWAddrLen
= LinkAddressLength
;
64 Header
->ProtoAddrLen
= ProtoAddressLength
;
65 Header
->Opcode
= Opcode
; /* Already swapped */
66 DataBuffer
= (PVOID
)((ULONG_PTR
)Header
+ sizeof(ARP_HEADER
));
68 /* Our hardware address */
69 RtlCopyMemory(DataBuffer
, SenderLinkAddress
, LinkAddressLength
);
70 DataBuffer
= (PVOID
)((ULONG_PTR
)DataBuffer
+ LinkAddressLength
);
72 /* Our protocol address */
73 RtlCopyMemory(DataBuffer
, SenderProtoAddress
, ProtoAddressLength
);
75 if (TargetLinkAddress
) {
76 DataBuffer
= (PVOID
)((ULONG_PTR
)DataBuffer
+ ProtoAddressLength
);
77 /* Target hardware address */
78 RtlCopyMemory(DataBuffer
, TargetLinkAddress
, LinkAddressLength
);
79 DataBuffer
= (PVOID
)((ULONG_PTR
)DataBuffer
+ LinkAddressLength
);
81 /* Don't care about target hardware address */
82 DataBuffer
= (PVOID
)((ULONG_PTR
)DataBuffer
+ ProtoAddressLength
+ LinkAddressLength
);
84 /* Target protocol address */
85 RtlCopyMemory(DataBuffer
, TargetProtoAddress
, ProtoAddressLength
);
91 VOID
ARPTransmitComplete(
93 PNDIS_PACKET NdisPacket
,
94 NDIS_STATUS NdisStatus
)
96 * FUNCTION: ARP request transmit completion handler
98 * Context = Pointer to context information (IP_INTERFACE)
99 * Packet = Pointer to NDIS packet that was sent
100 * NdisStatus = NDIS status of operation
102 * This routine is called when an ARP request has been sent
105 TI_DbgPrint(DEBUG_ARP
, ("Called.\n"));
106 FreeNdisPacket(NdisPacket
);
112 PNET_TABLE_ENTRY NTE
)
114 * FUNCTION: Creates an ARP request and transmits it on a network
116 * Address = Pointer to IP address to resolve
117 * NTE = Pointer to net table entru to use for transmitting request
119 * TRUE if the request was successfully sent, FALSE if not
122 PIP_INTERFACE Interface
;
123 PNDIS_PACKET NdisPacket
;
127 TI_DbgPrint(DEBUG_ARP
, ("Called.\n"));
129 Interface
= NTE
->Interface
;
131 switch (Address
->Type
) {
133 ProtoType
= (USHORT
)ETYPE_IPv4
; /* IPv4 */
134 ProtoAddrLen
= 4; /* Length of IPv4 address */
137 ProtoType
= (USHORT
)ETYPE_IPv6
; /* IPv6 */
138 ProtoAddrLen
= 16; /* Length of IPv6 address */
141 TI_DbgPrint(DEBUG_ARP
,("Bad Address Type %x\n", Address
->Type
));
143 /* Should not happen */
147 NdisPacket
= PrepareARPPacket(
148 WN2H(0x0001), /* FIXME: Ethernet only */
149 ProtoType
, /* Protocol type */
150 (UCHAR
)Interface
->AddressLength
, /* Hardware address length */
151 (UCHAR
)ProtoAddrLen
, /* Protocol address length */
152 Interface
->Address
, /* Sender's (local) hardware address */
153 &NTE
->Address
->Address
, /* Sender's (local) protocol address */
154 NULL
, /* Don't care */
155 &Address
->Address
, /* Target's (remote) protocol address */
156 ARP_OPCODE_REQUEST
); /* ARP request */
158 PC(NdisPacket
)->DLComplete
= ARPTransmitComplete
;
160 TI_DbgPrint(DEBUG_ARP
,("Sending ARP Packet\n"));
162 (*Interface
->Transmit
)(Interface
->Context
, NdisPacket
,
163 MaxLLHeaderSize
, NULL
, LAN_PROTO_ARP
);
173 * FUNCTION: Receives an ARP packet
175 * Context = Pointer to context information (IP_INTERFACE)
176 * Packet = Pointer to packet
181 PVOID SenderHWAddress
;
182 PVOID SenderProtoAddress
;
183 PVOID TargetProtoAddress
;
185 PNEIGHBOR_CACHE_ENTRY NCE
;
186 PNDIS_PACKET NdisPacket
;
187 PIP_INTERFACE Interface
= (PIP_INTERFACE
)Context
;
189 TI_DbgPrint(DEBUG_ARP
, ("Called.\n"));
191 Header
= (PARP_HEADER
)Packet
->Header
;
193 /* FIXME: Ethernet only */
194 if (WN2H(Header
->HWType
) != 1) {
195 TI_DbgPrint(DEBUG_ARP
, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header
->HWType
)));
199 /* Check protocol type */
200 if (Header
->ProtoType
!= ETYPE_IPv4
) {
201 TI_DbgPrint(DEBUG_ARP
, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header
->ProtoType
)));
205 SenderHWAddress
= (PVOID
)((ULONG_PTR
)Header
+ sizeof(ARP_HEADER
));
206 SenderProtoAddress
= (PVOID
)((ULONG_PTR
)SenderHWAddress
+ Header
->HWAddrLen
);
208 /* Check if we have the target protocol address */
210 TargetProtoAddress
= (PVOID
)((ULONG_PTR
)SenderProtoAddress
+
211 Header
->ProtoAddrLen
+ Header
->HWAddrLen
);
213 Address
= AddrBuildIPv4(*((PULONG
)TargetProtoAddress
));
214 ADE
= IPLocateADE(Address
, ADE_UNICAST
);
216 TI_DbgPrint(DEBUG_ARP
, ("Target address (0x%X) is not mine.\n", *((PULONG
)TargetProtoAddress
)));
220 /* Check if we know the sender */
222 AddrInitIPv4(Address
, *((PULONG
)SenderProtoAddress
));
223 NCE
= NBLocateNeighbor(Address
);
225 /* We know the sender. Update the hardware address
226 and state in our neighbor address cache */
227 NBUpdateNeighbor(NCE
, SenderHWAddress
, NUD_REACHABLE
);
229 /* The packet had our protocol address as target. The sender
230 may want to communicate with us soon, so add his address
231 to our address cache */
232 NCE
= NBAddNeighbor(Interface
, Address
, SenderHWAddress
,
233 Header
->HWAddrLen
, NUD_REACHABLE
);
236 if (Header
->Opcode
!= ARP_OPCODE_REQUEST
)
239 /* This is a request for our address. Swap the addresses and
240 send an ARP reply back to the sender */
241 NdisPacket
= PrepareARPPacket(
242 Header
->HWType
, /* Hardware type */
243 Header
->ProtoType
, /* Protocol type */
244 (UCHAR
)Interface
->AddressLength
, /* Hardware address length */
245 (UCHAR
)Header
->ProtoAddrLen
, /* Protocol address length */
246 Interface
->Address
, /* Sender's (local) hardware address */
247 &ADE
->Address
->Address
, /* Sender's (local) protocol address */
248 SenderHWAddress
, /* Target's (remote) hardware address */
249 SenderProtoAddress
, /* Target's (remote) protocol address */
250 ARP_OPCODE_REPLY
); /* ARP reply */
252 PC(NdisPacket
)->DLComplete
= ARPTransmitComplete
;
253 (*Interface
->Transmit
)(Interface
->Context
,