FreeNOS
ICMP.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 "NetworkServer.h"
20 #include "NetworkProtocol.h"
21 #include "ICMP.h"
22 #include "ICMPFactory.h"
23 #include "ICMPSocket.h"
24 #include "IPV4.h"
25 
27  NetworkDevice &device,
28  NetworkProtocol &parent)
29  : NetworkProtocol(server, device, parent)
30 {
31 }
32 
34 {
35 }
36 
38 {
39  DEBUG("");
40 
42  m_server.registerDirectory(this, "/icmp");
43  m_server.registerFile(m_factory, "/icmp/factory");
44 
45  return FileSystem::Success;
46 }
47 
49  const Size offset)
50 {
51  const IPV4::Header *iphdr = (const IPV4::Header *) (pkt->data + offset - sizeof(IPV4::Header));
52  const ICMP::Header *hdr = (const ICMP::Header *) (pkt->data + offset);
53  const IPV4::Address source = readBe32(&iphdr->source);
54 
55  DEBUG("source = " << *IPV4::toString(source) << " type = " <<
56  hdr->type << " code = " << hdr->code << " id = " << hdr->id);
57 
58  switch (hdr->type)
59  {
60  case EchoRequest:
61  {
62  DEBUG("request");
63 
64  ICMP::Header reply;
65  MemoryBlock::copy(&reply, hdr, sizeof(reply));
66  reply.type = EchoReply;
67 
68  return sendPacket(source, &reply, hdr + 1, pkt->size - offset - sizeof(ICMP::Header));
69  }
70  case EchoReply:
71  {
72  DEBUG("reply");
73 
74  for (Size i = 0; i < m_sockets.size(); i++)
75  {
76  ICMPSocket *s = (ICMPSocket *) m_sockets.get(i);
77  if (s && s->getAddress() == source)
78  s->setReply(hdr);
79  }
80  break;
81  }
82  }
83 
84  return FileSystem::Success;
85 }
86 
88  const ProcessID pid)
89 {
90  Size pos = 0;
91 
92  DEBUG("");
93 
94  // Allocate socket
95  ICMPSocket *sock = new ICMPSocket(m_server.getNextInode(), this, pid);
96  if (!sock)
97  {
98  ERROR("failed to allocate ICMP socket");
99  return ZERO;
100  }
101 
102  // Insert to sockets array
103  if (!m_sockets.insert(pos, sock))
104  {
105  ERROR("failed to insert ICMP socket");
106  delete sock;
107  return ZERO;
108  }
109  String filepath;
110  filepath << "/icmp/" << pos;
111 
112  // Add socket to NetworkServer as a file
113  path << m_server.getMountPath() << filepath;
114  const FileSystem::Result result = m_server.registerFile(sock, *filepath);
115  if (result != FileSystem::Success)
116  {
117  ERROR("failed to register ICMP socket to NetworkServer: result = " << (int) result);
118  m_sockets.remove(pos);
119  delete sock;
120  return ZERO;
121  }
122 
123  return sock;
124 }
125 
127 {
128  DEBUG("pid = " << pid);
129 
130  for (Size i = 0; i < MaxIcmpSockets; i++)
131  {
132  ICMPSocket *sock = m_sockets[i];
133  if (sock != ZERO && sock->getProcessID() == pid)
134  {
135  m_sockets.remove(i);
136  String path;
137  path << "/icmp/" << i;
138  const FileSystem::Result result = m_server.unregisterFile(*path);
139  if (result != FileSystem::Success)
140  {
141  ERROR("failed to unregister ICMPSocket at " << *path <<
142  " for PID " << pid << ": result = " << (int) result);
143  }
144  }
145  }
146 }
147 
149  const ICMP::Header *headerInput,
150  const void *payload,
151  const Size payloadSize)
152 {
153  DEBUG("ip = " << *IPV4::toString(ip) << " header.type = " << headerInput->type <<
154  " header.id = " << readBe16(&headerInput->id) << " header.seq = " <<
155  readBe16(&headerInput->sequence) << " payloadSize = " << payloadSize);
156 
157  // Get a fresh packet
159  const FileSystem::Result result = m_parent.getTransmitPacket(&pkt, &ip, sizeof(ip),
161  sizeof(ICMP::Header) + payloadSize);
162  if (result != FileSystem::Success)
163  {
164  if (result != FileSystem::RetryAgain)
165  {
166  ERROR("failed to get transmit packet: result = " << (int) result);
167  }
168  return result;
169  }
170 
171  // Fill header
172  ICMP::Header *header = (ICMP::Header *) (pkt->data + pkt->size);
173  MemoryBlock::copy(header, headerInput, sizeof(ICMP::Header));
174  pkt->size += sizeof(ICMP::Header);
175 
176  // Fill payload
177  const Size maximum = getMaximumPacketSize();
178  const Size needed = pkt->size + payloadSize;
179  const Size amount = needed > maximum ? maximum - pkt->size : needed - pkt->size;
180 
181  MemoryBlock::copy(pkt->data + pkt->size, payload, amount);
182  pkt->size += amount;
183 
184  // Calculate checksum
185  write16(&header->checksum, 0);
186  write16(&header->checksum, IPV4::checksum(header, sizeof(ICMP::Header) + amount));
187 
188  // Transmit the packet
189  return m_device.transmit(pkt);
190 }
ICMPFactory
Internet Control Message Protocol (ICMP) factory.
Definition: ICMPFactory.h:39
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
ICMP::Header::id
u16 id
Definition: ICMP.h:69
readBe32
const u32 readBe32(const void *data)
Read 32-bit big endian integer.
Definition: ByteOrder.h:384
ICMP::Header
Packet header format.
Definition: ICMP.h:64
readBe16
const u16 readBe16(const void *data)
Read 16-bit big endian integer.
Definition: ByteOrder.h:398
FileSystemServer::getNextInode
u32 getNextInode()
Get next unused inode.
Definition: FileSystemServer.cpp:66
String
Abstraction of strings.
Definition: String.h:41
NetworkDevice
Network Device abstract class.
Definition: NetworkDevice.h:41
NetworkProtocol::m_parent
NetworkProtocol & m_parent
Parent upper-layer protocol instance.
Definition: NetworkProtocol.h:126
IPV4::checksum
static const u16 checksum(const void *buffer, const Size length)
Calculate IP checksum.
Definition: IPV4.cpp:184
ICMP::MaxIcmpSockets
static const Size MaxIcmpSockets
Definition: ICMP.h:46
ICMP::createSocket
ICMPSocket * createSocket(String &path, const ProcessID pid)
Creates an ICMP socket.
Definition: ICMP.cpp:87
IPV4::Header::source
Address source
Definition: IPV4.h:76
ICMP::m_factory
ICMPFactory * m_factory
Definition: ICMP.h:147
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
FileSystemServer::unregisterFile
FileSystem::Result unregisterFile(const char *path)
Remove a File from the FileSystemServer.
Definition: FileSystemServer.cpp:175
NetworkQueue::Packet::data
u8 * data
Definition: NetworkQueue.h:53
ICMP::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition: ICMP.cpp:48
NetworkQueue::Packet::size
Size size
Definition: NetworkQueue.h:52
ICMP::Header::code
u8 code
Definition: ICMP.h:67
ICMP::Header::type
u8 type
Definition: ICMP.h:66
FileSystem::Success
@ Success
Definition: FileSystem.h:54
NetworkProtocol.h
NetworkProtocol::m_device
NetworkDevice & m_device
Network device instance.
Definition: NetworkProtocol.h:123
NetworkSocket::getProcessID
ProcessID getProcessID() const
Get owner ProcessID.
Definition: NetworkSocket.cpp:36
write16
void write16(void *data, const u16 input)
Write 16-bit integer (no conversion)
Definition: ByteOrder.h:305
ICMP::sendPacket
FileSystem::Result sendPacket(const IPV4::Address ip, const Header *header, const void *payload, const Size payloadSize)
Send packet.
Definition: ICMP.cpp:148
ICMPSocket::setReply
void setReply(const ICMP::Header *reply)
Set ICMP reply.
Definition: ICMPSocket.cpp:89
ICMP::~ICMP
virtual ~ICMP()
Destructor.
Definition: ICMP.cpp:33
ICMPSocket::getAddress
const IPV4::Address getAddress() const
Get associated IP host.
Definition: ICMPSocket.cpp:39
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
ICMPFactory.h
ICMP::EchoReply
@ EchoReply
Definition: ICMP.h:55
ICMP::initialize
virtual FileSystem::Result initialize()
Perform initialization.
Definition: ICMP.cpp:37
NetworkServer
Networking server.
Definition: NetworkServer.h:40
NetworkProtocol::getMaximumPacketSize
virtual const Size getMaximumPacketSize() const
Get maximum packet size.
Definition: NetworkProtocol.cpp:36
header
SystemDescriptorHeader header
Definition: IntelACPI.h:63
Index::size
virtual Size size() const
Size of the Index.
Definition: Index.h:217
ByteOrder.h
ICMP::unregisterSockets
void unregisterSockets(const ProcessID pid)
Remove sockets for a process.
Definition: ICMP.cpp:126
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ICMPSocket.h
ICMP.h
IPV4::Address
u32 Address
IP-address.
Definition: IPV4.h:47
Index::get
virtual T * get(const Size position) const
Returns the item at the given position.
Definition: Index.h:187
IPV4.h
NetworkProtocol::ICMP
@ ICMP
Definition: NetworkProtocol.h:51
FileSystemServer::registerDirectory
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
Definition: FileSystemServer.cpp:138
IPV4::Header
IP network packet header.
Definition: IPV4.h:66
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
FileSystemServer::getMountPath
const char * getMountPath() const
Get mount path.
Definition: FileSystemServer.cpp:61
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
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
NetworkDevice::transmit
virtual FileSystem::Result transmit(NetworkQueue::Packet *packet)=0
Add a network packet to the transmit queue.
ICMP::EchoRequest
@ EchoRequest
Definition: ICMP.h:58
FileSystem::RetryAgain
@ RetryAgain
Definition: FileSystem.h:57
NetworkServer.h
Index::remove
virtual bool remove(const Size position)
Removes the item at the given position.
Definition: Index.h:143
ICMP::m_sockets
Index< ICMPSocket, MaxIcmpSockets > m_sockets
Definition: ICMP.h:149
ICMP::Header::sequence
u16 sequence
Definition: ICMP.h:70
NetworkQueue::Packet
Represents a network packet.
Definition: NetworkQueue.h:50
Index::insert
virtual bool insert(Size &position, T *item)
Adds the given item, if possible.
Definition: Index.h:60
ICMP::Header
struct ICMP::Header Header
Packet header format.
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
ICMPSocket
Internet Control Message Protocol (ICMP) socket.
Definition: ICMPSocket.h:42
FileSystemServer::registerFile
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Definition: FileSystemServer.cpp:115