FreeNOS
IPV4.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 <FreeNOS/System.h>
19 #include <String.h>
20 #include <List.h>
21 #include <ListIterator.h>
22 #include <ByteOrder.h>
23 #include "NetworkServer.h"
24 #include "NetworkDevice.h"
25 #include "IPV4.h"
26 #include "IPV4Address.h"
27 #include "UDP.h"
28 #include "ICMP.h"
29 
31  NetworkDevice &device,
32  NetworkProtocol &parent)
33  : NetworkProtocol(server, device, parent)
34 {
35  m_address = 0;
36  m_icmp = 0;
37  m_udp = 0;
38  m_id = 1;
39 }
40 
42 {
43 }
44 
46 {
47  DEBUG("");
48 
49  m_server.registerDirectory(this, "/ipv4");
50  m_server.registerFile(new IPV4Address(m_server.getNextInode(), this), "/ipv4/address");
51 
52  return FileSystem::Success;
53 }
54 
55 void IPV4::setICMP(::ICMP *icmp)
56 {
57  m_icmp = icmp;
58 }
59 
60 void IPV4::setARP(::ARP *arp)
61 {
62  m_arp = arp;
63 }
64 
65 void IPV4::setUDP(::UDP *udp)
66 {
67  m_udp = udp;
68 }
69 
71 {
72  *address = m_address;
73  return FileSystem::Success;
74 }
75 
77 {
78  m_address = *address;
79  return FileSystem::Success;
80 }
81 
82 const String IPV4::toString(const Address address)
83 {
84  String s;
85 
86  s << ((address >> 24) & 0xff) << "."
87  << ((address >> 16) & 0xff) << "."
88  << ((address >> 8) & 0xff) << "."
89  << ((address & 0xff));
90 
91  return s;
92 }
93 
94 const IPV4::Address IPV4::toAddress(const char *address)
95 {
96  const String input = address;
97  const List<String> lst = input.split('.');
98  Size shift = 24;
99  IPV4::Address addr = 0;
100 
101  // The address must be 4 bytes
102  if (lst.count() != 4)
103  {
104  return ZERO;
105  }
106 
107  // Extract bytes in dot format (xxx.xxx.xxx.xxx)
108  for (ListIterator<String> i(lst); i.hasCurrent(); i++)
109  {
110  String & s = i.current();
111  u8 byte = s.toLong();
112  addr |= (byte << shift);
113  shift -= 8;
114  }
115 
116  // Done
117  return addr;
118 }
119 
121 {
122  switch (id)
123  {
125  return IPV4::ICMP;
127  return IPV4::UDP;
128  default:
129  return IPV4::TCP;
130  }
131 }
132 
134  const void *address,
135  const Size addressSize,
136  const NetworkProtocol::Identifier protocol,
137  const Size payloadSize)
138 {
139  Ethernet::Address ethAddr;
140 
141  // Find the ethernet address using ARP first
142  FileSystem::Result result = m_arp->lookupAddress((const IPV4::Address *)address, &ethAddr);
143  if (result != FileSystem::Success)
144  {
145  if (result != FileSystem::RetryAgain)
146  {
147  ERROR("failed to perform ARP lookup: result = " << (int) result);
148  }
149  return result;
150  }
151 
152  // Get a fresh ethernet packet
153  result = m_parent.getTransmitPacket(pkt, &ethAddr, sizeof(ethAddr),
154  NetworkProtocol::IPV4, payloadSize);
155  if (result != FileSystem::Success)
156  {
157  if (result != FileSystem::RetryAgain)
158  {
159  ERROR("failed to get transmit packet: result = " << (int) result);
160  }
161  return result;
162  }
163 
164  // Fill IP header
165  Header *hdr = (Header *) ((*pkt)->data + (*pkt)->size);
166  hdr->versionIHL = (sizeof(Header) / sizeof(u32)) | (4 << 4);
167  hdr->typeOfService = 0;
168  hdr->timeToLive = 64;
169  hdr->protocol = getProtocolByIdentifier(protocol);
170  writeBe16(&hdr->length, payloadSize + sizeof(Header));
171  writeBe16(&hdr->identification, m_id);
172  writeBe16(&hdr->fragmentOffset, 0x4000); // dont fragment flag
173  writeBe32(&hdr->source, m_address);
174  writeBe32(&hdr->destination, *(u32 *)address);
175  hdr->checksum = 0;
176  hdr->checksum = checksum(hdr, sizeof(Header));
177  (*pkt)->size += sizeof(Header);
178  m_id++;
179 
180  // Success
181  return FileSystem::Success;
182 }
183 
184 const u16 IPV4::checksum(const void *buffer, const Size length)
185 {
186  const u16 *ptr = (const u16 *) buffer;
187  Size len = length;
188  uint sum = 0;
189 
190  // Calculate sum of the buffer
191  while (len > 1)
192  {
193  sum += read16(ptr);
194  ptr++;
195  len -= 2;
196  }
197 
198  // Add left-over byte, if any
199  if (len > 0)
200  sum += (readBe16(ptr) << 8);
201 
202  // Enforce 16-bit checksum
203  while (sum >> 16)
204  sum = (sum >> 16) + (sum & 0xFFFF);
205 
206  // Convert to one's complement
207  return (~sum);
208 }
209 
211  const Size offset)
212 {
213  DEBUG("");
214 
215  const Header *hdr = (const Header *) (pkt->data + offset);
216  const u32 destination = readBe32(&hdr->destination);
217 
218  if (destination != m_address && destination != 0xffffffff && m_address != 0)
219  {
220  DEBUG("dropped packet for " << *IPV4::toString(destination));
221  return FileSystem::NotFound;
222  }
223 
224  switch (hdr->protocol)
225  {
226  case ICMP:
227  return m_icmp->process(pkt, offset + sizeof(Header));
228 
229  case UDP:
230  return m_udp->process(pkt, offset + sizeof(Header));
231 
232  default:
233  break;
234  }
235 
237 }
IPV4::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition: IPV4.cpp:210
NetworkProtocol
Network protocol abstraction class.
Definition: NetworkProtocol.h:39
ARP::lookupAddress
FileSystem::Result lookupAddress(const IPV4::Address *ipAddr, Ethernet::Address *ethAddr)
Lookup Ethernet address for an IP.
Definition: ARP.cpp:86
readBe32
const u32 readBe32(const void *data)
Read 32-bit big endian integer.
Definition: ByteOrder.h:384
readBe16
const u16 readBe16(const void *data)
Read 16-bit big endian integer.
Definition: ByteOrder.h:398
IPV4::Header::fragmentOffset
u16 fragmentOffset
Definition: IPV4.h:72
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
UDP.h
IPV4::Header::identification
u16 identification
Definition: IPV4.h:71
IPV4Address.h
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
IPV4::Header::source
Address source
Definition: IPV4.h:76
UDP
User Datagram Protocol (UDP)
Definition: UDP.h:41
FileSystem::InvalidArgument
@ InvalidArgument
Definition: FileSystem.h:55
NetworkQueue::Packet::data
u8 * data
Definition: NetworkQueue.h:53
NetworkProtocol::UDP
@ UDP
Definition: NetworkProtocol.h:52
IPV4::Header
struct IPV4::Header Header
IP network packet header.
List::count
Size count() const
Get the number of items on the list.
Definition: List.h:402
ICMP::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition: ICMP.cpp:48
NetworkProtocol::IPV4
@ IPV4
Definition: NetworkProtocol.h:49
IPV4::TCP
@ TCP
Definition: IPV4.h:57
FileSystem::Success
@ Success
Definition: FileSystem.h:54
IPV4::Header::length
u16 length
Definition: IPV4.h:70
uint
unsigned int uint
Unsigned integer number.
Definition: Types.h:44
IPV4::m_udp
::UDP * m_udp
UDP instance.
Definition: IPV4.h:240
String::split
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition: String.cpp:408
UDP::process
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition: UDP.cpp:117
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
Ethernet::Address
Ethernet network address.
Definition: Ethernet.h:52
IPV4::m_address
Address m_address
Current IP address.
Definition: IPV4.h:231
IPV4::Header::versionIHL
u8 versionIHL
Version and header length (IHL)
Definition: IPV4.h:68
NetworkDevice.h
NetworkServer
Networking server.
Definition: NetworkServer.h:40
IPV4::ICMP
@ ICMP
Definition: IPV4.h:54
ListIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item on the List.
Definition: ListIterator.h:104
IPV4::Header::protocol
u8 protocol
Definition: IPV4.h:74
u16
unsigned short u16
Unsigned 16-bit number.
Definition: Types.h:56
IPV4::toAddress
static const Address toAddress(const char *address)
Convert string to IPV4 address.
Definition: IPV4.cpp:94
IPV4Address
IPV4 address file.
Definition: IPV4Address.h:36
ByteOrder.h
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ICMP.h
IPV4::Header::timeToLive
u8 timeToLive
Definition: IPV4.h:73
IPV4::setAddress
virtual FileSystem::Result setAddress(const Address *address)
Set current IP address.
Definition: IPV4.cpp:76
IPV4::Address
u32 Address
IP-address.
Definition: IPV4.h:47
IPV4.h
IPV4::setARP
void setARP(::ARP *arp)
Set ARP instance.
Definition: IPV4.cpp:60
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
read16
const u16 read16(const void *data)
Read 16-bit integer (no conversion)
Definition: ByteOrder.h:256
IPV4::Header
IP network packet header.
Definition: IPV4.h:66
IPV4::initialize
virtual FileSystem::Result initialize()
Perform initialization.
Definition: IPV4.cpp:45
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
IPV4::~IPV4
virtual ~IPV4()
Destructor.
Definition: IPV4.cpp:41
ListIterator.h
IPV4::setUDP
void setUDP(::UDP *udp)
Set UDP instance.
Definition: IPV4.cpp:65
IPV4::setICMP
void setICMP(::ICMP *icmp)
Set ICMP instance.
Definition: IPV4.cpp:55
IPV4::getProtocolByIdentifier
Protocol getProtocolByIdentifier(const NetworkProtocol::Identifier id) const
Convert protocol identifier.
Definition: IPV4.cpp:120
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
IPV4::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: IPV4.cpp:133
IPV4::m_id
u16 m_id
Packet ID for IPV4.
Definition: IPV4.h:243
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
IPV4::Header::typeOfService
u8 typeOfService
Definition: IPV4.h:69
IPV4::getAddress
virtual FileSystem::Result getAddress(Address *address)
Get current IP address.
Definition: IPV4.cpp:70
FileSystem::RetryAgain
@ RetryAgain
Definition: FileSystem.h:57
String.h
NetworkServer.h
IPV4::Header::destination
Address destination
Definition: IPV4.h:77
FileSystem::NotFound
@ NotFound
Definition: FileSystem.h:56
IPV4::m_arp
::ARP * m_arp
ARP instance.
Definition: IPV4.h:237
List< String >
IPV4::m_icmp
::ICMP * m_icmp
ICMP instance.
Definition: IPV4.h:234
IPV4::Header::checksum
u16 checksum
Definition: IPV4.h:75
NetworkQueue::Packet
Represents a network packet.
Definition: NetworkQueue.h:50
IPV4::UDP
@ UDP
Definition: IPV4.h:56
ARP
Address Resolution Protocol.
Definition: ARP.h:42
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
IPV4::Protocol
Protocol
Protocol types.
Definition: IPV4.h:52
NetworkProtocol::Identifier
Identifier
List of known network protocol identifiers.
Definition: NetworkProtocol.h:46
String::toLong
long toLong(const Number::Base base=Number::Dec) const
Convert the String to a signed long integer.
Definition: String.cpp:456
length
u32 length
Definition: IntelACPI.h:64
List.h
ListIterator
Iterate through a List.
Definition: ListIterator.h:37
ICMP
Internet Control Message Protocol (ICMP)
Definition: ICMP.h:42
FileSystemServer::registerFile
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Definition: FileSystemServer.cpp:115