📄 import-tinydns.c
字号:
/************************************************************************************************** $Id: import-tinydns.c,v 1.14 2005/04/20 16:49:12 bboy Exp $ import-tinydns.c: Import DNS data from a tinydns-data format data file. 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"#ifdef TINYDNS_IMPORT#define MAX_FIELDS 20 /* Max fields per line */#define TINYDNS_DEF_REFRESH 16384#define TINYDNS_DEF_RETRY 2048#define TINYDNS_DEF_EXPIRE 1048576#define TINYDNS_DEF_MINIMUM 2560#define TINYDNS_DEF_TTL 2560typedef struct _zone{ uint32_t id; char *origin, *ns, *mbox; uint32_t serial, refresh, retry, expire, minimum, ttl;} ZONE;static ZONE **Zones = NULL; /* List of zones found */static int numZones = 0; /* Number of zones found */static uint32_t default_serial; /* Default serial */static unsigned int lineno; /* Current line number */static char *filename; /* Input file name */static char *field[MAX_FIELDS]; /* Fields parsed from line */static char tinydns_zone[DNS_MAXNAMELEN+1]; /* Zone to import (only this zone) */extern uint32_t import_zone_id; /* ID of current zone */extern uint32_t import_soa(const char *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);/************************************************************************************************** TWARN Convenience function; outputs error message for current file/line.**************************************************************************************************/static voidtwarn(const char *fmt, ...){ va_list ap; char buf[1024]; va_start(ap, fmt); vsnprintf(buf, sizeof(buf)-1, fmt, ap); va_end(ap); Warnx("%s: line %u: %s", filename, lineno, buf); return;}/*--- twarn() -----------------------------------------------------------------------------------*//************************************************************************************************** ZONE_OK Given an fqdn, is this a zone we want to process?**************************************************************************************************/static inline intzone_ok(const char *fqdn){ if (!tinydns_zone[0]) /* Processing all zones */ return 1; if (!strcasecmp(fqdn, tinydns_zone)) /* Exact match on zone */ return 1; /* Does FQDN at least end with the zone? */ if (strlen(fqdn) > strlen(tinydns_zone) && !strcasecmp(fqdn + strlen(fqdn) - strlen(tinydns_zone), tinydns_zone)) return 1; return 0;}/*--- zone_ok() ---------------------------------------------------------------------------------*//************************************************************************************************** ZONECMP Comparison function for sorting zones.**************************************************************************************************/static intzonecmp(const void *p1, const void *p2){ ZONE *z1 = *(ZONE **)p1, *z2 = *(ZONE **)p2; return strcasecmp(z1->origin, z2->origin);}/*--- zonecmp() ---------------------------------------------------------------------------------*//************************************************************************************************** FIND_ZONE Looks for the specified zone. Returns it if found, else NULL.**************************************************************************************************/static inline ZONE *find_zone(const char *origin){ register int n; for (n = 0; n < numZones; n++) if (!strcasecmp(Zones[n]->origin, origin)) return Zones[n]; return NULL;}/*--- find_zone() -------------------------------------------------------------------------------*//************************************************************************************************** FIND_HOST_ZONE Looks for the zone matching the provided FQDN. Returns it if found, else NULL. Also sets the hostname part of 'fqdn' in 'hostname'.**************************************************************************************************/static inline ZONE *find_host_zone(char *fqdn, char *hostname){ register char *c; ZONE *z; hostname[0] = '\0'; if ((z = find_zone(fqdn))) /* See if 'fqdn' is a plain zone origin */ return (z); for (c = fqdn; *c; c++) if (*c == '.') if ((z = find_zone(c + 1))) { memcpy(hostname, fqdn, c - fqdn); hostname[c - fqdn] = '\0'; return (z); } return NULL;}/*--- find_host_zone() --------------------------------------------------------------------------*//************************************************************************************************** FIND_ARPA_ZONE Given an IP address in numbers-and-dots format, returns the relevant in-addr.arpa zone, or NULL if not found.**************************************************************************************************/static inline ZONE *find_arpa_zone(const char *ip, char *hostname){ char zone[DNS_MAXNAMELEN + 1], buf[DNS_MAXNAMELEN + 1], *p, *a, *b, *c, *d; ZONE *z; hostname[0] = '\0'; strncpy(buf, ip, sizeof(buf)-1); p = buf; if (!(a = strsep(&p, ".")) || !(b = strsep(&p, ".")) || !(c = strsep(&p, ".")) || !(d = strsep(&p, "."))) return NULL; snprintf(zone, sizeof(zone), "%s.in-addr.arpa", a); if ((z = find_zone(zone))) { snprintf(hostname, DNS_MAXNAMELEN, "%s.%s.%s", d, c, b); return z; } snprintf(zone, sizeof(zone), "%s.%s.in-addr.arpa", b, a); if ((z = find_zone(zone))) { snprintf(hostname, DNS_MAXNAMELEN, "%s.%s", d, c); return z; } snprintf(zone, sizeof(zone), "%s.%s.%s.in-addr.arpa", c, b, a); if ((z = find_zone(zone))) { strncpy(hostname, d, DNS_MAXNAMELEN); return z; } return NULL;}/*--- find_arpa_zone() --------------------------------------------------------------------------*//************************************************************************************************** NEW_ZONE Adds a new zone. Returns the zone.**************************************************************************************************/static ZONE *new_zone(const char *originp){ ZONE *z; char origin[DNS_MAXNAMELEN+1]; /* If this is an 'in-addr.arpa' zone, knock off the first quad if present */ if (strlen(originp) > 12 && !strcasecmp(originp + strlen(originp) - 13, ".in-addr.arpa")) { char buf[DNS_MAXNAMELEN+1], *p, *a, *b, *c, *d; strncpy(buf, originp, sizeof(buf)-1); p = buf; if ((d = strsep(&p, ".")) && (c = strsep(&p, ".")) && (b = strsep(&p, ".")) && (a = strsep(&p, "."))) snprintf(origin, sizeof(origin), "%s.%s.%s.in-addr.arpa", c, b, a); else strncpy(origin, originp, sizeof(origin)-1); } else strncpy(origin, originp, sizeof(origin)-1); if ((z = find_zone(origin))) return z; if (!(z = malloc(sizeof(ZONE)))) Err("malloc"); z->id = 0; if (!(z->origin = strdup(origin))) Err("strdup"); z->ns = NULL; z->mbox = NULL; z->serial = default_serial; z->refresh = TINYDNS_DEF_REFRESH; z->retry = TINYDNS_DEF_RETRY; z->expire = TINYDNS_DEF_EXPIRE; z->minimum = TINYDNS_DEF_MINIMUM; z->ttl = TINYDNS_DEF_TTL; if (!Zones) { if (!(Zones = malloc((numZones + 1) * sizeof(ZONE)))) Err("malloc"); } else { if (!(Zones = realloc(Zones, (numZones + 1) * sizeof(ZONE)))) Err("realloc"); } Zones[numZones++] = z; return z;}/*--- new_zone() --------------------------------------------------------------------------------*//************************************************************************************************** TINYDNS_ADD_SOA Adds a zone to 'Zones' due to a '.' or 'Z' line.**************************************************************************************************/voidtinydns_add_soa(char *line){ char *l = line + 1; ZONE *z; if (line[0] == '.') /* '.' (NS) line */ { char *fqdn = NULL, *ip = NULL, *x = NULL, *ttl = NULL, *timestamp = NULL, *lo = NULL; if (!(fqdn = strsep(&l, ":")) || !strlen(fqdn)) return twarn("'.' line has no fqdn"); if (!zone_ok(fqdn)) return; if (!(ip = strsep(&l, ":"))) return twarn("'.' line has no ip"); if ((x = strsep(&l, ":")) && (ttl = strsep(&l, ":")) && (timestamp = strsep(&l, ":")) && (lo = strsep(&l, ":"))) /* DONOTHING */; z = new_zone(fqdn); /* Assign 'ns' */ if (!z->ns) { if (!x || !strlen(x)) sdprintf(&z->ns, "ns.%s", fqdn); else if (strchr(x, '.')) { if (!(z->ns = strdup(x))) Err("strdup"); } else sdprintf(&z->ns, "%s.ns.%s", x, fqdn); } /* Assign 'mbox' */ if (!z->mbox) sdprintf(&z->mbox, "hostmaster.%s", fqdn); } else if (line[0] == 'Z') /* 'Z' (SOA) line */ { char *fqdn = NULL, *ns = NULL, *mbox = NULL, *serial = NULL, *refresh = NULL, *retry = NULL, *expire = NULL, *minimum = NULL, *ttl = NULL, *timestamp = NULL, *lo = NULL; if (!(fqdn = strsep(&l, ":")) || !strlen(fqdn)) return twarn("'Z' line has no fqdn"); if (!zone_ok(fqdn)) return; if (!(ns = strsep(&l, ":")) || !strlen(ns)) return twarn("'Z' line has no ns"); if (!(mbox = strsep(&l, ":")) || !strlen(mbox)) return twarn("'Z' line has no mbox"); if ((serial = strsep(&l, ":")) && (refresh = strsep(&l, ":")) && (retry = strsep(&l, ":")) && (expire = strsep(&l, ":")) && (minimum = strsep(&l, ":")) && (ttl = strsep(&l, ":")) && (timestamp = strsep(&l, ":")) && (lo = strsep(&l, ":"))) /* DONOTHING */; z = new_zone(fqdn); if (!z->ns) { if (!(z->ns = strdup(ns))) Err("strdup"); } if (!z->mbox) { if (!(z->mbox = strdup(mbox))) Err("strdup"); } if (serial) z->serial = atol(serial); if (refresh) z->refresh = atol(refresh); if (retry) z->retry = atol(retry); if (expire) z->expire = atol(expire); if (minimum) z->minimum = atol(minimum); if (ttl) z->ttl = atol(ttl); }}/*--- tinydns_add_soa() -------------------------------------------------------------------------*//************************************************************************************************** CREATE_ZONE Loads or creates the actual SOA record and loads the ID.**************************************************************************************************/static voidcreate_zone(ZONE *z){ char origin[DNS_MAXNAMELEN + 3], ns[DNS_MAXNAMELEN + 3], mbox[DNS_MAXNAMELEN + 3]; if (!z->ns) sdprintf(&z->ns, "ns.%s", z->origin); if (!z->mbox) sdprintf(&z->mbox, "hostmaster.%s", z->origin); snprintf(origin, sizeof(origin), "%s.", z->origin); snprintf(ns, sizeof(ns), "%s.", z->ns); snprintf(mbox, sizeof(mbox), "%s.", z->mbox); z->id = import_soa(origin, ns, mbox, z->serial, z->refresh, z->retry, z->expire, z->minimum, z->ttl);}/*--- create_zone() -----------------------------------------------------------------------------*//************************************************************************************************** TINYDNS_PLUS +fqdn:ip:ttl:timestamp:lo Alias fqdn with IP address ip. This is just like =fqdn:ip:ttl except that tinydns-data does not create the PTR record.**************************************************************************************************/static voidtinydns_plus(void){ ZONE *z; char *fqdn = field[0], *ip = field[1], *ttl = field[2]; char hostname[DNS_MAXNAMELEN + 1] = ""; if (!fqdn || !strlen(fqdn)) return (void)Warnx("%s:%u: %s", filename, lineno, _("fqdn field empty")); if (!zone_ok(fqdn)) return; if (!(z = find_host_zone(fqdn, hostname))) return (void)Warnx("%s:%u: %s: %s", filename, lineno, fqdn, _("fqdn does not match any zones")); /* Set import_zone_id and import the record */ if (ip && strlen(ip)) { import_zone_id = z->id; import_rr(hostname, "A", ip, 0, ttl ? atol(ttl) : z->ttl); }}/*--- tinydns_plus() ----------------------------------------------------------------------------*//************************************************************************************************** TINYDNS_DOT .fqdn:ip:x:ttl:timestamp:lo 1. Create an NS record showing x.ns.fqdn as a name server for fqdn 2. Create an A record showing ip as the IP address of x.ns.fqdn**************************************************************************************************/static voidtinydns_dot(void){ ZONE *z; char *fqdn = field[0], *ip = field[1], *x = field[2], *ttl = field[3]; char hostname[DNS_MAXNAMELEN + 1] = "", buf[DNS_MAXNAMELEN + 1]; if (!fqdn || !strlen(fqdn)) return (void)Warnx("%s:%u: %s", filename, lineno, _("fqdn field empty")); if (!zone_ok(fqdn)) return; if (!(z = find_host_zone(fqdn, hostname))) return (void)Warnx("%s:%u: %s: %s", filename, lineno, fqdn, _("fqdn does not match any zones")); import_zone_id = z->id; /* Create NS record */ if (x && strlen(x)) { if (strchr(x, '.')) strncpy(buf, x, sizeof(buf)-1); else snprintf(buf, sizeof(buf), "%s.ns", x); if (LASTCHAR(buf) != '.') strcat(buf, "."); import_rr(hostname, "NS", buf, 0, ttl ? atol(ttl) : z->ttl); } else { strncpy(buf, "ns", sizeof(buf)-1); import_rr(hostname, "NS", buf, 0, ttl ? atol(ttl) : z->ttl); } /* Create A record if 'ip' is present */ if (ip && strlen(ip)) import_rr(buf, "A", ip, 0, ttl ? atol(ttl) : z->ttl);}/*--- tinydns_dot() -----------------------------------------------------------------------------*//************************************************************************************************** TINYDNS_AMP &fqdn:ip:x:ttl:timestamp:lo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -