123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- /* This file is part of Netsukuku
- *
- * This source code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This source code 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.
- * Please refer to the GNU Public License for more details.
- *
- * You should have received a copy of the GNU Public License along with
- * this source code; if not, write to:
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #include <netinet/in.h>
-
- #include "includes.h"
-
- #include "ntkresolv.h"
- #include "andns_net.h"
- #include "snsd_cache.h"
- #include "crypto.h"
- #include "common.h"
-
- static ntkresolv_opts globopts;
- static struct timeval time_start, time_stop;
- uint8_t mode_compute_hash = 0;
- uint8_t mode_parsable_output = 0;
-
- void
- version(void)
- {
- say("ntk-resolv version %s (Netsukuku tools)\n\n"
- "Copyright (C) 2006.\n"
- "This is free software. You may redistribute copies of it under the terms of\n"
- "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
- "There is NO WARRANTY, to the extent permitted by law.\n\n"
- "Report bugs and ideas to <%s>.\n", VERSION, NTK_RESOLV_MAIL_BUGS);
- ntkresolv_safe_exit(1);
- }
-
-
- void
- usage(void)
- {
- say("Usage:\n"
- "\tntk-resolv [OPTIONS] host\n"
- "\tntk-resolv -H host\n\n"
- " -v --version print version, then exit.\n"
- " -n --nameserver=ns use nameserver `ns' instead of localhost.\n"
- " -P --port=port nameserver port, default 53.\n"
- " -t --query-type=qt query type (`-t help' shows more info).\n"
- " -r --realm=realm realm to scan (`-r help' shows more info).\n"
- " -s --service=service SNSD service (`-s help' shows more info).\n"
- " -p --protocolo=proto SNSD protocol (`-p help' shows more info).\n"
- " -S --silent ntk-resolv will be not loquacious.\n"
- " -b --block-recursion set recursion OFF.\n"
- " -m --md5-hash hostname specified is hash-ed.\n"
- " -H --compute-hash print the hash'ed hostname.\n"
- " -l --parsable-output print answers in a synthetic way.\n"
- " -h --help display this help, then exit.\n\n"
- "Report bugs and ideas to <%s>.\n", NTK_RESOLV_MAIL_BUGS);
- ntkresolv_safe_exit(1);
- }
-
- void
- qt_usage(char *arg)
- {
- if (arg)
- say("Bad Query Type %s\n\n", arg);
- else
- say("ntk-resolv Query Type Help.\n\n");
- say("Valid query types are:\n"
- " * snsd\t\thost:port -> ip\n"
- " ptr\t\tip -> host\n"
- " global\thostname -> all services ip\n"
- " mx\t\thostname MX -> ip\n\n"
- "(you can also use univoque abbreviation)\n"
- "Note: mx query is equivalent to --query-type="
- "snsd AND --service=25\n\n");
- ntkresolv_safe_exit(1);
- }
-
- void
- realm_usage(char *arg)
- {
- if (arg)
- say("Bad Realm %s\n\n", arg);
- else
- say("ntk-resolv Realm Help.\n\n");
- say("Valid realms are:\n"
- " * ntk\tnetsukuku realm\n"
- " inet\tinternet realm\n\n"
- "(you can also use univoque abbreviation)\n\n");
- ntkresolv_safe_exit(1);
- }
-
- void
- proto_usage(char *arg)
- {
- if (arg)
- say("Bad Protocol %s\n\n", arg);
- else
- say("ntk-resolv Protocol Help.\n\n");
- say("Valid protocols are:\n"
- " * tcp\n"
- " udp\n"
- "(you can also use univoque abbreviation)\n"
- "Note: you can also specify the protocol with option `-s'.\n"
- "To know more, type:\n" "\tntk-resolv -s help\n\n");
- ntkresolv_safe_exit(1);
- }
-
- void
- service_and_proto_usage(char *arg)
- {
- if (arg)
- say("Bad service/proto %s\n\n"
- "Use `ntk-resolv -s help` for more info on"
- " service and proto.\n", arg);
- else
- say("ntk-resolv Service and Proto Help.\n\n"
- "The form to specify a service and a protocol are:\n"
- " ntk-resolv -s service/proto\n"
- " ntk-resolv -s service -p proto\n\n"
- "Valid protocols are:\n"
- " * tcp\n"
- " udp\n\n"
- "Valid services are expressed in /etc/services.\n"
- "You can use numeric form too.\n\n"
- "As example, the next commands are equivalent and\n"
- "will return the IP of the hostname that offers\n"
- "webpages for the hostname \"some_hostname\":\n\n"
- " ntk-resolv -s http -p tcp some_hostname\n"
- " ntk-resolv -s http/tcp some_hostname\n"
- " ntk-resolv -s 80/tcp some_hostname\n"
- " ntk-resolv -s 80 some_hostname\n\n");
- ntkresolv_safe_exit(1);
- }
-
-
- double
- diff_time(struct timeval a, struct timeval b)
- {
- double res;
- res = (double) (b.tv_sec - a.tv_sec);
- if (res < 0.9 || b.tv_usec >= a.tv_usec)
- res += (b.tv_usec - a.tv_usec) / TIME_SCALE;
- else {
- res -= 1.0;
- res += (TIME_SCALE + b.tv_usec - a.tv_usec) / TIME_SCALE;
- }
- return res;
- }
-
-
- void
- opts_init(void)
- {
- memset(&GOP, 0, NTKRESOLV_OPTS_SZ);
- strcpy(GOP.nsserver, LOCALHOST);
- GOP.port = NTKRESOLV_PORT;
- GQT = create_andns_pkt();
- GQT->nk = REALM_NTK;
- GQT->p = SNSD_PROTO_DEFAULT;
- GQT->service = SNSD_SERVICE_DEFAULT;
- GQT->r = 1;
- xsrand();
- }
-
- void
- opts_set_silent(void)
- {
- GOP.silent = 1;
- }
-
- void
- opts_set_port(char *arg)
- {
- int res;
- uint16_t port;
-
- res = atoi(arg);
- port = (uint16_t) res;
-
- if (port != res) {
- say("Bad port %s.", arg);
- ntkresolv_safe_exit(1);
- }
- GOP.port = port;
- }
-
- void
- opts_set_ns(char *arg)
- {
- int slen;
-
- slen = strlen(arg);
- if (slen >= MAX_HOSTNAME_LEN) {
- say("Server hostname too long.");
- ntkresolv_safe_exit(1);
- }
- strcpy(GOP.nsserver, arg);
- GOP.nsserver[slen] = 0;
- }
-
- void
- opts_set_qt(char *arg)
- {
- int res;
-
- if (!strcmp(arg, HELP_STR))
- qt_usage(NULL);
- res = QTFROMPREF(arg);
- if (res == -1)
- qt_usage(arg);
- if (res == QTYPE_MX) {
- GQT->qtype = QTYPE_A;
- GQT->service = 25;
- GQT->p = SNSD_PROTO_TCP;
- } else
- GQT->qtype = res;
- }
-
- void
- opts_set_realm(char *arg)
- {
- uint8_t res;
-
- if (!strcmp(arg, HELP_STR))
- realm_usage(NULL);
- res = REALMFROMPREF(arg);
- if (!res)
- realm_usage(arg);
- GQT->nk = res;
- }
-
- void
- opts_set_service_and_proto(char *arg)
- {
- int ret;
-
- if (!strcmp(arg, HELP_STR))
- service_and_proto_usage(NULL);
- ret = str_to_snsd_service(arg, (int *) &GQT->service, &GQT->p);
- /* if(ret == -1)
- say("Bad service %s.",arg);
- else if(ret == -2)
- proto_usage(arg);*/
- if (ret < 0)
- service_and_proto_usage(arg);
- GQT->p -= 1;
- }
-
- void
- opts_set_proto(char *arg)
- {
- int ret;
-
- if (!strcmp(arg, HELP_STR))
- proto_usage(NULL);
- ret = PROTOFROMPREF(arg);
- if (ret < 0)
- proto_usage(arg);
- GQT->p = ret;
- }
-
- /* This is a complex set of function. */
- void
- opts_set_recursion(void)
- {
- GQT->r = 0;
- }
-
- void
- opts_set_hash(void)
- {
- GOP.hash = 1;
- }
-
- void
- opts_set_compute_hash(void)
- {
- mode_compute_hash = 1;
- }
-
- void
- opts_set_parsable_output(void)
- {
- mode_parsable_output = 1;
- AMISILENT = 1;
- }
-
- void
- opts_set_question(char *arg)
- {
- struct in_addr ia;
- struct in6_addr i6a;
- int res;
-
- strcpy(GOP.obj, arg);
- res = strlen(arg);
-
- switch (GQT->qtype) {
- case QTYPE_A:
- if (GQT->nk == REALM_NTK) {
- G_ALIGN(ANDNS_HASH_H);
- if (GOP.hash) {
- if (res != 2 * ANDNS_HASH_H) {
- say("Malformed Hostname hash `%s'.\n", arg);
- ntkresolv_safe_exit(1);
- }
- NTK_RESOLV_STR_HASH(arg, GQT->qstdata);
- } else
- hash_md5((unsigned char *) arg, res,
- (unsigned char *) GQT->qstdata);
- } else {
- if (res > 255) {
- say("Hostname %s is too long for DNS standard.", arg);
- ntkresolv_safe_exit(1);
- }
- G_ALIGN(res);
- strcpy(GQT->qstdata, arg);
- }
- return;
- case QTYPE_PTR:
- res = inet_pton(AF_INET, arg, &ia);
- if (res) {
- G_ALIGN(ANDNS_HASH_H);
- memcpy(GQT->qstdata, &ia.s_addr, 4);
- return;
- }
- res = inet_pton(AF_INET6, arg, &i6a);
- if (!res) {
- say("Bad address `%s'\n", arg);
- ntkresolv_safe_exit(1);
- }
- G_ALIGN(16);
- memcpy(GQT->qstdata, &i6a.s6_addr16, 16);
- GQT->ipv = ANDNS_IPV6;
- return;
- case QTYPE_G:
- if (GQT->nk != REALM_NTK) {
- say("Global query type is valid only for the Ntk realm.");
- ntkresolv_safe_exit(1);
- }
- G_ALIGN(ANDNS_HASH_H);
- if (GOP.hash)
- NTK_RESOLV_STR_HASH(arg, GQT->qstdata);
- else
- hash_md5((unsigned char *) arg, res,
- (unsigned char *) GQT->qstdata);
- return;
- default:
- say("Unknow Query Type.\n");
- return;
- }
- }
-
- void
- opts_finish(char *arg)
- {
- int r;
-
- r = strlen(arg);
- if (r > NTKRESOLV_MAX_OBJ_LEN) {
- say("Object requested is too long: %s", arg);
- ntkresolv_safe_exit(1);
- }
-
- if (mode_compute_hash) { /* Do command here and exit */
- G_ALIGN(ANDNS_HASH_H);
- hash_md5((unsigned char *) arg, r, (unsigned char *) GQT->qstdata);
- NTK_RESOLV_HASH_STR(GQT->qstdata, GOP.obj);
- say("%s\n", GOP.obj);
- ntkresolv_safe_exit(0);
- }
- if (GOP.hash && GQT->qtype == AT_PTR) {
- say("Option `-m' is not usable with inverse queries.\n");
- ntkresolv_safe_exit(1);
- }
- r = rand();
- GQT->id = r >> 16;
- opts_set_question(arg);
- }
-
- void
- print_headers()
- {
- andns_pkt *ap = GQT;
- say("\n - Headers Section:\n"
- "\tid ~ %6d\tqr ~ %4d\tqtype ~ %7s\n"
- "\tan ~ %6d\tipv ~ %s\trealm ~ %7s\n"
- "\tsv ~ %6s\tprt ~ %4s\trCode ~ %s\n"
- "\trc ~ %6d\n",
- ap->id, ap->qr, QTYPE_STR(ap),
- ap->ancount, IPV_STR(ap), NK_STR(ap),
- SERVICE_STR(ap), PROTO_STR(ap), RCODE_STR(ap), ap->r);
- }
-
- void
- print_question()
- {
- say("\n - Question Section:\n" "\tObj ~ %s\n", GOP.obj);
- }
-
- void
- ip_bin_to_str(void *data, char *dst)
- {
- int family;
- struct in_addr ia;
- struct in6_addr i6a;
- const void *via;
- const char *crow;
-
- family = GQT->ipv == ANDNS_IPV4 ? AF_INET : AF_INET6;
- switch (family) {
- case AF_INET:
- memcpy(&(ia.s_addr), data, 4);
- via = (void *) (&ia);
- break;
- case AF_INET6:
- memcpy(&(i6a.s6_addr16), data, 16);
- via = (void *) (&i6a);
- break;
- default:
- strcpy(dst, "Unprintable Object");
- return;
- }
- crow = inet_ntop(family, via, dst, NTKRESOLV_MAX_OBJ_LEN);
- if (!crow)
- strcpy(dst, "Unprintable Object");
- }
-
- void
- answer_data_to_str(andns_pkt_data * apd, char *dst)
- {
- if (GQT->qtype == AT_PTR)
- strcpy(dst, apd->rdata);
- else if (GQT->qtype == AT_G || GQT->qtype == AT_A) {
- if (apd->m & APD_IP)
- ip_bin_to_str(apd->rdata, dst);
- else
- NTK_RESOLV_HASH_STR(apd->rdata, dst);
- } else
- strcpy(dst, "Unprintable Object");
- }
-
- void
- print_answers()
- {
- int i = 0;
- int ancount = GQT->ancount;
- andns_pkt_data *apd;
-
- if (!ancount)
- return;
-
- say("\n - Answers Section:\n");
-
- apd = GQT->pkt_answ;
- while (apd) {
- i++;
- if (i > ancount)
- say("Answer not declared in Headers Packet.\n");
- answer_data_to_str(apd, GOP.obj);
- say("\t ~ %s", GOP.obj);
- if (apd->m & APD_MAIN_IP)
- say(" *");
- else if (GQT->qtype != AT_PTR && !(apd->m & APD_IP) && GQT->r)
- say("\t + Recursion Failed");
- say("\n");
- if (GQT->qtype == AT_A || GQT->qtype == AT_G)
- say("\t\tPrio ~ %d Weigth ~ %d\n", apd->prio, apd->wg);
- if (GQT->qtype == AT_G)
- say("\t\tService ~ %d Proto ~ %s\n",
- apd->service, apd->m & APD_UDP ? "udp" : "tcp");
- say("\n");
- apd = apd->next;
- }
- }
-
- void
- print_parsable_answers(void)
- {
- int i = 0;
- int ancount = GQT->ancount;
- andns_pkt_data *apd;
-
- if (!ancount)
- return;
-
- apd = GQT->pkt_answ;
- while (apd) {
- i++;
- if (i > ancount)
- say("Answer not declared in Headers Packet.\n");
- answer_data_to_str(apd, GOP.obj);
- if (GQT->qtype == AT_PTR || (GQT->qtype == AT_A && !GQT->service))
- say("%s %s\n", NTK_RESOLV_SYMBOL(apd), GOP.obj);
- else if (GQT->qtype == AT_A)
- say("%s %s %d %d\n", NTK_RESOLV_SYMBOL(apd),
- GOP.obj, apd->prio, apd->wg);
- else
- say("%s %s %d %s %d %d\n", NTK_RESOLV_SYMBOL(apd),
- GOP.obj, apd->service,
- apd->m & APD_UDP ? "udp" : "tcp", apd->prio, apd->wg);
- apd = apd->next;
- }
- }
-
- void
- print_results(void)
- {
- if (!AMISILENT) {
- print_headers();
- print_question();
- }
- if (mode_parsable_output)
- print_parsable_answers();
- else
- print_answers();
- }
-
- void
- do_command(void)
- {
- char buf[ANDNS_MAX_SZ];
- char answer[ANDNS_MAX_PK_LEN];
- int res;
-
- memset(buf, 0, ANDNS_MAX_SZ);
- GOP.id = GQT->id;
- res = a_p(GQT, buf);
- if (res == -1) {
- say("Error building question.\n");
- ntkresolv_exit(1);
- }
- res = hn_send_recv_close(GOP.nsserver, GOP.port,
- SOCK_DGRAM, buf, res, answer,
- ANDNS_MAX_PK_LEN, 0, NTK_RESOLV_TIMEOUT);
- if (res == -1) {
- say("Communication failed with %s.\n", GOP.nsserver);
- ntkresolv_exit(1);
- }
- if (res == -2) {
- say("Unable to send() to %s.\n", GOP.nsserver);
- ntkresolv_exit(1);
- }
- if (res == -3) {
- say("Unable to recv() from %s.\n", GOP.nsserver);
- ntkresolv_exit(1);
- }
- res = a_u(answer, res, &GQT);
- if (res <= 0) {
- say("Error interpreting server answer.\n");
- ntkresolv_exit(1);
- }
- if (GQT->id != GOP.id)
- say("Warning: ID query (%d) is mismatching ID answer (%d)!\n",
- GOP.id, GQT->id);
-
- print_results();
- destroy_andns_pkt(GQT);
- }
-
- void
- ntkresolv_exit(int i)
- {
- exit(i);
- }
-
- void
- ntkresolv_safe_exit(int i)
- {
- destroy_andns_pkt(GQT);
- ntkresolv_exit(i);
- }
-
- int
- main(int argc, char **argv)
- {
- int c;
- extern int optind, opterr, optopt;
- extern char *optarg;
-
- log_init("", 0, 1);
- gettimeofday(&time_start, NULL);
-
- opts_init();
- struct option longopts[] = {
- {"version", 0, 0, 'v'},
- {"nameserver", 1, 0, 'n'},
- {"port", 1, 0, 'P'},
- {"query-type", 1, 0, 't'},
- {"realm", 1, 0, 'r'},
- {"service", 1, 0, 's'},
- {"proto", 1, 0, 'p'},
- {"silent", 0, 0, 'S'},
- {"block-recursion", 0, 0, 'b'},
- {"md5-hash", 0, 0, 'm'},
- {"compute-hash", 0, 0, 'H'},
- {"parsable-output", 0, 0, 'l'},
- {"help", 0, 0, 'h'},
- {0, 0, 0, 0}
- };
-
- while (1) {
- int oindex = 0;
- c = getopt_long(argc, argv,
- "vn:P:t:r:s:p:ShbmHl", longopts, &oindex);
- if (c == -1)
- break;
- switch (c) {
- case 'v':
- version();
- case 'n':
- opts_set_ns(optarg);
- break;
- case 'P':
- opts_set_port(optarg);
- break;
- case 't':
- opts_set_qt(optarg);
- break;
- case 'r':
- opts_set_realm(optarg);
- break;
- case 's':
- opts_set_service_and_proto(optarg);
- break;
- case 'p':
- opts_set_proto(optarg);
- break;
- case 'h':
- usage();
- case 'S':
- opts_set_silent();
- break;
- case 'b':
- opts_set_recursion();
- break;
- case 'm':
- opts_set_hash();
- break;
- case 'H':
- opts_set_compute_hash();
- break;
- case 'l':
- opts_set_parsable_output();
- break;
- default:
- usage();
- }
- }
- if (optind == argc)
- usage();
- opts_finish(argv[optind]);
- do_command();
- time_report;
- bye;
- return 0;
- }
|