📄 check.c
字号:
/************************************************************************************************** $Id: check.c,v 1.36 2005/05/04 16:49:59 bboy Exp $ check.c: Check for problems with the data in the database. 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"MYDNS_SOA *soa; /* Current SOA record being scanned */MYDNS_RR *rr; /* Current RR record */char name[DNS_MAXNAMELEN*2]; /* Current expanded name */char data[DNS_MAXNAMELEN*2]; /* Current expanded data */int opt_consistency = 0; /* Consistency check? */int opt_consistency_only = 0; /* Consistency check only? */int ignore_minimum = 0; /* Ignore minimum TTL? */#ifdef EXTENDED_CHECK_WRITTENint opt_extended_check = 0; /* Extended check? */#endifint syntax_errors, consistency_errors; /* Number of errors found */#define EXPAND_DATA(str) \ if (!(str)[0] || LASTCHAR((str)) != '.') \ { \ if ((str)[0]) strncat((str), ".", sizeof((str))-strlen((str))-1); \ strncat((str), soa->origin, sizeof((str))-strlen((str))-1); \ }/************************************************************************************************** USAGE Display program usage information.**************************************************************************************************/static voidusage(int status){ if (status != EXIT_SUCCESS) { fprintf(stderr, _("Try `%s --help' for more information."), progname); fputs("\n", stderr); } else { printf(_("Usage: %s [ZONE..]"), progname); puts(""); puts(_("Check zone(s) or entire database for errors and consistency.")); puts("");/* puts("----------------------------------------------------------------------------78"); */ puts(_(" -c, --consistency do key consistency checks")); puts(_(" -C, --consistency-only do only the key consistency checks"));#ifdef EXTENDED_CHECK_WRITTEN puts(_(" -x, --extended extended check for data/name references"));#endif puts(""); puts(_(" -D, --database=DB database name to use")); puts(_(" -h, --host=HOST connect to SQL server at HOST")); puts(_(" -p, --password=PASS password for SQL server (or prompt from tty)")); puts(_(" -u, --user=USER username for SQL server if not current user")); puts("");#if DEBUG_ENABLED puts(_(" -d, --debug enable debug output"));#endif puts(_(" -v, --verbose be more verbose while running")); puts(_(" --help display this help and exit")); puts(_(" --version output version information and exit")); puts(""); printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit(status);}/*--- usage() -----------------------------------------------------------------------------------*//************************************************************************************************** CMDLINE Process command line options.**************************************************************************************************/static voidcmdline(int argc, char **argv){ char *optstr; int optc, optindex; struct option const longopts[] = { {"consistency-only", no_argument, NULL, 'C'}, {"consistency", no_argument, NULL, 'c'},#ifdef EXTENDED_CHECK_WRITTEN {"extended", no_argument, NULL, 'x'},#endif {"database", required_argument, NULL, 'D'}, {"host", required_argument, NULL, 'h'}, {"password", optional_argument, NULL, 'p'}, {"user", required_argument, NULL, 'u'}, {"debug", no_argument, NULL, 'd'}, {"verbose", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 0}, {"version", no_argument, NULL, 0}, {NULL, 0, NULL, 0} }; err_file = stdout; error_init(argv[0], LOG_USER); /* Init output routines */ optstr = getoptstr(longopts); while ((optc = getopt_long(argc, argv, optstr, longopts, &optindex)) != -1) { switch (optc) { case 0: { const char *opt = longopts[optindex].name; if (!strcmp(opt, "version")) /* --version */ { printf("%s ("PACKAGE_NAME") "PACKAGE_VERSION" ("SQL_VERSION_STR")\n", progname); puts("\n" PACKAGE_COPYRIGHT); puts(_("This is free software; see the source for copying conditions. There is NO")); puts(_("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.")); exit(EXIT_SUCCESS); } else if (!strcmp(opt, "help")) /* --help */ usage(EXIT_SUCCESS); } break; case 'C': /* -C, --consistency-only */ opt_consistency = opt_consistency_only = 1; break; case 'c': /* -c, --consistency */ opt_consistency = 1; break; case 'd': /* -d, --debug */#if DEBUG_ENABLED err_verbose = err_debug = 1;#endif break; case 'D': /* -D, --database=DB */ conf_set(&Conf, "database", optarg, 0); break; case 'h': /* -h, --host=HOST */ conf_set(&Conf, "db-host", optarg, 0); break; case 'p': /* -p, --password=PASS */ if (optarg) { conf_set(&Conf, "db-password", optarg, 0); memset(optarg, 'X', strlen(optarg)); } else conf_set(&Conf, "db-password", passinput(_("Enter password")), 0); break; case 'u': /* -u, --user=USER */ conf_set(&Conf, "db-user", optarg, 0); break; case 'v': /* -v, --verbose */ err_verbose = 1; break;#ifdef EXTENDED_CHECK_WRITTEN case 'x': /* -x, --extended */ opt_extended_check = 1; break;#endif default: usage(EXIT_FAILURE); } }}/*--- cmdline() ---------------------------------------------------------------------------------*//************************************************************************************************** RRPROBLEM Output a string describing a problem found.**************************************************************************************************/static void rrproblem(const char *fmt, ...) __printflike(1,2);static voidrrproblem(const char *fmt, ...){ va_list ap; meter(0,0); va_start(ap, fmt); vprintf(fmt, ap); /* 1. message */ va_end(ap); printf("\t"); if (soa) /* 2. soa id */ printf("%u\t", soa->id); else printf("-\t"); if (rr) /* 3. rr id */ printf("%u\t", rr->id); else printf("-\t"); printf("%s\t", *name ? name : "-"); /* 4. name */ if (soa || rr) /* 5. ttl */ printf("%u\t", rr ? rr->ttl : soa->ttl); else printf("-\t"); printf("%s\t", rr ? mydns_qtype_str(rr->type) : "-"); /* 6. rr type */ printf("%s\n", *data ? data : "-"); /* 7. data */ fflush(stdout); syntax_errors++;}/*--- rrproblem() -------------------------------------------------------------------------------*/#ifdef EXTENDED_CHECK_WRITTEN/************************************************************************************************** CHECK_NAME_EXTENDED**************************************************************************************************/static voidcheck_name_extended(const char *name_in, const char *fqdn, const char *col){ /* XXX: Add check to detect names that we should be authoritative for but that do not have records */}/*--- check_name_extended() ---------------------------------------------------------------------*/#endif/************************************************************************************************** SHORTNAME Removes the origin from a name if it is present.**************************************************************************************************/static char *shortname(char *name_to_shorten, int empty_name_is_ok){ size_t nlen = strlen(name_to_shorten), olen = strlen(soa->origin); if (nlen < olen) return (name_to_shorten); if (!strcasecmp(soa->origin, name_to_shorten)) { if (empty_name_is_ok) return (""); else return (name_to_shorten); } if (!strcasecmp(name_to_shorten + nlen - olen, soa->origin)) name[nlen - olen - 1] = '\0'; return (name_to_shorten);}/*--- shortname() -------------------------------------------------------------------------------*//************************************************************************************************** CHECK_NAME Verifies that "name" is a valid name.**************************************************************************************************/static voidcheck_name(const char *name_in, const char *col, int is_rr){ char buf[DNS_MAXNAMELEN * 2], *b, *label; char fqdn[DNS_MAXNAMELEN * 2]; strncpy(fqdn, name_in, sizeof(fqdn)-1); /* If last character isn't '.', append the origin */ if (is_rr && LASTCHAR(fqdn) != '.') strncat(fqdn, soa->origin, sizeof(fqdn) - strlen(fqdn) - 1); if (!strlen(fqdn)) return rrproblem(_("FQDN in `%s' is empty"), col); if (strlen(fqdn) > DNS_MAXNAMELEN) return rrproblem(_("FQDN in `%s' is too long"), col); /* Break into labels, verifying each */ if (strcmp(fqdn, ".")) { strncpy(buf, fqdn, sizeof(buf)-1); for (b = buf; (label = strsep(&b, ".")); ) { register int len = strlen(label); register char *cp; if (!b) /* Last label - should be the empty string */ { if (strlen(label)) rrproblem(_("Last label in `%s' not the root zone"), col); break; } if (strcmp(label, "*")) { if (len > DNS_MAXLABELLEN) rrproblem(_("Label in `%s' is too long"), col); if (len < 1) rrproblem(_("Blank label in `%s'"), col); for (cp = label; *cp; cp++) { if (*cp == '-' && cp == label) rrproblem(_("Label in `%s' begins with a hyphen"), col); if (*cp == '-' && ((cp - label) == len-1)) rrproblem(_("Label in `%s' ends with a hyphen"), col); if (!isalnum((int)(*cp)) && *cp != '-') { if (is_rr && *cp == '*') rrproblem(_("Wildcard character `%c' in `%s' not alone"), *cp, col); else rrproblem(_("Label in `%s' contains illegal character `%c'"), col, *cp); } } } else if (!is_rr) rrproblem(_("Wildcard not allowed in `%s'"), col); } }#ifdef EXTENDED_CHECK_WRITTEN /* If extended check, do extended check */ if (is_rr && opt_extended_check) check_name_extended(name_in, fqdn, col);#endif}/*--- check_name() ------------------------------------------------------------------------------*//************************************************************************************************** CHECK_SOA Perform SOA check for this zone and return the SOA record. Checks currently performed: - Make sure "ns" and "mbox" are present and valid. - Make sure none of the numeric values are unreasonable (like 0)**************************************************************************************************/static MYDNS_SOA *check_soa(const char *zone){ if (mydns_soa_load(sql, &soa, (char *)zone,0) != 0) //modi by zyl 080408 Errx("%s: %s", zone, _("error loading SOA record for zone")); if (!soa) Errx("%s: %s", zone, _("zone not found")); rr = NULL; *name = *data = '\0'; /* SOA validation */ strncpy(name, soa->origin, sizeof(name)-1); check_name(soa->ns, "soa.ns", 0); check_name(soa->mbox, "soa.mbox", 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -