/***************************************************************************
                          getroots.cpp  -  get root nameservers
                             -------------------
    begin                : ma feb 3 2003
    copyright            : (C) 2003 by Meilof
    email                : meilof@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <poslib/poslib.h>

struct ns_list {
  char name[16];
  char ips[16][16];
};

/* list mostly taken from maradns's mararc */
ns_list nslists[] = {
  { "icann", { "198.41.0.4", "128.9.0.107", "192.33.4.12", "128.8.10.90",
               "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53",
               "192.36.148.17", "192.58.128.30", "193.0.14.129",
               "198.32.64.12", "202.12.27.33" } },
  { "orsc",  { "199.166.24.1", "216.13.126.116", "216.196.51.3", "204.80.125.130",
               "195.117.6.25", "199.166.31.3", "199.166.31.250", "199.5.157.128",
               "204.57.55.100", "213.196.2.97", "" } },
  { "alternic", { "160.79.129.192", "65.2.214.15", "160.79.133.70", "24.13.64.102",
                  "216.99.37.240", "199.224.64.190", "160.79.133.66",
                  "216.99.37.246", "216.99.37.247" } },
  { "opennic",  { "209.21.75.51", "216.74.72.7", "216.74.72.8", "209.21.75.53",
                  "209.104.33.250", "209.104.63.249" } },
  { "pacificroot", { "204.107.129.2", "208.179.42.162", "12.28.140.20",
                     "204.107.129.10", "212.115.192.151", "202.76.159.5",
                     "209.54.94.3", "167.160.132.2" } },
  { "irsc", { "203.21.205.2", "203.21.205.3", "212.234.36.20", "212.234.36.19",
              "207.180.91.9", "198.199.168.92", "207.180.91.10" } },
  { "tinc", { "64.6.65.10", "208.128.113.35", "212.172.21.254", "207.112.147.14",
              "145.89.234.7", "209.133.38.16" } },
  { "superroot", { "195.117.6.10", "199.166.31.3", "199.5.157.128", "205.189.73.10",
                   "199.166.31.250", "199.166.24.1", "205.189.73.102", "199.166.24.3",
                   "204.80.125.130", "207.126.103.16", "204.57.55.100" } },
};

const int n_roots = sizeof(nslists) / sizeof(ns_list);

ns_list *list_get(const char *name) {
  for (int x = 0; x < n_roots; x++) {
    if (strcmpi(name, nslists[x].name) == 0) return &nslists[x];
  }
  return NULL;
}

void load_symlist(stl_slist(_addr)& nslist, ns_list *list) {
  _addr a;
  int x = 0;
  while (list->ips[x][0]) {
    txt_to_addr(&a, list->ips[x]);
    nslist.push_front(a);
    x++;
  }
}

void search_and_find(domainname dom, stl_list(DnsRR) &section) {
  stl_list(DnsRR)::iterator it = section.begin();

  while (it != section.end()) {
    if (it->NAME == dom) {
      if (it->TYPE == DNS_TYPE_A || it->TYPE == DNS_TYPE_AAAA) {
        printf("  %s@%s\n", dom.tocstr(),
                            rr_tostring(it->TYPE, it->RDATA, it->RDLENGTH).c_str());
      }
    }
    it++;
  }
}

int main(int argc, char **argv) {
  int x;
  stl_slist(_addr) nslist;
  _addr ad;
  int ret = 0;
  ns_list *nlist;

  if (argc == 1) {
    load_symlist(nslist, &nslists[0]);
  } else {
    for (x = 1; x < argc; x++) {
      if (strcmpi(argv[x], "default") == 0) {
        load_symlist(nslist, &nslists[0]);
      } else if ( (nlist = list_get(argv[x])) != NULL ) {
        load_symlist(nslist, nlist);
      } else {
        try {
          if (strcmpi(argv[x], "--help") == 0 || strcmpi(argv[x], "-h") == 0)
            throw PException("");
          txt_to_addr(&ad, argv[x]);
          printf("Address: %s\n", addr_to_string(&ad).c_str());
          nslist.push_front(ad);
        } catch (PException p) {
          fprintf(stderr, "Getroots - Get roots for your Posadisrc\n\n"
                 "Usage: getroots [");
          for (int y = 0; y < n_roots; y++) {
            fprintf(stderr, "%s|", nslists[y].name);
          }
          fprintf(stderr, "<server>]\n\n"
                 "Part of the Posadis DNS server. "
                 "Copyright (C) Meilof Veeningen, 2003.\n");
          return 1;
        }
      }
    }
  }
  
  pos_cliresolver res;
  DnsMessage *q = NULL, *a = NULL;
  stl_list(DnsRR)::iterator it;
  bool has_had = false;

  try {
    q = create_query(".", DNS_TYPE_NS);
    res.query(q, a, nslist);
    
    it = a->answers.begin();
    while (it != a->answers.end()) {
      if (it->NAME == "." && it->TYPE == DNS_TYPE_NS) {
        if (!has_had) printf("cache-ns .\n");
        search_and_find(domainname(true, it->RDATA), a->additional);
        has_had = true;
      }
      it++;
    }
    if (!has_had) throw PException("No nameservers listed!");
  } catch (PException p) {
    fprintf(stderr, "*** Error in query: %s\n", p.message);
    ret = 1;
  }

  if (q) delete q;
  if (a) delete a;

  return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1