1 /* 2 * Copyright 2003-2004, Waldemar Kornewald <Waldemar.Kornewald@web.de> 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 = PPP_UNDEFINED_INTERFACE_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 The interface's info structure is cached in this object. If you want to update 77 its values you must call \c SetTo() again or use \c Control() with an op of 78 \c PPPC_GET_INTERFACE_INFO.\n 79 If this fails it will set the interface's \a ID to \c PPP_UNDEFINED_INTERFACE_ID. 80 81 \param ID The ID of the new interface. 82 83 \return 84 - \c B_OK: Object could be initialized successfully and the interface exists. 85 - \c B_BAD_INDEX: The interface does not exist. 86 - any other value: The PPP stack could not be loaded. 87 88 \sa Control() 89 */ 90 status_t 91 PPPInterface::SetTo(ppp_interface_id ID) 92 { 93 if(fFD < 0) 94 return B_ERROR; 95 96 fID = ID; 97 98 status_t error = Control(PPPC_GET_INTERFACE_INFO, &fInfo, sizeof(fInfo)); 99 if(error != B_OK) { 100 memset(&fInfo, 0, sizeof(fInfo)); 101 fID = PPP_UNDEFINED_INTERFACE_ID; 102 } 103 104 return error; 105 } 106 107 108 /*! \brief Use this method for accessing additional PPP features. 109 110 \param op Any value of ppp_control_ops. 111 \param data Some ops require you to pass a structure or other data using this 112 argument. 113 \param length Make sure this value is correct (e.g.: size of structure). 114 115 \return 116 - \c B_OK: Operation was successful. 117 - \c B_BAD_INDEX: The interface does not exist. 118 - any other value: The PPP stack could not be loaded. 119 */ 120 status_t 121 PPPInterface::Control(uint32 op, void *data, size_t length) const 122 { 123 if(InitCheck() != B_OK) 124 return InitCheck(); 125 126 ppp_control_info control; 127 control_net_module_args args; 128 129 args.name = PPP_INTERFACE_MODULE_NAME; 130 args.op = PPPC_CONTROL_INTERFACE; 131 args.data = &control; 132 args.length = sizeof(control); 133 134 control.index = ID(); 135 control.op = op; 136 control.data = data; 137 control.length = length; 138 139 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args); 140 } 141 142 143 /*! \brief Find BEntry to the interface settings that this object represents. 144 145 \param entry The entry gets stored in this argument. 146 147 \return 148 - \c B_OK: The settings file was saved in \a entry. 149 - \c B_BAD_INDEX: The interface does not exist. 150 - \c B_BAD_VALUE: Either \a entry was \c NULL or the interface is anonymous. 151 - any other value: The interface could not be found. 152 */ 153 status_t 154 PPPInterface::GetSettingsEntry(BEntry *entry) const 155 { 156 if(InitCheck() != B_OK) 157 return InitCheck(); 158 else if(!entry || strlen(Name()) == 0) 159 return B_BAD_VALUE; 160 161 BDirectory directory(PTP_INTERFACE_SETTINGS_PATH); 162 return directory.FindEntry(Name(), entry, true); 163 } 164 165 166 /*! \brief Get the cached ppp_interface_info_t structure. 167 168 \param info The info structure is copied into this argument. 169 170 \return \c true on success, \c false otherwise. 171 */ 172 bool 173 PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const 174 { 175 if(InitCheck() != B_OK || !info) 176 return false; 177 178 memcpy(info, &fInfo, sizeof(fInfo)); 179 180 return true; 181 } 182 183 184 /*! \brief Get transfer statistics for this interface. 185 186 \param statistics The structure is copied into this argument. 187 188 \return \c true on success, \c false otherwise. 189 */ 190 bool 191 PPPInterface::GetStatistics(ppp_statistics *statistics) const 192 { 193 if(!statistics) 194 return false; 195 196 return Control(PPPC_GET_STATISTICS, statistics, sizeof(ppp_statistics)) == B_OK; 197 } 198 199 200 //! Compares interface's settings to given driver_settings structure. 201 bool 202 PPPInterface::HasSettings(const driver_settings *settings) const 203 { 204 if(InitCheck() != B_OK || !settings) 205 return false; 206 207 if(Control(PPPC_HAS_INTERFACE_SETTINGS, const_cast<driver_settings*>(settings), 208 sizeof(driver_settings)) == B_OK) 209 return true; 210 211 return false; 212 } 213 214 215 /*! \brief Changes the current interface profile. 216 217 You may change the interface's profile at any time. The changes take effect when 218 the interface connects. 219 220 \param profile The new profile. 221 */ 222 void 223 PPPInterface::SetProfile(const driver_settings *profile) const 224 { 225 if(InitCheck() != B_OK || !profile) 226 return; 227 228 Control(PPPC_SET_PROFILE, const_cast<driver_settings*>(profile), 0); 229 } 230 231 232 //! Brings the interface up. 233 bool 234 PPPInterface::Up() const 235 { 236 if(InitCheck() != B_OK) 237 return false; 238 239 int32 id = ID(); 240 control_net_module_args args; 241 args.name = PPP_INTERFACE_MODULE_NAME; 242 args.op = PPPC_BRING_INTERFACE_UP; 243 args.data = &id; 244 args.length = sizeof(id); 245 246 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; 247 } 248 249 250 //! Brings the interface down which causes the deletion of the interface. 251 bool 252 PPPInterface::Down() const 253 { 254 if(InitCheck() != B_OK) 255 return false; 256 257 int32 id = ID(); 258 control_net_module_args args; 259 args.name = PPP_INTERFACE_MODULE_NAME; 260 args.op = PPPC_BRING_INTERFACE_DOWN; 261 args.data = &id; 262 args.length = sizeof(id); 263 264 return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args) == B_OK; 265 } 266 267 268 /*! \brief Requests report messages from the interface. 269 270 \param type The type of report. 271 \param thread Receiver thread. 272 \param flags Optional flags. 273 274 \return \c true on success \c false otherwise. 275 */ 276 bool 277 PPPInterface::EnableReports(ppp_report_type type, thread_id thread, 278 int32 flags = PPP_NO_FLAGS) const 279 { 280 ppp_report_request request; 281 request.type = type; 282 request.thread = thread; 283 request.flags = flags; 284 285 return Control(PPPC_ENABLE_REPORTS, &request, sizeof(request)) == B_OK; 286 } 287 288 289 /*! \brief Removes thread from list of report requestors of this interface. 290 291 \param type The type of report. 292 \param thread Receiver thread. 293 294 \return \c true on success \c false otherwise. 295 */ 296 bool 297 PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const 298 { 299 ppp_report_request request; 300 request.type = type; 301 request.thread = thread; 302 303 return Control(PPPC_DISABLE_REPORTS, &request, sizeof(request)) == B_OK; 304 } 305