/*
* main.cxx
*
* PWLib application source file for DNSTest
*
* Main program entry point.
*
* Copyright 2003 Equivalence
*
* $Log: main.cxx,v $
* Revision 1.6 2004/12/08 00:54:29 csoutheren
* Added URL lookups
*
* Revision 1.5 2004/05/31 13:57:00 csoutheren
* Added tests for ENUM resolution
*
* Revision 1.4 2003/09/26 13:42:16 rjongbloed
* Added special test to give more indicative error if try to compile without DNS support.
*
* Revision 1.3 2003/04/22 23:25:13 craigs
* Changed help message for SRV records
*
* Revision 1.2 2003/04/15 08:15:16 craigs
* Added single string form of GetSRVRecords
*
* Revision 1.1 2003/04/15 04:12:38 craigs
* Initial version
*
*/
#include <ptlib.h>
#include <ptclib/pdns.h>
#include <ptclib/enum.h>
#include <ptclib/url.h>
#include "main.h"
#if !P_DNS
#error Must have DNS support for this application
#endif
PCREATE_PROCESS(DNSTest);
DNSTest::DNSTest()
: PProcess("Equivalence", "DNSTest", 1, 0, AlphaCode, 1)
{
}
void Usage()
{
PError << "usage: dnstest -t MX hostname\n"
" dnstest -t SRV service (i.e. _ras._udp._example.com)\n"
" dnstest -t NAPTR resource (i.e. 2.1.2.1.5.5.5.0.0.8.1.e164.org)\n"
" dnstest -t NAPTR resource service (i.e. 2.1.2.1.5.5.5.0.0.8.1.e164.org E2U+SIP)\n"
" dnstest -t ENUM service (i.e. +18005551212 E2U+SIP)\n"
" dnstest -u url (i.e. http://craigs@postincrement.com)\n"
;
}
template <class RecordListType>
void GetAndDisplayRecords(const PString & name)
{
RecordListType records;
if (!PDNS::GetRecords(name, records))
PError << "Lookup for " << name << " failed" << endl;
else
cout << "Lookup for " << name << " returned" << endl << records << endl;
}
struct LookupRecord {
PIPSocket::Address addr;
WORD port;
PString type;
PString source;
};
ostream & operator << (ostream & strm, const LookupRecord & rec)
{
strm << rec.type << " " << rec.addr << ":" << rec.port << " from " << rec.source;
return strm;
}
BOOL FindSRVRecords(std::vector<LookupRecord> & recs,
const PString & domain,
const PString & type,
const PString & srv)
{
PDNS::SRVRecordList srvRecords;
PString srvLookupStr = srv + domain;
BOOL found = PDNS::GetRecords(srvLookupStr, srvRecords);
if (found) {
PDNS::SRVRecord * recPtr = srvRecords.GetFirst();
while (recPtr != NULL) {
LookupRecord rec;
rec.addr = recPtr->hostAddress;
rec.port = recPtr->port;
rec.type = type;
rec.source = srv;
recs.push_back(rec);
recPtr = srvRecords.GetNext();
}
}
return found;
}
void DNSTest::Main()
{
PArgList & args = GetArguments();
args.Parse("t:u.");
if (args.GetCount() < 1) {
Usage();
return;
}
if (args.HasOption('u')) {
if (args.GetCount() < 0) {
Usage();
return;
}
PURL url(args[0]);
if (url.GetScheme() *= "h323") {
PString user = url.GetUserName();
PString domain = url.GetHostName();
WORD port = url.GetPort();
cout << "user = " << user << ", domain = " << domain << ", port = " << port << endl;
std::vector<LookupRecord> found;
BOOL hasGK = FindSRVRecords(found, domain, "LRQ", "_h323ls._udp.");
hasGK = hasGK || FindSRVRecords(found, domain, "LRQ", "_h323rs._udp.");
FindSRVRecords(found, domain, "Call direct", "_h323cs._tcp.");
// if no entries so far, see if the domain is actually a host
if (found.size() == 0) {
PIPSocket::Address addr;
if (PIPSocket::GetHostAddress(domain, addr)) {
LookupRecord rec;
rec.addr = addr;
rec.port = 1720;
rec.type = "Call direct";
rec.source = "DNS";
found.push_back(rec);
}
}
if (!hasGK) {
PDNS::MXRecordList mxRecords;
if (PDNS::GetRecords(domain, mxRecords)) {
PDNS::MXRecord * recPtr = mxRecords.GetFirst();
while (recPtr != NULL) {
LookupRecord rec;
rec.addr = recPtr->hostAddress;
rec.port = 1719;
rec.type = "LRQ";
rec.source = "MX";
found.push_back(rec);
recPtr = mxRecords.GetNext();
}
}
}
if (found.size() == 0) {
PError << "Cannot find match" << endl;
}
else
{
std::vector<LookupRecord>::const_iterator r;
cout << "Found\n";
for (r = found.begin(); r != found.end(); ++r) {
cout << *r << endl;
}
}
}
else {
PError << "error: unsupported scheme " << url.GetScheme() << endl;
}
}
else if (args.HasOption('t')) {
PString type = args.GetOptionString('t');
if (type *= "SRV")
GetAndDisplayRecords<PDNS::SRVRecordList>(args[0]);
else if (type *= "MX")
GetAndDisplayRecords<PDNS::MXRecordList>(args[0]);
else if (type *= "NAPTR") {
if (args.GetCount() == 1)
GetAndDisplayRecords<PDNS::NAPTRRecordList>(args[0]);
else {
PDNS::NAPTRRecordList records;
if (!PDNS::GetRecords(args[0], records))
PError << "Lookup for " << args[0] << " failed" << endl;
else {
cout << "Returned " << endl;
PDNS::NAPTRRecord * rec = records.GetFirst(args[1]);
while (rec != NULL) {
cout << *rec;
rec = records.GetNext(args[1]);
}
}
}
}
else if (type *= "enum") {
if (args.GetCount() < 2)
Usage();
else {
PString e164 = args[0];
PString service = args[1];
PString str;
if (!PDNS::ENUMLookup(e164, service, str))
cout << "Could not resolve E164 number " << e164 << " with service " << service << endl;
else
cout << "E164 number " << e164 << " with service " << service << " resolved to " << str << endl;
}
}
}
}
// End of File ///////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1