00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kinetd.h"
00020 #include "kinetd.moc"
00021 #include "kinetinterface.h"
00022 #include "kuser.h"
00023 #include "uuid.h"
00024 #include <qregexp.h>
00025 #include <kservicetype.h>
00026 #include <kdebug.h>
00027 #include <kstandarddirs.h>
00028 #include <kconfig.h>
00029 #include <KNotification>
00030 #include <ksocketaddress.h>
00031 #include <ksocketdevice.h>
00032 #include <klocale.h>
00033 #include <kglobal.h>
00034
00035 #include <unistd.h>
00036 #include <fcntl.h>
00037
00038 #include <kpluginfactory.h>
00039 #include <kpluginloader.h>
00040
00041 K_PLUGIN_FACTORY(KInetDFactory,
00042 registerPlugin<KInetD>();
00043 )
00044 K_EXPORT_PLUGIN(KInetDFactory("kinetd"))
00045
00046 PortListener::PortListener(KService::Ptr s,
00047 KConfig *config,
00048 KServiceRegistry *srvreg) :
00049 m_port(-1),
00050 m_serviceRegistered(false),
00051 m_socket(0),
00052 m_config(config),
00053 m_srvreg(srvreg),
00054 m_dnssdreg(0)
00055 {
00056 m_uuid = createUUID();
00057 loadConfig(s);
00058
00059 if (m_valid && m_enabled)
00060 acquirePort();
00061 }
00062
00063 bool PortListener::acquirePort() {
00064 if (m_socket) {
00065 if ((m_port >= m_portBase) &&
00066 (m_port < (m_portBase + m_autoPortRange)))
00067 return true;
00068 else
00069 delete m_socket;
00070 }
00071 m_port = m_portBase;
00072 m_socket = new KNetwork::KServerSocket(m_port, false);
00073 while (!m_socket->bindAndListen()) {
00074 m_port++;
00075 if (m_port >= (m_portBase+m_autoPortRange)) {
00076 kDebug() << "Kinetd cannot load service "<<m_serviceName
00077 <<": unable to get port" << endl;
00078 m_port = -1;
00079 delete m_socket;
00080 m_socket = 0;
00081 return false;
00082 }
00083 delete m_socket;
00084 m_socket = new KNetwork::KServerSocket(m_port, false);
00085 }
00086 connect(m_socket, SIGNAL(accepted(KSocket*)),
00087 SLOT(accepted(KSocket*)));
00088
00089 bool s = m_registerService;
00090 bool sd =m_dnssdRegister;
00091 setServiceRegistrationEnabledInternal(false);
00092 dnssdRegister(false);
00093 setServiceRegistrationEnabledInternal(s);
00094 dnssdRegister(sd);
00095 return true;
00096 }
00097
00098 void PortListener::freePort() {
00099 m_port = -1;
00100 delete m_socket;
00101 m_socket = 0;
00102 setServiceRegistrationEnabledInternal(m_registerService);
00103 dnssdRegister(false);
00104 }
00105
00106 void PortListener::loadConfig(KService::Ptr s) {
00107 m_valid = true;
00108 m_autoPortRange = 0;
00109 m_enabled = true;
00110 m_argument.clear();
00111 m_multiInstance = false;
00112
00113 QVariant vid, vport, vautoport, venabled, vargument, vmultiInstance, vurl,
00114 vsattributes, vslifetime, vdname, vdtype, vddata;
00115
00116 m_execPath = s->exec().utf8();
00117 vid = s->property("X-KDE-KINETD-id");
00118 vport = s->property("X-KDE-KINETD-port");
00119 vautoport = s->property("X-KDE-KINETD-autoPortRange");
00120 venabled = s->property("X-KDE-KINETD-enabled");
00121 vargument = s->property("X-KDE-KINETD-argument");
00122 vmultiInstance = s->property("X-KDE-KINETD-multiInstance");
00123 vurl = s->property("X-KDE-KINETD-serviceURL");
00124 vsattributes = s->property("X-KDE-KINETD-serviceAttributes");
00125 vslifetime = s->property("X-KDE-KINETD-serviceLifetime");
00126 vdname = s->property("X-KDE-KINETD-DNSSD-Name");
00127 vdtype = s->property("X-KDE-KINETD-DNSSD-Type");
00128 vddata = s->property("X-KDE-KINETD-DNSSD-Properties");
00129
00130 if (!vid.isValid()) {
00131 kDebug() << "Kinetd cannot load service "<<m_serviceName
00132 <<": no id set" << endl;
00133 m_valid = false;
00134 return;
00135 }
00136
00137 if (!vport.isValid()) {
00138 kDebug() << "Kinetd cannot load service "<<m_serviceName
00139 <<": invalid port" << endl;
00140 m_valid = false;
00141 return;
00142 }
00143
00144 m_serviceName = vid.toString();
00145 m_serviceLifetime = vslifetime.toInt();
00146 if (m_serviceLifetime < 120)
00147 m_serviceLifetime = 120;
00148 m_portBase = vport.toInt();
00149 if (vautoport.isValid())
00150 m_autoPortRange = vautoport.toInt();
00151 if (venabled.isValid())
00152 m_enabled = venabled.toBool();
00153 if (vargument.isValid())
00154 m_argument = vargument.toString();
00155 if (vmultiInstance.isValid())
00156 m_multiInstance = vmultiInstance.toBool();
00157 if (vurl.isValid()) {
00158 m_serviceURL = vurl.toString();
00159 m_registerService = true;
00160 }
00161 else {
00162 m_serviceURL.clear();
00163 m_registerService = false;
00164 }
00165 if (vsattributes.isValid()) {
00166 m_serviceAttributes = vsattributes.toString();
00167 }
00168 else
00169 m_serviceAttributes = "";
00170 if (vddata.isValid()) {
00171 QStringList attrs = vddata.toStringList();
00172 for (QStringList::iterator it=attrs.begin();
00173 it!=attrs.end();it++) {
00174 QString key = (*it).section('=',0,0);
00175 QString value = processServiceTemplate((*it).section('=',1))[0];
00176 if (!key.isEmpty()) m_dnssdData[key]=value;
00177 }
00178 }
00179 if (vdname.isValid() && vdtype.isValid()) {
00180 m_dnssdName = processServiceTemplate(vdname.toString())[0];
00181 m_dnssdType = vdtype.toString();
00182 m_dnssdRegister = true;
00183 kDebug() << "DNS-SD register is enabled\n";
00184 }
00185 else
00186 m_dnssdRegister = false;
00187
00188
00189 m_slpLifetimeEnd = QDateTime::currentDateTime().addSecs(m_serviceLifetime);
00190 m_defaultPortBase = m_portBase;
00191 m_defaultAutoPortRange = m_autoPortRange;
00192
00193 m_config->setGroup("ListenerConfig");
00194 m_enabled = m_config->readEntry("enabled_" + m_serviceName,
00195 m_enabled);
00196 m_portBase = m_config->readEntry("port_base_" + m_serviceName,
00197 m_portBase);
00198 m_autoPortRange = m_config->readEntry("auto_port_range_" + m_serviceName,
00199 m_autoPortRange);
00200 QDateTime nullTime;
00201 m_expirationTime = m_config->readDateTimeEntry("enabled_expiration_"+m_serviceName,
00202 &nullTime);
00203 if ((!m_expirationTime.isNull()) && (m_expirationTime < QDateTime::currentDateTime()))
00204 m_enabled = false;
00205 m_registerService = m_config->readEntry("enabled_srvreg_"+m_serviceName,
00206 m_registerService);
00207 }
00208
00209 void PortListener::accepted(KSocket *sock) {
00210 QString host, port;
00211 KSocketDevice device(sock->socket());
00212 KSocketAddress ksa = device->peerAddress();
00213 if ( ksa.address()) {
00214 delete sock;
00215 return;
00216 }
00217 KExtendedSocket::resolve(ksa, host, port);
00218 KNotification::event("IncomingConnection",
00219 i18n("Connection from %1", host));
00220 delete ksa;
00221
00222 if ((!m_enabled) ||
00223 ((!m_multiInstance) && m_process.isRunning())) {
00224 delete sock;
00225 return;
00226 }
00227
00228
00229 fcntl(sock->socket(), F_SETFD, fcntl(sock->socket(), F_GETFD) & ~FD_CLOEXEC);
00230
00231 m_process.clearArguments();
00232 m_process << m_execPath << m_argument << QString::number(sock->socket());
00233 if (!m_process.start(K3Process::DontCare)) {
00234 KNotification::event("ProcessFailed",
00235 i18n("Call \"%1 %2 %3\" failed", m_execPath,
00236 m_argument,
00237 sock->socket()));
00238 }
00239
00240 delete sock;
00241 }
00242
00243 bool PortListener::isValid() {
00244 return m_valid;
00245 }
00246
00247 bool PortListener::isEnabled() {
00248 return m_enabled && m_valid;
00249 }
00250
00251 int PortListener::port() {
00252 return m_port;
00253 }
00254
00255 QStringList PortListener::processServiceTemplate(const QString &a) {
00256 QStringList l;
00257 QValueVector<KInetInterface> v = KInetInterface::getAllInterfaces(false);
00258 QValueVector<KInetInterface>::Iterator it = v.begin();
00259 while (it != v.end()) {
00260 KInetSocketAddress *address = (*(it++)).address();
00261 if (!address)
00262 continue;
00263 QString hostName = address->nodeName();
00264 KUser u;
00265 QString x = a;
00266 l.append(x.replace(QString("%h"), KServiceRegistry::encodeAttributeValue(hostName))
00267 .replace(QString("%p"), QString::number(m_port))
00268 .replace(QString("%u"), KServiceRegistry::encodeAttributeValue(u.loginName()))
00269 .replace(QString("%i"), KServiceRegistry::encodeAttributeValue(m_uuid))
00270 .replace(QString("%f"), KServiceRegistry::encodeAttributeValue(u.fullName())));
00271 }
00272 return l;
00273 }
00274
00275 bool PortListener::setPort(int port, int autoPortRange) {
00276 if ((port == m_portBase) && (autoPortRange == m_autoPortRange))
00277 return (m_port != -1);
00278
00279 m_config->setGroup("ListenerConfig");
00280 if (port > 0) {
00281 m_portBase = port;
00282 m_autoPortRange = autoPortRange;
00283
00284 m_config->writeEntry("port_base_" + m_serviceName, m_portBase);
00285 m_config->writeEntry("auto_port_range_"+m_serviceName, m_autoPortRange);
00286 }
00287 else {
00288 m_portBase = m_defaultPortBase;
00289 m_autoPortRange = m_defaultAutoPortRange;
00290
00291 m_config->deleteEntry("port_base_" + m_serviceName);
00292 m_config->deleteEntry("auto_port_range_"+m_serviceName);
00293 }
00294
00295 m_config->sync();
00296 if (m_enabled)
00297 return acquirePort();
00298 else
00299 return false;
00300 }
00301
00302 void PortListener::setEnabled(bool e) {
00303 setEnabledInternal(e, QDateTime());
00304 }
00305
00306 void PortListener::setEnabledInternal(bool e, const QDateTime &ex) {
00307 m_config->setGroup("ListenerConfig");
00308 m_config->writeEntry("enabled_" + m_serviceName, e);
00309 m_config->writeEntry("enabled_expiration_"+m_serviceName, ex);
00310 m_config->sync();
00311
00312 m_expirationTime = ex;
00313
00314 if (e) {
00315 if (m_port < 0)
00316 acquirePort();
00317 m_enabled = m_port >= 0;
00318
00319 }
00320 else {
00321 freePort();
00322 m_enabled = false;
00323 }
00324 }
00325
00326 void PortListener::setEnabled(const QDateTime &ex) {
00327 setEnabledInternal(true, ex);
00328 }
00329
00330 bool PortListener::isServiceRegistrationEnabled() {
00331 return m_registerService;
00332 }
00333
00334 void PortListener::setServiceRegistrationEnabled(bool e) {
00335 setServiceRegistrationEnabledInternal(e);
00336 dnssdRegister(e && m_enabled);
00337 m_config->setGroup("ListenerConfig");
00338 m_config->writeEntry("enable_srvreg_" + m_serviceName, e);
00339 m_config->sync();
00340 }
00341
00342 void PortListener::setServiceRegistrationEnabledInternal(bool e) {
00343 m_registerService = e;
00344
00345 if ((!m_srvreg) || m_serviceURL.isNull())
00346 return;
00347 if (m_serviceRegistered == (m_enabled && e))
00348 return;
00349
00350 if (m_enabled && e) {
00351 m_registeredServiceURLs = processServiceTemplate(m_serviceURL);
00352 QStringList attributes = processServiceTemplate(m_serviceAttributes);
00353 QStringList::Iterator it = m_registeredServiceURLs.begin();
00354 QStringList::Iterator it2 = attributes.begin();
00355 while ((it != m_registeredServiceURLs.end()) &&
00356 (it2 != attributes.end())) {
00357 if (!m_srvreg->registerService(
00358 *(it++),
00359 *(it2++),
00360 m_serviceLifetime))
00361 kDebug(7021) << "Failure registering SLP service (no slpd running?)";
00362 }
00363 m_serviceRegistered = true;
00364
00365 m_slpLifetimeEnd = QDateTime::currentDateTime().addSecs(m_serviceLifetime-30);
00366 } else {
00367 QStringList::Iterator it = m_registeredServiceURLs.begin();
00368 while (it != m_registeredServiceURLs.end())
00369 m_srvreg->unregisterService(*(it++));
00370 m_serviceRegistered = false;
00371 }
00372 }
00373
00374 void PortListener::dnssdRegister(bool e) {
00375 if (m_dnssdName.isNull() || m_dnssdType.isNull())
00376 return;
00377 if (m_dnssdRegistered == e)
00378 return;
00379 if (e) {
00380 m_dnssdRegistered=true;
00381 m_dnssdreg = new DNSSD::PublicService(m_dnssdName,m_dnssdType,m_port);
00382 m_dnssdreg->setTextData(m_dnssdData);
00383 m_dnssdreg->publishAsync();
00384 } else {
00385 m_dnssdRegistered=false;
00386 delete m_dnssdreg;
00387 m_dnssdreg=0;
00388 }
00389 }
00390
00391 void PortListener::refreshRegistration() {
00392 if (m_serviceRegistered && (m_slpLifetimeEnd.addSecs(-90) < QDateTime::currentDateTime())) {
00393 setServiceRegistrationEnabledInternal(false);
00394 setServiceRegistrationEnabledInternal(true);
00395 }
00396 }
00397
00398 QDateTime PortListener::expiration() {
00399 return m_expirationTime;
00400 }
00401
00402 QDateTime PortListener::serviceLifetimeEnd() {
00403 if (m_serviceRegistered)
00404 return m_slpLifetimeEnd;
00405 else
00406 return QDateTime();
00407 }
00408
00409 QString PortListener::name() {
00410 return m_serviceName;
00411 }
00412
00413 PortListener::~PortListener() {
00414 setServiceRegistrationEnabledInternal(false);
00415 delete m_socket;
00416 }
00417
00418
00419 KInetD::KInetD(QObject* parent, const QList<QVariant>&) :
00420 KDEDModule(parent)
00421 {
00422 m_config = new KConfig("kinetdrc");
00423 m_srvreg = new KServiceRegistry();
00424 if (!m_srvreg->available()) {
00425 kDebug(7021) << "SLP not available";
00426 delete m_srvreg;
00427 m_srvreg = 0;
00428 }
00429 m_portListeners.setAutoDelete(true);
00430 connect(&m_expirationTimer, SIGNAL(timeout()), SLOT(setExpirationTimer()));
00431 connect(&m_portRetryTimer, SIGNAL(timeout()), SLOT(portRetryTimer()));
00432 connect(&m_reregistrationTimer, SIGNAL(timeout()), SLOT(reregistrationTimer()));
00433 loadServiceList();
00434 }
00435
00436 void KInetD::loadServiceList()
00437 {
00438 m_portListeners.clear();
00439
00440
00441 KService::List kinetdModules =
00442 KServiceType::offers("KInetDModule");
00443 for(KService::List::ConstIterator it = kinetdModules.begin();
00444 it != kinetdModules.end();
00445 it++) {
00446 KService::Ptr s = *it;
00447 PortListener *pl = new PortListener(s, m_config, m_srvreg);
00448 if (pl->isValid())
00449 m_portListeners.append(pl);
00450 else
00451 delete pl;
00452 }
00453
00454 setExpirationTimer();
00455 setPortRetryTimer(true);
00456 setReregistrationTimer();
00457 }
00458
00459 void KInetD::expirationTimer() {
00460 setExpirationTimer();
00461 setReregistrationTimer();
00462 }
00463
00464 void KInetD::setExpirationTimer() {
00465 QDateTime nextEx = getNextExpirationTime();
00466 if (!nextEx.isNull())
00467 m_expirationTimer.start(QDateTime::currentDateTime().secsTo(nextEx)*1000 + 30000,
00468 false);
00469 else
00470 m_expirationTimer.stop();
00471 }
00472
00473 void KInetD::portRetryTimer() {
00474 setPortRetryTimer(true);
00475 setReregistrationTimer();
00476 }
00477
00478 void KInetD::setReregistrationTimer() {
00479 QDateTime d;
00480 PortListener *pl = m_portListeners.first();
00481 while (pl) {
00482 QDateTime d2 = pl->serviceLifetimeEnd();
00483 if (!d2.isNull()) {
00484 if (d2 < QDateTime::currentDateTime()) {
00485 m_reregistrationTimer.start(0, true);
00486 return;
00487 }
00488 else if (d.isNull() || (d2 < d))
00489 d = d2;
00490 }
00491 pl = m_portListeners.next();
00492 }
00493
00494 if (!d.isNull()) {
00495 int s = QDateTime::currentDateTime().secsTo(d);
00496 if (s < 30)
00497 s = 30;
00498 m_reregistrationTimer.start(s*1000, true);
00499 }
00500 else
00501 m_reregistrationTimer.stop();
00502 }
00503
00504 void KInetD::reregistrationTimer() {
00505 PortListener *pl = m_portListeners.first();
00506 while (pl) {
00507 pl->refreshRegistration();
00508 pl = m_portListeners.next();
00509 }
00510 setReregistrationTimer();
00511 }
00512
00513 void KInetD::setPortRetryTimer(bool retry) {
00514 int unmappedPorts = 0;
00515
00516 PortListener *pl = m_portListeners.first();
00517 while (pl) {
00518 if (pl->isEnabled() && (pl->port() < 0))
00519 if (retry) {
00520 if (!pl->acquirePort())
00521 unmappedPorts++;
00522 }
00523 else if (pl->port() < 0)
00524 unmappedPorts++;
00525 pl = m_portListeners.next();
00526 }
00527
00528 if (unmappedPorts > 0)
00529 m_portRetryTimer.start(30000, false);
00530 else
00531 m_portRetryTimer.stop();
00532 }
00533
00534 PortListener *KInetD::getListenerByName(QString name)
00535 {
00536 PortListener *pl = m_portListeners.first();
00537 while (pl) {
00538 if (pl->name() == name)
00539 return pl;
00540 pl = m_portListeners.next();
00541 }
00542 return pl;
00543 }
00544
00545
00546 QDateTime KInetD::getNextExpirationTime()
00547 {
00548 PortListener *pl = m_portListeners.first();
00549 QDateTime d;
00550 while (pl) {
00551 QDateTime d2 = pl->expiration();
00552 if (!d2.isNull()) {
00553 if (d2 < QDateTime::currentDateTime())
00554 pl->setEnabled(false);
00555 else if (d.isNull() || (d2 < d))
00556 d = d2;
00557 }
00558 pl = m_portListeners.next();
00559 }
00560 return d;
00561 }
00562
00563 QStringList KInetD::services()
00564 {
00565 QStringList list;
00566 PortListener *pl = m_portListeners.first();
00567 while (pl) {
00568 list.append(pl->name());
00569 pl = m_portListeners.next();
00570 }
00571 return list;
00572 }
00573
00574 bool KInetD::isEnabled(QString service)
00575 {
00576 PortListener *pl = getListenerByName(service);
00577 if (!pl)
00578 return false;
00579
00580 return pl->isEnabled();
00581 }
00582
00583 int KInetD::port(QString service)
00584 {
00585 PortListener *pl = getListenerByName(service);
00586 if (!pl)
00587 return -1;
00588
00589 return pl->port();
00590 }
00591
00592 bool KInetD::setPort(QString service, int port, int autoPortRange)
00593 {
00594 PortListener *pl = getListenerByName(service);
00595 if (!pl)
00596 return false;
00597
00598 bool s = pl->setPort(port, autoPortRange);
00599 setPortRetryTimer(false);
00600 setReregistrationTimer();
00601 return s;
00602 }
00603
00604 bool KInetD::isInstalled(QString service)
00605 {
00606 PortListener *pl = getListenerByName(service);
00607 return (pl != 0);
00608 }
00609
00610 void KInetD::setEnabled(QString service, bool enable)
00611 {
00612 PortListener *pl = getListenerByName(service);
00613 if (!pl)
00614 return;
00615
00616 pl->setEnabled(enable);
00617 setExpirationTimer();
00618 setReregistrationTimer();
00619 }
00620
00621 void KInetD::setEnabled(QString service, QDateTime expiration)
00622 {
00623 PortListener *pl = getListenerByName(service);
00624 if (!pl)
00625 return;
00626
00627 pl->setEnabled(expiration);
00628 setExpirationTimer();
00629 setReregistrationTimer();
00630 }
00631
00632 void KInetD::setServiceRegistrationEnabled(QString service, bool enable)
00633 {
00634 PortListener *pl = getListenerByName(service);
00635 if (!pl)
00636 return;
00637
00638 pl->setServiceRegistrationEnabled(enable);
00639 setReregistrationTimer();
00640 }
00641
00642 bool KInetD::isServiceRegistrationEnabled(QString service)
00643 {
00644 PortListener *pl = getListenerByName(service);
00645 if (!pl)
00646 return false;
00647
00648 return pl->isServiceRegistrationEnabled();
00649 }
00650
00651 KInetD::~KInetD() {
00652 m_portListeners.clear();
00653 delete m_config;
00654 delete m_srvreg;
00655 }