3 * - Address Resolution Protocol
4 * - Part of the IPv4 protocol
10 #include "ipv4.h" // For IPv4_Netmask
11 #include "include/adapters_int.h" // for MAC addr
12 #include <semaphore.h>
14 #include "hwaddr_cache.h"
17 #define ARP_CACHE_SIZE 128
18 #define ARP_MAX_AGE (60*60*1000) // 1Hr
21 extern tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
23 extern tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
28 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
34 * \fn int ARP_Initialise()
35 * \brief Initalise the ARP section
39 Link_RegisterType(0x0806, ARP_int_GetPacket);
43 void ARP_Request4(tInterface *Interface, tIPv4 Address)
45 struct sArpRequest4 req;
47 Log_Log("ARP4", "Asking for address %i.%i.%i.%i",
48 Address.B[0], Address.B[1], Address.B[2], Address.B[3]
50 req.HWType = htons(0x0001); // Ethernet
51 req.Type = htons(0x0800);
54 req.Request = htons(1);
55 memcpy(&req.SourceMac, Interface->Adapter->HWAddr, 6); // TODO: Remove hard size
56 req.SourceIP = *(tIPv4*)Interface->Address;
57 req.DestMac = cMAC_BROADCAST;
60 // Assumes only a header and footer at link layer
61 tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3);
62 IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, &req, NULL, NULL);
65 Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, buffer);
69 * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
70 * \brief Called when an ARP packet is recieved
72 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
74 tArpRequest4 *req4 = Buffer;
76 tArpRequest6 *req6 = Buffer;
80 // Sanity Check Packet
81 if( Length < (int)sizeof(tArpRequest4) ) {
82 Log_Log("ARP", "Recieved undersized packet");
85 if( ntohs(req4->Type) != 0x0800 ) {
86 Log_Log("ARP", "Recieved a packet with a bad type (0x%x)", ntohs(req4->Type));
89 if( req4->HWSize != 6 ) {
90 Log_Log("ARP", "Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
94 if( !MAC_EQU(req4->SourceMac, From) ) {
95 Log_Log("ARP", "ARP spoofing detected "
96 "(%02x%02x:%02x%02x:%02x%02x != %02x%02x:%02x%02x:%02x%02x)",
97 req4->SourceMac.B[0], req4->SourceMac.B[1], req4->SourceMac.B[2],
98 req4->SourceMac.B[3], req4->SourceMac.B[4], req4->SourceMac.B[5],
99 From.B[0], From.B[1], From.B[2],
100 From.B[3], From.B[4], From.B[5]
106 switch( ntohs(req4->Request) )
108 case 1: // You want my IP?
109 // Check what type of IP it is
110 switch( req4->SWSize )
113 iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
116 Log_Debug("ARP", "ARP Request IPv4 Address %i.%i.%i.%i from %i.%i.%i.%i"
117 " (%02x:%02x:%02x:%02x:%02x:%02x)",
118 req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
120 req4->SourceIP.B[0], req4->SourceIP.B[1],
121 req4->SourceIP.B[2], req4->SourceIP.B[3],
122 req4->SourceMac.B[0], req4->SourceMac.B[1],
123 req4->SourceMac.B[2], req4->SourceMac.B[3],
124 req4->SourceMac.B[4], req4->SourceMac.B[5]);
125 // Someone has ARPed us, let's cache them
126 HWCache_Set(Adapter, 4, &req4->SourceIP, &req4->SourceMac);
128 req4->DestIP = req4->SourceIP;
129 req4->DestMac = req4->SourceMac;
130 req4->SourceIP = *(tIPv4*)iface->Address;;
131 memcpy(&req4->SourceMac, Adapter->HWAddr, 6); // TODO: Remove hard size
132 req4->Request = htons(2);
133 Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)",
134 req4->SourceMac.B[0], req4->SourceMac.B[1],
135 req4->SourceMac.B[2], req4->SourceMac.B[3],
136 req4->SourceMac.B[4], req4->SourceMac.B[5]);
138 // Assumes only a header and footer at link layer
139 tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3);
140 IPStack_Buffer_AppendSubBuffer(buffer,
141 sizeof(struct sArpRequest4), 0, req4,
143 Link_SendPacket(Adapter, 0x0806, req4->DestMac, buffer);
148 if( Length < (int)sizeof(tArpRequest6) ) {
149 Log_Log("ARP", "Recieved undersized packet (IPv6)");
152 Log_Debug("ARP", "ARP Request IPv6 Address %08x:%08x:%08x:%08x",
153 ntohl(req6->DestIP.L[0]), ntohl(req6->DestIP.L[1]),
154 ntohl(req6->DestIP.L[2]), ntohl(req6->DestIP.L[3])
156 iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
159 req6->DestIP = req6->SourceIP;
160 req6->DestMac = req6->SourceMac;
161 req6->SourceIP = *(tIPv6*)iface->Address;
162 req6->SourceMac = Adapter->MacAddr;
163 req6->Request = htons(2);
164 Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)",
165 req4->SourceMac.B[0], req4->SourceMac.B[1],
166 req4->SourceMac.B[2], req4->SourceMac.B[3],
167 req4->SourceMac.B[4], req4->SourceMac.B[5]);
168 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
173 Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
179 case 2: // Ooh! A response!
180 // Check what type of IP it is
181 switch( req4->SWSize )
184 HWCache_Set(Adapter, 4, &req4->SourceIP, &From);
188 if( Length < (int)sizeof(tArpRequest6) ) {
189 Log_Debug("ARP", "Recieved undersized packet (IPv6)");
192 HWCache_Set(Adapter, 6, &req6->SourceIP, &From );
196 Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
203 Log_Warning("ARP", "Unknown Request ID %i", ntohs(req4->Request));