The Pedigree Project  0.1
NetworkStack.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "NetworkStack.h"
21 
22 #include "modules/Module.h"
23 #include "pedigree/kernel/LockGuard.h"
24 #include "pedigree/kernel/Log.h"
25 #include "pedigree/kernel/processor/Processor.h"
26 
32 
33 #include "Filter.h"
34 
35 NetworkStack *NetworkStack::stack = 0;
36 
37 static NetworkStack *g_NetworkStack = 0;
38 
39 static err_t linkOutput(struct netif *netif, struct pbuf *p)
40 {
41  Network *pDevice = reinterpret_cast<Network *>(netif->state);
42 
43  size_t totalLength = p->tot_len;
44 
45  // pull the chain of pbufs into a single packet to transmit
46  size_t offset = 0;
47  char *output = new char[totalLength];
48 
49  pbuf_copy_partial(p, output, totalLength, 0);
50 
51  // Check for filtering
52  if (!NetworkFilter::instance().filter(
53  1, reinterpret_cast<uintptr_t>(output), totalLength))
54  {
55  pDevice->droppedPacket();
56  return ERR_IF; // Drop the packet.
57  }
58 
59  // transmit!
60  err_t e = ERR_OK;
61  if (!pDevice->send(totalLength, reinterpret_cast<uintptr_t>(output)))
62  {
63  e = ERR_IF;
64  }
65 
66  delete[] output;
67 
68  return e;
69 }
70 
71 static void netifStatusUpdate(struct netif *netif)
72 {
73  if (netif_is_up(netif))
74  {
75  NOTICE("netif " << String(netif->name, 2) << Dec << netif->num << ": is now up");
76  }
77  else
78  {
79  NOTICE("netif " << String(netif->name, 2) << Dec << netif->num << ": is now down");
80  }
81 }
82 
83 static void netifLinkUpdate(struct netif *netif)
84 {
85  if (netif_is_link_up(netif))
86  {
87  NOTICE("netif " << String(netif->name, 2) << Dec << netif->num << ": link is now up");
88  }
89  else
90  {
91  NOTICE("netif " << String(netif->name, 2) << Dec << netif->num << ": link is now down");
92  }
93 }
94 
95 static err_t netifInit(struct netif *netif)
96 {
97  Network *pDevice = reinterpret_cast<Network *>(netif->state);
98  StationInfo info = pDevice->getStationInfo();
99 
101  netif->hwaddr_len = 6;
102  MemoryCopy(netif->hwaddr, info.mac.getMac(), 6);
103  netif->mtu = 1400;
105  netif->linkoutput = linkOutput;
106  netif->output = etharp_output;
107  netif->output_ip6 = ethip6_output;
108 
109  netif_set_status_callback(netif, netifStatusUpdate);
110  netif_set_link_callback(netif, netifLinkUpdate);
111 
112  return ERR_OK;
113 }
114 
115 NetworkStack::NetworkStack()
116  : RequestQueue("Network Stack"), m_pLoopback(0), m_Children(),
117  m_MemPool("network-pool")
118 #ifdef UTILITY_LINUX
119  ,
120  m_Lock(false)
121 #endif
122  ,
123  m_NextInterfaceNumber(0)
124 {
125  if (stack)
126  {
127  FATAL("NetworkStack created multiple times.");
128  }
129 
130  stack = this;
131 
132  initialise();
133 
134 #if defined(X86_COMMON) || defined(HOSTED)
135  // Lots of RAM to burn! Try 16 MB, then 8 MB, then 4 MB, then give up
136  if (!m_MemPool.initialise(4096, 1600))
137  if (!m_MemPool.initialise(2048, 1600))
138  if (!m_MemPool.initialise(1024, 1600))
139  ERROR("Couldn't get a valid buffer pool for networking use");
140 #elif defined(ARM_COMMON)
141  // Probably very little RAM to burn - 4 MB then 2 MB, then 512 KB
142  NOTICE("allocating memory pool");
143  if (!m_MemPool.initialise(1024, 1600))
144  if (!m_MemPool.initialise(512, 1600))
145  if (!m_MemPool.initialise(128, 1600))
146  ERROR("Couldn't get a valid buffer pool for networking use");
147 #else
148 #warning Unhandled architecture for the NetworkStack buffer pool
149 #endif
150 }
151 
152 NetworkStack::~NetworkStack()
153 {
154  destroy();
155 
156  stack = 0;
157 }
158 
160  uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
161  uint64_t p6, uint64_t p7, uint64_t p8)
162 {
163  // OK, we are now processing the packet.
164  // We hold a lock that allows us to handle concurrency (not an issue with
165  // a true RequestQueue, but is an issue on other environments).
166 #if defined(THREADS) || defined(UTILITY_LINUX)
167  LockGuard<Mutex> guard(m_Lock);
168 #endif
169 
170  struct pbuf *p = reinterpret_cast<struct pbuf *>(p1);
171  struct netif *iface = reinterpret_cast<struct netif *>(p2);
172 
173  iface->input(p, iface);
174 
175  return 0;
176 }
177 
179  size_t nBytes, uintptr_t packet, Network *pCard, uint32_t offset)
180 {
181  packet += offset;
182 
183  // Check for filtering before doing anything else
184  if (!NetworkFilter::instance().filter(1, packet, nBytes))
185  {
186  pCard->droppedPacket();
187  return; // Drop the packet.
188  }
189 
190  struct netif *iface = getInterface(pCard);
191  if (!iface)
192  {
193  ERROR("Network Stack: no lwIP interface for received packet");
194  pCard->droppedPacket();
195  return;
196  }
197 
198  struct pbuf *p = pbuf_alloc(PBUF_RAW, nBytes, PBUF_POOL);
199  if (p != 0)
200  {
201  struct pbuf *buf = p;
202  while (buf != nullptr)
203  {
204  size_t copyLength = buf->len;
205  MemoryCopy(
206  buf->payload, reinterpret_cast<void *>(packet), buf->len);
207 
208  packet += buf->len;
209  nBytes -= buf->len;
210 
211  buf = buf->next;
212  }
213  }
214  else
215  {
216  ERROR("Network Stack: Out of memory pool space, dropping incoming "
217  "packet");
218  pCard->droppedPacket();
219  return;
220  }
221 
222  uint64_t result = addRequest(
223  0, reinterpret_cast<uint64_t>(p), reinterpret_cast<uintptr_t>(iface));
224 }
225 
227 {
228 #if defined(THREADS) || defined(UTILITY_LINUX)
229  LockGuard<Mutex> guard(m_Lock);
230 #endif
231 
232  size_t interfaceNumber = m_NextInterfaceNumber++;
233 
234  if (interfaceNumber >= 0xFFU)
235  {
236  FATAL("Too many network interfaces!");
237  }
238 
239  m_Children.pushBack(pDevice);
240 
241  struct netif *iface = new struct netif;
242  ByteSet(iface, 0, sizeof(*iface));
243 
244  ip4_addr_t ipaddr;
245  ip4_addr_t netmask;
246  ip4_addr_t gateway;
247 
248  // for dhcp/auto configuration
249  ByteSet(&ipaddr, 0, sizeof(ipaddr));
250  ByteSet(&netmask, 0, sizeof(netmask));
251  ByteSet(&gateway, 0, sizeof(gateway));
252 
253  iface->name[0] = 'e';
254  iface->name[1] = 'n';
255  iface->num = interfaceNumber;
256 
257  iface = netif_add(iface, &ipaddr, &netmask, &gateway, pDevice, netifInit, tcpip_input);
258 
259  m_Interfaces.insert(pDevice, iface);
260 }
261 
263 {
264  return m_Children[n];
265 }
266 
268 {
269  return m_Children.count();
270 }
271 
273 {
274  int i = 0;
276  it != m_Children.end(); it++, i++)
277  if (*it == pDevice)
278  {
279  m_Children.erase(it);
280  break;
281  }
282 
283  struct netif *iface = m_Interfaces.lookup(pDevice);
284  m_Interfaces.remove(pDevice);
285 
286  if (iface != nullptr)
287  {
288  netif_remove(iface);
289 
290  delete iface;
291  }
292 }
293 
294 NetworkStack::Packet::Packet() = default;
295 
296 NetworkStack::Packet::~Packet()
297 {
298  // Packet destroyed, clean up our buffer if it existed.
299  if (m_Buffer)
300  {
302  }
303 }
304 
305 bool NetworkStack::Packet::copyFrom(uintptr_t otherPacket, size_t size)
306 {
307  uint8_t *safePacket = reinterpret_cast<uint8_t *>(
309  if (!safePacket)
310  {
311  return false;
312  }
313  MemoryCopy(safePacket, reinterpret_cast<void *>(otherPacket), size);
314 
315  m_Buffer = reinterpret_cast<uintptr_t>(safePacket);
316  m_PacketLength = size;
317  return true;
318 }
319 
320 static bool entry()
321 {
322  g_NetworkStack = new NetworkStack();
323 
324  return true;
325 }
326 
327 static void exit()
328 {
329  delete g_NetworkStack;
330 }
331 
332 // NetManager exposes a Filesystem, and so needs the vfs module.
333 MODULE_INFO("network-stack", &entry, &exit, "config", "vfs", "lwip");
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:322
u16_t tot_len
Definition: pbuf.h:175
virtual void droppedPacket()
Called when a packet is dropped by the system.
Definition: Network.cc:133
void pushBack(const T &value)
Definition: Vector.h:270
Iterator begin()
Definition: Vector.h:148
Iterator end()
Definition: Vector.h:160
Definition: pbuf.h:113
struct pbuf * next
Definition: pbuf.h:163
u16_t len
Definition: pbuf.h:178
size_t count() const
Definition: Vector.h:264
struct netif * netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:260
A vector / dynamic array.
#define netif_is_link_up(netif)
Definition: netif.h:432
virtual const StationInfo & getStationInfo()
Definition: Network.cc:76
u8_t num
Definition: netif.h:328
MemoryPool m_MemPool
Definition: NetworkStack.h:145
#define NETIF_FLAG_BROADCAST
Definition: netif.h:100
Definition: String.h:49
u8_t hwaddr_len
Definition: netif.h:320
void receive(size_t nBytes, uintptr_t packet, Network *pCard, uint32_t offset)
#define NETIF_FLAG_ETHERNET
Definition: netif.h:114
Network * getDevice(size_t n)
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:231
#define NETIF_FLAG_LINK_UP
Definition: netif.h:106
virtual bool send(size_t nBytes, uintptr_t buffer)=0
Definition: pbuf.h:161
u8_t flags
Definition: netif.h:324
#define NOTICE(text)
Definition: Log.h:74
Definition: netif.h:244
Definition: err.h:106
void netif_remove(struct netif *netif)
Definition: netif.c:396
s8_t err_t
Definition: err.h:76
void deRegisterDevice(Network *pDevice)
u16_t mtu
Definition: netif.h:318
uintptr_t allocateNow()
Definition: MemoryPool.cc:184
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1034
#define netif_is_up(netif)
Definition: netif.h:420
static NetworkStack & instance()
Definition: NetworkStack.h:47
void registerDevice(Network *pDevice)
#define NETIF_FLAG_ETHARP
Definition: netif.h:110
void * state
Definition: netif.h:298
void free(uintptr_t buffer)
Frees an allocated buffer, allowing it to be used elsewhere.
Definition: MemoryPool.cc:251
size_t getNumDevices()
netif_input_fn input
Definition: netif.h:263
#define ERROR(text)
Definition: Log.h:82
Definition: err.h:82
void * payload
Definition: pbuf.h:166
Definition: Log.h:138
char name[2]
Definition: netif.h:326
#define FATAL(text)
Definition: Log.h:89
void erase(size_t index)
Definition: Vector.h:350
virtual uint64_t executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)
static NetworkFilter & instance()
Definition: Filter.h:40
netif_linkoutput_fn linkoutput
Definition: netif.h:274
Vector< Device * > m_Children
Definition: Device.h:364