xref: /haiku/src/add-ons/kernel/network/devices/tunnel/tunnel.cpp (revision 2a2e7ad562841be14b2d1f8ad870780f32be2b1f)
1 /*
2  * Copyright 2023, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Augustin Cavalier <waddlesplash>
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Sean Brady, swangeon@gmail.com
9  */
10 
11 #include <new>
12 #include <string.h>
13 
14 #include <fs/select_sync_pool.h>
15 #include <fs/devfs.h>
16 #include <util/AutoLock.h>
17 #include <util/Random.h>
18 
19 #include <net_buffer.h>
20 #include <net_device.h>
21 #include <net_stack.h>
22 
23 #include <net/if.h>
24 #include <net/if_dl.h>
25 #include <net/if_media.h>
26 #include <net/if_types.h>
27 #include <net/if_tun.h>
28 #include <netinet/in.h>
29 #include <ethernet.h>
30 
31 
32 //#define TRACE_TUNNEL
33 #ifdef TRACE_TUNNEL
34 #	define TRACE(x...) dprintf("network/tunnel: " x)
35 #else
36 #   define TRACE(x...)
37 #endif
38 
39 #define CALLED(x...)			TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
40 #define TRACE_ALWAYS(x...)		dprintf("network/tunnel: " x)
41 
42 
43 struct tunnel_device : net_device {
44 	bool				is_tap;
45 
46 	net_fifo			send_queue, receive_queue;
47 
48 	int32				open_count;
49 
50 	mutex				select_lock;
51 	select_sync_pool*	select_pool;
52 };
53 
54 #define TUNNEL_QUEUE_MAX (ETHER_MAX_FRAME_SIZE * 32)
55 
56 
57 struct net_buffer_module_info* gBufferModule;
58 static net_stack_module_info* gStackModule;
59 
60 
61 //	#pragma mark - devices array
62 
63 
64 static tunnel_device* gDevices[10] = {};
65 static mutex gDevicesLock = MUTEX_INITIALIZER("tunnel devices");
66 
67 
68 static tunnel_device*
69 find_tunnel_device(const char* name)
70 {
71 	ASSERT_LOCKED_MUTEX(&gDevicesLock);
72 	for (size_t i = 0; i < B_COUNT_OF(gDevices); i++) {
73 		if (gDevices[i] == NULL)
74 			continue;
75 
76 		if (strcmp(gDevices[i]->name, name) == 0)
77 			return gDevices[i];
78 	}
79 	return NULL;
80 }
81 
82 
83 //	#pragma mark - devfs device
84 
85 
86 struct tunnel_cookie {
87 	tunnel_device*	device;
88 	uint32		flags;
89 };
90 
91 
92 status_t
93 tunnel_open(const char* name, uint32 flags, void** _cookie)
94 {
95 	MutexLocker devicesLocker(gDevicesLock);
96 	tunnel_device* device = find_tunnel_device(name);
97 	if (device == NULL)
98 		return ENODEV;
99 	if (atomic_or(&device->open_count, 1) != 0)
100 		return EBUSY;
101 
102 	tunnel_cookie* cookie = new(std::nothrow) tunnel_cookie;
103 	if (cookie == NULL)
104 		return B_NO_MEMORY;
105 
106 	cookie->device = device;
107 	cookie->flags = flags;
108 
109 	*_cookie = cookie;
110 	return B_OK;
111 }
112 
113 
114 status_t
115 tunnel_close(void* _cookie)
116 {
117 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
118 
119 	// Wake up the send queue, so that any threads waiting to read return at once.
120 	release_sem_etc(cookie->device->send_queue.notify, B_INTERRUPTED, B_RELEASE_ALL);
121 
122 	return B_OK;
123 }
124 
125 
126 status_t
127 tunnel_free(void* _cookie)
128 {
129 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
130 	atomic_and(&cookie->device->open_count, 0);
131 	delete cookie;
132 	return B_OK;
133 }
134 
135 
136 status_t
137 tunnel_control(void* _cookie, uint32 op, void* data, size_t len)
138 {
139 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
140 
141 	switch (op) {
142 		case B_SET_NONBLOCKING_IO:
143 			cookie->flags |= O_NONBLOCK;
144 			return B_OK;
145 		case B_SET_BLOCKING_IO:
146 			cookie->flags &= ~O_NONBLOCK;
147 			return B_OK;
148 	}
149 
150 	return B_DEV_INVALID_IOCTL;
151 }
152 
153 
154 status_t
155 tunnel_read(void* _cookie, off_t position, void* data, size_t* _length)
156 {
157 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
158 
159 	net_buffer* buffer = NULL;
160 	status_t status = gStackModule->fifo_dequeue_buffer(
161 		&cookie->device->send_queue, 0, B_INFINITE_TIMEOUT, &buffer);
162 	if (status != B_OK)
163 		return status;
164 
165 	const size_t length = min_c(*_length, buffer->size);
166 	status = gBufferModule->read(buffer, 0, data, length);
167 	if (status != B_OK)
168 		return status;
169 	*_length = length;
170 
171 	gBufferModule->free(buffer);
172 	return B_OK;
173 }
174 
175 
176 status_t
177 tunnel_write(void* _cookie, off_t position, const void* data, size_t* _length)
178 {
179 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
180 
181 	net_buffer* buffer = gBufferModule->create(256);
182 	if (buffer == NULL)
183 		return B_NO_MEMORY;
184 
185 	status_t status = gBufferModule->append(buffer, data, *_length);
186 	if (status != B_OK) {
187 		gBufferModule->free(buffer);
188 		return status;
189 	}
190 
191 	if (!cookie->device->is_tap) {
192 		// TUN: Detect packet type.
193 		uint8 version;
194 		status = gBufferModule->read(buffer, 0, &version, 1);
195 		if (status != B_OK) {
196 			gBufferModule->free(buffer);
197 			return status;
198 		}
199 
200 		version = (version & 0xF0) >> 4;
201 		if (version != 4 && version != 6) {
202 			// Not any IP packet we recognize.
203 			gBufferModule->free(buffer);
204 			return B_BAD_DATA;
205 		}
206 		buffer->type = (version == 6) ? B_NET_FRAME_TYPE_IPV6
207 			: B_NET_FRAME_TYPE_IPV4;
208 
209 		struct sockaddr_in& src = *(struct sockaddr_in*)buffer->source;
210 		struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
211 		src.sin_len		= dst.sin_len		= sizeof(sockaddr_in);
212 		src.sin_family	= dst.sin_family	= (version == 6) ? AF_INET6 : AF_INET;
213 		src.sin_port	= dst.sin_port		= 0;
214 		src.sin_addr.s_addr = dst.sin_addr.s_addr = 0;
215 	}
216 
217 	// We use a queue and the receive_data() hook instead of device_enqueue_buffer()
218 	// for two reasons: 1. listeners (e.g. packet capture) are only processed by the
219 	// reader thread that calls receive_data(), and 2. device_enqueue_buffer() has
220 	// to look up the device interface every time, which is inefficient.
221 	status = gStackModule->fifo_enqueue_buffer(&cookie->device->receive_queue, buffer);
222 	if (status != B_OK)
223 		gBufferModule->free(buffer);
224 
225 	return status;
226 }
227 
228 
229 status_t
230 tunnel_select(void* _cookie, uint8 event, uint32 ref, selectsync* sync)
231 {
232 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
233 
234 	if (event != B_SELECT_READ && event != B_SELECT_WRITE)
235 		return B_BAD_VALUE;
236 
237 	MutexLocker selectLocker(cookie->device->select_lock);
238 	status_t status = add_select_sync_pool_entry(&cookie->device->select_pool, sync, event);
239 	if (status != B_OK)
240 		return B_BAD_VALUE;
241 	selectLocker.Unlock();
242 
243 	MutexLocker fifoLocker(cookie->device->send_queue.lock);
244 	if (event == B_SELECT_READ && cookie->device->send_queue.current_bytes != 0)
245 		notify_select_event(sync, event);
246 	if (event == B_SELECT_WRITE)
247 		notify_select_event(sync, event);
248 
249 	return B_OK;
250 }
251 
252 
253 status_t
254 tunnel_deselect(void* _cookie, uint8 event, selectsync* sync)
255 {
256 	tunnel_cookie* cookie = (tunnel_cookie*)_cookie;
257 
258 	MutexLocker selectLocker(cookie->device->select_lock);
259 	if (event != B_SELECT_READ && event != B_SELECT_WRITE)
260 		return B_BAD_VALUE;
261 	return remove_select_sync_pool_entry(&cookie->device->select_pool, sync, event);
262 }
263 
264 
265 static device_hooks sDeviceHooks = {
266 	tunnel_open,
267 	tunnel_close,
268 	tunnel_free,
269 	tunnel_control,
270 	tunnel_read,
271 	tunnel_write,
272 	tunnel_select,
273 	tunnel_deselect,
274 };
275 
276 
277 //	#pragma mark - network stack device
278 
279 
280 status_t
281 tunnel_init(const char* name, net_device** _device)
282 {
283 	const bool isTAP = strncmp(name, "tap/", 4) == 0;
284 	if (!isTAP && strncmp(name, "tun/", 4) != 0)
285 		return B_BAD_VALUE;
286 	if (strlen(name) >= sizeof(tunnel_device::name))
287 		return ENAMETOOLONG;
288 
289 	// Make sure this device doesn't already exist.
290 	MutexLocker devicesLocker(gDevicesLock);
291 	if (find_tunnel_device(name) != NULL)
292 		return EEXIST;
293 
294 	tunnel_device* device = new(std::nothrow) tunnel_device;
295 	if (device == NULL)
296 		return B_NO_MEMORY;
297 
298 	ssize_t index = -1;
299 	for (size_t i = 0; i < B_COUNT_OF(gDevices); i++) {
300 		if (gDevices[i] != NULL)
301 			continue;
302 
303 		gDevices[i] = device;
304 		index = i;
305 		break;
306 	}
307 	if (index < 0) {
308 		delete device;
309 		return ENOSPC;
310 	}
311 	devicesLocker.Unlock();
312 
313 	memset(device, 0, sizeof(tunnel_device));
314 	strcpy(device->name, name);
315 
316 	device->mtu = ETHER_MAX_FRAME_SIZE;
317 	device->media = IFM_ACTIVE;
318 
319 	device->is_tap = isTAP;
320 	if (device->is_tap) {
321 		device->flags = IFF_BROADCAST | IFF_ALLMULTI | IFF_LINK;
322 		device->type = IFT_ETHER;
323 
324 		// Generate a random MAC address.
325 		for (int i = 0; i < ETHER_ADDRESS_LENGTH; i++)
326 			device->address.data[i] = secure_get_random<uint8>();
327 		device->address.data[0] &= 0xFE; // multicast
328 		device->address.data[0] |= 0x02; // local assignment
329 
330 		device->address.length = ETHER_ADDRESS_LENGTH;
331 	} else {
332 		device->flags = IFF_POINTOPOINT | IFF_LINK;
333 		device->type = IFT_TUNNEL;
334 	}
335 
336 	status_t status = gStackModule->init_fifo(&device->send_queue,
337 		"tunnel send queue", TUNNEL_QUEUE_MAX);
338 	if (status != B_OK) {
339 		delete device;
340 		return status;
341 	}
342 
343 	status = gStackModule->init_fifo(&device->receive_queue,
344 		"tunnel receive queue", TUNNEL_QUEUE_MAX);
345 	if (status != B_OK) {
346 		gStackModule->uninit_fifo(&device->send_queue);
347 		delete device;
348 		return status;
349 	}
350 
351 	mutex_init(&device->select_lock, "tunnel select lock");
352 
353 	status = devfs_publish_device(name, &sDeviceHooks);
354 	if (status != B_OK) {
355 		gStackModule->uninit_fifo(&device->send_queue);
356 		gStackModule->uninit_fifo(&device->receive_queue);
357 		delete device;
358 		return status;
359 	}
360 
361 	*_device = device;
362 	return B_OK;
363 }
364 
365 
366 status_t
367 tunnel_uninit(net_device* _device)
368 {
369 	tunnel_device* device = (tunnel_device*)_device;
370 
371 	MutexLocker devicesLocker(gDevicesLock);
372 	if (atomic_get(&device->open_count) != 0)
373 		return EBUSY;
374 
375 	for (size_t i = 0; i < B_COUNT_OF(gDevices); i++) {
376 		if (gDevices[i] != device)
377 			continue;
378 
379 		gDevices[i] = NULL;
380 		break;
381 	}
382 	status_t status = devfs_unpublish_device(device->name, false);
383 	if (status != B_OK)
384 		panic("devfs_unpublish_device failed: %" B_PRId32, status);
385 
386 	gStackModule->uninit_fifo(&device->send_queue);
387 	gStackModule->uninit_fifo(&device->receive_queue);
388 	mutex_destroy(&device->select_lock);
389 	delete device;
390 	return B_OK;
391 }
392 
393 
394 status_t
395 tunnel_up(net_device* _device)
396 {
397 	return B_OK;
398 }
399 
400 
401 void
402 tunnel_down(net_device* _device)
403 {
404 	tunnel_device* device = (tunnel_device*)_device;
405 
406 	// Wake up the receive queue, so that the reader thread returns at once.
407 	release_sem_etc(device->receive_queue.notify, B_INTERRUPTED, B_RELEASE_ALL);
408 }
409 
410 
411 status_t
412 tunnel_control(net_device* device, int32 op, void* argument, size_t length)
413 {
414 	return B_BAD_VALUE;
415 }
416 
417 
418 status_t
419 tunnel_send_data(net_device* _device, net_buffer* buffer)
420 {
421 	tunnel_device* device = (tunnel_device*)_device;
422 
423 	status_t status = B_OK;
424 	if (!device->is_tap) {
425 		// Ensure this is an IP frame.
426 		struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
427 		if (dst.sin_family != AF_INET && dst.sin_family != AF_INET6)
428 			return B_BAD_DATA;
429 	}
430 
431 	status = gStackModule->fifo_enqueue_buffer(
432 		&device->send_queue, buffer);
433 	if (status == B_OK) {
434 		MutexLocker selectLocker(device->select_lock);
435 		notify_select_event_pool(device->select_pool, B_SELECT_READ);
436 	}
437 
438 	return status;
439 }
440 
441 
442 status_t
443 tunnel_receive_data(net_device* _device, net_buffer** _buffer)
444 {
445 	tunnel_device* device = (tunnel_device*)_device;
446 	return gStackModule->fifo_dequeue_buffer(&device->receive_queue,
447 		0, B_INFINITE_TIMEOUT, _buffer);
448 }
449 
450 
451 status_t
452 tunnel_set_mtu(net_device* device, size_t mtu)
453 {
454 	if (mtu > 65536 || mtu < 16)
455 		return B_BAD_VALUE;
456 
457 	device->mtu = mtu;
458 	return B_OK;
459 }
460 
461 
462 status_t
463 tunnel_set_promiscuous(net_device* device, bool promiscuous)
464 {
465 	return EOPNOTSUPP;
466 }
467 
468 
469 status_t
470 tunnel_set_media(net_device* device, uint32 media)
471 {
472 	return EOPNOTSUPP;
473 }
474 
475 
476 status_t
477 tunnel_add_multicast(net_device* device, const sockaddr* address)
478 {
479 	return B_OK;
480 }
481 
482 
483 status_t
484 tunnel_remove_multicast(net_device* device, const sockaddr* address)
485 {
486 	return B_OK;
487 }
488 
489 
490 net_device_module_info sTunModule = {
491 	{
492 		"network/devices/tunnel/v1",
493 		0,
494 		NULL
495 	},
496 	tunnel_init,
497 	tunnel_uninit,
498 	tunnel_up,
499 	tunnel_down,
500 	tunnel_control,
501 	tunnel_send_data,
502 	tunnel_receive_data,
503 	tunnel_set_mtu,
504 	tunnel_set_promiscuous,
505 	tunnel_set_media,
506 	tunnel_add_multicast,
507 	tunnel_remove_multicast,
508 };
509 
510 module_dependency module_dependencies[] = {
511 	{NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
512 	{NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
513 	{}
514 };
515 
516 module_info* modules[] = {
517 	(module_info*)&sTunModule,
518 	NULL
519 };
520