• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

ksocks.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, 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 #ifdef __CYGWIN__
00200 bool KSocks::_disabled = true;
00201 #else 
00202 bool KSocks::_disabled = false;
00203 #endif 
00204 static KStaticDeleter<KSocks> med;
00205 
00206 void KSocks::disable()
00207 {
00208    if (!_me)
00209       _disabled = true;
00210 }
00211 
00212 KSocks *KSocks::self() {
00213   // Note that we don't use a static deleter here. It makes no sense and tends to cause crashes.
00214   if (!_me) {
00215      if (kapp) {
00216         KConfigGroup cfg(kapp->config(), "Socks");
00217         _me = new KSocks(&cfg);
00218      } else {
00219         _disabled = true;
00220         _me = new KSocks(0);
00221      }
00222   }
00223   return _me;
00224 }
00225 
00226 void KSocks::setConfig(KConfigBase *config)
00227 {
00228   // We can change the config from disabled to enabled
00229   // but not the other way around.
00230   if (_me && _disabled) {
00231      delete _me;
00232      _me = 0;
00233      _disabled = false;
00234   }
00235   if (!_me)
00236     _me = new KSocks(config);
00237 }
00238 
00239 bool KSocks::activated() { return (_me != 0L); }
00240 
00241 
00242 KSocks::KSocks(KConfigBase *config) : _socksLib(0L), _st(0L) {
00243    _hasSocks = false;
00244    _useSocks = false;
00245 
00246    if (!config)
00247       return;
00248 
00249    if (!(config->readBoolEntry("SOCKS_enable", false))) {
00250       _disabled = true;
00251    }
00252 
00253    if (_disabled)
00254       return;
00255 
00256    _libPaths << ""
00257          << "/usr/lib" KDELIBSUFF "/"
00258              << "/usr/lib/"
00259          << "/usr/local/lib" KDELIBSUFF "/"
00260              << "/usr/local/lib/"
00261          << "/usr/local/socks5/lib" KDELIBSUFF "/"
00262              << "/usr/local/socks5/lib/"
00263          << "/opt/socks5/lib" KDELIBSUFF "/"
00264              << "/opt/socks5/lib/";
00265    _libNames << "libsocks.so"                  // Dante
00266              << "libdsocksd.so.0"              // Dante 1.1.14-2 on
00267                                                // Debian unstable 17-12-2003
00268              << "libsocks5.so"                 // ?
00269              << "libsocks5_sh.so";             // NEC
00270 
00271    // Add the custom library paths here
00272    QStringList newlibs = config->readListEntry("SOCKS_lib_path");
00273 
00274    for (QStringList::Iterator it = newlibs.begin();
00275                               it != newlibs.end();
00276                               ++it) {
00277       QString thisone = *it;
00278       if (thisone[thisone.length()-1] != '/') thisone += "/";
00279       _libPaths << thisone;
00280       kdDebug(171) << "KSocks added a new library path: " << thisone << endl;
00281    }
00282 
00283    // Load the proper libsocks and KSocksTable
00284    KLibLoader *ll = KLibLoader::self();
00285 
00286 
00287    int _meth = config->readNumEntry("SOCKS_method", 1);
00288          /****       Current methods
00289           *   1) Autodetect (read: any)     2) NEC
00290           *   3) Dante                      4) Custom
00291           */
00292 
00293    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
00294       _socksLib = ll->library(config->readPathEntry("SOCKS_lib").latin1());
00295       if (_socksLib && _socksLib->symbol("Rconnect")) {  // Dante compatible?
00296          _st = new KDanteSocksTable;
00297          _useSocks = true;
00298          _hasSocks = true;
00299       } else if (_socksLib && _socksLib->symbol("connect")) { // NEC compatible?
00300          _st = new KNECSocksTable;
00301          _useSocks = true;
00302          _hasSocks = true;
00303       } else if (_socksLib) {
00304          _socksLib->unload();
00305          _socksLib = 0L;
00306       }
00307    } else              // leave this here   "else for {}"
00308    for (QStringList::Iterator pit  = _libPaths.begin();
00309                               !_hasSocks && pit != _libPaths.end();
00310                               ++pit)
00311    for (QStringList::Iterator it  = _libNames.begin();
00312                               it != _libNames.end();
00313                               ++it) {
00314       _socksLib = ll->library((*pit + *it).latin1());
00315       if (_socksLib) {
00316          if ((_meth == 1 || _meth == 2) &&
00317              _socksLib->symbol("S5LogShowThreadIDS") != 0L) {  // NEC SOCKS
00318             kdDebug(171) << "Found NEC SOCKS" << endl;
00319             _st = new KNECSocksTable;
00320             _useSocks = true;
00321             _hasSocks = true;
00322             break;
00323          } else if ((_meth == 1 || _meth == 3) &&
00324                     _socksLib->symbol("sockaddr2ruleaddress") != 0L) { //Dante
00325             kdDebug(171) << "Found Dante SOCKS" << endl;
00326             _st = new KDanteSocksTable;
00327             _useSocks = true;
00328             _hasSocks = true;
00329             break;
00330          } else {
00331            _socksLib->unload();
00332            _socksLib = 0L;
00333          }
00334       }
00335    }
00336 
00337    // Load in all the symbols
00338    if (_st) {
00339       for (QMap<SymbolKeys,QString>::Iterator it  = _st->symbols.begin();
00340                                               it != _st->symbols.end();
00341                                               ++it) {
00342          switch(it.key()) {
00343          case S_SOCKSinit:
00344            F_SOCKSinit = (int (*)(char *))
00345                          _socksLib->symbol(it.data().latin1());
00346           break;
00347          case S_connect:
00348            F_connect = (int (*)(int, const struct sockaddr *, ksocklen_t))
00349                        _socksLib->symbol(it.data().latin1());
00350           break;
00351          case S_read:
00352            F_read = (signed long int (*)(int, void *, unsigned long int))
00353                     _socksLib->symbol(it.data().latin1());
00354           break;
00355          case S_write:
00356            F_write = (signed long int (*)(int, const void *, unsigned long int))
00357                      _socksLib->symbol(it.data().latin1());
00358           break;
00359          case S_recvfrom:
00360            F_recvfrom = (int (*)(int, void *, unsigned long int, int,
00361                                  struct sockaddr *, ksocklen_t *))
00362                         _socksLib->symbol(it.data().latin1());
00363           break;
00364          case S_sendto:
00365            F_sendto = (int (*)(int, const void *, unsigned long int, int,
00366                                const struct sockaddr *, ksocklen_t))
00367                       _socksLib->symbol(it.data().latin1());
00368           break;
00369          case S_recv:
00370            F_recv = (int (*)(int, void *, unsigned long int, int))
00371                     _socksLib->symbol(it.data().latin1());
00372           break;
00373          case S_send:
00374            F_send = (int (*)(int, const void *, unsigned long int, int))
00375                     _socksLib->symbol(it.data().latin1());
00376           break;
00377          case S_getsockname:
00378            F_getsockname = (int (*)(int, struct sockaddr *, ksocklen_t *))
00379                            _socksLib->symbol(it.data().latin1());
00380           break;
00381          case S_getpeername:
00382            F_getpeername = (int (*)(int, struct sockaddr *, ksocklen_t *))
00383                            _socksLib->symbol(it.data().latin1());
00384           break;
00385          case S_accept:
00386            F_accept = (int (*)(int, struct sockaddr *, ksocklen_t *))
00387                       _socksLib->symbol(it.data().latin1());
00388           break;
00389          case S_select:
00390            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
00391                       _socksLib->symbol(it.data().latin1());
00392           break;
00393          case S_listen:
00394            F_listen = (int (*)(int, int))
00395                       _socksLib->symbol(it.data().latin1());
00396           break;
00397          case S_bind:
00398            F_bind = (int (*)(int, const struct sockaddr *, ksocklen_t))
00399                     _socksLib->symbol(it.data().latin1());
00400           break;
00401          default:
00402           kdDebug(171) << "KSocks got a symbol it doesn't know about!" << endl;
00403           break;
00404          }
00405       }
00406 
00407       // Now we check for the critical stuff.
00408       if (F_SOCKSinit) {
00409          int rc = (*F_SOCKSinit)((char *)"KDE");
00410          if (rc != 0)
00411             stopSocks();
00412          else kdDebug(171) << "SOCKS has been activated!" << endl;
00413       } else {
00414          stopSocks();
00415       }
00416    }
00417 }
00418 
00419 
00420 KSocks::~KSocks() {
00421    stopSocks();
00422    _me = 0;
00423 }
00424 
00425 void KSocks::die() {
00426    if (_me == this) {
00427       _me = 0;
00428       delete this;
00429    }
00430 }
00431 
00432 void KSocks::stopSocks() {
00433    if (_hasSocks) {
00434       // This library doesn't even provide the basics.
00435       // It's probably broken.  Let's abort.
00436       _useSocks = false;
00437       _hasSocks = false;
00438       if (_socksLib) {
00439          _socksLib->unload();
00440          _socksLib = 0L;
00441       }
00442       delete _st;
00443       _st = 0L;
00444    }
00445 }
00446 
00447 
00448 bool KSocks::usingSocks() {
00449    return _useSocks;
00450 }
00451 
00452 
00453 bool KSocks::hasSocks() {
00454    return _hasSocks;
00455 }
00456 
00457 
00458 void KSocks::disableSocks() {
00459    _useSocks = false;
00460 }
00461 
00462 
00463 void KSocks::enableSocks() {
00464    if (_hasSocks)
00465       _useSocks = true;
00466 }
00467 
00468 bool KSocks::hasWorkingAsyncConnect()
00469 {
00470    return (_useSocks && _st) ? _st->hasWorkingAsyncConnect : true;
00471 }
00472 
00473 
00474 /*
00475  *   REIMPLEMENTED FUNCTIONS FROM LIBC
00476  *
00477  */
00478 
00479 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
00480                                                    ksocklen_t addrlen) {
00481    if (_useSocks && F_connect)
00482       return (*F_connect)(sockfd, serv_addr, addrlen);
00483    else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
00484 }
00485 
00486 
00487 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
00488    if (_useSocks && F_read)
00489       return (*F_read)(fd, buf, count);
00490    else return ::read(fd, buf, count);
00491 }
00492 
00493 
00494 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
00495    if (_useSocks && F_write)
00496       return (*F_write)(fd, buf, count);
00497    else return ::write(fd, buf, count);
00498 }
00499 
00500 
00501 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
00502                                 sockaddr *from, ksocklen_t *fromlen) {
00503    if (_useSocks && F_recvfrom) {
00504       return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
00505    } else {
00506       socklen_t casted_len = (socklen_t) *fromlen;
00507       int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
00508       *fromlen = casted_len;
00509       return rc;
00510    }
00511 }
00512 
00513 
00514 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
00515                              const sockaddr *to, ksocklen_t tolen) {
00516    if (_useSocks && F_sendto)
00517       return (*F_sendto)(s, msg, len, flags, to, tolen);
00518    else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
00519 }
00520 
00521 
00522 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
00523    if (_useSocks && F_recv)
00524       return (*F_recv)(s, buf, len, flags);
00525    else return ::recv(s, (char*) buf, len, flags);
00526 }
00527 
00528 
00529 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
00530    if (_useSocks && F_send)
00531       return (*F_send)(s, msg, len, flags);
00532    else return ::send(s, (char*) msg, len, flags);
00533 }
00534 
00535 
00536 int KSocks::getsockname (int s, sockaddr *name, ksocklen_t *namelen) {
00537    if (_useSocks && F_getsockname) {
00538       return (*F_getsockname)(s, name, namelen);
00539    } else {
00540      socklen_t casted_len = *namelen;
00541      int rc = ::getsockname(s, name, &casted_len);
00542      *namelen = casted_len;
00543      return rc;
00544    }
00545 }
00546 
00547 
00548 int KSocks::getpeername (int s, sockaddr *name, ksocklen_t *namelen) {
00549    if (_useSocks && F_getpeername) {
00550       return (*F_getpeername)(s, name, namelen);
00551    } else {
00552       socklen_t casted_len = *namelen;
00553       int rc = ::getpeername(s, name, &casted_len);
00554       *namelen = casted_len;
00555       return rc;
00556    }
00557 }
00558 
00559 
00560 int KSocks::accept (int s, sockaddr *addr, ksocklen_t *addrlen) {
00561    if (_useSocks && F_accept) {
00562      return (*F_accept)(s, addr, addrlen);
00563    } else {
00564       socklen_t casted_len = *addrlen;
00565       int rc = ::accept(s, addr, &casted_len);
00566       *addrlen = casted_len;
00567       return rc;
00568    }
00569 }
00570 
00571 
00572 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
00573                                 fd_set *exceptfds, struct timeval *timeout) {
00574    if (_useSocks && F_select)
00575       return (*F_select)(n, readfds, writefds, exceptfds, timeout);
00576    else return ::select(n, readfds, writefds, exceptfds, timeout);
00577 }
00578 
00579 
00580 int KSocks::listen (int s, int backlog) {
00581    if (_useSocks && F_listen)
00582       return (*F_listen)(s, backlog);
00583    else return ::listen(s, backlog);
00584 }
00585 
00586 
00587 int KSocks::bind (int sockfd, const sockaddr *my_addr, ksocklen_t addrlen) {
00588    if (_useSocks && F_bind)
00589       return (*F_bind)(sockfd, my_addr, addrlen);
00590    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00591 }
00592 
00593 int KSocks::bind (int sockfd, sockaddr *my_addr, ksocklen_t addrlen) {
00594    if (_useSocks && F_bind)
00595       return (*F_bind)(sockfd, my_addr, addrlen);
00596    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00597 }
00598 
00599 
00600 

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal