/* Copyright (c) 2003 Malte Starostik This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #include #ifdef HAVE_ARPA_NAMESER8_COMPAT_H #include #endif #ifdef HAVE_SYS_PARAM_H // Basically, the BSDs need this before resolv.h #include #endif #include #include #include #include #include #include #include "discovery.moc" namespace KPAC { Discovery::Discovery( TQObject* parent ) : Downloader( parent ), m_helper( new KProcIO ) { connect( m_helper, TQT_SIGNAL( readReady( KProcIO* ) ), TQT_SLOT( helperOutput() ) ); connect( m_helper, TQT_SIGNAL( processExited( TDEProcess* ) ), TQT_SLOT( failed() ) ); *m_helper << "kpac_dhcp_helper"; if ( !m_helper->start() ) TQTimer::singleShot( 0, this, TQT_SLOT( failed() ) ); } bool Discovery::initHostName() { struct utsname uts; if (uname (&uts) > -1) { struct hostent *hent = gethostbyname (uts.nodename); if (hent != 0) m_hostname = TQString::fromLocal8Bit( hent->h_name ); } // If no hostname, try gethostname as a last resort. if (m_hostname.isEmpty()) { char buf [256]; if (gethostname (buf, sizeof(buf)) == 0) { buf[255] = '\0'; m_hostname = TQString::fromLocal8Bit( buf ); } } return !m_hostname.isEmpty(); } bool Discovery::checkDomain() const { // If a domain has a SOA record, don't traverse any higher. // Returns true if no SOA can be found (domain is "ok" to use) // Stick to old resolver interface for portability reasons. union { HEADER header; unsigned char buf[ PACKETSZ ]; } response; int len = res_query( m_hostname.local8Bit(), C_IN, T_SOA, response.buf, sizeof( response.buf ) ); if ( len <= int( sizeof( response.header ) ) || ntohs( response.header.ancount ) != 1 ) return true; unsigned char* pos = response.buf + sizeof( response.header ); unsigned char* end = response.buf + len; // skip query section pos += dn_skipname( pos, end ) + QFIXEDSZ; if ( pos >= end ) return true; // skip answer domain pos += dn_skipname( pos, end ); short type; GETSHORT( type, pos ); return type != T_SOA; } void Discovery::failed() { setError( i18n( "Could not find a usable proxy configuration script" ) ); // If this is the first DNS query, initialize our host name or abort // on failure. Otherwise abort if the current domain (which was already // queried for a host called "wpad" contains a SOA record) bool firstQuery = m_hostname.isEmpty(); if ( ( firstQuery && !initHostName() ) || ( !firstQuery && !checkDomain() ) ) { emit result( false ); return; } int dot = m_hostname.find( '.' ); if ( dot >= 0 ) { m_hostname.remove( 0, dot + 1 ); // remove one domain level download( KURL( "http://wpad." + m_hostname + "./wpad.dat" ) ); } else emit result( false ); } void Discovery::helperOutput() { m_helper->disconnect( this ); TQString line; m_helper->readln( line ); download( KURL( line.stripWhiteSpace() ) ); } }