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