/* * Copyright 2003-2007, Waldemar Kornewald * Distributed under the terms of the MIT License. */ /*! \class PPPInterface \brief This class represents a PPP interface living in kernel space. Use this class to control PPP interfaces and get the current interface settings. You can also use it to enable/disable report messages. */ #include "PPPInterface.h" #include #include #include #include #include #include #include #include #include #include #include /*! \brief Sets the interface to \a ID. \param ID The ID of the new interface. */ PPPInterface::PPPInterface(ppp_interface_id ID) { // printf("direct constructor\n"); int family = AF_INET; fFD = socket(family, SOCK_DGRAM, 0); SetTo(ID); } //! Copy constructor. PPPInterface::PPPInterface(const PPPInterface& copy) { // printf("Copy constructor\n"); // fFD = open(get_stack_driver_path(), O_RDWR); int family = AF_INET; fFD = socket(family, SOCK_DGRAM, 0); SetTo(copy.ID()); } //! Destructor. PPPInterface::~PPPInterface() { // printf("Destructor\n"); if (fFD >= 0) close(fFD); } /*! \brief Checks if object was created correctly. You should always call this method after you constructed a PPPInterface object. \return - \c B_OK: Object could be initialized successfully and the interface exists. - \c B_BAD_INDEX: The interface does not exist. - \c B_ERROR: The PPP stack could not be loaded. */ status_t PPPInterface::InitCheck() const { if (fFD < 0) return B_ERROR; if (fID == PPP_UNDEFINED_INTERFACE_ID) return B_BAD_INDEX; return B_OK; } /*! \brief Changes the current interface. If this fails it will set the interface's \a ID to \c PPP_UNDEFINED_INTERFACE_ID. \param ID The ID of the new interface. \return - \c B_OK: Object could be initialized successfully and the interface exists. - \c B_BAD_INDEX: The interface does not exist. - any other value: The PPP stack could not be loaded. \sa Control() */ status_t PPPInterface::SetTo(ppp_interface_id ID) { // printf("Set To %ld begin=============================\n", ID); if (fFD < 0) { printf("No fFD\n"); return B_ERROR; } fID = ID; ppp_interface_info_t info; // printf("SetTo info:%p\n", &info); if (GetInterfaceInfo(&info)) { fName = info.info.name; fID = ID; // printf("%s fine: name:%s, fID:%ld\n", __func__, info.info.name, fID); } else { fName = ""; fID = PPP_UNDEFINED_INTERFACE_ID; // printf("%s fail: name:%s, fID:%ld\n", __func__, "", fID); return B_ERROR; } // printf("Set To %ld end =============================\n", ID); return B_OK; } /*! \brief Use this method for accessing additional PPP features. \param op Any value of ppp_control_ops. \param data Some ops require you to pass a structure or other data using this argument. \param length Make sure this value is correct (e.g.: size of structure). \return - \c B_OK: Operation was successful. - \c B_BAD_INDEX: The interface does not exist. - any other value: The PPP stack could not be loaded. */ status_t PPPInterface::Control(uint32 op, void *data, size_t length) const { if (InitCheck() != B_OK) { printf("%s:InitCheck fail\n", __func__); return InitCheck(); } ppp_control_info info; control_net_module_args args; sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_CONTROL_INTERFACE; args.data = &info; args.length = sizeof(ppp_control_info); info.index = ID(); info.op = op; info.data = data; info.length = length; printf("PPPInterface::Control: ppp_control_info %p control_net_module_args %p data %p \n", &info, &args, data); status_t status = ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args); if (status != B_OK) printf("%s:%s: fail\n", __FILE__, __func__); return status; } //! Sets the username used for authentication. bool PPPInterface::SetUsername(const char *username) const { printf("PPPInterface::SetUsername\n"); if (InitCheck() != B_OK || !username) return false; return Control(PPPC_SET_USERNAME, const_cast(username), strlen(username)) == B_OK; } //! Sets the password used for authentication. bool PPPInterface::SetPassword(const char *password) const { printf("PPPInterface::SetPassword\n"); if (InitCheck() != B_OK || !password) return false; return Control(PPPC_SET_PASSWORD, const_cast(password), strlen(password)) == B_OK; } //! Sets whether a request window should be shown before connecting. bool PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const { printf("PPPInterface::SetAskBeforeConnecting\n"); if (InitCheck() != B_OK) return false; uint32 value = askBeforeConnecting ? 1 : 0; return Control(PPPC_SET_ASK_BEFORE_CONNECTING, &value, sizeof(value)) == B_OK; } /*! \brief Find BEntry to the interface settings that this object represents. \param entry The entry gets stored in this argument. \return - \c B_OK: The settings file was saved in \a entry. - \c B_BAD_INDEX: The interface does not exist. - \c B_BAD_VALUE: Either \a entry was \c NULL or the interface is anonymous. - any other value: The interface could not be found. */ status_t PPPInterface::GetSettingsEntry(BEntry *entry) const { printf("PPPInterface::GetSettingsEntry\n"); if (InitCheck() != B_OK) return InitCheck(); else if (!entry || strlen(Name()) == 0) return B_BAD_VALUE; BDirectory directory(PTP_INTERFACE_SETTINGS_PATH); return directory.FindEntry(Name(), entry, true); } /*! \brief Get the ppp_interface_info_t structure. \return \c true on success, \c false otherwise. */ bool PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) { // printf("InitCheck fail %s info at:%p", __func__, info); return false; } return Control(PPPC_GET_INTERFACE_INFO, info, sizeof(ppp_interface_info_t)) == B_OK; } bool PPPInterface::ControlDevice(ppp_device_info_t *info) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; ppp_control_info controlInfo; controlInfo.op = PPPC_GET_DEVICE_INFO; controlInfo.index = 0; controlInfo.data = info; controlInfo.length = sizeof(ppp_device_info_t); return Control(PPPC_CONTROL_DEVICE, &controlInfo, sizeof(ppp_control_info)) == B_OK; } bool PPPInterface::ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; ppp_control_info controlInfo; controlInfo.index = handlerindex; controlInfo.op = handlerOP; controlInfo.data = info; controlInfo.length = sizeof(ppp_simple_handler_info_t); return Control(PPPC_CONTROL_OPTION_HANDLER, &controlInfo, sizeof(ppp_control_info)) == B_OK; } bool PPPInterface::ControlChild(void *info, uint32 childindex, uint32 childOP) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; ppp_control_info controlInfo; controlInfo.index = childindex; controlInfo.op = childOP; controlInfo.data = info; // controlInfo.length = sizeof(ppp_simple_handler_info_t); return Control(PPPC_CONTROL_CHILD, &controlInfo, sizeof(ppp_control_info)) == B_OK; } bool PPPInterface::ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; ppp_control_info controlInfo; controlInfo.index = LCPExtensionindex; controlInfo.op = LCPExtensionOP; controlInfo.data = info; controlInfo.length = sizeof(ppp_simple_handler_info_t); return Control(PPPC_CONTROL_LCP_EXTENSION, &controlInfo, sizeof(ppp_control_info)) == B_OK; } bool PPPInterface::ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 protocolOP) const { // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; ppp_control_info controlInfo; controlInfo.index = protocolindex; controlInfo.op = protocolOP; controlInfo.data = info; controlInfo.length = sizeof(ppp_protocol_info_t); return Control(PPPC_CONTROL_PROTOCOL, &controlInfo, sizeof(ppp_control_info)) == B_OK; } /*! \brief Get transfer statistics for this interface. \param statistics The structure is copied into this argument. \return \c true on success, \c false otherwise. */ bool PPPInterface::GetStatistics(ppp_statistics *statistics) const { printf("PPPInterface::GetStatistics\n"); if (!statistics) return false; return Control(PPPC_GET_STATISTICS, statistics, sizeof(ppp_statistics)) == B_OK; } //! Compares interface's settings to given driver_settings structure. bool PPPInterface::HasSettings(const driver_settings *settings) const { printf("PPPInterface::HasSettings\n"); if (InitCheck() != B_OK || !settings) return false; if (Control(PPPC_HAS_INTERFACE_SETTINGS, const_cast(settings), sizeof(driver_settings)) == B_OK) return true; return false; } //! Brings the interface up. bool PPPInterface::Up() const { if (InitCheck() != B_OK) return false; BNetworkInterface interface(Name()); if (!interface.Exists()) return false; int32 currentFlags = interface.Flags(); currentFlags |= IFF_UP; status_t status = interface.SetFlags(currentFlags); if (status != B_OK) return false; return true; int32 id = ID(); control_net_module_args args; sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_BRING_INTERFACE_UP; args.data = &id; args.length = sizeof(id); return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; } //! Brings the interface down which causes the deletion of the interface. bool PPPInterface::Down() const { if (InitCheck() != B_OK) return false; BNetworkInterface interface(Name()); if (!interface.Exists()) return false; int32 currentFlags = interface.Flags(); currentFlags &= ~IFF_UP; status_t status = interface.SetFlags(currentFlags); if (status != B_OK) return false; return true; int32 id = ID(); control_net_module_args args; sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_BRING_INTERFACE_DOWN; args.data = &id; args.length = sizeof(id); return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; } /*! \brief Requests report messages from the interface. \param type The type of report. \param thread Receiver thread. \param flags Optional flags. \return \c true on success \c false otherwise. */ bool PPPInterface::EnableReports(ppp_report_type type, thread_id thread, int32 flags) const { printf("PPPInterface::EnableReports\n"); ppp_report_request request; request.type = type; request.thread = thread; request.flags = flags; return Control(PPPC_ENABLE_REPORTS, &request, sizeof(request)) == B_OK; } /*! \brief Removes thread from list of report requestors of this interface. \param type The type of report. \param thread Receiver thread. \return \c true on success \c false otherwise. */ bool PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const { printf("PPPInterface::DisableReports\n"); ppp_report_request request; request.type = type; request.thread = thread; return Control(PPPC_DISABLE_REPORTS, &request, sizeof(request)) == B_OK; }