1 /* 2 * Copyright 2006-2011, 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 * Atis Elsts, the.kfx@gmail.com 8 */ 9 10 11 #include "ipv6_address.h" 12 #include "ipv6_utils.h" 13 #include "multicast.h" 14 15 #include <net_datalink.h> 16 #include <net_datalink_protocol.h> 17 #include <net_device.h> 18 #include <net_protocol.h> 19 #include <net_stack.h> 20 #include <NetBufferUtilities.h> 21 #include <ProtocolUtilities.h> 22 23 #include <ByteOrder.h> 24 #include <KernelExport.h> 25 #include <util/AutoLock.h> 26 #include <util/list.h> 27 #include <util/khash.h> 28 #include <util/DoublyLinkedList.h> 29 #include <util/MultiHashTable.h> 30 31 #include <netinet6/in6.h> 32 #include <netinet/ip6.h> 33 #include <netinet/icmp6.h> 34 #include <new> 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <utility> 39 40 41 #define TRACE_IPV6 42 #ifdef TRACE_IPV6 43 # define TRACE(format, args...) \ 44 dprintf("IPv6 [%llu] " format "\n", system_time() , ##args) 45 # define TRACE_SK(protocol, format, args...) \ 46 dprintf("IPv6 [%llu] %p " format "\n", system_time(), \ 47 protocol , ##args) 48 #else 49 # define TRACE(args...) do { } while (0) 50 # define TRACE_SK(args...) do { } while (0) 51 #endif 52 53 54 #define MAX_HASH_FRAGMENTS 64 55 // slots in the fragment packet's hash 56 #define FRAGMENT_TIMEOUT 60000000LL 57 // discard fragment after 60 seconds [RFC 2460] 58 59 60 struct IPv6Header { 61 struct ip6_hdr header; 62 63 uint8 ProtocolVersion() const { return header.ip6_vfc & IPV6_VERSION_MASK; } 64 uint8 ServiceType() const { return ntohl(header.ip6_flow) >> 20;} 65 uint16 PayloadLength() const { return ntohs(header.ip6_plen); } 66 const in6_addr& Dst() const { return header.ip6_dst; } 67 const in6_addr& Src() const { return header.ip6_src; } 68 uint8 NextHeader() const { return header.ip6_nxt; } 69 uint16 GetHeaderOffset(net_buffer* buffer, uint32 headerCode = ~0u) const; 70 }; 71 72 73 typedef DoublyLinkedList<struct net_buffer, 74 DoublyLinkedListCLink<struct net_buffer> > FragmentList; 75 76 // TODO: make common fragmentation interface for both address families 77 struct ipv6_packet_key { 78 in6_addr source; 79 in6_addr destination; 80 // We use uint32 here due to the hash function 81 uint32 id; 82 uint32 protocol; 83 }; 84 85 class FragmentPacket { 86 public: 87 FragmentPacket(const ipv6_packet_key& key); 88 ~FragmentPacket(); 89 90 status_t AddFragment(uint16 start, uint16 end, 91 net_buffer* buffer, bool lastFragment); 92 status_t Reassemble(net_buffer* to); 93 94 bool IsComplete() const 95 { return fReceivedLastFragment 96 && fBytesLeft == 0; } 97 98 const ipv6_packet_key& Key() const { return fKey; } 99 FragmentPacket*& HashTableLink() { return fNext; } 100 101 static void StaleTimer(struct net_timer* timer, void* data); 102 103 private: 104 FragmentPacket* fNext; 105 struct ipv6_packet_key fKey; 106 uint32 fIndex; 107 int32 fBytesLeft; 108 FragmentList fFragments; 109 net_timer fTimer; 110 bool fReceivedLastFragment; 111 }; 112 113 114 struct FragmentHashDefinition { 115 typedef ipv6_packet_key KeyType; 116 typedef FragmentPacket ValueType; 117 118 size_t HashKey(const KeyType& key) const 119 { 120 return jenkins_hashword((const uint32*)&key, 121 sizeof(ipv6_packet_key) / sizeof(uint32), 0); 122 } 123 124 size_t Hash(ValueType* value) const 125 { 126 return HashKey(value->Key()); 127 } 128 129 bool Compare(const KeyType& key, ValueType* value) const 130 { 131 const ipv6_packet_key& packetKey = value->Key(); 132 133 return packetKey.id == key.id 134 && packetKey.source == key.source 135 && packetKey.destination == key.destination 136 && packetKey.protocol == key.protocol; 137 } 138 139 ValueType*& GetLink(ValueType* value) const 140 { 141 return value->HashTableLink(); 142 } 143 }; 144 145 typedef BOpenHashTable<FragmentHashDefinition, false, true> FragmentTable; 146 147 148 class RawSocket 149 : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> { 150 public: 151 RawSocket(net_socket* socket); 152 }; 153 154 typedef DoublyLinkedList<RawSocket> RawSocketList; 155 156 157 typedef MulticastGroupInterface<IPv6Multicast> IPv6GroupInterface; 158 typedef MulticastFilter<IPv6Multicast> IPv6MulticastFilter; 159 160 struct MulticastStateHash { 161 typedef std::pair<const in6_addr*, uint32> KeyType; 162 typedef IPv6GroupInterface ValueType; 163 164 size_t HashKey(const KeyType &key) const; 165 size_t Hash(ValueType* value) const 166 { return HashKey(std::make_pair(&value->Address(), 167 value->Interface()->index)); } 168 bool Compare(const KeyType &key, ValueType* value) const 169 { return value->Interface()->index == key.second 170 && value->Address() == *key.first; } 171 bool CompareValues(ValueType* value1, ValueType* value2) const 172 { return value1->Interface()->index == value2->Interface()->index 173 && value1->Address() == value2->Address(); } 174 ValueType*& GetLink(ValueType* value) const { return value->HashLink(); } 175 }; 176 177 178 struct ipv6_protocol : net_protocol { 179 ipv6_protocol() 180 : 181 multicast_filter(this) 182 { 183 } 184 185 RawSocket *raw; 186 uint8 service_type; 187 uint8 time_to_live; 188 uint8 multicast_time_to_live; 189 uint8 receive_hoplimit; 190 uint8 receive_pktinfo; 191 struct sockaddr* multicast_address; // for IPV6_MULTICAST_IF 192 193 IPv6MulticastFilter multicast_filter; 194 }; 195 196 197 static const int kDefaultTTL = IPV6_DEFHLIM; 198 static const int kDefaultMulticastTTL = 1; 199 200 201 extern net_protocol_module_info gIPv6Module; 202 // we need this in ipv6_std_ops() for registering the AF_INET6 domain 203 204 net_stack_module_info* gStackModule; 205 net_buffer_module_info* gBufferModule; 206 207 static struct net_domain* sDomain; 208 static net_datalink_module_info* sDatalinkModule; 209 static net_socket_module_info* sSocketModule; 210 static RawSocketList sRawSockets; 211 static mutex sRawSocketsLock; 212 static mutex sFragmentLock; 213 static FragmentTable sFragmentHash; 214 static int32 sFragmentID; 215 static mutex sMulticastGroupsLock; 216 217 typedef MultiHashTable<MulticastStateHash> MulticastState; 218 static MulticastState* sMulticastState; 219 220 static net_protocol_module_info* sReceivingProtocol[256]; 221 static mutex sReceivingProtocolLock; 222 223 224 uint16 225 IPv6Header::GetHeaderOffset(net_buffer* buffer, uint32 headerCode) const 226 { 227 uint16 offset = sizeof(struct ip6_hdr); 228 uint8 next = header.ip6_nxt; 229 230 // these are the extension headers that might be supported one day 231 while (next != headerCode 232 && (next == IPPROTO_HOPOPTS 233 || next == IPPROTO_ROUTING 234 || next == IPPROTO_FRAGMENT 235 || next == IPPROTO_ESP 236 || next == IPPROTO_AH 237 || next == IPPROTO_DSTOPTS)) { 238 struct ip6_ext extensionHeader; 239 status_t status = gBufferModule->read(buffer, offset, 240 &extensionHeader, sizeof(ip6_ext)); 241 if (status != B_OK) 242 break; 243 244 next = extensionHeader.ip6e_nxt; 245 offset += extensionHeader.ip6e_len; 246 } 247 248 // were we looking for a specific header? 249 if (headerCode != ~0u) { 250 if (next == headerCode) { 251 // found the specific header 252 return offset; 253 } 254 // return 0 if fragement header is not present 255 return 0; 256 } 257 258 // the general transport layer header case 259 buffer->protocol = next; 260 return offset; 261 } 262 263 264 RawSocket::RawSocket(net_socket* socket) 265 : 266 DatagramSocket<>("ipv6 raw socket", socket) 267 { 268 } 269 270 271 // #pragma mark - 272 273 274 FragmentPacket::FragmentPacket(const ipv6_packet_key &key) 275 : 276 fKey(key), 277 fBytesLeft(IPV6_MAXPACKET), 278 fReceivedLastFragment(false) 279 { 280 gStackModule->init_timer(&fTimer, FragmentPacket::StaleTimer, this); 281 } 282 283 284 FragmentPacket::~FragmentPacket() 285 { 286 // cancel the kill timer 287 gStackModule->set_timer(&fTimer, -1); 288 289 // delete all fragments 290 net_buffer* buffer; 291 while ((buffer = fFragments.RemoveHead()) != NULL) { 292 gBufferModule->free(buffer); 293 } 294 } 295 296 297 status_t 298 FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer* buffer, 299 bool lastFragment) 300 { 301 // restart the timer 302 gStackModule->set_timer(&fTimer, FRAGMENT_TIMEOUT); 303 304 if (start >= end) { 305 // invalid fragment 306 return B_BAD_DATA; 307 } 308 309 // Search for a position in the list to insert the fragment 310 311 FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator(); 312 net_buffer* previous = NULL; 313 net_buffer* next = NULL; 314 while ((previous = iterator.Next()) != NULL) { 315 if (previous->fragment.start <= start) { 316 // The new fragment can be inserted after this one 317 break; 318 } 319 320 next = previous; 321 } 322 323 // See if we already have the fragment's data 324 325 if (previous != NULL && previous->fragment.start <= start 326 && previous->fragment.end >= end) { 327 // we do, so we can just drop this fragment 328 gBufferModule->free(buffer); 329 return B_OK; 330 } 331 332 fIndex = buffer->index; 333 // adopt the buffer's device index 334 335 TRACE(" previous: %p, next: %p", previous, next); 336 337 // If we have parts of the data already, truncate as needed 338 339 if (previous != NULL && previous->fragment.end > start) { 340 TRACE(" remove header %d bytes", previous->fragment.end - start); 341 gBufferModule->remove_header(buffer, previous->fragment.end - start); 342 start = previous->fragment.end; 343 } 344 if (next != NULL && next->fragment.start < end) { 345 TRACE(" remove trailer %d bytes", next->fragment.start - end); 346 gBufferModule->remove_trailer(buffer, next->fragment.start - end); 347 end = next->fragment.start; 348 } 349 350 // Now try if we can already merge the fragments together 351 352 // We will always keep the last buffer received, so that we can still 353 // report an error (in which case we're not responsible for freeing it) 354 355 if (previous != NULL && previous->fragment.end == start) { 356 fFragments.Remove(previous); 357 358 buffer->fragment.start = previous->fragment.start; 359 buffer->fragment.end = end; 360 361 status_t status = gBufferModule->merge(buffer, previous, false); 362 TRACE(" merge previous: %s", strerror(status)); 363 if (status != B_OK) { 364 fFragments.Insert(next, previous); 365 return status; 366 } 367 368 fFragments.Insert(next, buffer); 369 370 // cut down existing hole 371 fBytesLeft -= end - start; 372 373 if (lastFragment && !fReceivedLastFragment) { 374 fReceivedLastFragment = true; 375 fBytesLeft -= IPV6_MAXPACKET - end; 376 } 377 378 TRACE(" hole length: %d", (int)fBytesLeft); 379 380 return B_OK; 381 } else if (next != NULL && next->fragment.start == end) { 382 net_buffer* afterNext = (net_buffer*)next->link.next; 383 fFragments.Remove(next); 384 385 buffer->fragment.start = start; 386 buffer->fragment.end = next->fragment.end; 387 388 status_t status = gBufferModule->merge(buffer, next, true); 389 TRACE(" merge next: %s", strerror(status)); 390 if (status != B_OK) { 391 // Insert "next" at its previous position 392 fFragments.Insert(afterNext, next); 393 return status; 394 } 395 396 fFragments.Insert(afterNext, buffer); 397 398 // cut down existing hole 399 fBytesLeft -= end - start; 400 401 if (lastFragment && !fReceivedLastFragment) { 402 fReceivedLastFragment = true; 403 fBytesLeft -= IPV6_MAXPACKET - end; 404 } 405 406 TRACE(" hole length: %d", (int)fBytesLeft); 407 408 return B_OK; 409 } 410 411 // We couldn't merge the fragments, so we need to add it as is 412 413 TRACE(" new fragment: %p, bytes %d-%d", buffer, start, end); 414 415 buffer->fragment.start = start; 416 buffer->fragment.end = end; 417 fFragments.Insert(next, buffer); 418 419 // update length of the hole, if any 420 fBytesLeft -= end - start; 421 422 if (lastFragment && !fReceivedLastFragment) { 423 fReceivedLastFragment = true; 424 fBytesLeft -= IPV6_MAXPACKET - end; 425 } 426 427 TRACE(" hole length: %d", (int)fBytesLeft); 428 429 return B_OK; 430 } 431 432 433 /*! Reassembles the fragments to the specified buffer \a to. 434 This buffer must have been added via AddFragment() before. 435 */ 436 status_t 437 FragmentPacket::Reassemble(net_buffer* to) 438 { 439 if (!IsComplete()) 440 return B_ERROR; 441 442 net_buffer* buffer = NULL; 443 444 net_buffer* fragment; 445 while ((fragment = fFragments.RemoveHead()) != NULL) { 446 if (buffer != NULL) { 447 status_t status; 448 if (to == fragment) { 449 status = gBufferModule->merge(fragment, buffer, false); 450 buffer = fragment; 451 } else 452 status = gBufferModule->merge(buffer, fragment, true); 453 if (status != B_OK) 454 return status; 455 } else 456 buffer = fragment; 457 } 458 459 if (buffer != to) 460 panic("ipv6 packet reassembly did not work correctly."); 461 462 to->index = fIndex; 463 // reset the buffer's device index 464 465 return B_OK; 466 } 467 468 469 /*static*/ void 470 FragmentPacket::StaleTimer(struct net_timer* timer, void* data) 471 { 472 FragmentPacket* packet = (FragmentPacket*)data; 473 TRACE("Assembling FragmentPacket %p timed out!", packet); 474 475 MutexLocker locker(&sFragmentLock); 476 sFragmentHash.Remove(packet); 477 locker.Unlock(); 478 479 if (!packet->fFragments.IsEmpty()) { 480 // Send error: fragment reassembly time exceeded 481 sDomain->module->error_reply(NULL, packet->fFragments.First(), 482 B_NET_ERROR_REASSEMBLY_TIME_EXCEEDED, NULL); 483 } 484 485 delete packet; 486 } 487 488 489 // #pragma mark - 490 491 492 size_t 493 MulticastStateHash::HashKey(const KeyType &key) const 494 { 495 size_t result = 0; 496 result = jenkins_hashword((const uint32*)&key.first, 497 sizeof(in6_addr) / sizeof(uint32), result); 498 result = jenkins_hashword(&key.second, 1, result); 499 return result; 500 } 501 502 503 // #pragma mark - 504 505 506 static inline void 507 dump_ipv6_header(IPv6Header &header) 508 { 509 #ifdef TRACE_IPV6 510 char addrbuf[INET6_ADDRSTRLEN]; 511 dprintf(" version: %d\n", header.ProtocolVersion() >> 4); 512 dprintf(" service_type: %d\n", header.ServiceType()); 513 dprintf(" payload_length: %d\n", header.PayloadLength()); 514 dprintf(" next_header: %d\n", header.NextHeader()); 515 dprintf(" hop_limit: %d\n", header.header.ip6_hops); 516 dprintf(" source: %s\n", ip6_sprintf(&header.header.ip6_src, addrbuf)); 517 dprintf(" destination: %s\n", 518 ip6_sprintf(&header.header.ip6_dst, addrbuf)); 519 #endif 520 } 521 522 523 /*! Attempts to re-assemble fragmented packets. 524 \return B_OK if everything went well; if it could reassemble the packet, \a _buffer 525 will point to its buffer, otherwise, it will be \c NULL. 526 \return various error codes if something went wrong (mostly B_NO_MEMORY) 527 */ 528 static status_t 529 reassemble_fragments(const IPv6Header &header, net_buffer** _buffer, uint16 offset) 530 { 531 net_buffer* buffer = *_buffer; 532 status_t status; 533 534 ip6_frag fragmentHeader; 535 status = gBufferModule->read(buffer, offset, &fragmentHeader, sizeof(ip6_frag)); 536 if (status != B_OK) 537 return status; 538 539 struct ipv6_packet_key key; 540 memcpy(&key.source, &header.Src(), sizeof(in6_addr)); 541 memcpy(&key.destination, &header.Dst(), sizeof(in6_addr)); 542 key.id = fragmentHeader.ip6f_ident; 543 key.protocol = fragmentHeader.ip6f_nxt; 544 545 // TODO: Make locking finer grained. 546 MutexLocker locker(&sFragmentLock); 547 548 FragmentPacket* packet = sFragmentHash.Lookup(key); 549 if (packet == NULL) { 550 // New fragment packet 551 packet = new (std::nothrow) FragmentPacket(key); 552 if (packet == NULL) 553 return B_NO_MEMORY; 554 555 // add packet to hash 556 status = sFragmentHash.Insert(packet); 557 if (status != B_OK) { 558 delete packet; 559 return status; 560 } 561 } 562 563 uint16 start = ntohs(fragmentHeader.ip6f_offlg & IP6F_OFF_MASK); 564 uint16 end = start + header.PayloadLength(); 565 bool lastFragment = (fragmentHeader.ip6f_offlg & IP6F_MORE_FRAG) == 0; 566 567 TRACE(" Received IPv6 %sfragment of size %d, offset %d.", 568 lastFragment ? "last ": "", end - start, start); 569 570 // Remove header unless this is the first fragment 571 if (start != 0) 572 gBufferModule->remove_header(buffer, offset); 573 574 status = packet->AddFragment(start, end, buffer, lastFragment); 575 if (status != B_OK) 576 return status; 577 578 if (packet->IsComplete()) { 579 sFragmentHash.Remove(packet); 580 // no matter if reassembling succeeds, we won't need this packet 581 // anymore 582 583 status = packet->Reassemble(buffer); 584 delete packet; 585 586 // _buffer does not change 587 return status; 588 } 589 590 // This indicates that the packet is not yet complete 591 *_buffer = NULL; 592 return B_OK; 593 } 594 595 596 /*! Fragments the incoming buffer and send all fragments via the specified 597 \a route. 598 */ 599 static status_t 600 send_fragments(ipv6_protocol* protocol, struct net_route* route, 601 net_buffer* buffer, uint32 mtu) 602 { 603 TRACE_SK(protocol, "SendFragments(%lu bytes, mtu %lu)", buffer->size, mtu); 604 605 NetBufferHeaderReader<IPv6Header> originalHeader(buffer); 606 if (originalHeader.Status() != B_OK) 607 return originalHeader.Status(); 608 609 // TODO: currently FragHeader goes always as the last one, but in theory 610 // ext. headers like AuthHeader and DestOptions should go after it. 611 uint16 headersLength = originalHeader->GetHeaderOffset(buffer); 612 uint16 extensionHeadersLength = headersLength 613 - sizeof(ip6_hdr) + sizeof(ip6_frag); 614 uint32 bytesLeft = buffer->size - headersLength; 615 uint32 fragmentOffset = 0; 616 status_t status = B_OK; 617 618 // TODO: this is rather inefficient 619 net_buffer* headerBuffer = gBufferModule->clone(buffer, false); 620 if (headerBuffer == NULL) 621 return B_NO_MEMORY; 622 623 status = gBufferModule->remove_trailer(headerBuffer, bytesLeft); 624 if (status != B_OK) 625 return status; 626 627 uint8 data[bytesLeft]; 628 status = gBufferModule->read(buffer, headersLength, data, bytesLeft); 629 if (status != B_OK) 630 return status; 631 632 // TODO (from ipv4): we need to make sure all header space is contiguous or 633 // use another construct. 634 NetBufferHeaderReader<IPv6Header> bufferHeader(headerBuffer); 635 636 // Adapt MTU to be a multiple of 8 (fragment offsets can only be specified 637 // this way) 638 mtu -= headersLength + sizeof(ip6_frag); 639 mtu &= ~7; 640 TRACE(" adjusted MTU to %ld, bytesLeft %ld", mtu, bytesLeft); 641 642 while (bytesLeft > 0) { 643 uint32 fragmentLength = min_c(bytesLeft, mtu); 644 bytesLeft -= fragmentLength; 645 bool lastFragment = bytesLeft == 0; 646 647 bufferHeader->header.ip6_nxt = IPPROTO_FRAGMENT; 648 bufferHeader->header.ip6_plen = 649 htons(fragmentLength + extensionHeadersLength); 650 bufferHeader.Sync(); 651 652 ip6_frag fragmentHeader; 653 fragmentHeader.ip6f_nxt = originalHeader->NextHeader(); 654 fragmentHeader.ip6f_reserved = 0; 655 fragmentHeader.ip6f_offlg = htons(fragmentOffset) & IP6F_OFF_MASK; 656 if (!lastFragment) 657 fragmentHeader.ip6f_offlg |= IP6F_MORE_FRAG; 658 fragmentHeader.ip6f_ident = htonl(atomic_add(&sFragmentID, 1)); 659 660 TRACE(" send fragment of %ld bytes (%ld bytes left)", fragmentLength, 661 bytesLeft); 662 663 net_buffer* fragmentBuffer; 664 if (!lastFragment) 665 fragmentBuffer = gBufferModule->clone(headerBuffer, false); 666 else 667 fragmentBuffer = buffer; 668 669 if (fragmentBuffer == NULL) { 670 status = B_NO_MEMORY; 671 break; 672 } 673 674 // copy data to fragment 675 do { 676 status = gBufferModule->append( 677 fragmentBuffer, &fragmentHeader, sizeof(ip6_frag)); 678 if (status != B_OK) 679 break; 680 681 status = gBufferModule->append( 682 fragmentBuffer, &data[fragmentOffset], fragmentLength); 683 if (status != B_OK) 684 break; 685 686 // send fragment 687 status = sDatalinkModule->send_routed_data(route, fragmentBuffer); 688 } while (false); 689 690 if (lastFragment) { 691 // we don't own the last buffer, so we don't have to free it 692 break; 693 } 694 695 if (status != B_OK) { 696 gBufferModule->free(fragmentBuffer); 697 break; 698 } 699 700 fragmentOffset += fragmentLength; 701 } 702 703 gBufferModule->free(headerBuffer); 704 return status; 705 } 706 707 708 static status_t 709 deliver_multicast(net_protocol_module_info* module, net_buffer* buffer, 710 bool deliverToRaw, net_interface *interface) 711 { 712 sockaddr_in6* multicastAddr = (sockaddr_in6*)buffer->destination; 713 714 MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair( 715 &multicastAddr->sin6_addr, interface->index)); 716 717 while (it.HasNext()) { 718 IPv6GroupInterface* state = it.Next(); 719 ipv6_protocol* ipproto = state->Parent()->Socket(); 720 721 if (deliverToRaw && ipproto->raw == NULL) 722 continue; 723 724 if (state->FilterAccepts(buffer)) { 725 // TODO: do as in IPv4 code 726 module->deliver_data(ipproto, buffer); 727 } 728 } 729 730 return B_OK; 731 } 732 733 734 static status_t 735 deliver_multicast(net_protocol_module_info* module, net_buffer* buffer, 736 bool deliverToRaw) 737 { 738 if (module->deliver_data == NULL) 739 return B_OK; 740 741 MutexLocker _(sMulticastGroupsLock); 742 743 status_t status = B_OK; 744 if (buffer->interface_address != NULL) { 745 status = deliver_multicast(module, buffer, deliverToRaw, 746 buffer->interface_address->interface); 747 } else { 748 #if 0 // FIXME: multicast 749 net_domain_private* domain = (net_domain_private*)sDomain; 750 RecursiveLocker locker(domain->lock); 751 752 net_interface* interface = NULL; 753 while (true) { 754 interface = (net_interface*)list_get_next_item( 755 &domain->interfaces, interface); 756 if (interface == NULL) 757 break; 758 759 status = deliver_multicast(module, buffer, deliverToRaw, interface); 760 if (status < B_OK) 761 break; 762 } 763 #endif 764 } 765 return status; 766 } 767 768 769 static void 770 raw_receive_data(net_buffer* buffer) 771 { 772 MutexLocker locker(sRawSocketsLock); 773 774 if (sRawSockets.IsEmpty()) 775 return; 776 777 TRACE("RawReceiveData(%i)", buffer->protocol); 778 779 if ((buffer->flags & MSG_MCAST) != 0) { 780 deliver_multicast(&gIPv6Module, buffer, true); 781 } else { 782 RawSocketList::Iterator iterator = sRawSockets.GetIterator(); 783 784 while (iterator.HasNext()) { 785 RawSocket* raw = iterator.Next(); 786 787 if (raw->Socket()->protocol == buffer->protocol) 788 raw->EnqueueClone(buffer); 789 } 790 } 791 } 792 793 794 static inline sockaddr* 795 fill_sockaddr_in6(sockaddr_in6* target, const in6_addr &address) 796 { 797 target->sin6_family = AF_INET6; 798 target->sin6_len = sizeof(sockaddr_in6); 799 target->sin6_port = 0; 800 target->sin6_flowinfo = 0; 801 memcpy(target->sin6_addr.s6_addr, address.s6_addr, sizeof(in6_addr)); 802 target->sin6_scope_id = 0; 803 return (sockaddr*)target; 804 } 805 806 807 status_t 808 IPv6Multicast::JoinGroup(IPv6GroupInterface* state) 809 { 810 MutexLocker _(sMulticastGroupsLock); 811 812 sockaddr_in6 groupAddr; 813 status_t status = sDatalinkModule->join_multicast(state->Interface(), 814 sDomain, fill_sockaddr_in6(&groupAddr, state->Address())); 815 if (status != B_OK) 816 return status; 817 818 sMulticastState->Insert(state); 819 return B_OK; 820 } 821 822 823 status_t 824 IPv6Multicast::LeaveGroup(IPv6GroupInterface* state) 825 { 826 MutexLocker _(sMulticastGroupsLock); 827 828 sMulticastState->Remove(state); 829 830 sockaddr_in6 groupAddr; 831 return sDatalinkModule->leave_multicast(state->Interface(), sDomain, 832 fill_sockaddr_in6(&groupAddr, state->Address())); 833 } 834 835 836 static net_protocol_module_info* 837 receiving_protocol(uint8 protocol) 838 { 839 net_protocol_module_info* module = sReceivingProtocol[protocol]; 840 if (module != NULL) 841 return module; 842 843 MutexLocker locker(sReceivingProtocolLock); 844 845 module = sReceivingProtocol[protocol]; 846 if (module != NULL) 847 return module; 848 849 if (gStackModule->get_domain_receiving_protocol(sDomain, protocol, 850 &module) == B_OK) 851 sReceivingProtocol[protocol] = module; 852 853 return module; 854 } 855 856 857 static status_t 858 ipv6_delta_group(IPv6GroupInterface* group, int option, 859 net_interface* interface, const in6_addr* sourceAddr) 860 { 861 switch (option) { 862 case IPV6_JOIN_GROUP: 863 return group->Add(); 864 case IPV6_LEAVE_GROUP: 865 return group->Drop(); 866 } 867 868 return B_ERROR; 869 } 870 871 872 static status_t 873 ipv6_delta_membership(ipv6_protocol* protocol, int option, 874 net_interface* interface, const in6_addr* groupAddr, 875 const in6_addr* sourceAddr) 876 { 877 IPv6MulticastFilter &filter = protocol->multicast_filter; 878 IPv6GroupInterface* state = NULL; 879 status_t status = B_OK; 880 881 switch (option) { 882 // TODO: support more options 883 case IPV6_JOIN_GROUP: 884 status = filter.GetState(*groupAddr, interface, state, true); 885 break; 886 887 case IPV6_LEAVE_GROUP: 888 filter.GetState(*groupAddr, interface, state, false); 889 if (state == NULL) 890 return EADDRNOTAVAIL; 891 break; 892 } 893 894 if (status != B_OK) 895 return status; 896 897 status = ipv6_delta_group(state, option, interface, sourceAddr); 898 filter.ReturnState(state); 899 return status; 900 } 901 902 903 static status_t 904 ipv6_delta_membership(ipv6_protocol* protocol, int option, 905 uint32 interfaceIndex, in6_addr* groupAddr, in6_addr* sourceAddr) 906 { 907 net_interface* interface; 908 909 // TODO: can the interface be unspecified? 910 interface = sDatalinkModule->get_interface(sDomain, interfaceIndex); 911 912 if (interface == NULL) 913 return B_DEVICE_NOT_FOUND; 914 915 return ipv6_delta_membership(protocol, option, interface, 916 groupAddr, sourceAddr); 917 } 918 919 920 static status_t 921 get_int_option(void* target, size_t length, int value) 922 { 923 if (length != sizeof(int)) 924 return B_BAD_VALUE; 925 926 return user_memcpy(target, &value, sizeof(int)); 927 } 928 929 930 template<typename Type> static status_t 931 set_int_option(Type &target, const void* _value, size_t length) 932 { 933 int value; 934 935 if (length != sizeof(int)) 936 return B_BAD_VALUE; 937 938 if (user_memcpy(&value, _value, sizeof(int)) != B_OK) 939 return B_BAD_ADDRESS; 940 941 target = value; 942 return B_OK; 943 } 944 945 946 // #pragma mark - 947 948 949 net_protocol* 950 ipv6_init_protocol(net_socket* socket) 951 { 952 ipv6_protocol* protocol = new (std::nothrow) ipv6_protocol(); 953 if (protocol == NULL) 954 return NULL; 955 956 protocol->raw = NULL; 957 protocol->service_type = 0; 958 protocol->time_to_live = kDefaultTTL; 959 protocol->multicast_time_to_live = kDefaultMulticastTTL; 960 protocol->receive_hoplimit = 0; 961 protocol->receive_pktinfo = 0; 962 protocol->multicast_address = NULL; 963 return protocol; 964 } 965 966 967 status_t 968 ipv6_uninit_protocol(net_protocol* _protocol) 969 { 970 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 971 972 delete protocol->raw; 973 delete protocol->multicast_address; 974 delete protocol; 975 return B_OK; 976 } 977 978 979 /*! Since open() is only called on the top level protocol, when we get here 980 it means we are on a SOCK_RAW socket. 981 */ 982 status_t 983 ipv6_open(net_protocol* _protocol) 984 { 985 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 986 987 RawSocket* raw = new (std::nothrow) RawSocket(protocol->socket); 988 if (raw == NULL) 989 return B_NO_MEMORY; 990 991 status_t status = raw->InitCheck(); 992 if (status != B_OK) { 993 delete raw; 994 return status; 995 } 996 997 TRACE_SK(protocol, "Open()"); 998 999 protocol->raw = raw; 1000 1001 MutexLocker locker(sRawSocketsLock); 1002 sRawSockets.Add(raw); 1003 return B_OK; 1004 } 1005 1006 1007 status_t 1008 ipv6_close(net_protocol* _protocol) 1009 { 1010 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1011 RawSocket* raw = protocol->raw; 1012 if (raw == NULL) 1013 return B_ERROR; 1014 1015 TRACE_SK(protocol, "Close()"); 1016 1017 MutexLocker locker(sRawSocketsLock); 1018 sRawSockets.Remove(raw); 1019 delete raw; 1020 protocol->raw = NULL; 1021 1022 return B_OK; 1023 } 1024 1025 1026 status_t 1027 ipv6_free(net_protocol* protocol) 1028 { 1029 return B_OK; 1030 } 1031 1032 1033 status_t 1034 ipv6_connect(net_protocol* protocol, const struct sockaddr* address) 1035 { 1036 return B_ERROR; 1037 } 1038 1039 1040 status_t 1041 ipv6_accept(net_protocol* protocol, struct net_socket** _acceptedSocket) 1042 { 1043 return EOPNOTSUPP; 1044 } 1045 1046 1047 status_t 1048 ipv6_control(net_protocol* _protocol, int level, int option, void* value, 1049 size_t* _length) 1050 { 1051 if ((level & LEVEL_MASK) != IPPROTO_IPV6) 1052 return sDatalinkModule->control(sDomain, option, value, _length); 1053 1054 return B_BAD_VALUE; 1055 } 1056 1057 1058 status_t 1059 ipv6_getsockopt(net_protocol* _protocol, int level, int option, void* value, 1060 int* _length) 1061 { 1062 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1063 1064 if (level == IPPROTO_IPV6) { 1065 // TODO: support more of these options 1066 1067 if (option == IPV6_MULTICAST_HOPS) { 1068 return get_int_option(value, *_length, 1069 protocol->multicast_time_to_live); 1070 } 1071 if (option == IPV6_MULTICAST_LOOP) 1072 return EOPNOTSUPP; 1073 if (option == IPV6_UNICAST_HOPS) 1074 return get_int_option(value, *_length, protocol->time_to_live); 1075 if (option == IPV6_V6ONLY) 1076 return EOPNOTSUPP; 1077 if (option == IPV6_RECVPKTINFO) 1078 return get_int_option(value, *_length, protocol->receive_pktinfo); 1079 if (option == IPV6_RECVHOPLIMIT) 1080 return get_int_option(value, *_length, protocol->receive_hoplimit); 1081 if (option == IPV6_JOIN_GROUP 1082 || option == IPV6_LEAVE_GROUP) 1083 return EOPNOTSUPP; 1084 1085 dprintf("IPv6::getsockopt(): get unknown option: %d\n", option); 1086 return ENOPROTOOPT; 1087 } 1088 1089 return sSocketModule->get_option(protocol->socket, level, option, value, 1090 _length); 1091 } 1092 1093 1094 status_t 1095 ipv6_setsockopt(net_protocol* _protocol, int level, int option, 1096 const void* value, int length) 1097 { 1098 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1099 1100 if (level == IPPROTO_IPV6) { 1101 // TODO: support more of these options 1102 1103 if (option == IPV6_MULTICAST_IF) { 1104 if (length != sizeof(struct in6_addr)) 1105 return B_BAD_VALUE; 1106 1107 struct sockaddr_in6* address = new (std::nothrow) sockaddr_in6; 1108 if (address == NULL) 1109 return B_NO_MEMORY; 1110 1111 if (user_memcpy(&address->sin6_addr, value, sizeof(in6_addr)) 1112 != B_OK) { 1113 delete address; 1114 return B_BAD_ADDRESS; 1115 } 1116 1117 // Using the unspecifed address to remove the previous setting. 1118 if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)) { 1119 delete address; 1120 delete protocol->multicast_address; 1121 protocol->multicast_address = NULL; 1122 return B_OK; 1123 } 1124 1125 struct net_interface* interface 1126 = sDatalinkModule->get_interface_with_address( 1127 (sockaddr*)address); 1128 if (interface == NULL) { 1129 delete address; 1130 return EADDRNOTAVAIL; 1131 } 1132 1133 delete protocol->multicast_address; 1134 protocol->multicast_address = (struct sockaddr*)address; 1135 return B_OK; 1136 } 1137 if (option == IPV6_MULTICAST_HOPS) { 1138 return set_int_option(protocol->multicast_time_to_live, 1139 value, length); 1140 } 1141 if (option == IPV6_MULTICAST_LOOP) 1142 return EOPNOTSUPP; 1143 if (option == IPV6_UNICAST_HOPS) 1144 return set_int_option(protocol->time_to_live, value, length); 1145 if (option == IPV6_V6ONLY) 1146 return EOPNOTSUPP; 1147 if (option == IPV6_RECVPKTINFO) 1148 return set_int_option(protocol->receive_pktinfo, value, length); 1149 if (option == IPV6_RECVHOPLIMIT) 1150 return set_int_option(protocol->receive_hoplimit, value, length); 1151 if (option == IPV6_JOIN_GROUP || option == IPV6_LEAVE_GROUP) { 1152 ipv6_mreq mreq; 1153 if (length != sizeof(ipv6_mreq)) 1154 return B_BAD_VALUE; 1155 if (user_memcpy(&mreq, value, sizeof(ipv6_mreq)) != B_OK) 1156 return B_BAD_ADDRESS; 1157 1158 return ipv6_delta_membership(protocol, option, mreq.ipv6mr_interface, 1159 &mreq.ipv6mr_multiaddr, NULL); 1160 } 1161 1162 dprintf("IPv6::setsockopt(): set unknown option: %d\n", option); 1163 return ENOPROTOOPT; 1164 } 1165 1166 return sSocketModule->set_option(protocol->socket, level, option, 1167 value, length); 1168 } 1169 1170 1171 status_t 1172 ipv6_bind(net_protocol* protocol, const sockaddr* _address) 1173 { 1174 if (_address->sa_family != AF_INET6) 1175 return EAFNOSUPPORT; 1176 1177 const sockaddr_in6* address = (const sockaddr_in6*)_address; 1178 1179 // only INADDR_ANY and addresses of local interfaces are accepted: 1180 if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr) 1181 || IN6_IS_ADDR_MULTICAST(&address->sin6_addr) 1182 || sDatalinkModule->is_local_address(sDomain, _address, NULL, NULL)) { 1183 memcpy(&protocol->socket->address, address, sizeof(sockaddr_in6)); 1184 protocol->socket->address.ss_len = sizeof(sockaddr_in6); 1185 // explicitly set length, as our callers can't be trusted to 1186 // always provide the correct length! 1187 return B_OK; 1188 } 1189 1190 return B_ERROR; 1191 // address is unknown on this host 1192 } 1193 1194 1195 status_t 1196 ipv6_unbind(net_protocol* protocol, struct sockaddr* address) 1197 { 1198 // nothing to do here 1199 return B_OK; 1200 } 1201 1202 1203 status_t 1204 ipv6_listen(net_protocol* protocol, int count) 1205 { 1206 return EOPNOTSUPP; 1207 } 1208 1209 1210 status_t 1211 ipv6_shutdown(net_protocol* protocol, int direction) 1212 { 1213 return EOPNOTSUPP; 1214 } 1215 1216 1217 static uint8 1218 ip6_select_hoplimit(net_protocol* _protocol, net_buffer* buffer) 1219 { 1220 // TODO: the precedence should be as follows: 1221 // 1. Hoplimit value specified via ioctl. 1222 // 2. (If the outgoing interface is detected) the current 1223 // hop limit of the interface specified by router advertisement. 1224 // 3. The system default hoplimit. 1225 1226 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1227 const bool isMulticast = buffer->flags & MSG_MCAST; 1228 1229 if (protocol) { 1230 return isMulticast ? protocol->multicast_time_to_live 1231 : protocol->time_to_live; 1232 } 1233 return isMulticast ? kDefaultMulticastTTL : kDefaultTTL; 1234 } 1235 1236 1237 status_t 1238 ipv6_send_routed_data(net_protocol* _protocol, struct net_route* route, 1239 net_buffer* buffer) 1240 { 1241 if (route == NULL) 1242 return B_BAD_VALUE; 1243 1244 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1245 net_interface* interface = route->interface_address->interface; 1246 uint8 protocolNumber; 1247 if (protocol != NULL && protocol->socket != NULL) 1248 protocolNumber = protocol->socket->protocol; 1249 else 1250 protocolNumber = buffer->protocol; 1251 1252 TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer, 1253 buffer->size); 1254 1255 sockaddr_in6& source = *(sockaddr_in6*)buffer->source; 1256 sockaddr_in6& destination = *(sockaddr_in6*)buffer->destination; 1257 1258 buffer->flags &= ~(MSG_BCAST | MSG_MCAST); 1259 1260 if (IN6_IS_ADDR_UNSPECIFIED(&destination.sin6_addr)) 1261 return EDESTADDRREQ; 1262 1263 if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr)) 1264 buffer->flags |= MSG_MCAST; 1265 1266 uint16 dataLength = buffer->size; 1267 1268 // Add IPv6 header 1269 1270 NetBufferPrepend<ip6_hdr> header(buffer); 1271 if (header.Status() != B_OK) 1272 return header.Status(); 1273 1274 if (buffer->size > 0xffff) 1275 return EMSGSIZE; 1276 1277 uint32 flowinfo = 0; 1278 // TODO: fill in the flow id from somewhere 1279 if (protocol) { 1280 // fill in traffic class 1281 flowinfo |= htonl(protocol->service_type << 20); 1282 } 1283 // set lower 28 bits 1284 header->ip6_flow = htonl(flowinfo) & IPV6_FLOWINFO_MASK; 1285 // set upper 4 bits 1286 header->ip6_vfc |= IPV6_VERSION; 1287 header->ip6_plen = htons(dataLength); 1288 header->ip6_nxt = protocolNumber; 1289 header->ip6_hlim = ip6_select_hoplimit(protocol, buffer); 1290 memcpy(&header->ip6_src, &source.sin6_addr, sizeof(in6_addr)); 1291 memcpy(&header->ip6_dst, &destination.sin6_addr, sizeof(in6_addr)); 1292 1293 header.Sync(); 1294 1295 // write the checksum for ICMPv6 sockets 1296 if (protocolNumber == IPPROTO_ICMPV6 1297 && dataLength >= sizeof(struct icmp6_hdr)) { 1298 NetBufferField<uint16, 1299 sizeof(ip6_hdr) + offsetof(icmp6_hdr, icmp6_cksum)> 1300 icmpChecksum(buffer); 1301 // first make sure the existing checksum is zero 1302 *icmpChecksum = 0; 1303 icmpChecksum.Sync(); 1304 1305 uint16 checksum = gBufferModule->checksum(buffer, sizeof(ip6_hdr), 1306 buffer->size - sizeof(ip6_hdr), false); 1307 checksum = ipv6_checksum(&header->ip6_src, 1308 &header->ip6_dst, dataLength, protocolNumber, 1309 checksum); 1310 *icmpChecksum = checksum; 1311 } 1312 1313 char addrbuf[INET6_ADDRSTRLEN]; 1314 TRACE_SK(protocol, " SendRoutedData(): destination: %s", 1315 ip6_sprintf(&destination.sin6_addr, addrbuf)); 1316 1317 uint32 mtu = route->mtu ? route->mtu : interface->mtu; 1318 if (buffer->size > mtu) { 1319 // we need to fragment the packet 1320 return send_fragments(protocol, route, buffer, mtu); 1321 } 1322 1323 return sDatalinkModule->send_routed_data(route, buffer); 1324 } 1325 1326 1327 status_t 1328 ipv6_send_data(net_protocol* _protocol, net_buffer* buffer) 1329 { 1330 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1331 1332 TRACE_SK(protocol, "SendData(%p [%ld bytes])", buffer, buffer->size); 1333 1334 sockaddr_in6* destination = (sockaddr_in6*)buffer->destination; 1335 1336 // handle IPV6_MULTICAST_IF 1337 if (IN6_IS_ADDR_MULTICAST(&destination->sin6_addr) 1338 && protocol->multicast_address != NULL) { 1339 net_interface_address* address = sDatalinkModule->get_interface_address( 1340 protocol->multicast_address); 1341 if (address == NULL || (address->interface->flags & IFF_UP) == 0) { 1342 sDatalinkModule->put_interface_address(address); 1343 return EADDRNOTAVAIL; 1344 } 1345 1346 sDatalinkModule->put_interface_address(buffer->interface_address); 1347 buffer->interface_address = address; 1348 // the buffer takes over ownership of the address 1349 1350 net_route* route = sDatalinkModule->get_route(sDomain, address->local); 1351 if (route == NULL) 1352 return ENETUNREACH; 1353 1354 return sDatalinkModule->send_routed_data(route, buffer); 1355 } 1356 1357 return sDatalinkModule->send_data(protocol, sDomain, buffer); 1358 } 1359 1360 1361 ssize_t 1362 ipv6_send_avail(net_protocol* protocol) 1363 { 1364 return B_ERROR; 1365 } 1366 1367 1368 status_t 1369 ipv6_read_data(net_protocol* _protocol, size_t numBytes, uint32 flags, 1370 net_buffer** _buffer) 1371 { 1372 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1373 RawSocket* raw = protocol->raw; 1374 if (raw == NULL) 1375 return B_ERROR; 1376 1377 TRACE_SK(protocol, "ReadData(%lu, 0x%lx)", numBytes, flags); 1378 1379 return raw->Dequeue(flags, _buffer); 1380 } 1381 1382 1383 ssize_t 1384 ipv6_read_avail(net_protocol* _protocol) 1385 { 1386 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1387 RawSocket* raw = protocol->raw; 1388 if (raw == NULL) 1389 return B_ERROR; 1390 1391 return raw->AvailableData(); 1392 } 1393 1394 1395 struct net_domain* 1396 ipv6_get_domain(net_protocol* protocol) 1397 { 1398 return sDomain; 1399 } 1400 1401 1402 size_t 1403 ipv6_get_mtu(net_protocol* protocol, const struct sockaddr* address) 1404 { 1405 net_route* route = sDatalinkModule->get_route(sDomain, address); 1406 if (route == NULL) 1407 return 0; 1408 1409 size_t mtu; 1410 if (route->mtu != 0) 1411 mtu = route->mtu; 1412 else 1413 mtu = route->interface_address->interface->mtu; 1414 1415 sDatalinkModule->put_route(sDomain, route); 1416 // TODO: what about extension headers? 1417 // this function probably shoud be changed in calling places, not here 1418 return mtu - sizeof(ip6_hdr); 1419 } 1420 1421 1422 status_t 1423 ipv6_receive_data(net_buffer* buffer) 1424 { 1425 TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size); 1426 1427 NetBufferHeaderReader<IPv6Header> bufferHeader(buffer); 1428 if (bufferHeader.Status() != B_OK) 1429 return bufferHeader.Status(); 1430 1431 IPv6Header &header = bufferHeader.Data(); 1432 // dump_ipv6_header(header); 1433 1434 if (header.ProtocolVersion() != IPV6_VERSION) 1435 return B_BAD_TYPE; 1436 1437 uint16 packetLength = header.PayloadLength() + sizeof(ip6_hdr); 1438 if (packetLength > buffer->size) 1439 return B_BAD_DATA; 1440 1441 // lower layers notion of Broadcast or Multicast have no relevance to us 1442 buffer->flags &= ~(MSG_BCAST | MSG_MCAST); 1443 1444 sockaddr_in6 destination; 1445 fill_sockaddr_in6(&destination, header.Dst()); 1446 1447 if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr)) { 1448 buffer->flags |= MSG_MCAST; 1449 } else { 1450 uint32 matchedAddressType = 0; 1451 1452 // test if the packet is really for us 1453 if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination, 1454 &buffer->interface_address, &matchedAddressType) 1455 && !sDatalinkModule->is_local_link_address(sDomain, true, 1456 buffer->destination, &buffer->interface_address)) { 1457 char srcbuf[INET6_ADDRSTRLEN]; 1458 char dstbuf[INET6_ADDRSTRLEN]; 1459 TRACE(" ipv6_receive_data(): packet was not for us %s -> %s", 1460 ip6_sprintf(&header.Src(), srcbuf), 1461 ip6_sprintf(&header.Dst(), dstbuf)); 1462 1463 // TODO: Send ICMPv6 error: Host unreachable 1464 return B_ERROR; 1465 } 1466 1467 // copy over special address types (MSG_BCAST or MSG_MCAST): 1468 buffer->flags |= matchedAddressType; 1469 } 1470 1471 // set net_buffer's source/destination address 1472 fill_sockaddr_in6((struct sockaddr_in6*)buffer->source, header.Src()); 1473 memcpy(buffer->destination, &destination, sizeof(sockaddr_in6)); 1474 1475 // get the transport protocol and transport header offset 1476 uint16 transportHeaderOffset = header.GetHeaderOffset(buffer); 1477 uint8 protocol = buffer->protocol; 1478 1479 // remove any trailing/padding data 1480 status_t status = gBufferModule->trim(buffer, packetLength); 1481 if (status != B_OK) 1482 return status; 1483 1484 // check for fragmentation 1485 uint16 fragmentHeaderOffset = header.GetHeaderOffset(buffer, IPPROTO_FRAGMENT); 1486 if (fragmentHeaderOffset != 0) { 1487 // this is a fragment 1488 TRACE(" ipv6_receive_data(): Found a Fragment!"); 1489 status = reassemble_fragments(header, &buffer, fragmentHeaderOffset); 1490 TRACE(" ipv6_receive_data(): -> %s", strerror(status)); 1491 if (status != B_OK) 1492 return status; 1493 1494 if (buffer == NULL) { 1495 // buffer was put into fragment packet 1496 TRACE(" ipv6_receive_data(): Not yet assembled."); 1497 return B_OK; 1498 } 1499 } 1500 1501 // tell the buffer to preserve removed ipv6 header - may need it later 1502 gBufferModule->store_header(buffer); 1503 1504 // remove ipv6 headers for now 1505 gBufferModule->remove_header(buffer, transportHeaderOffset); 1506 1507 // deliver the data to raw sockets 1508 raw_receive_data(buffer); 1509 1510 net_protocol_module_info* module = receiving_protocol(protocol); 1511 if (module == NULL) { 1512 // no handler for this packet 1513 return EAFNOSUPPORT; 1514 } 1515 1516 if ((buffer->flags & MSG_MCAST) != 0) { 1517 // Unfortunately historical reasons dictate that the IP multicast 1518 // model be a little different from the unicast one. We deliver 1519 // this frame directly to all sockets registered with interest 1520 // for this multicast group. 1521 return deliver_multicast(module, buffer, false); 1522 } 1523 1524 return module->receive_data(buffer); 1525 } 1526 1527 1528 status_t 1529 ipv6_deliver_data(net_protocol* _protocol, net_buffer* buffer) 1530 { 1531 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1532 1533 if (protocol->raw == NULL) 1534 return B_ERROR; 1535 1536 return protocol->raw->EnqueueClone(buffer); 1537 } 1538 1539 1540 status_t 1541 ipv6_error_received(net_error error, net_buffer* data) 1542 { 1543 return B_ERROR; 1544 } 1545 1546 1547 status_t 1548 ipv6_error_reply(net_protocol* protocol, net_buffer* cause, net_error error, 1549 net_error_data* errorData) 1550 { 1551 return B_ERROR; 1552 } 1553 1554 1555 ssize_t 1556 ipv6_process_ancillary_data_no_container(net_protocol* _protocol, 1557 net_buffer* buffer, void* msgControl, size_t msgControlLen) 1558 { 1559 ipv6_protocol* protocol = (ipv6_protocol*)_protocol; 1560 ssize_t bytesWritten = 0; 1561 1562 if (protocol->receive_hoplimit != 0) { 1563 TRACE("receive_hoplimit"); 1564 1565 if (msgControlLen < CMSG_SPACE(sizeof(int))) 1566 return B_NO_MEMORY; 1567 1568 // use some default value (64 at the moment) when extracting the real one fails 1569 int hopLimit = IPV6_DEFHLIM; 1570 1571 if (gBufferModule->stored_header_length(buffer) 1572 >= (int)sizeof(ip6_hdr)) { 1573 IPv6Header header; 1574 if (gBufferModule->restore_header(buffer, 0, 1575 &header, sizeof(ip6_hdr)) == B_OK 1576 && header.ProtocolVersion() != IPV6_VERSION) { 1577 // header is OK, take hoplimit from it 1578 hopLimit = header.header.ip6_hlim; 1579 } 1580 } 1581 1582 cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten); 1583 messageHeader->cmsg_len = CMSG_LEN(sizeof(int)); 1584 messageHeader->cmsg_level = IPPROTO_IPV6; 1585 messageHeader->cmsg_type = IPV6_HOPLIMIT; 1586 1587 memcpy(CMSG_DATA(messageHeader), &hopLimit, sizeof(int)); 1588 1589 bytesWritten += CMSG_SPACE(sizeof(int)); 1590 msgControlLen -= CMSG_SPACE(sizeof(int)); 1591 } 1592 1593 if (protocol->receive_pktinfo != 0) { 1594 TRACE("receive_pktinfo"); 1595 1596 if (msgControlLen < CMSG_SPACE(sizeof(struct in6_pktinfo))) 1597 return B_NO_MEMORY; 1598 1599 cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten); 1600 messageHeader->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1601 messageHeader->cmsg_level = IPPROTO_IPV6; 1602 messageHeader->cmsg_type = IPV6_PKTINFO; 1603 1604 struct in6_pktinfo pi; 1605 memcpy(&pi.ipi6_addr, 1606 &((struct sockaddr_in6*)buffer->destination)->sin6_addr, 1607 sizeof(struct in6_addr)); 1608 if (buffer->interface_address != NULL 1609 && buffer->interface_address->interface != NULL) 1610 pi.ipi6_ifindex = buffer->interface_address->interface->index; 1611 else 1612 pi.ipi6_ifindex = 0; 1613 memcpy(CMSG_DATA(messageHeader), &pi, sizeof(struct in6_pktinfo)); 1614 1615 bytesWritten += CMSG_SPACE(sizeof(struct in6_pktinfo)); 1616 msgControlLen -= CMSG_SPACE(sizeof(struct in6_pktinfo)); 1617 } 1618 1619 return bytesWritten; 1620 } 1621 1622 1623 // #pragma mark - 1624 1625 1626 status_t 1627 init_ipv6() 1628 { 1629 mutex_init(&sRawSocketsLock, "raw sockets"); 1630 mutex_init(&sMulticastGroupsLock, "IPv6 multicast groups"); 1631 mutex_init(&sReceivingProtocolLock, "IPv6 receiving protocols"); 1632 1633 status_t status; 1634 1635 sMulticastState = new MulticastState(); 1636 if (sMulticastState == NULL) { 1637 status = B_NO_MEMORY; 1638 goto err1; 1639 } 1640 1641 status = sMulticastState->Init(); 1642 if (status != B_OK) 1643 goto err2; 1644 1645 new (&sFragmentHash) FragmentTable(); 1646 status = sFragmentHash.Init(256); 1647 if (status != B_OK) 1648 goto err3; 1649 1650 new (&sRawSockets) RawSocketList; 1651 // static initializers do not work in the kernel, 1652 // so we have to do it here, manually 1653 // TODO: for modules, this shouldn't be required 1654 1655 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_RAW, 0, 1656 NET_IPV6_MODULE_NAME, NULL); 1657 if (status != B_OK) 1658 goto err3; 1659 1660 status = gStackModule->register_domain(AF_INET6, "internet6", &gIPv6Module, 1661 &gIPv6AddressModule, &sDomain); 1662 if (status != B_OK) 1663 goto err3; 1664 1665 TRACE("init_ipv6: OK"); 1666 return B_OK; 1667 1668 err3: 1669 sFragmentHash.~FragmentTable(); 1670 err2: 1671 delete sMulticastState; 1672 err1: 1673 mutex_destroy(&sReceivingProtocolLock); 1674 mutex_destroy(&sMulticastGroupsLock); 1675 mutex_destroy(&sRawSocketsLock); 1676 TRACE("init_ipv6: error %s", strerror(status)); 1677 return status; 1678 } 1679 1680 1681 status_t 1682 uninit_ipv6() 1683 { 1684 mutex_lock(&sReceivingProtocolLock); 1685 1686 // put all the domain receiving protocols we gathered so far 1687 for (uint32 i = 0; i < 256; i++) { 1688 if (sReceivingProtocol[i] != NULL) 1689 gStackModule->put_domain_receiving_protocol(sDomain, i); 1690 } 1691 1692 sFragmentHash.~FragmentTable(); 1693 delete sMulticastState; 1694 1695 gStackModule->unregister_domain(sDomain); 1696 mutex_unlock(&sReceivingProtocolLock); 1697 1698 mutex_destroy(&sMulticastGroupsLock); 1699 mutex_destroy(&sRawSocketsLock); 1700 mutex_destroy(&sReceivingProtocolLock); 1701 1702 return B_OK; 1703 } 1704 1705 1706 static status_t 1707 ipv6_std_ops(int32 op, ...) 1708 { 1709 switch (op) { 1710 case B_MODULE_INIT: 1711 return init_ipv6(); 1712 case B_MODULE_UNINIT: 1713 return uninit_ipv6(); 1714 default: 1715 return B_ERROR; 1716 } 1717 } 1718 1719 1720 net_protocol_module_info gIPv6Module = { 1721 { 1722 NET_IPV6_MODULE_NAME, 1723 0, 1724 ipv6_std_ops 1725 }, 1726 NET_PROTOCOL_ATOMIC_MESSAGES, 1727 1728 ipv6_init_protocol, 1729 ipv6_uninit_protocol, 1730 ipv6_open, 1731 ipv6_close, 1732 ipv6_free, 1733 ipv6_connect, 1734 ipv6_accept, 1735 ipv6_control, 1736 ipv6_getsockopt, 1737 ipv6_setsockopt, 1738 ipv6_bind, 1739 ipv6_unbind, 1740 ipv6_listen, 1741 ipv6_shutdown, 1742 ipv6_send_data, 1743 ipv6_send_routed_data, 1744 ipv6_send_avail, 1745 ipv6_read_data, 1746 ipv6_read_avail, 1747 ipv6_get_domain, 1748 ipv6_get_mtu, 1749 ipv6_receive_data, 1750 ipv6_deliver_data, 1751 ipv6_error_received, 1752 ipv6_error_reply, 1753 NULL, // add_ancillary_data() 1754 NULL, // process_ancillary_data() 1755 ipv6_process_ancillary_data_no_container, 1756 NULL, // send_data_no_buffer() 1757 NULL // read_data_no_buffer() 1758 }; 1759 1760 module_dependency module_dependencies[] = { 1761 {NET_STACK_MODULE_NAME, (module_info**)&gStackModule}, 1762 {NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule}, 1763 {NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule}, 1764 {NET_SOCKET_MODULE_NAME, (module_info**)&sSocketModule}, 1765 {} 1766 }; 1767 1768 module_info* modules[] = { 1769 (module_info*)&gIPv6Module, 1770 NULL 1771 }; 1772