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
ppp_deframe(net_device * device,net_buffer * buffer)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
ppp_frame_init(struct net_interface * interface,net_domain * domain,net_datalink_protocol ** _protocol)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
ppp_frame_uninit(net_datalink_protocol * protocol)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
ppp_frame_send_data(net_datalink_protocol * protocol,net_buffer * buffer)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
ppp_frame_up(net_datalink_protocol * protocol)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
ppp_frame_down(net_datalink_protocol * protocol)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
ppp_frame_change_address(net_datalink_protocol * protocol,net_interface_address * address,int32 option,const struct sockaddr * oldAddress,const struct sockaddr * newAddress)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
PPP_module_control(int32 option,void * argument,size_t length)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
ppp_frame_control(net_datalink_protocol * protocol,int32 option,void * argument,size_t length)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
ppp_frame_join_multicast(net_datalink_protocol * protocol,const sockaddr * address)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
ppp_frame_leave_multicast(net_datalink_protocol * protocol,const sockaddr * address)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
pppoe_frame_std_ops(int32 op,...)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