1/*
2 * Copyright 2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Lin Longzhou, linlongzhou@163.com
7 */
8
9
10#include <ethernet.h>
11#include <net/if_types.h>
12#include <net_datalink_protocol.h>
13#include <net_datalink.h>
14
15#include <KernelExport.h>
16
17#include <new>
18
19#include <PPPControl.h>
20#include <ppp_device.h>
21
22struct ppp_frame_protocol : net_datalink_protocol {
23};
24
25
26static net_stack_module_info *sStackModule;
27
28status_t
29ppp_deframe(net_device* device, net_buffer* buffer)
30{
31	TRACE("%s: buffer type:0x%" B_PRIx32 "\n", __func__, buffer->type);
32	return B_OK;
33}
34
35
36//	#pragma mark -
37
38status_t
39ppp_frame_init(struct net_interface* interface, net_domain* domain,
40	net_datalink_protocol** _protocol)
41{
42	// We only support a single type!
43	dprintf("in function: %s::%s\n", __FILE__, __func__);
44	if (interface->device->type != IFT_PPP)
45		return B_BAD_TYPE;
46
47	ppp_frame_protocol* protocol;
48
49	status_t status = sStackModule->register_device_deframer(interface->device,
50		&ppp_deframe);
51	if (status != B_OK)
52		return status;
53
54	status = sStackModule->register_domain_device_handler(
55		interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_PPPOE), domain);
56	if (status != B_OK)
57		return status;
58
59	status = sStackModule->register_domain_device_handler(
60		interface->device, B_NET_FRAME_TYPE_IPV4, domain);
61	if (status != B_OK)
62		return status;
63
64	// Locally received buffers don't need a domain device handler, as the
65	// buffer reception is handled internally.
66
67	protocol = new(std::nothrow) ppp_frame_protocol;
68	if (protocol == NULL) {
69		sStackModule->unregister_device_deframer(interface->device);
70		return B_NO_MEMORY;
71	}
72
73	*_protocol = protocol;
74	return B_OK;
75}
76
77
78status_t
79ppp_frame_uninit(net_datalink_protocol* protocol)
80{
81	sStackModule->unregister_device_deframer(protocol->interface->device);
82	sStackModule->unregister_device_handler(protocol->interface->device, 0);
83
84	delete protocol;
85	TRACE("%s\n", __func__);
86	return B_OK;
87}
88
89
90status_t
91ppp_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
92{
93	TRACE("%s: next module is %s\n", __func__, protocol->next->module->info.name);
94	return protocol->next->module->send_data(protocol->next, buffer);
95}
96
97
98status_t
99ppp_frame_up(net_datalink_protocol* protocol)
100{
101	dprintf("in function: %s\n", __func__);
102
103	return protocol->next->module->interface_up(protocol->next);
104}
105
106
107void
108ppp_frame_down(net_datalink_protocol* protocol)
109{
110	dprintf("%s::%s: entry\n", __FILE__, __func__);
111	protocol->next->module->interface_down(protocol->next);
112	return;
113}
114
115
116status_t
117ppp_frame_change_address(net_datalink_protocol* protocol,
118	net_interface_address* address, int32 option,
119	const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
120{
121	TRACE("in function: %s::%s\n", __FILE__, __func__);
122	return protocol->next->module->change_address(protocol->next, address,
123		option, oldAddress, newAddress);
124}
125
126
127static status_t
128PPP_module_control(int32 option, void* argument, size_t length)
129{
130	// control_net_module_args* args=(control_net_module_args*)argument;
131
132	if (option < PPPC_CONTROL_MODULE || option > PPP_CONTROL_OPS_END)
133		return B_ERROR;
134
135	// if (args->name != PPP_INTERFACE_MODULE_NAME)
136		// return B_ERROR;
137
138	switch(option)
139	{
140		case PPPC_CREATE_INTERFACE:
141			// process_CreateInterface(args->data, args->length);
142		case PPPC_CREATE_INTERFACE_WITH_NAME:
143		case PPPC_DELETE_INTERFACE:
144		case PPPC_BRING_INTERFACE_UP:
145		case PPPC_BRING_INTERFACE_DOWN:
146		case PPPC_CONTROL_INTERFACE:
147		case PPPC_GET_INTERFACES:
148		case PPPC_COUNT_INTERFACES:
149		case PPPC_FIND_INTERFACE_WITH_SETTINGS:
150
151		// interface control
152		case PPPC_GET_INTERFACE_INFO:
153		case PPPC_SET_USERNAME:
154		case PPPC_SET_PASSWORD:
155		case PPPC_SET_ASK_BEFORE_CONNECTING:
156			// ppp_up uses this in order to finalize a connection request
157		case PPPC_SET_MRU:
158		case PPPC_SET_CONNECT_ON_DEMAND:
159		case PPPC_SET_AUTO_RECONNECT:
160		case PPPC_HAS_INTERFACE_SETTINGS:
161		case PPPC_GET_STATISTICS:
162		// handler access
163		case PPPC_CONTROL_DEVICE:
164		case PPPC_CONTROL_PROTOCOL:
165		case PPPC_CONTROL_OPTION_HANDLER:
166		case PPPC_CONTROL_LCP_EXTENSION:
167		case PPPC_CONTROL_CHILD:
168		// KPPPDevice
169		case PPPC_GET_DEVICE_INFO:
170		// KPPPProtocol
171		case PPPC_GET_PROTOCOL_INFO:
172		// Common/mixed ops
173		case PPPC_ENABLE:
174		case PPPC_GET_SIMPLE_HANDLER_INFO:
175
176		// these two control ops use the ppp_report_request structure
177		case PPPC_ENABLE_REPORTS:
178		case PPPC_DISABLE_REPORTS:
179
180		case PPP_CONTROL_OPS_END:
181		case PPPC_CONTROL_MODULE:
182		default:
183			return B_ERROR;
184	}
185}
186
187
188static status_t
189ppp_frame_control(net_datalink_protocol* protocol, int32 option,
190	void* argument, size_t length)
191{
192	TRACE("%s: option:%" B_PRId32 "\n", __func__, option);
193
194	if (option >= PPPC_CONTROL_MODULE && option <=PPP_CONTROL_OPS_END)
195	{
196		status_t status =PPP_module_control(option, argument, length);
197		// gPPPInterfaceModule->ControlInterface(1, option, argument, length);
198		return status;
199	}
200
201	return protocol->next->module->control(protocol->next, option, argument,
202		length);
203}
204
205
206static status_t
207ppp_frame_join_multicast(net_datalink_protocol* protocol,
208	const sockaddr* address)
209{
210	TRACE("in function: %s\n", __func__);
211	return protocol->next->module->join_multicast(protocol->next, address);
212}
213
214
215static status_t
216ppp_frame_leave_multicast(net_datalink_protocol* protocol,
217	const sockaddr* address)
218{
219	TRACE("in function: %s\n", __func__);
220	return protocol->next->module->leave_multicast(protocol->next, address);
221}
222
223
224static status_t
225pppoe_frame_std_ops(int32 op, ...)
226{
227	switch (op) {
228		case B_MODULE_INIT:
229			if (get_module(NET_STACK_MODULE_NAME,
230				(module_info **)&sStackModule) != B_OK)
231				return B_ERROR;
232			return B_OK;
233
234		case B_MODULE_UNINIT:
235			put_module(NET_STACK_MODULE_NAME);
236			return B_OK;
237
238		default:
239			return B_ERROR;
240	}
241}
242
243
244static net_datalink_protocol_module_info sPPPFrameModule = {
245	{
246		"network/datalink_protocols/ppp_frame/v1",
247		0,
248		pppoe_frame_std_ops
249	},
250	ppp_frame_init,
251	ppp_frame_uninit,
252	ppp_frame_send_data,
253	ppp_frame_up,
254	ppp_frame_down,
255	ppp_frame_change_address,
256	ppp_frame_control,
257	ppp_frame_join_multicast,
258	ppp_frame_leave_multicast,
259};
260
261
262module_info* modules[] = {
263	(module_info*)&sPPPFrameModule,
264	NULL
265};
266