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 
42 {
43  m_sock = new ARPSocket(m_server.getNextInode(), this);
44  m_server.registerDirectory(this, "/arp");
45  m_server.registerFile(m_sock, "/arp/socket");
46 
47  return FileSystem::Success;
48 }
49 
50 void ARP::setIP(::IPV4 *ip)
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));
96  return FileSystem::Success;
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);
130  return FileSystem::RetryAgain;
131 }
132 
134 {
135  DEBUG("address = " << *IPV4::toString(address));
136 
137  // Get cache entry
138  ARPCache *entry = getCacheEntry(address);
139  if (!entry)
140  {
141  return FileSystem::NotFound;
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;
150  return FileSystem::NotFound;
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),
162  NetworkProtocol::ARP, sizeof(Header));
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),
209  NetworkProtocol::ARP, sizeof(Header));
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 }
ARP::Header::etherTarget
Ethernet::Address etherTarget
Definition: ARP.h:105
NetworkProtocol
Network protocol abstraction class.
Definition: NetworkProtocol.h:39
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
ARP::lookupAddress
FileSystem::Result lookupAddress(const IPV4::Address *ipAddr, Ethernet::Address *ethAddr)
Lookup Ethernet address for an IP.
Definition: ARP.cpp:86
ARP::Ethernet
@ Ethernet
Definition: ARP.h:68
readBe32
const u32 readBe32(const void *data)
Read 32-bit big endian integer.
Definition: ByteOrder.h:384
ARP::m_sock
ARPSocket * m_sock
The single ARP socket.
Definition: ARP.h:216
ARP::Header
ARP network packet header.
Definition: ARP.h:94
ARP::ARPCache
ARP table cache entry.
Definition: ARP.h:52
ARPSocket::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt)
Process incoming network packet.
Definition: ARPSocket.cpp:85
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
ARP::Header::hardwareType
u16 hardwareType
Definition: ARP.h:96
readBe16
const u16 readBe16(const void *data)
Read 16-bit big endian integer.
Definition: ByteOrder.h:398
ARP::Header::hardwareLength
u8 hardwareLength
Definition: ARP.h:98
ARP::Header::ipTarget
IPV4::Address ipTarget
Definition: ARP.h:106
FileSystemServer::getNextInode
u32 getNextInode()
Get next unused inode.
Definition: FileSystemServer.cpp:66
writeBe16
void writeBe16(void *data, const u16 input)
Write 16-bit big endian integer.
Definition: ByteOrder.h:471
ARP::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition: ARP.cpp:246
ARP::sendReply
FileSystem::Result sendReply(const Ethernet::Address *ethaddr, const IPV4::Address ipAddr)
Send ARP reply.
Definition: ARP.cpp:197
NetworkDevice
Network Device abstract class.
Definition: NetworkDevice.h:41
HashIterator
Iterate through a HashTable.
Definition: HashIterator.h:39
ARP::Request
@ Request
Definition: ARP.h:84
NetworkProtocol::m_parent
NetworkProtocol & m_parent
Parent upper-layer protocol instance.
Definition: NetworkProtocol.h:126
ARP::m_cache
HashTable< IPV4::Address, ARPCache * > m_cache
Contains a cached mapping from IP to Ethernet addresses.
Definition: ARP.h:222
ARP::setIP
void setIP(::IPV4 *ip)
Set IPV4 instance.
Definition: ARP.cpp:50
ARPSocket
Address Resolution Protocol (ARP) socket.
Definition: ARPSocket.h:40
FileSystem::InvalidArgument
@ InvalidArgument
Definition: FileSystem.h:55
Timer::Info::frequency
Size frequency
Definition: Timer.h:45
NetworkQueue::Packet::data
u8 * data
Definition: NetworkQueue.h:53
ARP::Header
struct ARP::Header Header
ARP network packet header.
ARP::Header::operation
u16 operation
Definition: ARP.h:100
NetworkQueue::Packet::size
Size size
Definition: NetworkQueue.h:52
FileSystem::Success
@ Success
Definition: FileSystem.h:54
Timer::Info
Timer information structure.
Definition: Timer.h:42
ARP::Header::protocolType
u16 protocolType
Definition: ARP.h:97
NetworkProtocol::m_device
NetworkDevice & m_device
Network device instance.
Definition: NetworkProtocol.h:123
ARP::m_kernelTimer
KernelTimer m_kernelTimer
Provides access to the kernel timer.
Definition: ARP.h:225
ARP::getCacheEntry
ARPCache * getCacheEntry(const IPV4::Address ipAddr)
Retrieve cache entry by IP.
Definition: ARP.cpp:55
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
Ethernet::Address
Ethernet network address.
Definition: Ethernet.h:52
NetworkDevice.h
NetworkServer
Networking server.
Definition: NetworkServer.h:40
ARP::initialize
virtual FileSystem::Result initialize()
Perform initialization.
Definition: ARP.cpp:41
u16
unsigned short u16
Unsigned 16-bit number.
Definition: Types.h:56
ARP::m_ip
::IPV4 * m_ip
IPV4 instance object.
Definition: ARP.h:219
ByteOrder.h
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
ARP::Header::etherSender
Ethernet::Address etherSender
Definition: ARP.h:102
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ChannelServer::setTimeout
void setTimeout(const uint msec)
Set a sleep timeout.
Definition: ChannelServer.h:179
IPV4::Address
u32 Address
IP-address.
Definition: IPV4.h:47
Ethernet::Header
Ethernet network packet header.
Definition: Ethernet.h:64
Timer::isExpired
bool isExpired(const Info &info) const
Check if a timer value is expired.
Definition: Timer.cpp:85
IPV4
Internet Protocol Version 4.
Definition: IPV4.h:40
Timer::Info::ticks
u32 ticks
Definition: Timer.h:44
FileSystemServer::registerDirectory
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
Definition: FileSystemServer.cpp:138
ARP.h
NetworkProtocol::getTransmitPacket
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.
Definition: NetworkProtocol.cpp:41
IPV4::toString
static const String toString(const Address address)
Convert address to string.
Definition: IPV4.cpp:82
Ethernet::Header::source
Address source
packet source address
Definition: Ethernet.h:67
writeBe32
void writeBe32(void *data, const u32 input)
Write 32-bit big endian integer.
Definition: ByteOrder.h:459
NetworkProtocol::m_server
NetworkServer & m_server
Network server instance.
Definition: NetworkProtocol.h:120
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
entry
u32 entry[]
Definition: IntelACPI.h:64
KernelTimer::tick
virtual Result tick()
Process timer tick.
Definition: KernelTimer.cpp:23
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
IPV4::getAddress
virtual FileSystem::Result getAddress(Address *address)
Get current IP address.
Definition: IPV4.cpp:70
ARP::Header::protocolLength
u8 protocolLength
Definition: ARP.h:99
NetworkDevice::transmit
virtual FileSystem::Result transmit(NetworkQueue::Packet *packet)=0
Add a network packet to the transmit queue.
FileSystem::RetryAgain
@ RetryAgain
Definition: FileSystem.h:57
NetworkServer.h
NetworkProtocol::ARP
@ ARP
Definition: NetworkProtocol.h:50
ARP::MaxRetries
static const Size MaxRetries
Maximum number of retries for ARP lookup.
Definition: ARP.h:47
FileSystem::NotFound
@ NotFound
Definition: FileSystem.h:56
HashIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item.
Definition: HashIterator.h:83
ARP::Reply
@ Reply
Definition: ARP.h:85
ARPSocket.h
NetworkClient.h
Ethernet::Address
struct Ethernet::Address Address
Ethernet network address.
ARP::IPV4
@ IPV4
Definition: ARP.h:76
NetworkQueue::Packet
Represents a network packet.
Definition: NetworkQueue.h:50
ARP::updateCacheEntry
void updateCacheEntry(const IPV4::Address ipAddr, const Ethernet::Address *ethAddr)
Update cache entry.
Definition: ARP.cpp:75
ARP::Header::ipSender
IPV4::Address ipSender
Definition: ARP.h:103
ARP::~ARP
virtual ~ARP()
Destructor.
Definition: ARP.cpp:33
Timer::getCurrent
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition: Timer.cpp:44
ARP::sendRequest
FileSystem::Result sendRequest(const IPV4::Address address)
Send ARP request.
Definition: ARP.cpp:133
ARP::ARPCache
struct ARP::ARPCache ARPCache
ARP table cache entry.
Ethernet::Header::destination
Address destination
packet destination address
Definition: Ethernet.h:66
ARP::insertCacheEntry
ARPCache * insertCacheEntry(const IPV4::Address ipAddr)
Insert a new entry to the ARP cache.
Definition: ARP.cpp:64
FileSystemServer::registerFile
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Definition: FileSystemServer.cpp:115