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