xref: /haiku/src/add-ons/kernel/network/stack/datalink.cpp (revision da4dbfa47a47beb355289f3dd685797cee69ab77)
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  *		Hugo Santos, hugosantos@gmail.com
8  */
9 
10 
11 #include <net/if.h>
12 #include <net/if_dl.h>
13 #include <net/if_media.h>
14 #include <net/route.h>
15 #include <new>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/sockio.h>
20 
21 #include <ByteOrder.h>
22 #include <KernelExport.h>
23 
24 #include <net_datalink.h>
25 #include <net_device.h>
26 #include <NetBufferUtilities.h>
27 #include <NetUtilities.h>
28 
29 #include "device_interfaces.h"
30 #include "domains.h"
31 #include "ethernet.h"
32 #include "interfaces.h"
33 #include "routes.h"
34 #include "stack_private.h"
35 #include "utility.h"
36 
37 
38 //#define TRACE_DATALINK
39 #ifdef TRACE_DATALINK
40 #	define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
41 #else
42 #	define TRACE(x...) ;
43 #endif
44 
45 
46 struct datalink_protocol : net_protocol {
47 	struct net_domain_private* domain;
48 };
49 
50 struct interface_protocol : net_datalink_protocol {
51 	struct net_device_module_info* device_module;
52 	struct net_device* device;
53 };
54 
55 
56 #ifdef TRACE_DATALINK
57 
58 
59 static const char*
60 option_to_string(int32 option)
61 {
62 #	define CODE(x) case x: return #x;
63 	switch (option) {
64 		CODE(SIOCADDRT)			/* add route */
65 		CODE(SIOCDELRT)			/* delete route */
66 		CODE(SIOCSIFADDR)		/* set interface address */
67 		CODE(SIOCGIFADDR)		/* get interface address */
68 		CODE(SIOCSIFDSTADDR)	/* set point-to-point address */
69 		CODE(SIOCGIFDSTADDR)	/* get point-to-point address */
70 		CODE(SIOCSIFFLAGS)		/* set interface flags */
71 		CODE(SIOCGIFFLAGS)		/* get interface flags */
72 		CODE(SIOCGIFBRDADDR)	/* get broadcast address */
73 		CODE(SIOCSIFBRDADDR)	/* set broadcast address */
74 		CODE(SIOCGIFCOUNT)		/* count interfaces */
75 		CODE(SIOCGIFCONF)		/* get interface list */
76 		CODE(SIOCGIFINDEX)		/* interface name -> index */
77 		CODE(SIOCGIFNAME)		/* interface index -> name */
78 		CODE(SIOCGIFNETMASK)	/* get net address mask */
79 		CODE(SIOCSIFNETMASK)	/* set net address mask */
80 		CODE(SIOCGIFMETRIC)		/* get interface metric */
81 		CODE(SIOCSIFMETRIC)		/* set interface metric */
82 		CODE(SIOCDIFADDR)		/* delete interface address */
83 		CODE(SIOCAIFADDR)		/* configure interface alias */
84 		CODE(SIOCADDMULTI)		/* add multicast address */
85 		CODE(SIOCDELMULTI)		/* delete multicast address */
86 		CODE(SIOCGIFMTU)		/* get interface MTU */
87 		CODE(SIOCSIFMTU)		/* set interface MTU */
88 		CODE(SIOCSIFMEDIA)		/* set net media */
89 		CODE(SIOCGIFMEDIA)		/* get net media */
90 
91 		CODE(SIOCGRTSIZE)		/* get route table size */
92 		CODE(SIOCGRTTABLE)		/* get route table */
93 		CODE(SIOCGETRT)			/* get route information for destination */
94 
95 		CODE(SIOCGIFSTATS)		/* get interface stats */
96 		CODE(SIOCGIFTYPE)		/* get interface type */
97 
98 		CODE(SIOCSPACKETCAP)	/* Start capturing packets on an interface */
99 		CODE(SIOCCPACKETCAP)	/* Stop capturing packets on an interface */
100 
101 		CODE(SIOCSHIWAT)		/* set high watermark */
102 		CODE(SIOCGHIWAT)		/* get high watermark */
103 		CODE(SIOCSLOWAT)		/* set low watermark */
104 		CODE(SIOCGLOWAT)		/* get low watermark */
105 		CODE(SIOCATMARK)		/* at out-of-band mark? */
106 		CODE(SIOCSPGRP)			/* set process group */
107 		CODE(SIOCGPGRP)			/* get process group */
108 
109 		CODE(SIOCGPRIVATE_0)	/* device private 0 */
110 		CODE(SIOCGPRIVATE_1)	/* device private 1 */
111 		CODE(SIOCSDRVSPEC)		/* set driver-specific parameters */
112 		CODE(SIOCGDRVSPEC)		/* get driver-specific parameters */
113 
114 		CODE(SIOCSIFGENERIC)	/* generic IF set op */
115 		CODE(SIOCGIFGENERIC)	/* generic IF get op */
116 
117 		CODE(B_SOCKET_SET_ALIAS)		/* set interface alias, ifaliasreq */
118 		CODE(B_SOCKET_GET_ALIAS)		/* get interface alias, ifaliasreq */
119 		CODE(B_SOCKET_COUNT_ALIASES)	/* count interface aliases */
120 
121 		default:
122 			static char buffer[24];
123 			snprintf(buffer, sizeof(buffer), "%" B_PRId32, option);
124 			return buffer;
125 	}
126 #	undef CODE
127 }
128 
129 
130 #endif	// TRACE_DATALINK
131 
132 
133 static status_t
134 get_interface_name_or_index(net_domain* domain, int32 option, void* value,
135 	size_t* _length)
136 {
137 	ASSERT(option == SIOCGIFINDEX || option == SIOCGIFNAME);
138 
139 	size_t expected = option == SIOCGIFINDEX ? IF_NAMESIZE : sizeof(ifreq);
140 	if (*_length > 0 && *_length < expected)
141 		return B_BAD_VALUE;
142 
143 	ifreq request;
144 	memset(&request, 0, sizeof(request));
145 
146 	if (user_memcpy(&request, value, expected) < B_OK)
147 		return B_BAD_ADDRESS;
148 
149 	Interface* interface = NULL;
150 	if (option == SIOCGIFINDEX)
151 		interface = get_interface(domain, request.ifr_name);
152 	else
153 		interface = get_interface(domain, request.ifr_index);
154 
155 	if (interface == NULL)
156 		return B_BAD_VALUE;
157 
158 	if (option == SIOCGIFINDEX)
159 		request.ifr_index = interface->index;
160 	else
161 		strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
162 
163 	*_length = sizeof(ifreq);
164 	interface->ReleaseReference();
165 
166 	return user_memcpy(value, &request, sizeof(ifreq));
167 }
168 
169 
170 static void
171 set_interface_address(net_interface_address*& target, InterfaceAddress* address)
172 {
173 	if (target != NULL)
174 		static_cast<InterfaceAddress*>(target)->ReleaseReference();
175 
176 	target = address;
177 }
178 
179 
180 static status_t
181 fill_address(const sockaddr* from, sockaddr* to, size_t maxLength)
182 {
183 	if (from != NULL) {
184 		// Copy address over
185 		return user_memcpy(to, from, min_c(from->sa_len, maxLength));
186 	}
187 
188 	// Fill in empty address
189 	sockaddr empty;
190 	empty.sa_len = 2;
191 	empty.sa_family = AF_UNSPEC;
192 
193 	return user_memcpy(to, &empty, min_c(2, maxLength));
194 }
195 
196 
197 static void
198 update_device_send_stats(struct net_device* device, status_t status, size_t packetSize)
199 {
200 	if (status == B_OK) {
201 		atomic_add((int32*)&device->stats.send.packets, 1);
202 		atomic_add64((int64*)&device->stats.send.bytes, packetSize);
203 	} else {
204 		if (status == ENOBUFS || status == EMSGSIZE)
205 			atomic_add((int32*)&device->stats.send.dropped, 1);
206 		else
207 			atomic_add((int32*)&device->stats.send.errors, 1);
208 	}
209 }
210 
211 
212 //	#pragma mark - datalink module
213 
214 
215 static status_t
216 datalink_control(net_domain* _domain, int32 option, void* value,
217 	size_t* _length)
218 {
219 	TRACE("%s(domain %p, option %s, value %p, length %zu)\n", __FUNCTION__,
220 		_domain, option_to_string(option), value, *_length);
221 
222 	net_domain_private* domain = (net_domain_private*)_domain;
223 	if (domain == NULL || domain->family == AF_LINK) {
224 		// the AF_LINK family is already handled completely in the link protocol
225 		return B_BAD_VALUE;
226 	}
227 
228 	switch (option) {
229 		case SIOCGIFINDEX:
230 		case SIOCGIFNAME:
231 			return get_interface_name_or_index(domain, option, value, _length);
232 
233 		case SIOCAIFADDR:	/* same as B_SOCKET_ADD_ALIAS */
234 		{
235 			// add new interface address
236 			if (*_length > 0 && *_length < sizeof(struct ifaliasreq))
237 				return B_BAD_VALUE;
238 
239 			struct ifaliasreq request;
240 			if (user_memcpy(&request, value, sizeof(struct ifaliasreq)) != B_OK)
241 				return B_BAD_ADDRESS;
242 
243 			Interface* interface = get_interface(domain, request.ifra_name);
244 			if (interface != NULL) {
245 				// A new alias is added to this interface
246 				status_t status = add_interface_address(interface, domain,
247 					request);
248 				notify_interface_changed(interface);
249 				interface->ReleaseReference();
250 
251 				return status;
252 			}
253 
254 			// A new interface needs to be added
255 			net_device_interface* deviceInterface
256 				= get_device_interface(request.ifra_name);
257 			if (deviceInterface == NULL)
258 				return B_DEVICE_NOT_FOUND;
259 
260 			status_t status = add_interface(request.ifra_name, domain, request,
261 				deviceInterface);
262 
263 			put_device_interface(deviceInterface);
264 			return status;
265 		}
266 
267 		case SIOCDIFADDR:	/* same as B_SOCKET_REMOVE_ALIAS */
268 		{
269 			// remove interface (address)
270 			struct ifreq request;
271 			if (user_memcpy(&request, value, sizeof(struct ifreq)) != B_OK)
272 				return B_BAD_ADDRESS;
273 
274 			Interface* interface = get_interface(domain, request.ifr_name);
275 			if (interface == NULL)
276 				return B_BAD_VALUE;
277 
278 			status_t status = B_OK;
279 
280 			if (request.ifr_addr.sa_family != AF_UNSPEC
281 				&& request.ifr_addr.sa_len != 0) {
282 				status = interface->Control(domain, SIOCDIFADDR, request,
283 					(ifreq*)value, *_length);
284 			} else
285 				remove_interface(interface);
286 
287 			interface->ReleaseReference();
288 
289 			return status;
290 		}
291 
292 		case SIOCGIFCOUNT:
293 		{
294 			// count number of interfaces
295 			struct ifconf config;
296 			config.ifc_value = count_interfaces();
297 
298 			return user_memcpy(value, &config, sizeof(struct ifconf));
299 		}
300 
301 		case SIOCGIFCONF:
302 		{
303 			// retrieve ifreqs for all interfaces
304 			struct ifconf config;
305 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
306 				return B_BAD_ADDRESS;
307 
308 			size_t size = config.ifc_len;
309 			status_t status
310 				= list_interfaces(domain->family, config.ifc_buf, &size);
311 			if (status != B_OK)
312 				return status;
313 
314 			config.ifc_len = (int)size;
315 			return user_memcpy(value, &config, sizeof(struct ifconf));
316 		}
317 
318 		case SIOCGRTSIZE:
319 		{
320 			// determine size of buffer to hold the routing table
321 			struct ifconf config;
322 			config.ifc_value = route_table_size(domain);
323 
324 			return user_memcpy(value, &config, sizeof(struct ifconf));
325 		}
326 		case SIOCGRTTABLE:
327 		{
328 			// retrieve all routes for this domain
329 			struct ifconf config;
330 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
331 				return B_BAD_ADDRESS;
332 
333 			return list_routes(domain, config.ifc_buf, config.ifc_len);
334 		}
335 		case SIOCGETRT:
336 			return get_route_information(domain, value, *_length);
337 
338 		default:
339 		{
340 			// We also accept partial ifreqs as long as the name is complete.
341 			size_t length = sizeof(struct ifreq);
342 			if (*_length > 0 && *_length >= IF_NAMESIZE)
343 				length = min_c(length, *_length);
344 
345 			// try to pass the request to an existing interface
346 			struct ifreq request;
347 			if (user_memcpy(&request, value, length) != B_OK)
348 				return B_BAD_ADDRESS;
349 
350 			Interface* interface = get_interface(domain, request.ifr_name);
351 			if (interface == NULL)
352 				return B_BAD_VALUE;
353 
354 			status_t status = interface->Control(domain, option, request,
355 				(ifreq*)value, *_length);
356 
357 			interface->ReleaseReference();
358 			return status;
359 		}
360 	}
361 	return B_BAD_VALUE;
362 }
363 
364 
365 static status_t
366 datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
367 {
368 	TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer);
369 
370 	InterfaceAddress* address = (InterfaceAddress*)route->interface_address;
371 	Interface* interface = (Interface*)address->interface;
372 
373 	//dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
374 	//	buffer->size, interface->name, route->flags);
375 
376 	if ((route->flags & RTF_REJECT) != 0) {
377 		TRACE("  rejected route\n");
378 		return ENETUNREACH;
379 	}
380 
381 	if ((route->flags & RTF_HOST) != 0) {
382 		TRACE("  host route\n");
383 		// We set the interface address here, so the buffer is delivered
384 		// directly to the domain in interfaces.cpp:device_consumer_thread()
385 		address->AcquireReference();
386 		set_interface_address(buffer->interface_address, address);
387 	}
388 
389 	if ((route->flags & RTF_LOCAL) != 0) {
390 		TRACE("  local route\n");
391 
392 		// We set the interface address here, so the buffer is delivered
393 		// directly to the domain in interfaces.cpp:device_consumer_thread()
394 		address->AcquireReference();
395 		set_interface_address(buffer->interface_address, address);
396 
397 		if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) {
398 			{
399 				NetBufferPrepend<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer);
400 				if (bufferHeader.Status() != B_OK)
401 					return bufferHeader.Status();
402 
403 				ether_header &header = bufferHeader.Data();
404 				switch (buffer->interface_address->domain->family) {
405 					case AF_INET:
406 						header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IP);
407 						break;
408 					case AF_INET6:
409 						header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IPV6);
410 						break;
411 					default:
412 						header.type = 0;
413 						break;
414 				}
415 
416 				memset(header.source, 0, ETHER_ADDRESS_LENGTH);
417 				memset(header.destination, 0, ETHER_ADDRESS_LENGTH);
418 				bufferHeader.Sync();
419 			}
420 			device_interface_monitor_receive(interface->DeviceInterface(), buffer);
421 			{
422 				NetBufferHeaderRemover<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer);
423 				if (bufferHeader.Status() != B_OK)
424 					return bufferHeader.Status();
425 			}
426 		}
427 
428 		// this one goes back to the domain directly
429 		const size_t packetSize = buffer->size;
430 		status_t status = fifo_enqueue_buffer(
431 			&interface->DeviceInterface()->receive_queue, buffer);
432 		update_device_send_stats(interface->DeviceInterface()->device,
433 			status, packetSize);
434 		return status;
435 	}
436 
437 	if ((route->flags & RTF_GATEWAY) != 0) {
438 		TRACE("  gateway route\n");
439 
440 		// This route involves a gateway, we need to use the gateway address
441 		// instead of the destination address:
442 		if (route->gateway == NULL)
443 			return B_MISMATCHED_VALUES;
444 		memcpy(buffer->destination, route->gateway, route->gateway->sa_len);
445 	}
446 
447 	// this goes out to the datalink protocols
448 	domain_datalink* datalink
449 		= interface->DomainDatalink(address->domain->family);
450 	return datalink->first_info->send_data(datalink->first_protocol, buffer);
451 }
452 
453 
454 /*!	Finds a route for the given \a buffer in the given \a domain, and calls
455 	net_protocol_info::send_routed_data() on either the \a protocol (if
456 	non-NULL), or the domain.
457 */
458 static status_t
459 datalink_send_data(net_protocol* protocol, net_domain* domain,
460 	net_buffer* buffer)
461 {
462 	TRACE("%s(%p, domain %p, buffer %p)\n", __FUNCTION__, protocol, domain,
463 		buffer);
464 
465 	if (protocol == NULL && domain == NULL)
466 		return B_BAD_VALUE;
467 
468 	net_protocol_module_info* module = protocol != NULL
469 		? protocol->module : domain->module;
470 
471 	if (domain == NULL)
472 		domain = protocol->module->get_domain(protocol);
473 
474 	net_route* route = NULL;
475 	status_t status;
476 	if (protocol != NULL && protocol->socket != NULL
477 		&& protocol->socket->bound_to_device != 0) {
478 		status = get_device_route(domain, protocol->socket->bound_to_device,
479 			&route);
480 	} else
481 		status = get_buffer_route(domain, buffer, &route);
482 
483 	TRACE("  route status: %s\n", strerror(status));
484 
485 	if (status != B_OK)
486 		return status;
487 
488 	status = module->send_routed_data(protocol, route, buffer);
489 	put_route(domain, route);
490 	return status;
491 }
492 
493 
494 /*!	Tests if \a address is a local address in the domain.
495 
496 	\param _interfaceAddress will be set to the interface address belonging to
497 		that address if non-NULL. If the address \a _interfaceAddress points to
498 		is not NULL, it is assumed that it already points to an address, which
499 		is then released before the new address is assigned.
500 	\param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
501 */
502 static bool
503 datalink_is_local_address(net_domain* domain, const struct sockaddr* address,
504 	net_interface_address** _interfaceAddress, uint32* _matchedType)
505 {
506 	TRACE("%s(domain %p, address %s)\n", __FUNCTION__, domain,
507 		AddressString(domain, address).Data());
508 
509 	if (domain == NULL || address == NULL
510 		|| domain->family != address->sa_family)
511 		return false;
512 
513 	uint32 matchedType = 0;
514 
515 	InterfaceAddress* interfaceAddress = get_interface_address(address);
516 	if (interfaceAddress == NULL) {
517 		// Check for matching broadcast address
518 		if ((domain->address_module->flags
519 				& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
520 			interfaceAddress
521 				= get_interface_address_for_destination(domain, address);
522 			matchedType = MSG_BCAST;
523 		}
524 		if (interfaceAddress == NULL) {
525 			TRACE("  no\n");
526 			return false;
527 		}
528 	}
529 
530 	TRACE("  it is, interface address %p\n", interfaceAddress);
531 
532 	if (_interfaceAddress != NULL)
533 		set_interface_address(*_interfaceAddress, interfaceAddress);
534 	else
535 		interfaceAddress->ReleaseReference();
536 
537 	if (_matchedType != NULL)
538 		*_matchedType = matchedType;
539 
540 	return true;
541 }
542 
543 
544 /*!	Tests if \a address is a local link address in the domain.
545 
546 	\param unconfiguredOnly only unconfigured interfaces are taken into account.
547 	\param _interfaceAddress will be set to the first address of the interface
548 		and domain belonging to that address if non-NULL. If the address
549 		\a _interfaceAddress points to is not NULL, it is assumed that it
550 		already points to an address, which is then released before the new
551 		address is assigned.
552 */
553 static bool
554 datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly,
555 	const struct sockaddr* address, net_interface_address** _interfaceAddress)
556 {
557 	if (domain == NULL || address == NULL || address->sa_family != AF_LINK)
558 		return false;
559 
560 #ifdef TRACE_DATALINK
561 	uint8* data = LLADDR((sockaddr_dl*)address);
562 	TRACE("%s(domain %p, unconfiguredOnly %d, address %02x:%02x:%02x:%02x:%02x"
563 		":%02x)\n", __FUNCTION__, domain, unconfiguredOnly, data[0], data[1],
564 		data[2], data[3], data[4], data[5]);
565 #endif
566 
567 	InterfaceAddress* interfaceAddress = get_interface_address_for_link(domain,
568 		address, unconfiguredOnly);
569 	if (interfaceAddress == NULL) {
570 		TRACE("  no\n");
571 		return false;
572 	}
573 
574 	if (_interfaceAddress != NULL)
575 		set_interface_address(*_interfaceAddress, interfaceAddress);
576 	else
577 		interfaceAddress->ReleaseReference();
578 
579 	return true;
580 }
581 
582 
583 static net_interface*
584 datalink_get_interface(net_domain* domain, uint32 index)
585 {
586 	return get_interface(domain, index);
587 }
588 
589 
590 static net_interface*
591 datalink_get_interface_with_address(const sockaddr* address)
592 {
593 	InterfaceAddress* interfaceAddress = get_interface_address(address);
594 	if (interfaceAddress == NULL)
595 		return NULL;
596 
597 	Interface* interface = static_cast<Interface*>(interfaceAddress->interface);
598 
599 	interface->AcquireReference();
600 	interfaceAddress->ReleaseReference();
601 
602 	return interface;
603 }
604 
605 
606 static void
607 datalink_put_interface(net_interface* interface)
608 {
609 	if (interface == NULL)
610 		return;
611 
612 	((Interface*)interface)->ReleaseReference();
613 }
614 
615 
616 static net_interface_address*
617 datalink_get_interface_address(const struct sockaddr* address)
618 {
619 	return get_interface_address(address);
620 }
621 
622 
623 /*!	Returns a reference to the next address of the given interface in
624 	\a _address. When you call this function the first time, \a _address must
625 	point to a NULL address. Upon the next call, the reference to the previous
626 	address is taken over again.
627 
628 	If you do not traverse the list to the end, you'll have to manually release
629 	the reference to the address where you stopped.
630 
631 	\param interface The interface whose address list should be iterated over.
632 	\param _address A pointer to the location where the next address should
633 		be stored.
634 
635 	\return \c true if an address reference was returned, \c false if not.
636 */
637 static bool
638 datalink_get_next_interface_address(net_interface* _interface,
639 	net_interface_address** _address)
640 {
641 	Interface* interface = (Interface*)_interface;
642 
643 	InterfaceAddress* address = (InterfaceAddress*)*_address;
644 	bool gotOne = interface->GetNextAddress(&address);
645 	*_address = address;
646 
647 	return gotOne;
648 }
649 
650 
651 static void
652 datalink_put_interface_address(net_interface_address* address)
653 {
654 	if (address == NULL)
655 		return;
656 
657 	((InterfaceAddress*)address)->ReleaseReference();
658 }
659 
660 
661 static status_t
662 datalink_join_multicast(net_interface* _interface, net_domain* domain,
663 	const struct sockaddr* address)
664 {
665 	Interface* interface = (Interface*)_interface;
666 	domain_datalink* datalink = interface->DomainDatalink(domain->family);
667 
668 	return datalink->first_info->join_multicast(datalink->first_protocol,
669 		address);
670 }
671 
672 
673 static status_t
674 datalink_leave_multicast(net_interface* _interface, net_domain* domain,
675 	const struct sockaddr* address)
676 {
677 	Interface* interface = (Interface*)_interface;
678 	domain_datalink* datalink = interface->DomainDatalink(domain->family);
679 
680 	return datalink->first_info->leave_multicast(datalink->first_protocol,
681 		address);
682 }
683 
684 
685 static status_t
686 datalink_std_ops(int32 op, ...)
687 {
688 	switch (op) {
689 		case B_MODULE_INIT:
690 		case B_MODULE_UNINIT:
691 			return B_OK;
692 
693 		default:
694 			return B_ERROR;
695 	}
696 }
697 
698 
699 //	#pragma mark - net_datalink_protocol
700 
701 
702 static status_t
703 interface_protocol_init(net_interface* interface, net_domain* domain,
704 	net_datalink_protocol** _protocol)
705 {
706 	interface_protocol* protocol = new(std::nothrow) interface_protocol;
707 	if (protocol == NULL)
708 		return B_NO_MEMORY;
709 
710 	TRACE("%s(%p, interface %p - %s, domain %p)\n", __FUNCTION__, protocol,
711 		interface, interface->name, domain);
712 
713 	protocol->device_module = interface->device->module;
714 	protocol->device = interface->device;
715 
716 	*_protocol = protocol;
717 	return B_OK;
718 }
719 
720 
721 static status_t
722 interface_protocol_uninit(net_datalink_protocol* protocol)
723 {
724 	TRACE("%s(%p)\n", __FUNCTION__, protocol);
725 
726 	delete protocol;
727 	return B_OK;
728 }
729 
730 
731 static status_t
732 interface_protocol_send_data(net_datalink_protocol* _protocol,
733 	net_buffer* buffer)
734 {
735 	TRACE("%s(%p, buffer %p)\n", __FUNCTION__, _protocol, buffer);
736 
737 	interface_protocol* protocol = (interface_protocol*)_protocol;
738 	Interface* interface = (Interface*)protocol->interface;
739 
740 	if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0)
741 		device_interface_monitor_receive(interface->DeviceInterface(), buffer);
742 
743 	const size_t packetSize = buffer->size;
744 	status_t status = protocol->device_module->send_data(protocol->device, buffer);
745 	update_device_send_stats(protocol->device, status, packetSize);
746 	return status;
747 }
748 
749 
750 static status_t
751 interface_protocol_up(net_datalink_protocol* protocol)
752 {
753 	TRACE("%s(%p)\n", __FUNCTION__, protocol);
754 	return B_OK;
755 }
756 
757 
758 static void
759 interface_protocol_down(net_datalink_protocol* _protocol)
760 {
761 	TRACE("%s(%p)\n", __FUNCTION__, _protocol);
762 
763 	interface_protocol* protocol = (interface_protocol*)_protocol;
764 	Interface* interface = (Interface*)protocol->interface;
765 	net_device_interface* deviceInterface = interface->DeviceInterface();
766 
767 	if (deviceInterface->up_count == 0)
768 		return;
769 
770 	deviceInterface->up_count--;
771 
772 	interface->WentDown();
773 
774 	if (deviceInterface->up_count > 0)
775 		return;
776 
777 	down_device_interface(deviceInterface);
778 }
779 
780 
781 static status_t
782 interface_protocol_change_address(net_datalink_protocol* protocol,
783 	net_interface_address* interfaceAddress, int32 option,
784 	const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
785 {
786 	TRACE("%s(%p, interface address %p, option %s, old %p, new %p)\n",
787 		__FUNCTION__, protocol, interfaceAddress, option_to_string(option),
788 		oldAddress, newAddress);
789 
790 	switch (option) {
791 		case SIOCSIFADDR:
792 		case SIOCSIFNETMASK:
793 		case SIOCSIFBRDADDR:
794 		case SIOCSIFDSTADDR:
795 		case SIOCDIFADDR:
796 			return update_interface_address((InterfaceAddress*)interfaceAddress,
797 				option, oldAddress, newAddress);
798 	}
799 
800 	return B_OK;
801 }
802 
803 
804 static status_t
805 interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
806 	void* argument, size_t length)
807 {
808 	TRACE("%s(%p, option %s, argument %p, length %zu)\n", __FUNCTION__,
809 		_protocol, option_to_string(option), argument, length);
810 
811 	interface_protocol* protocol = (interface_protocol*)_protocol;
812 	Interface* interface = (Interface*)protocol->interface;
813 
814 	switch (option) {
815 		case SIOCGIFADDR:
816 		case SIOCGIFNETMASK:
817 		case SIOCGIFBRDADDR:
818 		case SIOCGIFDSTADDR:
819 		{
820 			if (length == 0)
821 				length = sizeof(ifreq);
822 			else if (length < sizeof(ifreq))
823 				return B_BAD_VALUE;
824 
825 			ifreq request;
826 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
827 				return B_BAD_ADDRESS;
828 
829 			InterfaceAddress* interfaceAddress
830 				= get_interface_address(&request.ifr_addr);
831 			if (interfaceAddress == NULL) {
832 				interfaceAddress
833 					= interface->FirstForFamily(protocol->domain->family);
834 				if (interfaceAddress == NULL)
835 					return B_BAD_VALUE;
836 			}
837 
838 			size_t maxLength = length - offsetof(ifreq, ifr_addr);
839 
840 			status_t status = fill_address(
841 				*interfaceAddress->AddressFor(option),
842 				&((struct ifreq*)argument)->ifr_addr, maxLength);
843 
844 			interfaceAddress->ReleaseReference();
845 			return status;
846 		}
847 
848 		case B_SOCKET_COUNT_ALIASES:
849 		{
850 			ifreq request;
851 			request.ifr_count = interface->CountAddresses();
852 
853 			return user_memcpy(&((struct ifreq*)argument)->ifr_count,
854 				&request.ifr_count, sizeof(request.ifr_count));
855 		}
856 
857 		case B_SOCKET_GET_ALIAS:
858 		{
859 			ifaliasreq request;
860 			if (user_memcpy(&request, argument, sizeof(ifaliasreq)) != B_OK)
861 				return B_BAD_ADDRESS;
862 
863 			InterfaceAddress* address = NULL;
864 			if (request.ifra_index < 0) {
865 				if (!protocol->domain->address_module->is_empty_address(
866 						(const sockaddr*)&request.ifra_addr, false)) {
867 					// Find first address that matches the local address
868 					address = interface->AddressForLocal(protocol->domain,
869 						(const sockaddr*)&request.ifra_addr);
870 				} else {
871 					// Find first address for family
872 					address = interface->FirstForFamily(
873 						protocol->domain->family);
874 				}
875 
876 				request.ifra_index = interface->IndexOfAddress(address);
877 			} else
878 				address = interface->AddressAt(request.ifra_index);
879 			if (address == NULL)
880 				return B_BAD_VALUE;
881 
882 			// Copy index (in case none was specified)
883 			status_t status = user_memcpy(
884 				&((struct ifaliasreq*)argument)->ifra_index,
885 				&request.ifra_index, sizeof(request.ifra_index));
886 
887 			// Copy address info
888 			if (status == B_OK) {
889 				status = fill_address(address->local,
890 					(sockaddr*)&((struct ifaliasreq*)argument)->ifra_addr,
891 					sizeof(sockaddr_storage));
892 			}
893 			if (status == B_OK) {
894 				status = fill_address(address->mask,
895 					(sockaddr*)&((struct ifaliasreq*)argument)->ifra_mask,
896 					sizeof(sockaddr_storage));
897 			}
898 			if (status == B_OK) {
899 				status = fill_address(address->destination,
900 					(sockaddr*)&((struct ifaliasreq*)argument)
901 						->ifra_destination,
902 					sizeof(sockaddr_storage));
903 			}
904 
905 			address->ReleaseReference();
906 
907 			return status;
908 		}
909 
910 		case SIOCGIFFLAGS:
911 		{
912 			// get flags
913 			struct ifreq request;
914 			request.ifr_flags = interface->flags | interface->device->flags;
915 
916 			return user_memcpy(&((struct ifreq*)argument)->ifr_flags,
917 				&request.ifr_flags, sizeof(request.ifr_flags));
918 		}
919 
920 		case SIOCGIFSTATS:
921 		{
922 			// get stats
923 			return user_memcpy(&((struct ifreq*)argument)->ifr_stats,
924 				&interface->DeviceInterface()->device->stats,
925 				sizeof(struct ifreq_stats));
926 		}
927 
928 		case SIOCGIFTYPE:
929 		{
930 			// get type
931 			struct ifreq request;
932 			request.ifr_type = interface->type;
933 
934 			return user_memcpy(&((struct ifreq*)argument)->ifr_type,
935 				&request.ifr_type, sizeof(request.ifr_type));
936 		}
937 
938 		case SIOCGIFMTU:
939 		{
940 			// get MTU
941 			struct ifreq request;
942 			request.ifr_mtu = interface->device->mtu;
943 
944 			return user_memcpy(&((struct ifreq*)argument)->ifr_mtu,
945 				&request.ifr_mtu, sizeof(request.ifr_mtu));
946 		}
947 		case SIOCSIFMTU:
948 		{
949 			// set MTU
950 			struct ifreq request;
951 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
952 				return B_BAD_ADDRESS;
953 
954 			status_t status = interface->device->module->set_mtu(
955 				interface->device, request.ifr_mtu);
956 			if (status == B_OK)
957 				notify_interface_changed(interface);
958 			return status;
959 		}
960 
961 		case SIOCSIFMEDIA:
962 		{
963 			// set media
964 			struct ifreq request;
965 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
966 				return B_BAD_ADDRESS;
967 
968 			status_t status
969 				= interface->device->module->set_media(
970 					interface->device, request.ifr_media);
971 			if (status == B_NOT_SUPPORTED) {
972 				// TODO: this isn't so nice, and should be solved differently
973 				// (for example by removing the set_media() call altogether, or
974 				// making it able to deal properly with FreeBSD drivers as well)
975 				// try driver directly
976 				status = interface->device->module->control(
977 					interface->device, SIOCSIFMEDIA, &request, sizeof(request));
978 			}
979 
980 			return status;
981 		}
982 		case SIOCGIFMEDIA:
983 		{
984 			// get media
985 			const size_t copylen = offsetof(ifreq, ifr_media) + sizeof(ifreq::ifr_media);
986 			if (length > 0 && length < copylen)
987 				return B_BAD_VALUE;
988 
989 			struct ifreq request;
990 			if (user_memcpy(&request, argument, copylen) != B_OK)
991 				return B_BAD_ADDRESS;
992 
993 			request.ifr_media = interface->device->media;
994 			return user_memcpy(argument, &request, copylen);
995 		}
996 
997 		case SIOCGIFMETRIC:
998 		{
999 			// get metric
1000 			struct ifreq request;
1001 			request.ifr_metric = interface->metric;
1002 
1003 			return user_memcpy(&((struct ifreq*)argument)->ifr_metric,
1004 				&request.ifr_metric, sizeof(request.ifr_metric));
1005 		}
1006 		case SIOCSIFMETRIC:
1007 		{
1008 			// set metric
1009 			struct ifreq request;
1010 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
1011 				return B_BAD_ADDRESS;
1012 
1013 			interface->metric = request.ifr_metric;
1014 			notify_interface_changed(interface);
1015 			return B_OK;
1016 		}
1017 
1018 		case SIOCADDRT:
1019 		case SIOCDELRT:
1020 			// interface related route options
1021 			return control_routes(interface, protocol->domain, option, argument,
1022 				length);
1023 	}
1024 
1025 	return protocol->device_module->control(protocol->device,
1026 		option, argument, length);
1027 }
1028 
1029 
1030 static status_t
1031 interface_protocol_join_multicast(net_datalink_protocol* _protocol,
1032 	const sockaddr* address)
1033 {
1034 	interface_protocol* protocol = (interface_protocol*)_protocol;
1035 
1036 	return protocol->device_module->add_multicast(protocol->device, address);
1037 }
1038 
1039 
1040 static status_t
1041 interface_protocol_leave_multicast(net_datalink_protocol* _protocol,
1042 	const sockaddr* address)
1043 {
1044 	interface_protocol* protocol = (interface_protocol*)_protocol;
1045 
1046 	return protocol->device_module->remove_multicast(protocol->device,
1047 		address);
1048 }
1049 
1050 
1051 net_datalink_module_info gNetDatalinkModule = {
1052 	{
1053 		NET_DATALINK_MODULE_NAME,
1054 		0,
1055 		datalink_std_ops
1056 	},
1057 
1058 	datalink_control,
1059 	datalink_send_routed_data,
1060 	datalink_send_data,
1061 
1062 	datalink_is_local_address,
1063 	datalink_is_local_link_address,
1064 
1065 	datalink_get_interface,
1066 	datalink_get_interface_with_address,
1067 	datalink_put_interface,
1068 
1069 	datalink_get_interface_address,
1070 	datalink_get_next_interface_address,
1071 	datalink_put_interface_address,
1072 
1073 	datalink_join_multicast,
1074 	datalink_leave_multicast,
1075 
1076 	add_route,
1077 	remove_route,
1078 	get_route,
1079 	get_buffer_route,
1080 	put_route,
1081 	register_route_info,
1082 	unregister_route_info,
1083 	update_route_info
1084 };
1085 
1086 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
1087 	{
1088 		NULL,
1089 		0,
1090 		NULL
1091 	},
1092 	interface_protocol_init,
1093 	interface_protocol_uninit,
1094 	interface_protocol_send_data,
1095 	interface_protocol_up,
1096 	interface_protocol_down,
1097 	interface_protocol_change_address,
1098 	interface_protocol_control,
1099 	interface_protocol_join_multicast,
1100 	interface_protocol_leave_multicast,
1101 };
1102