-rw-r--r-- | libopie2/opienet/onetutils.cpp | 7 | ||||
-rw-r--r-- | libopie2/opienet/onetutils.h | 1 | ||||
-rw-r--r-- | libopie2/opienet/opcap.cpp | 27 | ||||
-rw-r--r-- | libopie2/opienet/opcap.h | 5 | ||||
-rw-r--r-- | noncore/net/wellenreiter/gui/scanlist.cpp | 48 | ||||
-rw-r--r-- | noncore/net/wellenreiter/gui/scanlist.h | 1 | ||||
-rw-r--r-- | noncore/net/wellenreiter/gui/wellenreiter.cpp | 64 | ||||
-rw-r--r-- | noncore/net/wellenreiter/gui/wellenreiter.h | 7 | ||||
-rwxr-xr-x | pics/wellenreiter/service.png | bin | 0 -> 863 bytes |
9 files changed, 148 insertions, 12 deletions
diff --git a/libopie2/opienet/onetutils.cpp b/libopie2/opienet/onetutils.cpp index 08c40b4..ad0e89d 100644 --- a/libopie2/opienet/onetutils.cpp +++ b/libopie2/opienet/onetutils.cpp @@ -37,50 +37,55 @@ #include <cstdio> using namespace std; #define IW_PRIV_TYPE_MASK 0x7000 #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 #define IW_PRIV_TYPE_CHAR 0x2000 #define IW_PRIV_TYPE_INT 0x4000 #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_TYPE_ADDR 0x6000 #define IW_PRIV_SIZE_FIXED 0x0800 #define IW_PRIV_SIZE_MASK 0x07FF /*====================================================================================== * OMacAddress *======================================================================================*/ // static initializer for broadcast and unknown MAC Adresses const unsigned char __broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; const OMacAddress& OMacAddress::broadcast = OMacAddress( __broadcast ); const unsigned char __unknown[6] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }; const OMacAddress& OMacAddress::unknown = OMacAddress( __unknown ); +//TODO: Incorporate Ethernet Manufacturer database here! (inline or so) + +OMacAddress::OMacAddress() +{ + memcpy( _bytes, __unknown, 6 ); +} -//TODO: Incorporate Ethernet Manufacturer database here! OMacAddress::OMacAddress( unsigned char* p ) { memcpy( _bytes, p, 6 ); } OMacAddress::OMacAddress( const unsigned char* p ) { memcpy( _bytes, p, 6 ); } OMacAddress::OMacAddress( struct ifreq& ifr ) { memcpy( _bytes, ifr.ifr_hwaddr.sa_data, 6 ); } OMacAddress::~OMacAddress() { } diff --git a/libopie2/opienet/onetutils.h b/libopie2/opienet/onetutils.h index 9611518..18731ba 100644 --- a/libopie2/opienet/onetutils.h +++ b/libopie2/opienet/onetutils.h @@ -30,48 +30,49 @@ */ #ifndef ONETUTILS_H #define ONETUTILS_H #include <qdict.h> #include <qmap.h> #include <qstring.h> #include <qhostaddress.h> #include <qobject.h> #include <sys/types.h> struct ifreq; class OWirelessNetworkInterface; /*====================================================================================== * OMacAddress *======================================================================================*/ class OMacAddress { public: // QString c'tor? -zecke + OMacAddress(); OMacAddress( unsigned char* ); OMacAddress( const unsigned char* ); OMacAddress( struct ifreq& ); ~OMacAddress(); QString manufacturer() const; QString toString( bool substitute = false ) const; const unsigned char* native() const; // no c'tor but this one why not make it a c'tor. it could also replace the others or is this the problem? static OMacAddress fromString( const QString& ); public: static const OMacAddress& broadcast; // ff:ff:ff:ff:ff:ff static const OMacAddress& unknown; // 44:44:44:44:44:44 private: unsigned char _bytes[6]; friend bool operator==( const OMacAddress &m1, const OMacAddress &m2 ); }; bool operator==( const OMacAddress &m1, const OMacAddress &m2 ); diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 7a6f61b..313f5bb 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -87,48 +87,71 @@ timevalstruct OPacket::timeval() const { return _hdr.ts; } int OPacket::caplen() const { return _hdr.caplen; } void OPacket::updateStats( QMap<QString,int>& stats, QObjectList* l ) { if (!l) return; QObject* o = l->first(); while ( o ) { stats[o->name()]++; updateStats( stats, const_cast<QObjectList*>( o->children() ) ); o = l->next(); } } +void OPacket::dumpStructure( QObjectList* l ) +{ + QString packetString( "[ |" + _dumpStructure( l ) + " ]" ); + qDebug( "OPacket::dumpStructure: %s", (const char*) packetString ); +} + + +QString OPacket::_dumpStructure( QObjectList* l ) +{ + if (!l) return QString::null; + QObject* o = l->first(); + QString str(" "); + + while ( o ) + { + str.append( o->name() ); + str.append( " |" ); + str += _dumpStructure( const_cast<QObjectList*>( o->children() ) ); + o = l->next(); + } + return str; +} + QString OPacket::dump( int bpl ) const { static int index = 0; index++; int len = _hdr.caplen; QString str; str.sprintf( "\n<----- Packet #%04d Len = 0x%X (%d) ----->\n\n", index, len, len ); str.append( "0000: " ); QString tmp; QString bytes; QString chars; for ( int i = 0; i < len; ++i ) { tmp.sprintf( "%02X ", _data[i] ); bytes.append( tmp ); if ( (_data[i] > 31) && (_data[i]<128) ) chars.append( _data[i] ); else chars.append( '.' ); if ( !((i+1) % bpl) ) { str.append( bytes ); str.append( ' ' ); str.append( chars ); str.append( '\n' ); @@ -1095,49 +1118,51 @@ int OPacketCapturer::fileno() const return pcap_fileno( _pch ); } else { return -1; } } OPacket* OPacketCapturer::next() { packetheaderstruct header; qDebug( "==> OPacketCapturer::next()" ); const unsigned char* pdata = pcap_next( _pch, &header ); qDebug( "<== OPacketCapturer::next()" ); if ( pdata && header.len ) { OPacket* p = new OPacket( dataLink(), header, pdata, 0 ); // packets shouldn't be inserted in the QObject child-parent hierarchy, // because due to memory constraints they will be deleted as soon // as possible - that is right after they have been processed // by emit() [ see below ] //TODO: make gathering statistics optional, because it takes time p->updateStats( _stats, const_cast<QObjectList*>( p->children() ) ); - + #ifndef NODEBUG + p->dumpStructure( const_cast<QObjectList*>( p->children() ) ); + #endif return p; } else { qWarning( "OPacketCapturer::next() - no packet received!" ); return 0; } } bool OPacketCapturer::open( const QString& name ) { if ( _open ) { if ( name == _name ) // ignore opening an already openend device { return true; } else // close the last opened device { close(); } } diff --git a/libopie2/opienet/opcap.h b/libopie2/opienet/opcap.h index a031dd1..f0d1d81 100644 --- a/libopie2/opienet/opcap.h +++ b/libopie2/opienet/opcap.h @@ -112,48 +112,53 @@ class QSocketNotifier; * OIPPacket* ip = (OIPPacket*) p->child( "IP" ); // returns 0, if no such child exists * odebug << "got ip packet from " << ip->fromIPAddress().toString() << " to " << ip->toIPAddress().toString() << oendl; * */ class OPacket : public QObject { Q_OBJECT friend class OPacketCapturer; public: OPacket( int datalink, packetheaderstruct, const unsigned char*, QObject* parent ); virtual ~OPacket(); timevalstruct timeval() const; int caplen() const; int len() const; QString dump( int = 32 ) const; void updateStats( QMap<QString,int>&, QObjectList* ); private: + + void dumpStructure( QObjectList* ); + QString _dumpStructure( QObjectList* ); + + private: const packetheaderstruct _hdr; // pcap packet header const unsigned char* _data; // pcap packet data const unsigned char* _end; // end of pcap packet data }; /*====================================================================================== * OEthernetPacket - DLT_EN10MB frame *======================================================================================*/ class OEthernetPacket : public QObject { Q_OBJECT public: OEthernetPacket( const unsigned char*, const struct ether_header*, QObject* parent = 0 ); virtual ~OEthernetPacket(); OMacAddress sourceAddress() const; OMacAddress destinationAddress() const; int type() const; private: const struct ether_header* _ether; }; diff --git a/noncore/net/wellenreiter/gui/scanlist.cpp b/noncore/net/wellenreiter/gui/scanlist.cpp index 245290d..9d6ed6a 100644 --- a/noncore/net/wellenreiter/gui/scanlist.cpp +++ b/noncore/net/wellenreiter/gui/scanlist.cpp @@ -318,48 +318,96 @@ void MScanListView::IBSStraffic( const OMacAddress& from, const OMacAddress& to, qWarning( "D'oh! Not yet implemented..." ); MLogWindow::logwindow()->log( "WARNING: Unhandled IBSS traffic!" ); } void MScanListView::identify( const OMacAddress& macaddr, const QString& ip ) { qDebug( "identify %s = %s", (const char*) macaddr.toString(), (const char*) ip ); QListViewItemIterator it( this ); for ( ; it.current(); ++it ) { if ( it.current()->text( col_ap ) == macaddr.toString(true) ) { it.current()->setText( col_ip, ip ); return; } } qDebug( "D'oh! Received identification, but item not yet in list... ==> Handle this!" ); MLogWindow::logwindow()->log( QString().sprintf( "WARNING: Unhandled identification %s = %s!", (const char*) macaddr.toString(), (const char*) ip ) ); } +void MScanListView::addService( const QString& name, const OMacAddress& macaddr, const QString& ip ) +{ + qDebug( "addService '%s', Server = %s = %s", (const char*) name, (const char*) macaddr.toString(), (const char*) ip ); + + //TODO: Refactor that out, we need it all over the place. + // Best to do it in a more comfortable abstraction in OListView + // (Hmm, didn't I already start something in this direction?) + + QListViewItemIterator it( this ); + for ( ; it.current(); ++it ) + { + if ( it.current()->text( col_ap ) == macaddr.toString(true) ) + { + + MScanListItem* subitem = static_cast<MScanListItem*>( it.current()->firstChild() ); + + while ( subitem && ( subitem->text( col_essid ) != name ) ) + { + #ifdef DEBUG + qDebug( "subitemtext: %s", (const char*) subitem->text( col_essid ) ); + #endif + subitem = static_cast<MScanListItem*> ( subitem->nextSibling() ); + } + + if ( subitem ) + { + // we have already seen this item, it's a dupe + #ifdef DEBUG + qDebug( "%s is a dupe - ignoring...", (const char*) name ); + #endif + subitem->receivedBeacon(); //FIXME: sent data bit + return; + } + + // never seen that - add new item + + MScanListItem* item = new MScanListItem( it.current(), "service", "N/A", false, -1, -1 ); + item->setText( col_essid, name ); + + return; + } + } + qDebug( "D'oh! Received identification, but item not yet in list... ==> Handle this!" ); + MLogWindow::logwindow()->log( QString().sprintf( "WARNING: Unhandled service addition %s = %s!", + (const char*) macaddr.toString(), (const char*) ip ) ); +} + + void MScanListView::contextMenuRequested( QListViewItem* item, const QPoint&, int col ) { if ( !item ) return; MScanListItem* itm = static_cast<MScanListItem*>( item ); qDebug( "contextMenuRequested on item '%s' (%s) in column: '%d'", (const char*) itm->text(0), (const char*) itm->type, col ); if ( itm->type == "adhoc" || itm->type == "managed" ) { QString entry = QString().sprintf( "&Join %s Net '%s'...", (const char*) itm->type, (const char*) itm->essid() ); QPopupMenu m( this ); m.insertItem( entry, 37773, 0 ); int result = m.exec( QCursor::pos() ); if ( result == 37773 ) emit joinNetwork( itm->type, itm->essid(), itm->channel(), itm->macaddr() ); } } //============================================================ // MScanListItem //============================================================ diff --git a/noncore/net/wellenreiter/gui/scanlist.h b/noncore/net/wellenreiter/gui/scanlist.h index 2703b6a..a9b74f1 100644 --- a/noncore/net/wellenreiter/gui/scanlist.h +++ b/noncore/net/wellenreiter/gui/scanlist.h @@ -21,48 +21,49 @@ /* OPIE */ #include <opie2/olistview.h> #include <opie2/onetutils.h> /* QT */ #include <qtextstream.h> class QString; class MScanListItem; class MScanListView: public OListView { Q_OBJECT public: MScanListView( QWidget* parent = 0, const char* name = 0 ); virtual ~MScanListView(); virtual OListViewItem* childFactory(); virtual void serializeTo( QDataStream& s ) const; virtual void serializeFrom( QDataStream& s ); public slots: void addNewItem( const QString& type, const QString& essid, const OMacAddress& macaddr, bool wep, int channel, int signal, const GpsLocation& location ); + void addService( const QString& name, const OMacAddress& macaddr, const QString& ip ); void fromDStraffic( const OMacAddress& from, const OMacAddress& to, const OMacAddress& via ); void toDStraffic( const OMacAddress& from, const OMacAddress& to, const OMacAddress& via ); void WDStraffic( const OMacAddress& from, const OMacAddress& to, const OMacAddress& viaFrom, const OMacAddress& viaTo ); void IBSStraffic( const OMacAddress& from, const OMacAddress& to, const OMacAddress& via ); void identify( const OMacAddress&, const QString& ipaddr ); void contextMenuRequested( QListViewItem* item, const QPoint&, int ); signals: void rightButtonClicked(QListViewItem*,const QPoint&,int); void joinNetwork( const QString&, const QString&, int, const QString& ); protected: void addIfNotExisting( MScanListItem* parent, const OMacAddress& addr, const QString& type = "station" ); }; //****************************** MScanListItem **************************************************************** class MScanListItem: public OListViewItem { public: diff --git a/noncore/net/wellenreiter/gui/wellenreiter.cpp b/noncore/net/wellenreiter/gui/wellenreiter.cpp index 405eda8..7394742 100644 --- a/noncore/net/wellenreiter/gui/wellenreiter.cpp +++ b/noncore/net/wellenreiter/gui/wellenreiter.cpp @@ -173,87 +173,116 @@ void Wellenreiter::handleBeacon( OPacket* p, OWaveLanManagementPacket* beacon ) GpsLocation loc( 0, 0 ); if ( configwindow->enableGPS->isChecked() ) { // TODO: add check if GPS is working!? qDebug( "Wellenreiter::gathering GPS data..." ); loc = gps->position(); qDebug( "Wellenreiter::GPS data received is ( %f , %f )", loc.latitude, loc.longitude ); } netView()->addNewItem( type, essid, header->macAddress2(), beacon->canPrivacy(), channel, 0, loc ); // update graph window if ( ds ) { OPrismHeaderPacket* prism = static_cast<OPrismHeaderPacket*>( p->child( "Prism" ) ); if ( prism ) graphwindow->traffic( ds->channel(), prism->signalStrength() ); else graphwindow->traffic( ds->channel(), 95 ); } } -void Wellenreiter::handleData( OPacket* p, OWaveLanDataPacket* data ) +void Wellenreiter::handleWlanData( OPacket* p, OWaveLanDataPacket* data, OMacAddress& from, OMacAddress& to ) { OWaveLanPacket* wlan = (OWaveLanPacket*) p->child( "802.11" ); if ( wlan->fromDS() && !wlan->toDS() ) { netView()->fromDStraffic( wlan->macAddress3(), wlan->macAddress1(), wlan->macAddress2() ); + from = wlan->macAddress3(); + to = wlan->macAddress2(); } else if ( !wlan->fromDS() && wlan->toDS() ) { netView()->toDStraffic( wlan->macAddress2(), wlan->macAddress3(), wlan->macAddress1() ); + from = wlan->macAddress2(); + to = wlan->macAddress3(); } else if ( wlan->fromDS() && wlan->toDS() ) { netView()->WDStraffic( wlan->macAddress4(), wlan->macAddress3(), wlan->macAddress1(), wlan->macAddress2() ); + from = wlan->macAddress4(); + to = wlan->macAddress3(); } else { netView()->IBSStraffic( wlan->macAddress2(), wlan->macAddress1(), wlan->macAddress3() ); + from = wlan->macAddress2(); + to = wlan->macAddress1(); } +} + + +void Wellenreiter::handleEthernetData( OPacket* p, OEthernetPacket* data, OMacAddress& from, OMacAddress& to ) +{ + from = data->sourceAddress(); + to = data->destinationAddress(); + + netView()->addNewItem( "station", "<wired>", from, false, -1, 0, GpsLocation( 0, 0 ) ); +} + +void Wellenreiter::handleIPData( OPacket* p, OIPPacket* ip, OMacAddress& source, OMacAddress& dest ) +{ OARPPacket* arp = (OARPPacket*) p->child( "ARP" ); if ( arp ) { qDebug( "Received ARP traffic (type '%s'): ", (const char*) arp->type() ); if ( arp->type() == "REQUEST" ) { netView()->identify( arp->senderMacAddress(), arp->senderIPV4Address().toString() ); } else if ( arp->type() == "REPLY" ) { netView()->identify( arp->senderMacAddress(), arp->senderIPV4Address().toString() ); netView()->identify( arp->targetMacAddress(), arp->targetIPV4Address().toString() ); } } - OIPPacket* ip = (OIPPacket*) p->child( "IP" ); - if ( ip ) + ODHCPPacket* dhcp = (ODHCPPacket*) p->child( "DHCP" ); + if ( dhcp ) + { + qDebug( "Received DHCP '%s' packet", (const char*) dhcp->type() ); + if ( dhcp->type() == "OFFER" ) { - qDebug( "Received IP packet." ); + qDebug( "ADDSERVICE: '%s' ('%s') seems to be a DHCP server.", (const char*) source.toString(), (const char*) dhcp->serverAddress().toString() ); + //netView()->addNewItem( "station", "<wired>", from, false, -1, 0, GpsLocation( 0, 0 ) ); + + netView()->identify( source, dhcp->serverAddress().toString() ); + netView()->addService( "DHCP", source, dhcp->serverAddress().toString() ); + } } } QObject* Wellenreiter::childIfToParse( OPacket* p, const QString& protocol ) { if ( configwindow->parsePackets->isProtocolChecked( protocol ) ) if ( configwindow->parsePackets->protocolAction( protocol ) == "Discard!" ) return 0; return p->child( protocol ); } bool Wellenreiter::checkDumpPacket( OPacket* p ) { // go through all child packets and see if one is inside the child hierarchy for p // if so, do what the user requested (protocolAction), e.g. pass or discard if ( !configwindow->writeCaptureFile->isChecked() ) return false; QObjectList* l = p->queryList(); QObjectListIt it( *l ); QObject* o; @@ -277,58 +306,75 @@ bool Wellenreiter::checkDumpPacket( OPacket* p ) } ++it; } return true; } void Wellenreiter::receivePacket( OPacket* p ) { hexWindow()->log( p->dump( 8 ) ); if ( checkDumpPacket( p ) ) { pcap->dump( p ); } // check if we received a beacon frame OWaveLanManagementPacket* beacon = static_cast<OWaveLanManagementPacket*>( childIfToParse( p, "802.11 Management" ) ); if ( beacon && beacon->managementType() == "Beacon" ) { handleBeacon( p, beacon ); return; } + OMacAddress source; + OMacAddress dest; + //TODO: WEP check here - // check for a data frame - OWaveLanDataPacket* data = static_cast<OWaveLanDataPacket*>( childIfToParse( p, "802.11 Data" ) ); - if ( data ) + // check for a wireless data frame + OWaveLanDataPacket* wlan = static_cast<OWaveLanDataPacket*>( childIfToParse( p, "802.11 Data" ) ); + if ( wlan ) + { + handleWlanData( p, wlan, source, dest ); + } + + // check for a wired data frame + OEthernetPacket* eth = static_cast<OEthernetPacket*>( childIfToParse( p, "Ethernet" ) ); + if ( eth ) + { + handleEthernetData( p, eth, source, dest ); + } + + // check for a ip frame + OIPPacket* ip = static_cast<OIPPacket*>( childIfToParse( p, "IP" ) ); + if ( ip ) { - handleData( p, data ); + handleIPData( p, ip, source, dest ); } - handleNotification( p ); + //handleNotification( p ); } void Wellenreiter::stopClicked() { if ( iface ) { disconnect( SIGNAL( receivedPacket(OPacket*) ), this, SLOT( receivePacket(OPacket*) ) ); disconnect( SIGNAL( hopped(int) ), this, SLOT( channelHopped(int) ) ); iface->setChannelHopping(); // stop hopping channels } else killTimers(); pcap->close(); sniffing = false; if ( iface ) { // switch off monitor mode iface->setMonitorMode( false ); // switch off promisc flag iface->setPromiscuousMode( false ); diff --git a/noncore/net/wellenreiter/gui/wellenreiter.h b/noncore/net/wellenreiter/gui/wellenreiter.h index 43f6f99..ed96375 100644 --- a/noncore/net/wellenreiter/gui/wellenreiter.h +++ b/noncore/net/wellenreiter/gui/wellenreiter.h @@ -7,87 +7,92 @@ ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** **********************************************************************/ #ifndef WELLENREITER_H #define WELLENREITER_H #include "wellenreiterbase.h" #ifdef QWS #include <opie/odevice.h> using namespace Opie; #endif class QTimerEvent; class QPixmap; class OPacket; class OWaveLanManagementPacket; class OWaveLanDataPacket; +class OEthernetPacket; +class OMacAddress; +class OIPPacket; class OPacketCapturer; class OWirelessNetworkInterface; class WellenreiterConfigWindow; class MLogWindow; class MHexWindow; class GPS; class Wellenreiter : public WellenreiterBase { Q_OBJECT public: Wellenreiter( QWidget* parent = 0 ); ~Wellenreiter(); void setConfigWindow( WellenreiterConfigWindow* cw ); MScanListView* netView() const { return netview; }; MLogWindow* logWindow() const { return logwindow; }; MHexWindow* hexWindow() const { return hexwindow; }; bool isDaemonRunning() const { return sniffing; }; public: bool sniffing; protected: virtual void timerEvent( QTimerEvent* ); public slots: void channelHopped(int); void receivePacket(OPacket*); void startClicked(); void stopClicked(); void joinNetwork(const QString&,const QString&,int,const QString&); signals: void startedSniffing(); void stoppedSniffing(); private: void handleBeacon( OPacket* p, OWaveLanManagementPacket* beacon ); - void handleData( OPacket* p, OWaveLanDataPacket* data ); + void handleWlanData( OPacket* p, OWaveLanDataPacket* data, OMacAddress& from, OMacAddress& to ); + void handleEthernetData( OPacket* p, OEthernetPacket* data, OMacAddress& from, OMacAddress& to ); + void handleIPData( OPacket* p, OIPPacket* ip, OMacAddress& from, OMacAddress& to ); void handleNotification( OPacket* p ); void doAction( const QString& action, const QString& protocol, OPacket* p ); QObject* childIfToParse( OPacket* p, const QString& protocol ); bool checkDumpPacket( OPacket* p ); private: #ifdef QWS OSystem _system; // Opie Operating System identifier #endif OWirelessNetworkInterface* iface; OPacketCapturer* pcap; WellenreiterConfigWindow* configwindow; GPS* gps; //void readConfig(); //void writeConfig(); }; #endif diff --git a/pics/wellenreiter/service.png b/pics/wellenreiter/service.png Binary files differnew file mode 100755 index 0000000..4e06a0a --- a/dev/null +++ b/pics/wellenreiter/service.png |