📄 update.c
字号:
return 0; case DNS_QTYPE_HINFO: { char data1[DNS_MAXPACKETLEN_UDP], data2[DNS_MAXPACKETLEN_UDP], *c; int data1sp, data2sp; if (!(src = text_retrieve(src, end, data1, sizeof(data1), 1))) return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); if (!(src = text_retrieve(src, end, data2, sizeof(data2), 1))) return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); /* See if either value contains spaces, so we can enclose it with quotes */ for (c = data1, data1sp = 0; *c && !data1sp; c++) if (isspace(*c)) data1sp = 1; for (c = data2, data2sp = 0; *c && !data2sp; c++) if (isspace(*c)) data2sp = 1; snprintf(data, datalen, "%s%s%s %s%s%s", data1sp ? "\"" : "", data1, data1sp ? "\"" : "", data2sp ? "\"" : "", data2, data2sp ? "\"" : ""); } return 0; case DNS_QTYPE_MX: DNS_GET16(*aux, src); if (!(src = name_unencode(t->query, t->len, src, data, datalen))) return formerr(t, DNS_RCODE_FORMERR, (task_error_t)data[0], NULL); return 0; case DNS_QTYPE_NS: if (!(src = name_unencode(t->query, t->len, src, data, datalen))) return formerr(t, DNS_RCODE_FORMERR, (task_error_t)data[0], NULL); return 0; case DNS_QTYPE_TXT: if (!(src = text_retrieve(src, end, data, datalen, 0))) return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); return 0; case DNS_QTYPE_PTR: return dnserror(t, DNS_RCODE_SERVFAIL, ERR_UNSUPPORTED_TYPE); return 0; case DNS_QTYPE_RP: { char data1[DNS_MAXPACKETLEN_UDP], data2[DNS_MAXPACKETLEN_UDP]; if (!(src = name_unencode(t->query, t->len, src, data1, sizeof(data1)))) return formerr(t, DNS_RCODE_FORMERR, (task_error_t)data1[0], NULL); if (!(src = name_unencode(t->query, t->len, src, data2, sizeof(data2)))) return formerr(t, DNS_RCODE_FORMERR, (task_error_t)data2[0], NULL); snprintf(data, datalen, "%s %s", data1, data2); } return 0; case DNS_QTYPE_SRV: { uint16_t weight, port; char data1[DNS_MAXPACKETLEN_UDP]; DNS_GET16(*aux, src); DNS_GET16(weight, src); DNS_GET16(port, src); if (!(src = name_unencode(t->query, t->len, src, data1, sizeof(data1)))) return formerr(t, DNS_RCODE_FORMERR, (task_error_t)data1[0], NULL); snprintf(data, datalen, "%u %u %s", weight, port, data1); } return 0; default: snprintf(data, datalen, "Unknown type %s", mydns_qtype_str(rr->type)); break; } return (-1);}/*--- update_get_rr_data() ----------------------------------------------------------------------*//************************************************************************************************** UPDATE_IN_ZONE Checks to see if 'name' is within 'origin'. Returns 1 if it is, 0 if it's not.**************************************************************************************************/static intupdate_in_zone(TASK *t, char *name, char *origin){ char nbuf[DNS_MAXNAMELEN+1], obuf[DNS_MAXNAMELEN+1]; strncpy(nbuf, name, sizeof(nbuf)-1); strtolower(nbuf); strncpy(obuf, origin, sizeof(obuf)-1); strtolower(obuf); if (strlen(obuf) > strlen(nbuf)) return 0; if (strcmp(obuf, nbuf + strlen(nbuf) - strlen(obuf))) return 0; return 1;}/*--- update_in_zone() --------------------------------------------------------------------------*//************************************************************************************************** UPDATE_ZONE_HAS_NAME Check to see that there is at least one RR in the zone whose name is the same as the prerequisite RR. Returns 1 if the name exists, 0 if not, -1 on error.**************************************************************************************************/static intupdate_zone_has_name(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ SQL_RES *res = NULL; SQL_ROW row; char query[512]; size_t querylen; char *xname = NULL; int found = 0;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: update_zone_has_name: does [%s] have an RR for [%s]?", desctask(t), soa->origin, rr->name);#endif if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); querylen = snprintf(query, sizeof(query), "SELECT id FROM %s WHERE zone=%u AND name='%s' LIMIT 1", mydns_rr_table_name, soa->id, xname);#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif if (!(res = sql_query(sql, query, querylen))) { WarnSQL(sql, "%s: %s", desctask(t), _("error searching name for DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } if (sql_num_rows(res) > 0) found = 1; Free(xname); sql_free(res); return (found);}/*--- update_zone_has_name() --------------------------------------------------------------------*//************************************************************************************************** UPDATE_ZONE_HAS_RRSET Check to see that there is an RRset in the zone whose name and type are the same as the prerequisite RR. Returns 1 if the name exists, 0 if not, -1 on error.**************************************************************************************************/static intupdate_zone_has_rrset(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ SQL_RES *res = NULL; SQL_ROW row; char query[512]; size_t querylen; char *xname = NULL; int found = 0;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: update_zone_has_rrset: does [%s] have an RR for [%s] with type %s?", desctask(t), soa->origin, rr->name, mydns_qtype_str(rr->type));#endif if (!(xname = calloc(strlen(rr->name) * 2 + 1, sizeof(char)))) Err(_("out of memory")); sql_escstr(sql, xname, rr->name, strlen(rr->name)); querylen = snprintf(query, sizeof(query), "SELECT id FROM %s WHERE zone=%u AND name='%s' AND type='%s' LIMIT 1", mydns_rr_table_name, soa->id, xname, mydns_qtype_str(rr->type));#if DEBUG_UPDATE_SQL Verbose("%s: DNS UPDATE: %s", desctask(t), query);#endif if (!(res = sql_query(sql, query, querylen))) { WarnSQL(sql, "%s: %s", desctask(t), _("error searching name/type for DNS UPDATE")); return dnserror(t, DNS_RCODE_SERVFAIL, ERR_DB_ERROR); } if (sql_num_rows(res) > 0) found = 1; Free(xname); sql_free(res); return (found); return 1;}/*--- update_zone_has_rrset() -------------------------------------------------------------------*//************************************************************************************************** CHECK_PREREQUISITE Check the specified prerequisite as described in RFC 2136 3.2. Returns 0 on success, -1 on error.**************************************************************************************************/static intcheck_prerequisite(TASK *t, MYDNS_SOA *soa, UQ *q, UQRR *rr){ static char data[DNS_MAXPACKETLEN_UDP] = ""; uint32_t aux = 0; int n, rv;#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequsisite: rr->name=[%s]", desctask(t), rr->name); Debug("%s: DNS UPDATE: check_prerequsisite: rr->class=%s", desctask(t), mydns_class_str(rr->class)); Debug("%s: DNS UPDATE: check_prerequsisite: q->class=%s", desctask(t), mydns_class_str(q->class)); Debug("%s: DNS UPDATE: check_prerequsisite: rr->type=%s", desctask(t), mydns_qtype_str(rr->type)); Debug("%s: DNS UPDATE: check_prerequsisite: rr->rdlength=%u", desctask(t), rr->rdlength);#endif /* Get aux/data */ update_get_rr_data(t, soa, q, rr, data, sizeof(data), &aux); /* Ignore error */#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequsisite: aux=%u", desctask(t), aux); Debug("%s: DNS UPDATE: check_prerequsisite: data=[%s]", desctask(t), data);#endif /* TTL must be zero */ if (rr->ttl) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: TTL nonzero", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_TTL); } /* rr->name bust be in-zone */ if (!update_in_zone(t, rr->name, soa->origin)) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: name (%s) not in zone (%s)", desctask(t), rr->name, soa->origin);#endif return dnserror(t, DNS_RCODE_NOTZONE, ERR_INVALID_DATA); } /* Following pseudocode from section 3.2.5... */ if (rr->class == DNS_CLASS_ANY) { if (rr->rdlength) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: class is ANY but rdlength is nonzero", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); } if (rr->type == DNS_QTYPE_ANY) { if ((rv = update_zone_has_name(t, soa, q, rr)) != 1) { if (!rv) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: zone contains no names matching [%s]", desctask(t), rr->name);#endif return dnserror(t, DNS_RCODE_NXDOMAIN, ERR_PREREQUISITE_FAILED); } else return -1; } } else if ((rv = update_zone_has_rrset(t, soa, q, rr)) != 1) { if (!rv) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: zone contains no names matching [%s] with type %s", desctask(t), rr->name, mydns_qtype_str(rr->type));#endif return dnserror(t, DNS_RCODE_NXRRSET, ERR_PREREQUISITE_FAILED); } else return -1; } } else if (rr->class == DNS_CLASS_NONE) { if (rr->rdlength != 0) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: class is NONE but rdlength is zero", desctask(t));#endif return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); } if (rr->type == DNS_QTYPE_ANY) { if ((rv = update_zone_has_name(t, soa, q, rr)) != 0) { if (rv == 1) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: zone contains a name matching [%s]", desctask(t), rr->name);#endif return dnserror(t, DNS_RCODE_YXDOMAIN, ERR_PREREQUISITE_FAILED); } else return -1; } } else if ((rv = update_zone_has_rrset(t, soa, q, rr)) != 0) { if (rv == 1) {#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: check_prerequisite failed: zone contains a name matching [%s] with type %s", desctask(t), rr->name, mydns_qtype_str(rr->type));#endif return dnserror(t, DNS_RCODE_YXRRSET, ERR_PREREQUISITE_FAILED); } else return -1; } } else if (rr->class == q->class) { int unique; /* Is this rrset element unique? */ char data[DNS_MAXPACKETLEN_UDP + 1]; /* Parsed rrset data */ uint32_t aux = 0; /* 'aux' value for parsed data */#if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: want to add %s/%s to tmprr", desctask(t), rr->name, mydns_qtype_str(rr->type));#endif /* Get the RR data */ if (update_get_rr_data(t, soa, q, rr, data, sizeof(data)-1, &aux) < 0) return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); #if DEBUG_ENABLED && DEBUG_UPDATE Debug("%s: DNS UPDATE: for tmprr, data=[%s], aux=%u", desctask(t), data, aux);#endif /* Add this name/type to the "tmprr" list (in the UQRR struct) */ /* First, check to make sure it's unique */ for (n = 0, unique = 1; n < q->num_tmprr && unique; n++) if (q->tmprr[n]->type == rr->type && !strcasecmp(q->tmprr[n]->name, rr->name) && !strcasecmp(q->tmprr[n]->data, data) && q->tmprr[n]->aux == aux) unique = 0; if (unique) { if (!q->num_tmprr) q->tmprr = calloc(1, sizeof(TMPRR *)); else q->tmprr = realloc(q->tmprr, sizeof(TMPRR *) * (q->num_tmprr + 1)); if (!q->tmprr) Err(_("out of memory")); /* Add this stuff to the new tmprr */ if (!(q->tmprr[q->num_tmprr] = malloc(sizeof(TMPRR)))) Err(_("out of memory")); strncpy(q->tmprr[q->num_tmprr]->name, rr->name, sizeof(q->tmprr[q->num_tmprr]->name) - 1); q->tmprr[q->num_tmprr]->type = rr->type; strncpy(q->tmprr[q->num_tmprr]->data, data, sizeof(q->tmprr[q->num_tmprr]->data) - 1); q->tmprr[q->num_tmprr]->aux = aux; q->tmprr[q->num_tmprr]->checked = 0; q->num_tmprr++; } } else return dnserror(t, DNS_RCODE_FORMERR, ERR_INVALID_DATA); return 0;}/*--- check_prerequisite() ----------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -