📄 ns_resp.c
字号:
return (-1); } cp += n; cp1 = data + (n = strlen((char *)data) + 1); n1 = sizeof(data) - n; if (type == T_SOA) n1 -= 5 * sizeof(u_int32_t); if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, cp1, n1)) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 += strlen((char *)cp1) + 1; if (type == T_SOA) { bcopy(cp, cp1, n = 5 * sizeof(u_int32_t)); cp += n; cp1 += n; } n = cp1 - data; cp1 = data; break; case T_MX: case T_AFSDB: /* grab preference */ bcopy(cp, data, sizeof(u_int16_t)); cp1 = data + sizeof(u_int16_t); cp += sizeof(u_int16_t); /* get name */ if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, cp1, sizeof(data) - sizeof(u_int16_t))) < 0) { hp->rcode = FORMERR; return(-1); } cp += n; /* compute end of data */ cp1 += strlen((char *)cp1) + 1; /* compute size of data */ n = cp1 - data; cp1 = data; break; default: dprintf(3, (ddt, "unknown type %d\n", type)); return ((cp - rrp) + dlen); } if (n > MAXDATA) { dprintf(1, (ddt, "update type %d: %d bytes is too much data\n", type, n)); hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */ return(-1); }#ifdef ALLOW_UPDATES /* * If this is a dynamic update request, process it specially; else, * execute normal update code. */ switch(hp->opcode) { /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */ case UPDATEM: case UPDATEMA: /* * The named code for UPDATED and UPDATEDA is the same except that for * UPDATEDA we we ignore any data that was passed: we just delete all * RRs whose name, type, and class matches */ case UPDATED: case UPDATEDA: if (type == T_SOA) { /* Not allowed */ dprintf(1, (ddt, "UDPATE: REFUSED - SOA delete\n")); hp->rcode = REFUSED; return(-1); } /* * Don't check message length if doing UPDATEM/UPDATEMA, * since the whole message wont have been demarshalled until * we reach the code for UPDATEA */ if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) { if (cp != (u_char *)(msg + msglen)) { dprintf(1, (ddt, "FORMERR UPDATE message length off\n" ) ); hp->rcode = FORMERR; return(-1); } } if ((zonenum = findzone(dname, class)) == 0) { hp->rcode = NXDOMAIN; return(-1); } if (zones[zonenum].z_state & Z_DYNADDONLY) { hp->rcode = NXDOMAIN; return(-1); } if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) { /* Make a dp for use in db_update, as old dp */ dp = savedata(class, type, 0, cp1, n); dp->d_zone = zonenum;#ifdef CRED dp->d_cred = cred; dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE, hashtab); if (n != OK) { dprintf(1, (ddt, "UPDATE: db_update failed\n")); free((char*) dp); hp->rcode = NOCHANGE; return(-1); } } else { /* UPDATEDA or UPDATEMA */ int DeletedOne = 0; /* Make a dp for use in db_update, as old dp */ dp = savedata(class, type, 0, NULL, 0); dp->d_zone = zonenum;#ifdef CRED dp->d_cred = cred; dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif do { /* Loop and delete all matching RR(s) */ n = db_update(dname, dp, NULL, DB_DELETE, hashtab); if (n != OK) break; DeletedOne++; } while (1); free((char*) dp); /* Ok for UPDATEMA not to have deleted any RRs */ if (!DeletedOne && hp->opcode == UPDATEDA) { dprintf(1, (ddt, "UPDATE: db_update failed\n")); hp->rcode = NOCHANGE; return(-1); } } if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) return (cp - rrp);; /* * Else unmarshal the RR to be added and continue on to * UPDATEA code for UPDATEM/UPDATEMA */ if ((n = dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) { dprintf(1, (ddt, "FORMERR UPDATE expand name failed\n")); hp->rcode = FORMERR; return(-1); } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); GETSHORT(n, cp); cp1 = cp;/**** XXX - need bounds checking here ****/ cp += n; case UPDATEA: if (n > MAXDATA) { dprintf(1, (ddt, "UPDATE: too much data\n")); hp->rcode = NOCHANGE; return(-1); } if (cp != (u_char *)(msg + msglen)) { dprintf(1, (ddt, "FORMERR UPDATE message length off\n")); hp->rcode = FORMERR; return(-1); } if ((zonenum = findzone(dname, class)) == 0) { hp->rcode = NXDOMAIN; return(-1); } if (zones[zonenum].z_state & Z_DYNADDONLY) { struct hashbuf *htp = hashtab; char *fname; if (nlookup(dname, &htp, &fname, 0) && !strcmp(dname, fname)) { dprintf(1, (ddt, "refusing add of existing name\n" )); hp->rcode = REFUSED; return(-1); } } dp = savedata(class, type, ttl, cp1, n); dp->d_zone = zonenum;#ifdef CRED dp->d_cred = cred; dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif if ((n = db_update(dname, NULL, dp, DB_NODATA, hashtab)) != OK) { dprintf(1, (ddt, "UPDATE: db_update failed\n")); hp->rcode = NOCHANGE; free((char*) dp); /* vix@dec mar92 */ return (-1); } else return (cp - rrp); }#endif /* ALLOW_UPDATES */ if (zone == 0) ttl += tt.tv_sec;#if defined(TRACEROOT) || defined(BOGUSNS) /* * This is a variation on a theme which was posted by * pma@cnd.hp.com. It not only records who is giving out * bogus root NS records, it also prevents them from * polluting our cache. */ if ((type == T_NS) && (savens != NULL)) { char qname[MAXDNAME], *temp; int bogus = 0, qn;#ifdef BOGUSNS if (net_on_netlist(from_addr.sin_addr, boglist)) bogus++;#endif if (!bogus && ((temp = strrchr((char *)data, '.')) != NULL) && !strcasecmp(temp, ".arpa") ) bogus++; qname[0] = qname[1] = '\0'; qn = dn_expand((u_char *)msg, (u_char *)msg + msglen, (u_char *)msg + sizeof(HEADER), (u_char *)qname, sizeof(qname)); if (qn < 0) qname[0] = '?'; else if (qname[0] == '\0') qname[0] = '.'; if (bogus && ((dname[0] == '\0') && (zone == 0))) {/* We want the filtering but not (normally) the syslogging, since we are occasionally plagued with multi-megabyte floods of syslog messages. syslog call therefore replaced with dprintf call.*/ dprintf(1, (ddt, "Bogus root NS %s received from %s on query on name [%s] -- rejected\n", data, inet_ntoa(from_addr.sin_addr), qname)); return(cp - rrp); } }#endif /*TRACEROOT || BOGUSNS*/ dp = savedata(class, type, ttl, cp1, n); dp->d_zone = zone;#ifdef CRED dp->d_cred = cred; dp->d_clev = 0; /* We trust what is on disk more, except root servers */#endif if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) {#ifdef DEBUG if (debug && (n != DATAEXISTS)) fprintf(ddt,"update failed (%d)\n", n); else if (debug >= 3) fprintf(ddt,"update failed (DATAEXISTS)\n");#endif free((char *)dp); } else if (type == T_NS && savens != NULL) *savens = dp; return (cp - rrp);}intsend_msg(msg, msglen, qp) char *msg; int msglen; struct qinfo *qp;{#ifdef DEBUG struct qinfo *tqp;#endif /* DEBUG */ if (qp->q_flags & Q_SYSTEM) return(1);#ifdef DEBUG if (debug) { fprintf(ddt,"send_msg -> [%s] (%s %d %d) id=%d\n", inet_ntoa(qp->q_from.sin_addr), qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP", qp->q_stream == QSTREAM_NULL ? qp->q_dfd : qp->q_stream->s_rfd, ntohs(qp->q_from.sin_port), ntohs(qp->q_id)); } if (debug>4) for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) { fprintf(ddt, "qp %x q_id: %d q_nsid: %d q_msglen: %d ", tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen); fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr, tqp->q_curaddr); fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next, qp->q_link); } if (debug >= 10) fp_query(msg, ddt);#endif /* DEBUG */ if (qp->q_stream == QSTREAM_NULL) { if (sendto(qp->q_dfd, msg, msglen, 0, (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) { dprintf(1, (ddt, "sendto error errno= %d\n",errno)); return(1); } stats[S_OUTPKTS].cnt++; } else { (void) writemsg(qp->q_stream->s_rfd, (u_char*)msg, msglen); sq_done(qp->q_stream); } return 0;}#ifdef notdef/* i don't quite understand this but the only ref to it is notdef'd --vix */prime(class, type, oqp) int class, type; register struct qinfo *oqp;{ char dname[BUFSIZ]; if (oqp->q_msg == NULL) return; if (dn_expand((u_char *)oqp->q_msg, (u_char *)oqp->q_msg + oqp->q_msglen, (u_char *)oqp->q_msg + sizeof(HEADER), (u_char *)dname, sizeof(dname)) < 0) return; dprintf(2, (ddt, "prime: %s\n", dname)); (void) sysquery(dname, class, type, NULL, 0);}#endifvoidprime_cache(){ register struct qinfo *qp; dprintf(1, (ddt, "prime_cache: priming = %d\n", priming)); stats[S_PRIMECACHE].cnt++; if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) { priming++; if ((qp = sysquery("", C_IN, T_NS, NULL, 0)) == NULL) priming = 0; else qp->q_flags |= (Q_SYSTEM | Q_PRIMING); } needs_prime_cache = 0; return;}struct qinfo *sysquery(dname, class, type, nss, nsc) char *dname; int class, type; struct in_addr *nss; int nsc;{ register struct qinfo *qp, *oqp; register HEADER *hp; struct namebuf *np; struct databuf *nsp[NSMAX]; struct hashbuf *htp; char *fname; int count;#ifdef DATUMREFCNT nsp[0] = NULL;#endif dprintf(3, (ddt, "sysquery(%s, %d, %d, 0x%x, %d)\n", dname, class, type, nss, nsc)); stats[S_SYSQUERIES].cnt++; qp = qnew(); if (nss && nsc) { } else { htp = hashtab; if (priming && dname[0] == '\0') { np = NULL; } else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) { dprintf(1, (ddt, "sysquery: nlookup error on %s?\n", dname)); qfree(qp); return 0; } switch (findns(&np, class, nsp, &count, 0)) { case NXDOMAIN: case SERVFAIL: dprintf(1, (ddt, "sysquery: findns error on %s?\n", dname)); qfree(qp);#ifdef DATUMREFCNT free_nsp(nsp);#endif return(0); } } /* build new qinfo struct */ qp->q_cmsg = qp->q_msg = NULL; qp->q_dfd = ds; if (nss && nsc) qp->q_fwd = NULL; else qp->q_fwd = fwdtab; qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; qp->q_flags |= Q_SYSTEM; if ((qp->q_msg = malloc(BUFSIZ)) == NULL) { qfree(qp);#ifdef DATUMREFCNT free_nsp(nsp);#endif return(0); } qp->q_msglen = res_mkquery(QUERY, dname, class, type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ); hp = (HEADER *) qp->q_msg; hp->id = qp->q_nsid = htons((u_int16_t)++nsid); hp->rd = (qp->q_fwd ? 1 : 0); /* First check for an already pending query for this data */ for (oqp = qhead; oqp != QINFO_NULL; oqp = oqp->q_link) { if ((oqp != qp) && (oqp->q_msglen == qp->q_msglen) && bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0 ) { dprintf(3, (ddt, "sysquery: duplicate\n")); qfree(qp);#ifdef DATUMREFCNT free_nsp(nsp);#endif return(0); } } if (nss && nsc) { int i; struct qserv *qs; for (i = 0, qs = qp->q_addr; i < nsc; i++, qs++) { qs->ns_addr.sin_family = AF_INET; qs->ns_addr.sin_addr = nss[i]; qs->ns_addr.sin_port = ns_port; qs->ns = NULL; qs->nsdata = NULL; qs->stime = tt; qs->nretry = 0; } qp->q_naddr = nsc; } else { if ((count = nslookup(nsp, qp, dname, "sysquery")) <= 0) { if (count < 0) { dprintf(1, (ddt, "sysquery: nslookup reports danger\n")); } else { dprintf(1, (ddt, "sysquery: no addrs found for NS's\n")); } qfree(qp);#ifdef DATUMREFCNT free_nsp(nsp);#endif return(0); } } schedretry(qp, retrytime(qp)); if (qp->q_fwd == NULL) qp->q_addr[0].stime = tt; /* XXX - why not every? */ dprintf(1, (ddt, "sysquery: send -> [%s].%d dfd=%d, nsid=%d id=%d %dms\n", inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr), ntohs(Q_NEXTADDR(qp,0)->sin_port), qp->q_dfd, ntohs(qp->q_nsid), ntohs(qp->q_id), (qp->q_addr[0].nsdata != NULL) ? qp->q_addr[0].nsdata->d_nstime : (-1)));#ifdef DEBUG if (debug >= 10) fp_query(qp->q_msg, ddt);#endif if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,0), sizeof(struct sockaddr_in)) < 0) { /* XXX - syslog or put in stats or something */ dprintf(1, (ddt, "sendto error (%s)\n", strerror(errno))); } stats[S_OUTPKTS].cnt++;#ifdef DATUMREFCNT free_nsp(nsp);#endif return(qp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -