xref: /haiku/src/add-ons/kernel/network/stack/datalink.cpp (revision 2222d0559df303a9846a2fad53741f8b20b14d7c)
1 /*
2  * Copyright 2006-2009, 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 "datalink.h"
12 #include "domains.h"
13 #include "interfaces.h"
14 #include "routes.h"
15 #include "stack_private.h"
16 #include "utility.h"
17 
18 #include <net_device.h>
19 #include <KernelExport.h>
20 #include <util/AutoLock.h>
21 
22 #include <net/if.h>
23 #include <net/if_media.h>
24 #include <net/route.h>
25 #include <sys/sockio.h>
26 
27 #include <new>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 
32 
33 struct datalink_protocol : net_protocol {
34 	struct net_domain_private* domain;
35 };
36 
37 struct interface_protocol : net_datalink_protocol {
38 	struct net_device_module_info* device_module;
39 	struct net_device* device;
40 };
41 
42 
43 /*!	A service thread for each device interface. It just reads as many packets
44 	as availabe, deframes them, and puts them into the receive queue of the
45 	device interface.
46 */
47 static status_t
48 device_reader_thread(void* _interface)
49 {
50 	net_device_interface* interface = (net_device_interface*)_interface;
51 	net_device* device = interface->device;
52 	status_t status = B_OK;
53 
54 	RecursiveLocker locker(interface->receive_lock);
55 
56 	while ((device->flags & IFF_UP) != 0) {
57 		locker.Unlock();
58 
59 		net_buffer* buffer;
60 		status = device->module->receive_data(device, &buffer);
61 
62 		locker.Lock();
63 
64 		if (status == B_OK) {
65 			// feed device monitors
66 			DeviceMonitorList::Iterator iterator =
67 				interface->monitor_funcs.GetIterator();
68 			while (net_device_monitor* monitor = iterator.Next()) {
69 				monitor->receive(monitor, buffer);
70 			}
71 
72 			buffer->interface = NULL;
73 			buffer->type = interface->deframe_func(interface->device, buffer);
74 			if (buffer->type < 0) {
75 				gNetBufferModule.free(buffer);
76 				continue;
77 			}
78 
79 			fifo_enqueue_buffer(&interface->receive_queue, buffer);
80 		} else {
81 			// In case of error, give the other threads some
82 			// time to run since this is a high priority time thread.
83 			snooze(10000);
84 		}
85 	}
86 
87 	return status;
88 }
89 
90 
91 static struct sockaddr**
92 interface_address(net_interface* interface, int32 option)
93 {
94 	switch (option) {
95 		case SIOCSIFADDR:
96 		case SIOCGIFADDR:
97 			return &interface->address;
98 
99 		case SIOCSIFNETMASK:
100 		case SIOCGIFNETMASK:
101 			return &interface->mask;
102 
103 		case SIOCSIFBRDADDR:
104 		case SIOCSIFDSTADDR:
105 		case SIOCGIFBRDADDR:
106 		case SIOCGIFDSTADDR:
107 			return &interface->destination;
108 
109 		default:
110 			return NULL;
111 	}
112 }
113 
114 
115 /*!	Removes the default routes as set by add_default_routes() again. */
116 static void
117 remove_default_routes(net_interface_private* interface, int32 option)
118 {
119 	net_route route;
120 	route.destination = interface->address;
121 	route.gateway = NULL;
122 	route.interface = interface;
123 
124 	if (interface->mask != NULL
125 		&& (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
126 		route.mask = interface->mask;
127 		route.flags = 0;
128 		remove_route(interface->domain, &route);
129 	}
130 
131 	if (option == SIOCSIFADDR) {
132 		route.mask = NULL;
133 		route.flags = RTF_LOCAL | RTF_HOST;
134 		remove_route(interface->domain, &route);
135 	}
136 }
137 
138 
139 /*!	Adds the default routes that every interface needs, ie. the local host
140 	route, and one for the subnet (if set).
141 */
142 static void
143 add_default_routes(net_interface_private* interface, int32 option)
144 {
145 	net_route route;
146 	route.destination = interface->address;
147 	route.gateway = NULL;
148 	route.interface = interface;
149 
150 	if (interface->mask != NULL
151 		&& (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
152 		route.mask = interface->mask;
153 		route.flags = 0;
154 		add_route(interface->domain, &route);
155 	}
156 
157 	if (option == SIOCSIFADDR) {
158 		route.mask = NULL;
159 		route.flags = RTF_LOCAL | RTF_HOST;
160 		add_route(interface->domain, &route);
161 	}
162 }
163 
164 
165 static sockaddr*
166 reallocate_address(sockaddr** _address, uint32 size)
167 {
168 	sockaddr* address = *_address;
169 
170 	size = max_c(size, sizeof(struct sockaddr));
171 	if (address != NULL && address->sa_len >= size)
172 		return address;
173 
174 	address = (sockaddr*)malloc(size);
175 	if (address == NULL)
176 		return NULL;
177 
178 	free(*_address);
179 	*_address = address;
180 
181 	return address;
182 }
183 
184 
185 static status_t
186 datalink_control_interface(net_domain_private* domain, int32 option,
187 	void* value, size_t* _length, size_t expected, bool getByName)
188 {
189 	if (*_length < expected)
190 		return B_BAD_VALUE;
191 
192 	ifreq request;
193 	memset(&request, 0, sizeof(request));
194 
195 	if (user_memcpy(&request, value, expected) < B_OK)
196 		return B_BAD_ADDRESS;
197 
198 	RecursiveLocker _(domain->lock);
199 	net_interface* interface = NULL;
200 
201 	if (getByName)
202 		interface = find_interface(domain, request.ifr_name);
203 	else
204 		interface = find_interface(domain, request.ifr_index);
205 
206 	status_t status = interface == NULL ? ENODEV : B_OK;
207 
208 	switch (option) {
209 		case SIOCGIFINDEX:
210 			if (interface)
211 				request.ifr_index = interface->index;
212 			else
213 				request.ifr_index = 0;
214 			break;
215 
216 		case SIOCGIFNAME:
217 			if (interface)
218 				strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
219 			else
220 				status = B_BAD_VALUE; // TODO: should be ENXIO?
221 			break;
222 	}
223 
224 	if (status < B_OK)
225 		return status;
226 
227 	return user_memcpy(value, &request, sizeof(ifreq));
228 }
229 
230 
231 //	#pragma mark - datalink module
232 
233 
234 status_t
235 datalink_control(net_domain* _domain, int32 option, void* value,
236 	size_t* _length)
237 {
238 	net_domain_private* domain = (net_domain_private*)_domain;
239 	if (domain == NULL || domain->family == AF_LINK) {
240 		// the AF_LINK family is already handled completely in the link protocol
241 		return B_BAD_VALUE;
242 	}
243 
244 	switch (option) {
245 		case SIOCGIFINDEX:
246 			return datalink_control_interface(domain, option, value, _length,
247 				IF_NAMESIZE, true);
248 		case SIOCGIFNAME:
249 			return datalink_control_interface(domain, option, value, _length,
250 				sizeof(ifreq), false);
251 
252 		case SIOCDIFADDR:
253 		case SIOCSIFFLAGS:
254 		{
255 			struct ifreq request;
256 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
257 				return B_BAD_ADDRESS;
258 
259 			return domain_interface_control(domain, option, &request);
260 		}
261 
262 		case SIOCAIFADDR:
263 		{
264 			// add new interface address
265 			struct ifreq request;
266 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
267 				return B_BAD_ADDRESS;
268 
269 			return add_interface_to_domain(domain, request);
270 		}
271 
272 		case SIOCGIFCOUNT:
273 		{
274 			// count number of interfaces
275 			struct ifconf config;
276 			config.ifc_value = count_domain_interfaces();
277 
278 			return user_memcpy(value, &config, sizeof(struct ifconf));
279 		}
280 
281 		case SIOCGIFCONF:
282 		{
283 			// retrieve ifreqs for all interfaces
284 			struct ifconf config;
285 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
286 				return B_BAD_ADDRESS;
287 
288 			status_t result = list_domain_interfaces(config.ifc_buf,
289 				(size_t*)&config.ifc_len);
290 			if (result != B_OK)
291 				return result;
292 
293 			return user_memcpy(value, &config, sizeof(struct ifconf));
294 		}
295 
296 		case SIOCGRTSIZE:
297 		{
298 			// determine size of buffer to hold the routing table
299 			struct ifconf config;
300 			config.ifc_value = route_table_size(domain);
301 
302 			return user_memcpy(value, &config, sizeof(struct ifconf));
303 		}
304 		case SIOCGRTTABLE:
305 		{
306 			// retrieve all routes for this domain
307 			struct ifconf config;
308 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
309 				return B_BAD_ADDRESS;
310 
311 			return list_routes(domain, config.ifc_buf, config.ifc_len);
312 		}
313 		case SIOCGETRT:
314 			return get_route_information(domain, value, *_length);
315 
316 		default:
317 		{
318 			// try to pass the request to an existing interface
319 			struct ifreq request;
320 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
321 				return B_BAD_ADDRESS;
322 
323 			RecursiveLocker _(domain->lock);
324 
325 			net_interface* interface = find_interface(domain,
326 				request.ifr_name);
327 			if (interface == NULL)
328 				return B_BAD_VALUE;
329 
330 			// pass the request into the datalink protocol stack
331 			return interface->first_info->control(
332 				interface->first_protocol, option, value, *_length);
333 		}
334 	}
335 	return B_BAD_VALUE;
336 }
337 
338 
339 status_t
340 datalink_send_data(struct net_route* route, net_buffer* buffer)
341 {
342 	net_interface_private* interface =
343 		(net_interface_private*)route->interface;
344 
345 	//dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
346 	//	buffer->size, interface->name, route->flags);
347 
348 	if (route->flags & RTF_REJECT)
349 		return ENETUNREACH;
350 
351 	if (route->flags & RTF_LOCAL) {
352 		// we set the interface here so the buffer is delivered directly
353 		// to the domain in interfaces.cpp:device_consumer_thread()
354 		buffer->interface = interface;
355 		// this one goes back to the domain directly
356 		return fifo_enqueue_buffer(
357 			&interface->device_interface->receive_queue, buffer);
358 	}
359 
360 	if (route->flags & RTF_GATEWAY) {
361 		// this route involves a gateway, we need to use the gateway address
362 		// instead of the destination address:
363 		if (route->gateway == NULL)
364 			return B_MISMATCHED_VALUES;
365 		memcpy(buffer->destination, route->gateway, route->gateway->sa_len);
366 	}
367 
368 	// this goes out to the datalink protocols
369 	return interface->first_info->send_data(interface->first_protocol, buffer);
370 }
371 
372 
373 status_t
374 datalink_send_datagram(net_protocol* protocol, net_domain* domain,
375 	net_buffer* buffer)
376 {
377 	if (protocol == NULL && domain == NULL)
378 		return B_BAD_VALUE;
379 
380 	net_protocol_module_info* module = protocol ? protocol->module
381 		: domain->module;
382 
383 	if (domain == NULL)
384 		domain = protocol->module->get_domain(protocol);
385 
386 	net_route* route = NULL;
387 	status_t status;
388 	if (protocol != NULL && protocol->socket->bound_to_device > 0) {
389 		status = get_device_route(domain, protocol->socket->bound_to_device,
390 			&route);
391 	} else
392 		status = get_buffer_route(domain, buffer, &route);
393 	if (status < B_OK)
394 		return status;
395 
396 	status = module->send_routed_data(protocol, route, buffer);
397 	put_route(domain, route);
398 	return status;
399 }
400 
401 
402 /*!
403 	Tests if \a address is a local address in the domain.
404 	\param _interface will be set to the interface belonging to that address
405 		if non-NULL.
406 	\param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
407 */
408 bool
409 datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
410 	net_interface** _interface, uint32* _matchedType)
411 {
412 	net_domain_private* domain = (net_domain_private*)_domain;
413 	if (domain == NULL || address == NULL)
414 		return false;
415 
416 	RecursiveLocker locker(domain->lock);
417 
418 	net_interface* interface = NULL;
419 	net_interface* fallback = NULL;
420 	uint32 matchedType = 0;
421 
422 	while (true) {
423 		interface = (net_interface*)list_get_next_item(
424 			&domain->interfaces, interface);
425 		if (interface == NULL)
426 			break;
427 		if (interface->address == NULL) {
428 			fallback = interface;
429 			continue;
430 		}
431 
432 		// check for matching unicast address first
433 		if (domain->address_module->equal_addresses(interface->address, address))
434 			break;
435 
436 		// check for matching broadcast address if interface supports
437 		// broadcasting (IFF_BROADCAST is a link-level flag, so it is
438 		// a property of the device)
439 		if ((interface->device->flags & IFF_BROADCAST)
440 			&& domain->address_module->equal_addresses(interface->destination,
441 				address)) {
442 			matchedType = MSG_BCAST;
443 			break;
444 		}
445 	}
446 
447 	if (interface == NULL) {
448 		interface = fallback;
449 		if (interface == NULL)
450 			return false;
451 	}
452 
453 	if (_interface != NULL)
454 		*_interface = interface;
455 	if (_matchedType != NULL)
456 		*_matchedType = matchedType;
457 	return true;
458 }
459 
460 
461 net_interface*
462 datalink_get_interface_with_address(net_domain* _domain,
463 	const sockaddr* address)
464 {
465 	net_domain_private* domain = (net_domain_private*)_domain;
466 	if (domain == NULL)
467 		return NULL;
468 
469 	RecursiveLocker _(domain->lock);
470 
471 	net_interface* interface = NULL;
472 
473 	while (true) {
474 		interface = (net_interface*)list_get_next_item(
475 			&domain->interfaces, interface);
476 		if (interface == NULL)
477 			break;
478 
479 		if (address == NULL)
480 			return interface;
481 
482 		if (domain->address_module->equal_addresses(interface->address,
483 				address))
484 			return interface;
485 	}
486 
487 	return NULL;
488 }
489 
490 
491 net_interface*
492 datalink_get_interface(net_domain* domain, uint32 index)
493 {
494 	if (index == 0)
495 		return datalink_get_interface_with_address(domain, NULL);
496 
497 	return find_interface(domain, index);
498 }
499 
500 
501 static status_t
502 datalink_std_ops(int32 op, ...)
503 {
504 	switch (op) {
505 		case B_MODULE_INIT:
506 		case B_MODULE_UNINIT:
507 			return B_OK;
508 
509 		default:
510 			return B_ERROR;
511 	}
512 }
513 
514 
515 //	#pragma mark - net_datalink_protocol
516 
517 
518 status_t
519 interface_protocol_init(struct net_interface* _interface,
520 	net_datalink_protocol** _protocol)
521 {
522 	net_interface_private* interface = (net_interface_private*)_interface;
523 
524 	interface_protocol* protocol = new (std::nothrow) interface_protocol;
525 	if (protocol == NULL)
526 		return B_NO_MEMORY;
527 
528 	protocol->device_module = interface->device->module;
529 	protocol->device = interface->device;
530 
531 	*_protocol = protocol;
532 	return B_OK;
533 }
534 
535 
536 status_t
537 interface_protocol_uninit(net_datalink_protocol* protocol)
538 {
539 	delete protocol;
540 	return B_OK;
541 }
542 
543 
544 status_t
545 interface_protocol_send_data(net_datalink_protocol* _protocol,
546 	net_buffer* buffer)
547 {
548 	interface_protocol* protocol = (interface_protocol*)_protocol;
549 	net_interface_private* interface
550 		= (net_interface_private*)protocol->interface;
551 
552 	// TODO: Need to think about this locking. We can't obtain the
553 	//       RX Lock here (nor would it make sense) as the ARP
554 	//       module calls send_data() with it's lock held (similiar
555 	//       to the domain lock, which would violate the locking
556 	//       protocol).
557 
558 	DeviceMonitorList::Iterator iterator =
559 		interface->device_interface->monitor_funcs.GetIterator();
560 	while (iterator.HasNext()) {
561 		net_device_monitor* monitor = iterator.Next();
562 		monitor->receive(monitor, buffer);
563 	}
564 
565 	return protocol->device_module->send_data(protocol->device, buffer);
566 }
567 
568 
569 status_t
570 interface_protocol_up(net_datalink_protocol* _protocol)
571 {
572 	interface_protocol* protocol = (interface_protocol*)_protocol;
573 	net_device_interface* deviceInterface =
574 		((net_interface_private*)protocol->interface)->device_interface;
575 	net_device* device = protocol->device;
576 
577 	// This function is called with the RX lock held.
578 
579 	if (deviceInterface->up_count != 0) {
580 		deviceInterface->up_count++;
581 		return B_OK;
582 	}
583 
584 	status_t status = protocol->device_module->up(device);
585 	if (status < B_OK)
586 		return status;
587 
588 	if (device->module->receive_data != NULL) {
589 		// give the thread a nice name
590 		char name[B_OS_NAME_LENGTH];
591 		snprintf(name, sizeof(name), "%s reader", device->name);
592 
593 		deviceInterface->reader_thread =
594 			spawn_kernel_thread(device_reader_thread, name,
595 				B_REAL_TIME_DISPLAY_PRIORITY - 10, deviceInterface);
596 		if (deviceInterface->reader_thread < B_OK)
597 			return deviceInterface->reader_thread;
598 	}
599 
600 	device->flags |= IFF_UP;
601 
602 	if (device->module->receive_data != NULL)
603 		resume_thread(deviceInterface->reader_thread);
604 
605 	deviceInterface->up_count = 1;
606 	return B_OK;
607 }
608 
609 
610 void
611 interface_protocol_down(net_datalink_protocol* _protocol)
612 {
613 	interface_protocol* protocol = (interface_protocol*)_protocol;
614 	net_device_interface* deviceInterface =
615 		((net_interface_private*)protocol->interface)->device_interface;
616 
617 	// This function is called with the RX lock held.
618 	if (deviceInterface->up_count == 0)
619 		return;
620 
621 	deviceInterface->up_count--;
622 
623 	domain_interface_went_down(protocol->interface);
624 
625 	if (deviceInterface->up_count > 0)
626 		return;
627 
628 	down_device_interface(deviceInterface);
629 }
630 
631 
632 status_t
633 interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
634 	void* argument, size_t length)
635 {
636 	interface_protocol* protocol = (interface_protocol*)_protocol;
637 	net_interface_private* interface
638 		= (net_interface_private*)protocol->interface;
639 
640 	switch (option) {
641 		case SIOCSIFADDR:
642 		case SIOCSIFNETMASK:
643 		case SIOCSIFBRDADDR:
644 		case SIOCSIFDSTADDR:
645 		{
646 			// set logical interface address
647 			struct ifreq request;
648 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
649 				return B_BAD_ADDRESS;
650 
651 			sockaddr** _address = interface_address(interface, option);
652 			if (_address == NULL)
653 				return B_BAD_VALUE;
654 
655 			// allocate new address if needed
656 			sockaddr* address = reallocate_address(_address,
657 				request.ifr_addr.sa_len);
658 
659 			// copy new address over
660 			if (address != NULL) {
661 				remove_default_routes(interface, option);
662 				memcpy(address, &request.ifr_addr, request.ifr_addr.sa_len);
663 
664 				if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
665 					// reset netmask and broadcast addresses to defaults
666 					sockaddr* netmask = NULL;
667 					sockaddr* oldNetmask = NULL;
668 					if (option == SIOCSIFADDR) {
669 						netmask = reallocate_address(&interface->mask,
670 							request.ifr_addr.sa_len);
671 					} else
672 						oldNetmask = address;
673 
674 					sockaddr* broadcast = reallocate_address(
675 						&interface->destination, request.ifr_addr.sa_len);
676 
677 					interface->domain->address_module->set_to_defaults(
678 						netmask, broadcast, interface->address, oldNetmask);
679 				}
680 
681 				add_default_routes(interface, option);
682 			}
683 
684 			return address != NULL ? B_OK : B_NO_MEMORY;
685 		}
686 
687 		case SIOCGIFADDR:
688 		case SIOCGIFNETMASK:
689 		case SIOCGIFBRDADDR:
690 		case SIOCGIFDSTADDR:
691 		{
692 			// get logical interface address
693 			sockaddr** _address = interface_address(interface, option);
694 			if (_address == NULL)
695 				return B_BAD_VALUE;
696 
697 			struct ifreq request;
698 
699 			sockaddr* address = *_address;
700 			if (address != NULL)
701 				memcpy(&request.ifr_addr, address, address->sa_len);
702 			else {
703 				request.ifr_addr.sa_len = 2;
704 				request.ifr_addr.sa_family = AF_UNSPEC;
705 			}
706 
707 			// copy address over
708 			return user_memcpy(&((struct ifreq*)argument)->ifr_addr,
709 				&request.ifr_addr, request.ifr_addr.sa_len);
710 		}
711 
712 		case SIOCGIFFLAGS:
713 		{
714 			// get flags
715 			struct ifreq request;
716 			request.ifr_flags = interface->flags | interface->device->flags;
717 
718 			return user_memcpy(&((struct ifreq*)argument)->ifr_flags,
719 				&request.ifr_flags, sizeof(request.ifr_flags));
720 		}
721 
722 		case SIOCGIFPARAM:
723 		{
724 			// get interface parameter
725 			struct ifreq request;
726 			strlcpy(request.ifr_parameter.base_name, interface->base_name, IF_NAMESIZE);
727 			strlcpy(request.ifr_parameter.device,
728 				interface->device_interface->device->name, IF_NAMESIZE);
729 			request.ifr_parameter.sub_type = 0;
730 				// TODO: for now, we ignore the sub type...
731 
732 			return user_memcpy(&((struct ifreq*)argument)->ifr_parameter,
733 				&request.ifr_parameter, sizeof(request.ifr_parameter));
734 		}
735 
736 		case SIOCGIFSTATS:
737 		{
738 			// get stats
739 			return user_memcpy(&((struct ifreq*)argument)->ifr_stats,
740 				&interface->device_interface->device->stats,
741 				sizeof(struct ifreq_stats));
742 		}
743 
744 		case SIOCGIFTYPE:
745 		{
746 			// get type
747 			struct ifreq request;
748 			request.ifr_type = interface->type;
749 
750 			return user_memcpy(&((struct ifreq*)argument)->ifr_type,
751 				&request.ifr_type, sizeof(request.ifr_type));
752 		}
753 
754 		case SIOCGIFMTU:
755 		{
756 			// get MTU
757 			struct ifreq request;
758 			request.ifr_mtu = interface->mtu;
759 
760 			return user_memcpy(&((struct ifreq*)argument)->ifr_mtu,
761 				&request.ifr_mtu, sizeof(request.ifr_mtu));
762 		}
763 		case SIOCSIFMTU:
764 		{
765 			// set MTU
766 			struct ifreq request;
767 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
768 				return B_BAD_ADDRESS;
769 
770 			// check for valid bounds
771 			if (request.ifr_mtu < 100
772 				|| (uint32)request.ifr_mtu > interface->device->mtu)
773 				return B_BAD_VALUE;
774 
775 			interface->mtu = request.ifr_mtu;
776 			return B_OK;
777 		}
778 
779 		case SIOCSIFMEDIA:
780 		{
781 			// set media
782 			struct ifreq request;
783 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
784 				return B_BAD_ADDRESS;
785 
786 			return interface->device_interface->device->module->set_media(
787 				interface->device, request.ifr_media);
788 		}
789 		case SIOCGIFMEDIA:
790 		{
791 			// get media
792 			struct ifreq request;
793 			request.ifr_media = interface->device->media;
794 
795 			return user_memcpy(&((struct ifreq*)argument)->ifr_media,
796 				&request.ifr_media, sizeof(request.ifr_media));
797 		}
798 
799 		case SIOCGIFMETRIC:
800 		{
801 			// get metric
802 			struct ifreq request;
803 			request.ifr_metric = interface->metric;
804 
805 			return user_memcpy(&((struct ifreq*)argument)->ifr_metric,
806 				&request.ifr_metric, sizeof(request.ifr_metric));
807 		}
808 		case SIOCSIFMETRIC:
809 		{
810 			// set metric
811 			struct ifreq request;
812 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
813 				return B_BAD_ADDRESS;
814 
815 			interface->metric = request.ifr_metric;
816 			return B_OK;
817 		}
818 
819 		case SIOCADDRT:
820 		case SIOCDELRT:
821 			// interface related route options
822 			return control_routes(interface, option, argument, length);
823 	}
824 
825 	return protocol->device_module->control(protocol->device,
826 		option, argument, length);
827 }
828 
829 
830 static status_t
831 interface_protocol_join_multicast(net_datalink_protocol* _protocol,
832 	const sockaddr* address)
833 {
834 	interface_protocol* protocol = (interface_protocol*)_protocol;
835 
836 	return protocol->device_module->add_multicast(protocol->device, address);
837 }
838 
839 
840 static status_t
841 interface_protocol_leave_multicast(net_datalink_protocol* _protocol,
842 	const sockaddr* address)
843 {
844 	interface_protocol* protocol = (interface_protocol*)_protocol;
845 
846 	return protocol->device_module->remove_multicast(protocol->device,
847 		address);
848 }
849 
850 
851 net_datalink_module_info gNetDatalinkModule = {
852 	{
853 		NET_DATALINK_MODULE_NAME,
854 		0,
855 		datalink_std_ops
856 	},
857 
858 	datalink_control,
859 	datalink_send_data,
860 	datalink_send_datagram,
861 	datalink_is_local_address,
862 	datalink_get_interface,
863 	datalink_get_interface_with_address,
864 
865 	add_route,
866 	remove_route,
867 	get_route,
868 	get_buffer_route,
869 	put_route,
870 	register_route_info,
871 	unregister_route_info,
872 	update_route_info
873 };
874 
875 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
876 	{
877 		NULL,
878 		0,
879 		NULL
880 	},
881 	interface_protocol_init,
882 	interface_protocol_uninit,
883 	interface_protocol_send_data,
884 	interface_protocol_up,
885 	interface_protocol_down,
886 	interface_protocol_control,
887 	interface_protocol_join_multicast,
888 	interface_protocol_leave_multicast,
889 };
890