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