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