1/*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 */
8
9
10#include "ipv4.h"
11#include "ipv4_address.h"
12#include "multicast.h"
13
14#include <net_datalink.h>
15#include <net_datalink_protocol.h>
16#include <net_device.h>
17#include <net_protocol.h>
18#include <net_stack.h>
19#include <NetBufferUtilities.h>
20#include <ProtocolUtilities.h>
21
22#include <KernelExport.h>
23#include <util/AutoLock.h>
24#include <util/list.h>
25#include <util/DoublyLinkedList.h>
26#include <util/MultiHashTable.h>
27
28#include <netinet/in.h>
29#include <netinet/ip.h>
30#include <new>
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <utility>
35
36
37//#define TRACE_IPV4
38#ifdef TRACE_IPV4
39#	define TRACE(format, args...) \
40		dprintf("IPv4 [%" B_PRIdBIGTIME "] " format "\n", system_time() , \
41			##args)
42#	define TRACE_SK(protocol, format, args...) \
43		dprintf("IPv4 [%" B_PRIdBIGTIME "] %p " format "\n", system_time(), \
44			protocol , ##args)
45#	define TRACE_ONLY(x) x
46#else
47#	define TRACE(args...) ;
48#	define TRACE_SK(args...) ;
49#	define TRACE_ONLY(x)
50#endif
51
52
53#define MAX_HASH_FRAGMENTS 		64
54	// slots in the fragment packet's hash
55#define FRAGMENT_TIMEOUT		60000000LL
56	// discard fragment after 60 seconds
57
58
59typedef DoublyLinkedList<struct net_buffer,
60	DoublyLinkedListCLink<struct net_buffer> > FragmentList;
61
62typedef NetBufferField<uint16, offsetof(ipv4_header, checksum)> IPChecksumField;
63
64struct ipv4_packet_key {
65	in_addr_t	source;
66	in_addr_t	destination;
67	uint16		id;
68	uint8		protocol;
69};
70
71
72class FragmentPacket {
73public:
74								FragmentPacket(const ipv4_packet_key& key);
75								~FragmentPacket();
76
77			status_t			AddFragment(uint16 start, uint16 end,
78									net_buffer* buffer, bool lastFragment);
79			status_t			Reassemble(net_buffer* to);
80
81			bool				IsComplete() const
82									{ return fReceivedLastFragment
83										&& fBytesLeft == 0; }
84
85			const ipv4_packet_key& Key() const { return fKey; }
86			FragmentPacket*&	HashTableLink() { return fNext; }
87
88	static	void				StaleTimer(struct net_timer* timer, void* data);
89
90private:
91			FragmentPacket*		fNext;
92			struct ipv4_packet_key fKey;
93			uint32				fIndex;
94			bool				fReceivedLastFragment;
95			int32				fBytesLeft;
96			FragmentList		fFragments;
97			net_timer			fTimer;
98};
99
100
101struct FragmentHashDefinition {
102	typedef ipv4_packet_key KeyType;
103	typedef FragmentPacket ValueType;
104
105	size_t HashKey(const KeyType& key) const
106	{
107		return (key.source ^ key.destination ^ key.protocol ^ key.id);
108	}
109
110	size_t Hash(ValueType* value) const
111	{
112		return HashKey(value->Key());
113	}
114
115	bool Compare(const KeyType& key, ValueType* value) const
116	{
117		const ipv4_packet_key& packetKey = value->Key();
118
119		return packetKey.id == key.id
120			&& packetKey.source == key.source
121			&& packetKey.destination == key.destination
122			&& packetKey.protocol == key.protocol;
123	}
124
125	ValueType*& GetLink(ValueType* value) const
126	{
127		return value->HashTableLink();
128	}
129};
130
131typedef BOpenHashTable<FragmentHashDefinition, false, true> FragmentTable;
132
133
134class RawSocket
135	: public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
136public:
137								RawSocket(net_socket* socket);
138};
139
140typedef DoublyLinkedList<RawSocket> RawSocketList;
141
142typedef MulticastGroupInterface<IPv4Multicast> IPv4GroupInterface;
143typedef MulticastFilter<IPv4Multicast> IPv4MulticastFilter;
144
145struct MulticastStateHash {
146	typedef std::pair<const in_addr* , uint32> KeyType;
147	typedef IPv4GroupInterface ValueType;
148
149	size_t HashKey(const KeyType &key) const
150		{ return key.first->s_addr ^ key.second; }
151	size_t Hash(ValueType* value) const
152		{ return HashKey(std::make_pair(&value->Address(),
153			value->Interface()->index)); }
154	bool Compare(const KeyType &key, ValueType* value) const
155		{ return value->Interface()->index == key.second
156			&& value->Address().s_addr == key.first->s_addr; }
157	bool CompareValues(ValueType* value1, ValueType* value2) const
158		{ return value1->Interface()->index == value2->Interface()->index
159			&& value1->Address().s_addr == value2->Address().s_addr; }
160	ValueType*& GetLink(ValueType* value) const { return value->MulticastGroupsHashLink(); }
161};
162
163
164struct ipv4_protocol : net_protocol {
165	ipv4_protocol()
166		:
167		raw(NULL),
168		multicast_filter(this)
169	{
170	}
171
172	~ipv4_protocol()
173	{
174		delete raw;
175	}
176
177	RawSocket*			raw;
178	uint8				service_type;
179	uint8				time_to_live;
180	uint8				multicast_time_to_live;
181	bool				multicast_loopback;
182	uint32				flags;
183	struct sockaddr*	multicast_address; // for IP_MULTICAST_IF
184
185	IPv4MulticastFilter	multicast_filter;
186};
187
188// protocol flags
189#define IP_FLAG_HEADER_INCLUDED		0x01
190#define IP_FLAG_RECEIVE_DEST_ADDR	0x02
191
192
193static const int kDefaultTTL = 254;
194static const int kDefaultMulticastTTL = 1;
195static const bool kDefaultMulticastLoopback = true;
196
197
198extern net_protocol_module_info gIPv4Module;
199	// we need this in ipv4_std_ops() for registering the AF_INET domain
200
201net_stack_module_info* gStackModule;
202net_buffer_module_info* gBufferModule;
203
204static struct net_domain* sDomain;
205static net_datalink_module_info* sDatalinkModule;
206static net_socket_module_info* sSocketModule;
207static int32 sPacketID;
208static RawSocketList sRawSockets;
209static mutex sRawSocketsLock;
210static mutex sFragmentLock;
211static FragmentTable sFragmentHash;
212static mutex sMulticastGroupsLock;
213
214typedef MultiHashTable<MulticastStateHash> MulticastState;
215static MulticastState* sMulticastState;
216
217static net_protocol_module_info* sReceivingProtocol[256];
218static mutex sReceivingProtocolLock;
219
220
221static const char*
222print_address(const in_addr* address, char* buf, size_t bufLen)
223{
224	unsigned int addr = ntohl(address->s_addr);
225
226	snprintf(buf, bufLen, "%u.%u.%u.%u", (addr >> 24) & 0xff,
227		(addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
228
229	return buf;
230}
231
232
233RawSocket::RawSocket(net_socket* socket)
234	:
235	DatagramSocket<>("ipv4 raw socket", socket)
236{
237}
238
239
240//	#pragma mark -
241
242
243FragmentPacket::FragmentPacket(const ipv4_packet_key& key)
244	:
245	fKey(key),
246	fIndex(0),
247	fReceivedLastFragment(false),
248	fBytesLeft(IP_MAXPACKET)
249{
250	gStackModule->init_timer(&fTimer, FragmentPacket::StaleTimer, this);
251}
252
253
254FragmentPacket::~FragmentPacket()
255{
256	// cancel the kill timer
257	gStackModule->set_timer(&fTimer, -1);
258
259	// delete all fragments
260	net_buffer* buffer;
261	while ((buffer = fFragments.RemoveHead()) != NULL) {
262		gBufferModule->free(buffer);
263	}
264}
265
266
267status_t
268FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer* buffer,
269	bool lastFragment)
270{
271	// restart the timer
272	gStackModule->set_timer(&fTimer, FRAGMENT_TIMEOUT);
273
274	if (start >= end) {
275		// invalid fragment
276		return B_BAD_DATA;
277	}
278
279	// Search for a position in the list to insert the fragment
280
281	FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator();
282	net_buffer* previous = NULL;
283	net_buffer* next = NULL;
284	while ((previous = iterator.Next()) != NULL) {
285		if (previous->fragment.start <= start) {
286			// The new fragment can be inserted after this one
287			break;
288		}
289
290		next = previous;
291	}
292
293	// See if we already have the fragment's data
294
295	if (previous != NULL && previous->fragment.start <= start
296		&& previous->fragment.end >= end) {
297		// we do, so we can just drop this fragment
298		gBufferModule->free(buffer);
299		return B_OK;
300	}
301
302	fIndex = buffer->index;
303		// adopt the buffer's device index
304
305	TRACE("    previous: %p, next: %p", previous, next);
306
307	// If we have parts of the data already, truncate as needed
308
309	if (previous != NULL && previous->fragment.end > start) {
310		TRACE("    remove header %d bytes", previous->fragment.end - start);
311		gBufferModule->remove_header(buffer, previous->fragment.end - start);
312		start = previous->fragment.end;
313	}
314	if (next != NULL && end > next->fragment.start) {
315		TRACE("    remove trailer %d bytes", end - next->fragment.start);
316		gBufferModule->remove_trailer(buffer, end - next->fragment.start);
317		end = next->fragment.start;
318	}
319
320	// Now try if we can already merge the fragments together
321
322	// We will always keep the last buffer received, so that we can still
323	// report an error (in which case we're not responsible for freeing it)
324
325	if (previous != NULL && previous->fragment.end == start) {
326		fFragments.Remove(previous);
327
328		buffer->fragment.start = previous->fragment.start;
329		buffer->fragment.end = end;
330
331		status_t status = gBufferModule->merge(buffer, previous, false);
332		TRACE("    merge previous: %s", strerror(status));
333		if (status != B_OK) {
334			fFragments.InsertBefore(next, previous);
335			return status;
336		}
337
338		fFragments.InsertBefore(next, buffer);
339
340		// cut down existing hole
341		fBytesLeft -= end - start;
342
343		if (lastFragment && !fReceivedLastFragment) {
344			fReceivedLastFragment = true;
345			fBytesLeft -= IP_MAXPACKET - end;
346		}
347
348		TRACE("    hole length: %d", (int)fBytesLeft);
349
350		return B_OK;
351	} else if (next != NULL && next->fragment.start == end) {
352		net_buffer* afterNext = (net_buffer*)next->link.next;
353		fFragments.Remove(next);
354
355		buffer->fragment.start = start;
356		buffer->fragment.end = next->fragment.end;
357
358		status_t status = gBufferModule->merge(buffer, next, true);
359		TRACE("    merge next: %s", strerror(status));
360		if (status != B_OK) {
361			// Insert "next" at its previous position
362			fFragments.InsertBefore(afterNext, next);
363			return status;
364		}
365
366		fFragments.InsertBefore(afterNext, buffer);
367
368		// cut down existing hole
369		fBytesLeft -= end - start;
370
371		if (lastFragment && !fReceivedLastFragment) {
372			fReceivedLastFragment = true;
373			fBytesLeft -= IP_MAXPACKET - end;
374		}
375
376		TRACE("    hole length: %d", (int)fBytesLeft);
377
378		return B_OK;
379	}
380
381	// We couldn't merge the fragments, so we need to add it as is
382
383	TRACE("    new fragment: %p, bytes %d-%d", buffer, start, end);
384
385	buffer->fragment.start = start;
386	buffer->fragment.end = end;
387	fFragments.InsertBefore(next, buffer);
388
389	// update length of the hole, if any
390	fBytesLeft -= end - start;
391
392	if (lastFragment && !fReceivedLastFragment) {
393		fReceivedLastFragment = true;
394		fBytesLeft -= IP_MAXPACKET - end;
395	}
396
397	TRACE("    hole length: %d", (int)fBytesLeft);
398
399	return B_OK;
400}
401
402
403/*!	Reassembles the fragments to the specified buffer \a to.
404	This buffer must have been added via AddFragment() before.
405*/
406status_t
407FragmentPacket::Reassemble(net_buffer* to)
408{
409	if (!IsComplete())
410		return B_ERROR;
411
412	net_buffer* buffer = NULL;
413
414	net_buffer* fragment;
415	while ((fragment = fFragments.RemoveHead()) != NULL) {
416		if (buffer != NULL) {
417			status_t status;
418			if (to == fragment) {
419				status = gBufferModule->merge(fragment, buffer, false);
420				buffer = fragment;
421			} else
422				status = gBufferModule->merge(buffer, fragment, true);
423			if (status != B_OK)
424				return status;
425		} else
426			buffer = fragment;
427	}
428
429	if (buffer != to)
430		panic("ipv4 packet reassembly did not work correctly.");
431
432	to->index = fIndex;
433		// reset the buffer's device index
434
435	return B_OK;
436}
437
438
439/*static*/ void
440FragmentPacket::StaleTimer(struct net_timer* timer, void* data)
441{
442	FragmentPacket* packet = (FragmentPacket*)data;
443	TRACE("Assembling FragmentPacket %p timed out!", packet);
444
445	MutexLocker locker(&sFragmentLock);
446	sFragmentHash.Remove(packet);
447	locker.Unlock();
448
449	if (!packet->fFragments.IsEmpty()) {
450		// Send error: fragment reassembly time exceeded
451		sDomain->module->error_reply(NULL, packet->fFragments.First(),
452			B_NET_ERROR_REASSEMBLY_TIME_EXCEEDED, NULL);
453	}
454
455	delete packet;
456}
457
458
459//	#pragma mark -
460
461
462#ifdef TRACE_IPV4
463static void
464dump_ipv4_header(ipv4_header &header)
465{
466	struct pretty_ipv4 {
467	#if B_HOST_IS_LENDIAN == 1
468		uint8 a;
469		uint8 b;
470		uint8 c;
471		uint8 d;
472	#else
473		uint8 d;
474		uint8 c;
475		uint8 b;
476		uint8 a;
477	#endif
478	};
479	struct pretty_ipv4* src = (struct pretty_ipv4*)&header.source;
480	struct pretty_ipv4* dst = (struct pretty_ipv4*)&header.destination;
481	dprintf("  version: %d\n", header.version);
482	dprintf("  header_length: 4 * %d\n", header.header_length);
483	dprintf("  service_type: %d\n", header.service_type);
484	dprintf("  total_length: %d\n", header.TotalLength());
485	dprintf("  id: %d\n", ntohs(header.id));
486	dprintf("  fragment_offset: %d (flags: %c%c%c)\n",
487		header.FragmentOffset() & IP_FRAGMENT_OFFSET_MASK,
488		(header.FragmentOffset() & IP_RESERVED_FLAG) ? 'r' : '-',
489		(header.FragmentOffset() & IP_DONT_FRAGMENT) ? 'd' : '-',
490		(header.FragmentOffset() & IP_MORE_FRAGMENTS) ? 'm' : '-');
491	dprintf("  time_to_live: %d\n", header.time_to_live);
492	dprintf("  protocol: %d\n", header.protocol);
493	dprintf("  checksum: %d\n", ntohs(header.checksum));
494	dprintf("  source: %d.%d.%d.%d\n", src->a, src->b, src->c, src->d);
495	dprintf("  destination: %d.%d.%d.%d\n", dst->a, dst->b, dst->c, dst->d);
496}
497#endif	// TRACE_IPV4
498
499
500static int
501dump_ipv4_multicast(int argc, char** argv)
502{
503	MulticastState::Iterator groupIterator = sMulticastState->GetIterator();
504
505	while (groupIterator.HasNext()) {
506		IPv4GroupInterface* state = groupIterator.Next();
507
508		char addressBuffer[64];
509
510		kprintf("%p: group <%s, %s, %s {", state, state->Interface()->name,
511			print_address(&state->Address(), addressBuffer,
512			sizeof(addressBuffer)),
513			state->Mode() == IPv4GroupInterface::kExclude
514				? "Exclude" : "Include");
515
516		int count = 0;
517		IPv4GroupInterface::AddressSet::Iterator addressIterator
518			= state->Sources().GetIterator();
519		while (addressIterator.HasNext()) {
520			kprintf("%s%s", count > 0 ? ", " : "",
521				print_address(&addressIterator.Next(),
522				addressBuffer, sizeof(addressBuffer)));
523			count++;
524		}
525
526		kprintf("}> sock %p\n", state->Parent()->Socket());
527	}
528
529	return 0;
530}
531
532
533/*!	Attempts to re-assemble fragmented packets.
534	\return B_OK if everything went well; if it could reassemble the packet, \a _buffer
535		will point to its buffer, otherwise, it will be \c NULL.
536	\return various error codes if something went wrong (mostly B_NO_MEMORY)
537*/
538static status_t
539reassemble_fragments(const ipv4_header &header, net_buffer** _buffer)
540{
541	net_buffer* buffer = *_buffer;
542	status_t status;
543
544	struct ipv4_packet_key key;
545	key.source = (in_addr_t)header.source;
546	key.destination = (in_addr_t)header.destination;
547	key.id = header.id;
548	key.protocol = header.protocol;
549
550	// TODO: Make locking finer grained.
551	MutexLocker locker(&sFragmentLock);
552
553	FragmentPacket* packet = sFragmentHash.Lookup(key);
554	if (packet == NULL) {
555		// New fragment packet
556		packet = new (std::nothrow) FragmentPacket(key);
557		if (packet == NULL)
558			return B_NO_MEMORY;
559
560		// add packet to hash
561		status = sFragmentHash.Insert(packet);
562		if (status != B_OK) {
563			delete packet;
564			return status;
565		}
566	}
567
568	uint16 fragmentOffset = header.FragmentOffset();
569	uint16 start = (fragmentOffset & IP_FRAGMENT_OFFSET_MASK) << 3;
570	uint16 end = start + header.TotalLength() - header.HeaderLength();
571	bool lastFragment = (fragmentOffset & IP_MORE_FRAGMENTS) == 0;
572
573	TRACE("   Received IPv4 %sfragment of size %d, offset %d.",
574		lastFragment ? "last ": "", end - start, start);
575
576	// Remove header unless this is the first fragment
577	if (start != 0)
578		gBufferModule->remove_header(buffer, header.HeaderLength());
579
580	status = packet->AddFragment(start, end, buffer, lastFragment);
581	if (status != B_OK)
582		return status;
583
584	if (packet->IsComplete()) {
585		sFragmentHash.Remove(packet);
586			// no matter if reassembling succeeds, we won't need this packet
587			// anymore
588
589		status = packet->Reassemble(buffer);
590		delete packet;
591
592		// _buffer does not change
593		return status;
594	}
595
596	// This indicates that the packet is not yet complete
597	*_buffer = NULL;
598	return B_OK;
599}
600
601
602/*!	Fragments the incoming buffer and send all fragments via the specified
603	\a route.
604*/
605static status_t
606send_fragments(ipv4_protocol* protocol, struct net_route* route,
607	net_buffer* buffer, uint32 mtu)
608{
609	TRACE_SK(protocol, "SendFragments(%" B_PRIu32 " bytes, mtu %" B_PRIu32 ")",
610		buffer->size, mtu);
611
612	NetBufferHeaderReader<ipv4_header> originalHeader(buffer);
613	if (originalHeader.Status() != B_OK)
614		return originalHeader.Status();
615
616	uint16 headerLength = originalHeader->HeaderLength();
617	uint32 bytesLeft = buffer->size - headerLength;
618	uint32 fragmentOffset = 0;
619	status_t status = B_OK;
620
621	net_buffer* headerBuffer = gBufferModule->split(buffer, headerLength);
622	if (headerBuffer == NULL)
623		return B_NO_MEMORY;
624
625	// TODO: we need to make sure ipv4_header is contiguous or
626	// use another construct.
627	NetBufferHeaderReader<ipv4_header> bufferHeader(headerBuffer);
628	ipv4_header* header = &bufferHeader.Data();
629
630	// Adapt MTU to be a multiple of 8 (fragment offsets can only be specified
631	// this way)
632	mtu -= headerLength;
633	mtu &= ~7;
634	TRACE("  adjusted MTU to %" B_PRIu32 ", bytesLeft %" B_PRIu32, mtu,
635		bytesLeft);
636
637	while (bytesLeft > 0) {
638		uint32 fragmentLength = min_c(bytesLeft, mtu);
639		bytesLeft -= fragmentLength;
640		bool lastFragment = bytesLeft == 0;
641
642		header->total_length = htons(fragmentLength + headerLength);
643		header->fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS)
644			| (fragmentOffset >> 3));
645		header->checksum = 0;
646		header->checksum = gStackModule->checksum((uint8*)header,
647			headerLength);
648			// TODO: compute the checksum only for those parts that changed?
649
650		TRACE("  send fragment of %" B_PRIu32 " bytes (%" B_PRIu32 " bytes "
651			"left)", fragmentLength, bytesLeft);
652
653		net_buffer* fragmentBuffer;
654		if (!lastFragment) {
655			fragmentBuffer = gBufferModule->split(buffer, fragmentLength);
656			fragmentOffset += fragmentLength;
657		} else
658			fragmentBuffer = buffer;
659
660		if (fragmentBuffer == NULL) {
661			status = B_NO_MEMORY;
662			break;
663		}
664
665		// copy header to fragment
666		status = gBufferModule->prepend(fragmentBuffer, header, headerLength);
667
668		// send fragment
669		if (status == B_OK)
670			status = sDatalinkModule->send_routed_data(route, fragmentBuffer);
671
672		if (lastFragment) {
673			// we don't own the last buffer, so we don't have to free it
674			break;
675		}
676
677		if (status != B_OK) {
678			gBufferModule->free(fragmentBuffer);
679			break;
680		}
681	}
682
683	gBufferModule->free(headerBuffer);
684	return status;
685}
686
687
688status_t ipv4_receive_data(net_buffer* buffer);
689
690
691/*!	Delivers the provided \a buffer to all listeners of this multicast group.
692	Does not take over ownership of the buffer.
693*/
694static bool
695deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
696	bool deliverToRaw)
697{
698	TRACE("deliver_multicast(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
699	if (module->deliver_data == NULL)
700		return false;
701
702	MutexLocker _(sMulticastGroupsLock);
703
704	sockaddr_in* multicastAddr = (sockaddr_in*)buffer->destination;
705
706	uint32 index = buffer->index;
707	if (buffer->interface_address != NULL)
708		index = buffer->interface_address->interface->index;
709
710	MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
711		&multicastAddr->sin_addr, index));
712
713	size_t count = 0;
714
715	while (it.HasNext()) {
716		IPv4GroupInterface* state = it.Next();
717
718		ipv4_protocol* ipProtocol = state->Parent()->Socket();
719		if (deliverToRaw && (ipProtocol->raw == NULL
720				|| ipProtocol->socket->protocol != buffer->protocol))
721			continue;
722
723		if (state->FilterAccepts(buffer)) {
724			net_protocol* protocol = ipProtocol;
725			if (protocol->module != module) {
726				// as multicast filters are installed with an IPv4 protocol
727				// reference, we need to go and find the appropriate instance
728				// related to the 'receiving protocol' with module 'module'.
729				protocol = ipProtocol->socket->first_protocol;
730
731				while (protocol != NULL && protocol->module != module)
732					protocol = protocol->next;
733			}
734
735			if (protocol != NULL) {
736				module->deliver_data(protocol, buffer);
737				count++;
738			}
739		}
740	}
741
742	return count > 0;
743}
744
745
746/*!	Delivers the buffer to all listening raw sockets without taking ownership of
747	the provided \a buffer.
748	Returns \c true if there was any receiver, \c false if not.
749*/
750static bool
751raw_receive_data(net_buffer* buffer)
752{
753	MutexLocker locker(sRawSocketsLock);
754
755	if (sRawSockets.IsEmpty())
756		return false;
757
758	TRACE("RawReceiveData(%i)", buffer->protocol);
759
760	if ((buffer->flags & MSG_MCAST) != 0) {
761		// we need to call deliver_multicast here separately as
762		// buffer still has the IP header, and it won't in the
763		// next call. This isn't very optimized but works for now.
764		// A better solution would be to hold separate hash tables
765		// and lists for RAW and non-RAW sockets.
766		return deliver_multicast(&gIPv4Module, buffer, true);
767	}
768
769	RawSocketList::Iterator iterator = sRawSockets.GetIterator();
770	size_t count = 0;
771
772	while (iterator.HasNext()) {
773		RawSocket* raw = iterator.Next();
774
775		if (raw->Socket()->protocol == buffer->protocol) {
776			raw->EnqueueClone(buffer);
777			count++;
778		}
779	}
780
781	return count > 0;
782}
783
784
785static inline sockaddr*
786fill_sockaddr_in(sockaddr_in* target, in_addr_t address)
787{
788	target->sin_family = AF_INET;
789	target->sin_len = sizeof(sockaddr_in);
790	target->sin_port = 0;
791	target->sin_addr.s_addr = address;
792	return (sockaddr*)target;
793}
794
795
796static status_t
797get_int_option(void* target, size_t length, int value)
798{
799	if (length != sizeof(int))
800		return B_BAD_VALUE;
801
802	return user_memcpy(target, &value, sizeof(int));
803}
804
805
806static status_t
807get_char_int_option(void* target, size_t length, int value)
808{
809	if (length == sizeof(int))
810		return user_memcpy(target, &value, sizeof(int));
811	if (length == sizeof(unsigned char)) {
812		unsigned char uvalue = value;
813		return user_memcpy(target, &uvalue, sizeof(uvalue));
814	}
815	return B_BAD_VALUE;
816}
817
818
819template<typename Type> static status_t
820set_int_option(Type &target, const void* _value, size_t length)
821{
822	int value;
823
824	if (length != sizeof(int))
825		return B_BAD_VALUE;
826
827	if (user_memcpy(&value, _value, sizeof(int)) != B_OK)
828		return B_BAD_ADDRESS;
829
830	target = value;
831	return B_OK;
832}
833
834
835template<typename Type> static status_t
836set_char_int_option(Type &target, const void* _value, size_t length)
837{
838	if (length == sizeof(int)) {
839		int value;
840		if (user_memcpy(&value, _value, sizeof(int)) != B_OK)
841			return B_BAD_ADDRESS;
842		if (value > 255)
843			return B_BAD_VALUE;
844		target = value;
845		return B_OK;
846	}
847	if (length == sizeof(unsigned char)) {
848		unsigned char value;
849		if (user_memcpy(&value, _value, sizeof(value)) != B_OK)
850			return B_BAD_ADDRESS;
851
852		target = value;
853		return B_OK;
854	}
855	return B_BAD_VALUE;
856}
857
858
859static net_protocol_module_info*
860receiving_protocol(uint8 protocol)
861{
862	net_protocol_module_info* module = sReceivingProtocol[protocol];
863	if (module != NULL)
864		return module;
865
866	MutexLocker locker(sReceivingProtocolLock);
867
868	module = sReceivingProtocol[protocol];
869	if (module != NULL)
870		return module;
871
872	if (gStackModule->get_domain_receiving_protocol(sDomain, protocol,
873			&module) == B_OK)
874		sReceivingProtocol[protocol] = module;
875
876	return module;
877}
878
879
880// #pragma mark - multicast
881
882
883status_t
884IPv4Multicast::JoinGroup(IPv4GroupInterface* state)
885{
886	MutexLocker _(sMulticastGroupsLock);
887
888	sockaddr_in groupAddr;
889	status_t status = sDatalinkModule->join_multicast(state->Interface(),
890		sDomain, fill_sockaddr_in(&groupAddr, state->Address().s_addr));
891	if (status != B_OK)
892		return status;
893
894	sMulticastState->Insert(state);
895	return B_OK;
896}
897
898
899status_t
900IPv4Multicast::LeaveGroup(IPv4GroupInterface* state)
901{
902	MutexLocker _(sMulticastGroupsLock);
903
904	sMulticastState->Remove(state);
905
906	sockaddr_in groupAddr;
907	return sDatalinkModule->leave_multicast(state->Interface(), sDomain,
908		fill_sockaddr_in(&groupAddr, state->Address().s_addr));
909}
910
911
912static status_t
913ipv4_delta_group(IPv4GroupInterface* group, int option,
914	net_interface* interface, const in_addr* sourceAddr)
915{
916	switch (option) {
917		case IP_ADD_MEMBERSHIP:
918			return group->Add();
919		case IP_DROP_MEMBERSHIP:
920			return group->Drop();
921		case IP_BLOCK_SOURCE:
922			return group->BlockSource(*sourceAddr);
923		case IP_UNBLOCK_SOURCE:
924			return group->UnblockSource(*sourceAddr);
925		case IP_ADD_SOURCE_MEMBERSHIP:
926			return group->AddSSM(*sourceAddr);
927		case IP_DROP_SOURCE_MEMBERSHIP:
928			return group->DropSSM(*sourceAddr);
929	}
930
931	return B_ERROR;
932}
933
934
935static status_t
936ipv4_delta_membership(ipv4_protocol* protocol, int option,
937	net_interface* interface, const in_addr* groupAddr,
938	const in_addr* sourceAddr)
939{
940	IPv4MulticastFilter& filter = protocol->multicast_filter;
941	IPv4GroupInterface* state = NULL;
942	status_t status = B_OK;
943
944	switch (option) {
945		case IP_ADD_MEMBERSHIP:
946		case IP_ADD_SOURCE_MEMBERSHIP:
947			status = filter.GetState(*groupAddr, interface, state, true);
948			break;
949
950		case IP_DROP_MEMBERSHIP:
951		case IP_BLOCK_SOURCE:
952		case IP_UNBLOCK_SOURCE:
953		case IP_DROP_SOURCE_MEMBERSHIP:
954			filter.GetState(*groupAddr, interface, state, false);
955			if (state == NULL) {
956				if (option == IP_DROP_MEMBERSHIP
957					|| option == IP_DROP_SOURCE_MEMBERSHIP)
958					return EADDRNOTAVAIL;
959
960				return B_BAD_VALUE;
961			}
962			break;
963	}
964
965	if (status != B_OK)
966		return status;
967
968	status = ipv4_delta_group(state, option, interface, sourceAddr);
969	filter.ReturnState(state);
970	return status;
971}
972
973
974static int
975generic_to_ipv4(int option)
976{
977	switch (option) {
978		case MCAST_JOIN_GROUP:
979			return IP_ADD_MEMBERSHIP;
980		case MCAST_JOIN_SOURCE_GROUP:
981			return IP_ADD_SOURCE_MEMBERSHIP;
982		case MCAST_LEAVE_GROUP:
983			return IP_DROP_MEMBERSHIP;
984		case MCAST_BLOCK_SOURCE:
985			return IP_BLOCK_SOURCE;
986		case MCAST_UNBLOCK_SOURCE:
987			return IP_UNBLOCK_SOURCE;
988		case MCAST_LEAVE_SOURCE_GROUP:
989			return IP_DROP_SOURCE_MEMBERSHIP;
990	}
991
992	return -1;
993}
994
995
996static net_interface*
997get_multicast_interface(ipv4_protocol* protocol, const in_addr* address)
998{
999	// TODO: this is broken and leaks references
1000	sockaddr_in groupAddr;
1001	net_route* route = sDatalinkModule->get_route(sDomain,
1002		fill_sockaddr_in(&groupAddr, address ? address->s_addr : INADDR_ANY));
1003	if (route == NULL)
1004		return NULL;
1005
1006	return route->interface_address->interface;
1007}
1008
1009
1010static status_t
1011ipv4_delta_membership(ipv4_protocol* protocol, int option,
1012	in_addr* interfaceAddr, in_addr* groupAddr, in_addr* sourceAddr)
1013{
1014	net_interface* interface = NULL;
1015
1016	if (interfaceAddr->s_addr == INADDR_ANY) {
1017		interface = get_multicast_interface(protocol, groupAddr);
1018	} else {
1019		sockaddr_in address;
1020		interface = sDatalinkModule->get_interface_with_address(
1021			fill_sockaddr_in(&address, interfaceAddr->s_addr));
1022	}
1023
1024	if (interface == NULL)
1025		return B_DEVICE_NOT_FOUND;
1026
1027	return ipv4_delta_membership(protocol, option, interface,
1028		groupAddr, sourceAddr);
1029}
1030
1031
1032static status_t
1033ipv4_generic_delta_membership(ipv4_protocol* protocol, int option,
1034	uint32 index, const sockaddr_storage* _groupAddr,
1035	const sockaddr_storage* _sourceAddr)
1036{
1037	if (_groupAddr->ss_family != AF_INET
1038		|| (_sourceAddr != NULL && _sourceAddr->ss_family != AF_INET))
1039		return B_BAD_VALUE;
1040
1041	const in_addr* groupAddr = &((const sockaddr_in*)_groupAddr)->sin_addr;
1042
1043	// TODO: this is broken and leaks references
1044	net_interface* interface;
1045	if (index == 0)
1046		interface = get_multicast_interface(protocol, groupAddr);
1047	else
1048		interface = sDatalinkModule->get_interface(sDomain, index);
1049
1050	if (interface == NULL)
1051		return B_DEVICE_NOT_FOUND;
1052
1053	const in_addr* sourceAddr = NULL;
1054	if (_sourceAddr != NULL)
1055		sourceAddr = &((const sockaddr_in*)_sourceAddr)->sin_addr;
1056
1057	return ipv4_delta_membership(protocol, generic_to_ipv4(option), interface,
1058		groupAddr, sourceAddr);
1059}
1060
1061
1062//	#pragma mark - module interface
1063
1064
1065net_protocol*
1066ipv4_init_protocol(net_socket* socket)
1067{
1068	ipv4_protocol* protocol = new (std::nothrow) ipv4_protocol();
1069	if (protocol == NULL)
1070		return NULL;
1071
1072	protocol->raw = NULL;
1073	protocol->service_type = 0;
1074	protocol->time_to_live = kDefaultTTL;
1075	protocol->multicast_time_to_live = kDefaultMulticastTTL;
1076	protocol->multicast_loopback = kDefaultMulticastLoopback;
1077	protocol->flags = 0;
1078	protocol->multicast_address = NULL;
1079	return protocol;
1080}
1081
1082
1083status_t
1084ipv4_uninit_protocol(net_protocol* _protocol)
1085{
1086	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1087
1088	delete protocol;
1089
1090	return B_OK;
1091}
1092
1093
1094/*!	Since open() is only called on the top level protocol, when we get here
1095	it means we are on a SOCK_RAW socket.
1096*/
1097status_t
1098ipv4_open(net_protocol* _protocol)
1099{
1100	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1101
1102	// Only root may open raw sockets
1103	if (geteuid() != 0)
1104		return B_NOT_ALLOWED;
1105
1106	RawSocket* raw = new (std::nothrow) RawSocket(protocol->socket);
1107	if (raw == NULL)
1108		return B_NO_MEMORY;
1109
1110	status_t status = raw->InitCheck();
1111	if (status != B_OK) {
1112		delete raw;
1113		return status;
1114	}
1115
1116	TRACE_SK(protocol, "Open()");
1117
1118	protocol->raw = raw;
1119
1120	MutexLocker locker(sRawSocketsLock);
1121	sRawSockets.Add(raw);
1122	return B_OK;
1123}
1124
1125
1126status_t
1127ipv4_close(net_protocol* _protocol)
1128{
1129	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1130	RawSocket* raw = protocol->raw;
1131	if (raw == NULL)
1132		return B_ERROR;
1133
1134	TRACE_SK(protocol, "Close()");
1135
1136	MutexLocker locker(sRawSocketsLock);
1137	sRawSockets.Remove(raw);
1138	delete raw;
1139	protocol->raw = NULL;
1140
1141	return B_OK;
1142}
1143
1144
1145status_t
1146ipv4_free(net_protocol* protocol)
1147{
1148	return B_OK;
1149}
1150
1151
1152status_t
1153ipv4_connect(net_protocol* _protocol, const struct sockaddr* address)
1154{
1155	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1156	RawSocket* raw = protocol->raw;
1157	if (raw == NULL)
1158		return B_ERROR;
1159	if (address->sa_len != sizeof(struct sockaddr_in))
1160		return B_BAD_VALUE;
1161	if (address->sa_family != AF_INET)
1162		return EAFNOSUPPORT;
1163
1164	memcpy(&protocol->socket->peer, address, sizeof(struct sockaddr_in));
1165	sSocketModule->set_connected(protocol->socket);
1166
1167	return B_OK;
1168}
1169
1170
1171status_t
1172ipv4_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
1173{
1174	return B_NOT_SUPPORTED;
1175}
1176
1177
1178status_t
1179ipv4_control(net_protocol* _protocol, int level, int option, void* value,
1180	size_t* _length)
1181{
1182	if ((level & LEVEL_MASK) != IPPROTO_IP)
1183		return sDatalinkModule->control(sDomain, option, value, _length);
1184
1185	return B_BAD_VALUE;
1186}
1187
1188
1189status_t
1190ipv4_getsockopt(net_protocol* _protocol, int level, int option, void* value,
1191	int* _length)
1192{
1193	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1194
1195	if (level == IPPROTO_IP) {
1196		bool isDgramOrRaw = protocol->socket->type == SOCK_DGRAM
1197			|| protocol->socket->type == SOCK_RAW;
1198		if (option == IP_HDRINCL) {
1199			return get_int_option(value, *_length,
1200				(protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0);
1201		}
1202		if (option == IP_RECVDSTADDR) {
1203			return get_int_option(value, *_length,
1204				(protocol->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0);
1205		}
1206		if (option == IP_TTL)
1207			return get_int_option(value, *_length, protocol->time_to_live);
1208		if (option == IP_TOS)
1209			return get_int_option(value, *_length, protocol->service_type);
1210		if (option == IP_MULTICAST_IF) {
1211			if (*_length != sizeof(struct in_addr))
1212				return B_BAD_VALUE;
1213			if (!isDgramOrRaw)
1214				return B_NOT_SUPPORTED;
1215			struct sockaddr_in defaultAddress;
1216			defaultAddress.sin_addr.s_addr = htonl(INADDR_ANY);
1217			struct sockaddr_in* address =
1218				(struct sockaddr_in*)protocol->multicast_address;
1219			if (address == NULL)
1220				address = &defaultAddress;
1221			if (user_memcpy(value, &address->sin_addr, sizeof(struct in_addr))
1222					!= B_OK) {
1223				return B_BAD_ADDRESS;
1224			}
1225			return B_OK;
1226		}
1227		if (option == IP_MULTICAST_TTL) {
1228			if (!isDgramOrRaw)
1229				return B_NOT_SUPPORTED;
1230			return get_char_int_option(value, *_length,
1231				protocol->multicast_time_to_live);
1232		}
1233		if (option == IP_MULTICAST_LOOP) {
1234			if (!isDgramOrRaw)
1235				return B_NOT_SUPPORTED;
1236			return get_char_int_option(value, *_length,
1237				protocol->multicast_loopback ? 1 : 0);
1238		}
1239		if (option == IP_ADD_MEMBERSHIP
1240			|| option == IP_DROP_MEMBERSHIP
1241			|| option == IP_BLOCK_SOURCE
1242			|| option == IP_UNBLOCK_SOURCE
1243			|| option == IP_ADD_SOURCE_MEMBERSHIP
1244			|| option == IP_DROP_SOURCE_MEMBERSHIP
1245			|| option == MCAST_JOIN_GROUP
1246			|| option == MCAST_LEAVE_GROUP
1247			|| option == MCAST_BLOCK_SOURCE
1248			|| option == MCAST_UNBLOCK_SOURCE
1249			|| option == MCAST_JOIN_SOURCE_GROUP
1250			|| option == MCAST_LEAVE_SOURCE_GROUP) {
1251			// RFC 3678, Section 4.1:
1252			// ``An error of EOPNOTSUPP is returned if these options are
1253			// used with getsockopt().''
1254			return B_NOT_SUPPORTED;
1255		}
1256
1257		dprintf("IPv4::getsockopt(): get unknown option: %d\n", option);
1258		return ENOPROTOOPT;
1259	}
1260
1261	return sSocketModule->get_option(protocol->socket, level, option, value,
1262		_length);
1263}
1264
1265
1266status_t
1267ipv4_setsockopt(net_protocol* _protocol, int level, int option,
1268	const void* value, int length)
1269{
1270	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1271
1272	if (level == IPPROTO_IP) {
1273		bool isDgramOrRaw = protocol->socket->type == SOCK_DGRAM
1274			|| protocol->socket->type == SOCK_RAW;
1275		if (option == IP_HDRINCL) {
1276			int headerIncluded;
1277			if (length != sizeof(int))
1278				return B_BAD_VALUE;
1279			if (user_memcpy(&headerIncluded, value, sizeof(headerIncluded))
1280					!= B_OK)
1281				return B_BAD_ADDRESS;
1282
1283			if (headerIncluded)
1284				protocol->flags |= IP_FLAG_HEADER_INCLUDED;
1285			else
1286				protocol->flags &= ~IP_FLAG_HEADER_INCLUDED;
1287
1288			return B_OK;
1289		}
1290		if (option == IP_RECVDSTADDR) {
1291			int getAddress;
1292			if (length != sizeof(int))
1293				return B_BAD_VALUE;
1294			if (user_memcpy(&getAddress, value, sizeof(int)) != B_OK)
1295				return B_BAD_ADDRESS;
1296
1297			if (getAddress && (protocol->socket->type == SOCK_DGRAM
1298					|| protocol->socket->type == SOCK_RAW))
1299				protocol->flags |= IP_FLAG_RECEIVE_DEST_ADDR;
1300			else
1301				protocol->flags &= ~IP_FLAG_RECEIVE_DEST_ADDR;
1302
1303			return B_OK;
1304		}
1305		if (option == IP_TTL)
1306			return set_int_option(protocol->time_to_live, value, length);
1307		if (option == IP_TOS)
1308			return set_int_option(protocol->service_type, value, length);
1309		if (option == IP_MULTICAST_IF) {
1310			if (length != sizeof(struct in_addr))
1311				return B_BAD_VALUE;
1312			if (!isDgramOrRaw)
1313				return B_NOT_SUPPORTED;
1314
1315			struct sockaddr_in* address = new (std::nothrow) sockaddr_in;
1316			if (address == NULL)
1317				return B_NO_MEMORY;
1318
1319			struct in_addr sin_addr;
1320			if (user_memcpy(&sin_addr, value, sizeof(struct in_addr))
1321					!= B_OK) {
1322				delete address;
1323				return B_BAD_ADDRESS;
1324			}
1325			fill_sockaddr_in(address, sin_addr.s_addr);
1326
1327			// Using INADDR_ANY to remove the previous setting.
1328			if (address->sin_addr.s_addr == htonl(INADDR_ANY)) {
1329				delete address;
1330				delete protocol->multicast_address;
1331				protocol->multicast_address = NULL;
1332				return B_OK;
1333			}
1334
1335			struct net_interface* interface
1336				= sDatalinkModule->get_interface_with_address(
1337					(sockaddr*)address);
1338			if (interface == NULL) {
1339				delete address;
1340				return EADDRNOTAVAIL;
1341			}
1342
1343			delete protocol->multicast_address;
1344			protocol->multicast_address = (struct sockaddr*)address;
1345
1346			sDatalinkModule->put_interface(interface);
1347			return B_OK;
1348		}
1349		if (option == IP_MULTICAST_TTL) {
1350			if (!isDgramOrRaw)
1351				return B_NOT_SUPPORTED;
1352			return set_char_int_option(protocol->multicast_time_to_live, value,
1353				length);
1354		}
1355		if (option == IP_MULTICAST_LOOP) {
1356			if (!isDgramOrRaw)
1357				return B_NOT_SUPPORTED;
1358			uint8 multicast_loopback;
1359			status_t status = set_char_int_option(multicast_loopback, value,
1360				length);
1361			if (status == B_OK)
1362				protocol->multicast_loopback = multicast_loopback != 0;
1363			return status;
1364		}
1365		if (option == IP_ADD_MEMBERSHIP || option == IP_DROP_MEMBERSHIP) {
1366			if (!isDgramOrRaw)
1367				return B_NOT_SUPPORTED;
1368			ip_mreq mreq;
1369			if (length != sizeof(ip_mreq))
1370				return B_BAD_VALUE;
1371			if (user_memcpy(&mreq, value, sizeof(ip_mreq)) != B_OK)
1372				return B_BAD_ADDRESS;
1373
1374			return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
1375				&mreq.imr_multiaddr, NULL);
1376		}
1377		if (option == IP_BLOCK_SOURCE
1378			|| option == IP_UNBLOCK_SOURCE
1379			|| option == IP_ADD_SOURCE_MEMBERSHIP
1380			|| option == IP_DROP_SOURCE_MEMBERSHIP) {
1381			if (!isDgramOrRaw)
1382				return B_NOT_SUPPORTED;
1383			ip_mreq_source mreq;
1384			if (length != sizeof(ip_mreq_source))
1385				return B_BAD_VALUE;
1386			if (user_memcpy(&mreq, value, sizeof(ip_mreq_source)) != B_OK)
1387				return B_BAD_ADDRESS;
1388
1389			return ipv4_delta_membership(protocol, option, &mreq.imr_interface,
1390				&mreq.imr_multiaddr, &mreq.imr_sourceaddr);
1391		}
1392		if (option == MCAST_LEAVE_GROUP || option == MCAST_JOIN_GROUP) {
1393			if (!isDgramOrRaw)
1394				return B_NOT_SUPPORTED;
1395			group_req greq;
1396			if (length != sizeof(group_req))
1397				return B_BAD_VALUE;
1398			if (user_memcpy(&greq, value, sizeof(group_req)) != B_OK)
1399				return B_BAD_ADDRESS;
1400
1401			return ipv4_generic_delta_membership(protocol, option,
1402				greq.gr_interface, &greq.gr_group, NULL);
1403		}
1404		if (option == MCAST_BLOCK_SOURCE
1405			|| option == MCAST_UNBLOCK_SOURCE
1406			|| option == MCAST_JOIN_SOURCE_GROUP
1407			|| option == MCAST_LEAVE_SOURCE_GROUP) {
1408			if (!isDgramOrRaw)
1409				return B_NOT_SUPPORTED;
1410			group_source_req greq;
1411			if (length != sizeof(group_source_req))
1412				return B_BAD_VALUE;
1413			if (user_memcpy(&greq, value, sizeof(group_source_req)) != B_OK)
1414				return B_BAD_ADDRESS;
1415
1416			return ipv4_generic_delta_membership(protocol, option,
1417				greq.gsr_interface, &greq.gsr_group, &greq.gsr_source);
1418		}
1419
1420		dprintf("IPv4::setsockopt(): set unknown option: %d\n", option);
1421		return ENOPROTOOPT;
1422	}
1423
1424	return sSocketModule->set_option(protocol->socket, level, option,
1425		value, length);
1426}
1427
1428
1429status_t
1430ipv4_bind(net_protocol* protocol, const struct sockaddr* address)
1431{
1432	if (address->sa_family != AF_INET)
1433		return EAFNOSUPPORT;
1434
1435	// only INADDR_ANY and addresses of local interfaces are accepted:
1436	if (((sockaddr_in*)address)->sin_addr.s_addr == INADDR_ANY
1437		|| IN_MULTICAST(ntohl(((sockaddr_in*)address)->sin_addr.s_addr))
1438		|| sDatalinkModule->is_local_address(sDomain, address, NULL, NULL)) {
1439		memcpy(&protocol->socket->address, address, sizeof(struct sockaddr_in));
1440		protocol->socket->address.ss_len = sizeof(struct sockaddr_in);
1441			// explicitly set length, as our callers can't be trusted to
1442			// always provide the correct length!
1443		return B_OK;
1444	}
1445
1446	return EADDRNOTAVAIL;
1447		// address is unknown on this host
1448}
1449
1450
1451status_t
1452ipv4_unbind(net_protocol* protocol, struct sockaddr* address)
1453{
1454	// nothing to do here
1455	return B_OK;
1456}
1457
1458
1459status_t
1460ipv4_listen(net_protocol* protocol, int count)
1461{
1462	return B_NOT_SUPPORTED;
1463}
1464
1465
1466status_t
1467ipv4_shutdown(net_protocol* protocol, int direction)
1468{
1469	return B_NOT_SUPPORTED;
1470}
1471
1472
1473status_t
1474ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route,
1475	net_buffer* buffer)
1476{
1477	if (route == NULL)
1478		return B_BAD_VALUE;
1479
1480	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1481	net_interface_address* interfaceAddress = route->interface_address;
1482	net_interface* interface = interfaceAddress->interface;
1483
1484	TRACE_SK(protocol, "SendRoutedData(%p, %p [%" B_PRIu32 " bytes])", route,
1485		buffer, buffer->size);
1486
1487	sockaddr_in& source = *(sockaddr_in*)buffer->source;
1488	sockaddr_in& destination = *(sockaddr_in*)buffer->destination;
1489	sockaddr_in* broadcastAddress = (sockaddr_in*)interfaceAddress->destination;
1490
1491	bool checksumNeeded = true;
1492	bool headerIncluded = false;
1493	if (protocol != NULL)
1494		headerIncluded = (protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0;
1495
1496	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
1497
1498	if (destination.sin_addr.s_addr == INADDR_ANY)
1499		return EDESTADDRREQ;
1500
1501	if ((interface->device->flags & IFF_BROADCAST) != 0
1502		&& (destination.sin_addr.s_addr == INADDR_BROADCAST
1503			|| (broadcastAddress != NULL && destination.sin_addr.s_addr
1504					== broadcastAddress->sin_addr.s_addr))) {
1505		if (protocol && !(protocol->socket->options & SO_BROADCAST))
1506			return B_BAD_VALUE;
1507		buffer->flags |= MSG_BCAST;
1508	} else if (IN_MULTICAST(ntohl(destination.sin_addr.s_addr)))
1509		buffer->flags |= MSG_MCAST;
1510
1511	// Add IP header (if needed)
1512
1513	if (!headerIncluded) {
1514		NetBufferPrepend<ipv4_header> header(buffer);
1515		if (header.Status() != B_OK)
1516			return header.Status();
1517
1518		header->version = IPV4_VERSION;
1519		header->header_length = sizeof(ipv4_header) / 4;
1520		header->service_type = protocol ? protocol->service_type : 0;
1521		header->total_length = htons(buffer->size);
1522		header->id = htons(atomic_add(&sPacketID, 1));
1523		header->fragment_offset = 0;
1524		if (protocol) {
1525			header->time_to_live = (buffer->flags & MSG_MCAST) != 0
1526				? protocol->multicast_time_to_live : protocol->time_to_live;
1527		} else {
1528			header->time_to_live = (buffer->flags & MSG_MCAST) != 0
1529				? kDefaultMulticastTTL : kDefaultTTL;
1530		}
1531		header->protocol = protocol
1532			? protocol->socket->protocol : buffer->protocol;
1533		header->checksum = 0;
1534
1535		header->source = source.sin_addr.s_addr;
1536		header->destination = destination.sin_addr.s_addr;
1537
1538		TRACE_ONLY(dump_ipv4_header(*header));
1539	} else {
1540		// if IP_HDRINCL, check if the source address is set
1541		NetBufferHeaderReader<ipv4_header> header(buffer);
1542		if (header.Status() != B_OK)
1543			return header.Status();
1544
1545		if (header->source == 0) {
1546			header->source = source.sin_addr.s_addr;
1547			header->checksum = 0;
1548			header.Sync();
1549		} else
1550			checksumNeeded = false;
1551
1552		TRACE("  Header was already supplied:");
1553		TRACE_ONLY(dump_ipv4_header(*header));
1554	}
1555
1556	if (buffer->size > 0xffff)
1557		return EMSGSIZE;
1558
1559	if (checksumNeeded) {
1560		*IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0,
1561			sizeof(ipv4_header), true);
1562	}
1563
1564	if ((buffer->flags & MSG_MCAST) != 0
1565		&& (protocol != NULL && protocol->multicast_loopback)) {
1566		// copy an IP multicast packet to the input queue of the loopback
1567		// interface
1568		net_buffer *loopbackBuffer = gBufferModule->duplicate(buffer);
1569		if (loopbackBuffer == NULL)
1570			return B_NO_MEMORY;
1571		status_t status = B_ERROR;
1572
1573		// get the IPv4 loopback address
1574		struct sockaddr loopbackAddress;
1575		gIPv4AddressModule.get_loopback_address(&loopbackAddress);
1576
1577		// get the matching interface address if any
1578		net_interface_address* address =
1579			sDatalinkModule->get_interface_address(&loopbackAddress);
1580		if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
1581			sDatalinkModule->put_interface_address(address);
1582		} else {
1583			sDatalinkModule->put_interface_address(
1584				loopbackBuffer->interface_address);
1585			loopbackBuffer->interface_address = address;
1586			status = ipv4_receive_data(loopbackBuffer);
1587		}
1588
1589		if (status != B_OK)
1590			gBufferModule->free(loopbackBuffer);
1591	}
1592
1593	TRACE_SK(protocol, "  SendRoutedData(): header chksum: %" B_PRIu32
1594		", buffer checksum: %" B_PRIu32,
1595		gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true),
1596		gBufferModule->checksum(buffer, 0, buffer->size, true));
1597
1598	TRACE_SK(protocol, "  SendRoutedData(): destination: %08x",
1599		ntohl(destination.sin_addr.s_addr));
1600
1601	uint32 mtu = route->mtu ? route->mtu : interface->device->mtu;
1602	if (buffer->size > mtu) {
1603		// we need to fragment the packet
1604		return send_fragments(protocol, route, buffer, mtu);
1605	}
1606
1607	return sDatalinkModule->send_routed_data(route, buffer);
1608}
1609
1610
1611status_t
1612ipv4_send_data(net_protocol* _protocol, net_buffer* buffer)
1613{
1614	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1615
1616	TRACE_SK(protocol, "SendData(%p [%" B_PRIu32 " bytes])", buffer,
1617		buffer->size);
1618
1619	if (protocol != NULL && (protocol->flags & IP_FLAG_HEADER_INCLUDED)) {
1620		if (buffer->size < sizeof(ipv4_header))
1621			return B_BAD_VALUE;
1622
1623		sockaddr_in* source = (sockaddr_in*)buffer->source;
1624		sockaddr_in* destination = (sockaddr_in*)buffer->destination;
1625
1626		fill_sockaddr_in(source, *NetBufferField<in_addr_t,
1627			offsetof(ipv4_header, source)>(buffer));
1628		fill_sockaddr_in(destination, *NetBufferField<in_addr_t,
1629			offsetof(ipv4_header, destination)>(buffer));
1630	}
1631
1632	// handle IP_MULTICAST_IF
1633	if (IN_MULTICAST(ntohl(
1634			((sockaddr_in*)buffer->destination)->sin_addr.s_addr))
1635		&& protocol != NULL && protocol->multicast_address != NULL) {
1636		net_interface_address* address = sDatalinkModule->get_interface_address(
1637			protocol->multicast_address);
1638		if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
1639			sDatalinkModule->put_interface_address(address);
1640			return EADDRNOTAVAIL;
1641		}
1642
1643		sDatalinkModule->put_interface_address(buffer->interface_address);
1644		buffer->interface_address = address;
1645			// the buffer takes over ownership of the address
1646
1647		net_route* route = sDatalinkModule->get_route(sDomain, address->local);
1648		if (route == NULL)
1649			return ENETUNREACH;
1650
1651		return sDatalinkModule->send_routed_data(route, buffer);
1652	}
1653
1654	return sDatalinkModule->send_data(protocol, sDomain, buffer);
1655}
1656
1657
1658ssize_t
1659ipv4_send_avail(net_protocol* protocol)
1660{
1661	return B_ERROR;
1662}
1663
1664
1665status_t
1666ipv4_read_data(net_protocol* _protocol, size_t numBytes, uint32 flags,
1667	net_buffer** _buffer)
1668{
1669	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1670	RawSocket* raw = protocol->raw;
1671	if (raw == NULL)
1672		return B_ERROR;
1673
1674	TRACE_SK(protocol, "ReadData(%lu, 0x%" B_PRIx32 ")", numBytes, flags);
1675
1676	return raw->Dequeue(flags, _buffer);
1677}
1678
1679
1680ssize_t
1681ipv4_read_avail(net_protocol* _protocol)
1682{
1683	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1684	RawSocket* raw = protocol->raw;
1685	if (raw == NULL)
1686		return B_ERROR;
1687
1688	return raw->AvailableData();
1689}
1690
1691
1692struct net_domain*
1693ipv4_get_domain(net_protocol* protocol)
1694{
1695	return sDomain;
1696}
1697
1698
1699size_t
1700ipv4_get_mtu(net_protocol* protocol, const struct sockaddr* address)
1701{
1702	net_route* route = sDatalinkModule->get_route(sDomain, address);
1703	if (route == NULL)
1704		return 0;
1705
1706	size_t mtu;
1707	if (route->mtu != 0)
1708		mtu = route->mtu;
1709	else
1710		mtu = route->interface_address->interface->device->mtu;
1711
1712	sDatalinkModule->put_route(sDomain, route);
1713
1714	if (mtu > 0xffff)
1715		mtu = 0xffff;
1716
1717	return mtu - sizeof(ipv4_header);
1718}
1719
1720
1721status_t
1722ipv4_receive_data(net_buffer* buffer)
1723{
1724	TRACE("ipv4_receive_data(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
1725
1726	uint16 headerLength = 0;
1727	{
1728	NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
1729	if (bufferHeader.Status() != B_OK)
1730		return bufferHeader.Status();
1731
1732	ipv4_header& header = bufferHeader.Data();
1733	TRACE_ONLY(dump_ipv4_header(header));
1734
1735	if (header.version != IPV4_VERSION)
1736		return B_BAD_TYPE;
1737
1738	uint16 packetLength = header.TotalLength();
1739	headerLength = header.HeaderLength();
1740	if (packetLength > buffer->size
1741		|| headerLength < sizeof(ipv4_header))
1742		return B_BAD_DATA;
1743
1744	// TODO: would be nice to have a direct checksum function somewhere
1745	if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
1746		return B_BAD_DATA;
1747
1748	// lower layers notion of broadcast or multicast have no relevance to us
1749	// other than deciding whether to send an ICMP error
1750	bool wasMulticast = (buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0;
1751	bool notForUs = false;
1752	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
1753
1754	sockaddr_in destination;
1755	fill_sockaddr_in(&destination, header.destination);
1756
1757	if (header.destination == INADDR_BROADCAST) {
1758		buffer->flags |= MSG_BCAST;
1759
1760		// Find first interface with a matching family
1761		if (!sDatalinkModule->is_local_link_address(sDomain, true,
1762				buffer->destination, &buffer->interface_address))
1763			notForUs = !wasMulticast;
1764	} else if (IN_MULTICAST(ntohl(header.destination))) {
1765		buffer->flags |= MSG_MCAST;
1766	} else {
1767		uint32 matchedAddressType = 0;
1768
1769		// test if the packet is really for us
1770		if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
1771				&buffer->interface_address, &matchedAddressType)
1772			&& !sDatalinkModule->is_local_link_address(sDomain, true,
1773				buffer->destination, &buffer->interface_address)) {
1774			// if the buffer was a link layer multicast, regard it as a
1775			// broadcast, and let the upper levels decide what to do with it
1776			if (wasMulticast)
1777				buffer->flags |= MSG_BCAST;
1778			else
1779				notForUs = true;
1780		} else {
1781			// copy over special address types (MSG_BCAST or MSG_MCAST):
1782			buffer->flags |= matchedAddressType;
1783		}
1784	}
1785
1786	// set net_buffer's source/destination address
1787	fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
1788	memcpy(buffer->destination, &destination, sizeof(sockaddr_in));
1789
1790	buffer->protocol = header.protocol;
1791
1792	if (notForUs) {
1793		TRACE("  ipv4_receive_data(): packet was not for us %x -> %x",
1794			ntohl(header.source), ntohl(header.destination));
1795
1796		if (!wasMulticast) {
1797			// Send ICMP error: Host unreachable
1798			sDomain->module->error_reply(NULL, buffer, B_NET_ERROR_UNREACH_HOST,
1799				NULL);
1800		}
1801
1802		return B_ERROR;
1803	}
1804
1805	// remove any trailing/padding data
1806	status_t status = gBufferModule->trim(buffer, packetLength);
1807	if (status != B_OK)
1808		return status;
1809
1810	// check for fragmentation
1811	uint16 fragmentOffset = header.FragmentOffset();
1812	if ((fragmentOffset & IP_MORE_FRAGMENTS) != 0
1813		|| (fragmentOffset & IP_FRAGMENT_OFFSET_MASK) != 0) {
1814		// this is a fragment
1815		TRACE("  ipv4_receive_data(): Found a Fragment!");
1816		status = reassemble_fragments(header, &buffer);
1817		TRACE("  ipv4_receive_data():  -> %s", strerror(status));
1818		if (status != B_OK)
1819			return status;
1820
1821		if (buffer == NULL) {
1822			// buffer was put into fragment packet
1823			TRACE("  ipv4_receive_data(): Not yet assembled.");
1824			return B_OK;
1825		}
1826	}
1827
1828	// Since the buffer might have been changed (reassembled fragment)
1829	// we must no longer access bufferHeader or header anymore after
1830	// this point
1831	}
1832
1833	bool rawDelivered = raw_receive_data(buffer);
1834
1835	// Preserve the ipv4 header for ICMP processing
1836	gBufferModule->store_header(buffer);
1837	gBufferModule->remove_header(buffer, headerLength);
1838		// the header is of variable size and may include IP options
1839		// (TODO: that we ignore for now)
1840
1841	net_protocol_module_info* module = receiving_protocol(buffer->protocol);
1842	if (module == NULL) {
1843		// no handler for this packet
1844		if (!rawDelivered) {
1845			sDomain->module->error_reply(NULL, buffer,
1846				B_NET_ERROR_UNREACH_PROTOCOL, NULL);
1847		}
1848		return EAFNOSUPPORT;
1849	}
1850
1851	if ((buffer->flags & MSG_MCAST) != 0) {
1852		// Unfortunately historical reasons dictate that the IP multicast
1853		// model be a little different from the unicast one. We deliver
1854		// this frame directly to all sockets registered with interest
1855		// for this multicast group.
1856		deliver_multicast(module, buffer, false);
1857		gBufferModule->free(buffer);
1858		return B_OK;
1859	}
1860
1861	return module->receive_data(buffer);
1862}
1863
1864
1865status_t
1866ipv4_deliver_data(net_protocol* _protocol, net_buffer* buffer)
1867{
1868	ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1869
1870	if (protocol->raw == NULL)
1871		return B_ERROR;
1872
1873	return protocol->raw->EnqueueClone(buffer);
1874}
1875
1876
1877status_t
1878ipv4_error_received(net_error error, net_buffer* buffer)
1879{
1880	TRACE("  ipv4_error_received(error %d, buffer %p [%" B_PRIu32 " bytes])",
1881		(int)error, buffer, buffer->size);
1882
1883	NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
1884	if (bufferHeader.Status() != B_OK)
1885		return bufferHeader.Status();
1886
1887	ipv4_header& header = bufferHeader.Data();
1888	TRACE_ONLY(dump_ipv4_header(header));
1889
1890	// We do not check the packet length, as we usually only get a part of it
1891	uint16 headerLength = header.HeaderLength();
1892	if (header.version != IPV4_VERSION
1893		|| headerLength < sizeof(ipv4_header)
1894		|| gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
1895		return B_BAD_DATA;
1896
1897	// Restore addresses of the original buffer
1898
1899	// lower layers notion of broadcast or multicast have no relevance to us
1900	// TODO: they actually have when deciding whether to send an ICMP error
1901	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
1902
1903	fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
1904	fill_sockaddr_in((struct sockaddr_in*)buffer->destination,
1905		header.destination);
1906
1907	if (header.destination == INADDR_BROADCAST)
1908		buffer->flags |= MSG_BCAST;
1909	else if (IN_MULTICAST(ntohl(header.destination)))
1910		buffer->flags |= MSG_MCAST;
1911
1912	// test if the packet is really from us
1913	if (!sDatalinkModule->is_local_address(sDomain, buffer->source, NULL,
1914			NULL)) {
1915		TRACE("  ipv4_error_received(): packet was not for us %x -> %x",
1916			ntohl(header.source), ntohl(header.destination));
1917		return B_ERROR;
1918	}
1919
1920	buffer->protocol = header.protocol;
1921
1922	bufferHeader.Remove(headerLength);
1923
1924	net_protocol_module_info* protocol = receiving_protocol(buffer->protocol);
1925	if (protocol == NULL)
1926		return B_ERROR;
1927
1928	// propagate error
1929	return protocol->error_received(error, buffer);
1930}
1931
1932
1933status_t
1934ipv4_error_reply(net_protocol* protocol, net_buffer* cause, net_error error,
1935	net_error_data* errorData)
1936{
1937	// Directly obtain the ICMP protocol module
1938	net_protocol_module_info* icmp = receiving_protocol(IPPROTO_ICMP);
1939	if (icmp == NULL)
1940		return B_ERROR;
1941
1942	return icmp->error_reply(protocol, cause, error, errorData);
1943}
1944
1945
1946ssize_t
1947ipv4_process_ancillary_data_no_container(net_protocol* protocol,
1948	net_buffer* buffer, void* msgControl, size_t msgControlLen)
1949{
1950	ssize_t bytesWritten = 0;
1951
1952	if ((((ipv4_protocol*)protocol)->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0) {
1953		if (msgControlLen < CMSG_SPACE(sizeof(struct in_addr)))
1954			return B_NO_MEMORY;
1955
1956		cmsghdr* messageHeader = (cmsghdr*)msgControl;
1957		messageHeader->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
1958		messageHeader->cmsg_level = IPPROTO_IP;
1959		messageHeader->cmsg_type = IP_RECVDSTADDR;
1960
1961		memcpy(CMSG_DATA(messageHeader),
1962		 	&((struct sockaddr_in*)buffer->destination)->sin_addr,
1963		 	sizeof(struct in_addr));
1964
1965		bytesWritten += CMSG_SPACE(sizeof(struct in_addr));
1966	}
1967
1968	return bytesWritten;
1969}
1970
1971
1972//	#pragma mark -
1973
1974
1975status_t
1976init_ipv4()
1977{
1978	sPacketID = (int32)system_time();
1979
1980	mutex_init(&sRawSocketsLock, "raw sockets");
1981	mutex_init(&sFragmentLock, "IPv4 Fragments");
1982	mutex_init(&sMulticastGroupsLock, "IPv4 multicast groups");
1983	mutex_init(&sReceivingProtocolLock, "IPv4 receiving protocols");
1984
1985	status_t status;
1986
1987	sMulticastState = new MulticastState();
1988	if (sMulticastState == NULL) {
1989		status = B_NO_MEMORY;
1990		goto err4;
1991	}
1992
1993	status = sMulticastState->Init();
1994	if (status != B_OK)
1995		goto err5;
1996
1997	new (&sFragmentHash) FragmentTable();
1998	status = sFragmentHash.Init(256);
1999	if (status != B_OK)
2000		goto err5;
2001
2002	new (&sRawSockets) RawSocketList;
2003		// static initializers do not work in the kernel,
2004		// so we have to do it here, manually
2005		// TODO: for modules, this shouldn't be required
2006
2007	status = gStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0,
2008		"network/protocols/ipv4/v1", NULL);
2009	if (status != B_OK)
2010		goto err6;
2011
2012	status = gStackModule->register_domain(AF_INET, "internet", &gIPv4Module,
2013		&gIPv4AddressModule, &sDomain);
2014	if (status != B_OK)
2015		goto err6;
2016
2017	add_debugger_command("ipv4_multicast", dump_ipv4_multicast,
2018		"list all current IPv4 multicast states");
2019
2020	return B_OK;
2021
2022err6:
2023	sFragmentHash.~FragmentTable();
2024err5:
2025	delete sMulticastState;
2026err4:
2027	mutex_destroy(&sReceivingProtocolLock);
2028	mutex_destroy(&sMulticastGroupsLock);
2029	mutex_destroy(&sFragmentLock);
2030	mutex_destroy(&sRawSocketsLock);
2031	return status;
2032}
2033
2034
2035status_t
2036uninit_ipv4()
2037{
2038	mutex_lock(&sReceivingProtocolLock);
2039
2040	remove_debugger_command("ipv4_multicast", dump_ipv4_multicast);
2041
2042	// put all the domain receiving protocols we gathered so far
2043	for (uint32 i = 0; i < 256; i++) {
2044		if (sReceivingProtocol[i] != NULL)
2045			gStackModule->put_domain_receiving_protocol(sDomain, i);
2046	}
2047
2048	gStackModule->unregister_domain(sDomain);
2049	mutex_unlock(&sReceivingProtocolLock);
2050
2051	delete sMulticastState;
2052	sFragmentHash.~FragmentTable();
2053
2054	mutex_destroy(&sMulticastGroupsLock);
2055	mutex_destroy(&sFragmentLock);
2056	mutex_destroy(&sRawSocketsLock);
2057	mutex_destroy(&sReceivingProtocolLock);
2058
2059	return B_OK;
2060}
2061
2062
2063static status_t
2064ipv4_std_ops(int32 op, ...)
2065{
2066	switch (op) {
2067		case B_MODULE_INIT:
2068			return init_ipv4();
2069		case B_MODULE_UNINIT:
2070			return uninit_ipv4();
2071
2072		default:
2073			return B_ERROR;
2074	}
2075}
2076
2077
2078net_protocol_module_info gIPv4Module = {
2079	{
2080		"network/protocols/ipv4/v1",
2081		0,
2082		ipv4_std_ops
2083	},
2084	NET_PROTOCOL_ATOMIC_MESSAGES,
2085
2086	ipv4_init_protocol,
2087	ipv4_uninit_protocol,
2088	ipv4_open,
2089	ipv4_close,
2090	ipv4_free,
2091	ipv4_connect,
2092	ipv4_accept,
2093	ipv4_control,
2094	ipv4_getsockopt,
2095	ipv4_setsockopt,
2096	ipv4_bind,
2097	ipv4_unbind,
2098	ipv4_listen,
2099	ipv4_shutdown,
2100	ipv4_send_data,
2101	ipv4_send_routed_data,
2102	ipv4_send_avail,
2103	ipv4_read_data,
2104	ipv4_read_avail,
2105	ipv4_get_domain,
2106	ipv4_get_mtu,
2107	ipv4_receive_data,
2108	ipv4_deliver_data,
2109	ipv4_error_received,
2110	ipv4_error_reply,
2111	NULL,		// add_ancillary_data()
2112	NULL,		// process_ancillary_data()
2113	ipv4_process_ancillary_data_no_container,
2114	NULL,		// send_data_no_buffer()
2115	NULL		// read_data_no_buffer()
2116};
2117
2118module_dependency module_dependencies[] = {
2119	{NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
2120	{NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
2121	{NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule},
2122	{NET_SOCKET_MODULE_NAME, (module_info**)&sSocketModule},
2123	{}
2124};
2125
2126module_info* modules[] = {
2127	(module_info*)&gIPv4Module,
2128	NULL
2129};
2130