~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/src/jdns/main.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005  Justin Karneges
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the
 
6
 * "Software"), to deal in the Software without restriction, including
 
7
 * without limitation the rights to use, copy, modify, merge, publish,
 
8
 * distribute, sublicense, and/or sell copies of the Software, and to
 
9
 * permit persons to whom the Software is furnished to do so, subject to
 
10
 * the following conditions:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included
 
13
 * in all copies or substantial portions of the Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
19
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
20
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
21
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
#include <QtCore>
 
25
#include <QtNetwork>
 
26
#include "qjdns.h"
 
27
 
 
28
QString dataToString(const QByteArray &buf)
 
29
{
 
30
        QString out;
 
31
        for(int n = 0; n < buf.size(); ++n)
 
32
        {
 
33
                unsigned char c = (unsigned char)buf[n];
 
34
                if(c == '\\')
 
35
                        out += "\\\\";
 
36
                else if(c >= 0x20 && c < 0x7f)
 
37
                        out += c;
 
38
                else
 
39
                        out += QString().sprintf("\\x%02x", (unsigned int)c);
 
40
        }
 
41
        return out;
 
42
}
 
43
 
 
44
void print_record(const QJDns::Record &r)
 
45
{
 
46
        switch(r.type)
 
47
        {
 
48
                case QJDns::A:
 
49
                        printf("  A: [%s] (ttl=%d)\n", qPrintable(r.address.toString()), r.ttl);
 
50
                        break;
 
51
                case QJDns::Aaaa:
 
52
                        printf("  AAAA: [%s] (ttl=%d)\n", qPrintable(r.address.toString()), r.ttl);
 
53
                        break;
 
54
                case QJDns::Mx:
 
55
                        printf("  MX: [%s] priority=%d (ttl=%d)\n", r.name.data(), r.priority, r.ttl);
 
56
                        break;
 
57
                case QJDns::Srv:
 
58
                        printf("  SRV: [%s] port=%d priority=%d weight=%d (ttl=%d)\n", r.name.data(), r.port, r.priority, r.weight, r.ttl);
 
59
                        break;
 
60
                case QJDns::Cname:
 
61
                        printf("  CNAME: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
 
62
                        break;
 
63
                case QJDns::Ptr:
 
64
                        printf("  PTR: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
 
65
                        break;
 
66
                case QJDns::Txt:
 
67
                {
 
68
                        printf("  TXT: count=%d (ttl=%d)\n", r.texts.count(), r.ttl);
 
69
                        for(int n = 0; n < r.texts.count(); ++n)
 
70
                                printf("    len=%d [%s]\n", r.texts[n].size(), qPrintable(dataToString(r.texts[n])));
 
71
                        break;
 
72
                }
 
73
                case QJDns::Hinfo:
 
74
                        printf("  HINFO: [%s] [%s] (ttl=%d)\n", r.cpu.data(), r.os.data(), r.ttl);
 
75
                        break;
 
76
                case QJDns::Ns:
 
77
                        printf("  NS: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
 
78
                        break;
 
79
                default:
 
80
                        printf("  (Unknown): type=%d, size=%d (ttl=%d)\n", r.type, r.rdata.size(), r.ttl);
 
81
                        break;
 
82
        }
 
83
}
 
84
 
 
85
class App : public QObject
 
86
{
 
87
        Q_OBJECT
 
88
public:
 
89
        bool opt_debug, opt_ipv6, opt_quit;
 
90
        int quit_time;
 
91
        QString mode, type, name, ipaddr;
 
92
        QStringList nslist;
 
93
        QList<QJDns::Record> pubitems;
 
94
        QJDns jdns;
 
95
        int req_id;
 
96
 
 
97
        App()
 
98
        {
 
99
                connect(&jdns, SIGNAL(resultsReady(int, const QJDns::Response &)), SLOT(jdns_resultsReady(int, const QJDns::Response &)));
 
100
                connect(&jdns, SIGNAL(published(int)), SLOT(jdns_published(int)));
 
101
                connect(&jdns, SIGNAL(error(int, QJDns::Error)), SLOT(jdns_error(int, QJDns::Error)));
 
102
                connect(&jdns, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
 
103
                connect(&jdns, SIGNAL(debugLinesReady()), SLOT(jdns_debugLinesReady()));
 
104
        }
 
105
 
 
106
        ~App()
 
107
        {
 
108
        }
 
109
 
 
110
public slots:
 
111
        void start()
 
112
        {
 
113
                if(mode == "uni")
 
114
                {
 
115
                        if(!jdns.init(QJDns::Unicast, opt_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any))
 
116
                        {
 
117
                                jdns_debugLinesReady();
 
118
                                printf("unable to bind\n");
 
119
                                emit quit();
 
120
                                return;
 
121
                        }
 
122
 
 
123
                        QList<QJDns::NameServer> addrs;
 
124
                        for(int n = 0; n < nslist.count(); ++n)
 
125
                        {
 
126
                                QJDns::NameServer host;
 
127
                                QString str = nslist[n];
 
128
                                if(str == "mul")
 
129
                                {
 
130
                                        if(opt_ipv6)
 
131
                                                host.address = QHostAddress("FF02::FB");
 
132
                                        else
 
133
                                                host.address = QHostAddress("224.0.0.251");
 
134
                                        host.port = 5353;
 
135
                                }
 
136
                                else
 
137
                                {
 
138
                                        int at = str.indexOf(';');
 
139
                                        if(at != -1)
 
140
                                        {
 
141
                                                host.address = QHostAddress(str.mid(0, at));
 
142
                                                host.port = str.mid(at + 1).toInt();
 
143
                                        }
 
144
                                        else
 
145
                                        {
 
146
                                                host.address = QHostAddress(str);
 
147
                                        }
 
148
                                }
 
149
 
 
150
                                if(host.address.isNull() || host.port <= 0)
 
151
                                {
 
152
                                        printf("bad nameserver: [%s]\n", qPrintable(nslist[n]));
 
153
                                        emit quit();
 
154
                                        return;
 
155
                                }
 
156
                                addrs += host;
 
157
                        }
 
158
 
 
159
                        if(addrs.isEmpty())
 
160
                                addrs = QJDns::systemInfo().nameServers;
 
161
 
 
162
                        if(addrs.isEmpty())
 
163
                        {
 
164
                                printf("no nameservers were detected or specified\n");
 
165
                                emit quit();
 
166
                                return;
 
167
                        }
 
168
 
 
169
                        jdns.setNameServers(addrs);
 
170
                }
 
171
                else
 
172
                {
 
173
                        if(!jdns.init(QJDns::Multicast, opt_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any))
 
174
                        {
 
175
                                jdns_debugLinesReady();
 
176
                                printf("unable to bind\n");
 
177
                                emit quit();
 
178
                                return;
 
179
                        }
 
180
                }
 
181
 
 
182
                if(mode == "uni" || mode == "mul")
 
183
                {
 
184
                        int x = QJDns::A;
 
185
                        if(type == "ptr")
 
186
                                x = QJDns::Ptr;
 
187
                        else if(type == "srv")
 
188
                                x = QJDns::Srv;
 
189
                        else if(type == "a")
 
190
                                x = QJDns::A;
 
191
                        else if(type == "aaaa")
 
192
                                x = QJDns::Aaaa;
 
193
                        else if(type == "mx")
 
194
                                x = QJDns::Mx;
 
195
                        else if(type == "txt")
 
196
                                x = QJDns::Txt;
 
197
                        else if(type == "hinfo")
 
198
                                x = QJDns::Hinfo;
 
199
                        else if(type == "cname")
 
200
                                x = QJDns::Cname;
 
201
                        else if(type == "any")
 
202
                                x = QJDns::Any;
 
203
                        else
 
204
                        {
 
205
                                bool ok;
 
206
                                int y = type.toInt(&ok);
 
207
                                if(ok)
 
208
                                        x = y;
 
209
                        }
 
210
 
 
211
                        req_id = jdns.queryStart(name.toLatin1(), x);
 
212
                        printf("[%d] Querying for [%s] type=%d ...\n", req_id, qPrintable(name), x);
 
213
                }
 
214
                else // publish
 
215
                {
 
216
                        for(int n = 0; n < pubitems.count(); ++n)
 
217
                        {
 
218
                                const QJDns::Record &rr = pubitems[n];
 
219
                                QJDns::PublishMode m = QJDns::Unique;
 
220
                                if(rr.type == QJDns::Ptr)
 
221
                                        m = QJDns::Shared;
 
222
                                int id = jdns.publishStart(m, rr);
 
223
                                printf("[%d] Publishing [%s] type=%d ...\n", id, rr.owner.data(), rr.type);
 
224
                        }
 
225
                }
 
226
 
 
227
                if(opt_quit)
 
228
                        QTimer::singleShot(quit_time * 1000, this, SLOT(doShutdown()));
 
229
        }
 
230
 
 
231
signals:
 
232
        void quit();
 
233
 
 
234
private slots:
 
235
        void jdns_resultsReady(int id, const QJDns::Response &results)
 
236
        {
 
237
                printf("[%d] Results\n", id);
 
238
                for(int n = 0; n < results.answerRecords.count(); ++n)
 
239
                        print_record(results.answerRecords[n]);
 
240
 
 
241
                if(mode == "uni")
 
242
                        jdns.shutdown();
 
243
        }
 
244
 
 
245
        void jdns_published(int id)
 
246
        {
 
247
                printf("[%d] Published\n", id);
 
248
        }
 
249
 
 
250
        void jdns_error(int id, QJDns::Error e)
 
251
        {
 
252
                QString str;
 
253
                if(e == QJDns::ErrorGeneric)
 
254
                        str = "Generic";
 
255
                else if(e == QJDns::ErrorNXDomain)
 
256
                        str = "NXDomain";
 
257
                else if(e == QJDns::ErrorTimeout)
 
258
                        str = "Timeout";
 
259
                else if(e == QJDns::ErrorConflict)
 
260
                        str = "Conflict";
 
261
                printf("[%d] Error: %s\n", id, qPrintable(str));
 
262
                jdns.shutdown();
 
263
        }
 
264
 
 
265
        void jdns_shutdownFinished()
 
266
        {
 
267
                emit quit();
 
268
        }
 
269
 
 
270
        void jdns_debugLinesReady()
 
271
        {
 
272
                QStringList lines = jdns.debugLines();
 
273
                if(opt_debug)
 
274
                {
 
275
                        for(int n = 0; n < lines.count(); ++n)
 
276
                                printf("jdns: %s\n", qPrintable(lines[n]));
 
277
                }
 
278
        }
 
279
 
 
280
        void doShutdown()
 
281
        {
 
282
                jdns.shutdown();
 
283
        }
 
284
};
 
285
 
 
286
#include "main.moc"
 
287
 
 
288
void usage()
 
289
{
 
290
        printf("usage: jdns (options) uni [type] [name] (nameserver(;port)|mul ...)\n");
 
291
        printf("       jdns (options) mul [type] [name]\n");
 
292
        printf("       jdns (options) pub [items ...]\n");
 
293
        printf("       jdns sys\n");
 
294
        printf("\n");
 
295
        printf("options:\n");
 
296
        printf("  -d     show debug output\n");
 
297
        printf("  -6     use ipv6\n");
 
298
        printf("  -q x   quit x seconds after starting\n");
 
299
        printf("\n");
 
300
        printf("uni/mul types: a aaaa ptr srv mx txt hinfo cname any\n");
 
301
        printf("pub items: ptr:name,answer srv:name,answer,port a:name,ipaddr\n");
 
302
        printf("           txt:name,str0,...,strn aaaa:name,ipaddr\n");
 
303
        printf("\n");
 
304
        printf("examples:\n");
 
305
        printf("  jdns uni a jabber.org 192.168.0.1\n");
 
306
        printf("  jdns uni srv _xmpp-client._tcp.jabber.org 192.168.0.1;53\n");
 
307
        printf("  jdns uni 10 user@host._presence._tcp.local mul\n");
 
308
        printf("  jdns mul a foobar.local\n");
 
309
        printf("  jdns mul ptr _services._dns-sd._udp.local\n");
 
310
        printf("  jdns pub a:mybox.local.,192.168.0.55\n");
 
311
        printf("\n");
 
312
}
 
313
 
 
314
int main(int argc, char **argv)
 
315
{
 
316
        QCoreApplication app(argc, argv);
 
317
 
 
318
        if(argc < 2)
 
319
        {
 
320
                usage();
 
321
                return 1;
 
322
        }
 
323
 
 
324
        // get args
 
325
        QStringList args;
 
326
        for(int n = 1; n < argc; ++n)
 
327
                args += QString(argv[n]);
 
328
 
 
329
        bool opt_debug = false;
 
330
        bool opt_ipv6 = false;
 
331
        bool opt_quit = false;
 
332
        int quit_time = 0;
 
333
        QString mode, type, name, ipaddr;
 
334
        QStringList nslist;
 
335
        QList<QJDns::Record> pubitems;
 
336
 
 
337
        // options
 
338
        for(int n = 0; n < args.count(); ++n)
 
339
        {
 
340
                if(args[n].left(1) == "-")
 
341
                {
 
342
                        if(args[n] == "-d")
 
343
                                opt_debug = true;
 
344
                        else if(args[n] == "-6")
 
345
                                opt_ipv6 = true;
 
346
                        else if(args[n] == "-q")
 
347
                        {
 
348
                                if(n + 1 >= args.count())
 
349
                                {
 
350
                                        printf("need to specify number of seconds\n");
 
351
                                        usage();
 
352
                                        return 1;
 
353
                                }
 
354
 
 
355
                                int x = args[n + 1].toInt();
 
356
                                if(x < 1)
 
357
                                        x = 30;
 
358
 
 
359
                                opt_quit = true;
 
360
                                quit_time = x;
 
361
 
 
362
                                args.removeAt(n + 1);
 
363
                        }
 
364
                        else
 
365
                        {
 
366
                                printf("bad option\n");
 
367
                                usage();
 
368
                                return 1;
 
369
                        }
 
370
                        args.removeAt(n);
 
371
                        --n; // adjust position
 
372
                }
 
373
        }
 
374
 
 
375
        mode = args[0];
 
376
        if(mode == "uni" || mode == "mul")
 
377
        {
 
378
                if(args.count() < 3)
 
379
                {
 
380
                        printf("not enough args\n");
 
381
                        usage();
 
382
                        return 1;
 
383
                }
 
384
                type = args[1];
 
385
                name = args[2];
 
386
                if(mode == "uni")
 
387
                {
 
388
                        for(int n = 3; n < args.count(); ++n)
 
389
                                nslist += QString(args[n]);
 
390
                }
 
391
        }
 
392
        else if(mode == "pub")
 
393
        {
 
394
                if(args.count() < 2)
 
395
                {
 
396
                        printf("not enough args\n");
 
397
                        usage();
 
398
                        return 1;
 
399
                }
 
400
                for(int n = 1; n < args.count(); ++n)
 
401
                {
 
402
                        QString arg = args[n];
 
403
                        int at = arg.indexOf(':');
 
404
                        if(at == -1)
 
405
                        {
 
406
                                printf("missing colon\n");
 
407
                                usage();
 
408
                                return 1;
 
409
                        }
 
410
                        QString type = arg.mid(0, at).toLower();
 
411
                        QString val = arg.mid(at + 1);
 
412
                        if(type == "a")
 
413
                        {
 
414
                                QStringList list = val.split(',');
 
415
                                if(list.count() != 2)
 
416
                                {
 
417
                                        printf("bad format for A type\n");
 
418
                                        usage();
 
419
                                        return 1;
 
420
                                }
 
421
                                QHostAddress host(list[1]);
 
422
                                if(host.isNull() || host.protocol() != QAbstractSocket::IPv4Protocol)
 
423
                                {
 
424
                                        printf("bad format for A type IP address\n");
 
425
                                        usage();
 
426
                                        return 1;
 
427
                                }
 
428
 
 
429
                                QJDns::Record rec;
 
430
                                rec.owner = list[0].toLatin1();
 
431
                                rec.type = QJDns::A;
 
432
                                rec.ttl = 120;
 
433
                                rec.haveKnown = true;
 
434
                                rec.address = host;
 
435
                                pubitems += rec;
 
436
                        }
 
437
                        else if(type == "aaaa")
 
438
                        {
 
439
                                QStringList list = val.split(',');
 
440
                                if(list.count() != 2)
 
441
                                {
 
442
                                        printf("bad format for AAAA type\n");
 
443
                                        usage();
 
444
                                        return 1;
 
445
                                }
 
446
                                QHostAddress host(list[1]);
 
447
                                if(host.isNull() || host.protocol() != QAbstractSocket::IPv6Protocol)
 
448
                                {
 
449
                                        printf("bad format for AAAA type IP address\n");
 
450
                                        usage();
 
451
                                        return 1;
 
452
                                }
 
453
 
 
454
                                QJDns::Record rec;
 
455
                                rec.owner = list[0].toLatin1();
 
456
                                rec.type = QJDns::Aaaa;
 
457
                                rec.ttl = 120;
 
458
                                rec.haveKnown = true;
 
459
                                rec.address = host;
 
460
                                pubitems += rec;
 
461
                        }
 
462
                        else if(type == "srv")
 
463
                        {
 
464
                                QStringList list = val.split(',');
 
465
                                if(list.count() != 3)
 
466
                                {
 
467
                                        printf("bad format for SRV type\n");
 
468
                                        usage();
 
469
                                        return 1;
 
470
                                }
 
471
 
 
472
                                QJDns::Record rec;
 
473
                                rec.owner = list[0].toLatin1();
 
474
                                rec.type = QJDns::Srv;
 
475
                                rec.ttl = 120;
 
476
                                rec.haveKnown = true;
 
477
                                rec.name = list[1].toLatin1();
 
478
                                rec.priority = 0;
 
479
                                rec.weight = 0;
 
480
                                rec.port = list[2].toInt();
 
481
                                pubitems += rec;
 
482
                        }
 
483
                        else if(type == "ptr")
 
484
                        {
 
485
                                QStringList list = val.split(',');
 
486
                                if(list.count() != 2)
 
487
                                {
 
488
                                        printf("bad format for PTR type\n");
 
489
                                        usage();
 
490
                                        return 1;
 
491
                                }
 
492
 
 
493
                                QJDns::Record rec;
 
494
                                rec.owner = list[0].toLatin1();
 
495
                                rec.type = QJDns::Ptr;
 
496
                                rec.ttl = 120;
 
497
                                rec.haveKnown = true;
 
498
                                rec.name = list[1].toLatin1();
 
499
                                pubitems += rec;
 
500
                        }
 
501
                        else if(type == "txt")
 
502
                        {
 
503
                                QStringList list = val.split(',');
 
504
                                QList<QByteArray> texts;
 
505
                                for(int n = 1; n < list.count(); ++n)
 
506
                                        texts += list[n].toLatin1();
 
507
 
 
508
                                QJDns::Record rec;
 
509
                                rec.owner = list[0].toLatin1();
 
510
                                rec.type = QJDns::Txt;
 
511
                                rec.ttl = 120;
 
512
                                rec.haveKnown = true;
 
513
                                rec.texts = texts;
 
514
                                pubitems += rec;
 
515
                        }
 
516
                        else
 
517
                        {
 
518
                                printf("bad record type [%s]\n", qPrintable(type));
 
519
                                usage();
 
520
                                return 1;
 
521
                        }
 
522
                }
 
523
        }
 
524
        else if(mode == "sys")
 
525
        {
 
526
                QJDns::SystemInfo info = QJDns::systemInfo();
 
527
 
 
528
                printf("DNS System Information\n");
 
529
                printf("  Name Servers:\n");
 
530
                if(!info.nameServers.isEmpty())
 
531
                {
 
532
                        for(int n = 0; n < info.nameServers.count(); ++n)
 
533
                                printf("    %s\n", qPrintable(info.nameServers[n].address.toString()));
 
534
                }
 
535
                else
 
536
                        printf("    (None)\n");
 
537
 
 
538
                printf("  Domains:\n");
 
539
                if(!info.domains.isEmpty())
 
540
                {
 
541
                        for(int n = 0; n < info.domains.count(); ++n)
 
542
                                printf("    [%s]\n", info.domains[n].data());
 
543
                }
 
544
                else
 
545
                        printf("    (None)\n");
 
546
 
 
547
                printf("  Hosts:\n");
 
548
                if(!info.hosts.isEmpty())
 
549
                {
 
550
                        for(int n = 0; n < info.hosts.count(); ++n)
 
551
                        {
 
552
                                const QJDns::DnsHost &h = info.hosts[n];
 
553
                                printf("    [%s] -> %s\n", h.name.data(), qPrintable(h.address.toString()));
 
554
                        }
 
555
                }
 
556
                else
 
557
                        printf("    (None)\n");
 
558
 
 
559
                QHostAddress addr;
 
560
                printf("Primary IPv4 Multicast Address: ");
 
561
                addr = QJDns::detectPrimaryMulticast(QHostAddress::Any);
 
562
                if(!addr.isNull())
 
563
                        printf("%s\n", qPrintable(addr.toString()));
 
564
                else
 
565
                        printf("(None)\n");
 
566
                printf("Primary IPv6 Multicast Address: ");
 
567
                addr = QJDns::detectPrimaryMulticast(QHostAddress::AnyIPv6);
 
568
                if(!addr.isNull())
 
569
                        printf("%s\n", qPrintable(addr.toString()));
 
570
                else
 
571
                        printf("(None)\n");
 
572
 
 
573
                return 0;
 
574
        }
 
575
        else
 
576
        {
 
577
                usage();
 
578
                return 1;
 
579
        }
 
580
 
 
581
        App a;
 
582
        a.opt_debug = opt_debug;
 
583
        a.opt_ipv6 = opt_ipv6;
 
584
        a.opt_quit = opt_quit;
 
585
        a.quit_time = quit_time;
 
586
        a.mode = mode;
 
587
        a.type = type.toLower();
 
588
        a.name = name;
 
589
        a.ipaddr = ipaddr;
 
590
        a.nslist = nslist;
 
591
        a.pubitems = pubitems;
 
592
        QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
 
593
        QTimer::singleShot(0, &a, SLOT(start()));
 
594
        app.exec();
 
595
        return 0;
 
596
}