FreeNOS
ARP.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <ByteOrder.h>
19#include "NetworkClient.h"
20#include "NetworkServer.h"
21#include "NetworkDevice.h"
22#include "ARP.h"
23#include "ARPSocket.h"
24
26 NetworkDevice &device,
27 NetworkProtocol &parent)
28 : NetworkProtocol(server, device, parent)
29{
30 m_ip = 0;
31}
32
34{
36 {
37 delete i.current();
38 }
39}
40
49
51{
52 m_ip = ip;
53}
54
56{
57 ARPCache **entry = (ARPCache **) m_cache.get(ipAddr);
58 if (entry)
59 return (*entry);
60 else
61 return insertCacheEntry(ipAddr);
62}
63
65{
66 ARPCache *entry = new ARPCache;
67 MemoryBlock::set(entry, 0, sizeof(*entry));
68 entry->valid = false;
69
70 // Insert to the ARP cache
71 m_cache.insert(ipAddr, entry);
72 return entry;
73}
74
76 const Ethernet::Address *ethAddr)
77{
78 ARPCache *entry = getCacheEntry(ipAddr);
79 if (entry)
80 {
81 entry->valid = true;
82 MemoryBlock::copy(&entry->ethAddr, ethAddr, sizeof(Ethernet::Address));
83 }
84}
85
87 Ethernet::Address *ethAddr)
88{
89 DEBUG("");
90
91 // See if we have the IP cached
92 const ARPCache *entry = getCacheEntry(*ipAddr);
93 if (entry && entry->valid)
94 {
95 MemoryBlock::copy(ethAddr, &entry->ethAddr, sizeof(Ethernet::Address));
97 }
98
99 // Is this a broadcast address?
100 if (*ipAddr == 0xffffffff)
101 {
102 MemoryBlock::set(ethAddr, 0xff, sizeof(Ethernet::Address));
103 return FileSystem::Success;
104 }
105
106 // See if timeout has expired for re-transmission
108 Timer::Info inf;
110 DEBUG("entry->time.ticks = " << entry->time.ticks <<
111 " entry->time.freq = " << entry->time.frequency <<
112 " kernelTimer.ticks = " << inf.ticks <<
113 " kernelTimer.freq = " << inf.frequency);
114
115 if (!entry->time.ticks || m_kernelTimer.isExpired(entry->time))
116 {
117 DEBUG("entry timeout: re-transmitting");
118
119 // Send an ARP request
120 const FileSystem::Result result = sendRequest(*ipAddr);
121 if (result != FileSystem::Success && result != FileSystem::RetryAgain)
122 {
123 ERROR("failed to send request: result = " << (int) result);
124 return result;
125 }
126 }
127
128 // Make sure we are called again in about 500msec (or earlier)
129 m_server.setTimeout(500);
131}
132
134{
135 DEBUG("address = " << *IPV4::toString(address));
136
137 // Get cache entry
138 ARPCache *entry = getCacheEntry(address);
139 if (!entry)
140 {
142 }
143
144 // Update the cache entry administration
145 entry->valid = false;
146 entry->retryCount++;
147 if (entry->retryCount > MaxRetries)
148 {
149 entry->retryCount = 0;
151 }
153 m_kernelTimer.getCurrent(&entry->time, 500);
154
155 // Destination is broadcast ethernet address
156 Ethernet::Address destAddr;
157 MemoryBlock::set(&destAddr, 0xff, sizeof(destAddr));
158
159 // Get a fresh ethernet packet
161 const FileSystem::Result result = m_parent.getTransmitPacket(&pkt, &destAddr, sizeof(destAddr),
163 if (result != FileSystem::Success)
164 {
165 if (result != FileSystem::RetryAgain)
166 {
167 ERROR("failed to get transmit packet: result = " << (int) result);
168 }
169 return result;
170 }
171
172 Ethernet::Header *ether = (Ethernet::Header *) (pkt->data + pkt->size - sizeof(Ethernet::Header));
173 ARP::Header *arp = (ARP::Header *) (pkt->data + pkt->size);
174 pkt->size += sizeof(ARP::Header);
175
176 // Fill the ARP packet
180 arp->hardwareLength = sizeof(Ethernet::Address);
181 arp->protocolLength = sizeof(IPV4::Address);
182
183 // Get our current IP
184 IPV4::Address ipaddr;
185 m_ip->getAddress(&ipaddr);
186
187 // Fill source and destinations
188 MemoryBlock::copy(&arp->etherSender, &ether->source, sizeof(Ethernet::Address));
190 writeBe32(&arp->ipSender, ipaddr);
191 writeBe32(&arp->ipTarget, address);
192
193 // Send the packet using the network device
194 return m_device.transmit(pkt);
195}
196
198{
199 DEBUG("");
200
201 if (!m_ip)
202 {
204 }
205
206 // Get a fresh ethernet packet
208 const FileSystem::Result result = m_parent.getTransmitPacket(&pkt, ethAddr, sizeof(*ethAddr),
210 if (result != FileSystem::Success)
211 {
212 if (result != FileSystem::RetryAgain)
213 {
214 ERROR("failed to get transmit packet: result = " << (int) result);
215 }
216 return result;
217 }
218
219 IPV4::Address myip;
220 m_ip->getAddress(&myip);
221
222 // Fill the ARP packet
223 Ethernet::Header *ether = (Ethernet::Header *)(pkt->data + pkt->size - sizeof(Ethernet::Header));
224 ARP::Header *arp = (ARP::Header *)(pkt->data + pkt->size);
225 pkt->size += sizeof(ARP::Header);
226
227 DEBUG("eth: source=" << ether->source << " dest=" << ether->destination);
228
229 // ARP packet
233 arp->hardwareLength = sizeof(Ethernet::Address);
234 arp->protocolLength = sizeof(IPV4::Address);
235
236 // Fill source and destinations
237 MemoryBlock::copy(&arp->etherSender, &ether->source, sizeof(Ethernet::Address));
239 writeBe32(&arp->ipSender, myip);
240 writeBe32(&arp->ipTarget, ipAddr);
241
242 // Send the packet using the network device
243 return m_device.transmit(pkt);
244}
245
247{
248 const Ethernet::Header *ether = (const Ethernet::Header *) (pkt->data + offset - sizeof(Ethernet::Header));
249 const Header *arp = (const Header *) (pkt->data + offset);
250 const u16 operation = readBe16(&arp->operation);
251 const u32 ipTarget = readBe32(&arp->ipTarget);
252 const u32 ipSender = readBe32(&arp->ipSender);
253 IPV4::Address ipAddr;
254
255 m_ip->getAddress(&ipAddr);
256
257 DEBUG("target = " << *IPV4::toString(ipTarget) << " sender = " << *IPV4::toString(ipSender) <<
258 " ipAddr = " << *IPV4::toString(ipAddr) << " operation = " << operation <<
259 " etherSender = " << arp->etherSender << " etherTarget = " << arp->etherTarget);
260
261 switch (operation)
262 {
263 case Request:
264 // Only send reply if the request is for our IP
265 if (ipTarget == ipAddr)
266 {
267 updateCacheEntry(ipSender, &arp->etherSender);
268 return sendReply(&ether->source, ipSender);
269 }
270 return FileSystem::Success;
271
272 case Reply: {
273 updateCacheEntry(ipSender, &arp->etherSender);
274 return m_sock->process(pkt);
275 }
276 }
277
278 // Unknown ARP operation
280}
u32 entry[]
Definition IntelACPI.h:1
Address Resolution Protocol (ARP) socket.
Definition ARPSocket.h:41
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt)
Process incoming network packet.
Definition ARPSocket.cpp:85
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition ARP.cpp:246
@ IPV4
Definition ARP.h:76
KernelTimer m_kernelTimer
Provides access to the kernel timer.
Definition ARP.h:225
void updateCacheEntry(const IPV4::Address ipAddr, const Ethernet::Address *ethAddr)
Update cache entry.
Definition ARP.cpp:75
@ Ethernet
Definition ARP.h:68
::IPV4 * m_ip
IPV4 instance object.
Definition ARP.h:219
virtual FileSystem::Result initialize()
Perform initialization.
Definition ARP.cpp:41
HashTable< IPV4::Address, ARPCache * > m_cache
Contains a cached mapping from IP to Ethernet addresses.
Definition ARP.h:222
FileSystem::Result sendReply(const Ethernet::Address *ethaddr, const IPV4::Address ipAddr)
Send ARP reply.
Definition ARP.cpp:197
FileSystem::Result sendRequest(const IPV4::Address address)
Send ARP request.
Definition ARP.cpp:133
@ Request
Definition ARP.h:84
@ Reply
Definition ARP.h:85
ARPCache * getCacheEntry(const IPV4::Address ipAddr)
Retrieve cache entry by IP.
Definition ARP.cpp:55
static const Size MaxRetries
Maximum number of retries for ARP lookup.
Definition ARP.h:47
virtual ~ARP()
Destructor.
Definition ARP.cpp:33
void setIP(::IPV4 *ip)
Set IPV4 instance.
Definition ARP.cpp:50
FileSystem::Result lookupAddress(const IPV4::Address *ipAddr, Ethernet::Address *ethAddr)
Lookup Ethernet address for an IP.
Definition ARP.cpp:86
ARPCache * insertCacheEntry(const IPV4::Address ipAddr)
Insert a new entry to the ARP cache.
Definition ARP.cpp:64
ARPSocket * m_sock
The single ARP socket.
Definition ARP.h:216
void setTimeout(const uint msec)
Set a sleep timeout.
u32 getNextInode()
Get next unused inode.
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Iterate through a HashTable.
virtual bool hasCurrent() const
Check if there is a current item.
Internet Protocol Version 4.
Definition IPV4.h:41
static const String toString(const Address address)
Convert address to string.
Definition IPV4.cpp:82
u32 Address
IP-address.
Definition IPV4.h:47
virtual FileSystem::Result getAddress(Address *address)
Get current IP address.
Definition IPV4.cpp:70
virtual Result tick()
Process timer tick.
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Network Device abstract class.
virtual FileSystem::Result transmit(NetworkQueue::Packet *packet)=0
Add a network packet to the transmit queue.
Network protocol abstraction class.
NetworkProtocol & m_parent
Parent upper-layer protocol instance.
NetworkDevice & m_device
Network device instance.
virtual FileSystem::Result getTransmitPacket(NetworkQueue::Packet **pkt, const void *address, const Size addressSize, const Identifier protocol, const Size payloadSize)
Get a new packet for transmission.
NetworkServer & m_server
Network server instance.
Networking server.
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition Timer.cpp:44
bool isExpired(const Info &info) const
Check if a timer value is expired.
Definition Timer.cpp:85
void writeBe32(void *data, const u32 input)
Write 32-bit big endian integer.
Definition ByteOrder.h:459
unsigned int u32
Unsigned 32-bit number.
Definition Types.h:53
#define ERROR(msg)
Output an error message.
Definition Log.h:61
const u16 readBe16(const void *data)
Read 16-bit big endian integer.
Definition ByteOrder.h:398
const u32 readBe32(const void *data)
Read 32-bit big endian integer.
Definition ByteOrder.h:384
unsigned short u16
Unsigned 16-bit number.
Definition Types.h:56
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
void writeBe16(void *data, const u16 input)
Write 16-bit big endian integer.
Definition ByteOrder.h:471
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ InvalidArgument
Definition FileSystem.h:55
ARP table cache entry.
Definition ARP.h:53
ARP network packet header.
Definition ARP.h:95
u16 operation
Definition ARP.h:100
Ethernet::Address etherTarget
Definition ARP.h:105
u8 protocolLength
Definition ARP.h:99
IPV4::Address ipSender
Definition ARP.h:103
IPV4::Address ipTarget
Definition ARP.h:106
u16 protocolType
Definition ARP.h:97
Ethernet::Address etherSender
Definition ARP.h:102
u16 hardwareType
Definition ARP.h:96
u8 hardwareLength
Definition ARP.h:98
Ethernet network address.
Definition Ethernet.h:53
Ethernet network packet header.
Definition Ethernet.h:65
Address destination
packet destination address
Definition Ethernet.h:66
Address source
packet source address
Definition Ethernet.h:67
Represents a network packet.
Timer information structure.
Definition Timer.h:43
u32 ticks
Definition Timer.h:44
Size frequency
Definition Timer.h:45