diff options
Diffstat (limited to 'kppp/requester.cpp')
-rw-r--r-- | kppp/requester.cpp | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/kppp/requester.cpp b/kppp/requester.cpp new file mode 100644 index 00000000..bca7f63a --- /dev/null +++ b/kppp/requester.cpp @@ -0,0 +1,365 @@ +/* + * kPPP: A pppd Front End for the KDE project + * + * $Id$ + * + * Copyright (C) 1997,98 Bernd Johannes Wuebben, + * Mario Weilguni, + * Harri Porten + * + * + * This file was contributed by Harri Porten <porten@tu-harburg.de> + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef __osf__ +#define _XOPEN_SOURCE_EXTENDED 1 +#endif + + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <sys/uio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <fcntl.h> +#include <assert.h> +#include <errno.h> +#include <string.h> + +#ifdef __osf__ +#undef accept +extern "C" unsigned int alarm(unsigned int); +#endif + +#ifdef _XPG4_2 +extern "C" { + ssize_t sendmsg(int, const struct msghdr *, int); + ssize_t recvmsg(int, struct msghdr *, int); +} +#endif + +#include <kdebug.h> +#include <qfile.h> + +#include "auth.h" +#include "pppdata.h" +#include "opener.h" +#include "requester.h" +#include "devices.h" + +Requester *Requester::rq = 0L; + +Requester::Requester(int s) : socket(s) { + assert(rq==0L); + rq = this; + lastStatus = -1; +} + +Requester::~Requester() { +} + +// +// Receive file name and file descriptors from envoy +// +int Requester::recvFD() { + struct { struct cmsghdr cmsg; int fd; } control; + struct msghdr msg; + struct ResponseHeader response; + + struct iovec iov; + int flags = 0, fd, len; + size_t cmsglen; + + msg.msg_name = 0L; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = IOV_BASE_CAST &response; + iov.iov_len = sizeof(struct ResponseHeader); +#ifdef CMSG_LEN + cmsglen = CMSG_LEN(sizeof(int)); +#else + cmsglen = sizeof(struct cmsghdr) + sizeof(int); +#endif + control.cmsg.cmsg_len = cmsglen; + control.cmsg.cmsg_level = SOL_SOCKET; + control.cmsg.cmsg_type = MY_SCM_RIGHTS; + + msg.msg_control = (char *) &control; + msg.msg_controllen = control.cmsg.cmsg_len; + + fd = -1; + + // set alarm in case recvmsg() hangs + signal(SIGALRM, recv_timeout); + alarm(2); + + len = recvmsg(socket, &msg, flags); + + alarm(0); + signal(SIGALRM, SIG_DFL); + + if(len <= 0) { + kdError(5002) << "recvmsg failed " << strerror(errno) << endl; + return -1; + } else if (msg.msg_controllen < cmsglen) { + kdError(5002) << "recvmsg: truncated message " << strerror(errno) << endl; + exit(1); + } else { +#ifdef CMSG_DATA + fd = *((int *)CMSG_DATA(&control.cmsg)); +#else + fd = *((int *) control.cmsg.cmsg_data); +#endif + kdDebug(5002) << "response.status: " << response.status << endl; + assert(response.status <= 0); + if(response.status < 0) + return response.status; + } + + return fd; +} + +bool Requester::recvResponse() { + + struct msghdr msg; + struct iovec iov; + struct ResponseHeader response; + int flags = 0, len; + + msg.msg_name = 0L; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = 0L; + msg.msg_controllen = 0; + + iov.iov_base = IOV_BASE_CAST &response; + iov.iov_len = sizeof(struct ResponseHeader); + kdDebug(5002) << "recvResponse(): waiting for message" << endl; + len = recvmsg(socket, &msg, flags); + kdDebug(5002) << "recvResponse(): received message" << endl; + if (len <= 0) { + if (errno == EINTR) + kdDebug(5002) << "Interrupted system call. Continuing." << endl; + else + perror("recvmsg failed"); + } else { + kdDebug(5002) << "response.status: " << response.status << endl; + } + + lastStatus = response.status; + return (response.status == 0); +} + +int Requester::openModem(const QString & dev) { + + struct OpenModemRequest req; + req.header.type = Opener::OpenDevice; + if((req.deviceNum = indexDevice(dev)) < 0) + return -1; + + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvFD(); +} + + +int Requester::openLockfile(const QString &dev, int flags) { + + struct OpenLockRequest req; + + req.header.type = Opener::OpenLock; + if((req.deviceNum = indexDevice(dev)) < 0) + return -1; + req.flags = flags; + + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvFD(); +} + + +bool Requester::removeLockfile() { + + struct RemoveLockRequest req; + + req.header.type = Opener::RemoveLock; + + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + + +int Requester::openResolv(int flags) { + + struct OpenResolvRequest req; + + req.header.type = Opener::OpenResolv; + req.flags = flags; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvFD(); +} + + +int Requester::openSysLog() { + + struct OpenLogRequest req; + + req.header.type = Opener::OpenSysLog; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvFD(); +} + + +bool Requester::setSecret(int method, const QString &name, const QString &password) { + assert(name!=0); + assert(password!=0); + + if(method == AUTH_PAPCHAP) + return setSecret(AUTH_PAP, name, password) && + setSecret(AUTH_CHAP, name, password); + + struct SetSecretRequest req; + req.header.type = Opener::SetSecret; + switch(method) { + case AUTH_PAP: + req.method = Opener::PAP; + break; + case AUTH_CHAP: + req.method = Opener::CHAP; + break; + default: + return false; + } + strncpy(req.username, QFile::encodeName(name), Opener::MaxStrLen); + req.username[Opener::MaxStrLen] = '\0'; + strncpy(req.password, QFile::encodeName(password), Opener::MaxStrLen); + req.password[Opener::MaxStrLen] = '\0'; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + +bool Requester::removeSecret(int authMethod) { + struct RemoveSecretRequest req; + req.header.type = Opener::RemoveSecret; + if(authMethod == AUTH_PAP) + req.method = Opener::PAP; + else + if(authMethod == AUTH_CHAP) + req.method = Opener::CHAP; + else + return false; + + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + +bool Requester::setHostname(const QString &name) { + if (name.isEmpty()) + return false; + struct SetHostnameRequest req; + req.header.type = Opener::SetHostname; + strncpy(req.name, QFile::encodeName(name), Opener::MaxStrLen); + req.name[Opener::MaxStrLen] = '\0'; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + + +bool Requester::execPPPDaemon(const QString &arguments) { + struct ExecDaemonRequest req; + req.header.type = Opener::ExecPPPDaemon; + strncpy(req.arguments, QFile::encodeName(arguments), MAX_CMDLEN); + req.arguments[MAX_CMDLEN] = '\0'; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + if(recvResponse()==0) { + gpppdata.setpppdRunning(true); + return true; + } else + return false; +} + + +bool Requester::killPPPDaemon() { + struct KillDaemonRequest req; + gpppdata.setpppdRunning(false); + req.header.type = Opener::KillPPPDaemon; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + +int Requester::pppdExitStatus() +{ + struct PPPDExitStatusRequest req; + req.header.type = Opener::PPPDExitStatus; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + return recvResponse(); +} + +bool Requester::stop() { + + struct StopRequest req; + req.header.type = Opener::Stop; + sendRequest((struct RequestHeader *) &req, sizeof(req)); + + // return recvResponse(); + return true; +} + + +bool Requester::sendRequest(struct RequestHeader *request, int len) { + + request->len = len - sizeof(struct RequestHeader); + + struct msghdr msg; + struct iovec iov; + + iov.iov_base = IOV_BASE_CAST request; + iov.iov_len = len; + + msg.msg_name = 0L; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = 0L; + msg.msg_controllen = 0; + kdDebug(5002) << "sendRequest: trying to send msg type " << request->type << endl; + sendmsg(socket, &msg, 0); + kdDebug(5002) << "sendRequest: sent message" << endl; + + return true; +} + + +int Requester::indexDevice(const QString &dev) { + + int index = -1; + + for(int i = 0; devices[i]; i++) + if (dev == devices[i]) + index = i; + return index; +} + + +void recv_timeout(int) { + kdDebug(5002) << "timeout()" << endl; +} |