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
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 {
77 if (s && s->getAddress() == source)
78 s->setReply(hdr);
79 }
80 break;
81 }
82 }
83
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}
SystemDescriptorHeader header
Definition IntelACPI.h:0
u32 getNextInode()
Get next unused inode.
FileSystem::Result unregisterFile(const char *path)
Remove a File from the FileSystemServer.
const char * getMountPath() const
Get mount path.
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Internet Control Message Protocol (ICMP) factory.
Definition ICMPFactory.h:40
Internet Control Message Protocol (ICMP) socket.
Definition ICMPSocket.h:43
const IPV4::Address getAddress() const
Get associated IP host.
void setReply(const ICMP::Header *reply)
Set ICMP reply.
ICMPFactory * m_factory
Definition ICMP.h:147
Index< ICMPSocket, MaxIcmpSockets > m_sockets
Definition ICMP.h:149
ICMPSocket * createSocket(String &path, const ProcessID pid)
Creates an ICMP socket.
Definition ICMP.cpp:87
virtual ~ICMP()
Destructor.
Definition ICMP.cpp:33
FileSystem::Result sendPacket(const IPV4::Address ip, const Header *header, const void *payload, const Size payloadSize)
Send packet.
Definition ICMP.cpp:148
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition ICMP.cpp:48
void unregisterSockets(const ProcessID pid)
Remove sockets for a process.
Definition ICMP.cpp:126
@ EchoRequest
Definition ICMP.h:58
@ EchoReply
Definition ICMP.h:55
static const Size MaxIcmpSockets
Definition ICMP.h:46
virtual FileSystem::Result initialize()
Perform initialization.
Definition ICMP.cpp:37
static const String toString(const Address address)
Convert address to string.
Definition IPV4.cpp:82
u32 Address
IP-address.
Definition IPV4.h:47
static const u16 checksum(const void *buffer, const Size length)
Calculate IP checksum.
Definition IPV4.cpp:184
virtual T * get(const Size position) const
Returns the item at the given position.
Definition Index.h:187
virtual bool insert(Size &position, T *item)
Adds the given item, if possible.
Definition Index.h:60
virtual Size size() const
Size of the Index.
Definition Index.h:217
virtual bool remove(const Size position)
Removes the item at the given position.
Definition Index.h:143
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.
virtual const Size getMaximumPacketSize() const
Get maximum packet size.
Networking server.
ProcessID getProcessID() const
Get owner ProcessID.
Abstraction of strings.
Definition String.h:42
u32 ProcessID
Process Identification Number.
Definition Types.h:140
#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
void write16(void *data, const u16 input)
Write 16-bit integer (no conversion)
Definition ByteOrder.h:305
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
Packet header format.
Definition ICMP.h:65
u16 sequence
Definition ICMP.h:70
u16 id
Definition ICMP.h:69
u8 code
Definition ICMP.h:67
u8 type
Definition ICMP.h:66
IP network packet header.
Definition IPV4.h:67
Address source
Definition IPV4.h:76
Represents a network packet.