1/*
2 * Copyright 2006-2007, 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#include <net_tun.h>
10
11#include <net_buffer.h>
12#include <net_device.h>
13#include <net_stack.h>
14
15#include <KernelExport.h>
16
17#include <net/if.h>
18#include <net/if_types.h>
19#include <net/if_media.h>
20#include <new>
21#include <stdlib.h>
22#include <string.h>
23
24
25
26struct net_buffer_module_info* gBufferModule;
27static struct net_stack_module_info* sStackModule;
28
29//static mutex sListLock;
30//static DoublyLinkedList<ethernet_device> sCheckList;
31
32
33//	#pragma mark -
34
35
36status_t
37tun_init(const char* name, net_device** _device)
38{
39	tun_device* device;
40
41	if (strncmp(name, "tun", 3)
42		&& strncmp(name, "tap", 3)
43		&& strncmp(name, "dns", 3))	/* iodine uses that */
44		return B_BAD_VALUE;
45
46	device = new (std::nothrow) tun_device;
47	if (device == NULL) {
48		return B_NO_MEMORY;
49	}
50
51	memset(device, 0, sizeof(tun_device));
52
53	strcpy(device->name, name);
54	device->flags = IFF_LINK;
55	device->type = strncmp(name, "tap", 3) ? IFT_TUN : IFT_ETHER;
56	device->mtu = 16384;
57	device->media = IFM_ACTIVE;
58
59	*_device = device;
60	return B_OK;
61}
62
63
64status_t
65tun_uninit(net_device* _device)
66{
67	tun_device* device = (tun_device*)_device;
68
69	put_module(NET_STACK_MODULE_NAME);
70	put_module(NET_BUFFER_MODULE_NAME);
71	delete device;
72
73	return B_OK;
74}
75
76
77status_t
78tun_up(net_device* device)
79{
80	return B_OK;
81}
82
83
84void
85tun_down(net_device* device)
86{
87}
88
89
90status_t
91tun_control(net_device* device, int32 op, void* argument,
92	size_t length)
93{
94	return B_BAD_VALUE;
95}
96
97
98status_t
99tun_send_data(net_device* device, net_buffer* buffer)
100{
101	return sStackModule->device_enqueue_buffer(device, buffer);
102}
103
104
105status_t
106tun_set_mtu(net_device* device, size_t mtu)
107{
108	if (mtu > 65536 || mtu < 16)
109		return B_BAD_VALUE;
110
111	device->mtu = mtu;
112	return B_OK;
113}
114
115
116status_t
117tun_set_promiscuous(net_device* device, bool promiscuous)
118{
119	return EOPNOTSUPP;
120}
121
122
123status_t
124tun_set_media(net_device* device, uint32 media)
125{
126	return EOPNOTSUPP;
127}
128
129
130status_t
131tun_add_multicast(net_device* device, const sockaddr* address)
132{
133	return B_OK;
134}
135
136
137status_t
138tun_remove_multicast(net_device* device, const sockaddr* address)
139{
140	return B_OK;
141}
142
143
144static status_t
145tun_std_ops(int32 op, ...)
146{
147	switch (op) {
148		case B_MODULE_INIT:
149		{
150			status_t status = get_module(NET_STACK_MODULE_NAME,
151				(module_info**)&sStackModule);
152			if (status < B_OK)
153				return status;
154			status = get_module(NET_BUFFER_MODULE_NAME,
155				(module_info**)&gBufferModule);
156			if (status < B_OK) {
157				put_module(NET_STACK_MODULE_NAME);
158				return status;
159			}
160			return B_OK;
161		}
162		case B_MODULE_UNINIT:
163			put_module(NET_BUFFER_MODULE_NAME);
164			put_module(NET_STACK_MODULE_NAME);
165			return B_OK;
166		default:
167			return B_ERROR;
168	}
169}
170
171
172net_device_module_info sTunModule = {
173	{
174		"network/devices/tun/v1",
175		0,
176		tun_std_ops
177	},
178	tun_init,
179	tun_uninit,
180	tun_up,
181	tun_down,
182	tun_control,
183	tun_send_data,
184	NULL, // receive_data
185	tun_set_mtu,
186	tun_set_promiscuous,
187	tun_set_media,
188	tun_add_multicast,
189	tun_remove_multicast,
190
191};
192
193module_info* modules[] = {
194	(module_info*)&sTunModule,
195	NULL
196};
197