xref: /haiku/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
1 /*
2  * Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*!	\class PPPInterface
7 	\brief This class represents a PPP interface living in kernel space.
8 
9 	Use this class to control PPP interfaces and get the current interface settings.
10 	You can also use it to enable/disable report messages.
11 */
12 
13 #include "PPPInterface.h"
14 
15 #include <cstring>
16 #include <cstdlib>
17 #include <cstdio>
18 #include <cctype>
19 #include <unistd.h>
20 
21 #include <Path.h>
22 #include <Directory.h>
23 #include <Entry.h>
24 
25 #include <net/if.h>
26 
27 #include <NetworkDevice.h>
28 #include <NetworkInterface.h>
29 
30 
31 /*!	\brief Sets the interface to \a ID.
32 
33 	\param ID The ID of the new interface.
34 */
PPPInterface(ppp_interface_id ID)35 PPPInterface::PPPInterface(ppp_interface_id ID)
36 {
37 	// printf("direct constructor\n");
38 	int family = AF_INET;
39 	fFD = socket(family, SOCK_DGRAM, 0);
40 
41 	SetTo(ID);
42 }
43 
44 
45 //!	Copy constructor.
PPPInterface(const PPPInterface & copy)46 PPPInterface::PPPInterface(const PPPInterface& copy)
47 {
48 	// printf("Copy constructor\n");
49 	// fFD = open(get_stack_driver_path(), O_RDWR);
50 	int family = AF_INET;
51 	fFD = socket(family, SOCK_DGRAM, 0);
52 
53 	SetTo(copy.ID());
54 }
55 
56 
57 //!	Destructor.
~PPPInterface()58 PPPInterface::~PPPInterface()
59 {
60 	// printf("Destructor\n");
61 	if (fFD >= 0)
62 		close(fFD);
63 }
64 
65 
66 /*!	\brief Checks if object was created correctly.
67 
68 	You should always call this method after you constructed a PPPInterface object.
69 
70 	\return
71 		- \c B_OK: Object could be initialized successfully and the interface exists.
72 		- \c B_BAD_INDEX: The interface does not exist.
73 		- \c B_ERROR: The PPP stack could not be loaded.
74 */
75 status_t
InitCheck() const76 PPPInterface::InitCheck() const
77 {
78 	if (fFD < 0)
79 		return B_ERROR;
80 
81 	if (fID == PPP_UNDEFINED_INTERFACE_ID)
82 		return B_BAD_INDEX;
83 
84 	return B_OK;
85 }
86 
87 
88 /*!	\brief Changes the current interface.
89 
90 	If this fails it will set the interface's \a ID to \c PPP_UNDEFINED_INTERFACE_ID.
91 
92 	\param ID The ID of the new interface.
93 
94 	\return
95 		- \c B_OK: Object could be initialized successfully and the interface exists.
96 		- \c B_BAD_INDEX: The interface does not exist.
97 		- any other value: The PPP stack could not be loaded.
98 
99 	\sa Control()
100 */
101 status_t
SetTo(ppp_interface_id ID)102 PPPInterface::SetTo(ppp_interface_id ID)
103 {
104 	// printf("Set To %ld begin=============================\n", ID);
105 	if (fFD < 0) {
106 		printf("No fFD\n");
107 		return B_ERROR;
108 	}
109 
110 	fID = ID;
111 
112 	ppp_interface_info_t info;
113 	// printf("SetTo info:%p\n", &info);
114 	if (GetInterfaceInfo(&info)) {
115 		fName = info.info.name;
116 		fID = ID;
117 		// printf("%s fine: name:%s, fID:%ld\n", __func__, info.info.name, fID);
118 	} else {
119 		fName = "";
120 		fID = PPP_UNDEFINED_INTERFACE_ID;
121 		// printf("%s fail: name:%s, fID:%ld\n", __func__, "", fID);
122 		return B_ERROR;
123 	}
124 
125 	// printf("Set To %ld end =============================\n", ID);
126 
127 	return B_OK;
128 }
129 
130 
131 /*!	\brief Use this method for accessing additional PPP features.
132 
133 	\param op Any value of ppp_control_ops.
134 	\param data Some ops require you to pass a structure or other data using this
135 		argument.
136 	\param length Make sure this value is correct (e.g.: size of structure).
137 
138 	\return
139 		- \c B_OK: Operation was successful.
140 		- \c B_BAD_INDEX: The interface does not exist.
141 		- any other value: The PPP stack could not be loaded.
142 */
143 status_t
Control(uint32 op,void * data,size_t length) const144 PPPInterface::Control(uint32 op, void *data, size_t length) const
145 {
146 	if (InitCheck() != B_OK) {
147 		printf("%s:InitCheck fail\n", __func__);
148 		return InitCheck();
149 	}
150 
151 	ppp_control_info info;
152 	control_net_module_args args;
153 
154 	sprintf(args.ifr_name, "%s", "ppp1");
155 	args.name = PPP_INTERFACE_MODULE_NAME;
156 	args.op = PPPC_CONTROL_INTERFACE;
157 	args.data = &info;
158 	args.length = sizeof(ppp_control_info);
159 
160 	info.index = ID();
161 	info.op = op;
162 	info.data = data;
163 	info.length = length;
164 
165 	printf("PPPInterface::Control: ppp_control_info %p control_net_module_args %p data %p \n", &info, &args, data);
166 
167 	status_t status = ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args);
168 	if (status != B_OK)
169 		printf("%s:%s: fail\n", __FILE__, __func__);
170 
171 	return status;
172 }
173 
174 
175 //!	Sets the username used for authentication.
176 bool
SetUsername(const char * username) const177 PPPInterface::SetUsername(const char *username) const
178 {
179 	printf("PPPInterface::SetUsername\n");
180 	if (InitCheck() != B_OK || !username)
181 		return false;
182 
183 	return Control(PPPC_SET_USERNAME, const_cast<char*>(username), strlen(username))
184 		== B_OK;
185 }
186 
187 
188 //!	Sets the password used for authentication.
189 bool
SetPassword(const char * password) const190 PPPInterface::SetPassword(const char *password) const
191 {
192 	printf("PPPInterface::SetPassword\n");
193 	if (InitCheck() != B_OK || !password)
194 		return false;
195 
196 	return Control(PPPC_SET_PASSWORD, const_cast<char*>(password), strlen(password))
197 		== B_OK;
198 }
199 
200 
201 //!	Sets whether a request window should be shown before connecting.
202 bool
SetAskBeforeConnecting(bool askBeforeConnecting) const203 PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const
204 {
205 	printf("PPPInterface::SetAskBeforeConnecting\n");
206 	if (InitCheck() != B_OK)
207 		return false;
208 
209 	uint32 value = askBeforeConnecting ? 1 : 0;
210 	return Control(PPPC_SET_ASK_BEFORE_CONNECTING, &value, sizeof(value)) == B_OK;
211 }
212 
213 
214 /*!	\brief Find BEntry to the interface settings that this object represents.
215 
216 	\param entry The entry gets stored in this argument.
217 
218 	\return
219 		- \c B_OK: The settings file was saved in \a entry.
220 		- \c B_BAD_INDEX: The interface does not exist.
221 		- \c B_BAD_VALUE: Either \a entry was \c NULL or the interface is anonymous.
222 		- any other value: The interface could not be found.
223 */
224 status_t
GetSettingsEntry(BEntry * entry) const225 PPPInterface::GetSettingsEntry(BEntry *entry) const
226 {
227 	printf("PPPInterface::GetSettingsEntry\n");
228 	if (InitCheck() != B_OK)
229 		return InitCheck();
230 	else if (!entry || strlen(Name()) == 0)
231 		return B_BAD_VALUE;
232 
233 	BDirectory directory(PTP_INTERFACE_SETTINGS_PATH);
234 	return directory.FindEntry(Name(), entry, true);
235 }
236 
237 
238 /*!	\brief Get the ppp_interface_info_t structure.
239 
240 	\return \c true on success, \c false otherwise.
241 */
242 bool
GetInterfaceInfo(ppp_interface_info_t * info) const243 PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const
244 {
245 	// printf("%s info at:%p", __func__, info);
246 	if (InitCheck() != B_OK || !info) {
247 		// printf("InitCheck fail %s info at:%p", __func__, info);
248 		return false;
249 	}
250 
251 	return Control(PPPC_GET_INTERFACE_INFO, info, sizeof(ppp_interface_info_t))
252 		== B_OK;
253 }
254 
255 
256 bool
ControlDevice(ppp_device_info_t * info) const257 PPPInterface::ControlDevice(ppp_device_info_t *info) const
258 {
259 	// printf("%s info at:%p", __func__, info);
260 	if (InitCheck() != B_OK || !info)
261 		return false;
262 
263 	ppp_control_info controlInfo;
264 	controlInfo.op = PPPC_GET_DEVICE_INFO;
265 	controlInfo.index = 0;
266 	controlInfo.data = info;
267 	controlInfo.length = sizeof(ppp_device_info_t);
268 
269 	return Control(PPPC_CONTROL_DEVICE, &controlInfo, sizeof(ppp_control_info))
270 		== B_OK;
271 }
272 
273 
274 bool
ControlOptionHandler(ppp_simple_handler_info_t * info,uint32 handlerindex,uint32 handlerOP) const275 PPPInterface::ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const
276 {
277 	// printf("%s info at:%p", __func__, info);
278 	if (InitCheck() != B_OK || !info)
279 		return false;
280 
281 	ppp_control_info controlInfo;
282 	controlInfo.index = handlerindex;
283 	controlInfo.op = handlerOP;
284 	controlInfo.data = info;
285 	controlInfo.length = sizeof(ppp_simple_handler_info_t);
286 
287 	return Control(PPPC_CONTROL_OPTION_HANDLER, &controlInfo, sizeof(ppp_control_info))
288 		== B_OK;
289 }
290 
291 
292 bool
ControlChild(void * info,uint32 childindex,uint32 childOP) const293 PPPInterface::ControlChild(void *info, uint32 childindex, uint32 childOP) const
294 {
295 	// printf("%s info at:%p", __func__, info);
296 	if (InitCheck() != B_OK || !info)
297 		return false;
298 
299 	ppp_control_info controlInfo;
300 	controlInfo.index = childindex;
301 	controlInfo.op = childOP;
302 	controlInfo.data = info;
303 	// controlInfo.length = sizeof(ppp_simple_handler_info_t);
304 
305 	return Control(PPPC_CONTROL_CHILD, &controlInfo, sizeof(ppp_control_info))
306 		== B_OK;
307 }
308 
309 
310 bool
ControlLCPExtension(ppp_simple_handler_info_t * info,uint32 LCPExtensionindex,uint32 LCPExtensionOP) const311 PPPInterface::ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const
312 {
313 	// printf("%s info at:%p", __func__, info);
314 	if (InitCheck() != B_OK || !info)
315 		return false;
316 
317 	ppp_control_info controlInfo;
318 	controlInfo.index = LCPExtensionindex;
319 	controlInfo.op = LCPExtensionOP;
320 	controlInfo.data = info;
321 	controlInfo.length = sizeof(ppp_simple_handler_info_t);
322 
323 	return Control(PPPC_CONTROL_LCP_EXTENSION, &controlInfo, sizeof(ppp_control_info))
324 		== B_OK;
325 }
326 
327 
328 bool
ControlProtocol(ppp_protocol_info_t * info,uint32 protocolindex,uint32 protocolOP) const329 PPPInterface::ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 protocolOP) const
330 {
331 	// printf("%s info at:%p", __func__, info);
332 	if (InitCheck() != B_OK || !info)
333 		return false;
334 
335 	ppp_control_info controlInfo;
336 	controlInfo.index = protocolindex;
337 	controlInfo.op = protocolOP;
338 	controlInfo.data = info;
339 	controlInfo.length = sizeof(ppp_protocol_info_t);
340 
341 	return Control(PPPC_CONTROL_PROTOCOL, &controlInfo, sizeof(ppp_control_info))
342 		== B_OK;
343 }
344 
345 
346 /*!	\brief Get transfer statistics for this interface.
347 
348 	\param statistics The structure is copied into this argument.
349 
350 	\return \c true on success, \c false otherwise.
351 */
352 bool
GetStatistics(ppp_statistics * statistics) const353 PPPInterface::GetStatistics(ppp_statistics *statistics) const
354 {
355 	printf("PPPInterface::GetStatistics\n");
356 	if (!statistics)
357 		return false;
358 
359 	return Control(PPPC_GET_STATISTICS, statistics, sizeof(ppp_statistics)) == B_OK;
360 }
361 
362 
363 //!	Compares interface's settings to given driver_settings structure.
364 bool
HasSettings(const driver_settings * settings) const365 PPPInterface::HasSettings(const driver_settings *settings) const
366 {
367 	printf("PPPInterface::HasSettings\n");
368 	if (InitCheck() != B_OK || !settings)
369 		return false;
370 
371 	if (Control(PPPC_HAS_INTERFACE_SETTINGS, const_cast<driver_settings*>(settings),
372 			sizeof(driver_settings)) == B_OK)
373 		return true;
374 
375 	return false;
376 }
377 
378 
379 //!	Brings the interface up.
380 bool
Up() const381 PPPInterface::Up() const
382 {
383 	if (InitCheck() != B_OK)
384 		return false;
385 
386 	BNetworkInterface interface(Name());
387 	if (!interface.Exists())
388 		return false;
389 
390 	int32 currentFlags = interface.Flags();
391 	currentFlags |= IFF_UP;
392 
393 	status_t status = interface.SetFlags(currentFlags);
394 
395 	if (status != B_OK)
396 		return false;
397 
398 	return true;
399 
400 	int32 id = ID();
401 	control_net_module_args args;
402 	sprintf(args.ifr_name, "%s", "ppp1");
403 	args.name = PPP_INTERFACE_MODULE_NAME;
404 	args.op = PPPC_BRING_INTERFACE_UP;
405 	args.data = &id;
406 	args.length = sizeof(id);
407 
408 	return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK;
409 }
410 
411 
412 //!	Brings the interface down which causes the deletion of the interface.
413 bool
Down() const414 PPPInterface::Down() const
415 {
416 	if (InitCheck() != B_OK)
417 		return false;
418 
419 	BNetworkInterface interface(Name());
420 	if (!interface.Exists())
421 		return false;
422 
423 	int32 currentFlags = interface.Flags();
424 	currentFlags &= ~IFF_UP;
425 
426 	status_t status = interface.SetFlags(currentFlags);
427 
428 	if (status != B_OK)
429 		return false;
430 
431 	return true;
432 
433 	int32 id = ID();
434 	control_net_module_args args;
435 	sprintf(args.ifr_name, "%s", "ppp1");
436 	args.name = PPP_INTERFACE_MODULE_NAME;
437 	args.op = PPPC_BRING_INTERFACE_DOWN;
438 	args.data = &id;
439 	args.length = sizeof(id);
440 
441 	return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK;
442 }
443 
444 
445 /*!	\brief Requests report messages from the interface.
446 
447 	\param type The type of report.
448 	\param thread Receiver thread.
449 	\param flags Optional flags.
450 
451 	\return \c true on success \c false otherwise.
452 */
453 bool
EnableReports(ppp_report_type type,thread_id thread,int32 flags) const454 PPPInterface::EnableReports(ppp_report_type type, thread_id thread,
455 	int32 flags) const
456 {
457 	printf("PPPInterface::EnableReports\n");
458 	ppp_report_request request;
459 	request.type = type;
460 	request.thread = thread;
461 	request.flags = flags;
462 
463 	return Control(PPPC_ENABLE_REPORTS, &request, sizeof(request)) == B_OK;
464 }
465 
466 
467 /*!	\brief Removes thread from list of report requestors of this interface.
468 
469 	\param type The type of report.
470 	\param thread Receiver thread.
471 
472 	\return \c true on success \c false otherwise.
473 */
474 bool
DisableReports(ppp_report_type type,thread_id thread) const475 PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const
476 {
477 	printf("PPPInterface::DisableReports\n");
478 	ppp_report_request request;
479 	request.type = type;
480 	request.thread = thread;
481 
482 	return Control(PPPC_DISABLE_REPORTS, &request, sizeof(request)) == B_OK;
483 }
484