xref: /haiku/src/add-ons/kernel/network/ppp/ppp_frame/ppp_frame.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 
22 struct ppp_frame_protocol : net_datalink_protocol {
23 };
24 
25 
26 static net_stack_module_info *sStackModule;
27 
28 status_t
29 ppp_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 
38 status_t
39 ppp_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 
78 status_t
79 ppp_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 
90 status_t
91 ppp_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 
98 status_t
99 ppp_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 
107 void
108 ppp_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 
116 status_t
117 ppp_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 
127 static status_t
128 PPP_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 
188 static status_t
189 ppp_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 
206 static status_t
207 ppp_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 
215 static status_t
216 ppp_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 
224 static status_t
225 pppoe_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 
244 static 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 
262 module_info* modules[] = {
263 	(module_info*)&sPPPFrameModule,
264 	NULL
265 };
266