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