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