kdecore Library API Documentation

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, struct sockaddr *, ksocklen_t) = 0L;
00080 }
00081 
00082 
00083 class KSocksTable {
00084  public:
00085    KSocksTable();
00086  
00087    // The name of each symbol and it's SOCKS replacement
00088    QMap<SymbolKeys,QString>  symbols;
00089    // The name of this library
00090    QString                   myname;
00091    bool                      hasWorkingAsyncConnect;
00092 };
00093 
00094 
00095 KSocksTable::KSocksTable() : myname("Unknown"), hasWorkingAsyncConnect(true) {
00096 }
00097 
00098 
00099 /*
00100  *   How to add support for a new SOCKS package.
00101  * 
00102  *   1) Subclass KSocksTable as is done below and write out all the symbols
00103  *   1.b) Give the class a "myname"
00104  *   2) Make sure that all possible library names are written into the
00105  *      _libNames string list.  Don't forget that different OSes name shared
00106  *      libraries differently.  Expect .so, .sl, .a (!) (AIX does this).
00107  *   3) Find a unique symbol in the library that we can use to identify that
00108  *      library and write out the test case in the constructor
00109  *   4) Make necessary changes to the KControl module in kdebase/kcontrol/....
00110  *   5) TEST!
00111  *
00112  */
00113 
00117 
00118 
00119 //
00120 //    Support for NEC SOCKS client
00121 //
00122 
00123 class KNECSocksTable : public KSocksTable {
00124   public:
00125     KNECSocksTable();
00126     virtual ~KNECSocksTable();
00127 };
00128 
00129 
00130 KNECSocksTable::KNECSocksTable() : KSocksTable() {
00131   myname = i18n("NEC SOCKS client");
00132   symbols.insert(S_SOCKSinit,   "SOCKSinit");
00133   symbols.insert(S_connect,     "connect");
00134   symbols.insert(S_read,        "read");
00135   symbols.insert(S_write,       "write");
00136   symbols.insert(S_recvfrom,    "recvfrom");
00137   symbols.insert(S_sendto,      "sendto");
00138   symbols.insert(S_recv,        "recv");
00139   symbols.insert(S_send,        "send");
00140   symbols.insert(S_getsockname, "getsockname");
00141   symbols.insert(S_getpeername, "getpeername");
00142   symbols.insert(S_accept,      "accept");
00143   symbols.insert(S_select,      "select");
00144   symbols.insert(S_listen,      "listen");
00145   symbols.insert(S_bind,        "bind");
00146 }
00147 
00148 KNECSocksTable::~KNECSocksTable() {
00149 }
00150 
00151 
00152 
00153 
00154 //
00155 //    Support for Dante SOCKS client
00156 //
00157 
00158 class KDanteSocksTable : public KSocksTable {
00159   public:
00160     KDanteSocksTable();
00161     virtual ~KDanteSocksTable();
00162 };
00163 
00164 KDanteSocksTable::KDanteSocksTable() : KSocksTable() {
00165   hasWorkingAsyncConnect = false;
00166   myname = i18n("Dante SOCKS client");
00167   symbols.insert(S_SOCKSinit,   "SOCKSinit");
00168   symbols.insert(S_connect,     "Rconnect");
00169   symbols.insert(S_read,        "Rread");
00170   symbols.insert(S_write,       "Rwrite");
00171   symbols.insert(S_recvfrom,    "Rrecvfrom");
00172   symbols.insert(S_sendto,      "Rsendto");
00173   symbols.insert(S_recv,        "Rrecv");
00174   symbols.insert(S_send,        "Rsend");
00175   symbols.insert(S_getsockname, "Rgetsockname");
00176   symbols.insert(S_getpeername, "Rgetpeername");
00177   symbols.insert(S_accept,      "Raccept");
00178   symbols.insert(S_select,      "Rselect");
00179   symbols.insert(S_listen,      "Rlisten");
00180   symbols.insert(S_bind,        "Rbind");
00181 }
00182 
00183 
00184 KDanteSocksTable::~KDanteSocksTable() {
00185 }
00186 
00187 
00188 
00192 
00193 
00194 KSocks *KSocks::_me = 0;
00195 bool KSocks::_disabled = false;
00196 
00197 void KSocks::disable() 
00198 { 
00199    if (!_me)
00200       _disabled = true; 
00201 }
00202 
00203 KSocks *KSocks::self() {
00204   // Note that we don't use a static deleter here. It makes no sense and tends to cause crashes.
00205   if (!_me) {
00206      if (kapp) {
00207         KConfigGroup cfg(kapp->config(), "Socks");
00208         _me = new KSocks(&cfg);
00209      } else {
00210         _disabled = true;
00211         _me = new KSocks(0);
00212      }
00213   }
00214   return _me;
00215 }
00216 
00217 void KSocks::setConfig(KConfigBase *config)
00218 {
00219   // We can change the config from disabled to enabled
00220   // but not the other way around.
00221   if (_me && _disabled) { 
00222      delete _me;
00223      _me = 0;
00224      _disabled = false;
00225   }
00226   if (!_me)
00227     _me = new KSocks(config);
00228 }
00229 
00230 bool KSocks::activated() { return (_me != 0L); }
00231 
00232 
00233 KSocks::KSocks(KConfigBase *config) : _socksLib(0L), _st(0L) {
00234    _hasSocks = false;
00235    _useSocks = false;
00236 
00237    if (!config)
00238       return;
00239 
00240    if (!(config->readBoolEntry("SOCKS_enable", false))) {
00241       _disabled = true;
00242    }
00243 
00244    if (_disabled)
00245       return;
00246 
00247    _libPaths << ""
00248              << "/usr/lib/"
00249              << "/usr/local/lib/"
00250              << "/usr/local/socks5/lib/"
00251              << "/opt/socks5/lib/";
00252    _libNames << "libsocks.so"                  // Dante
00253              << "libsocks5.so"                 // ?
00254              << "libsocks5_sh.so";             // NEC
00255 
00256    // Add the custom library paths here
00257    QStringList newlibs = config->readListEntry("SOCKS_lib_path");
00258 
00259    for (QStringList::Iterator it = newlibs.begin();
00260                               it != newlibs.end();
00261                               ++it) {
00262       QString thisone = *it;
00263       if (thisone[thisone.length()-1] != '/') thisone += "/";
00264       _libPaths << thisone;
00265       kdDebug(171) << "KSocks added a new library path: " << thisone << endl;
00266    }
00267 
00268    // Load the proper libsocks and KSocksTable
00269    KLibLoader *ll = KLibLoader::self();
00270    
00271 
00272    int _meth = config->readNumEntry("SOCKS_method", 1);
00273          /****       Current methods
00274           *   1) Autodetect (read: any)     2) NEC
00275           *   3) Dante                      4) Custom
00276           */
00277 
00278    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
00279       _socksLib = ll->library(config->readPathEntry("SOCKS_lib", "").latin1());
00280       if (_socksLib && _socksLib->symbol("Rconnect")) {  // Dante compatible?
00281          _st = new KDanteSocksTable;       
00282          _useSocks = true;
00283          _hasSocks = true;
00284       } else if (_socksLib && _socksLib->symbol("connect")) { // NEC compatible?
00285          _st = new KNECSocksTable;       
00286          _useSocks = true;
00287          _hasSocks = true;
00288       } else if (_socksLib) {
00289          _socksLib->unload();
00290          _socksLib = 0L;
00291       }
00292    } else              // leave this here   "else for {}"
00293    for (QStringList::Iterator pit  = _libPaths.begin();
00294                               !_hasSocks && pit != _libPaths.end();
00295                               ++pit)
00296    for (QStringList::Iterator it  = _libNames.begin();
00297                               it != _libNames.end();
00298                               ++it) {
00299       _socksLib = ll->library((*pit + *it).latin1());
00300       if (_socksLib) {
00301          if ((_meth == 1 || _meth == 2) &&
00302              _socksLib->symbol("S5LogShowThreadIDS") != 0L) {  // NEC SOCKS
00303             kdDebug(171) << "Found NEC SOCKS" << endl;
00304             _st = new KNECSocksTable;
00305             _useSocks = true;
00306             _hasSocks = true;
00307             break;
00308          } else if ((_meth == 1 || _meth == 3) && 
00309                     _socksLib->symbol("sockaddr2ruleaddress") != 0L) { //Dante
00310             kdDebug(171) << "Found Dante SOCKS" << endl;
00311             _st = new KDanteSocksTable;
00312             _useSocks = true;
00313             _hasSocks = true;
00314             break;
00315          } else {
00316            _socksLib->unload();
00317            _socksLib = 0L;
00318          }
00319       }
00320    }
00321 
00322    // Load in all the symbols
00323    if (_st) {
00324       for (QMap<SymbolKeys,QString>::Iterator it  = _st->symbols.begin();
00325                                               it != _st->symbols.end();
00326                                               ++it) {
00327          switch(it.key()) {
00328          case S_SOCKSinit:
00329            F_SOCKSinit = (int (*)(char *))
00330                          _socksLib->symbol(it.data().latin1());
00331           break;
00332          case S_connect:
00333            F_connect = (int (*)(int, const struct sockaddr *, ksocklen_t))
00334                        _socksLib->symbol(it.data().latin1());
00335           break;
00336          case S_read:
00337            F_read = (signed long int (*)(int, void *, unsigned long int))
00338                     _socksLib->symbol(it.data().latin1());
00339           break;
00340          case S_write:
00341            F_write = (signed long int (*)(int, const void *, unsigned long int))
00342                      _socksLib->symbol(it.data().latin1());
00343           break;
00344          case S_recvfrom:
00345            F_recvfrom = (int (*)(int, void *, unsigned long int, int, 
00346                                  struct sockaddr *, ksocklen_t *))
00347                         _socksLib->symbol(it.data().latin1());
00348           break;
00349          case S_sendto:
00350            F_sendto = (int (*)(int, const void *, unsigned long int, int,
00351                                const struct sockaddr *, ksocklen_t))
00352                       _socksLib->symbol(it.data().latin1());
00353           break;
00354          case S_recv:
00355            F_recv = (int (*)(int, void *, unsigned long int, int))
00356                     _socksLib->symbol(it.data().latin1());
00357           break;
00358          case S_send:
00359            F_send = (int (*)(int, const void *, unsigned long int, int))
00360                     _socksLib->symbol(it.data().latin1());
00361           break;
00362          case S_getsockname:
00363            F_getsockname = (int (*)(int, struct sockaddr *, ksocklen_t *))
00364                            _socksLib->symbol(it.data().latin1());
00365           break;
00366          case S_getpeername:
00367            F_getpeername = (int (*)(int, struct sockaddr *, ksocklen_t *))
00368                            _socksLib->symbol(it.data().latin1());
00369           break;
00370          case S_accept:
00371            F_accept = (int (*)(int, struct sockaddr *, ksocklen_t *))
00372                       _socksLib->symbol(it.data().latin1());
00373           break;
00374          case S_select:
00375            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
00376                       _socksLib->symbol(it.data().latin1());
00377           break;
00378          case S_listen:
00379            F_listen = (int (*)(int, int))
00380                       _socksLib->symbol(it.data().latin1());
00381           break;
00382          case S_bind:
00383            F_bind = (int (*)(int, struct sockaddr *, ksocklen_t))
00384                     _socksLib->symbol(it.data().latin1());
00385           break;
00386          default:
00387           kdDebug(171) << "KSocks got a symbol it doesn't know about!" << endl;
00388           break;
00389          }
00390       }
00391  
00392       // Now we check for the critical stuff.
00393       if (F_SOCKSinit) {
00394          int rc = (*F_SOCKSinit)((char *)"KDE");
00395          if (rc != 0)
00396             stopSocks();
00397          else kdDebug(171) << "SOCKS has been activated!" << endl;
00398       } else {
00399          stopSocks();
00400       }
00401    }
00402 }
00403 
00404 
00405 KSocks::~KSocks() {
00406    stopSocks();
00407    _me = 0;
00408 }
00409 
00410 void KSocks::die() {
00411    if (_me == this) {
00412       _me = 0;
00413       delete this;
00414    }
00415 }
00416 
00417 void KSocks::stopSocks() {
00418    if (_hasSocks) {
00419       // This library doesn't even provide the basics.
00420       // It's probably broken.  Let's abort.
00421       _useSocks = false;
00422       _hasSocks = false;
00423       if (_socksLib) {
00424          _socksLib->unload();
00425          _socksLib = 0L;
00426       }
00427       delete _st;
00428       _st = 0L;
00429    }
00430 }
00431 
00432  
00433 bool KSocks::usingSocks() {
00434    return _useSocks;
00435 }
00436 
00437 
00438 bool KSocks::hasSocks() {
00439    return _hasSocks;
00440 }
00441 
00442 
00443 void KSocks::disableSocks() {
00444    _useSocks = false;
00445 }
00446 
00447 
00448 void KSocks::enableSocks() {
00449    if (_hasSocks)
00450       _useSocks = true;
00451 }
00452 
00453 bool KSocks::hasWorkingAsyncConnect()
00454 {
00455    return (_useSocks && _st) ? _st->hasWorkingAsyncConnect : true;
00456 }
00457 
00458 
00459 /*
00460  *   REIMPLEMENTED FUNCTIONS FROM LIBC
00461  *
00462  */
00463 
00464 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
00465                                                    ksocklen_t addrlen) {
00466    if (_useSocks && F_connect)
00467       return (*F_connect)(sockfd, serv_addr, addrlen);
00468    else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
00469 }
00470 
00471 
00472 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
00473    if (_useSocks && F_read)
00474       return (*F_read)(fd, buf, count);
00475    else return ::read(fd, buf, count);
00476 }
00477 
00478 
00479 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
00480    if (_useSocks && F_write)
00481       return (*F_write)(fd, buf, count);
00482    else return ::write(fd, buf, count);
00483 }
00484 
00485 
00486 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
00487                                 sockaddr *from, ksocklen_t *fromlen) {
00488    if (_useSocks && F_recvfrom) {
00489       return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
00490    } else {
00491       socklen_t casted_len = (socklen_t) *fromlen;
00492       int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
00493       *fromlen = casted_len;
00494       return rc;
00495    }
00496 }
00497 
00498 
00499 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
00500                              const sockaddr *to, ksocklen_t tolen) {
00501    if (_useSocks && F_sendto)
00502       return (*F_sendto)(s, msg, len, flags, to, tolen);
00503    else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
00504 }
00505 
00506 
00507 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
00508    if (_useSocks && F_recv)
00509       return (*F_recv)(s, buf, len, flags);
00510    else return ::recv(s, (char*) buf, len, flags);
00511 }
00512 
00513 
00514 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
00515    if (_useSocks && F_send)
00516       return (*F_send)(s, msg, len, flags);
00517    else return ::send(s, (char*) msg, len, flags);
00518 }
00519 
00520 
00521 int KSocks::getsockname (int s, sockaddr *name, ksocklen_t *namelen) {
00522    if (_useSocks && F_getsockname) {
00523       return (*F_getsockname)(s, name, namelen);
00524    } else {
00525      socklen_t casted_len = *namelen;
00526      int rc = ::getsockname(s, name, &casted_len);
00527      *namelen = casted_len;
00528      return rc;
00529    }
00530 }
00531 
00532 
00533 int KSocks::getpeername (int s, sockaddr *name, ksocklen_t *namelen) {
00534    if (_useSocks && F_getpeername) {
00535       return (*F_getpeername)(s, name, namelen);
00536    } else {
00537       socklen_t casted_len = *namelen;
00538       int rc = ::getpeername(s, name, &casted_len);
00539       *namelen = casted_len;
00540       return rc;
00541    }
00542 }
00543 
00544 
00545 int KSocks::accept (int s, sockaddr *addr, ksocklen_t *addrlen) {
00546    if (_useSocks && F_accept) {
00547      return (*F_accept)(s, addr, addrlen);
00548    } else {
00549       socklen_t casted_len = *addrlen;
00550       int rc = ::accept(s, addr, &casted_len);
00551       *addrlen = casted_len;
00552       return rc;
00553    }
00554 }
00555 
00556 
00557 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
00558                                 fd_set *exceptfds, struct timeval *timeout) {
00559    if (_useSocks && F_select)
00560       return (*F_select)(n, readfds, writefds, exceptfds, timeout);
00561    else return ::select(n, readfds, writefds, exceptfds, timeout);
00562 }
00563 
00564 
00565 int KSocks::listen (int s, int backlog) {
00566    if (_useSocks && F_listen)
00567       return (*F_listen)(s, backlog);
00568    else return ::listen(s, backlog);
00569 }
00570 
00571 
00572 int KSocks::bind (int sockfd, sockaddr *my_addr, ksocklen_t addrlen) {
00573    if (_useSocks && F_bind)
00574       return (*F_bind)(sockfd, my_addr, addrlen);
00575    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00576 }
00577 
00578 
00579 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:14:47 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001