1/****************************************************************************
2**
3** Copyright (C) 2016 Jeremy Lainé <jeremy.laine@m4x.org>
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "dnslookup.h"
52
53#include <QCoreApplication>
54#include <QDnsLookup>
55#include <QHostAddress>
56#include <QStringList>
57#include <QTimer>
58#include <QCommandLineParser>
59#include <QCommandLineOption>
60
61#include <stdio.h>
62
63static int typeFromParameter(const QString &type)
64{
65 if (type == "a")
66 return QDnsLookup::A;
67 if (type == "aaaa")
68 return QDnsLookup::AAAA;
69 if (type == "any")
70 return QDnsLookup::ANY;
71 if (type == "cname")
72 return QDnsLookup::CNAME;
73 if (type == "mx")
74 return QDnsLookup::MX;
75 if (type == "ns")
76 return QDnsLookup::NS;
77 if (type == "ptr")
78 return QDnsLookup::PTR;
79 if (type == "srv")
80 return QDnsLookup::SRV;
81 if (type == "txt")
82 return QDnsLookup::TXT;
83 return -1;
84}
85
86//! [0]
87
88enum CommandLineParseResult
89{
90 CommandLineOk,
91 CommandLineError,
92 CommandLineVersionRequested,
93 CommandLineHelpRequested
94};
95
96CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage)
97{
98 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
99 const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver");
100 parser.addOption(commandLineOption: nameServerOption);
101 const QCommandLineOption typeOption("t", "The lookup type.", "type");
102 parser.addOption(commandLineOption: typeOption);
103 parser.addPositionalArgument(name: "name", description: "The name to look up.");
104 const QCommandLineOption helpOption = parser.addHelpOption();
105 const QCommandLineOption versionOption = parser.addVersionOption();
106
107 if (!parser.parse(arguments: QCoreApplication::arguments())) {
108 *errorMessage = parser.errorText();
109 return CommandLineError;
110 }
111
112 if (parser.isSet(option: versionOption))
113 return CommandLineVersionRequested;
114
115 if (parser.isSet(option: helpOption))
116 return CommandLineHelpRequested;
117
118 if (parser.isSet(option: nameServerOption)) {
119 const QString nameserver = parser.value(option: nameServerOption);
120 query->nameServer = QHostAddress(nameserver);
121 if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
122 *errorMessage = "Bad nameserver address: " + nameserver;
123 return CommandLineError;
124 }
125 }
126
127 if (parser.isSet(option: typeOption)) {
128 const QString typeParameter = parser.value(option: typeOption);
129 const int type = typeFromParameter(type: typeParameter.toLower());
130 if (type < 0) {
131 *errorMessage = "Bad record type: " + typeParameter;
132 return CommandLineError;
133 }
134 query->type = static_cast<QDnsLookup::Type>(type);
135 }
136
137 const QStringList positionalArguments = parser.positionalArguments();
138 if (positionalArguments.isEmpty()) {
139 *errorMessage = "Argument 'name' missing.";
140 return CommandLineError;
141 }
142 if (positionalArguments.size() > 1) {
143 *errorMessage = "Several 'name' arguments specified.";
144 return CommandLineError;
145 }
146 query->name = positionalArguments.first();
147
148 return CommandLineOk;
149}
150
151//! [0]
152
153DnsManager::DnsManager()
154 : dns(new QDnsLookup(this))
155{
156 connect(sender: dns, signal: &QDnsLookup::finished, receiver: this, slot: &DnsManager::showResults);
157}
158
159void DnsManager::execute()
160{
161 // lookup type
162 dns->setType(query.type);
163 if (!query.nameServer.isNull())
164 dns->setNameserver(query.nameServer);
165 dns->setName(query.name);
166 dns->lookup();
167}
168
169void DnsManager::showResults()
170{
171 if (dns->error() != QDnsLookup::NoError)
172 printf(format: "Error: %i (%s)\n", dns->error(), qPrintable(dns->errorString()));
173
174 // CNAME records
175 const QList<QDnsDomainNameRecord> cnameRecords = dns->canonicalNameRecords();
176 for (const QDnsDomainNameRecord &record : cnameRecords)
177 printf(format: "%s\t%i\tIN\tCNAME\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
178
179 // A and AAAA records
180 const QList<QDnsHostAddressRecord> aRecords = dns->hostAddressRecords();
181 for (const QDnsHostAddressRecord &record : aRecords) {
182 const char *type = (record.value().protocol() == QAbstractSocket::IPv6Protocol) ? "AAAA" : "A";
183 printf(format: "%s\t%i\tIN\t%s\t%s\n", qPrintable(record.name()), record.timeToLive(), type, qPrintable(record.value().toString()));
184 }
185
186 // MX records
187 const QList<QDnsMailExchangeRecord> mxRecords = dns->mailExchangeRecords();
188 for (const QDnsMailExchangeRecord &record : mxRecords)
189 printf(format: "%s\t%i\tIN\tMX\t%u %s\n", qPrintable(record.name()), record.timeToLive(), record.preference(), qPrintable(record.exchange()));
190
191 // NS records
192 const QList<QDnsDomainNameRecord> nsRecords = dns->nameServerRecords();
193 for (const QDnsDomainNameRecord &record : nsRecords)
194 printf(format: "%s\t%i\tIN\tNS\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
195
196 // PTR records
197 const QList<QDnsDomainNameRecord> ptrRecords = dns->pointerRecords();
198 for (const QDnsDomainNameRecord &record : ptrRecords)
199 printf(format: "%s\t%i\tIN\tPTR\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
200
201 // SRV records
202 const QList<QDnsServiceRecord> srvRecords = dns->serviceRecords();
203 for (const QDnsServiceRecord &record : srvRecords)
204 printf(format: "%s\t%i\tIN\tSRV\t%u %u %u %s\n", qPrintable(record.name()), record.timeToLive(), record.priority(), record.weight(), record.port(), qPrintable(record.target()));
205
206 // TXT records
207 const QList<QDnsTextRecord> txtRecords = dns->textRecords();
208 for (const QDnsTextRecord &record : txtRecords) {
209 QStringList values;
210 const QList<QByteArray> dnsRecords = record.values();
211 for (const QByteArray &ba : dnsRecords)
212 values << "\"" + QString::fromLatin1(str: ba) + "\"";
213 printf(format: "%s\t%i\tIN\tTXT\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(values.join(' ')));
214 }
215
216 QCoreApplication::instance()->quit();
217}
218
219int main(int argc, char *argv[])
220{
221 QCoreApplication app(argc, argv);
222
223//! [1]
224 QCoreApplication::setApplicationVersion(QT_VERSION_STR);
225 QCoreApplication::setApplicationName(QCoreApplication::translate(context: "QDnsLookupExample", key: "DNS Lookup Example"));
226 QCommandLineParser parser;
227 parser.setApplicationDescription(QCoreApplication::translate(context: "QDnsLookupExample", key: "An example demonstrating the class QDnsLookup."));
228 DnsQuery query;
229 QString errorMessage;
230 switch (parseCommandLine(parser, query: &query, errorMessage: &errorMessage)) {
231 case CommandLineOk:
232 break;
233 case CommandLineError:
234 fputs(qPrintable(errorMessage), stderr);
235 fputs(s: "\n\n", stderr);
236 fputs(qPrintable(parser.helpText()), stderr);
237 return 1;
238 case CommandLineVersionRequested:
239 printf(format: "%s %s\n", qPrintable(QCoreApplication::applicationName()),
240 qPrintable(QCoreApplication::applicationVersion()));
241 return 0;
242 case CommandLineHelpRequested:
243 parser.showHelp();
244 Q_UNREACHABLE();
245 }
246//! [1]
247
248 DnsManager manager;
249 manager.setQuery(query);
250 QTimer::singleShot(msec: 0, receiver: &manager, SLOT(execute()));
251
252 return app.exec();
253}
254

source code of qtbase/examples/network/dnslookup/dnslookup.cpp