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, 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
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:40:09 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003