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 <unistd.h> 17 #include "_libppputils.h" 18 19 #include <Path.h> 20 #include <Directory.h> 21 #include <Entry.h> 22 23 24 /*! \brief Sets the interface to \a ID. 25 26 \param ID The ID of the new interface. 27 */ 28 PPPInterface::PPPInterface(ppp_interface_id ID) 29 { 30 fFD = open(get_stack_driver_path(), O_RDWR); 31 32 SetTo(ID); 33 } 34 35 36 //! Copy constructor. 37 PPPInterface::PPPInterface(const PPPInterface& copy) 38 { 39 fFD = open(get_stack_driver_path(), O_RDWR); 40 41 SetTo(copy.ID()); 42 } 43 44 45 //! Destructor. 46 PPPInterface::~PPPInterface() 47 { 48 if (fFD >= 0) 49 close(fFD); 50 } 51 52 53 /*! \brief Checks if object was created correctly. 54 55 You should always call this method after you constructed a PPPInterface object. 56 57 \return 58 - \c B_OK: Object could be initialized successfully and the interface exists. 59 - \c B_BAD_INDEX: The interface does not exist. 60 - \c B_ERROR: The PPP stack could not be loaded. 61 */ 62 status_t 63 PPPInterface::InitCheck() const 64 { 65 if (fFD < 0) 66 return B_ERROR; 67 if (fID == PPP_UNDEFINED_INTERFACE_ID) 68 return B_BAD_INDEX; 69 70 return B_OK; 71 } 72 73 74 /*! \brief Changes the current interface. 75 76 If this fails it will set the interface's \a ID to \c PPP_UNDEFINED_INTERFACE_ID. 77 78 \param ID The ID of the new interface. 79 80 \return 81 - \c B_OK: Object could be initialized successfully and the interface exists. 82 - \c B_BAD_INDEX: The interface does not exist. 83 - any other value: The PPP stack could not be loaded. 84 85 \sa Control() 86 */ 87 status_t 88 PPPInterface::SetTo(ppp_interface_id ID) 89 { 90 if (fFD < 0) 91 return B_ERROR; 92 93 ppp_interface_info_t info; 94 if (GetInterfaceInfo(&info)) { 95 fName = info.info.name; 96 fID = ID; 97 } else { 98 fName = ""; 99 fID = PPP_UNDEFINED_INTERFACE_ID; 100 return B_ERROR; 101 } 102 103 return B_OK; 104 } 105 106 107 /*! \brief Use this method for accessing additional PPP features. 108 109 \param op Any value of ppp_control_ops. 110 \param data Some ops require you to pass a structure or other data using this 111 argument. 112 \param length Make sure this value is correct (e.g.: size of structure). 113 114 \return 115 - \c B_OK: Operation was successful. 116 - \c B_BAD_INDEX: The interface does not exist. 117 - any other value: The PPP stack could not be loaded. 118 */ 119 status_t 120 PPPInterface::Control(uint32 op, void *data, size_t length) const 121 { 122 if (InitCheck() != B_OK) 123 return InitCheck(); 124 125 ppp_control_info control; 126 control_net_module_args args; 127 128 args.name = PPP_INTERFACE_MODULE_NAME; 129 args.op = PPPC_CONTROL_INTERFACE; 130 args.data = &control; 131 args.length = sizeof(control); 132 133 control.index = ID(); 134 control.op = op; 135 control.data = data; 136 control.length = length; 137 138 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args); 139 } 140 141 142 //! Sets the username used for authentication. 143 bool 144 PPPInterface::SetUsername(const char *username) const 145 { 146 if (InitCheck() != B_OK || !username) 147 return false; 148 149 return Control(PPPC_SET_USERNAME, const_cast<char*>(username), strlen(username)) 150 == B_OK; 151 } 152 153 154 //! Sets the password used for authentication. 155 bool 156 PPPInterface::SetPassword(const char *password) const 157 { 158 if (InitCheck() != B_OK || !password) 159 return false; 160 161 return Control(PPPC_SET_PASSWORD, const_cast<char*>(password), strlen(password)) 162 == B_OK; 163 } 164 165 166 //! Sets whether a request window should be shown before connecting. 167 bool 168 PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const 169 { 170 if (InitCheck() != B_OK) 171 return false; 172 173 uint32 value = askBeforeConnecting ? 1 : 0; 174 return Control(PPPC_SET_ASK_BEFORE_CONNECTING, &value, sizeof(value)) == B_OK; 175 } 176 177 178 /*! \brief Find BEntry to the interface settings that this object represents. 179 180 \param entry The entry gets stored in this argument. 181 182 \return 183 - \c B_OK: The settings file was saved in \a entry. 184 - \c B_BAD_INDEX: The interface does not exist. 185 - \c B_BAD_VALUE: Either \a entry was \c NULL or the interface is anonymous. 186 - any other value: The interface could not be found. 187 */ 188 status_t 189 PPPInterface::GetSettingsEntry(BEntry *entry) const 190 { 191 if (InitCheck() != B_OK) 192 return InitCheck(); 193 else if (!entry || strlen(Name()) == 0) 194 return B_BAD_VALUE; 195 196 BDirectory directory(PTP_INTERFACE_SETTINGS_PATH); 197 return directory.FindEntry(Name(), entry, true); 198 } 199 200 201 /*! \brief Get the ppp_interface_info_t structure. 202 203 \return \c true on success, \c false otherwise. 204 */ 205 bool 206 PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const 207 { 208 if (InitCheck() != B_OK || !info) 209 return false; 210 211 return Control(PPPC_GET_INTERFACE_INFO, &info, sizeof(ppp_interface_info_t)) 212 == B_OK; 213 } 214 215 216 /*! \brief Get transfer statistics for this interface. 217 218 \param statistics The structure is copied into this argument. 219 220 \return \c true on success, \c false otherwise. 221 */ 222 bool 223 PPPInterface::GetStatistics(ppp_statistics *statistics) const 224 { 225 if (!statistics) 226 return false; 227 228 return Control(PPPC_GET_STATISTICS, statistics, sizeof(ppp_statistics)) == B_OK; 229 } 230 231 232 //! Compares interface's settings to given driver_settings structure. 233 bool 234 PPPInterface::HasSettings(const driver_settings *settings) const 235 { 236 if (InitCheck() != B_OK || !settings) 237 return false; 238 239 if (Control(PPPC_HAS_INTERFACE_SETTINGS, const_cast<driver_settings*>(settings), 240 sizeof(driver_settings)) == B_OK) 241 return true; 242 243 return false; 244 } 245 246 247 //! Brings the interface up. 248 bool 249 PPPInterface::Up() const 250 { 251 if (InitCheck() != B_OK) 252 return false; 253 254 int32 id = ID(); 255 control_net_module_args args; 256 args.name = PPP_INTERFACE_MODULE_NAME; 257 args.op = PPPC_BRING_INTERFACE_UP; 258 args.data = &id; 259 args.length = sizeof(id); 260 261 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; 262 } 263 264 265 //! Brings the interface down which causes the deletion of the interface. 266 bool 267 PPPInterface::Down() const 268 { 269 if (InitCheck() != B_OK) 270 return false; 271 272 int32 id = ID(); 273 control_net_module_args args; 274 args.name = PPP_INTERFACE_MODULE_NAME; 275 args.op = PPPC_BRING_INTERFACE_DOWN; 276 args.data = &id; 277 args.length = sizeof(id); 278 279 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; 280 } 281 282 283 /*! \brief Requests report messages from the interface. 284 285 \param type The type of report. 286 \param thread Receiver thread. 287 \param flags Optional flags. 288 289 \return \c true on success \c false otherwise. 290 */ 291 bool 292 PPPInterface::EnableReports(ppp_report_type type, thread_id thread, 293 int32 flags) const 294 { 295 ppp_report_request request; 296 request.type = type; 297 request.thread = thread; 298 request.flags = flags; 299 300 return Control(PPPC_ENABLE_REPORTS, &request, sizeof(request)) == B_OK; 301 } 302 303 304 /*! \brief Removes thread from list of report requestors of this interface. 305 306 \param type The type of report. 307 \param thread Receiver thread. 308 309 \return \c true on success \c false otherwise. 310 */ 311 bool 312 PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const 313 { 314 ppp_report_request request; 315 request.type = type; 316 request.thread = thread; 317 318 return Control(PPPC_DISABLE_REPORTS, &request, sizeof(request)) == B_OK; 319 } 320