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