kdecore Library API Documentation

ksocks.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2001 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 "kstaticdeleter.h"
00033 #include <kconfig.h>
00034 #include <kapplication.h>
00035 
00036 #include <sys/types.h>
00037 #include <sys/socket.h>
00038 
00039 #include <unistd.h>
00040 
00041 #include "ksocks.h"
00042 
00043 // DO NOT RE-ORDER THESE.
00044 enum SymbolKeys {
00045       S_SOCKSinit    =  0,
00046       S_connect      =  1,
00047       S_read         =  2,
00048       S_write        =  3,
00049       S_recvfrom     =  4,
00050       S_sendto       =  5,
00051       S_recv         =  6,
00052       S_send         =  7,
00053       S_getsockname  =  8,
00054       S_getpeername  =  9,
00055       S_accept       = 10,
00056       S_select       = 11,
00057       S_listen       = 12,
00058       S_bind         = 13
00059      };
00060 
00061 
00062 extern "C" {
00063 // Function pointer table
00064 static int     (*F_SOCKSinit)   (char *) = NULL;
00065 static int     (*F_connect)     (int, const struct sockaddr *, ksocklen_t) = NULL;
00066 static signed long int (*F_read)        (int, void *, unsigned long int) = NULL;
00067 static signed long int (*F_write)       (int, const void *, unsigned long int) = NULL;
00068 static int     (*F_recvfrom)    (int, void *, unsigned long int, int, struct sockaddr *, 
00069                                  ksocklen_t *) = NULL;
00070 static int     (*F_sendto)      (int, const void *, unsigned long int, int,
00071                                  const struct sockaddr *, ksocklen_t) = NULL;
00072 static int     (*F_recv)        (int, void *, unsigned long int, int) = NULL;
00073 static int     (*F_send)        (int, const void *, unsigned long int, int) = NULL;
00074 static int     (*F_getsockname) (int, struct sockaddr *, ksocklen_t *) = NULL;
00075 static int     (*F_getpeername) (int, struct sockaddr *, ksocklen_t *) = NULL;
00076 static int     (*F_accept)      (int, struct sockaddr *, ksocklen_t *) = NULL;
00077 static int     (*F_select)      (int, fd_set *, fd_set *, fd_set *, 
00078                                  struct timeval *) = NULL;
00079 static int     (*F_listen)      (int, int) = NULL;
00080 static int     (*F_bind)        (int, struct sockaddr *, ksocklen_t) = NULL;
00081 };
00082 
00083 
00084 class KSocksTable {
00085  public:
00086    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 };
00093 
00094 
00095 KSocksTable::KSocksTable() : myname("Unknown") {
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   myname = i18n("Dante SOCKS client");
00166   symbols.insert(S_SOCKSinit,   "SOCKSinit");
00167   symbols.insert(S_connect,     "Rconnect");
00168   symbols.insert(S_read,        "Rread");
00169   symbols.insert(S_write,       "Rwrite");
00170   symbols.insert(S_recvfrom,    "Rrecvfrom");
00171   symbols.insert(S_sendto,      "Rsendto");
00172   symbols.insert(S_recv,        "Rrecv");
00173   symbols.insert(S_send,        "Rsend");
00174   symbols.insert(S_getsockname, "Rgetsockname");
00175   symbols.insert(S_getpeername, "Rgetpeername");
00176   symbols.insert(S_accept,      "Raccept");
00177   symbols.insert(S_select,      "Rselect");
00178   symbols.insert(S_listen,      "Rlisten");
00179   symbols.insert(S_bind,        "Rbind");
00180 }
00181 
00182 
00183 KDanteSocksTable::~KDanteSocksTable() {
00184 }
00185 
00186 
00187 
00191 
00192 
00193 KSocks *KSocks::_me = 0;
00194 bool KSocks::_disabled = false;
00195 static KStaticDeleter<KSocks> med;
00196 
00197 void KSocks::disable() 
00198 { 
00199    if (!_me) _disabled = true; 
00200 }
00201 
00202 KSocks *KSocks::self() {
00203   if (!_me) {
00204     if (kapp)
00205     {
00206        KConfigGroup cfg(kapp->config(), "Socks");
00207        _me = med.setObject(new KSocks(&cfg));
00208     }
00209     else
00210     {
00211        _disabled = true;
00212        _me = med.setObject(new KSocks(0));
00213     }
00214   }
00215   return _me;
00216 }
00217 
00218 void KSocks::setConfig(KConfigBase *config)
00219 {
00220   // We can change the config from disabled to enabled
00221   // but not the other way around.
00222   if (_me && _disabled) 
00223   { 
00224      delete _me;
00225      _me = 0;
00226      _disabled = false;
00227   }
00228   if (_me) return;
00229   _me = med.setObject(new KSocks(config));
00230 }
00231 
00232 bool KSocks::activated() { return (_me != NULL); }
00233 
00234 
00235 KSocks::KSocks(KConfigBase *config) : _socksLib(NULL), _st(NULL) {
00236    _hasSocks = false;
00237    _useSocks = false;
00238 
00239    if (_disabled || !config)
00240       return;
00241 
00242    _libPaths << ""
00243              << "/usr/lib/"
00244              << "/usr/local/lib/"
00245              << "/usr/local/socks5/lib/"
00246              << "/opt/socks5/lib/";
00247    _libNames << "libsocks.so"                  // Dante
00248              << "libsocks5.so"                 // ?
00249              << "libsocks5_sh.so";             // NEC
00250 
00251 
00252 
00253    if (!(config->readBoolEntry("SOCKS_enable", false))) 
00254    {
00255       _disabled = true;
00256       return;
00257    }
00258 
00259    // Add the custom library paths here
00260    QStringList newlibs = config->readListEntry("SOCKS_lib_path");
00261 
00262    for (QStringList::Iterator it = newlibs.begin();
00263                               it != newlibs.end();
00264                               ++it) {
00265       QString thisone = *it;
00266       if (thisone[thisone.length()-1] != '/') thisone += "/";
00267       _libPaths << thisone;
00268       kdDebug(171) << "KSocks added a new library path: " << thisone << endl;
00269    }
00270 
00271    // Load the proper libsocks and KSocksTable
00272    KLibLoader *ll = KLibLoader::self();
00273    
00274 
00275    int _meth = config->readNumEntry("SOCKS_method", 1);
00276          /****       Current methods
00277           *   1) Autodetect (read: any)     2) NEC
00278           *   3) Dante                      4) Custom
00279           */
00280 
00281    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
00282       _socksLib = ll->library(config->readEntry("SOCKS_lib", "").latin1());
00283       if (_socksLib && _socksLib->symbol("Rconnect")) {  // Dante compatible?
00284          _st = new KDanteSocksTable;       
00285          _useSocks = true;
00286          _hasSocks = true;
00287       } else if (_socksLib && _socksLib->symbol("connect")) { // NEC compatible?
00288          _st = new KNECSocksTable;       
00289          _useSocks = true;
00290          _hasSocks = true;
00291       } else if (_socksLib) {
00292          ll->unloadLibrary(QFile::encodeName(_socksLib->name()));
00293          _socksLib = NULL;
00294       }
00295    } else              // leave this here   "else for {}"
00296    for (QStringList::Iterator pit  = _libPaths.begin();
00297                               !_hasSocks && pit != _libPaths.end();
00298                               ++pit)
00299    for (QStringList::Iterator it  = _libNames.begin();
00300                               it != _libNames.end();
00301                               ++it) {
00302       _socksLib = ll->library((*pit + *it).latin1());
00303       if (_socksLib) {
00304          if ((_meth == 1 || _meth == 2) &&
00305              _socksLib->symbol("S5LogShowThreadIDS") != NULL) {  // NEC SOCKS
00306             kdDebug(171) << "Found NEC SOCKS" << endl;
00307             _st = new KNECSocksTable;
00308             _useSocks = true;
00309             _hasSocks = true;
00310             break;
00311          } else if ((_meth == 1 || _meth == 3) && 
00312                     _socksLib->symbol("sockaddr2ruleaddress") != NULL) { //Dante
00313             kdDebug(171) << "Found Dante SOCKS" << endl;
00314             _st = new KDanteSocksTable;
00315             _useSocks = true;
00316             _hasSocks = true;
00317             break;
00318          } else {
00319            ll->unloadLibrary(QFile::encodeName(_socksLib->name()));
00320            _socksLib = NULL;
00321          }
00322       }
00323    }
00324 
00325    // Load in all the symbols
00326    if (_st) {
00327       for (QMap<SymbolKeys,QString>::Iterator it  = _st->symbols.begin();
00328                                               it != _st->symbols.end();
00329                                               ++it) {
00330          switch(it.key()) {
00331          case S_SOCKSinit:
00332            F_SOCKSinit = (int (*)(char *))
00333                          _socksLib->symbol(it.data().latin1());
00334           break;
00335          case S_connect:
00336            F_connect = (int (*)(int, const struct sockaddr *, ksocklen_t))
00337                        _socksLib->symbol(it.data().latin1());
00338           break;
00339          case S_read:
00340            F_read = (signed long int (*)(int, void *, unsigned long int))
00341                     _socksLib->symbol(it.data().latin1());
00342           break;
00343          case S_write:
00344            F_write = (signed long int (*)(int, const void *, unsigned long int))
00345                      _socksLib->symbol(it.data().latin1());
00346           break;
00347          case S_recvfrom:
00348            F_recvfrom = (int (*)(int, void *, unsigned long int, int, 
00349                                  struct sockaddr *, ksocklen_t *))
00350                         _socksLib->symbol(it.data().latin1());
00351           break;
00352          case S_sendto:
00353            F_sendto = (int (*)(int, const void *, unsigned long int, int,
00354                                const struct sockaddr *, ksocklen_t))
00355                       _socksLib->symbol(it.data().latin1());
00356           break;
00357          case S_recv:
00358            F_recv = (int (*)(int, void *, unsigned long int, int))
00359                     _socksLib->symbol(it.data().latin1());
00360           break;
00361          case S_send:
00362            F_send = (int (*)(int, const void *, unsigned long int, int))
00363                     _socksLib->symbol(it.data().latin1());
00364           break;
00365          case S_getsockname:
00366            F_getsockname = (int (*)(int, struct sockaddr *, ksocklen_t *))
00367                            _socksLib->symbol(it.data().latin1());
00368           break;
00369          case S_getpeername:
00370            F_getpeername = (int (*)(int, struct sockaddr *, ksocklen_t *))
00371                            _socksLib->symbol(it.data().latin1());
00372           break;
00373          case S_accept:
00374            F_accept = (int (*)(int, struct sockaddr *, ksocklen_t *))
00375                       _socksLib->symbol(it.data().latin1());
00376           break;
00377          case S_select:
00378            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
00379                       _socksLib->symbol(it.data().latin1());
00380           break;
00381          case S_listen:
00382            F_listen = (int (*)(int, int))
00383                       _socksLib->symbol(it.data().latin1());
00384           break;
00385          case S_bind:
00386            F_bind = (int (*)(int, struct sockaddr *, ksocklen_t))
00387                     _socksLib->symbol(it.data().latin1());
00388           break;
00389          default:
00390           kdDebug(171) << "KSocks got a symbol it doesn't know about!" << endl;
00391           break;
00392          }
00393       }
00394  
00395       // Now we check for the critical stuff.
00396       if (F_SOCKSinit) {
00397         int rc = (*F_SOCKSinit)((char *)"KDE");
00398         if (rc != 0) stopSocks();
00399         else  kdDebug(171) << "SOCKS has been activated!" << endl;
00400       } else {
00401         stopSocks();
00402       }
00403    }
00404 }
00405 
00406 
00407 KSocks::~KSocks() {
00408   stopSocks();
00409   _me = med.setObject(0);
00410 }
00411 
00412 
00413 void KSocks::die() {
00414   if (_me == this) {
00415     _me = NULL;
00416     delete this;
00417   }
00418 }
00419 
00420 void KSocks::stopSocks() {
00421    if (_hasSocks) {
00422         // This library doesn't even provide the basics.
00423         // it's probably broken.  Lets abort.
00424           _useSocks = false;
00425           _hasSocks = false;
00426           if (_socksLib)
00427             _socksLib->unload();
00428           _socksLib = NULL;
00429           delete _st;
00430           _st = NULL;
00431    }
00432 }
00433 
00434  
00435 bool KSocks::usingSocks() {
00436    return _useSocks;
00437 }
00438 
00439 
00440 bool KSocks::hasSocks() {
00441 return _hasSocks;
00442 }
00443 
00444 
00445 void KSocks::disableSocks() {
00446   _useSocks = false;
00447 }
00448 
00449 
00450 void KSocks::enableSocks() {
00451   if (_hasSocks)
00452      _useSocks = true;
00453 }
00454 
00455 
00456 
00457 /*
00458  *   REIMPLEMENTED FUNCTIONS FROM LIBC
00459  *
00460  */
00461 
00462 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
00463                                                    ksocklen_t addrlen) {
00464   if (_useSocks && F_connect)
00465     return (*F_connect)(sockfd, serv_addr, addrlen);
00466   else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
00467 }
00468 
00469 
00470 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
00471   if (_useSocks && F_read)
00472     return (*F_read)(fd, buf, count);
00473   else return ::read(fd, buf, count);
00474 }
00475 
00476 
00477 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
00478   if (_useSocks && F_write)
00479     return (*F_write)(fd, buf, count);
00480   else return ::write(fd, buf, count);
00481 }
00482 
00483 
00484 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
00485                                 sockaddr *from, ksocklen_t *fromlen) {
00486   if (_useSocks && F_recvfrom)
00487     return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
00488   else {
00489     socklen_t casted_len = (socklen_t) *fromlen;
00490     int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
00491     *fromlen = casted_len;
00492     return rc;
00493   }
00494 }
00495 
00496 
00497 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
00498                              const sockaddr *to, ksocklen_t tolen) {
00499   if (_useSocks && F_sendto)
00500     return (*F_sendto)(s, msg, len, flags, to, tolen);
00501   else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
00502 }
00503 
00504 
00505 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
00506   if (_useSocks && F_recv)
00507     return (*F_recv)(s, buf, len, flags);
00508   else return ::recv(s, (char*) buf, len, flags);
00509 }
00510 
00511 
00512 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
00513   if (_useSocks && F_send)
00514     return (*F_send)(s, msg, len, flags);
00515   else return ::send(s, (char*) msg, len, flags);
00516 }
00517 
00518 
00519 int KSocks::getsockname (int s, sockaddr *name, ksocklen_t *namelen) {
00520   if (_useSocks && F_getsockname)
00521     return (*F_getsockname)(s, name, namelen);
00522   else {
00523     socklen_t casted_len = *namelen;
00524     int rc = ::getsockname(s, name, &casted_len);
00525     *namelen = casted_len;
00526     return rc;
00527   }
00528 }
00529 
00530 
00531 int KSocks::getpeername (int s, sockaddr *name, ksocklen_t *namelen) {
00532   if (_useSocks && F_getpeername)
00533     return (*F_getpeername)(s, name, namelen);
00534   else {
00535     socklen_t casted_len = *namelen;
00536     int rc = ::getpeername(s, name, &casted_len);
00537     *namelen = casted_len;
00538     return rc;
00539   }
00540 }
00541 
00542 
00543 int KSocks::accept (int s, sockaddr *addr, ksocklen_t *addrlen) {
00544   if (_useSocks && F_accept)
00545     return (*F_accept)(s, addr, addrlen);
00546   else {
00547     socklen_t casted_len = *addrlen;
00548     int rc = ::accept(s, addr, &casted_len);
00549     *addrlen = casted_len;
00550     return rc;
00551   }
00552 }
00553 
00554 
00555 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
00556                                 fd_set *exceptfds, struct timeval *timeout) {
00557   if (_useSocks && F_select)
00558     return (*F_select)(n, readfds, writefds, exceptfds, timeout);
00559   else return ::select(n, readfds, writefds, exceptfds, timeout);
00560 }
00561 
00562 
00563 int KSocks::listen (int s, int backlog) {
00564   if (_useSocks && F_listen)
00565     return (*F_listen)(s, backlog);
00566   else return ::listen(s, backlog);
00567 }
00568 
00569 
00570 int KSocks::bind (int sockfd, sockaddr *my_addr, ksocklen_t addrlen) {
00571   if (_useSocks && F_bind)
00572     return (*F_bind)(sockfd, my_addr, addrlen);
00573   else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00574 }
00575 
00576 
00577 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:20:42 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001