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