| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ksocks.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2001-2003 George Staikos <staikos@kde.org>
    00003
    00004    This library is free software; you can redistribute it and/or
    00005    modify it under the terms of the GNU Library General Public
    00006    License version 2 as published by the Free Software Foundation.
    00007
    00008    This library is distributed in the hope that it will be useful,
    00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00011    Library General Public License for more details.
    00012
    00013    You should have received a copy of the GNU Library General Public License
    00014    along with this library; see the file COPYING.LIB.  If not, write to
    00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00016    Boston, MA 02111-1307, USA.
    00017 */
    00018
    00019 #include <config.h>
    00020
    00021 #ifdef HAVE_SYS_TIME_H
    00022 #include <sys/time.h>
    00023 #endif
    00024
    00025 #include <qfile.h>
    00026 #include <qstring.h>
    00027 #include <qmap.h>
    00028
    00029 #include <klocale.h>
    00030 #include <kdebug.h>
    00031 #include "klibloader.h"
    00032 #include <kconfig.h>
    00033 #include <kapplication.h>
    00034
    00035 #include <sys/types.h>
    00036 #include <sys/socket.h>
    00037
    00038 #include <unistd.h>
    00039
    00040 #include "ksocks.h"
    00041
    00042 // DO NOT RE-ORDER THESE.
    00043 enum SymbolKeys {
    00044       S_SOCKSinit    =  0,
    00045       S_connect      =  1,
    00046       S_read         =  2,
    00047       S_write        =  3,
    00048       S_recvfrom     =  4,
    00049       S_sendto       =  5,
    00050       S_recv         =  6,
    00051       S_send         =  7,
    00052       S_getsockname  =  8,
    00053       S_getpeername  =  9,
    00054       S_accept       = 10,
    00055       S_select       = 11,
    00056       S_listen       = 12,
    00057       S_bind         = 13
    00058      };
    00059
    00060
    00061 extern "C" {
    00062 // Function pointer table
    00063 static int     (*F_SOCKSinit)   (char *) = 0L;
    00064 static int     (*F_connect)     (int, const struct sockaddr *, ksocklen_t) = 0L;
    00065 static signed long int (*F_read)        (int, void *, unsigned long int) = 0L;
    00066 static signed long int (*F_write)       (int, const void *, unsigned long int) = 0L;
    00067 static int     (*F_recvfrom)    (int, void *, unsigned long int, int, struct sockaddr *,
    00068                                  ksocklen_t *) = 0L;
    00069 static int     (*F_sendto)      (int, const void *, unsigned long int, int,
    00070                                  const struct sockaddr *, ksocklen_t) = 0L;
    00071 static int     (*F_recv)        (int, void *, unsigned long int, int) = 0L;
    00072 static int     (*F_send)        (int, const void *, unsigned long int, int) = 0L;
    00073 static int     (*F_getsockname) (int, struct sockaddr *, ksocklen_t *) = 0L;
    00074 static int     (*F_getpeername) (int, struct sockaddr *, ksocklen_t *) = 0L;
    00075 static int     (*F_accept)      (int, struct sockaddr *, ksocklen_t *) = 0L;
    00076 static int     (*F_select)      (int, fd_set *, fd_set *, fd_set *,
    00077                                                      struct timeval *) = 0L;
    00078 static int     (*F_listen)      (int, int) = 0L;
    00079 static int     (*F_bind)        (int, const struct sockaddr *, ksocklen_t) = 0L;
    00080 }
    00081
    00082
    00083 class KSocksTable {
    00084  public:
    00085    KSocksTable();
    00086   virtual ~KSocksTable();
    00087
    00088    // The name of each symbol and it's SOCKS replacement
    00089    QMap<SymbolKeys,QString>  symbols;
    00090    // The name of this library
    00091    QString                   myname;
    00092    bool                      hasWorkingAsyncConnect;
    00093 };
    00094
    00095
    00096 KSocksTable::KSocksTable() : myname("Unknown"), hasWorkingAsyncConnect(true) {
    00097 }
    00098
    00099 KSocksTable::~KSocksTable() {
    00100 }
    00101
    00102
    00103 /*
    00104  *   How to add support for a new SOCKS package.
    00105  *
    00106  *   1) Subclass KSocksTable as is done below and write out all the symbols
    00107  *   1.b) Give the class a "myname"
    00108  *   2) Make sure that all possible library names are written into the
    00109  *      _libNames string list.  Don't forget that different OSes name shared
    00110  *      libraries differently.  Expect .so, .sl, .a (!) (AIX does this).
    00111  *   3) Find a unique symbol in the library that we can use to identify that
    00112  *      library and write out the test case in the constructor
    00113  *   4) Make necessary changes to the KControl module in kdebase/kcontrol/....
    00114  *   5) TEST!
    00115  *
    00116  */
    00117
    00121
    00122
    00123 //
    00124 //    Support for NEC SOCKS client
    00125 //
    00126
    00127 class KNECSocksTable : public KSocksTable {
    00128   public:
    00129     KNECSocksTable();
    00130     virtual ~KNECSocksTable();
    00131 };
    00132
    00133
    00134 KNECSocksTable::KNECSocksTable() : KSocksTable() {
    00135   myname = i18n("NEC SOCKS client");
    00136   symbols.insert(S_SOCKSinit,   "SOCKSinit");
    00137   symbols.insert(S_connect,     "connect");
    00138   symbols.insert(S_read,        "read");
    00139   symbols.insert(S_write,       "write");
    00140   symbols.insert(S_recvfrom,    "recvfrom");
    00141   symbols.insert(S_sendto,      "sendto");
    00142   symbols.insert(S_recv,        "recv");
    00143   symbols.insert(S_send,        "send");
    00144   symbols.insert(S_getsockname, "getsockname");
    00145   symbols.insert(S_getpeername, "getpeername");
    00146   symbols.insert(S_accept,      "accept");
    00147   symbols.insert(S_select,      "select");
    00148   symbols.insert(S_listen,      "listen");
    00149   symbols.insert(S_bind,        "bind");
    00150 }
    00151
    00152 KNECSocksTable::~KNECSocksTable() {
    00153 }
    00154
    00155
    00156
    00157
    00158 //
    00159 //    Support for Dante SOCKS client
    00160 //
    00161
    00162 class KDanteSocksTable : public KSocksTable {
    00163   public:
    00164     KDanteSocksTable();
    00165     virtual ~KDanteSocksTable();
    00166 };
    00167
    00168 KDanteSocksTable::KDanteSocksTable() : KSocksTable() {
    00169   hasWorkingAsyncConnect = false;
    00170   myname = i18n("Dante SOCKS client");
    00171   symbols.insert(S_SOCKSinit,   "SOCKSinit");
    00172   symbols.insert(S_connect,     "Rconnect");
    00173   symbols.insert(S_read,        "Rread");
    00174   symbols.insert(S_write,       "Rwrite");
    00175   symbols.insert(S_recvfrom,    "Rrecvfrom");
    00176   symbols.insert(S_sendto,      "Rsendto");
    00177   symbols.insert(S_recv,        "Rrecv");
    00178   symbols.insert(S_send,        "Rsend");
    00179   symbols.insert(S_getsockname, "Rgetsockname");
    00180   symbols.insert(S_getpeername, "Rgetpeername");
    00181   symbols.insert(S_accept,      "Raccept");
    00182   symbols.insert(S_select,      "Rselect");
    00183   symbols.insert(S_listen,      "Rlisten");
    00184   symbols.insert(S_bind,        "Rbind");
    00185 }
    00186
    00187
    00188 KDanteSocksTable::~KDanteSocksTable() {
    00189 }
    00190
    00191
    00192
    00196
    00197
    00198 KSocks *KSocks::_me = 0;
    00199 bool KSocks::_disabled = false;
    00200
    00201 void KSocks::disable()
    00202 {
    00203    if (!_me)
    00204       _disabled = true;
    00205 }
    00206
    00207 KSocks *KSocks::self() {
    00208   // Note that we don't use a static deleter here. It makes no sense and tends to cause crashes.
    00209   if (!_me) {
    00210      if (kapp) {
    00211         KConfigGroup cfg(kapp->config(), "Socks");
    00212         _me = new KSocks(&cfg);
    00213      } else {
    00214         _disabled = true;
    00215         _me = new KSocks(0);
    00216      }
    00217   }
    00218   return _me;
    00219 }
    00220
    00221 void KSocks::setConfig(KConfigBase *config)
    00222 {
    00223   // We can change the config from disabled to enabled
    00224   // but not the other way around.
    00225   if (_me && _disabled) {
    00226      delete _me;
    00227      _me = 0;
    00228      _disabled = false;
    00229   }
    00230   if (!_me)
    00231     _me = new KSocks(config);
    00232 }
    00233
    00234 bool KSocks::activated() { return (_me != 0L); }
    00235
    00236
    00237 KSocks::KSocks(KConfigBase *config) : _socksLib(0L), _st(0L) {
    00238    _hasSocks = false;
    00239    _useSocks = false;
    00240
    00241    if (!config)
    00242       return;
    00243
    00244    if (!(config->readBoolEntry("SOCKS_enable", false))) {
    00245       _disabled = true;
    00246    }
    00247
    00248    if (_disabled)
    00249       return;
    00250
    00251    _libPaths << ""
    00252          << "/usr/lib" KDELIBSUFF "/"
    00253              << "/usr/lib/"
    00254          << "/usr/local/lib" KDELIBSUFF "/"
    00255              << "/usr/local/lib/"
    00256          << "/usr/local/socks5/lib" KDELIBSUFF "/"
    00257              << "/usr/local/socks5/lib/"
    00258          << "/opt/socks5/lib" KDELIBSUFF "/"
    00259              << "/opt/socks5/lib/";
    00260    _libNames << "libsocks.so"                  // Dante
    00261              << "libdsocksd.so.0"              // Dante 1.1.14-2 on
    00262                                                // Debian unstable 17-12-2003
    00263              << "libsocks5.so"                 // ?
    00264              << "libsocks5_sh.so";             // NEC
    00265
    00266    // Add the custom library paths here
    00267    QStringList newlibs = config->readListEntry("SOCKS_lib_path");
    00268
    00269    for (QStringList::Iterator it = newlibs.begin();
    00270                               it != newlibs.end();
    00271                               ++it) {
    00272       QString thisone = *it;
    00273       if (thisone[thisone.length()-1] != '/') thisone += "/";
    00274       _libPaths << thisone;
    00275       kdDebug(171) << "KSocks added a new library path: " << thisone << endl;
    00276    }
    00277
    00278    // Load the proper libsocks and KSocksTable
    00279    KLibLoader *ll = KLibLoader::self();
    00280
    00281
    00282    int _meth = config->readNumEntry("SOCKS_method", 1);
    00283          /****       Current methods
    00284           *   1) Autodetect (read: any)     2) NEC
    00285           *   3) Dante                      4) Custom
    00286           */
    00287
    00288    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
    00289       _socksLib = ll->library(config->readPathEntry("SOCKS_lib").latin1());
    00290       if (_socksLib && _socksLib->symbol("Rconnect")) {  // Dante compatible?
    00291          _st = new KDanteSocksTable;
    00292          _useSocks = true;
    00293          _hasSocks = true;
    00294       } else if (_socksLib && _socksLib->symbol("connect")) { // NEC compatible?
    00295          _st = new KNECSocksTable;
    00296          _useSocks = true;
    00297          _hasSocks = true;
    00298       } else if (_socksLib) {
    00299          _socksLib->unload();
    00300          _socksLib = 0L;
    00301       }
    00302    } else              // leave this here   "else for {}"
    00303    for (QStringList::Iterator pit  = _libPaths.begin();
    00304                               !_hasSocks && pit != _libPaths.end();
    00305                               ++pit)
    00306    for (QStringList::Iterator it  = _libNames.begin();
    00307                               it != _libNames.end();
    00308                               ++it) {
    00309       _socksLib = ll->library((*pit + *it).latin1());
    00310       if (_socksLib) {
    00311          if ((_meth == 1 || _meth == 2) &&
    00312              _socksLib->symbol("S5LogShowThreadIDS") != 0L) {  // NEC SOCKS
    00313             kdDebug(171) << "Found NEC SOCKS" << endl;
    00314             _st = new KNECSocksTable;
    00315             _useSocks = true;
    00316             _hasSocks = true;
    00317             break;
    00318          } else if ((_meth == 1 || _meth == 3) &&
    00319                     _socksLib->symbol("sockaddr2ruleaddress") != 0L) { //Dante
    00320             kdDebug(171) << "Found Dante SOCKS" << endl;
    00321             _st = new KDanteSocksTable;
    00322             _useSocks = true;
    00323             _hasSocks = true;
    00324             break;
    00325          } else {
    00326            _socksLib->unload();
    00327            _socksLib = 0L;
    00328          }
    00329       }
    00330    }
    00331
    00332    // Load in all the symbols
    00333    if (_st) {
    00334       for (QMap<SymbolKeys,QString>::Iterator it  = _st->symbols.begin();
    00335                                               it != _st->symbols.end();
    00336                                               ++it) {
    00337          switch(it.key()) {
    00338          case S_SOCKSinit:
    00339            F_SOCKSinit = (int (*)(char *))
    00340                          _socksLib->symbol(it.data().latin1());
    00341           break;
    00342          case S_connect:
    00343            F_connect = (int (*)(int, const struct sockaddr *, ksocklen_t))
    00344                        _socksLib->symbol(it.data().latin1());
    00345           break;
    00346          case S_read:
    00347            F_read = (signed long int (*)(int, void *, unsigned long int))
    00348                     _socksLib->symbol(it.data().latin1());
    00349           break;
    00350          case S_write:
    00351            F_write = (signed long int (*)(int, const void *, unsigned long int))
    00352                      _socksLib->symbol(it.data().latin1());
    00353           break;
    00354          case S_recvfrom:
    00355            F_recvfrom = (int (*)(int, void *, unsigned long int, int,
    00356                                  struct sockaddr *, ksocklen_t *))
    00357                         _socksLib->symbol(it.data().latin1());
    00358           break;
    00359          case S_sendto:
    00360            F_sendto = (int (*)(int, const void *, unsigned long int, int,
    00361                                const struct sockaddr *, ksocklen_t))
    00362                       _socksLib->symbol(it.data().latin1());
    00363           break;
    00364          case S_recv:
    00365            F_recv = (int (*)(int, void *, unsigned long int, int))
    00366                     _socksLib->symbol(it.data().latin1());
    00367           break;
    00368          case S_send:
    00369            F_send = (int (*)(int, const void *, unsigned long int, int))
    00370                     _socksLib->symbol(it.data().latin1());
    00371           break;
    00372          case S_getsockname:
    00373            F_getsockname = (int (*)(int, struct sockaddr *, ksocklen_t *))
    00374                            _socksLib->symbol(it.data().latin1());
    00375           break;
    00376          case S_getpeername:
    00377            F_getpeername = (int (*)(int, struct sockaddr *, ksocklen_t *))
    00378                            _socksLib->symbol(it.data().latin1());
    00379           break;
    00380          case S_accept:
    00381            F_accept = (int (*)(int, struct sockaddr *, ksocklen_t *))
    00382                       _socksLib->symbol(it.data().latin1());
    00383           break;
    00384          case S_select:
    00385            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
    00386                       _socksLib->symbol(it.data().latin1());
    00387           break;
    00388          case S_listen:
    00389            F_listen = (int (*)(int, int))
    00390                       _socksLib->symbol(it.data().latin1());
    00391           break;
    00392          case S_bind:
    00393            F_bind = (int (*)(int, const struct sockaddr *, ksocklen_t))
    00394                     _socksLib->symbol(it.data().latin1());
    00395           break;
    00396          default:
    00397           kdDebug(171) << "KSocks got a symbol it doesn't know about!" << endl;
    00398           break;
    00399          }
    00400       }
    00401
    00402       // Now we check for the critical stuff.
    00403       if (F_SOCKSinit) {
    00404          int rc = (*F_SOCKSinit)((char *)"KDE");
    00405          if (rc != 0)
    00406             stopSocks();
    00407          else kdDebug(171) << "SOCKS has been activated!" << endl;
    00408       } else {
    00409          stopSocks();
    00410       }
    00411    }
    00412 }
    00413
    00414
    00415 KSocks::~KSocks() {
    00416    stopSocks();
    00417    _me = 0;
    00418 }
    00419
    00420 void KSocks::die() {
    00421    if (_me == this) {
    00422       _me = 0;
    00423       delete this;
    00424    }
    00425 }
    00426
    00427 void KSocks::stopSocks() {
    00428    if (_hasSocks) {
    00429       // This library doesn't even provide the basics.
    00430       // It's probably broken.  Let's abort.
    00431       _useSocks = false;
    00432       _hasSocks = false;
    00433       if (_socksLib) {
    00434          _socksLib->unload();
    00435          _socksLib = 0L;
    00436       }
    00437       delete _st;
    00438       _st = 0L;
    00439    }
    00440 }
    00441
    00442
    00443 bool KSocks::usingSocks() {
    00444    return _useSocks;
    00445 }
    00446
    00447
    00448 bool KSocks::hasSocks() {
    00449    return _hasSocks;
    00450 }
    00451
    00452
    00453 void KSocks::disableSocks() {
    00454    _useSocks = false;
    00455 }
    00456
    00457
    00458 void KSocks::enableSocks() {
    00459    if (_hasSocks)
    00460       _useSocks = true;
    00461 }
    00462
    00463 bool KSocks::hasWorkingAsyncConnect()
    00464 {
    00465    return (_useSocks && _st) ? _st->hasWorkingAsyncConnect : true;
    00466 }
    00467
    00468
    00469 /*
    00470  *   REIMPLEMENTED FUNCTIONS FROM LIBC
    00471  *
    00472  */
    00473
    00474 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
    00475                                                    ksocklen_t addrlen) {
    00476    if (_useSocks && F_connect)
    00477       return (*F_connect)(sockfd, serv_addr, addrlen);
    00478    else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
    00479 }
    00480
    00481
    00482 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
    00483    if (_useSocks && F_read)
    00484       return (*F_read)(fd, buf, count);
    00485    else return ::read(fd, buf, count);
    00486 }
    00487
    00488
    00489 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
    00490    if (_useSocks && F_write)
    00491       return (*F_write)(fd, buf, count);
    00492    else return ::write(fd, buf, count);
    00493 }
    00494
    00495
    00496 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
    00497                                 sockaddr *from, ksocklen_t *fromlen) {
    00498    if (_useSocks && F_recvfrom) {
    00499       return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
    00500    } else {
    00501       socklen_t casted_len = (socklen_t) *fromlen;
    00502       int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
    00503       *fromlen = casted_len;
    00504       return rc;
    00505    }
    00506 }
    00507
    00508
    00509 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
    00510                              const sockaddr *to, ksocklen_t tolen) {
    00511    if (_useSocks && F_sendto)
    00512       return (*F_sendto)(s, msg, len, flags, to, tolen);
    00513    else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
    00514 }
    00515
    00516
    00517 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
    00518    if (_useSocks && F_recv)
    00519       return (*F_recv)(s, buf, len, flags);
    00520    else return ::recv(s, (char*) buf, len, flags);
    00521 }
    00522
    00523
    00524 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
    00525    if (_useSocks && F_send)
    00526       return (*F_send)(s, msg, len, flags);
    00527    else return ::send(s, (char*) msg, len, flags);
    00528 }
    00529
    00530
    00531 int KSocks::getsockname (int s, sockaddr *name, ksocklen_t *namelen) {
    00532    if (_useSocks && F_getsockname) {
    00533       return (*F_getsockname)(s, name, namelen);
    00534    } else {
    00535      socklen_t casted_len = *namelen;
    00536      int rc = ::getsockname(s, name, &casted_len);
    00537      *namelen = casted_len;
    00538      return rc;
    00539    }
    00540 }
    00541
    00542
    00543 int KSocks::getpeername (int s, sockaddr *name, ksocklen_t *namelen) {
    00544    if (_useSocks && F_getpeername) {
    00545       return (*F_getpeername)(s, name, namelen);
    00546    } else {
    00547       socklen_t casted_len = *namelen;
    00548       int rc = ::getpeername(s, name, &casted_len);
    00549       *namelen = casted_len;
    00550       return rc;
    00551    }
    00552 }
    00553
    00554
    00555 int KSocks::accept (int s, sockaddr *addr, ksocklen_t *addrlen) {
    00556    if (_useSocks && F_accept) {
    00557      return (*F_accept)(s, addr, addrlen);
    00558    } else {
    00559       socklen_t casted_len = *addrlen;
    00560       int rc = ::accept(s, addr, &casted_len);
    00561       *addrlen = casted_len;
    00562       return rc;
    00563    }
    00564 }
    00565
    00566
    00567 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
    00568                                 fd_set *exceptfds, struct timeval *timeout) {
    00569    if (_useSocks && F_select)
    00570       return (*F_select)(n, readfds, writefds, exceptfds, timeout);
    00571    else return ::select(n, readfds, writefds, exceptfds, timeout);
    00572 }
    00573
    00574
    00575 int KSocks::listen (int s, int backlog) {
    00576    if (_useSocks && F_listen)
    00577       return (*F_listen)(s, backlog);
    00578    else return ::listen(s, backlog);
    00579 }
    00580
    00581
    00582 int KSocks::bind (int sockfd, const sockaddr *my_addr, ksocklen_t addrlen) {
    00583    if (_useSocks && F_bind)
    00584       return (*F_bind)(sockfd, my_addr, addrlen);
    00585    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
    00586 }
    00587
    00588 int KSocks::bind (int sockfd, sockaddr *my_addr, ksocklen_t addrlen) {
    00589    if (_useSocks && F_bind)
    00590       return (*F_bind)(sockfd, my_addr, addrlen);
    00591    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
    00592 }
    00593
    00594
    00595

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:11 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003