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