xref: /haiku/src/add-ons/kernel/network/stack/datalink.cpp (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
1 /*
2  * Copyright 2006, 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  */
8 
9 
10 #include "datalink.h"
11 #include "domains.h"
12 #include "interfaces.h"
13 #include "routes.h"
14 #include "stack_private.h"
15 
16 #include <net_device.h>
17 #include <KernelExport.h>
18 #include <util/AutoLock.h>
19 
20 #include <net/if.h>
21 #include <net/route.h>
22 #include <sys/sockio.h>
23 
24 #include <new>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 
30 struct datalink_protocol : net_protocol {
31 	struct net_domain_private *domain;
32 };
33 
34 struct interface_protocol : net_datalink_protocol {
35 	struct net_device_module_info *device_module;
36 	struct net_device *device;
37 };
38 
39 
40 static status_t
41 device_reader_thread(void *_interface)
42 {
43 	net_device_interface *interface = (net_device_interface *)_interface;
44 	net_device *device = interface->device;
45 	status_t status = B_OK;
46 	int32 tries = 0;
47 
48 	while ((device->flags & IFF_UP) != 0) {
49 		net_buffer *buffer;
50 		status = device->module->receive_data(device, &buffer);
51 		if (status == B_OK) {
52 			dprintf("received buffer of %ld bytes length\n", buffer->size);
53 			tries = 0;
54 
55 			// feed device monitors
56 			// TODO: locking!
57 			DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
58 			while (iterator.HasNext()) {
59 				net_device_monitor *monitor = iterator.Next();
60 				monitor->func(monitor->cookie, buffer);
61 			}
62 
63 			int32 type = interface->deframe_func(device, buffer);
64 			if (type >= 0) {
65 				// find handler for this packet
66 				// TODO: locking!
67 				DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
68 				status = B_ERROR;
69 
70 				while (iterator.HasNext()) {
71 					net_device_handler *handler = iterator.Next();
72 
73 					if (handler->type == type) {
74 						status = handler->func(handler->cookie, buffer);
75 						if (status == B_OK)
76 							break;
77 					}
78 				}
79 			} else
80 				status = type;
81 
82 			if (status == B_OK) {
83 				// the buffer no longer belongs to us
84 				continue;
85 			}
86 
87 			gNetBufferModule.free(buffer);
88 		}
89 
90 		if (status < B_OK) {
91 			// this is a near real-time thread - don't render the system unusable
92 			// in case of a device going down
93 			snooze(10000);
94 
95 			if (++tries > 20) {
96 				// TODO: bring down the interface!
97 				break;
98 			}
99 		}
100 	}
101 
102 	return status;
103 }
104 
105 
106 static struct sockaddr **
107 interface_address(net_interface *interface, int32 option)
108 {
109 	switch (option) {
110 		case SIOCSIFADDR:
111 		case SIOCGIFADDR:
112 			return &interface->address;
113 
114 		case SIOCSIFNETMASK:
115 		case SIOCGIFNETMASK:
116 			return &interface->mask;
117 
118 		case SIOCSIFBRDADDR:
119 		case SIOCSIFDSTADDR:
120 		case SIOCGIFBRDADDR:
121 		case SIOCGIFDSTADDR:
122 			return &interface->destination;
123 
124 		default:
125 			return NULL;
126 	}
127 }
128 
129 
130 void
131 remove_default_routes(net_interface_private *interface, int32 option)
132 {
133 	net_route route;
134 	route.destination = interface->address;
135 	route.gateway = NULL;
136 	route.interface = interface;
137 
138 	if (interface->mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
139 		route.mask = interface->mask;
140 		route.flags = 0;
141 		remove_route(interface->domain, &route);
142 	}
143 
144 	if (option == SIOCSIFADDR) {
145 		route.mask = NULL;
146 		route.flags = RTF_LOCAL | RTF_HOST;
147 		remove_route(interface->domain, &route);
148 	}
149 }
150 
151 
152 void
153 add_default_routes(net_interface_private *interface, int32 option)
154 {
155 	net_route route;
156 	route.destination = interface->address;
157 	route.gateway = NULL;
158 	route.interface = interface;
159 
160 	if (interface->mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
161 		route.mask = interface->mask;
162 		route.flags = 0;
163 		add_route(interface->domain, &route);
164 	}
165 
166 	if (option == SIOCSIFADDR) {
167 		route.mask = NULL;
168 		route.flags = RTF_LOCAL | RTF_HOST;
169 		add_route(interface->domain, &route);
170 	}
171 }
172 
173 
174 //	#pragma mark - datalink module
175 
176 
177 status_t
178 datalink_control(net_domain *_domain, int32 option, void *value,
179 	size_t *_length)
180 {
181 	net_domain_private *domain = (net_domain_private *)_domain;
182 	if (domain == NULL || domain->family == AF_LINK) {
183 		// the AF_LINK family is already handled completely in the link protocol
184 		return B_BAD_VALUE;
185 	}
186 
187 	switch (option) {
188 		case SIOCGIFINDEX:
189 		{
190 			// get index of interface
191 			struct ifreq request;
192 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
193 				return B_BAD_ADDRESS;
194 
195 			benaphore_lock(&domain->lock);
196 
197 			net_interface *interface = find_interface(domain,
198 				request.ifr_name);
199 			if (interface != NULL)
200 				request.ifr_index = interface->index;
201 			else
202 				request.ifr_index = 0;
203 
204 			benaphore_unlock(&domain->lock);
205 
206 			if (request.ifr_index == 0)
207 				return ENODEV;
208 
209 			return user_memcpy(value, &request, sizeof(struct ifreq));
210 		}
211 		case SIOCGIFNAME:
212 		{
213 			// get name of interface via index
214 			struct ifreq request;
215 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
216 				return B_BAD_ADDRESS;
217 
218 			benaphore_lock(&domain->lock);
219 			status_t status = B_OK;
220 
221 			net_interface *interface = find_interface(domain,
222 				request.ifr_index);
223 			if (interface != NULL)
224 				strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
225 			else
226 				status = B_BAD_VALUE;
227 
228 			benaphore_unlock(&domain->lock);
229 
230 			if (status < B_OK)
231 				return status;
232 
233 			return user_memcpy(value, &request, sizeof(struct ifreq));
234 		}
235 
236 		case SIOCAIFADDR:
237 		{
238 			// add new interface address
239 			struct ifreq request;
240 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
241 				return B_BAD_ADDRESS;
242 
243 			return add_interface_to_domain(domain, request);
244 		}
245 		case SIOCDIFADDR:
246 		{
247 			// remove interface address
248 			struct ifreq request;
249 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
250 				return B_BAD_ADDRESS;
251 
252 			benaphore_lock(&domain->lock);
253 			status_t status;
254 
255 			net_interface *interface = find_interface(domain,
256 				request.ifr_name);
257 			if (interface != NULL)
258 				status = remove_interface_from_domain(interface);
259 			else
260 				status = ENODEV;
261 
262 			benaphore_unlock(&domain->lock);
263 
264 			return status;
265 		}
266 
267 		case SIOCGIFCOUNT:
268 		{
269 			// count number of interfaces
270 			struct ifconf config;
271 			config.ifc_value = count_domain_interfaces();
272 
273 			return user_memcpy(value, &config, sizeof(struct ifconf));
274 		}
275 
276 		case SIOCGIFCONF:
277 		{
278 			// retrieve ifreqs for all interfaces
279 			struct ifconf config;
280 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
281 				return B_BAD_ADDRESS;
282 
283 			return list_domain_interfaces(config.ifc_buf, config.ifc_len);
284 		}
285 
286 		case SIOCGRTSIZE:
287 		{
288 			// determine size of buffer to hold the routing table
289 			struct ifconf config;
290 			config.ifc_value = route_table_size(domain);
291 
292 			return user_memcpy(value, &config, sizeof(struct ifconf));
293 		}
294 		case SIOCGRTTABLE:
295 		{
296 			// retrieve all routes for this domain
297 			struct ifconf config;
298 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
299 				return B_BAD_ADDRESS;
300 
301 			return list_routes(domain, config.ifc_buf, config.ifc_len);
302 		}
303 
304 		default:
305 		{
306 			// try to pass the request to an existing interface
307 
308 			struct ifreq request;
309 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
310 				return B_BAD_ADDRESS;
311 
312 			benaphore_lock(&domain->lock);
313 			status_t status = B_OK;
314 
315 			net_interface *interface = find_interface(domain,
316 				request.ifr_name);
317 			if (interface != NULL) {
318 				// filter out bringing the interface up or down
319 				if (option == SIOCSIFFLAGS
320 					&& ((uint32)request.ifr_flags & IFF_UP) != (interface->flags & IFF_UP)) {
321 					if ((interface->flags & IFF_UP) != 0) {
322 						// bring the interface down
323 						interface->flags &= ~IFF_UP;
324 						interface->first_info->interface_down(interface->first_protocol);
325 					} else {
326 						// bring it up
327 						status = interface->first_info->interface_up(interface->first_protocol);
328 						if (status == B_OK)
329 							interface->flags |= IFF_UP;
330 					}
331 
332 					request.ifr_flags = interface->flags;
333 				}
334 
335 				if (status == B_OK) {
336 					// pass the request into the datalink protocol stack
337 					status = interface->first_info->control(interface->first_protocol,
338 						option, value, *_length);
339 				}
340 			} else
341 				status = B_BAD_VALUE;
342 
343 			benaphore_unlock(&domain->lock);
344 			return status;
345 		}
346 	}
347 	return B_BAD_VALUE;
348 }
349 
350 
351 status_t
352 datalink_send_data(struct net_route *route, net_buffer *buffer)
353 {
354 	net_interface *interface = route->interface;
355 	net_domain *domain = interface->domain;
356 
357 	dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
358 		buffer->size, interface->name, route->flags);
359 
360 	if (route->flags & RTF_REJECT)
361 		return ENETUNREACH;
362 
363 	if (route->flags & RTF_LOCAL) {
364 		// this one goes back to the domain directly
365 		return domain->module->receive_data(buffer);
366 	}
367 
368 	if (route->flags & RTF_GATEWAY) {
369 		// this route involves a gateway, we need to use the gateway address
370 		// instead of the destination address:
371 		if (route->gateway == NULL)
372 			return B_MISMATCHED_VALUES;
373 		memcpy(&buffer->destination, route->gateway, sizeof(sockaddr));
374 	}
375 
376 	// this goes out to the datalink protocols
377 	return interface->first_info->send_data(interface->first_protocol, buffer);
378 }
379 
380 
381 bool
382 is_local_address(net_domain *_domain, const struct sockaddr *address,
383 	net_interface **_interface, uint32 *_matchedType)
384 {
385 	net_domain_private *domain = (net_domain_private *)_domain;
386 	if (domain == NULL || address == NULL)
387 		return false;
388 
389 	BenaphoreLocker locker(domain->lock);
390 
391 	uint32 matchedType = 0;
392 
393 	net_interface *interface = NULL;
394 	while (true) {
395 		interface = (net_interface *)list_get_next_item(
396 			&domain->interfaces, interface);
397 		if (interface == NULL)
398 			break;
399 		if (interface->address == NULL)
400 			continue;
401 
402 		// check for matching unicast address first
403 		if (domain->address_module->equal_addresses(interface->address, address))
404 			break;
405 
406 		// check for matching broadcast address if interface support broadcasting
407 		if (interface->flags & IFF_BROADCAST
408 			&& domain->address_module->equal_addresses(interface->destination,
409 				address)) {
410 			matchedType = MSG_BCAST;
411 			break;
412 		}
413 	}
414 
415 	if (interface == NULL)
416 		return false;
417 
418 	if (_interface != NULL)
419 		*_interface = interface;
420 	if (_matchedType != NULL)
421 		*_matchedType = matchedType;
422 	return true;
423 }
424 
425 
426 static status_t
427 datalink_std_ops(int32 op, ...)
428 {
429 	switch (op) {
430 		case B_MODULE_INIT:
431 		case B_MODULE_UNINIT:
432 			return B_OK;
433 
434 		default:
435 			return B_ERROR;
436 	}
437 }
438 
439 
440 //	#pragma mark - net_datalink_protocol
441 
442 
443 status_t
444 interface_protocol_init(struct net_interface *_interface, net_datalink_protocol **_protocol)
445 {
446 	net_interface_private *interface = (net_interface_private *)_interface;
447 
448 	interface_protocol *protocol = new (std::nothrow) interface_protocol;
449 	if (protocol == NULL)
450 		return B_NO_MEMORY;
451 
452 	protocol->device_module = interface->device->module;
453 	protocol->device = interface->device;
454 
455 	*_protocol = protocol;
456 	return B_OK;
457 }
458 
459 
460 status_t
461 interface_protocol_uninit(net_datalink_protocol *protocol)
462 {
463 	delete protocol;
464 	return B_OK;
465 }
466 
467 
468 status_t
469 interface_protocol_send_data(net_datalink_protocol *_protocol,
470 	net_buffer *buffer)
471 {
472 	interface_protocol *protocol = (interface_protocol *)_protocol;
473 	return protocol->device_module->send_data(protocol->device, buffer);
474 }
475 
476 
477 status_t
478 interface_protocol_up(net_datalink_protocol *_protocol)
479 {
480 	interface_protocol *protocol = (interface_protocol *)_protocol;
481 	net_device_interface *deviceInterface =
482 		((net_interface_private *)protocol->interface)->device_interface;
483 	net_device *device = protocol->device;
484 
485 	// TODO: locking!
486 
487 	if (deviceInterface->up_count != 0) {
488 		deviceInterface->up_count++;
489 		return B_OK;
490 	}
491 
492 	status_t status = protocol->device_module->up(device);
493 	if (status < B_OK)
494 		return status;
495 
496 	// give the thread a nice name
497 	char name[B_OS_NAME_LENGTH];
498 	snprintf(name, sizeof(name), "%s reader", device->name);
499 
500 	thread_id thread = spawn_kernel_thread(device_reader_thread, name,
501 		B_REAL_TIME_DISPLAY_PRIORITY - 10, deviceInterface);
502 	if (thread < B_OK)
503 		return thread;
504 
505 	device->flags |= IFF_UP;
506 	resume_thread(thread);
507 
508 	deviceInterface->up_count = 1;
509 	return B_OK;
510 }
511 
512 
513 void
514 interface_protocol_down(net_datalink_protocol *_protocol)
515 {
516 	interface_protocol *protocol = (interface_protocol *)_protocol;
517 	net_device_interface *deviceInterface =
518 		((net_interface_private *)protocol->interface)->device_interface;
519 	net_device *device = protocol->device;
520 
521 	// TODO: locking!
522 	if (deviceInterface->up_count == 0)
523 		return;
524 
525 	deviceInterface->up_count--;
526 
527 	if (deviceInterface->up_count > 0)
528 		return;
529 
530 	device->flags &= ~IFF_UP;
531 	protocol->device_module->down(protocol->device);
532 }
533 
534 
535 status_t
536 interface_protocol_control(net_datalink_protocol *_protocol,
537 	int32 option, void *argument, size_t length)
538 {
539 	interface_protocol *protocol = (interface_protocol *)_protocol;
540 	net_interface_private *interface = (net_interface_private *)protocol->interface;
541 
542 	switch (option) {
543 		case SIOCSIFADDR:
544 		case SIOCSIFNETMASK:
545 		case SIOCSIFBRDADDR:
546 		case SIOCSIFDSTADDR:
547 		{
548 			// set logical interface address
549 			struct ifreq request;
550 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
551 				return B_BAD_ADDRESS;
552 
553 			sockaddr **_address = interface_address(interface, option);
554 			if (_address == NULL)
555 				return B_BAD_VALUE;
556 
557 			sockaddr *address = *_address;
558 			sockaddr *original = address;
559 
560 			// allocate new address if needed
561 			if (address == NULL
562 				|| (address->sa_len < request.ifr_addr.sa_len
563 					&& request.ifr_addr.sa_len > sizeof(struct sockaddr))) {
564 				address = (sockaddr *)malloc(
565 					max_c(request.ifr_addr.sa_len, sizeof(struct sockaddr)));
566 			}
567 
568 			// copy new address over
569 			if (address != NULL) {
570 				remove_default_routes(interface, option);
571 
572 				if (original != address) {
573 					free(original);
574 					*_address = address;
575 				}
576 
577 				memcpy(address, &request.ifr_addr, request.ifr_addr.sa_len);
578 				add_default_routes(interface, option);
579 			}
580 
581 			return address != NULL ? B_OK : B_NO_MEMORY;
582 		}
583 
584 		case SIOCGIFADDR:
585 		case SIOCGIFNETMASK:
586 		case SIOCGIFBRDADDR:
587 		case SIOCGIFDSTADDR:
588 		{
589 			// get logical interface address
590 			sockaddr **_address = interface_address(interface, option);
591 			if (_address == NULL)
592 				return B_BAD_VALUE;
593 
594 			struct ifreq request;
595 
596 			sockaddr *address = *_address;
597 			if (address != NULL)
598 				memcpy(&request.ifr_addr, address, address->sa_len);
599 			else {
600 				request.ifr_addr.sa_len = 2;
601 				request.ifr_addr.sa_family = AF_UNSPEC;
602 			}
603 
604 			// copy address over
605 			return user_memcpy(&((struct ifreq *)argument)->ifr_addr,
606 				&request.ifr_addr, request.ifr_addr.sa_len);
607 		}
608 
609 		case SIOCGIFFLAGS:
610 		{
611 			// get flags
612 			struct ifreq request;
613 			request.ifr_flags = interface->flags;
614 
615 			return user_memcpy(&((struct ifreq *)argument)->ifr_flags,
616 				&request.ifr_flags, sizeof(request.ifr_flags));
617 		}
618 		case SIOCSIFFLAGS:
619 		{
620 			// set flags
621 			struct ifreq request;
622 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
623 				return B_BAD_ADDRESS;
624 
625 			// TODO: check flags!
626 			interface->flags = request.ifr_flags;
627 			return B_OK;
628 		}
629 
630 		case SIOCGIFPARAM:
631 		{
632 			// get interface parameter
633 			struct ifreq request;
634 			strlcpy(request.ifr_parameter.base_name, interface->base_name, IF_NAMESIZE);
635 			strlcpy(request.ifr_parameter.device, interface->device_interface->name,
636 				IF_NAMESIZE);
637 			request.ifr_parameter.sub_type = 0;
638 				// TODO: for now, we ignore the sub type...
639 
640 			return user_memcpy(&((struct ifreq *)argument)->ifr_parameter,
641 				&request.ifr_parameter, sizeof(request.ifr_parameter));
642 		}
643 
644 		case SIOCGIFSTATS:
645 		{
646 			// get stats
647 			return user_memcpy(&((struct ifreq *)argument)->ifr_stats,
648 				&interface->device_interface->device->stats,
649 				sizeof(struct ifreq_stats));
650 		}
651 
652 		case SIOCGIFTYPE:
653 		{
654 			// get type
655 			struct ifreq request;
656 			request.ifr_type = interface->type;
657 
658 			return user_memcpy(&((struct ifreq *)argument)->ifr_type,
659 				&request.ifr_type, sizeof(request.ifr_type));
660 		}
661 
662 		case SIOCGIFMTU:
663 		{
664 			// get MTU
665 			struct ifreq request;
666 			request.ifr_mtu = interface->mtu;
667 
668 			return user_memcpy(&((struct ifreq *)argument)->ifr_mtu,
669 				&request.ifr_mtu, sizeof(request.ifr_mtu));
670 		}
671 		case SIOCSIFMTU:
672 		{
673 			// set MTU
674 			struct ifreq request;
675 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
676 				return B_BAD_ADDRESS;
677 
678 			// check for valid bounds
679 			if (request.ifr_mtu < 100 || (uint32)request.ifr_mtu > interface->device->mtu)
680 				return B_BAD_VALUE;
681 
682 			interface->mtu = request.ifr_mtu;
683 			return B_OK;
684 		}
685 
686 		case SIOCGIFMETRIC:
687 		{
688 			// get metric
689 			struct ifreq request;
690 			request.ifr_metric = interface->metric;
691 
692 			return user_memcpy(&((struct ifreq *)argument)->ifr_metric,
693 				&request.ifr_metric, sizeof(request.ifr_metric));
694 		}
695 		case SIOCSIFMETRIC:
696 		{
697 			// set metric
698 			struct ifreq request;
699 			if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
700 				return B_BAD_ADDRESS;
701 
702 			interface->metric = request.ifr_metric;
703 			return B_OK;
704 		}
705 
706 		case SIOCADDRT:
707 		case SIOCDELRT:
708 			// interface related route options
709 			return control_routes(interface, option, argument, length);
710 	}
711 
712 	return protocol->device_module->control(protocol->device,
713 		option, argument, length);
714 }
715 
716 
717 net_datalink_module_info gNetDatalinkModule = {
718 	{
719 		NET_DATALINK_MODULE_NAME,
720 		0,
721 		datalink_std_ops
722 	},
723 
724 	datalink_control,
725 	datalink_send_data,
726 
727 	is_local_address,
728 
729 	add_route,
730 	remove_route,
731 	get_route,
732 	put_route,
733 	register_route_info,
734 	unregister_route_info,
735 	update_route_info
736 };
737 
738 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
739 	{
740 		NULL,
741 		0,
742 		NULL
743 	},
744 	interface_protocol_init,
745 	interface_protocol_uninit,
746 	interface_protocol_send_data,
747 	interface_protocol_up,
748 	interface_protocol_down,
749 	interface_protocol_control,
750 };
751