summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2003-04-04 13:45:49 (UTC)
committer mickeyl <mickeyl>2003-04-04 13:45:49 (UTC)
commitb2153d44e64c1ade3ee141ea24075add1fd33777 (patch) (side-by-side diff)
tree6164d2eeef1c0ee79fcf4da85f2c8ed88aa0ecb3
parent089385bb8ab768fbf6f394f326e565e3589163fc (diff)
downloadopie-b2153d44e64c1ade3ee141ea24075add1fd33777.zip
opie-b2153d44e64c1ade3ee141ea24075add1fd33777.tar.gz
opie-b2153d44e64c1ade3ee141ea24075add1fd33777.tar.bz2
reliable strategy to see if we're in monitor mode by looking at the MAC address family
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opienet/onetwork.cpp55
-rw-r--r--libopie2/opienet/onetwork.h2
2 files changed, 24 insertions, 33 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp
index 789e8ca..6a363d7 100644
--- a/libopie2/opienet/onetwork.cpp
+++ b/libopie2/opienet/onetwork.cpp
@@ -23,149 +23,147 @@
++=   -.     .`     .: 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* OPIE */
#include <opie2/onetwork.h>
/* QT */
#include <qfile.h>
#include <qtextstream.h>
/* UNIX */
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/sockios.h>
+#include <net/if_arp.h>
#include <stdarg.h>
using namespace std;
/*======================================================================================
* ONetwork
*======================================================================================*/
ONetwork* ONetwork::_instance = 0;
ONetwork::ONetwork()
{
qDebug( "ONetwork::ONetwork()" );
synchronize();
}
void ONetwork::synchronize()
{
// gather available interfaces by inspecting /proc/net/dev
- // we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices
+ //FIXME: we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices
+ //FIXME: Use SIOCGIFCONF anway, because we can disable listing of aliased devices
_interfaces.clear();
QString str;
QFile f( "/proc/net/dev" );
bool hasFile = f.open( IO_ReadOnly );
if ( !hasFile )
{
qDebug( "ONetwork: /proc/net/dev not existing. No network devices available" );
return;
}
QTextStream s( &f );
s.readLine();
s.readLine();
while ( !s.atEnd() )
{
s >> str;
str.truncate( str.find( ':' ) );
qDebug( "ONetwork: found interface '%s'", (const char*) str );
ONetworkInterface* iface;
if ( isWirelessInterface( str ) )
{
iface = new OWirelessNetworkInterface( this, str );
qDebug( "ONetwork: interface '%s' has Wireless Extensions", (const char*) str );
}
else
{
iface = new ONetworkInterface( this, str );
}
_interfaces.insert( str, iface );
s.readLine();
}
}
ONetworkInterface* ONetwork::interface( QString iface ) const
{
return _interfaces[iface];
}
ONetwork* ONetwork::instance()
{
if ( !_instance ) _instance = new ONetwork();
return _instance;
}
ONetwork::InterfaceIterator ONetwork::iterator() const
{
return ONetwork::InterfaceIterator( _interfaces );
}
bool ONetwork::isWirelessInterface( const char* name ) const
{
int sfd = socket( AF_INET, SOCK_STREAM, 0 );
struct iwreq iwr;
memset( &iwr, 0, sizeof( struct iwreq ) );
strcpy( (char*) &iwr.ifr_name, name );
int result = ::ioctl( sfd, SIOCGIWNAME, &iwr );
- if ( result == -1 )
- qDebug( "ONetwork::ioctl(): SIOCGIWNAME failed: %d (%s)", result, strerror( errno ) );
- else
- qDebug( "ONetwork::ioctl(): SIOCGIWNAME ok." );
- return ( result != -1 );
+ return result != -1;
}
/*======================================================================================
* ONetworkInterface
*======================================================================================*/
ONetworkInterface::ONetworkInterface( QObject* parent, const char* name )
:QObject( parent, name ),
_sfd( socket( AF_INET, SOCK_DGRAM, 0 ) ), _mon( 0 )
{
qDebug( "ONetworkInterface::ONetworkInterface()" );
init();
}
struct ifreq& ONetworkInterface::ifr() const
{
return _ifr;
}
void ONetworkInterface::init()
{
qDebug( "ONetworkInterface::init()" );
memset( &_ifr, 0, sizeof( struct ifreq ) );
if ( _sfd == -1 )
{
qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", name() );
return;
}
@@ -210,64 +208,77 @@ bool ONetworkInterface::isUp() const
{
ioctl( SIOCGIFFLAGS );
return _ifr.ifr_flags & IFF_UP;
}
QString ONetworkInterface::ipV4Address() const
{
if ( ioctl( SIOCGIFADDR ) )
{
struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr;
//FIXME: Use QHostAddress here
return QString( inet_ntoa( sa->sin_addr ) );
}
else
return "<unknown>";
}
OMacAddress ONetworkInterface::macAddress() const
{
if ( ioctl( SIOCGIFHWADDR ) )
{
return OMacAddress( _ifr );
}
else
{
return OMacAddress::unknown;
}
}
+int ONetworkInterface::dataLinkType() const
+{
+ if ( ioctl( SIOCGIFHWADDR ) )
+ {
+ return _ifr.ifr_hwaddr.sa_family;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
void ONetworkInterface::setMonitoring( OMonitoringInterface* m )
{
_mon = m;
qDebug( "ONetwork::setMonitoring(): Installed monitoring driver '%s' on interface '%s'", (const char*) m->name(), name() );
}
OMonitoringInterface* ONetworkInterface::monitoring() const
{
return _mon;
}
ONetworkInterface::~ONetworkInterface()
{
qDebug( "ONetworkInterface::~ONetworkInterface()" );
if ( _sfd != -1 ) ::close( _sfd );
}
bool ONetworkInterface::setPromiscuousMode( bool b )
{
ioctl( SIOCGIFFLAGS );
if ( b ) _ifr.ifr_flags |= IFF_PROMISC;
else _ifr.ifr_flags &= (~IFF_PROMISC);
return ioctl( SIOCSIFFLAGS );
}
bool ONetworkInterface::promiscuousMode() const
{
ioctl( SIOCGIFFLAGS );
@@ -556,65 +567,66 @@ double OWirelessNetworkInterface::frequency() const
int OWirelessNetworkInterface::channels() const
{
return _channels.count();
}
void OWirelessNetworkInterface::setChannelHopping( int interval )
{
if ( !_hopper ) _hopper = new OChannelHopper( this );
_hopper->setInterval( interval );
//FIXME: When and by whom will the channel hopper be deleted?
//TODO: rely on QObject hierarchy
}
int OWirelessNetworkInterface::channelHopping() const
{
return _hopper->interval();
}
void OWirelessNetworkInterface::setMonitorMode( bool b )
{
if ( _mon )
_mon->setEnabled( b );
else
qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" );
}
bool OWirelessNetworkInterface::monitorMode() const
{
- return _mon ? _mon->enabled() : false;
+ qDebug( "dataLinkType = %d", dataLinkType() );
+ return dataLinkType() == ARPHRD_IEEE80211;
}
QString OWirelessNetworkInterface::nickName() const
{
char str[IW_ESSID_MAX_SIZE];
_iwr.u.data.pointer = &str[0];
_iwr.u.data.length = IW_ESSID_MAX_SIZE;
if ( !wioctl( SIOCGIWNICKN ) )
{
return "<unknown>";
}
else
{
str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
return str;
}
}
void OWirelessNetworkInterface::setPrivate( const QString& call, int numargs, ... )
{
OPrivateIOCTL* priv = static_cast<OPrivateIOCTL*>( child( (const char*) call ) );
if ( !priv )
{
qDebug( "OWirelessNetworkInterface::setPrivate(): interface '%s' does not support private ioctl '%s'", name(), (const char*) call );
return;
}
if ( priv->numberSetArgs() != numargs )
{
qDebug( "OWirelessNetworkInterface::setPrivate(): parameter count not matching. '%s' expects %d arguments, but got %d", (const char*) call, priv->numberSetArgs(), numargs );
return;
@@ -656,270 +668,249 @@ QString OWirelessNetworkInterface::SSID() const
void OWirelessNetworkInterface::setSSID( const QString& ssid )
{
_iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
_iwr.u.essid.length = ssid.length();
wioctl( SIOCSIWESSID );
}
bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const
{
int result = ::ioctl( _sfd, call, &iwreq );
if ( result == -1 )
qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) );
else
qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Ok.", call );
return ( result != -1 );
}
bool OWirelessNetworkInterface::wioctl( int call ) const
{
strcpy( _iwr.ifr_name, name() );
return wioctl( call, _iwr );
}
/*======================================================================================
* OMonitoringInterface
*======================================================================================*/
OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface )
- :_enabled( false ), _if( static_cast<OWirelessNetworkInterface*>( iface ) )
+ :_if( static_cast<OWirelessNetworkInterface*>( iface ) )
{
}
OMonitoringInterface::~OMonitoringInterface()
{
}
void OMonitoringInterface::setChannel( int c )
{
// use standard WE channel switching protocol
memset( &_if->_iwr, 0, sizeof( struct iwreq ) );
_if->_iwr.u.freq.m = c;
_if->_iwr.u.freq.e = 0;
_if->wioctl( SIOCSIWFREQ );
}
bool OMonitoringInterface::enabled() const
{
- return _enabled;
+ return _if->monitorMode();
}
+
void OMonitoringInterface::setEnabled( bool b )
{
- // open a packet capturer here or leave this to
- // the client code?
-
- /*
-
- if ( b )
- {
- OPacketCapturer* opcap = new OPacketCapturer();
- opcap->open( _if->name() );
- }
- */
-
- _enabled = b;
-
}
+
/*======================================================================================
* OCiscoMonitoringInterface
*======================================================================================*/
OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface )
:OMonitoringInterface( iface )
{
iface->setMonitoring( this );
}
OCiscoMonitoringInterface::~OCiscoMonitoringInterface()
{
}
void OCiscoMonitoringInterface::setEnabled( bool b )
{
QString fname;
fname.sprintf( "/proc/driver/aironet/%s", (const char*) _if->name() );
QFile f( fname );
if ( !f.exists() ) return;
if ( f.open( IO_WriteOnly ) )
{
QTextStream s( &f );
s << "Mode: r";
s << "Mode: y";
s << "XmitPower: 1";
-
- OMonitoringInterface::setEnabled( b );
-
}
// flushing and closing will be done automatically when f goes out of scope
}
QString OCiscoMonitoringInterface::name() const
{
return "cisco";
}
void OCiscoMonitoringInterface::setChannel( int )
{
// cisco devices automatically switch channels when in monitor mode
}
/*======================================================================================
* OWlanNGMonitoringInterface
*======================================================================================*/
OWlanNGMonitoringInterface::OWlanNGMonitoringInterface( ONetworkInterface* iface )
:OMonitoringInterface( iface )
{
iface->setMonitoring( this );
}
OWlanNGMonitoringInterface::~OWlanNGMonitoringInterface()
{
}
void OWlanNGMonitoringInterface::setEnabled( bool b )
{
//FIXME: do nothing if its already in the same mode
QString enable = b ? "true" : "false";
QString cmd;
cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s", (const char*) _if->name(), 1, (const char*) enable );
system( cmd );
-
- OMonitoringInterface::setEnabled( b );
}
QString OWlanNGMonitoringInterface::name() const
{
return "wlan-ng";
}
void OWlanNGMonitoringInterface::setChannel( int )
{
// wlan-ng devices automatically switch channels when in monitor mode
}
/*======================================================================================
* OHostAPMonitoringInterface
*======================================================================================*/
OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface )
:OMonitoringInterface( iface )
{
iface->setMonitoring( this );
}
OHostAPMonitoringInterface::~OHostAPMonitoringInterface()
{
}
void OHostAPMonitoringInterface::setEnabled( bool b )
{
// IW_MODE_MONITOR was introduced in Wireless Extensions Version 15
// Wireless Extensions < Version 15 need iwpriv commandos for monitoring
if ( b )
{
#if WIRELESS_EXT > 14
_if->_iwr.u.mode = IW_MODE_MONITOR;
_if->wioctl( SIOCSIWMODE );
#else
int* args = (int*) &_if->_iwr.u.name;
args[0] = 2;
args[1] = 0;
_if->wioctl( SIOCDEVPRIVATE );
#endif
}
else
{
#if WIRELESS_EXT > 14
_if->_iwr.u.mode = IW_MODE_INFRA;
_if->wioctl( SIOCSIWMODE );
#else
int* args = (int*) &_if->_iwr.u.name;
args[0] = 0;
args[1] = 0;
_if->wioctl( SIOCDEVPRIVATE );
#endif
}
-
- OMonitoringInterface::setEnabled( b );
}
QString OHostAPMonitoringInterface::name() const
{
return "hostap";
}
/*======================================================================================
* OOrinocoNetworkInterface
*======================================================================================*/
OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface )
:OMonitoringInterface( iface )
{
iface->setMonitoring( this );
}
OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface()
{
}
void OOrinocoMonitoringInterface::setChannel( int c )
{
// call iwpriv <device> monitor 2 <channel>
int* args = (int*) &_if->_iwr.u.name;
args[0] = 2;
args[1] = c;
_if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
}
void OOrinocoMonitoringInterface::setEnabled( bool b )
{
if ( b )
{
setChannel( 1 );
}
else
{
// call iwpriv <device> monitor 0 0
int* args = (int*) &_if->_iwr.u.name;
args[0] = 0;
args[1] = 0;
_if->wioctl( SIOCIWFIRSTPRIV + 0x8 );
}
-
- OMonitoringInterface::setEnabled( b );
}
QString OOrinocoMonitoringInterface::name() const
{
return "orinoco";
}
diff --git a/libopie2/opienet/onetwork.h b/libopie2/opienet/onetwork.h
index 509c3db..4cadbeb 100644
--- a/libopie2/opienet/onetwork.h
+++ b/libopie2/opienet/onetwork.h
@@ -97,64 +97,65 @@ class ONetwork : public QObject
private:
static ONetwork* _instance;
InterfaceMap _interfaces;
};
/*======================================================================================
* ONetworkInterface
*======================================================================================*/
class ONetworkInterface : public QObject
{
friend class OMonitoringInterface;
friend class OCiscoMonitoringInterface;
friend class OWlanNGMonitoringInterface;
friend class OHostAPMonitoringInterface;
friend class OOrinocoMonitoringInterface;
public:
ONetworkInterface( QObject* parent, const char* name );
virtual ~ONetworkInterface();
void setMonitoring( OMonitoringInterface* );
OMonitoringInterface* monitoring() const;
bool setPromiscuousMode( bool );
bool promiscuousMode() const;
bool setUp( bool );
bool isUp() const;
bool isLoopback() const;
bool isWireless() const;
QString ipV4Address() const;
OMacAddress macAddress() const;
+ int dataLinkType() const;
protected:
const int _sfd;
mutable ifreq _ifr;
OMonitoringInterface* _mon;
protected:
struct ifreq& ifr() const;
virtual void init();
bool ioctl( int call ) const;
bool ioctl( int call, struct ifreq& ) const;
};
/*======================================================================================
* OChannelHopper
*======================================================================================*/
class OChannelHopper : public QObject
{
public:
OChannelHopper( OWirelessNetworkInterface* );
virtual ~OChannelHopper();
bool isActive() const;
int channel() const;
virtual void timerEvent( QTimerEvent* );
void setInterval( int );
int interval() const;
private:
OWirelessNetworkInterface* _iface;
int _interval;
int _tid;
@@ -219,65 +220,64 @@ class OWirelessNetworkInterface : public ONetworkInterface
bool wioctl( int call ) const;
bool wioctl( int call, struct iwreq& ) const;
protected:
mutable struct iwreq _iwr;
QMap<int,int> _channels;
private:
OChannelHopper* _hopper;
};
/*======================================================================================
* OMonitoringInterface
*======================================================================================*/
class OMonitoringInterface
{
public:
OMonitoringInterface();
OMonitoringInterface( ONetworkInterface* );
virtual ~OMonitoringInterface();
public:
virtual void setEnabled( bool );
virtual bool enabled() const;
virtual void setChannel( int );
virtual QString name() const = 0;
protected:
- bool _enabled;
const OWirelessNetworkInterface* _if;
};
/*======================================================================================
* OCiscoMonitoring
*======================================================================================*/
class OCiscoMonitoringInterface : public OMonitoringInterface
{
public:
OCiscoMonitoringInterface( ONetworkInterface* );
virtual ~OCiscoMonitoringInterface();
virtual void setEnabled( bool );
virtual QString name() const;
virtual void setChannel( int );
};
/*======================================================================================
* OWlanNGMonitoringInterface
*======================================================================================*/
class OWlanNGMonitoringInterface : public OMonitoringInterface
{
public:
OWlanNGMonitoringInterface( ONetworkInterface* );
virtual ~OWlanNGMonitoringInterface();