📄 check.c
字号:
if (LASTCHAR(name) != '.') rrproblem(_("soa.origin is not a FQDN (no trailing dot)")); if (soa->refresh < 300) rrproblem(_("soa.refresh is less than 300 seconds")); if (soa->retry < 300) rrproblem(_("soa.retry is less than 300 seconds")); if (soa->expire < 300) rrproblem(_("soa.expire is less than 300 seconds")); if (soa->minimum < 300) rrproblem(_("soa.minimum is less than 300 seconds")); if (soa->ttl < 300) rrproblem(_("soa.ttl is less than 300 seconds")); if (soa->minimum < 300) rrproblem(_("soa.minimum is less than 300 seconds")); return (soa);}/*--- check_soa() -------------------------------------------------------------------------------*//************************************************************************************************** CHECK_RR_CNAME Expanded check for CNAME resource record.**************************************************************************************************/static voidcheck_rr_cname(void){ unsigned char *xname; int found = 0; EXPAND_DATA(data); check_name(data, "rr.data", 1); /* A CNAME record can't have any other type of RR data for the same name */ if (!(xname = calloc(strlen(name) * 2 + 1, sizeof(unsigned char)))) Err(_("out of memory")); sql_escstr(sql, xname, (unsigned char *)name, strlen(name)); found = sql_count(sql, "SELECT COUNT(*) FROM %s WHERE zone=%u AND name='%s' AND type != 'CNAME'", mydns_rr_table_name, rr->zone, xname); /* If not found that way, check short name */ if (!found) { Free(xname); shortname(name, 1); if (!(xname = calloc(strlen(name) * 2 + 1, sizeof(unsigned char)))) Err(_("out of memory")); sql_escstr(sql, xname, (unsigned char *)name, strlen(name)); found = sql_count(sql, "SELECT COUNT(*) FROM %s WHERE zone=%u AND name='%s' AND type != 'CNAME'", mydns_rr_table_name, rr->zone, xname); EXPAND_DATA(name); } if (found) rrproblem(_("non-CNAME record(s) present alongside CNAME")); Free(xname);}/*--- check_rr_cname() --------------------------------------------------------------------------*//************************************************************************************************** CHECK_RR_HINFO Expanded check for HINFO resource record.**************************************************************************************************/static voidcheck_rr_hinfo(void){ char os[DNS_MAXNAMELEN + 1] = "", cpu[DNS_MAXNAMELEN + 1] = ""; if (hinfo_parse(rr->data, cpu, os, DNS_MAXNAMELEN) < 0) rrproblem(_("data too long in HINFO record"));}/*--- check_rr_hinfo() --------------------------------------------------------------------------*//************************************************************************************************** CHECK_RR_NAPTR Expanded check for NAPTR resource record.**************************************************************************************************/static voidcheck_rr_naptr(void){ char tmp[DNS_MAXNAMELEN * 2 + 2], data_copy[DNS_MAXNAMELEN * 2 + 2], *p; strncpy(data_copy, rr->data, sizeof(data_copy) - 1); p = data_copy; if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'order' field missing from NAPTR record")); if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'preference' field missing from NAPTR record")); if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'flags' field missing from NAPTR record")); if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'service' field missing from NAPTR record")); if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'regexp' field missing from NAPTR record")); if (!strsep_quotes(&p, tmp, sizeof(tmp))) return rrproblem(_("'replacement' field missing from NAPTR record")); /* For now, don't check 'replacement'.. the example in the RFC even contains illegal chars */ /* EXPAND_DATA(tmp); */ /* check_name(tmp, "replacement", 1); */}/*--- check_rr_naptr() --------------------------------------------------------------------------*//************************************************************************************************** CHECK_RR Check an individual resource record.**************************************************************************************************/static voidcheck_rr(void){ /* Expand RR's name into `name' */ strncpy(name, rr->name, sizeof(name)-1); strncpy(data, rr->data, sizeof(data)-1); EXPAND_DATA(name); check_name(name, "rr.name", 1); if (!ignore_minimum && (rr->ttl < soa->minimum)) rrproblem(_("TTL below zone minimum")); switch (rr->type) { case DNS_QTYPE_A: /* Data: IPv4 address */ { struct in_addr addr;#if ALIAS_ENABLED if (rr->alias == 1) check_rr_cname(); else {#endif /* ALIAS_ENABLED */ if (inet_pton(AF_INET, data, (void *)&addr) <= 0) rrproblem(_("IPv4 address in `data' is invalid"));#if ALIAS_ENABLED }#endif /* ALIAS_ENABLED */ } break; case DNS_QTYPE_AAAA: /* Data: IPv6 address */ { uint8_t addr[16]; if (inet_pton(AF_INET6, data, (void *)&addr) <= 0) rrproblem(_("IPv6 address in `data' is invalid")); } break; case DNS_QTYPE_CNAME: /* Data: Name */ check_rr_cname(); break; case DNS_QTYPE_HINFO: /* Data: Host info */ check_rr_hinfo(); break; case DNS_QTYPE_MX: /* Data: Name */ EXPAND_DATA(data); check_name(data, "rr.data", 1); break; case DNS_QTYPE_NAPTR: /* Data: Multiple fields */ check_rr_naptr(); break; case DNS_QTYPE_NS: /* Data: Name */ EXPAND_DATA(data); check_name(data, "rr.data", 1); break; case DNS_QTYPE_PTR: /* Data: PTR */ /* TODO */ break; case DNS_QTYPE_RP: /* Data: Responsible person */ { char txt[DNS_MAXNAMELEN*2]; strncpy(txt, rr->rp_txt, sizeof(txt)-1); EXPAND_DATA(txt); check_name(data, "rr.data (mbox)", 1); check_name(txt, "rr.data (txt)", 1); } break; case DNS_QTYPE_SRV: /* Data: Server location */ /* TODO */ break; case DNS_QTYPE_TXT: /* Data: Undefined text string */ /* Can be anything, so consider it always OK */ break; default: rrproblem(_("Unknown/unsupported resource record type")); break; }}/*--- check_rr() --------------------------------------------------------------------------------*/ /************************************************************************************************** CHECK_ZONE Checks each RR in the current zone through check_rr.**************************************************************************************************/static voidcheck_zone(void){ char query[BUFSIZ]; size_t querylen; unsigned int rrct = 0; SQL_RES *res; SQL_ROW row; querylen = snprintf(query, sizeof(query), "SELECT "MYDNS_RR_FIELDS" FROM %s WHERE zone=%u", mydns_rr_table_name, soa->id); if (!(res = sql_query(sql, query, querylen))) return; while ((row = sql_getrow(res))) { if (!(rr = mydns_rr_parse(row, soa->origin))) continue; check_rr(); mydns_rr_free(rr); rrct++; } sql_free(res); if (err_verbose) { meter(0, 0); Verbose("%s: %u %s", soa->origin, rrct, rrct == 1 ? _("resource record") : _("resource records")); }}/*--- check_zone() ------------------------------------------------------------------------------*//************************************************************************************************** CONSISTENCY_RR_ZONE Makes sure rr.zone matches a soa.id.**************************************************************************************************/static voidconsistency_rr_zone(void){ char query[BUFSIZ]; size_t querylen; SQL_RES *res; SQL_ROW row; querylen = snprintf(query, sizeof(query), "SELECT %s.id,%s.zone FROM %s LEFT JOIN %s ON %s.zone=%s.id WHERE %s.id IS NULL", mydns_rr_table_name, mydns_rr_table_name, mydns_rr_table_name, mydns_soa_table_name, mydns_rr_table_name, mydns_soa_table_name, mydns_soa_table_name); if (!(res = sql_query(sql, query, querylen))) return; while ((row = sql_getrow(res))) { char msg[80]; meter(0,0); snprintf(msg, sizeof(msg), _("%s id %s references invalid %s id %s"), mydns_rr_table_name, row[0], mydns_soa_table_name, row[1]); printf("%s\t-\t%s\t-\t-\t-\t-\t-\n", msg, row[0]); fflush(stdout); consistency_errors++; } sql_free(res);}/*--- consistency_rr_zone() ---------------------------------------------------------------------*//************************************************************************************************** CONSISTENCY_CHECK Does a general database consistency check - makes sure all keys are kosher.**************************************************************************************************/static voidconsistency_check(void){ consistency_rr_zone();}/*--- consistency_check() -----------------------------------------------------------------------*//************************************************************************************************** MAIN**************************************************************************************************/intmain(int argc, char **argv){ setlocale(LC_ALL, ""); /* Internationalization */ bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); cmdline(argc, argv); load_config(); ignore_minimum = GETBOOL(conf_get(&Conf, "ignore-minimum", NULL)); db_connect(); if (!opt_consistency_only) { if (optind >= argc) /* Check all zones */ { char query[BUFSIZ]; size_t querylen; SQL_RES *res; SQL_ROW row; unsigned long current = 0, total; querylen = snprintf(query, sizeof(query), "SELECT origin FROM %s", mydns_soa_table_name); if ((res = sql_query(sql, query, querylen))) { total = sql_num_rows(res); while ((row = sql_getrow(res))) { meter(current++, total); if ((soa = check_soa(row[0]))) { check_zone(); mydns_soa_free(soa); } } sql_free(res); } } else while (optind < argc) /* Check zones provided as args */ { char zone[DNS_MAXNAMELEN+2]; strncpy(zone, argv[optind++], sizeof(zone)-2); if (LASTCHAR(zone) != '.') strcat(zone, "."); if ((soa = check_soa(zone))) { check_zone(); mydns_soa_free(soa); } } } if (opt_consistency) consistency_check(); /* Do consistency check if requested */ meter(0, 0); if (!syntax_errors && !consistency_errors) Verbose(_("No errors")); else { if (opt_consistency_only) Verbose("%s: %d", _("Consistency errors"), consistency_errors); else if (opt_consistency) Verbose("%s: %d %s: %d", _("Syntax errors"), syntax_errors, _("Consistency errors"), consistency_errors); else Verbose("%s: %d", _("Syntax errors"), syntax_errors); } return (0);}/*--- main() ------------------------------------------------------------------------------------*//* vi:set ts=3: *//* NEED_PO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -