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
59 typedef DoublyLinkedList<struct net_buffer,
60 DoublyLinkedListCLink<struct net_buffer> > FragmentList;
61
62 typedef NetBufferField<uint16, offsetof(ipv4_header, checksum)> IPChecksumField;
63
64 struct ipv4_packet_key {
65 in_addr_t source;
66 in_addr_t destination;
67 uint16 id;
68 uint8 protocol;
69 };
70
71
72 class FragmentPacket {
73 public:
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
IsComplete() const81 bool IsComplete() const
82 { return fReceivedLastFragment
83 && fBytesLeft == 0; }
84
Key() const85 const ipv4_packet_key& Key() const { return fKey; }
HashTableLink()86 FragmentPacket*& HashTableLink() { return fNext; }
87
88 static void StaleTimer(struct net_timer* timer, void* data);
89
90 private:
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
101 struct FragmentHashDefinition {
102 typedef ipv4_packet_key KeyType;
103 typedef FragmentPacket ValueType;
104
HashKeyFragmentHashDefinition105 size_t HashKey(const KeyType& key) const
106 {
107 return (key.source ^ key.destination ^ key.protocol ^ key.id);
108 }
109
HashFragmentHashDefinition110 size_t Hash(ValueType* value) const
111 {
112 return HashKey(value->Key());
113 }
114
CompareFragmentHashDefinition115 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
GetLinkFragmentHashDefinition125 ValueType*& GetLink(ValueType* value) const
126 {
127 return value->HashTableLink();
128 }
129 };
130
131 typedef BOpenHashTable<FragmentHashDefinition, false, true> FragmentTable;
132
133
134 class RawSocket
135 : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
136 public:
137 RawSocket(net_socket* socket);
138 };
139
140 typedef DoublyLinkedList<RawSocket> RawSocketList;
141
142 typedef MulticastGroupInterface<IPv4Multicast> IPv4GroupInterface;
143 typedef MulticastFilter<IPv4Multicast> IPv4MulticastFilter;
144
145 struct MulticastStateHash {
146 typedef std::pair<const in_addr* , uint32> KeyType;
147 typedef IPv4GroupInterface ValueType;
148
HashKeyMulticastStateHash149 size_t HashKey(const KeyType &key) const
150 { return key.first->s_addr ^ key.second; }
HashMulticastStateHash151 size_t Hash(ValueType* value) const
152 { return HashKey(std::make_pair(&value->Address(),
153 value->Interface()->index)); }
CompareMulticastStateHash154 bool Compare(const KeyType &key, ValueType* value) const
155 { return value->Interface()->index == key.second
156 && value->Address().s_addr == key.first->s_addr; }
CompareValuesMulticastStateHash157 bool CompareValues(ValueType* value1, ValueType* value2) const
158 { return value1->Interface()->index == value2->Interface()->index
159 && value1->Address().s_addr == value2->Address().s_addr; }
GetLinkMulticastStateHash160 ValueType*& GetLink(ValueType* value) const { return value->MulticastGroupsHashLink(); }
161 };
162
163
164 struct ipv4_protocol : net_protocol {
ipv4_protocolipv4_protocol165 ipv4_protocol()
166 :
167 raw(NULL),
168 multicast_filter(this)
169 {
170 }
171
~ipv4_protocolipv4_protocol172 ~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
193 static const int kDefaultTTL = 254;
194 static const int kDefaultMulticastTTL = 1;
195 static const bool kDefaultMulticastLoopback = true;
196
197
198 extern net_protocol_module_info gIPv4Module;
199 // we need this in ipv4_std_ops() for registering the AF_INET domain
200
201 net_stack_module_info* gStackModule;
202 net_buffer_module_info* gBufferModule;
203
204 static struct net_domain* sDomain;
205 static net_datalink_module_info* sDatalinkModule;
206 static net_socket_module_info* sSocketModule;
207 static int32 sPacketID;
208 static RawSocketList sRawSockets;
209 static mutex sRawSocketsLock;
210 static mutex sFragmentLock;
211 static FragmentTable sFragmentHash;
212 static mutex sMulticastGroupsLock;
213
214 typedef MultiHashTable<MulticastStateHash> MulticastState;
215 static MulticastState* sMulticastState;
216
217 static net_protocol_module_info* sReceivingProtocol[256];
218 static mutex sReceivingProtocolLock;
219
220
221 static const char*
print_address(const in_addr * address,char * buf,size_t bufLen)222 print_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
RawSocket(net_socket * socket)233 RawSocket::RawSocket(net_socket* socket)
234 :
235 DatagramSocket<>("ipv4 raw socket", socket)
236 {
237 }
238
239
240 // #pragma mark -
241
242
FragmentPacket(const ipv4_packet_key & key)243 FragmentPacket::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
~FragmentPacket()254 FragmentPacket::~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
267 status_t
AddFragment(uint16 start,uint16 end,net_buffer * buffer,bool lastFragment)268 FragmentPacket::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 */
406 status_t
Reassemble(net_buffer * to)407 FragmentPacket::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
StaleTimer(struct net_timer * timer,void * data)440 FragmentPacket::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
463 static void
dump_ipv4_header(ipv4_header & header)464 dump_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
500 static int
dump_ipv4_multicast(int argc,char ** argv)501 dump_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 */
538 static status_t
reassemble_fragments(const ipv4_header & header,net_buffer ** _buffer)539 reassemble_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 */
605 static status_t
send_fragments(ipv4_protocol * protocol,struct net_route * route,net_buffer * buffer,uint32 mtu)606 send_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
688 status_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 */
694 static bool
deliver_multicast(net_protocol_module_info * module,net_buffer * buffer,bool deliverToRaw)695 deliver_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 */
750 static bool
raw_receive_data(net_buffer * buffer)751 raw_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->msg_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
785 static inline sockaddr*
fill_sockaddr_in(sockaddr_in * target,in_addr_t address)786 fill_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
796 static status_t
get_int_option(void * target,size_t length,int value)797 get_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
806 static status_t
get_char_int_option(void * target,size_t length,int value)807 get_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
819 template<typename Type> static status_t
set_int_option(Type & target,const void * _value,size_t length)820 set_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
835 template<typename Type> static status_t
set_char_int_option(Type & target,const void * _value,size_t length)836 set_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
859 static net_protocol_module_info*
receiving_protocol(uint8 protocol)860 receiving_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
883 status_t
JoinGroup(IPv4GroupInterface * state)884 IPv4Multicast::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
899 status_t
LeaveGroup(IPv4GroupInterface * state)900 IPv4Multicast::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
912 static status_t
ipv4_delta_group(IPv4GroupInterface * group,int option,net_interface * interface,const in_addr * sourceAddr)913 ipv4_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
935 static status_t
ipv4_delta_membership(ipv4_protocol * protocol,int option,net_interface * interface,const in_addr * groupAddr,const in_addr * sourceAddr)936 ipv4_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
974 static int
generic_to_ipv4(int option)975 generic_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
996 static net_interface*
get_multicast_interface(ipv4_protocol * protocol,const in_addr * address)997 get_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
1010 static status_t
ipv4_delta_membership(ipv4_protocol * protocol,int option,in_addr * interfaceAddr,in_addr * groupAddr,in_addr * sourceAddr)1011 ipv4_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
1032 static status_t
ipv4_generic_delta_membership(ipv4_protocol * protocol,int option,uint32 index,const sockaddr_storage * _groupAddr,const sockaddr_storage * _sourceAddr)1033 ipv4_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
1065 net_protocol*
ipv4_init_protocol(net_socket * socket)1066 ipv4_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
1083 status_t
ipv4_uninit_protocol(net_protocol * _protocol)1084 ipv4_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 */
1097 status_t
ipv4_open(net_protocol * _protocol)1098 ipv4_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
1126 status_t
ipv4_close(net_protocol * _protocol)1127 ipv4_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
1145 status_t
ipv4_free(net_protocol * protocol)1146 ipv4_free(net_protocol* protocol)
1147 {
1148 return B_OK;
1149 }
1150
1151
1152 status_t
ipv4_connect(net_protocol * _protocol,const struct sockaddr * address)1153 ipv4_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
1171 status_t
ipv4_accept(net_protocol * protocol,struct net_socket ** _acceptedSocket)1172 ipv4_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
1173 {
1174 return B_NOT_SUPPORTED;
1175 }
1176
1177
1178 status_t
ipv4_control(net_protocol * _protocol,int level,int option,void * value,size_t * _length)1179 ipv4_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
1189 status_t
ipv4_getsockopt(net_protocol * _protocol,int level,int option,void * value,int * _length)1190 ipv4_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
1266 status_t
ipv4_setsockopt(net_protocol * _protocol,int level,int option,const void * value,int length)1267 ipv4_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
1429 status_t
ipv4_bind(net_protocol * protocol,const struct sockaddr * address)1430 ipv4_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
1451 status_t
ipv4_unbind(net_protocol * protocol,struct sockaddr * address)1452 ipv4_unbind(net_protocol* protocol, struct sockaddr* address)
1453 {
1454 // nothing to do here
1455 return B_OK;
1456 }
1457
1458
1459 status_t
ipv4_listen(net_protocol * protocol,int count)1460 ipv4_listen(net_protocol* protocol, int count)
1461 {
1462 return B_NOT_SUPPORTED;
1463 }
1464
1465
1466 status_t
ipv4_shutdown(net_protocol * protocol,int direction)1467 ipv4_shutdown(net_protocol* protocol, int direction)
1468 {
1469 return B_NOT_SUPPORTED;
1470 }
1471
1472
1473 status_t
ipv4_send_routed_data(net_protocol * _protocol,struct net_route * route,net_buffer * buffer)1474 ipv4_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->msg_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->msg_flags |= MSG_BCAST;
1508 } else if (IN_MULTICAST(ntohl(destination.sin_addr.s_addr)))
1509 buffer->msg_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->msg_flags & MSG_MCAST) != 0
1526 ? protocol->multicast_time_to_live : protocol->time_to_live;
1527 } else {
1528 header->time_to_live = (buffer->msg_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 buffer->buffer_flags |= NET_BUFFER_L3_CHECKSUM_VALID;
1563 }
1564
1565 if ((buffer->msg_flags & MSG_MCAST) != 0
1566 && (protocol != NULL && protocol->multicast_loopback)) {
1567 // copy an IP multicast packet to the input queue of the loopback
1568 // interface
1569 net_buffer *loopbackBuffer = gBufferModule->duplicate(buffer);
1570 if (loopbackBuffer == NULL)
1571 return B_NO_MEMORY;
1572 status_t status = B_ERROR;
1573
1574 // get the IPv4 loopback address
1575 struct sockaddr loopbackAddress;
1576 gIPv4AddressModule.get_loopback_address(&loopbackAddress);
1577
1578 // get the matching interface address if any
1579 net_interface_address* address =
1580 sDatalinkModule->get_interface_address(&loopbackAddress);
1581 if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
1582 sDatalinkModule->put_interface_address(address);
1583 } else {
1584 sDatalinkModule->put_interface_address(
1585 loopbackBuffer->interface_address);
1586 loopbackBuffer->interface_address = address;
1587 status = ipv4_receive_data(loopbackBuffer);
1588 }
1589
1590 if (status != B_OK)
1591 gBufferModule->free(loopbackBuffer);
1592 }
1593
1594 TRACE_SK(protocol, " SendRoutedData(): header chksum: %" B_PRIu32
1595 ", buffer checksum: %" B_PRIu32,
1596 gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true),
1597 gBufferModule->checksum(buffer, 0, buffer->size, true));
1598
1599 TRACE_SK(protocol, " SendRoutedData(): destination: %08x",
1600 ntohl(destination.sin_addr.s_addr));
1601
1602 uint32 mtu = route->mtu ? route->mtu : interface->device->mtu;
1603 if (buffer->size > mtu) {
1604 // we need to fragment the packet
1605 return send_fragments(protocol, route, buffer, mtu);
1606 }
1607
1608 return sDatalinkModule->send_routed_data(route, buffer);
1609 }
1610
1611
1612 status_t
ipv4_send_data(net_protocol * _protocol,net_buffer * buffer)1613 ipv4_send_data(net_protocol* _protocol, net_buffer* buffer)
1614 {
1615 ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1616
1617 TRACE_SK(protocol, "SendData(%p [%" B_PRIu32 " bytes])", buffer,
1618 buffer->size);
1619
1620 if (protocol != NULL && (protocol->flags & IP_FLAG_HEADER_INCLUDED)) {
1621 if (buffer->size < sizeof(ipv4_header))
1622 return B_BAD_VALUE;
1623
1624 sockaddr_in* source = (sockaddr_in*)buffer->source;
1625 sockaddr_in* destination = (sockaddr_in*)buffer->destination;
1626
1627 fill_sockaddr_in(source, *NetBufferField<in_addr_t,
1628 offsetof(ipv4_header, source)>(buffer));
1629 fill_sockaddr_in(destination, *NetBufferField<in_addr_t,
1630 offsetof(ipv4_header, destination)>(buffer));
1631 }
1632
1633 // handle IP_MULTICAST_IF
1634 if (IN_MULTICAST(ntohl(
1635 ((sockaddr_in*)buffer->destination)->sin_addr.s_addr))
1636 && protocol != NULL && protocol->multicast_address != NULL) {
1637 net_interface_address* address = sDatalinkModule->get_interface_address(
1638 protocol->multicast_address);
1639 if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
1640 sDatalinkModule->put_interface_address(address);
1641 return EADDRNOTAVAIL;
1642 }
1643
1644 sDatalinkModule->put_interface_address(buffer->interface_address);
1645 buffer->interface_address = address;
1646 // the buffer takes over ownership of the address
1647
1648 net_route* route = sDatalinkModule->get_route(sDomain, address->local);
1649 if (route == NULL)
1650 return ENETUNREACH;
1651
1652 return sDatalinkModule->send_routed_data(route, buffer);
1653 }
1654
1655 return sDatalinkModule->send_data(protocol, sDomain, buffer);
1656 }
1657
1658
1659 ssize_t
ipv4_send_avail(net_protocol * protocol)1660 ipv4_send_avail(net_protocol* protocol)
1661 {
1662 return B_ERROR;
1663 }
1664
1665
1666 status_t
ipv4_read_data(net_protocol * _protocol,size_t numBytes,uint32 flags,net_buffer ** _buffer)1667 ipv4_read_data(net_protocol* _protocol, size_t numBytes, uint32 flags,
1668 net_buffer** _buffer)
1669 {
1670 ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1671 RawSocket* raw = protocol->raw;
1672 if (raw == NULL)
1673 return B_ERROR;
1674
1675 TRACE_SK(protocol, "ReadData(%lu, 0x%" B_PRIx32 ")", numBytes, flags);
1676
1677 return raw->Dequeue(flags, _buffer);
1678 }
1679
1680
1681 ssize_t
ipv4_read_avail(net_protocol * _protocol)1682 ipv4_read_avail(net_protocol* _protocol)
1683 {
1684 ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1685 RawSocket* raw = protocol->raw;
1686 if (raw == NULL)
1687 return B_ERROR;
1688
1689 return raw->AvailableData();
1690 }
1691
1692
1693 struct net_domain*
ipv4_get_domain(net_protocol * protocol)1694 ipv4_get_domain(net_protocol* protocol)
1695 {
1696 return sDomain;
1697 }
1698
1699
1700 size_t
ipv4_get_mtu(net_protocol * protocol,const struct sockaddr * address)1701 ipv4_get_mtu(net_protocol* protocol, const struct sockaddr* address)
1702 {
1703 net_route* route = sDatalinkModule->get_route(sDomain, address);
1704 if (route == NULL)
1705 return 0;
1706
1707 size_t mtu;
1708 if (route->mtu != 0)
1709 mtu = route->mtu;
1710 else
1711 mtu = route->interface_address->interface->device->mtu;
1712
1713 sDatalinkModule->put_route(sDomain, route);
1714
1715 if (mtu > 0xffff)
1716 mtu = 0xffff;
1717
1718 return mtu - sizeof(ipv4_header);
1719 }
1720
1721
1722 status_t
ipv4_receive_data(net_buffer * buffer)1723 ipv4_receive_data(net_buffer* buffer)
1724 {
1725 TRACE("ipv4_receive_data(%p [%" B_PRIu32 " bytes])", buffer, buffer->size);
1726
1727 uint16 headerLength = 0;
1728 {
1729 NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
1730 if (bufferHeader.Status() != B_OK)
1731 return bufferHeader.Status();
1732
1733 ipv4_header& header = bufferHeader.Data();
1734 TRACE_ONLY(dump_ipv4_header(header));
1735
1736 if (header.version != IPV4_VERSION)
1737 return B_BAD_TYPE;
1738
1739 uint16 packetLength = header.TotalLength();
1740 headerLength = header.HeaderLength();
1741 if (packetLength > buffer->size
1742 || headerLength < sizeof(ipv4_header))
1743 return B_BAD_DATA;
1744
1745 if ((buffer->buffer_flags & NET_BUFFER_L3_CHECKSUM_VALID) == 0) {
1746 if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
1747 return B_BAD_DATA;
1748 }
1749
1750 // lower layers notion of broadcast or multicast have no relevance to us
1751 // other than deciding whether to send an ICMP error
1752 bool wasMulticast = (buffer->msg_flags & (MSG_BCAST | MSG_MCAST)) != 0;
1753 bool notForUs = false;
1754 buffer->msg_flags &= ~(MSG_BCAST | MSG_MCAST);
1755
1756 sockaddr_in destination;
1757 fill_sockaddr_in(&destination, header.destination);
1758
1759 if (header.destination == INADDR_BROADCAST) {
1760 buffer->msg_flags |= MSG_BCAST;
1761
1762 // Find first interface with a matching family
1763 if (!sDatalinkModule->is_local_link_address(sDomain, true,
1764 buffer->destination, &buffer->interface_address))
1765 notForUs = !wasMulticast;
1766 } else if (IN_MULTICAST(ntohl(header.destination))) {
1767 buffer->msg_flags |= MSG_MCAST;
1768 } else {
1769 uint32 matchedAddressType = 0;
1770
1771 // test if the packet is really for us
1772 if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
1773 &buffer->interface_address, &matchedAddressType)
1774 && !sDatalinkModule->is_local_link_address(sDomain, true,
1775 buffer->destination, &buffer->interface_address)) {
1776 // if the buffer was a link layer multicast, regard it as a
1777 // broadcast, and let the upper levels decide what to do with it
1778 if (wasMulticast)
1779 buffer->msg_flags |= MSG_BCAST;
1780 else
1781 notForUs = true;
1782 } else {
1783 // copy over special address types (MSG_BCAST or MSG_MCAST):
1784 buffer->msg_flags |= matchedAddressType;
1785 }
1786 }
1787
1788 // set net_buffer's source/destination address
1789 fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
1790 memcpy(buffer->destination, &destination, sizeof(sockaddr_in));
1791
1792 buffer->protocol = header.protocol;
1793
1794 if (notForUs) {
1795 TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
1796 ntohl(header.source), ntohl(header.destination));
1797
1798 if (!wasMulticast) {
1799 // Send ICMP error: Host unreachable
1800 sDomain->module->error_reply(NULL, buffer, B_NET_ERROR_UNREACH_HOST,
1801 NULL);
1802 }
1803
1804 return B_ERROR;
1805 }
1806
1807 // remove any trailing/padding data
1808 status_t status = gBufferModule->trim(buffer, packetLength);
1809 if (status != B_OK)
1810 return status;
1811
1812 // check for fragmentation
1813 uint16 fragmentOffset = header.FragmentOffset();
1814 if ((fragmentOffset & IP_MORE_FRAGMENTS) != 0
1815 || (fragmentOffset & IP_FRAGMENT_OFFSET_MASK) != 0) {
1816 // this is a fragment
1817 TRACE(" ipv4_receive_data(): Found a Fragment!");
1818 status = reassemble_fragments(header, &buffer);
1819 TRACE(" ipv4_receive_data(): -> %s", strerror(status));
1820 if (status != B_OK)
1821 return status;
1822
1823 if (buffer == NULL) {
1824 // buffer was put into fragment packet
1825 TRACE(" ipv4_receive_data(): Not yet assembled.");
1826 return B_OK;
1827 }
1828 }
1829
1830 // Since the buffer might have been changed (reassembled fragment)
1831 // we must no longer access bufferHeader or header anymore after
1832 // this point
1833 }
1834
1835 bool rawDelivered = raw_receive_data(buffer);
1836
1837 // Preserve the ipv4 header for ICMP processing
1838 gBufferModule->store_header(buffer);
1839 gBufferModule->remove_header(buffer, headerLength);
1840 // the header is of variable size and may include IP options
1841 // (TODO: that we ignore for now)
1842
1843 net_protocol_module_info* module = receiving_protocol(buffer->protocol);
1844 if (module == NULL) {
1845 // no handler for this packet
1846 if (!rawDelivered) {
1847 sDomain->module->error_reply(NULL, buffer,
1848 B_NET_ERROR_UNREACH_PROTOCOL, NULL);
1849 }
1850 return EAFNOSUPPORT;
1851 }
1852
1853 if ((buffer->msg_flags & MSG_MCAST) != 0) {
1854 // Unfortunately historical reasons dictate that the IP multicast
1855 // model be a little different from the unicast one. We deliver
1856 // this frame directly to all sockets registered with interest
1857 // for this multicast group.
1858 deliver_multicast(module, buffer, false);
1859 gBufferModule->free(buffer);
1860 return B_OK;
1861 }
1862
1863 return module->receive_data(buffer);
1864 }
1865
1866
1867 status_t
ipv4_deliver_data(net_protocol * _protocol,net_buffer * buffer)1868 ipv4_deliver_data(net_protocol* _protocol, net_buffer* buffer)
1869 {
1870 ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
1871
1872 if (protocol->raw == NULL)
1873 return B_ERROR;
1874
1875 return protocol->raw->EnqueueClone(buffer);
1876 }
1877
1878
1879 status_t
ipv4_error_received(net_error error,net_buffer * buffer)1880 ipv4_error_received(net_error error, net_buffer* buffer)
1881 {
1882 TRACE(" ipv4_error_received(error %d, buffer %p [%" B_PRIu32 " bytes])",
1883 (int)error, buffer, buffer->size);
1884
1885 NetBufferHeaderReader<ipv4_header> bufferHeader(buffer);
1886 if (bufferHeader.Status() != B_OK)
1887 return bufferHeader.Status();
1888
1889 ipv4_header& header = bufferHeader.Data();
1890 TRACE_ONLY(dump_ipv4_header(header));
1891
1892 // We do not check the packet length, as we usually only get a part of it
1893 uint16 headerLength = header.HeaderLength();
1894 if (header.version != IPV4_VERSION
1895 || headerLength < sizeof(ipv4_header)
1896 || gBufferModule->checksum(buffer, 0, headerLength, true) != 0)
1897 return B_BAD_DATA;
1898
1899 // Restore addresses of the original buffer
1900
1901 // lower layers notion of broadcast or multicast have no relevance to us
1902 // TODO: they actually have when deciding whether to send an ICMP error
1903 buffer->msg_flags &= ~(MSG_BCAST | MSG_MCAST);
1904
1905 fill_sockaddr_in((struct sockaddr_in*)buffer->source, header.source);
1906 fill_sockaddr_in((struct sockaddr_in*)buffer->destination,
1907 header.destination);
1908
1909 if (header.destination == INADDR_BROADCAST)
1910 buffer->msg_flags |= MSG_BCAST;
1911 else if (IN_MULTICAST(ntohl(header.destination)))
1912 buffer->msg_flags |= MSG_MCAST;
1913
1914 // test if the packet is really from us
1915 if (!sDatalinkModule->is_local_address(sDomain, buffer->source, NULL,
1916 NULL)) {
1917 TRACE(" ipv4_error_received(): packet was not for us %x -> %x",
1918 ntohl(header.source), ntohl(header.destination));
1919 return B_ERROR;
1920 }
1921
1922 buffer->protocol = header.protocol;
1923
1924 bufferHeader.Remove(headerLength);
1925
1926 net_protocol_module_info* protocol = receiving_protocol(buffer->protocol);
1927 if (protocol == NULL)
1928 return B_ERROR;
1929
1930 // propagate error
1931 return protocol->error_received(error, buffer);
1932 }
1933
1934
1935 status_t
ipv4_error_reply(net_protocol * protocol,net_buffer * cause,net_error error,net_error_data * errorData)1936 ipv4_error_reply(net_protocol* protocol, net_buffer* cause, net_error error,
1937 net_error_data* errorData)
1938 {
1939 // Directly obtain the ICMP protocol module
1940 net_protocol_module_info* icmp = receiving_protocol(IPPROTO_ICMP);
1941 if (icmp == NULL)
1942 return B_ERROR;
1943
1944 return icmp->error_reply(protocol, cause, error, errorData);
1945 }
1946
1947
1948 ssize_t
ipv4_process_ancillary_data_no_container(net_protocol * protocol,net_buffer * buffer,void * msgControl,size_t msgControlLen)1949 ipv4_process_ancillary_data_no_container(net_protocol* protocol,
1950 net_buffer* buffer, void* msgControl, size_t msgControlLen)
1951 {
1952 ssize_t bytesWritten = 0;
1953
1954 if ((((ipv4_protocol*)protocol)->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0) {
1955 if (msgControlLen < CMSG_SPACE(sizeof(struct in_addr)))
1956 return B_NO_MEMORY;
1957
1958 cmsghdr* messageHeader = (cmsghdr*)msgControl;
1959 messageHeader->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
1960 messageHeader->cmsg_level = IPPROTO_IP;
1961 messageHeader->cmsg_type = IP_RECVDSTADDR;
1962
1963 memcpy(CMSG_DATA(messageHeader),
1964 &((struct sockaddr_in*)buffer->destination)->sin_addr,
1965 sizeof(struct in_addr));
1966
1967 bytesWritten += CMSG_SPACE(sizeof(struct in_addr));
1968 }
1969
1970 return bytesWritten;
1971 }
1972
1973
1974 // #pragma mark -
1975
1976
1977 status_t
init_ipv4()1978 init_ipv4()
1979 {
1980 sPacketID = (int32)system_time();
1981
1982 mutex_init(&sRawSocketsLock, "raw sockets");
1983 mutex_init(&sFragmentLock, "IPv4 Fragments");
1984 mutex_init(&sMulticastGroupsLock, "IPv4 multicast groups");
1985 mutex_init(&sReceivingProtocolLock, "IPv4 receiving protocols");
1986
1987 status_t status;
1988
1989 sMulticastState = new MulticastState();
1990 if (sMulticastState == NULL) {
1991 status = B_NO_MEMORY;
1992 goto err4;
1993 }
1994
1995 status = sMulticastState->Init();
1996 if (status != B_OK)
1997 goto err5;
1998
1999 new (&sFragmentHash) FragmentTable();
2000 status = sFragmentHash.Init(256);
2001 if (status != B_OK)
2002 goto err5;
2003
2004 new (&sRawSockets) RawSocketList;
2005 // static initializers do not work in the kernel,
2006 // so we have to do it here, manually
2007 // TODO: for modules, this shouldn't be required
2008
2009 status = gStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0,
2010 "network/protocols/ipv4/v1", NULL);
2011 if (status != B_OK)
2012 goto err6;
2013
2014 status = gStackModule->register_domain(AF_INET, "internet", &gIPv4Module,
2015 &gIPv4AddressModule, &sDomain);
2016 if (status != B_OK)
2017 goto err6;
2018
2019 add_debugger_command("ipv4_multicast", dump_ipv4_multicast,
2020 "list all current IPv4 multicast states");
2021
2022 return B_OK;
2023
2024 err6:
2025 sFragmentHash.~FragmentTable();
2026 err5:
2027 delete sMulticastState;
2028 err4:
2029 mutex_destroy(&sReceivingProtocolLock);
2030 mutex_destroy(&sMulticastGroupsLock);
2031 mutex_destroy(&sFragmentLock);
2032 mutex_destroy(&sRawSocketsLock);
2033 return status;
2034 }
2035
2036
2037 status_t
uninit_ipv4()2038 uninit_ipv4()
2039 {
2040 mutex_lock(&sReceivingProtocolLock);
2041
2042 remove_debugger_command("ipv4_multicast", dump_ipv4_multicast);
2043
2044 // put all the domain receiving protocols we gathered so far
2045 for (uint32 i = 0; i < 256; i++) {
2046 if (sReceivingProtocol[i] != NULL)
2047 gStackModule->put_domain_receiving_protocol(sDomain, i);
2048 }
2049
2050 gStackModule->unregister_domain(sDomain);
2051 mutex_unlock(&sReceivingProtocolLock);
2052
2053 delete sMulticastState;
2054 sFragmentHash.~FragmentTable();
2055
2056 mutex_destroy(&sMulticastGroupsLock);
2057 mutex_destroy(&sFragmentLock);
2058 mutex_destroy(&sRawSocketsLock);
2059 mutex_destroy(&sReceivingProtocolLock);
2060
2061 return B_OK;
2062 }
2063
2064
2065 static status_t
ipv4_std_ops(int32 op,...)2066 ipv4_std_ops(int32 op, ...)
2067 {
2068 switch (op) {
2069 case B_MODULE_INIT:
2070 return init_ipv4();
2071 case B_MODULE_UNINIT:
2072 return uninit_ipv4();
2073
2074 default:
2075 return B_ERROR;
2076 }
2077 }
2078
2079
2080 net_protocol_module_info gIPv4Module = {
2081 {
2082 "network/protocols/ipv4/v1",
2083 0,
2084 ipv4_std_ops
2085 },
2086 NET_PROTOCOL_ATOMIC_MESSAGES,
2087
2088 ipv4_init_protocol,
2089 ipv4_uninit_protocol,
2090 ipv4_open,
2091 ipv4_close,
2092 ipv4_free,
2093 ipv4_connect,
2094 ipv4_accept,
2095 ipv4_control,
2096 ipv4_getsockopt,
2097 ipv4_setsockopt,
2098 ipv4_bind,
2099 ipv4_unbind,
2100 ipv4_listen,
2101 ipv4_shutdown,
2102 ipv4_send_data,
2103 ipv4_send_routed_data,
2104 ipv4_send_avail,
2105 ipv4_read_data,
2106 ipv4_read_avail,
2107 ipv4_get_domain,
2108 ipv4_get_mtu,
2109 ipv4_receive_data,
2110 ipv4_deliver_data,
2111 ipv4_error_received,
2112 ipv4_error_reply,
2113 NULL, // add_ancillary_data()
2114 NULL, // process_ancillary_data()
2115 ipv4_process_ancillary_data_no_container,
2116 NULL, // send_data_no_buffer()
2117 NULL // read_data_no_buffer()
2118 };
2119
2120 module_dependency module_dependencies[] = {
2121 {NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
2122 {NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
2123 {NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule},
2124 {NET_SOCKET_MODULE_NAME, (module_info**)&sSocketModule},
2125 {}
2126 };
2127
2128 module_info* modules[] = {
2129 (module_info*)&gIPv4Module,
2130 NULL
2131 };
2132