initial commit

This commit is contained in:
mikhail "synzr" 2025-12-25 01:37:49 +05:00
commit 9d20827c46
2469 changed files with 470994 additions and 0 deletions

View file

@ -0,0 +1,589 @@
/*
* Copyright (C) 2006 Justin Karneges
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <stdio.h>
#include "processquit.h"
#include "netinterface.h"
#include "netnames.h"
using namespace XMPP;
class NetMonitor : public QObject
{
Q_OBJECT
public:
NetInterfaceManager *man;
QList<NetInterface*> ifaces;
~NetMonitor()
{
qDeleteAll(ifaces);
delete man;
}
signals:
void quit();
public slots:
void start()
{
connect(ProcessQuit::instance(), SIGNAL(quit()), SIGNAL(quit()));
man = new NetInterfaceManager;
connect(man, SIGNAL(interfaceAvailable(const QString &)),
SLOT(here(const QString &)));
QStringList list = man->interfaces();
for(int n = 0; n < list.count(); ++n)
here(list[n]);
}
void here(const QString &id)
{
NetInterface *iface = new NetInterface(id, man);
connect(iface, SIGNAL(unavailable()), SLOT(gone()));
printf("HERE: %s name=[%s]\n", qPrintable(iface->id()), qPrintable(iface->name()));
QList<QHostAddress> addrs = iface->addresses();
for(int n = 0; n < addrs.count(); ++n)
printf(" address: %s\n", qPrintable(addrs[n].toString()));
if(!iface->gateway().isNull())
printf(" gateway: %s\n", qPrintable(iface->gateway().toString()));
ifaces += iface;
}
void gone()
{
NetInterface *iface = (NetInterface *)sender();
printf("GONE: %s\n", qPrintable(iface->id()));
ifaces.removeAll(iface);
delete iface;
}
};
static QString dataToString(const QByteArray &buf)
{
QString out;
for(int n = 0; n < buf.size(); ++n)
{
unsigned char c = (unsigned char)buf[n];
if(c == '\\')
out += "\\\\";
else if(c >= 0x20 || c < 0x7f)
out += c;
else
out += QString("\\x%1").arg((uint)c, 2, 16);
}
return out;
}
static void print_record(const NameRecord &r)
{
switch(r.type())
{
case NameRecord::A:
printf("A: [%s] (ttl=%d)\n", qPrintable(r.address().toString()), r.ttl());
break;
case NameRecord::Aaaa:
printf("AAAA: [%s] (ttl=%d)\n", qPrintable(r.address().toString()), r.ttl());
break;
case NameRecord::Mx:
printf("MX: [%s] priority=%d (ttl=%d)\n", r.name().data(), r.priority(), r.ttl());
break;
case NameRecord::Srv:
printf("SRV: [%s] port=%d priority=%d weight=%d (ttl=%d)\n", r.name().data(), r.port(), r.priority(), r.weight(), r.ttl());
break;
case NameRecord::Ptr:
printf("PTR: [%s] (ttl=%d)\n", r.name().data(), r.ttl());
break;
case NameRecord::Txt:
{
QList<QByteArray> texts = r.texts();
printf("TXT: count=%d (ttl=%d)\n", texts.count(), r.ttl());
for(int n = 0; n < texts.count(); ++n)
printf(" len=%d [%s]\n", texts[n].size(), qPrintable(dataToString(texts[n])));
break;
}
case NameRecord::Hinfo:
printf("HINFO: [%s] [%s] (ttl=%d)\n", r.cpu().data(), r.os().data(), r.ttl());
break;
case NameRecord::Null:
printf("NULL: %d bytes (ttl=%d)\n", r.rawData().size(), r.ttl());
break;
default:
printf("(Unknown): type=%d (ttl=%d)\n", r.type(), r.ttl());
break;
}
}
static int str2rtype(const QString &in)
{
QString str = in.toLower();
if(str == "a")
return NameRecord::A;
else if(str == "aaaa")
return NameRecord::Aaaa;
else if(str == "ptr")
return NameRecord::Ptr;
else if(str == "srv")
return NameRecord::Srv;
else if(str == "mx")
return NameRecord::Mx;
else if(str == "txt")
return NameRecord::Txt;
else if(str == "hinfo")
return NameRecord::Hinfo;
else if(str == "null")
return NameRecord::Null;
else
return -1;
}
class ResolveName : public QObject
{
Q_OBJECT
public:
QString name;
NameRecord::Type type;
bool longlived;
NameResolver dns;
bool null_dump;
ResolveName()
{
null_dump = false;
}
public slots:
void start()
{
connect(ProcessQuit::instance(), SIGNAL(quit()), SIGNAL(quit()));
connect(&dns, SIGNAL(resultsReady(const QList<XMPP::NameRecord> &)),
SLOT(dns_resultsReady(const QList<XMPP::NameRecord> &)));
connect(&dns, SIGNAL(error(XMPP::NameResolver::Error)),
SLOT(dns_error(XMPP::NameResolver::Error)));
dns.start(name.toLatin1(), type, longlived ? NameResolver::LongLived : NameResolver::Single);
}
signals:
void quit();
private slots:
void dns_resultsReady(const QList<XMPP::NameRecord> &list)
{
if(null_dump && list[0].type() == NameRecord::Null)
{
QByteArray buf = list[0].rawData();
fwrite(buf.data(), buf.size(), 1, stdout);
}
else
{
for(int n = 0; n < list.count(); ++n)
print_record(list[n]);
}
if(!longlived)
{
dns.stop();
emit quit();
}
}
void dns_error(XMPP::NameResolver::Error e)
{
QString str;
if(e == NameResolver::ErrorNoName)
str = "ErrorNoName";
else if(e == NameResolver::ErrorTimeout)
str = "ErrorTimeout";
else if(e == NameResolver::ErrorNoLocal)
str = "ErrorNoLocal";
else if(e == NameResolver::ErrorNoLongLived)
str = "ErrorNoLongLived";
else // ErrorGeneric, or anything else
str = "ErrorGeneric";
printf("Error: %s\n", qPrintable(str));
emit quit();
}
};
class BrowseServices : public QObject
{
Q_OBJECT
public:
QString type, domain;
ServiceBrowser browser;
public slots:
void start()
{
connect(ProcessQuit::instance(), SIGNAL(quit()), SIGNAL(quit()));
connect(&browser, SIGNAL(instanceAvailable(const XMPP::ServiceInstance &)),
SLOT(browser_instanceAvailable(const XMPP::ServiceInstance &)));
connect(&browser, SIGNAL(instanceUnavailable(const XMPP::ServiceInstance &)),
SLOT(browser_instanceUnavailable(const XMPP::ServiceInstance &)));
connect(&browser, SIGNAL(error()), SLOT(browser_error()));
browser.start(type, domain);
}
signals:
void quit();
private slots:
void browser_instanceAvailable(const XMPP::ServiceInstance &i)
{
printf("HERE: [%s] (%d attributes)\n", qPrintable(i.instance()), i.attributes().count());
QMap<QString,QByteArray> attribs = i.attributes();
QMapIterator<QString,QByteArray> it(attribs);
while(it.hasNext())
{
it.next();
printf(" [%s] = [%s]\n", qPrintable(it.key()), qPrintable(dataToString(it.value())));
}
}
void browser_instanceUnavailable(const XMPP::ServiceInstance &i)
{
printf("GONE: [%s]\n", qPrintable(i.instance()));
}
void browser_error()
{
}
};
class ResolveService : public QObject
{
Q_OBJECT
public:
int mode;
QString instance;
QString type;
QString domain;
int port;
ServiceResolver dns;
public slots:
void start()
{
connect(ProcessQuit::instance(), SIGNAL(quit()), SIGNAL(quit()));
connect(&dns, SIGNAL(resultsReady(const QHostAddress &, int)),
SLOT(dns_resultsReady(const QHostAddress &, int)));
connect(&dns, SIGNAL(finished()), SLOT(dns_finished()));
connect(&dns, SIGNAL(error()), SLOT(dns_error()));
if(mode == 0)
dns.startFromInstance(instance.toLatin1() + '.' + type.toLatin1() + ".local.");
else if(mode == 1)
dns.startFromDomain(domain, type);
else // 2
dns.startFromPlain(domain, port);
}
signals:
void quit();
private slots:
void dns_resultsReady(const QHostAddress &addr, int port)
{
printf("[%s] port=%d\n", qPrintable(addr.toString()), port);
dns.tryNext();
}
void dns_finished()
{
emit quit();
}
void dns_error()
{
}
};
class PublishService : public QObject
{
Q_OBJECT
public:
QString instance;
QString type;
int port;
QMap<QString,QByteArray> attribs;
QByteArray extra_null;
ServiceLocalPublisher pub;
public slots:
void start()
{
//NetInterfaceManager::instance();
connect(ProcessQuit::instance(), SIGNAL(quit()), SIGNAL(quit()));
connect(&pub, SIGNAL(published()), SLOT(pub_published()));
connect(&pub, SIGNAL(error(XMPP::ServiceLocalPublisher::Error)),
SLOT(pub_error(XMPP::ServiceLocalPublisher::Error)));
pub.publish(instance, type, port, attribs);
}
signals:
void quit();
private slots:
void pub_published()
{
printf("Published\n");
if(!extra_null.isEmpty())
{
NameRecord rec;
rec.setNull(extra_null);
pub.addRecord(rec);
}
}
void pub_error(XMPP::ServiceLocalPublisher::Error e)
{
printf("Error: [%d]\n", e);
emit quit();
}
};
#include "main.moc"
void usage()
{
printf("irisnet: simple testing utility\n");
printf("usage: irisnet [command]\n");
printf("\n");
printf(" netmon monitor network interfaces\n");
printf(" rname (-r) [domain] (record type) look up record (default = a)\n");
printf(" rnamel [domain] [record type] look up record (long-lived)\n");
printf(" browse [service type] browse for local services\n");
printf(" rservi [instance] [service type] look up browsed instance\n");
printf(" rservd [domain] [service type] look up normal SRV\n");
printf(" rservp [domain] [port] look up non-SRV\n");
printf(" pserv [inst] [type] [port] (attr) (-a [rec]) publish service instance\n");
printf("\n");
printf("record types: a aaaa ptr srv mx txt hinfo null\n");
printf("service types: _service._proto format (e.g. \"_xmpp-client._tcp\")\n");
printf("attributes: var0[=val0],...,varn[=valn]\n");
printf("rname -r: for null type, dump raw record data to stdout\n");
printf("pub -a: add extra record. format: null:filename.dat\n");
printf("\n");
}
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
if(argc < 2)
{
usage();
return 1;
}
QStringList args;
for(int n = 1; n < argc; ++n)
args += argv[n];
if(args[0] == "netmon")
{
NetMonitor a;
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
QTimer::singleShot(0, &a, SLOT(start()));
app.exec();
}
else if(args[0] == "rname" || args[0] == "rnamel")
{
bool null_dump = false;
for(int n = 1; n < args.count(); ++n)
{
if(args[n] == "-r")
{
null_dump = true;
args.removeAt(n);
--n;
}
}
if(args.count() < 2)
{
usage();
return 1;
}
if(args[0] == "rnamel" && args.count() < 3)
{
usage();
return 1;
}
int x = NameRecord::A;
if(args.count() >= 3)
{
x = str2rtype(args[2]);
if(x == -1)
{
usage();
return 1;
}
}
ResolveName a;
a.name = args[1];
a.type = (NameRecord::Type)x;
a.longlived = (args[0] == "rnamel") ? true : false;
if(args[0] == "rname" && null_dump)
a.null_dump = true;
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
QTimer::singleShot(0, &a, SLOT(start()));
app.exec();
}
else if(args[0] == "browse")
{
if(args.count() < 2)
{
usage();
return 1;
}
BrowseServices a;
a.type = args[1];
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
QTimer::singleShot(0, &a, SLOT(start()));
app.exec();
}
else if(args[0] == "rservi" || args[0] == "rservd" || args[0] == "rservp")
{
// they all take 2 params
if(args.count() < 3)
{
usage();
return 1;
}
ResolveService a;
if(args[0] == "rservi")
{
a.mode = 0;
a.instance = args[1];
a.type = args[2];
}
else if(args[0] == "rservd")
{
a.mode = 1;
a.domain = args[1];
a.type = args[2];
}
else // rservp
{
a.mode = 2;
a.domain = args[1];
a.port = args[2].toInt();
}
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
QTimer::singleShot(0, &a, SLOT(start()));
app.exec();
}
else if(args[0] == "pserv")
{
QStringList addrecs;
for(int n = 1; n < args.count(); ++n)
{
if(args[n] == "-a")
{
if(n + 1 < args.count())
{
addrecs += args[n + 1];
args.removeAt(n);
args.removeAt(n);
--n;
}
else
{
usage();
return 1;
}
}
}
QByteArray extra_null;
for(int n = 0; n < addrecs.count(); ++n)
{
const QString &str = addrecs[n];
int x = str.indexOf(':');
if(x == -1 || str.mid(0, x) != "null")
{
usage();
return 1;
}
QString null_file = str.mid(x + 1);
if(!null_file.isEmpty())
{
QFile f(null_file);
if(!f.open(QFile::ReadOnly))
{
printf("can't read file\n");
return 1;
}
extra_null = f.readAll();
}
}
if(args.count() < 4)
{
usage();
return 1;
}
QMap<QString,QByteArray> attribs;
if(args.count() > 4)
{
QStringList parts = args[4].split(',');
for(int n = 0; n < parts.count(); ++n)
{
const QString &str = parts[n];
int x = str.indexOf('=');
if(x != -1)
attribs.insert(str.mid(0, x), str.mid(x + 1).toUtf8());
else
attribs.insert(str, QByteArray());
}
}
PublishService a;
a.instance = args[1];
a.type = args[2];
a.port = args[3].toInt();
a.attribs = attribs;
a.extra_null = extra_null;
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
QTimer::singleShot(0, &a, SLOT(start()));
app.exec();
}
else
{
usage();
return 1;
}
return 0;
}