Contact cannot be a null ptr, and it is accessed before anyway. Disscussed with kedge.
[kdenetwork.git] / kppp / requester.cpp
blob31667bb17c756c797450da693f69c8ce47360d94
1 /*
2 * kPPP: A pppd Front End for the KDE project
4 * $Id$
6 * Copyright (C) 1997,98 Bernd Johannes Wuebben,
7 * Mario Weilguni,
8 * Harri Porten
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.
29 #ifdef __osf__
30 #define _XOPEN_SOURCE_EXTENDED 1
31 #endif
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <signal.h>
38 #include <sys/uio.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42 #include <fcntl.h>
43 #include <assert.h>
44 #include <errno.h>
45 #include <string.h>
47 #ifdef __osf__
48 #undef accept
49 extern "C" unsigned int alarm(unsigned int);
50 #endif
52 #ifdef _XPG4_2
53 extern "C" {
54 ssize_t sendmsg(int, const struct msghdr *, int);
55 ssize_t recvmsg(int, struct msghdr *, int);
57 #endif
59 #include <kdebug.h>
60 #include <qfile.h>
62 #include "auth.h"
63 #include "pppdata.h"
64 #include "opener.h"
65 #include "requester.h"
66 #include "devices.h"
68 Requester *Requester::rq = 0L;
70 Requester::Requester(int s) : socket(s) {
71 assert(rq==0L);
72 rq = this;
73 lastStatus = -1;
76 Requester::~Requester() {
80 // Receive file name and file descriptors from envoy
82 int Requester::recvFD() {
83 struct { struct cmsghdr cmsg; int fd; } control;
84 struct msghdr msg;
85 struct ResponseHeader response;
87 struct iovec iov;
88 int flags = 0, fd, len;
89 size_t cmsglen;
91 msg.msg_name = 0L;
92 msg.msg_namelen = 0;
93 msg.msg_iov = &iov;
94 msg.msg_iovlen = 1;
96 iov.iov_base = IOV_BASE_CAST &response;
97 iov.iov_len = sizeof(struct ResponseHeader);
98 #ifdef CMSG_LEN
99 cmsglen = CMSG_LEN(sizeof(int));
100 #else
101 cmsglen = sizeof(struct cmsghdr) + sizeof(int);
102 #endif
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;
110 fd = -1;
112 // set alarm in case recvmsg() hangs
113 signal(SIGALRM, recv_timeout);
114 alarm(2);
116 len = recvmsg(socket, &msg, flags);
118 alarm(0);
119 signal(SIGALRM, SIG_DFL);
121 if(len <= 0) {
122 kError(5002) << "recvmsg failed " << strerror(errno) << endl;
123 return -1;
124 } else if (msg.msg_controllen < cmsglen) {
125 kError(5002) << "recvmsg: truncated message " << strerror(errno) << endl;
126 exit(1);
127 } else {
128 #ifdef CMSG_DATA
129 fd = *((int *)CMSG_DATA(&control.cmsg));
130 #else
131 fd = *((int *) control.cmsg.cmsg_data);
132 #endif
133 kDebug(5002) << "response.status: " << response.status;
134 assert(response.status <= 0);
135 if(response.status < 0)
136 return response.status;
139 return fd;
142 bool Requester::recvResponse() {
144 struct msghdr msg;
145 struct iovec iov;
146 struct ResponseHeader response;
147 int flags = 0, len;
149 msg.msg_name = 0L;
150 msg.msg_namelen = 0;
151 msg.msg_iov = &iov;
152 msg.msg_iovlen = 1;
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";
161 if (len <= 0) {
162 if (errno == EINTR)
163 kDebug(5002) << "Interrupted system call. Continuing.";
164 else
165 perror("recvmsg failed");
166 } else {
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)
179 return -1;
181 sendRequest((struct RequestHeader *) &req, sizeof(req));
182 return recvFD();
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)
192 return -1;
193 req.flags = flags;
195 sendRequest((struct RequestHeader *) &req, sizeof(req));
196 return recvFD();
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;
216 req.flags = flags;
217 sendRequest((struct RequestHeader *) &req, sizeof(req));
218 return recvFD();
222 int Requester::openSysLog() {
224 struct OpenLogRequest req;
226 req.header.type = Opener::OpenSysLog;
227 sendRequest((struct RequestHeader *) &req, sizeof(req));
228 return recvFD();
232 bool Requester::setSecret(int method, const QString &name, const QString &password) {
233 #ifdef __GNUC__
234 #warning check if QString != 0 means using isNull or isEmpty
235 #endif
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;
245 switch(method) {
246 case AUTH_PAP:
247 req.method = Opener::PAP;
248 break;
249 case AUTH_CHAP:
250 req.method = Opener::CHAP;
251 break;
252 default:
253 return false;
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;
268 else
269 if(authMethod == AUTH_CHAP)
270 req.method = Opener::CHAP;
271 else
272 return false;
274 sendRequest((struct RequestHeader *) &req, sizeof(req));
275 return recvResponse();
278 bool Requester::setHostname(const QString &name) {
279 if (name.isEmpty())
280 return false;
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);
298 return true;
299 } else
300 return false;
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();
327 return true;
331 bool Requester::sendRequest(struct RequestHeader *request, int len) {
333 request->len = len - sizeof(struct RequestHeader);
335 struct msghdr msg;
336 struct iovec iov;
338 iov.iov_base = IOV_BASE_CAST request;
339 iov.iov_len = len;
341 msg.msg_name = 0L;
342 msg.msg_namelen = 0;
343 msg.msg_iov = &iov;
344 msg.msg_iovlen = 1;
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";
351 return true;
355 int Requester::indexDevice(const QString &dev) {
357 int index = -1;
359 for(int i = 0; devices[i]; i++)
360 if (dev == devices[i])
361 index = i;
362 return index;
366 void recv_timeout(int) {
367 kDebug(5002) << "timeout()";