📄 import-axfr.c
字号:
/************************************************************************************************** $Id: import-axfr.c,v 1.19 2005/04/20 17:22:25 bboy Exp $ import-axfr.c: Import DNS data via AXFR. Copyright (C) 2002-2005 Don Moore <bboy@bboy.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. This program 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**************************************************************************************************/#include "util.h"#include <netdb.h>static char *hostname, *zone; /* Hostname of remote host and zone */static char origin[DNS_MAXNAMELEN+1]; /* The origin name reported by the peer */static uint32_t got_soa = 0; /* Have we read the initial SOA record? */extern int opt_notrim; /* Don't remove trailing origin */extern int opt_output; /* Output instead of insert */extern uint32_t import_soa(const char *import_origin, const char *ns, const char *mbox, unsigned serial, unsigned refresh, unsigned retry, unsigned expire, unsigned minimum, unsigned ttl);extern void import_rr(char *name, char *type, char *data, unsigned aux, unsigned ttl);/************************************************************************************************** AXFR_CONNECT Connects to the remote server specified by `arg' (format "HOST[:PORT]/ZONE") and return a fd to newly created socket.**************************************************************************************************/static intaxfr_connect(char *hostportp, char **hostnamep){ char hostport[512]; char *rem_hostname, *portp; unsigned int port = 53; int fd, n; struct hostent *he; struct sockaddr_in sa; strncpy(hostport, hostportp, sizeof(hostport)-1); if (!(rem_hostname = hostport) || !*rem_hostname) /* Parse hostname, port, zone */ Errx(_("host not specified")); if ((portp = strchr(hostport, ':'))) *portp++ = '\0', port = atoi(portp); strtrim(zone); /* REMOVE any trailing dot(s) from end of zone name.. We automatically append the dot in request_axfr */ while (LASTCHAR(zone) == '.') LASTCHAR(zone) = '\0'; if (strlen(zone) > 256) Errx(_("zone too long")); *hostnamep = rem_hostname; Verbose(_("importing `%s' from %s:%u"), zone, rem_hostname, port); memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_family = AF_INET; sa.sin_port = htons(port); if (!(he = gethostbyname(rem_hostname))) Errx("%s: %s", rem_hostname, _("unknown host")); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) Err("%s", rem_hostname); for (n = 0; he->h_addr_list[n]; n++) { memcpy(&sa.sin_addr, he->h_addr_list[n], sizeof(struct in_addr)); if (!connect(fd, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in))) return (fd); Warn("%s (%s)", rem_hostname, inet_ntoa(sa.sin_addr)); } close(fd); return (-1);}/*--- axfr_connect() ----------------------------------------------------------------------------*//************************************************************************************************** MAKE_QUESTION Creates a question. Returns the packet and stores the length of the packet in `packetlen'. The packet is dynamically allocated and should be free()'d.**************************************************************************************************/char *make_question(uint16_t id, dns_qtype_t qtype, char *name, size_t *packetlen){ char req[1024], *dest = req, *c; DNS_HEADER header; size_t len; if (packetlen) *packetlen = 0; memset(&header, 0, sizeof(DNS_HEADER)); DNS_PUT16(dest, id); /* ID */ header.rd = 1; memcpy(dest, &header, sizeof(DNS_HEADER)); dest += SIZE16; DNS_PUT16(dest, 1); /* QDCOUNT */ DNS_PUT16(dest, 0); /* ANCOUNT */ DNS_PUT16(dest, 0); /* NSCOUNT */ DNS_PUT16(dest, 0); /* ARCOUNT */ for (c = name; *c; c++) /* QNAME */ if (c == name || *c == '.') { char *end; if (c != name) c++; if ((end = strchr(c, '.'))) *end = '\0'; if ((len = strlen(c))) { if (len > 64) { Warnx(_("zone contains invalid label (64 chars max)")); return (NULL); } *dest++ = len; DNS_PUT(dest, c, len); } if (end) *end = '.'; } *dest++ = 0; DNS_PUT16(dest, (uint16_t)qtype); /* QTYPE */ DNS_PUT16(dest, DNS_CLASS_IN); /* QCLASS */ len = dest - req; if (packetlen) *packetlen = len; if (!(c = malloc(len))) Err("malloc"); memcpy(c, &req, len); return (c);}/*--- make_question() ---------------------------------------------------------------------------*//************************************************************************************************** REQUEST_AXFR Constructs and sends the AXFR request packet.**************************************************************************************************/static voidrequest_axfr(int fd, char *rem_hostname, char *zone){ char *qb, *q, *p; size_t qlen; int rv, off = 0; if (!(qb = make_question(getpid(), DNS_QTYPE_AXFR, zone, &qlen))) exit(EXIT_FAILURE); if (!(p = q = malloc(qlen + SIZE16))) Err("malloc"); DNS_PUT16(p, qlen); memcpy(p, qb, qlen); Free(qb); qlen += SIZE16; do { if ((rv = write(fd, q + off, qlen - off)) < 0) Err("%s: write", rem_hostname); off += rv; } while (off < qlen); Free(q);}/*--- request_axfr() ----------------------------------------------------------------------------*//************************************************************************************************** PROCESS_AXFR_SOA Find the SOA. Insert it, and return the SOA record.**************************************************************************************************/static voidprocess_axfr_soa(char *name, char *reply, size_t replylen, char *src, uint32_t ttl){ char ns[DNS_MAXNAMELEN+1], mbox[DNS_MAXNAMELEN+1]; uint32_t serial, refresh, retry, expire, minimum; if (got_soa) return; if (!(src = name_unencode(reply, replylen, src, ns, sizeof(ns)))) Errx("%s SOA: %s: %s", name , _("error reading ns from SOA"), name); if (!(src = name_unencode(reply, replylen, src, mbox, sizeof(mbox)))) Errx("%s SOA: %s: %s", name, _("error reading mbox from SOA"), name); DNS_GET32(serial, src); DNS_GET32(refresh, src); DNS_GET32(retry, src); DNS_GET32(expire, src); DNS_GET32(minimum, src); if (ttl < minimum) ttl = minimum; strncpy(origin, name, sizeof(origin)-1); got_soa = import_soa(origin, ns, mbox, serial, refresh, retry, expire, minimum, ttl);}/*--- process_axfr_soa() ------------------------------------------------------------------------*//************************************************************************************************** SHORTNAME Removes the origin from a name if it is present.**************************************************************************************************/static char *shortname(char *name, int empty_name_is_ok){ size_t nlen = strlen(name), olen = strlen(origin); if (opt_notrim) return (name); if (nlen < olen) return (name); if (!strcasecmp(origin, name)) { if (empty_name_is_ok) return (""); else return (name); } if (!strcasecmp(name + nlen - olen, origin)) name[nlen - olen - 1] = '\0'; return (name);}/*--- shortname() -------------------------------------------------------------------------------*//************************************************************************************************** PROCESS_AXFR_ANSWER Processes a single answer. If it's a SOA record, it is inserted, loaded, and the SOA record is returned.**************************************************************************************************/static char *process_axfr_answer(char *reply, size_t replylen, char *src){ char name[DNS_MAXNAMELEN+1], data[DNS_MAXNAMELEN+1], *rv; uint16_t type, class, rdlen; uint32_t ttl; if (!(src = name_unencode(reply, replylen, src, name, sizeof(name))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -