xref: /haiku/src/add-ons/kernel/network/protocols/ipv6/ipv6.cpp (revision 481f986b59e7782458dcc5fe98ad59a57480e5db)
1 /*
2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  *		Atis Elsts, the.kfx@gmail.com
8  */
9 
10 
11 #include "ipv6_address.h"
12 #include "ipv6_utils.h"
13 #include "multicast.h"
14 #include "../../stack/domains.h"
15 
16 #include <net_datalink.h>
17 #include <net_datalink_protocol.h>
18 #include <net_device.h>
19 #include <net_protocol.h>
20 #include <net_stack.h>
21 #include <NetBufferUtilities.h>
22 #include <ProtocolUtilities.h>
23 
24 #include <ByteOrder.h>
25 #include <KernelExport.h>
26 #include <util/AutoLock.h>
27 #include <util/list.h>
28 #include <util/DoublyLinkedList.h>
29 #include <util/MultiHashTable.h>
30 
31 #include <netinet6/in6.h>
32 #include <netinet/ip6.h>
33 #include <netinet/icmp6.h>
34 #include <new>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <utility>
39 
40 
41 #define TRACE_IPV6
42 #ifdef TRACE_IPV6
43 #	define TRACE(format, args...) \
44 		dprintf("IPv6 [%llu] " format "\n", system_time() , ##args)
45 #	define TRACE_SK(protocol, format, args...) \
46 		dprintf("IPv6 [%llu] %p " format "\n", system_time(), \
47 			protocol , ##args)
48 #else
49 #	define TRACE(args...)		do { } while (0)
50 #	define TRACE_SK(args...)	do { } while (0)
51 #endif
52 
53 
54 struct IPv6Header {
55 	struct ip6_hdr header;
56 
57 	uint8 ProtocolVersion() const { return header.ip6_vfc & IPV6_VERSION_MASK; }
58 	uint8 ServiceType() const { return ntohl(header.ip6_flow) >> 20;}
59  	uint16 PayloadLength() const { return ntohs(header.ip6_plen); }
60 	const in6_addr& Dst() const { return header.ip6_dst; }
61 	const in6_addr& Src() const { return header.ip6_src; }
62 	uint16 GetTransportHeaderOffset(net_buffer* buffer) const;
63 };
64 
65 class RawSocket
66 	: public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
67 public:
68 							RawSocket(net_socket* socket);
69 };
70 
71 typedef DoublyLinkedList<RawSocket> RawSocketList;
72 
73 
74 typedef MulticastGroupInterface<IPv6Multicast> IPv6GroupInterface;
75 typedef MulticastFilter<IPv6Multicast> IPv6MulticastFilter;
76 
77 struct MulticastStateHash {
78 	typedef std::pair<const in6_addr*, uint32> KeyType;
79 	typedef IPv6GroupInterface ValueType;
80 
81 	size_t HashKey(const KeyType &key) const;
82 	size_t Hash(ValueType* value) const
83 		{ return HashKey(std::make_pair(&value->Address(),
84 			value->Interface()->index)); }
85 	bool Compare(const KeyType &key, ValueType* value) const
86 		{ return value->Interface()->index == key.second
87 			&& value->Address() == *key.first; }
88 	bool CompareValues(ValueType* value1, ValueType* value2) const
89 		{ return value1->Interface()->index == value2->Interface()->index
90 			&& value1->Address() == value2->Address(); }
91 	ValueType*& GetLink(ValueType* value) const { return value->HashLink(); }
92 };
93 
94 
95 struct ipv6_protocol : net_protocol {
96 	ipv6_protocol()
97 		:
98 		multicast_filter(this)
99 	{
100 	}
101 
102 	RawSocket	*raw;
103 	uint8		service_type;
104 	uint8		time_to_live;
105 	uint8		multicast_time_to_live;
106 	uint8		receive_hoplimit;
107 	uint8		receive_pktinfo;
108 	struct sockaddr* interface_address; // for IPV6_MULTICAST_IF
109 
110 	IPv6MulticastFilter multicast_filter;
111 };
112 
113 
114 static const int kDefaultTTL = 254;
115 static const int kDefaultMulticastTTL = 1;
116 
117 
118 extern net_protocol_module_info gIPv6Module;
119 	// we need this in ipv6_std_ops() for registering the AF_INET domain
120 
121 net_stack_module_info* gStackModule;
122 net_buffer_module_info* gBufferModule;
123 
124 static struct net_domain* sDomain;
125 static net_datalink_module_info* sDatalinkModule;
126 static net_socket_module_info* sSocketModule;
127 static RawSocketList sRawSockets;
128 static mutex sRawSocketsLock;
129 static mutex sMulticastGroupsLock;
130 
131 typedef MultiHashTable<MulticastStateHash> MulticastState;
132 static MulticastState* sMulticastState;
133 
134 static net_protocol_module_info* sReceivingProtocol[256];
135 static mutex sReceivingProtocolLock;
136 
137 
138 uint16
139 IPv6Header::GetTransportHeaderOffset(net_buffer* buffer) const
140 {
141 	uint16 offset = sizeof(struct ip6_hdr);
142 	uint8 next = header.ip6_nxt;
143 
144 	// these are the extension headers that might be supported one day
145 	while (next == IPPROTO_HOPOPTS
146 		|| next == IPPROTO_ROUTING
147 		|| next == IPPROTO_FRAGMENT
148 		|| next == IPPROTO_ESP
149 		|| next == IPPROTO_AH
150 		|| next == IPPROTO_DSTOPTS) {
151 		struct ip6_ext extensionHeader;
152 		status_t status = gBufferModule->read(buffer, offset,
153 			&extensionHeader, sizeof(ip6_ext));
154 		if (status != B_OK)
155 			break;
156 
157 		next = extensionHeader.ip6e_nxt;
158 		offset += extensionHeader.ip6e_len;
159 	}
160 
161 	buffer->protocol = next;
162 	return offset;
163 }
164 
165 
166 RawSocket::RawSocket(net_socket* socket)
167 	:
168 	DatagramSocket<>("ipv6 raw socket", socket)
169 {
170 }
171 
172 
173 size_t
174 MulticastStateHash::HashKey(const KeyType &key) const
175 {
176 	size_t result = 0;
177 	result = jenkins_hashword((const uint32*)&key.first,
178 		sizeof(in6_addr) / sizeof(uint32), result);
179 	result = jenkins_hashword(&key.second, 1, result);
180 	return result;
181 }
182 
183 
184 //	#pragma mark -
185 
186 
187 static inline void
188 dump_ipv6_header(IPv6Header &header)
189 {
190 #ifdef TRACE_IPV6
191 	char addrbuf[INET6_ADDRSTRLEN];
192 	dprintf("  version: %d\n", header.ProtocolVersion() >> 4);
193 	dprintf("  service_type: %d\n", header.ServiceType());
194 	dprintf("  payload_length: %d\n", header.PayloadLength());
195 	dprintf("  next_header: %d\n", header.header.ip6_nxt);
196 	dprintf("  hop_limit: %d\n", header.header.ip6_hops);
197 	dprintf("  source: %s\n", ip6_sprintf(&header.header.ip6_src, addrbuf));
198 	dprintf("  destination: %s\n",
199 		ip6_sprintf(&header.header.ip6_dst, addrbuf));
200 #endif
201 }
202 
203 
204 static status_t
205 deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
206  	bool deliverToRaw, net_interface *interface)
207 {
208 	sockaddr_in6* multicastAddr = (sockaddr_in6*)buffer->destination;
209 
210 	MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
211 		&multicastAddr->sin6_addr, interface->index));
212 
213 	while (it.HasNext()) {
214 		IPv6GroupInterface* state = it.Next();
215 		ipv6_protocol* ipproto = state->Parent()->Socket();
216 
217 		if (deliverToRaw && ipproto->raw == NULL)
218 			continue;
219 
220 		if (state->FilterAccepts(buffer)) {
221 			// TODO: do as in IPv4 code
222 			module->deliver_data(ipproto, buffer);
223 		}
224 	}
225 
226 	return B_OK;
227 }
228 
229 
230 static status_t
231 deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
232  	bool deliverToRaw)
233 {
234 	if (module->deliver_data == NULL)
235 		return B_OK;
236 
237 	MutexLocker _(sMulticastGroupsLock);
238 
239 	status_t status = B_OK;
240 	if (buffer->interface) {
241 		status = deliver_multicast(module, buffer, deliverToRaw,
242 			buffer->interface);
243 	} else {
244 		// REVIEWME: does this look ok?
245 		net_domain_private* domain = (net_domain_private*)sDomain;
246 		RecursiveLocker locker(domain->lock);
247 
248 		net_interface* interface = NULL;
249 		while (true) {
250 			interface = (net_interface*)list_get_next_item(
251 				&domain->interfaces, interface);
252 			if (interface == NULL)
253 				break;
254 
255 			status = deliver_multicast(module, buffer, deliverToRaw, interface);
256 			if (status < B_OK)
257 				break;
258 		}
259 	}
260 	return status;
261 }
262 
263 
264 static void
265 raw_receive_data(net_buffer* buffer)
266 {
267 	MutexLocker locker(sRawSocketsLock);
268 
269 	if (sRawSockets.IsEmpty())
270 		return;
271 
272 	TRACE("RawReceiveData(%i)", buffer->protocol);
273 
274 	if ((buffer->flags & MSG_MCAST) != 0) {
275 		deliver_multicast(&gIPv6Module, buffer, true);
276 	} else {
277 		RawSocketList::Iterator iterator = sRawSockets.GetIterator();
278 
279 		while (iterator.HasNext()) {
280 			RawSocket* raw = iterator.Next();
281 
282 			if (raw->Socket()->protocol == buffer->protocol)
283 				raw->SocketEnqueue(buffer);
284 		}
285 	}
286 }
287 
288 
289 static inline sockaddr*
290 fill_sockaddr_in6(sockaddr_in6* target, const in6_addr &address)
291 {
292 	target->sin6_family = AF_INET6;
293 	target->sin6_len = sizeof(sockaddr_in6);
294 	target->sin6_port = 0;
295 	target->sin6_flowinfo = 0;
296 	memcpy(target->sin6_addr.s6_addr, address.s6_addr, sizeof(in6_addr));
297 	target->sin6_scope_id = 0;
298 	return (sockaddr*)target;
299 }
300 
301 
302 status_t
303 IPv6Multicast::JoinGroup(IPv6GroupInterface* state)
304 {
305 	MutexLocker _(sMulticastGroupsLock);
306 
307 	sockaddr_in6 groupAddr;
308 	net_interface* interface = state->Interface();
309 
310 	status_t status = interface->first_info->join_multicast(
311 		interface->first_protocol,
312 		fill_sockaddr_in6(&groupAddr, state->Address()));
313 	if (status != B_OK)
314 		return status;
315 
316 	sMulticastState->Insert(state);
317 	return B_OK;
318 }
319 
320 
321 status_t
322 IPv6Multicast::LeaveGroup(IPv6GroupInterface* state)
323 {
324 	MutexLocker _(sMulticastGroupsLock);
325 
326 	sMulticastState->Remove(state);
327 
328 	sockaddr_in6 groupAddr;
329 	net_interface* interface = state->Interface();
330 
331 	return interface->first_protocol->module->join_multicast(
332 		interface->first_protocol,
333 		fill_sockaddr_in6(&groupAddr, state->Address()));
334 }
335 
336 
337 static net_protocol_module_info*
338 receiving_protocol(uint8 protocol)
339 {
340 	net_protocol_module_info* module = sReceivingProtocol[protocol];
341 	if (module != NULL)
342 		return module;
343 
344 	MutexLocker locker(sReceivingProtocolLock);
345 
346 	module = sReceivingProtocol[protocol];
347 	if (module != NULL)
348 		return module;
349 
350 	if (gStackModule->get_domain_receiving_protocol(sDomain, protocol,
351 			&module) == B_OK)
352 		sReceivingProtocol[protocol] = module;
353 
354 	return module;
355 }
356 
357 
358 static status_t
359 ipv6_delta_group(IPv6GroupInterface* group, int option,
360 	net_interface* interface, const in6_addr* sourceAddr)
361 {
362 	switch (option) {
363 		case IPV6_JOIN_GROUP:
364 			return group->Add();
365 		case IPV6_LEAVE_GROUP:
366 			return group->Drop();
367 	}
368 
369 	return B_ERROR;
370 }
371 
372 
373 static status_t
374 ipv6_delta_membership(ipv6_protocol* protocol, int option,
375 	net_interface* interface, const in6_addr* groupAddr,
376 	const in6_addr* sourceAddr)
377 {
378 	IPv6MulticastFilter &filter = protocol->multicast_filter;
379 	IPv6GroupInterface* state = NULL;
380 	status_t status = B_OK;
381 
382 	switch (option) {
383 		// TODO: support more options
384 		case IPV6_JOIN_GROUP:
385 			status = filter.GetState(*groupAddr, interface, state, true);
386 			break;
387 
388 		case IPV6_LEAVE_GROUP:
389 			filter.GetState(*groupAddr, interface, state, false);
390 			if (state == NULL)
391 				return EADDRNOTAVAIL;
392 			break;
393 	}
394 
395 	if (status != B_OK)
396 		return status;
397 
398 	status = ipv6_delta_group(state, option, interface, sourceAddr);
399 	filter.ReturnState(state);
400 	return status;
401 }
402 
403 
404 static status_t
405 ipv6_delta_membership(ipv6_protocol* protocol, int option,
406 	uint32 interfaceIndex, in6_addr* groupAddr, in6_addr* sourceAddr)
407 {
408 	net_interface* interface;
409 
410 	// TODO: can the interface be unspecified?
411 	interface = sDatalinkModule->get_interface(sDomain, interfaceIndex);
412 
413 	if (interface == NULL)
414 		return B_DEVICE_NOT_FOUND;
415 
416 	return ipv6_delta_membership(protocol, option, interface,
417 		groupAddr, sourceAddr);
418 }
419 
420 
421 static status_t
422 get_int_option(void* target, size_t length, int value)
423 {
424 	if (length != sizeof(int))
425 		return B_BAD_VALUE;
426 
427 	return user_memcpy(target, &value, sizeof(int));
428 }
429 
430 
431 template<typename Type> static status_t
432 set_int_option(Type &target, const void* _value, size_t length)
433 {
434 	int value;
435 
436 	if (length != sizeof(int))
437 		return B_BAD_VALUE;
438 
439 	if (user_memcpy(&value, _value, sizeof(int)) != B_OK)
440 		return B_BAD_ADDRESS;
441 
442 	target = value;
443 	return B_OK;
444 }
445 
446 
447 //	#pragma mark -
448 
449 
450 net_protocol*
451 ipv6_init_protocol(net_socket* socket)
452 {
453 	ipv6_protocol* protocol = new (std::nothrow) ipv6_protocol();
454 	if (protocol == NULL)
455 		return NULL;
456 
457 	protocol->raw = NULL;
458 	protocol->service_type = 0;
459 	protocol->time_to_live = kDefaultTTL;
460 	protocol->multicast_time_to_live = kDefaultMulticastTTL;
461 	protocol->receive_hoplimit = 0;
462 	protocol->receive_pktinfo = 0;
463 	protocol->interface_address = NULL;
464 	return protocol;
465 }
466 
467 
468 status_t
469 ipv6_uninit_protocol(net_protocol* _protocol)
470 {
471 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
472 
473 	delete protocol->raw;
474 	delete protocol->interface_address;
475 	delete protocol;
476 	return B_OK;
477 }
478 
479 
480 /*!	Since open() is only called on the top level protocol, when we get here
481 	it means we are on a SOCK_RAW socket.
482 */
483 status_t
484 ipv6_open(net_protocol* _protocol)
485 {
486 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
487 
488 	RawSocket* raw = new (std::nothrow) RawSocket(protocol->socket);
489 	if (raw == NULL)
490 		return B_NO_MEMORY;
491 
492 	status_t status = raw->InitCheck();
493 	if (status != B_OK) {
494 		delete raw;
495 		return status;
496 	}
497 
498 	TRACE_SK(protocol, "Open()");
499 
500 	protocol->raw = raw;
501 
502 	MutexLocker locker(sRawSocketsLock);
503 	sRawSockets.Add(raw);
504 	return B_OK;
505 }
506 
507 
508 status_t
509 ipv6_close(net_protocol* _protocol)
510 {
511 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
512 	RawSocket* raw = protocol->raw;
513 	if (raw == NULL)
514 		return B_ERROR;
515 
516 	TRACE_SK(protocol, "Close()");
517 
518 	MutexLocker locker(sRawSocketsLock);
519 	sRawSockets.Remove(raw);
520 	delete raw;
521 	protocol->raw = NULL;
522 
523 	return B_OK;
524 }
525 
526 
527 status_t
528 ipv6_free(net_protocol* protocol)
529 {
530 	return B_OK;
531 }
532 
533 
534 status_t
535 ipv6_connect(net_protocol* protocol, const struct sockaddr* address)
536 {
537 	return B_ERROR;
538 }
539 
540 
541 status_t
542 ipv6_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
543 {
544 	return EOPNOTSUPP;
545 }
546 
547 
548 status_t
549 ipv6_control(net_protocol* _protocol, int level, int option, void* value,
550 	size_t* _length)
551 {
552 	if ((level & LEVEL_MASK) != IPPROTO_IPV6)
553 		return sDatalinkModule->control(sDomain, option, value, _length);
554 
555 	return B_BAD_VALUE;
556 }
557 
558 
559 status_t
560 ipv6_getsockopt(net_protocol* _protocol, int level, int option, void* value,
561 	int* _length)
562 {
563 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
564 
565  	if (level == IPPROTO_IPV6) {
566 		// TODO: support more of these options
567 
568 		if (option == IPV6_MULTICAST_HOPS) {
569 			return get_int_option(value, *_length,
570 				protocol->multicast_time_to_live);
571 		}
572 		if (option == IPV6_MULTICAST_LOOP)
573 			return EOPNOTSUPP;
574 		if (option == IPV6_UNICAST_HOPS)
575 			return get_int_option(value, *_length, protocol->time_to_live);
576 		if (option == IPV6_V6ONLY)
577 			return EOPNOTSUPP;
578 		if (option == IPV6_RECVPKTINFO)
579 			return get_int_option(value, *_length, protocol->receive_pktinfo);
580 		if (option == IPV6_RECVHOPLIMIT)
581 			return get_int_option(value, *_length, protocol->receive_hoplimit);
582 		if (option == IPV6_JOIN_GROUP
583 			|| option == IPV6_LEAVE_GROUP)
584 			return EOPNOTSUPP;
585 
586 		dprintf("IPv6::getsockopt(): get unknown option: %d\n", option);
587 		return ENOPROTOOPT;
588 	}
589 
590 	return sSocketModule->get_option(protocol->socket, level, option, value,
591 		_length);
592 }
593 
594 
595 status_t
596 ipv6_setsockopt(net_protocol* _protocol, int level, int option,
597 	const void* value, int length)
598 {
599 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
600 
601  	if (level == IPPROTO_IPV6) {
602 		// TODO: support more of these options
603 
604 		if (option == IPV6_MULTICAST_IF) {
605 			if (length != sizeof(struct in6_addr))
606 				return B_BAD_VALUE;
607 
608 			struct sockaddr_in6* address = new (std::nothrow) sockaddr_in6;
609 			if (address == NULL)
610 				return B_NO_MEMORY;
611 
612 			if (user_memcpy(&address->sin6_addr, value, sizeof(in6_addr))
613 					!= B_OK) {
614 				delete address;
615 				return B_BAD_ADDRESS;
616 			}
617 
618 			// Using the unspecifed address to remove the previous setting.
619 			if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)) {
620 				delete address;
621 				delete protocol->interface_address;
622 				protocol->interface_address = NULL;
623 				return B_OK;
624 			}
625 
626 			struct net_interface* interface
627 				= sDatalinkModule->get_interface_with_address(sDomain,
628 					(struct sockaddr*)address);
629 			if (interface == NULL) {
630 				delete address;
631 				return EADDRNOTAVAIL;
632 			}
633 
634 			delete protocol->interface_address;
635 			protocol->interface_address = (struct sockaddr*)address;
636 			return B_OK;
637 		}
638 		if (option == IPV6_MULTICAST_HOPS) {
639 			return set_int_option(protocol->multicast_time_to_live,
640 				value, length);
641 		}
642 		if (option == IPV6_MULTICAST_LOOP)
643 			return EOPNOTSUPP;
644 		if (option == IPV6_UNICAST_HOPS)
645 			return set_int_option(protocol->time_to_live, value, length);
646 		if (option == IPV6_V6ONLY)
647 			return EOPNOTSUPP;
648 		if (option == IPV6_RECVPKTINFO)
649 			return set_int_option(protocol->receive_pktinfo, value, length);
650 		if (option == IPV6_RECVHOPLIMIT)
651 			return set_int_option(protocol->receive_hoplimit, value, length);
652 		if (option == IPV6_JOIN_GROUP || option == IPV6_LEAVE_GROUP) {
653 			ipv6_mreq mreq;
654 			if (length != sizeof(ipv6_mreq))
655 				return B_BAD_VALUE;
656 			if (user_memcpy(&mreq, value, sizeof(ipv6_mreq)) != B_OK)
657 				return B_BAD_ADDRESS;
658 
659 			return ipv6_delta_membership(protocol, option, mreq.ipv6mr_interface,
660 				&mreq.ipv6mr_multiaddr, NULL);
661 		}
662 
663 		dprintf("IPv6::setsockopt(): set unknown option: %d\n", option);
664 		return ENOPROTOOPT;
665 	}
666 
667 	return sSocketModule->set_option(protocol->socket, level, option,
668 		value, length);
669 }
670 
671 
672 status_t
673 ipv6_bind(net_protocol* protocol, const sockaddr* _address)
674 {
675 	if (_address->sa_family != AF_INET6)
676 		return EAFNOSUPPORT;
677 
678 	const sockaddr_in6* address = (const sockaddr_in6*)_address;
679 
680 	// only INADDR_ANY and addresses of local interfaces are accepted:
681 	if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)
682 		|| IN6_IS_ADDR_MULTICAST(&address->sin6_addr)
683  		|| sDatalinkModule->is_local_address(sDomain, _address, NULL, NULL)) {
684 		memcpy(&protocol->socket->address, address, sizeof(sockaddr_in6));
685 		protocol->socket->address.ss_len = sizeof(sockaddr_in6);
686 			// explicitly set length, as our callers can't be trusted to
687 			// always provide the correct length!
688 		return B_OK;
689 	}
690 
691 	return B_ERROR;
692 		// address is unknown on this host
693 }
694 
695 
696 status_t
697 ipv6_unbind(net_protocol* protocol, struct sockaddr* address)
698 {
699 	// nothing to do here
700 	return B_OK;
701 }
702 
703 
704 status_t
705 ipv6_listen(net_protocol* protocol, int count)
706 {
707 	return EOPNOTSUPP;
708 }
709 
710 
711 status_t
712 ipv6_shutdown(net_protocol* protocol, int direction)
713 {
714 	return EOPNOTSUPP;
715 }
716 
717 
718 static uint8
719 ip6_select_hoplimit(net_protocol* _protocol, net_buffer* buffer)
720 {
721 	// TODO: the precedence should be as follows:
722 	// 1. Hoplimit value specified via ioctl.
723 	// 2. (If the outgoing interface is detected) the current
724 	//     hop limit of the interface specified by router advertisement.
725 	// 3. The system default hoplimit.
726 
727 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
728 	const bool isMulticast = buffer->flags & MSG_MCAST;
729 
730 	if (protocol) {
731 		return isMulticast ? protocol->multicast_time_to_live
732 			: protocol->time_to_live;
733  	}
734 	return isMulticast ? kDefaultMulticastTTL : kDefaultTTL;
735 }
736 
737 
738 status_t
739 ipv6_send_routed_data(net_protocol* _protocol, struct net_route* route,
740 	net_buffer* buffer)
741 {
742 	if (route == NULL)
743 		return B_BAD_VALUE;
744 
745 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
746 	net_interface* interface = route->interface;
747 	uint8 protocolNumber;
748 	if (protocol != NULL && protocol->socket != NULL)
749 		protocolNumber = protocol->socket->protocol;
750 	else
751 		protocolNumber = buffer->protocol;
752 
753 	TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer,
754 		buffer->size);
755 
756 	sockaddr_in6& source = *(sockaddr_in6*)buffer->source;
757 	sockaddr_in6& destination = *(sockaddr_in6*)buffer->destination;
758 
759 	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
760 
761 	if (IN6_IS_ADDR_UNSPECIFIED(&destination.sin6_addr))
762 		return EDESTADDRREQ;
763 
764 	if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr))
765  		buffer->flags |= MSG_MCAST;
766 
767 	uint16 dataLength = buffer->size;
768 
769 	// Add IPv6 header
770 
771 	NetBufferPrepend<ip6_hdr> header(buffer);
772 	if (header.Status() != B_OK)
773 		return header.Status();
774 
775 	if (buffer->size > 0xffff)
776 		return EMSGSIZE;
777 
778 	uint32 flowinfo = 0;
779 		// TODO: fill in the flow id from somewhere
780 	if (protocol) {
781 		// fill in traffic class
782 		flowinfo |= htonl(protocol->service_type << 20);
783 	}
784 	// set lower 28 bits
785 	header->ip6_flow = htonl(flowinfo) & IPV6_FLOWINFO_MASK;
786 	// set upper 4 bits
787 	header->ip6_vfc |= IPV6_VERSION;
788 	header->ip6_plen = htons(dataLength);
789 	header->ip6_nxt = protocolNumber;
790 	header->ip6_hlim = ip6_select_hoplimit(protocol, buffer);
791 	memcpy(&header->ip6_src, &source.sin6_addr, sizeof(in6_addr));
792 	memcpy(&header->ip6_dst, &destination.sin6_addr, sizeof(in6_addr));
793 
794 	header.Sync();
795 
796 	// write the checksum for ICMPv6 sockets
797 	if (protocolNumber == IPPROTO_ICMPV6
798 		&& dataLength >= sizeof(struct icmp6_hdr)) {
799 		NetBufferField<uint16,
800 			sizeof(ip6_hdr) + offsetof(icmp6_hdr, icmp6_cksum)>
801 			icmpChecksum(buffer);
802 		// first make sure the existing checksum is zero
803 		*icmpChecksum = 0;
804 		icmpChecksum.Sync();
805 
806 		uint16 checksum = gBufferModule->checksum(buffer, sizeof(ip6_hdr),
807 			buffer->size - sizeof(ip6_hdr), false);
808 		checksum = ipv6_checksum(&header->ip6_src,
809 			&header->ip6_dst, dataLength, protocolNumber,
810 			checksum);
811 		*icmpChecksum = checksum;
812 	}
813 
814 	char addrbuf[INET6_ADDRSTRLEN];
815 	TRACE_SK(protocol, "  SendRoutedData(): destination: %s",
816 		ip6_sprintf(&destination.sin6_addr, addrbuf));
817 
818 	uint32 mtu = route->mtu ? route->mtu : interface->mtu;
819 	if (buffer->size > mtu) {
820 		// we need to fragment the packet
821 		return EMSGSIZE; // TODO
822 		//return send_fragments(protocol, route, buffer, mtu);
823 	}
824 
825 	return sDatalinkModule->send_data(route, buffer);
826 }
827 
828 
829 status_t
830 ipv6_send_data(net_protocol* _protocol, net_buffer* buffer)
831 {
832 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
833 
834 	TRACE_SK(protocol, "SendData(%p [%ld bytes])", buffer, buffer->size);
835 
836 	sockaddr_in6* destination = (sockaddr_in6*)buffer->destination;
837 
838 	// handle IPV6_MULTICAST_IF
839 	if (IN6_IS_ADDR_MULTICAST(&destination->sin6_addr)
840 			&& protocol->interface_address != NULL) {
841 		net_interface* interface
842 			= sDatalinkModule->get_interface_with_address(sDomain,
843 				protocol->interface_address);
844 		if (interface == NULL || (interface->flags & IFF_UP) == 0)
845 			return EADDRNOTAVAIL;
846 
847 		buffer->interface = interface;
848 
849 		net_route* route = sDatalinkModule->get_route(sDomain,
850 			interface->address);
851 		if (route == NULL)
852 			return ENETUNREACH;
853 
854 		return sDatalinkModule->send_data(route, buffer);
855 	}
856 
857 	return sDatalinkModule->send_datagram(protocol, sDomain, buffer);
858 }
859 
860 
861 ssize_t
862 ipv6_send_avail(net_protocol* protocol)
863 {
864 	return B_ERROR;
865 }
866 
867 
868 status_t
869 ipv6_read_data(net_protocol* _protocol, size_t numBytes, uint32 flags,
870 	net_buffer** _buffer)
871 {
872 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
873 	RawSocket* raw = protocol->raw;
874 	if (raw == NULL)
875 		return B_ERROR;
876 
877 	TRACE_SK(protocol, "ReadData(%lu, 0x%lx)", numBytes, flags);
878 
879 	return raw->SocketDequeue(flags, _buffer);
880 }
881 
882 
883 ssize_t
884 ipv6_read_avail(net_protocol* _protocol)
885 {
886 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
887 	RawSocket* raw = protocol->raw;
888 	if (raw == NULL)
889 		return B_ERROR;
890 
891 	return raw->AvailableData();
892 }
893 
894 
895 struct net_domain*
896 ipv6_get_domain(net_protocol* protocol)
897 {
898 	return sDomain;
899 }
900 
901 
902 size_t
903 ipv6_get_mtu(net_protocol* protocol, const struct sockaddr* address)
904 {
905 	net_route* route = sDatalinkModule->get_route(sDomain, address);
906 	if (route == NULL)
907 		return 0;
908 
909 	size_t mtu;
910 	if (route->mtu != 0)
911 		mtu = route->mtu;
912 	else
913 		mtu = route->interface->mtu;
914 
915 	sDatalinkModule->put_route(sDomain, route);
916 	// TODO: what about extension headers?
917 	// this function probably shoud be changed in calling places, not here
918 	return mtu - sizeof(ip6_hdr);
919 }
920 
921 
922 status_t
923 ipv6_receive_data(net_buffer* buffer)
924 {
925 	TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size);
926 
927 	NetBufferHeaderReader<IPv6Header> bufferHeader(buffer);
928 	if (bufferHeader.Status() != B_OK)
929 		return bufferHeader.Status();
930 
931 	IPv6Header &header = bufferHeader.Data();
932 	// dump_ipv6_header(header);
933 
934 	if (header.ProtocolVersion() != IPV6_VERSION)
935 		return B_BAD_TYPE;
936 
937 	uint16 packetLength = header.PayloadLength() + sizeof(ip6_hdr);
938 	if (packetLength > buffer->size)
939 		return B_BAD_DATA;
940 
941 	// lower layers notion of Broadcast or Multicast have no relevance to us
942 	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
943 
944 	sockaddr_in6 destination;
945 	fill_sockaddr_in6(&destination, header.Dst());
946 
947 	if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr)) {
948 		buffer->flags |= MSG_MCAST;
949 	} else {
950 		// test if the packet is really for us
951 		if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
952 				&buffer->interface, NULL)
953 			&& !sDatalinkModule->is_local_link_address(sDomain, true,
954 				buffer->destination, &buffer->interface)) {
955 			char srcbuf[INET6_ADDRSTRLEN];
956 			char dstbuf[INET6_ADDRSTRLEN];
957 			TRACE("  ReceiveData(): packet was not for us %s -> %s",
958 				ip6_sprintf(&header.Src(), srcbuf),
959 				ip6_sprintf(&header.Dst(), dstbuf));
960 			return B_ERROR;
961 		}
962 	}
963 
964 	// set net_buffer's source/destination address
965 	fill_sockaddr_in6((struct sockaddr_in6*)buffer->source, header.Src());
966 	memcpy(buffer->destination, &destination, sizeof(sockaddr_in6));
967 
968 	// get the transport protocol and transport header offset
969 	uint16 transportHeaderOffset = header.GetTransportHeaderOffset(buffer);
970 	uint8 protocol = buffer->protocol;
971 
972 	// remove any trailing/padding data
973 	status_t status = gBufferModule->trim(buffer, packetLength);
974 	if (status != B_OK)
975 		return status;
976 
977 	//
978 	// TODO: check for fragmentation
979 	//
980 
981 	// tell the buffer to preserve removed ipv6 header - may need it later
982 	gBufferModule->store_header(buffer);
983 
984 	TRACE("store_header for %p\n", buffer);
985 
986 	// remove ipv6 headers for now
987 	gBufferModule->remove_header(buffer, transportHeaderOffset);
988 
989 	// deliver the data to raw sockets
990 	raw_receive_data(buffer);
991 
992 	net_protocol_module_info* module = receiving_protocol(protocol);
993 	if (module == NULL) {
994 		// no handler for this packet
995 		return EAFNOSUPPORT;
996 	}
997 
998 	if ((buffer->flags & MSG_MCAST) != 0) {
999 		// Unfortunely historical reasons dictate that the IP multicast
1000 		// model be a little different from the unicast one. We deliver
1001 		// this frame directly to all sockets registered with interest
1002 		// for this multicast group.
1003 		return deliver_multicast(module, buffer, false);
1004 	}
1005 
1006 	return module->receive_data(buffer);
1007 }
1008 
1009 
1010 status_t
1011 ipv6_deliver_data(net_protocol* _protocol, net_buffer* buffer)
1012 {
1013 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
1014 
1015 	if (protocol->raw == NULL)
1016 		return B_ERROR;
1017 
1018 	return protocol->raw->SocketEnqueue(buffer);
1019 }
1020 
1021 
1022 status_t
1023 ipv6_error_received(net_error error, net_buffer* data)
1024 {
1025 	return B_ERROR;
1026 }
1027 
1028 
1029 status_t
1030 ipv6_error_reply(net_protocol* protocol, net_buffer* cause, net_error error,
1031 	net_error_data* errorData)
1032 {
1033 	return B_ERROR;
1034 }
1035 
1036 
1037 ssize_t
1038 ipv6_process_ancillary_data_no_container(net_protocol* _protocol,
1039 	net_buffer* buffer, void* msgControl, size_t msgControlLen)
1040 {
1041 	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
1042 	ssize_t bytesWritten = 0;
1043 
1044 	if (protocol->receive_hoplimit != 0) {
1045 		TRACE("receive_hoplimit");
1046 
1047 		if (msgControlLen < CMSG_SPACE(sizeof(int)))
1048 			return B_NO_MEMORY;
1049 
1050 		TRACE("restore_header for %p\n", buffer);
1051 
1052 		if (gBufferModule->stored_header_length(buffer)
1053 				< (int)sizeof(ip6_hdr))
1054 			return B_ERROR;
1055 
1056 		IPv6Header header;
1057 		if (gBufferModule->restore_header(buffer, 0, &header, sizeof(ip6_hdr))
1058 				!= B_OK)
1059 			return B_ERROR;
1060 
1061 		if (header.ProtocolVersion() != IPV6_VERSION)
1062 			return B_ERROR;
1063 
1064 		cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten);
1065 		messageHeader->cmsg_len = CMSG_LEN(sizeof(int));
1066 		messageHeader->cmsg_level = IPPROTO_IPV6;
1067 		messageHeader->cmsg_type = IPV6_HOPLIMIT;
1068 
1069 		int hoplimit = header.header.ip6_hlim;
1070 		memcpy(CMSG_DATA(messageHeader), &hoplimit, sizeof(int));
1071 
1072 		bytesWritten += CMSG_SPACE(sizeof(int));
1073 		msgControlLen -= CMSG_SPACE(sizeof(int));
1074 	}
1075 
1076 	if (protocol->receive_pktinfo != 0) {
1077 		TRACE("receive_pktinfo");
1078 
1079 		if (msgControlLen < CMSG_SPACE(sizeof(struct in6_pktinfo)))
1080 			return B_NO_MEMORY;
1081 
1082 		cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten);
1083 		messageHeader->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1084 		messageHeader->cmsg_level = IPPROTO_IPV6;
1085 		messageHeader->cmsg_type = IPV6_PKTINFO;
1086 
1087 		struct in6_pktinfo pi;
1088 		memcpy(&pi.ipi6_addr,
1089 			&((struct sockaddr_in6*)buffer->destination)->sin6_addr,
1090 		 	sizeof(struct in6_addr));
1091 		// REVIEWME: assume buffer->interface cannot be NULL
1092 		pi.ipi6_ifindex = buffer->interface->index;
1093 		memcpy(CMSG_DATA(messageHeader), &pi, sizeof(struct in6_pktinfo));
1094 
1095 		bytesWritten += CMSG_SPACE(sizeof(struct in6_pktinfo));
1096 		msgControlLen -= CMSG_SPACE(sizeof(struct in6_pktinfo));
1097 	}
1098 
1099 	return bytesWritten;
1100 }
1101 
1102 
1103 //	#pragma mark -
1104 
1105 
1106 status_t
1107 init_ipv6()
1108 {
1109 	mutex_init(&sRawSocketsLock, "raw sockets");
1110 	mutex_init(&sMulticastGroupsLock, "IPv6 multicast groups");
1111 	mutex_init(&sReceivingProtocolLock, "IPv6 receiving protocols");
1112 
1113 	status_t status;
1114 
1115 	sMulticastState = new MulticastState();
1116 	if (sMulticastState == NULL) {
1117 		status = B_NO_MEMORY;
1118 		goto err;
1119 	}
1120 
1121 	status = sMulticastState->Init();
1122 	if (status != B_OK)
1123 		goto err;
1124 
1125 	new (&sRawSockets) RawSocketList;
1126 		// static initializers do not work in the kernel,
1127 		// so we have to do it here, manually
1128 		// TODO: for modules, this shouldn't be required
1129 
1130 	status = gStackModule->register_domain_protocols(AF_INET6, SOCK_RAW, 0,
1131 		NET_IPV6_MODULE_NAME, NULL);
1132 	if (status != B_OK)
1133 		goto err;
1134 
1135 	status = gStackModule->register_domain(AF_INET6, "internet6", &gIPv6Module,
1136 		&gIPv6AddressModule, &sDomain);
1137 	if (status != B_OK)
1138 		goto err;
1139 
1140 	TRACE("init_ipv6: OK\n");
1141 	return B_OK;
1142 
1143 err:
1144 	delete sMulticastState;
1145 	mutex_destroy(&sReceivingProtocolLock);
1146 	mutex_destroy(&sMulticastGroupsLock);
1147 	mutex_destroy(&sRawSocketsLock);
1148 	TRACE("init_ipv6: error, status=%u\n", status);
1149 	return status;
1150 }
1151 
1152 
1153 status_t
1154 uninit_ipv6()
1155 {
1156 	mutex_lock(&sReceivingProtocolLock);
1157 
1158 	// put all the domain receiving protocols we gathered so far
1159 	for (uint32 i = 0; i < 256; i++) {
1160 		if (sReceivingProtocol[i] != NULL)
1161 			gStackModule->put_domain_receiving_protocol(sDomain, i);
1162 	}
1163 
1164 	delete sMulticastState;
1165 
1166 	gStackModule->unregister_domain(sDomain);
1167 	mutex_unlock(&sReceivingProtocolLock);
1168 
1169 	mutex_destroy(&sMulticastGroupsLock);
1170 	mutex_destroy(&sRawSocketsLock);
1171 	mutex_destroy(&sReceivingProtocolLock);
1172 
1173 	return B_OK;
1174 }
1175 
1176 
1177 static status_t
1178 ipv6_std_ops(int32 op, ...)
1179 {
1180 	switch (op) {
1181 		case B_MODULE_INIT:
1182 			return init_ipv6();
1183 		case B_MODULE_UNINIT:
1184 			return uninit_ipv6();
1185 		default:
1186 			return B_ERROR;
1187 	}
1188 }
1189 
1190 
1191 net_protocol_module_info gIPv6Module = {
1192 	{
1193 		NET_IPV6_MODULE_NAME,
1194 		0,
1195 		ipv6_std_ops
1196 	},
1197 	NET_PROTOCOL_ATOMIC_MESSAGES,
1198 
1199 	ipv6_init_protocol,
1200 	ipv6_uninit_protocol,
1201 	ipv6_open,
1202 	ipv6_close,
1203 	ipv6_free,
1204 	ipv6_connect,
1205 	ipv6_accept,
1206 	ipv6_control,
1207 	ipv6_getsockopt,
1208 	ipv6_setsockopt,
1209 	ipv6_bind,
1210 	ipv6_unbind,
1211 	ipv6_listen,
1212 	ipv6_shutdown,
1213 	ipv6_send_data,
1214 	ipv6_send_routed_data,
1215 	ipv6_send_avail,
1216 	ipv6_read_data,
1217 	ipv6_read_avail,
1218 	ipv6_get_domain,
1219 	ipv6_get_mtu,
1220 	ipv6_receive_data,
1221 	ipv6_deliver_data,
1222 	ipv6_error_received,
1223 	ipv6_error_reply,
1224 	NULL,		// add_ancillary_data()
1225 	NULL,		// process_ancillary_data()
1226 	ipv6_process_ancillary_data_no_container,
1227 	NULL,		// send_data_no_buffer()
1228 	NULL		// read_data_no_buffer()
1229 };
1230 
1231 module_dependency module_dependencies[] = {
1232 	{NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
1233 	{NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
1234 	{NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule},
1235 	{NET_SOCKET_MODULE_NAME, (module_info**)&sSocketModule},
1236 	{}
1237 };
1238 
1239 module_info* modules[] = {
1240 	(module_info*)&gIPv6Module,
1241 	NULL
1242 };
1243