2 * kPPP: A pppd Front End for the KDE project
6 * Copyright (C) 1997,98 Bernd Johannes Wuebben,
11 * This file was contributed by Harri Porten <porten@tu-harburg.de>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Library General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with this program; if not, write to the Free
26 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 #define _XOPEN_SOURCE_EXTENDED 1
39 #include <sys/types.h>
40 #include <sys/socket.h>
49 extern "C" unsigned int alarm(unsigned int);
54 ssize_t
sendmsg(int, const struct msghdr
*, int);
55 ssize_t
recvmsg(int, struct msghdr
*, int);
65 #include "requester.h"
68 Requester
*Requester::rq
= 0L;
70 Requester::Requester(int s
) : socket(s
) {
76 Requester::~Requester() {
80 // Receive file name and file descriptors from envoy
82 int Requester::recvFD() {
83 struct { struct cmsghdr cmsg
; int fd
; } control
;
85 struct ResponseHeader response
;
88 int flags
= 0, fd
, len
;
96 iov
.iov_base
= IOV_BASE_CAST
&response
;
97 iov
.iov_len
= sizeof(struct ResponseHeader
);
99 cmsglen
= CMSG_LEN(sizeof(int));
101 cmsglen
= sizeof(struct cmsghdr
) + sizeof(int);
103 control
.cmsg
.cmsg_len
= cmsglen
;
104 control
.cmsg
.cmsg_level
= SOL_SOCKET
;
105 control
.cmsg
.cmsg_type
= MY_SCM_RIGHTS
;
107 msg
.msg_control
= (char *) &control
;
108 msg
.msg_controllen
= control
.cmsg
.cmsg_len
;
112 // set alarm in case recvmsg() hangs
113 signal(SIGALRM
, recv_timeout
);
116 len
= recvmsg(socket
, &msg
, flags
);
119 signal(SIGALRM
, SIG_DFL
);
122 kError(5002) << "recvmsg failed " << strerror(errno
) << endl
;
124 } else if (msg
.msg_controllen
< cmsglen
) {
125 kError(5002) << "recvmsg: truncated message " << strerror(errno
) << endl
;
129 fd
= *((int *)CMSG_DATA(&control
.cmsg
));
131 fd
= *((int *) control
.cmsg
.cmsg_data
);
133 kDebug(5002) << "response.status: " << response
.status
;
134 assert(response
.status
<= 0);
135 if(response
.status
< 0)
136 return response
.status
;
142 bool Requester::recvResponse() {
146 struct ResponseHeader response
;
153 msg
.msg_control
= 0L;
154 msg
.msg_controllen
= 0;
156 iov
.iov_base
= IOV_BASE_CAST
&response
;
157 iov
.iov_len
= sizeof(struct ResponseHeader
);
158 kDebug(5002) << "recvResponse(): waiting for message";
159 len
= recvmsg(socket
, &msg
, flags
);
160 kDebug(5002) << "recvResponse(): received message";
163 kDebug(5002) << "Interrupted system call. Continuing.";
165 perror("recvmsg failed");
167 kDebug(5002) << "response.status: " << response
.status
;
170 lastStatus
= response
.status
;
171 return (response
.status
== 0);
174 int Requester::openModem(const QString
& dev
) {
176 struct OpenModemRequest req
;
177 req
.header
.type
= Opener::OpenDevice
;
178 if((req
.deviceNum
= indexDevice(dev
)) < 0)
181 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
186 int Requester::openLockfile(const QString
&dev
, int flags
) {
188 struct OpenLockRequest req
;
190 req
.header
.type
= Opener::OpenLock
;
191 if((req
.deviceNum
= indexDevice(dev
)) < 0)
195 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
200 bool Requester::removeLockfile() {
202 struct RemoveLockRequest req
;
204 req
.header
.type
= Opener::RemoveLock
;
206 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
207 return recvResponse();
211 int Requester::openResolv(int flags
) {
213 struct OpenResolvRequest req
;
215 req
.header
.type
= Opener::OpenResolv
;
217 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
222 int Requester::openSysLog() {
224 struct OpenLogRequest req
;
226 req
.header
.type
= Opener::OpenSysLog
;
227 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
232 bool Requester::setSecret(int method
, const QString
&name
, const QString
&password
) {
234 #warning check if QString != 0 means using isNull or isEmpty
236 assert(!name
.isNull());
237 assert(!password
.isNull());
239 if(method
== AUTH_PAPCHAP
)
240 return setSecret(AUTH_PAP
, name
, password
) &&
241 setSecret(AUTH_CHAP
, name
, password
);
243 struct SetSecretRequest req
;
244 req
.header
.type
= Opener::SetSecret
;
247 req
.method
= Opener::PAP
;
250 req
.method
= Opener::CHAP
;
255 strncpy(req
.username
, QFile::encodeName(name
), Opener::MaxStrLen
);
256 req
.username
[Opener::MaxStrLen
] = '\0';
257 strncpy(req
.password
, QFile::encodeName(password
), Opener::MaxStrLen
);
258 req
.password
[Opener::MaxStrLen
] = '\0';
259 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
260 return recvResponse();
263 bool Requester::removeSecret(int authMethod
) {
264 struct RemoveSecretRequest req
;
265 req
.header
.type
= Opener::RemoveSecret
;
266 if(authMethod
== AUTH_PAP
)
267 req
.method
= Opener::PAP
;
269 if(authMethod
== AUTH_CHAP
)
270 req
.method
= Opener::CHAP
;
274 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
275 return recvResponse();
278 bool Requester::setHostname(const QString
&name
) {
281 struct SetHostnameRequest req
;
282 req
.header
.type
= Opener::SetHostname
;
283 strncpy(req
.name
, QFile::encodeName(name
), Opener::MaxStrLen
);
284 req
.name
[Opener::MaxStrLen
] = '\0';
285 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
286 return recvResponse();
290 bool Requester::execPPPDaemon(const QString
&arguments
) {
291 struct ExecDaemonRequest req
;
292 req
.header
.type
= Opener::ExecPPPDaemon
;
293 strncpy(req
.arguments
, QFile::encodeName(arguments
), MAX_CMDLEN
);
294 req
.arguments
[MAX_CMDLEN
] = '\0';
295 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
296 if(recvResponse()==0) {
297 gpppdata
.setpppdRunning(true);
304 bool Requester::killPPPDaemon() {
305 struct KillDaemonRequest req
;
306 gpppdata
.setpppdRunning(false);
307 req
.header
.type
= Opener::KillPPPDaemon
;
308 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
309 return recvResponse();
312 int Requester::pppdExitStatus()
314 struct PPPDExitStatusRequest req
;
315 req
.header
.type
= Opener::PPPDExitStatus
;
316 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
317 return recvResponse();
320 bool Requester::stop() {
322 struct StopRequest req
;
323 req
.header
.type
= Opener::Stop
;
324 sendRequest((struct RequestHeader
*) &req
, sizeof(req
));
326 // return recvResponse();
331 bool Requester::sendRequest(struct RequestHeader
*request
, int len
) {
333 request
->len
= len
- sizeof(struct RequestHeader
);
338 iov
.iov_base
= IOV_BASE_CAST request
;
345 msg
.msg_control
= 0L;
346 msg
.msg_controllen
= 0;
347 kDebug(5002) << "sendRequest: trying to send msg type " << request
->type
;
348 sendmsg(socket
, &msg
, 0);
349 kDebug(5002) << "sendRequest: sent message";
355 int Requester::indexDevice(const QString
&dev
) {
359 for(int i
= 0; devices
[i
]; i
++)
360 if (dev
== devices
[i
])
366 void recv_timeout(int) {
367 kDebug(5002) << "timeout()";