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