📄 update.c
字号:
querylen = snprintf(query, sizeof(query), "DELETE FROM %s WHERE zone=%u AND (name='%s' OR name='%s') AND type='%s'", mydns_rr_table_name, soa->id, xname, xhost, mydns_qtype_str(rr->type));#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: DELETE RRSET: %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 RRset 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", rr->name, mydns_qtype_str(rr->type)); task_output_info(t, query); t->update_done++; return 0;}/*--- update_delete_rr() ------------------------------------------------------------------------*//************************************************************************************************** PROCESS_UPDATE Perform the requested update. Returns 0 on success, -1 on failure.**************************************************************************************************/static intprocess_update(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: process_update: q->name=[%s], q->type=%s, q->class=%s", desctask(t), q->name, mydns_qtype_str(q->type), mydns_class_str(q->class)); Debug("%s: DNS UPDATE: process_update: rr->name=[%s], rr->type=%s, rr->class=%s", desctask(t), rr->name, mydns_qtype_str(rr->type), mydns_class_str(rr->class));#endif /* 2.5.1: Add to an RRset */ if (rr->class == q->class) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: 2.5.1: Add to an RRset", desctask(t));#endif return update_add_rr(t, soa, q, rr); } /* 2.5.2: Delete an RRset */ if (rr->type != DNS_CLASS_ANY && !rr->rdlength) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: 2.5.2: Delete an RRset", desctask(t));#endif return update_delete_rrset(t, soa, q, rr); } /* 2.5.3: Delete all RRsets from a name */ if (rr->type == DNS_CLASS_ANY && !rr->rdlength) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: 2.5.3: Delete all RRsets from a name", desctask(t));#endif return update_delete_rrset_all(t, soa, q, rr); } /* 2.5.4: Delete an RR from an RRset */ if (rr->type != DNS_CLASS_ANY && rr->rdlength) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: 2.5.4: Delete an RR from an RRset", desctask(t));#endif return update_delete_rr(t, soa, q, rr); }#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: process_update: no action", desctask(t));#endif return 0;}/*--- process_update() --------------------------------------------------------------------------*//************************************************************************************************** CHECK_TMPRR Check the set of RRs described in q->tmprr -- each RRset must match exactly what's in the database, else we send NXRRSET. AN "RRset" is described as an unique <NAME,TYPE>. Returns 0 on success, -1 on error. RFC 2136, 3.2.3 says: ...build an RRset for each unique <NAME,TYPE> and compare each resulting RRset for set equality (same members, no more, no less) with RRsets in the zone. If any Prerequisite RRset is not entirely and exactly matched by a zone RRset, signal NXRRSET to the requestor. If any RR in this section has a CLASS other than ZCLASS or NONE or ANY, signal FORMERR to the requestor. The temporary prerequisite RRsets are stored in q->tmprr (the count in q->num_tmprr). The algorithm used here is to loop through q->tmprr. The <NAME,TYPE> is inspected, and each RR with that <NAME,TYPE> is marked as 'tmprr->checked=1'. We then examine each <NAME,TYPE> of that sort in q->tmprr. Then, if any members of that <NAME,TYPE> are not matched, or if the count of records of that <NAME,TYPE> in the database does not match the number of records of that <NAME,TYPE> in q->tmprr, we return NXRRSET. The RFC isn't totally clear on AUX values, so I'm only checking AUX values on RR types where they ought to be relevant (currently MX and SRV).**************************************************************************************************/static intcheck_tmprr(TASK *t, MYDNS_SOA *soa, UQ *q){ int n, i;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Checking prerequisite RRsets for exact match", desctask(t));#endif /* Examine "tmprr" */ for (n = 0; n < q->num_tmprr; n++) { TMPRR *tmprr = q->tmprr[n]; char *current_name = tmprr->name; /* Current NAME being examined */ dns_qtype_t current_type = tmprr->type; /* Current TYPE being examined */ MYDNS_RR *rr_first = NULL; /* RRs for the current name/type */ MYDNS_RR *rr; /* Current RR */ int total_prereq_rr = 0, total_db_rr = 0; /* Total RRs in prereq and database */ if (tmprr->checked) /* Ignore if already checked */ {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Skipping prerequisite RRsets for %s/%s (already checked)", desctask(t), current_name, mydns_qtype_str(current_type));#endif continue; }#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Checking prerequisite RRsets for %s/%s", desctask(t), current_name, mydns_qtype_str(current_type));#endif /* Load all RRs for this name/type */ if (mydns_rr_load(sql, &rr_first, soa->id, current_type, current_name, NULL, "") != 0) { sql_reopen(); if (mydns_rr_load(sql, &rr_first, soa->id, current_type, current_name, NULL, "") != 0) { WarnSQL(sql, _("error finding %s type resource records for name `%s' in zone %u"), mydns_qtype_str(current_type), current_name, soa->id); sql_reopen(); return dnserror(t, DNS_RCODE_FORMERR, ERR_DB_ERROR); } } /* If no RRs were found, return NXRRSET */ if (!rr_first) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Found prerequisite RRsets for %s/%s, but none in database (NXRRSET)", desctask(t), current_name, mydns_qtype_str(current_type));#endif return dnserror(t, DNS_RCODE_NXRRSET, ERR_PREREQUISITE_FAILED); } /* Count the total number of RRs found in database */ for (rr = rr_first; rr; rr = rr->next) total_db_rr++;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Found %d database RRsets for %s/%s", desctask(t), total_db_rr, current_name, mydns_qtype_str(current_type));#endif /* Mark all <NAME,TYPE> matches in tmprr with checked=1, and count the number of RRs */ for (i = 0; i < q->num_tmprr; i++) if (q->tmprr[i]->type == current_type && !strcasecmp(q->tmprr[i]->name, current_name)) { q->tmprr[i]->checked = 1; total_prereq_rr++; }#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Found %d prerequisite RRsets for %s/%s", desctask(t), total_prereq_rr, current_name, mydns_qtype_str(current_type));#endif /* If total_db_rr doesn't equal total_prereq_rr, return NXRRSET */ if (total_db_rr != total_prereq_rr) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Found %d prerequisite RRsets for %s/%s, but %d in database (NXRRSET)", desctask(t), total_prereq_rr, current_name, mydns_qtype_str(current_type), total_db_rr);#endif mydns_rr_free(rr_first); return dnserror(t, DNS_RCODE_NXRRSET, ERR_PREREQUISITE_FAILED); } /* Also, for each matching <NAME,TYPE>, check to see if the record exists in the database. If it does, set matched=1. If it does not, return NXRRSET */ for (i = 0; i < q->num_tmprr; i++) if (q->tmprr[i]->type == current_type && !strcasecmp(q->tmprr[i]->name, current_name)) { int found_match = 0; /* Did we find a match for this RR? */#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: looking for tmprr[%d] = %s/%s/%u/%s in database", desctask(t), i, q->tmprr[i]->name, mydns_qtype_str(q->tmprr[i]->type), q->tmprr[i]->aux, q->tmprr[i]->data);#endif for (rr = rr_first; rr && !found_match; rr = rr->next) { /* See if the DATA (and possibly the AUX) matches */ if (!strcasecmp(rr->data, q->tmprr[i]->data)) { if (current_type == DNS_QTYPE_MX || current_type == DNS_QTYPE_SRV) { if (q->tmprr[i]->aux == rr->aux) found_match = 1; } else found_match = 1; } } /* No match found - return NXRRSET */ if (!found_match) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: No match for prerequisite %s/%s/%u/%s (NXRRSET)", desctask(t), q->tmprr[i]->name, mydns_qtype_str(q->tmprr[i]->type), q->tmprr[i]->aux, q->tmprr[i]->data);#endif mydns_rr_free(rr_first); return dnserror(t, DNS_RCODE_NXRRSET, ERR_PREREQUISITE_FAILED); } } mydns_rr_free(rr_first); } return 0;}/*--- check_tmprr() -----------------------------------------------------------------------------*//************************************************************************************************** DNS_UPDATE Process a DNS UPDATE query.**************************************************************************************************/intdns_update(TASK *t){ MYDNS_SOA *soa; /* SOA record for zone */ UQ *q; /* Update query data */ int n; /*add by zyl 20080331 --begin*/ char* myip = (char*)malloc(16); memset(myip,0,sizeof(myip)); iplong_to_ipchs(myip, 16, t->addr4.sin_addr.s_addr); /*add by zyl 20080331 --end*/ /*add by zyl 20080408 --begin*/ int telecom_operator = 0; int ipint = 0; ipchs_to_ipuint32(&ipint,myip); if(ipint) get_telecom_operator(&telecom_operator,ipint); /*add by zyl 20080408 --end*/ free(myip); /* Try to load SOA for zone */ if (mydns_soa_load(sql, &soa, t->qname,telecom_operator) < 0) //modi by zyl 080408 return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); /* If there's no such zone, say REFUSED rather than NOTAUTH, to prevent "zone mining" */ if (!soa) return dnserror(t, DNS_RCODE_REFUSED, ERR_ZONE_NOT_FOUND);#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: SOA id %u", desctask(t), soa->id); Debug("%s: DNS UPDATE: ZOCOUNT=%d (Zone)", desctask(t), t->qdcount); Debug("%s: DNS UPDATE: PRCOUNT=%d (Prerequisite)", desctask(t), t->ancount); Debug("%s: DNS UPDATE: UPCOUNT=%d (Update)", desctask(t), t->nscount); Debug("%s: DNS UPDATE: ADCOUNT=%d (Additional data)", desctask(t), t->arcount);#endif /* Check the optional 'update' column if it exists */ if (check_update(t, soa) != 0) return -1; /* Parse the update query */ if (!(q = calloc(1, sizeof(UQ)))) Err(_("out of memory")); if (parse_update_query(t, soa, q) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: parse_update_query failed", desctask(t));#endif goto dns_update_error; } /* Check the prerequsites as described in RFC 2136 3.2 */ for (n = 0; n < q->numPR; n++) if (check_prerequisite(t, soa, q, &q->PR[n]) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed", desctask(t));#endif goto dns_update_error; } /* Check the prerequisite RRsets -- RFC 2136 3.2.3 */ if (check_tmprr(t, soa, q) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_tmprr failed", desctask(t));#endif goto dns_update_error; } /* Prescan the update section (RFC 2136 3.4.1) */ for (n = 0; n < q->numUP; n++) if (prescan_update(t, soa, q, &q->UP[n]) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: prescan_update failed", desctask(t));#endif goto dns_update_error; } /* Process the update section (RFC 2136 3.4.2) */ if (update_transaction(t, "BEGIN") != 0) /* Start transaction */ goto dns_update_error; for (n = 0; n < q->numUP; n++) { if (process_update(t, soa, q, &q->UP[n]) != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: process_update failed", desctask(t));#endif if (update_transaction(t, "ROLLBACK") != 0) /* Rollback transaction */ goto dns_update_error; goto dns_update_error; } } if (update_transaction(t, "COMMIT") != 0) /* Commit changes */ goto dns_update_error; if (t->update_done) t->info_already_out = 1; /* Purge the cache for this zone */ cache_purge_zone(ZoneCache, soa->id);#if USE_NEGATIVE_CACHE cache_purge_zone(NegativeCache, soa->id);#endif cache_purge_zone(ReplyCache, soa->id); /* Construct reply and set task status */ build_reply(t, 0); t->status = NEED_WRITE; /* Clean up and return */ free_uq(q); mydns_soa_free(soa); return 0;dns_update_error: build_reply(t, 1);#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: Went to dns_update_error", desctask(t));#endif free_uq(q); mydns_soa_free(soa); return -1;}/*--- dns_update() ------------------------------------------------------------------------------*//* vi:set ts=3: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -