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 */ 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. 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. 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 76 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 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 144 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 177 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 190 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 203 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 225 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 243 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 257 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 275 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 293 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 311 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 329 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 353 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 365 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 381 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 414 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 454 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 475 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