123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- // Copyright (C) 2010-2011 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- // host rewritten in C++ using BIND 10 DNS library
- #include <arpa/inet.h>
- #include <netdb.h> // for getaddrinfo
- #include <sys/time.h> // for gettimeofday
- #include <sys/socket.h> // networking functions and definitions on FreeBSD
- #include <unistd.h>
- #include <string>
- #include <iostream>
- #include <util/buffer.h>
- #include <dns/name.h>
- #include <dns/message.h>
- #include <dns/messagerenderer.h>
- #include <dns/opcode.h>
- #include <dns/rcode.h>
- #include <dns/rrclass.h>
- #include <dns/rrtype.h>
- #include <dns/rrset.h>
- #include <dns/message.h>
- using namespace std;
- using namespace isc::dns;
- using namespace isc::util;
- namespace {
- char* dns_type = NULL; // not set, so A, AAAA, MX
- const char* server = "127.0.0.1";
- const char* server_port = "53";
- const char* dns_class = "IN";
- bool verbose = false;
- bool dns_any = false;
- int first_time = 1;
- bool recursive_bit = true;
- struct timeval before_time, after_time;
- int
- host_lookup(const char* const name, const char* const dns_class,
- const char* const type, bool any) {
- Message msg(Message::RENDER);
- msg.setQid(0); // does this matter?
- // TODO: add switch for this
- msg.setOpcode(Opcode::QUERY());
- msg.setRcode(Rcode::NOERROR());
- if (recursive_bit) {
- msg.setHeaderFlag(Message::HEADERFLAG_RD); // set recursive bit
- }
- msg.addQuestion(Question(Name(name),
- RRClass(dns_class),
- any ? RRType::ANY() : RRType(type))); // if NULL then:
- MessageRenderer renderer;
- msg.toWire(renderer);
- struct addrinfo hints, *res;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = 0; // not using AI_NUMERICHOST in case to bootstrap
- if (getaddrinfo(server, server_port, &hints, &res) != 0) {
- cerr << "address/port conversion for " << server << ":"
- << server_port << " failed" << endl;
- return (1);
- }
- if (verbose) {
- cout << "Trying \"" << name << "\"\n";
- }
- if (verbose && first_time) {
- // this is only output the first time
- first_time = 0;
- cout << "Using domain server:\n";
- cout << "Name: " << server << "\n";
- // TODO: I guess I have to do a lookup to get that address and aliases
- // too
- //cout << "Address: " << address << "\n" ;
- //cout << "Aliases: " << server << "\n";
- }
- int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s < 0) {
- cerr << "failed to open socket" << endl;
- return (1);
- }
- if (verbose) {
- gettimeofday(&before_time, NULL);
- }
- sendto(s, renderer.getData(), renderer.getLength(), 0, res->ai_addr,
- res->ai_addrlen);
- struct sockaddr_storage ss;
- struct sockaddr* sa;
- socklen_t sa_len;
- sa_len = sizeof(ss);
- sa = static_cast<struct sockaddr*>((void*)&ss);
- char recvbuf[4096];
- int cc;
- if ((cc = recvfrom(s, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) {
- try {
- Message rmsg(Message::PARSE);
- InputBuffer ibuffer(recvbuf, cc);
- rmsg.fromWire(ibuffer);
- if (!verbose) {
- string description = "";
- for (RRsetIterator it =
- rmsg.beginSection(Message::SECTION_ANSWER);
- it != rmsg.endSection(Message::SECTION_ANSWER);
- ++it) {
- if ((*it)->getType() == RRType::A()) {
- description = "has address";
- }
- else if ((*it)->getType() == RRType::AAAA()) {
- description = "has IPv6 address";
- }
- else if ((*it)->getType() == RRType::MX()) {
- description = "mail is handled by";
- }
- else if ((*it)->getType() == RRType::TXT()) {
- description = "descriptive text";
- }
- RdataIteratorPtr rit = (*it)->getRdataIterator();
- for (; !rit->isLast(); rit->next()) {
- // instead of using my name, maybe use returned label?
- cout << name << " " << description << " " <<
- (*rit).getCurrent().toText() << endl;
- }
- }
- } else {
- gettimeofday(&after_time, NULL);
- // HEADER and QUESTION, ANSWER, AUTHORITY, and ADDITIONAL
- std::cout << rmsg.toText() << std::endl;
- if (before_time.tv_usec > after_time.tv_usec) {
- after_time.tv_usec += 1000000;
- --after_time.tv_sec;
- }
- int elapsed_time =
- (after_time.tv_sec - before_time.tv_sec)
- + ((after_time.tv_usec - before_time.tv_usec))/1000;
- // TODO: if NXDOMAIN, host(1) doesn't show HEADER
- // Host hsdjkfhksjhdfkj not found: 3(NXDOMAIN)
- // TODO: test if NXDOMAIN
- std::cout << "Received " << cc <<
- " bytes in " << elapsed_time << " ms\n";
- // TODO: " bytes from 127.0.0.1#53 in 0 ms
- } //verbose
- /*
- TODO: handle InvalidRRClass
- TODO: handle invalid type exception
- } catch (InvalidType ivt) {
- std::cerr << "invalid type:" << ivt.what();
- */
- } catch (const exception& ex) {
- std::cerr << "parse failed for " <<
- string(name) << "/" << type << ": " << ex.what() << std::endl;
- } catch (...) {
- std::cerr << "parse failed for " << string(name) << "/" << type;
- }
- }
- freeaddrinfo(res);
- return (0);
- } // host_lookup()
- }
- int
- main(int argc, char* argv[]) {
- int c;
- while ((c = getopt(argc, argv, "ac:dp:rt:v")) != -1)
- switch (c) {
- case 'a':
- dns_any = true;
- verbose = true;
- break;
- case 'c':
- dns_class = optarg;
- break;
- // p for port is a non-standard switch
- case 'p':
- server_port = optarg;
- break;
- case 'r':
- recursive_bit = false;
- break;
- case 't':
- dns_type = optarg;
- break;
- case 'd':
- // drop through to v, because debug and verbose are equivalent
- case 'v':
- verbose = true;
- break;
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- cout << "Usage: host [-adrv] [-c class] [-p port] [-t type] hostname [server]\n";
- exit(1);
- }
- if (argc >= 2) {
- server = argv[1];
- }
- if (dns_type == NULL) {
- host_lookup(argv[0], dns_class, "A", dns_any);
- // TODO: don't do next if A doesn't exist
- host_lookup(argv[0], dns_class, "AAAA", dns_any);
- host_lookup(argv[0], dns_class, "MX", dns_any);
- } else {
- // -t overrides -a, regardless of order
- host_lookup(argv[0], dns_class, dns_type, false);
- }
- return (0);
- }
|