update.c
来自「此dns服务器是在mydns基础上改写」· C语言 代码 · 共 1,538 行 · 第 1/4 页
C
1,538 行
/************************************************************************************************** UPDATE_RRTYPE_OK Is this RR type okay with MyDNS? RFC 2136 3.4.1.2 specifically prohibigs ANY, AXFR, MAILA, MAILB, or "any other QUERY metatype" or "any unrecognized type". Returns 1 if OK, 0 if not OK.**************************************************************************************************/static inline intupdate_rrtype_ok(dns_qtype_t type){ switch (type) { /* We support UPDATEs of these types: */ case DNS_QTYPE_A: case DNS_QTYPE_AAAA: case DNS_QTYPE_CNAME: case DNS_QTYPE_HINFO: case DNS_QTYPE_MX: case DNS_QTYPE_NS: case DNS_QTYPE_TXT: case DNS_QTYPE_PTR: case DNS_QTYPE_RP: case DNS_QTYPE_SRV: return 1; default: return 0; } return 0;}/*--- update_rrtype_ok() ------------------------------------------------------------------------*//************************************************************************************************** PRESCAN_UPDATE Prescan the specified update section record (RFC 2136 3.4.1). Returns 0 on success, -1 on error.**************************************************************************************************/static intprescan_update(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ /* Class must be ANY, NONE, or the same as the zone's class */ if ((rr->class != DNS_CLASS_ANY) && (rr->class != DNS_CLASS_NONE) && (rr->class != q->class)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed test 1 (check class)", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_DB_ERROR); } /* "Using the definitions in Section 1.2, each RR's NAME must be in the zone specified by the Zone Section, else signal NOTZONE to the requestor. */ /* XXX WTF? */ /* "For RRs whose CLASS is not ANY, check the TYPE and if it is ANY, AXFR, MAILA, MAILB, or any other QUERY metatype, or any unrecognized type, then signal FORMERR to the requestor. */ if ((rr->class != DNS_CLASS_ANY) && !update_rrtype_ok(rr->type)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed test 2 (check RR types)", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_TYPE); } /* "For RRs whose CLASS is ANY or NONE, check the TTL to see that it is zero (0), else signal a FORMERR to the requestor." */ if (((rr->class == DNS_CLASS_ANY) || (rr->class == DNS_CLASS_NONE)) && (rr->ttl != 0)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed test 3 (check TTL)", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_TTL); } /* "For any RR whose CLASS is ANY, check the RDLENGTH to make sure that it is zero (0) (that is, the RDATA field is empty), and that the TYPE is not AXFR, MAILA, MAILB, or any other QUERY metatype besides ANY, or any unrecognized type, else signal FORMERR to the requestor." */ if ((rr->class == DNS_CLASS_ANY) && (rr->rdlength != 0)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed test 4 (check RDLENGTH)", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); } if ((rr->class == DNS_CLASS_ANY) && (!update_rrtype_ok(rr->type) && rr->type != DNS_QTYPE_ANY)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed test 5 (rr->type is %s)", desctask(t), mydns_qtype_str(rr->type));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_TYPE); } return 0;}/*--- prescan_update() --------------------------------------------------------------------------*//************************************************************************************************** UPDATE_ADD_RR Add an RR to the zone. Returns 0 on success, -1 on failure.**************************************************************************************************/static intupdate_add_rr(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ static char data[DNS_MAXPACKETLEN_UDP]; uint32_t aux; char *xname = NULL, *xdata = NULL; SQL_RES *res = NULL; SQL_ROW row; char query[512]; size_t querylen = 0; int duplicate = 0; if (update_get_rr_data(t, soa, q, rr, data, sizeof(data), &aux) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: update_get_rr_data failed", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); }#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_ADD_RR: %s %u %s %s %u %s", desctask(t), rr->name, rr->ttl, mydns_class_str(rr->class), mydns_qtype_str(rr->type), aux, data);#endif /* Construct query */ if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); if (!(xdata = calloc(strlen(data) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xdata, data, strlen(data)); /* First we have to see if this record exists. If it does, we should "silently ignore" it. */#if USE_PGSQL /* This is only necessary for Postgres, we can use "INSERT IGNORE" with MySQL */ querylen = snprintf(query, sizeof(query), "SELECT id FROM %s WHERE zone=%u AND name='%s' AND type='%s' AND data='%s' LIMIT 1", mydns_rr_table_name, soa->id, xname, mydns_qtype_str(rr->type), xdata);#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_ADD_RR: %s", desctask(t), query);#endif if (!(res = sql_query(sql, query, querylen))) { WarnSQL(sql, "%s: %s", desctask(t), _("error searching duplicate for DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } if (sql_num_rows(res) > 0) duplicate = 1; sql_free(res);#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_ADD_RR: duplicate=%d", desctask(t), duplicate);#endif#endif if (!duplicate) { querylen = snprintf(query, sizeof(query),#if USE_PGSQL "INSERT INTO %s"#else "INSERT IGNORE INTO %s"#endif " (zone,name,type,data,aux,ttl%s)" " VALUES (%u,'%s','%s','%s',%u,%u%s%s%s)", mydns_rr_table_name, mydns_rr_use_active ? ",active" : "", soa->id, xname, mydns_qtype_str(rr->type), xdata, aux, rr->ttl, mydns_rr_use_active ? ",'" : "", mydns_rr_use_active ? "Y" : "", mydns_rr_use_active ? "'" : "" );#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif } Free(xname); Free(xdata);#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: ADD RR: %s", desctask(t), query);#endif /* Execute the query */ if (!duplicate) { if (sql_nrquery(sql, query, querylen) != 0) { WarnSQL(sql, "%s: %s", desctask(t), _("error adding RR via DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } sql_free(res); } /* Output info to verbose log */ snprintf(query, sizeof(query), "ADD %s %u IN %s %u %s", rr->name, rr->ttl, mydns_qtype_str(rr->type), aux, data); task_output_info(t, query); t->update_done++; return 0;}/*--- update_add_rr() ---------------------------------------------------------------------------*//************************************************************************************************** UPDATE_DELETE_RRSET_ALL Deletes all RRsets from the zone for a specified name. Returns 0 on success, -1 on failure.**************************************************************************************************/static intupdate_delete_rrset_all(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ char *xname = NULL, *xhost = NULL; char query[512]; size_t querylen; SQL_RES *res = NULL; SQL_ROW row;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_DELETE_RRSET_ALL: %s %u %s %s", desctask(t), rr->name, rr->ttl, mydns_class_str(rr->class), mydns_qtype_str(rr->type));#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE ALL RRSETS: %s", desctask(t), rr->name);#endif /* Delete rrset - check both the FQDN and the hostname without trailing dot */ if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); if (!(xhost = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); querylen = snprintf(query, sizeof(query), "%.*s", strlen(rr->name) - strlen(soa->origin) - 1, rr->name); sql_escstr(sql, xhost, query, querylen); querylen = snprintf(query, sizeof(query), "DELETE FROM %s WHERE zone=%u AND (name='%s' OR name='%s')", mydns_rr_table_name, soa->id, xname, xhost);#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE RRSET_ALL: %s", desctask(t), query);#endif Free(xname); Free(xhost); /* Execute the query */ if (sql_nrquery(sql, query, querylen) != 0) { WarnSQL(sql, "%s: %s", desctask(t), _("error deleting all RRsets via DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } sql_free(res); /* Output info to verbose log */ snprintf(query, sizeof(query), "DELETE_ALL_RRSET %s", rr->name); task_output_info(t, query); t->update_done++; return 0;}/*--- update_delete_rrset_all() -----------------------------------------------------------------*//************************************************************************************************** UPDATE_DELETE_RR Deletes an RR from the zone for a specified name. Returns 0 on success, -1 on failure.**************************************************************************************************/static intupdate_delete_rr(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ static char data[DNS_MAXPACKETLEN_UDP]; uint32_t aux; char *xname = NULL, *xhost = NULL, *xdata = NULL; char query[512]; size_t querylen; SQL_RES *res = NULL; SQL_ROW row;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_DELETE_RR: %s %u %s %s", desctask(t), rr->name, rr->ttl, mydns_class_str(rr->class), mydns_qtype_str(rr->type));#endif if (update_get_rr_data(t, soa, q, rr, data, sizeof(data), &aux) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: update_get_rr_data failed", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); }#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE RR: %s IN %s %s", desctask(t), rr->name, mydns_qtype_str(rr->type), data);#endif /* Delete rr - check both the FQDN and the hostname without trailing dot */ if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); if (!(xhost = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); querylen = snprintf(query, sizeof(query), "%.*s", strlen(rr->name) - strlen(soa->origin) - 1, rr->name); sql_escstr(sql, xhost, query, querylen); if (!(xdata = calloc(strlen(data) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xdata, data, strlen(data)); querylen = snprintf(query, sizeof(query), "DELETE FROM %s WHERE zone=%u AND (name='%s' OR name='%s') AND type='%s' AND data='%s'", mydns_rr_table_name, soa->id, xname, xhost, mydns_qtype_str(rr->type), xdata);#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE RR: %s", desctask(t), query);#endif Free(xname); Free(xhost); Free(xdata); /* Execute the query */ if (sql_nrquery(sql, query, querylen) != 0) { WarnSQL(sql, "%s: %s", desctask(t), _("error deleting RR via DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } sql_free(res); /* Output info to verbose log */ snprintf(query, sizeof(query), "DELETE %s IN %s %s", rr->name, mydns_qtype_str(rr->type), data); task_output_info(t, query); t->update_done++; return 0;}/*--- update_delete_rr() ------------------------------------------------------------------------*//************************************************************************************************** UPDATE_DELETE_RRSET Deletes an RRset from the zone for a specified name. Returns 0 on success, -1 on failure.**************************************************************************************************/static intupdate_delete_rrset(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ char *xname = NULL, *xhost = NULL; char query[512]; size_t querylen; SQL_RES *res = NULL; SQL_ROW row;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: UPDATE_DELETE_RRSET: %s %u %s %s", desctask(t), rr->name, rr->ttl, mydns_class_str(rr->class), mydns_qtype_str(rr->type));#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE RRSET: %s IN %s", desctask(t), rr->name, mydns_qtype_str(rr->type));#endif /* Delete rr - check both the FQDN and the hostname without trailing dot */ if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); if (!(xhost = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); querylen = snprintf(query, sizeof(query), "%.*s", strlen(rr->name) - strlen(soa->origin) - 1, rr->name); sql_escstr(sql, xhost, query, querylen);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?