hg_dns_axfr.c
上传用户:tjescc
上传日期:2021-02-23
资源大小:419k
文件大小:8k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /* HostsGatherer
  2.  *
  3.  * Copyright (C) 1999 Renaud Deraison
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21. #include <includes.h>
  22. #ifndef _CYGWIN_
  23. #include "hosts_gatherer.h"
  24. #include "hg_filter.h"
  25. #include "hg_utils.h"
  26. #include "hg_add_hosts.h"
  27. #include <arpa/inet.h>
  28. #ifdef HAVE_NETINET_IN_H /* (debian) linux wants this - jh */
  29. #include <netinet/in.h>
  30. #endif
  31. #ifdef USE_ARPA_NAMESER_COMPAT_H
  32. #include <arpa/nameser_compat.h>
  33. #else
  34. #include <arpa/nameser.h>
  35. #endif
  36. #include <resolv.h>
  37. #ifndef INT16SZ
  38. #define INT16SZ 2
  39. #endif
  40. #ifndef INT32SZ
  41. #define INT32SZ 4
  42. #endif
  43. #ifndef HFIXEDSZ
  44. #define      HFIXEDSZ 12
  45. #endif
  46. typedef union {
  47. HEADER qb1;
  48. u_char qb2[PACKETSZ];
  49. } querybuf;
  50. static u_char *
  51. hg_dns_axfr_expand_name(cp, msg, name, namelen)
  52. u_char *cp, *msg;
  53. char *name;
  54.         int namelen;
  55. {
  56. int n;
  57.   if ((n = dn_expand(msg, msg + 512, cp, name, namelen - 2)) < 0)
  58. return (NULL);
  59. if (name[0] == '') {
  60. name[0] = '.';
  61. name[1] = '';
  62. }
  63. return (cp + n);
  64. }
  65. static char *
  66. hg_dns_axfr_add_host(globals, cp, msg)
  67. struct hg_globals * globals;
  68. u_char *cp, *msg;
  69. {
  70.   int type;
  71. char name[MAXDNAME];
  72. if ((cp = (u_char *)hg_dns_axfr_expand_name(cp, msg, name, sizeof(name))) == NULL)
  73. return (NULL); /* compression error */
  74. type = _getshort(cp);
  75. cp += INT16SZ*3 + INT32SZ;
  76. if(type == T_A)
  77. {
  78. struct in_addr addr;
  79. bcopy(cp, &addr, sizeof(addr));
  80. hg_add_host_with_options(globals, name, addr, 0, 32, 0, NULL);
  81. }
  82. return(NULL);
  83. }
  84. /*
  85.  * Asks to the nameserver the names of the
  86.  * name servers that are taking care of
  87.  * the domain we are interested in. Returns the
  88.  * length of the answer
  89.  */
  90. static int
  91.  hg_dns_get_nameservers(globals, domain, answer)
  92.   struct hg_globals * globals;
  93.   char      * domain;
  94.   querybuf     * answer;
  95. {
  96.  int msglen;
  97.  querybuf buffer;
  98.  
  99.  msglen = res_mkquery(QUERY, domain, C_IN, T_NS, NULL, 0, NULL, buffer.qb2,
  100.         sizeof(buffer));
  101.  if(msglen < 0) return(-1);
  102.  msglen = res_send(buffer.qb2, msglen, answer->qb2, sizeof(*answer));
  103.  if(msglen < 0) return(-1);
  104.  return(msglen);
  105. }
  106. /*
  107.  * Decodes the nameserver reply and put
  108.  * the list of nameservers into a struct
  109.  */
  110. static int
  111.  hg_dns_read_ns_from_answer(domainname, answer, ns, msglen)
  112.   char * domainname;
  113.   querybuf answer;
  114.   struct hg_host ** ns;
  115.   int msglen;
  116. {
  117.  struct hg_host * host;
  118.  int count;
  119.  u_char * cp;
  120.  
  121.  count = ntohs(answer.qb1.ancount) + ntohs(answer.qb1.nscount) +
  122.    ntohs(answer.qb1.arcount);
  123.  if(!count||answer.qb1.rcode != NOERROR)return(-1);
  124.  cp = (u_char *)answer.qb2 + 12; 
  125.  if(ntohs(answer.qb1.qdcount) > 0)
  126.       cp += dn_skipname(cp, answer.qb2 + msglen) + QFIXEDSZ;
  127.   
  128.  /*
  129.   * Now adding the nameservers into our host list
  130.   */
  131.   host = malloc(sizeof(struct hg_host));
  132.   bzero(host, sizeof(struct hg_host));
  133.   while(count)
  134.   {
  135.    int type;
  136.    int dlen;
  137.    char domain[256];
  138.    cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp, domain,sizeof(domain));
  139.    type = _getshort(cp);
  140.    cp += 2 * INT16SZ + INT32SZ;
  141.    dlen = _getshort(cp);
  142.    cp += INT16SZ;
  143.    if( type == T_NS) /* name server name */
  144.    {
  145.     char name[256];
  146.     if(dn_expand(answer.qb2, answer.qb2 + msglen, cp, name, sizeof(name)) >= 0)
  147.     {
  148.      int ok = 1;
  149.      struct hg_host * t = host;
  150.      if(!strcasecmp(domain, domainname))
  151.      {
  152.       while((t && t->next)&& ok) /* avoid duplicates */
  153.       {
  154.        if(host && host->hostname && !strcasecmp(host->hostname, name))ok = 0;
  155.        t = t->next;
  156.       }
  157.      
  158.      if(ok)
  159.      {
  160.       int len;
  161.       t = host;
  162.       while(t && t->next)t = t->next;
  163.       t->next = malloc(sizeof(struct hg_host));
  164.       bzero(t->next, sizeof(struct hg_host));
  165.       len = strlen(name);
  166.       t->hostname = malloc(len + 1);
  167.       strncpy(t->hostname, name, len + 1);
  168.      }
  169.     }
  170.    }
  171.   }
  172.   else if (type == T_A) /* name server address */
  173.   {
  174.    struct hg_host * t = host;
  175.    while(t && t->next)
  176.    {
  177.     if(!strcmp(t->hostname, domain)){
  178.      bcopy(cp, &t->addr, sizeof(t->addr));
  179.      t = NULL;
  180.     }
  181.     else t = t->next;
  182.    }
  183.   }
  184.  cp += dlen;
  185.  count --;
  186.  }
  187.  *ns = host;
  188.  return(0);
  189. }
  190.      
  191. /*
  192.  * Checks that we have the IP addresses
  193.  * of all the NS in our list
  194.  *
  195.  */
  196. static void
  197.  hg_dns_fill_ns_addrs(ns)
  198.   struct hg_host * ns;
  199. {
  200.  struct hg_host * t = ns;
  201.  
  202.  while(t && t->next)
  203.  {
  204.   if(!t->addr.s_addr)t->addr = hg_resolv(t->hostname);
  205.   t = t->next;
  206.  }
  207. }
  208. static int
  209.  hg_dns_axfr_decode(globals, answer, limit)
  210.  struct hg_globals * globals;
  211.  querybuf *answer;
  212.  u_char * limit;
  213. {
  214.   HEADER * hp = (HEADER *)answer;
  215.   u_char * cp;
  216.   int qdcount, ancount, nscount, arcount;
  217.   if(hp->rcode != NOERROR)return(-1);
  218.   qdcount = ntohs(hp->qdcount);
  219.   ancount = ntohs(hp->ancount);
  220.   nscount = ntohs(hp->nscount);
  221.   arcount = ntohs(hp->arcount);
  222.   
  223.   if(!(qdcount + ancount + nscount + arcount))return(-1);
  224.   cp = (u_char *)answer + HFIXEDSZ;
  225.   while(qdcount--)cp += dn_skipname(cp, limit) + QFIXEDSZ;
  226.   hg_dns_axfr_add_host(globals, cp, answer);
  227.   
  228.  return(0);
  229. }
  230.  
  231. static int
  232.  hg_dns_axfr_query(globals, domain, ns, answer, limit)
  233. struct hg_globals * globals;
  234. char * domain;
  235. struct hg_host * ns;
  236. querybuf * answer;
  237. u_char ** limit;
  238. {
  239.  int soc;
  240.  int msglen;
  241.  querybuf query;
  242.  int len;
  243.  int finished = 0;
  244.  int num;
  245.  u_char * cp, *nmp;
  246.  struct sockaddr_in addr;
  247.  char dname[2][255];
  248.  int soacnt = 0;
  249.  int error_code;
  250.  msglen = res_mkquery(QUERY, domain, C_IN, T_AXFR, NULL, 0, NULL,
  251.            query.qb2, sizeof(query));
  252.       
  253.  if(msglen < 0)return(-1);
  254.  bzero(&addr, sizeof(struct sockaddr_in));
  255.  addr.sin_family = AF_INET;
  256.  addr.sin_port   = htons(53);
  257.  addr.sin_addr   = ns->addr;
  258.  soc = socket(AF_INET, SOCK_STREAM, 0);
  259.  if(soc < 0)return(-1);
  260.  if(connect(soc, (struct sockaddr *)&addr, sizeof(addr))<0){
  261.   close(soc);
  262.   return(-1);
  263.   }
  264.  putshort(msglen,(u_char *)&len);
  265.  num = send(soc, (char *)&len, INT16SZ, 0);
  266.  num = send(soc, (char *)&query, msglen, 0);
  267.  if(num < msglen){
  268.   close(soc);
  269.   return(-1);
  270.  }
  271.  
  272.  while(!finished)
  273.  {
  274.  fd_set rd;
  275.  struct timeval tv = {0, 5};
  276.  
  277.  cp = (u_char *)answer;
  278.  FD_ZERO(&rd);
  279.  FD_SET(soc, &rd);
  280.  if(!select(soc+1, &rd, NULL, NULL, &tv))
  281.  {
  282.   close(soc);
  283.   return -1;
  284.  }
  285.  if(recv(soc, (char*)&len, INT16SZ, 0)<0)
  286.  {
  287.   close(soc);
  288. #ifdef DEBUG
  289.    perror("recv in axfr ");
  290. #endif
  291.    return(-1);
  292.   }
  293.  len = ntohs(len);
  294.  error_code = -1;
  295.  if(len>0)
  296.  {
  297.   int num_read;
  298.   int left;
  299.   
  300.   left = len;
  301.   while(left > 0)
  302.   {
  303.    num_read = recv(soc, cp, left, 0);
  304.    if(num_read < 0)
  305.    {
  306. #ifdef DEBUG
  307. perror("recv in axfr ");
  308. #endif
  309. close(soc);
  310. return(-1);
  311.    }
  312.    left -= num_read;
  313.    cp += num_read;
  314.   }
  315.  error_code = answer->qb1.rcode;
  316.  hg_dns_axfr_decode(globals, answer, cp);
  317.  cp = answer->qb2 + HFIXEDSZ;
  318.  if(ntohs(answer->qb1.qdcount) > 0)
  319.     cp+= dn_skipname(cp, answer->qb2 + len) + QFIXEDSZ;
  320.  nmp = cp;
  321.  cp += dn_skipname(cp, (u_char *)answer + len);
  322.  if((_getshort(cp) == T_SOA)){
  323.   (void)dn_expand(answer->qb2, answer->qb2 + len, nmp,dname[soacnt], 256);
  324.   if(soacnt){if(!strcmp(dname[0], dname[1]))finished = 1;}
  325.   else soacnt++;
  326.  }
  327. }
  328. else finished = 1;
  329. }
  330.  shutdown(soc, 2);
  331.  close(soc);
  332.  *limit = cp;
  333.  return(error_code);
  334. }
  335. /*
  336.  * Our "main" function regarding DNS AXFR
  337.  */     
  338. void
  339.  hg_dns_axfr_add_hosts(globals, domain)
  340.   struct hg_globals * globals;
  341.   char * domain;
  342. {
  343.  int msglen;
  344.  querybuf answer;
  345.  struct hg_host * ns = NULL;
  346.  u_char * limit;
  347.  if(!domain)return;
  348.  hg_add_domain(globals, domain);
  349.  res_init();
  350.  bzero(&answer, sizeof(answer));
  351.  msglen = hg_dns_get_nameservers(globals, domain, &answer);
  352.  if(msglen < 0)return;
  353.  if(hg_dns_read_ns_from_answer(domain, answer, &ns, msglen)<0)return;
  354.  hg_dns_fill_ns_addrs(ns);
  355.  
  356.  bzero(&answer, sizeof(answer));
  357. #ifdef DEBUG_HIGH
  358.  hg_dump_hosts(ns);
  359. #endif
  360.  hg_dns_axfr_query(globals, domain, ns, &answer, &limit);
  361.  hg_hosts_cleanup(ns);
  362. }
  363. #else  /* XXXXXXXXXXXXXXXXXXXXXXXXX TO IMPLEMENT */
  364. /*
  365.  * Our "main" function regarding DNS AXFR
  366.  */     
  367. void
  368.  hg_dns_axfr_add_hosts(globals, domain)
  369.   struct hg_globals * globals;
  370.   char * domain;
  371. {
  372. }
  373. #endif