xref: /haiku/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp (revision d1d811ec7007913f727f6b44d2d730554eacfa19)
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