/****************************************************************************/ /* Project: odisLogger */ /* */ /* Copyright: Olaf Dreyer individuelle Systemsoftware (ODIS) */ /* */ /* All rights reserved. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* File: wrapperlibpcap.cpp */ /* */ /* Purpose: A wrapper to communicate via libpcap */ /* */ /* */ /****************************************************************************/ // https://www.tcpdump.org/pcap.html #include "settings.h" #include "library.h" #include "wrapperlibpcap.h" #include "pcap/pcap.h" extern "C" { void pcapCallback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); typedef int (*fp_pcap_findalldevs_t)(pcap_if_t **, char *); fp_pcap_findalldevs_t fp_pcap_findalldevs = 0; typedef void (*fp_pcap_freealldevs_t)(pcap_if_t *); fp_pcap_freealldevs_t fp_pcap_freealldevs = 0; typedef char *(*fp_pcap_lookupdev_t)(char *errbuf); fp_pcap_lookupdev_t fp_pcap_lookupdev = 0; typedef pcap_t * (*fp_pcap_open_live_t)(const char *, int, int, int, char *); fp_pcap_open_live_t fp_pcap_open_live = 0; typedef int (*fp_pcap_lookupnet_t)(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); fp_pcap_lookupnet_t fp_pcap_lookupnet = 0; typedef int (*fp_pcap_compile_t)(pcap_t *p, struct bpf_program *fp, const char *str, int optimize, bpf_u_int32 netmask); fp_pcap_compile_t fp_pcap_compile = 0; typedef int (*fp_pcap_setfilter_t)(pcap_t *p, struct bpf_program *fp); fp_pcap_setfilter_t fp_pcap_setfilter = 0; typedef int (*fp_pcap_loop_t)(pcap_t *p, int cnt, pcap_handler callback, u_char *user); fp_pcap_loop_t fp_pcap_loop = 0; typedef int (*fp_pcap_dispatch_t)(pcap_t *p, int cnt, pcap_handler callback, u_char *user); fp_pcap_dispatch_t fp_pcap_dispatch = 0; typedef void (*fp_pcap_breakloop_t)(pcap_t *); fp_pcap_breakloop_t fp_pcap_breakloop = 0; typedef void (*fp_pcap_close_t)(pcap_t *p); fp_pcap_close_t fp_pcap_close = 0; typedef int (*fp_pcap_sendpacket_t)(pcap_t *p, const u_char *buf, int size); fp_pcap_sendpacket_t fp_pcap_sendpacket = 0; typedef void (*fp_pcap_handler_t)(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); fp_pcap_handler_t fp_pcap_handler = pcapCallback; typedef int (*fp_pcap_inject_t)(pcap_t *p, const void *buf, size_t size); fp_pcap_inject_t fp_pcap_inject = 0; void pcapCallback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { // qDebug() << "pcapCallback: got a packet"; if(user) ((Pcap*)user)->readcallback(h, bytes); } } // extern "C" QStringList Pcap::m_lDevice; bool Pcap::loadPcapSymbols() { bool bRet = false; fp_pcap_findalldevs = (fp_pcap_findalldevs_t)g_libPcap.resolve("pcap_findalldevs"); fp_pcap_freealldevs = (fp_pcap_freealldevs_t)g_libPcap.resolve("pcap_freealldevs"); fp_pcap_lookupdev = (fp_pcap_lookupdev_t)g_libPcap.resolve("pcap_lookupdev"); fp_pcap_open_live = (fp_pcap_open_live_t)g_libPcap.resolve("pcap_open_live"); fp_pcap_lookupnet = (fp_pcap_lookupnet_t)g_libPcap.resolve("pcap_lookupnet"); fp_pcap_compile = (fp_pcap_compile_t)g_libPcap.resolve("pcap_compile"); fp_pcap_setfilter = (fp_pcap_setfilter_t)g_libPcap.resolve("pcap_setfilter"); fp_pcap_loop = (fp_pcap_loop_t)g_libPcap.resolve("pcap_loop"); fp_pcap_dispatch = (fp_pcap_dispatch_t)g_libPcap.resolve("pcap_dispatch"); fp_pcap_breakloop = (fp_pcap_breakloop_t)g_libPcap.resolve("pcap_breakloop"); fp_pcap_close = (fp_pcap_close_t)g_libPcap.resolve("pcap_close"); fp_pcap_sendpacket = (fp_pcap_sendpacket_t)g_libPcap.resolve("pcap_sendpacket"); fp_pcap_inject = (fp_pcap_inject_t)g_libPcap.resolve("pcap_inject"); if( fp_pcap_findalldevs && fp_pcap_freealldevs && fp_pcap_lookupdev && fp_pcap_open_live && fp_pcap_lookupnet && fp_pcap_compile && fp_pcap_setfilter && fp_pcap_loop && fp_pcap_dispatch && fp_pcap_breakloop && fp_pcap_close && fp_pcap_sendpacket && fp_pcap_inject ) bRet = true; return bRet; } Pcap::Pcap(QString strKey) : m_strKey(strKey) , m_bPcapOperational(false) , m_pHandle(0) { if(openPcap()) m_bPcapOperational = true; } Pcap::~Pcap() { closePcap(); } bool Pcap::openPcap() { // Init the pcap handles return true; } void Pcap::closePcap() { } bool Pcap::open(QString strDevice, QString strFilter, int timeout) { bool bRet = true; pcap_t *handle = 0; /* Session handle */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ bpf_u_int32 mask; /* Our netmask */ bpf_u_int32 net; /* Our IP */ struct bpf_program fp; /* The compiled filter expression */ /* Find the properties for the device */ if(bRet && (fp_pcap_lookupnet(strDevice.toLatin1().data(), &net, &mask, errbuf) == -1)) { qDebug() << "Pcap::open: pcap_lookupnet failed"; m_strErrorText = errbuf; bRet = false; } /* Open the session in promiscuous mode */ if(bRet) { handle = fp_pcap_open_live(strDevice.toLatin1().data(), BUFSIZ, 1, timeout, errbuf); if(!handle) { qDebug() << QString("Pcap::open: pcap_open_live failed:\n%1").arg(errbuf); m_strErrorText = errbuf; bRet = false; } } /* Compile the filter */ if(bRet && !strFilter.isEmpty() && (fp_pcap_compile(handle, &fp, strFilter.toLatin1().data(), 0, net) == -1)) { qDebug() << QString("Pcap::open: pcap_compile failed:\n%1").arg(errbuf); m_strErrorText = errbuf; bRet = false; } /* Apply the filter */ if(bRet && !strFilter.isEmpty() && (fp_pcap_setfilter(handle, &fp) == -1)) { qDebug() << "Pcap::open: pcap_setfilter failed"; m_strErrorText = errbuf; bRet = false; } if(bRet) m_pHandle = handle; return bRet; } void Pcap::close() { if(fp_pcap_breakloop && m_pHandle) fp_pcap_breakloop(m_pHandle); if(fp_pcap_close && m_pHandle) fp_pcap_close(m_pHandle); } QStringList Pcap::getDevices() { return m_lDevice; } bool Pcap::loadDevices() { bool bRet = false; if(libPcapIsValid()) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_if_t * lIf = 0; if(!fp_pcap_findalldevs(&lIf, errbuf)) { m_lDevice.clear(); while(lIf) { qDebug() << "Pcap::loadDevices: found:" << QString(lIf->name) << QString(lIf->description); m_lDevice << QString(lIf->name); if(lIf->next) lIf = lIf->next; else break; } } if(lIf) fp_pcap_freealldevs(lIf); bRet = true; } return bRet; } quint64 Pcap::read(int timeout, qint64 /*maxLength*/) { // qDebug() << "Pcap::read"; if(m_pHandle && fp_pcap_dispatch(m_pHandle, timeout, fp_pcap_handler, (u_char*)this) == -1) { qDebug() << "Pcap::read: error on pcap_dispatch"; } return 0; } quint64 Pcap::write(const char * buffer, qint64 length) { int actual_length = 0; if(m_pHandle) { actual_length = fp_pcap_inject(m_pHandle, buffer, length); if(actual_length < 0) { qDebug() << "Pcap::write: error on pcap_inject"; actual_length = 0; } } return actual_length; } void Pcap::readcallback(const struct pcap_pkthdr *h, const u_char *bytes) { if(h && bytes) { QByteArray a((const char *)bytes, h->len); Message msg("", "", QDateTime::currentDateTime(), a, ""); emit signalDataReceived(msg); } }