ns_req.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,919 行 · 第 1/3 页
C
1,919 行
case FW_NOSERVER: if(np) np = np->n_parent; if(findns_count > 50) { needreload = 1;#ifdef DEBUG if (debug) fprintf(ddt,"ns_req:TOO many findns calls.\n");#endif syslog(LOG_ERR, "ns_req:TOO many findns calls. Auto HUP begins."); return; } goto fetchns; /* Try again. */ case FW_SERVFAIL: hp->rcode = SERVFAIL; goto finish; } /* Now is a safe time for housekeeping */ if (needs_prime_cache) prime_cache(); return; case IQUERY: { register struct invbuf *ip; register int i; int dlen, alen;/* PACKETSZ below was changed to BUFSIZ. This could affect transfers through gateways. Fix the problem with TCP and malloc. */ char anbuf[BUFSIZ], *data;#ifdef STATS stats[S_IQUERIES].cnt++;#endif hp->ancount = htons(hp->ancount); if (hp->ancount != 1 || hp->qdcount || hp->nscount || hp->arcount) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR IQuery header counts wrong\n");#endif hp->qdcount = 0; hp->ancount = 0; hp->nscount = 0; hp->arcount = 0; hp->rcode = FORMERR; goto finish; } /* * Skip domain name, get class, and type. */ if ((n = dn_skipname(cp, eom)) < 0) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR IQuery packet name problem\n");#endif hp->rcode = FORMERR; goto finish; } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); cp += sizeof(u_long); GETSHORT(dlen, cp); cp += dlen; if (cp != eom) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR IQuery message length off\n");#endif hp->rcode = FORMERR; goto finish; } /* not all inverse queries are handled. */ switch (type) { case T_A: case T_UID: case T_GID: break; default: hp->rcode = REFUSED; goto finish; }#ifdef DEBUG if (debug) fprintf(ddt,"req: IQuery class %d type %d\n", class, type);#endif fname = (char *)msg + sizeof(HEADER); bcopy(fname, anbuf, alen = (char *)cp - fname); data = anbuf + alen - dlen; cp = (u_char *)fname; buflen -= sizeof(HEADER); count = 0; for (ip = invtab[dhash(data, dlen)]; ip != NULL; ip = ip->i_next) { for (i = 0; i < INVBLKSZ; i++) { if ((np = ip->i_dname[i]) == NULL) break;#ifdef DEBUG if (debug >= 5) fprintf(ddt,"dname = %d\n", np->n_dname);#endif for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (!match(dp, class, type)) continue; if (dp->d_size != dlen || bcmp(dp->d_data, data, dlen)) continue; getname(np, dnbuf, sizeof(dnbuf));#ifdef DEBUG if (debug > 2) fprintf(ddt,"req: IQuery found %s\n", dnbuf);#endif buflen -= QFIXEDSZ; if ((n = dn_comp(dnbuf, cp, buflen, (char **)NULL, (char **)NULL)) < 0) { hp->tc = 1; goto finish; } cp += n; PUTSHORT((u_short)dp->d_type, cp); PUTSHORT((u_short)dp->d_class, cp); buflen -= n; count++; } } }#ifdef DEBUG if (debug) fprintf(ddt,"req: IQuery %d records\n", count);#endif hp->qdcount = htons((u_short)count); if (alen > buflen) { hp->tc = 1; break; } bcopy(anbuf, cp, alen); cp += alen; break; }#ifdef ALLOW_UPDATES/* * In a sense the following constant should be defined in <arpa/nameser.h>, * since it is returned here in place of a response code if the update was * forwarded, and the response codes are defined in nameser.h. On the other * hand, though, this constant is only seen in this file. The assumption * here is that none of the other return codes equals this one (a good * assumption, since they only occupy 4 bits over-the-wire) */#define FORWARDED 1000 /* Call InitDynUpdate for all dynamic update requests */ case UPDATEM: case UPDATEMA: case UPDATED: case UPDATEDA: case UPDATEA: n = InitDynUpdate(hp, nsp, msg, msglen, cp, from, qsp, dfd); if (n == FORWARDED) return; /* Return directly because InitDynUpdate * forwarded the query to the primary, so we * will send response later */ else break; /* Either sucessful primary update or failure; * return response code to client */#endif ALLOW_UPDATES case ZONEREF:#ifdef DEBUG if (debug) fprintf(ddt,"Refresh Zone\n");#endif default:#ifdef DEBUG if (debug >= 2) fprintf(ddt,"Opcode %d not implemented\n", hp->opcode);#endif hp->qdcount = 0; hp->ancount = 0; hp->nscount = 0; hp->arcount = 0; hp->rcode = NOTIMP; }finish:#ifdef STATS switch(hp->rcode) { case NOERROR: stats[S_RESPOK].cnt++; break; case FORMERR: stats[S_RESPFORMERR].cnt++; break; default: stats[S_RESPFAIL].cnt++; break; }#endif hp->qr = 1; /* set Response flag */ hp->ra = 1; /* Recursion is Available */ hp->ancount = htons(hp->ancount);#ifdef AUTHEN if(netsafe && query_to_aquery) { if(fixup_rrs(ocp, (int)(cp - ocp), (int)(ocp - (u_char *)hp), -(2 * sizeof(u_short))) < 0) return(-1); ocp2 = ocp; ocp -= 2 * sizeof(u_short); bcopy(ocp2, ocp, cp - ocp2); hp->opcode = QUERY; query_to_aquery = 0; cp -= 2 * sizeof(u_short); }#endif AUTHEN if (addcount) {#ifdef AUTHEN if(hp->opcode == AQUERY) n = doaddinfo(hp, cp, DEFSIZE_KRBCRED); else n = doaddinfo(hp, cp, buflen);#else n = doaddinfo(hp, cp, buflen);#endif AUTHEN cp += n; buflen -= n; } #ifdef AUTHEN if(hp->opcode == AQUERY && read_cred) { /* switch on auth type */ dnptr = dname_authenrr; if(type_authenrr != T_SOA && type_authenrr != T_AXFR) res_dotname_rmhead(&dnptr); hp->arcount = htons(1 + ntohs(hp->arcount)); if((cred_len = res_mks_krbcred(auth_version, "", "", &ns_ad, hp, cp, buflen, dnptr, type_authenrr, class_authenrr)) < RET_OK) { hp->rcode = AUTHENBAD; cp = ocp; hp->ancount = 0; hp->nscount = 0; hp->arcount = 0; } else { cp += cred_len; } }#endif AUTHEN #ifdef DEBUG if (debug) { fprintf(ddt,"req: answer -> %s %d (%d) id=%d %s\n", inet_ntoa(from->sin_addr), dfd, ntohs(from->sin_port), ntohs(hp->id), local(from) == NULL ? "Remote" : "Local"); } if (debug >= 10) fp_query(msg, ddt);#endif DEBUG if (qsp == QSTREAM_NULL) { if (sendto(dfd, msg, cp-msg, 0, (struct sockaddr *)from, sizeof(*from))< 0){#ifdef DEBUG if (debug) fprintf(ddt,"error returning msg errno=%d\n",errno);#endif DEBUG }#ifdef STATS stats[S_OUTPKTS].cnt++;#endif } else { (void) writemsg(qsp->s_rfd, msg, cp - msg); qsp->s_time = tt.tv_sec; qsp->s_refcnt--; } if (needs_prime_cache) prime_cache(); /* Now is a safe time */}fwritemsg(rfp, msg, msglen) FILE *rfp; char *msg; int msglen;{ u_short len = htons((u_short)msglen); if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 || fwrite(msg, msglen, 1, rfp) != 1) {#ifdef DEBUG if (debug) fprintf(ddt,"fwrite failed %d\n", errno);#endif } return;}writemsg(rfd, msg, msglen) int rfd; char *msg; int msglen;{ struct iovec iov[2]; u_short len = htons((u_short)msglen); iov[0].iov_base = (caddr_t)&len; iov[0].iov_len = sizeof(len); iov[1].iov_base = msg; iov[1].iov_len = msglen; if (writev(rfd, iov, 2) != sizeof(len) + msglen) {#ifdef DEBUG if (debug) fprintf(ddt,"write failed %d\n", errno);#endif return (-1); } return (0);}/* * Test a datum for validity and return non-zero if it is out of date. */stale(dp)register struct databuf *dp;{ register struct zoneinfo *zp = &zones[dp->d_zone]; switch (zp->z_type) { case Z_PRIMARY: return (0); case Z_SECONDARY: return ((u_long)(tt.tv_sec - zp->z_lastupdate) > zp->z_expire); case Z_CACHE:#ifdef DEBUG if (debug >= 3) fprintf(ddt,"stale: ttl %d %d (x%x)\n", dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags);#endif if (dp->d_flags & DB_F_HINT) return(0); return(dp->d_ttl < tt.tv_sec); } /* NOTREACHED */}/* * Copy databuf into a resource record for replies. * Return size of RR if OK, -1 if buffer is full. */make_rr(name, dp, buf, buflen, doadd) char *name; register struct databuf *dp; char *buf; int buflen, doadd;{ register char *cp; char *cp1, *sp; struct zoneinfo *zp; register long n; register long ttl; u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);#ifdef DEBUG if (debug >= 5) fprintf(ddt,"make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %d\n", name, dp, buf, buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl);#endif zp = &zones[dp->d_zone]; /* check for outdated RR before updating dnptrs by dn_comp() */ if (zp->z_type == Z_CACHE) { ttl = dp->d_ttl - (u_long) tt.tv_sec; if ((dp->d_flags & DB_F_HINT) || (ttl <= 0)) {#ifdef DEBUG/*XXX*/if (debug >= 3) fprintf(ddt,"make_rr: %d=>1, x%x\n", ttl, dp->d_flags);#endif ttl = 1; } } else { ttl = zp->z_minimum; /* really default */ if (dp->d_ttl > 0) ttl = dp->d_ttl; if (zp->z_type == Z_SECONDARY) { /* * Set ttl to value received from primary, * less time since we verified it (but never * less than a small positive value). */ ttl -= tt.tv_sec - zp->z_lastupdate; if (ttl <= 0) ttl = 120; } } buflen -= RRFIXEDSZ; if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0) return (-1); cp = buf + n; buflen -= n; PUTSHORT((u_short)dp->d_type, cp); PUTSHORT((u_short)dp->d_class, cp); PUTLONG(ttl, cp); sp = cp; cp += sizeof(u_short); switch (dp->d_type) { case T_CNAME: case T_MG: case T_MR: case T_PTR: if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs, (char **)edp)) < 0) return (-1); PUTSHORT((u_short)n, sp); cp += n; break; case T_MB: case T_NS: /* Store domain name in answer */ if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs, (char **)edp)) < 0) return (-1); PUTSHORT((u_short)n, sp); cp += n; if (doadd) addname(dp->d_data, dp->d_class); break; case T_SOA: case T_MINFO: cp1 = dp->d_data; if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, (char **)edp)) < 0) return (-1); cp += n; buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long); cp1 += strlen(cp1) + 1; if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, (char **)edp)) < 0) return (-1); cp += n; if (dp->d_type == T_SOA) { cp1 += strlen(cp1) + 1; bcopy(cp1, cp, (int)(n = dp->d_size - (cp1 - dp->d_data))); cp += n; } n = (u_short)(cp - sp) - sizeof(u_short); PUTSHORT((u_short)n, sp); break; case T_MX: /* cp1 == our data/ cp == data of RR */ cp1 = dp->d_data; /* copy preference */ bcopy(cp1,cp,sizeof(u_short)); cp += sizeof(u_short); cp1 += sizeof(u_short); buflen -= sizeof(u_short); if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs, (char **)edp)) < 0) return(-1); cp += n; /* save data length */ n = (u_short)(cp - sp) - sizeof(u_short); PUTSHORT((u_short)n, sp); if (doadd) addname(cp1, dp->d_class); break; default: if (dp->d_size > buflen) return (-1); bcopy(dp->d_data, cp, dp->d_size); PUTSHORT((u_short)dp->d_size, sp); cp += dp->d_size; } return (cp - buf);}addname(name, class)register char *name;short class;{ register struct addinfo *ap; register int n; for (ap = addinfo, n = addcount; --n >= 0; ap++) if (strcasecmp(ap->a_dname, name) == 0) return; /* add domain name to additional section */ if (addcount < NADDRECS) { addcount++; ap->a_dname = name; ap->a_class = class; }}/* * Lookup addresses for names in addinfo and put into the message's * additional section. */doaddinfo(hp, msg, msglen) HEADER *hp; char *msg; int msglen;{ register struct namebuf *np; register struct databuf *dp; register struct addinfo *ap; register char *cp; struct hashbuf *htp; char *fname; int n, count, foundstale;#ifdef DEBUG if (debug >= 3) fprintf(ddt,"doaddinfo() addcount = %d\n", addcount);#endif count = 0; cp = msg; for (ap = addinfo; --addcount >= 0; ap++) {#ifdef DEBUG if (debug >= 3) fprintf(ddt,"do additional '%s'\n", ap->a_dname);#endif htp = hashtab; /* because "nlookup" stomps on arg. */ np = nlookup(ap->a_dname, &htp, &fname, 0); if (np == NULL || fname != ap->a_dname) continue;#ifdef DEBUG if (debug >= 3) fprintf(ddt,"found it\n");#endif foundstale = 0; /* look for the data */ for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (!match(dp, (int)ap->a_class, T_A)) continue; if (stale(dp)) { foundstale++;#ifdef DEBUG if (debug) fprintf(ddt,"doaddinfo: stale entry '%s'%s\n", np->n_dname, (dp->d_flags&DB_F_HINT) ? " hint":"" );#endif continue; } /* * Should be smart and eliminate duplicate * data here. XXX */ if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0) break;#ifdef DEBUG if (debug >= 5) fprintf(ddt,"addinfo: adding address data n = %d\n", n);#endif cp += n; msglen -= n; count++; } if (foundstale) { /* Cache invalidate the address RR's */ delete_all(np, (int)ap->a_class, T_A); (void) sysquery(ap->a_dname, (int)ap->a_class, T_A); } } hp->arcount = htons((u_short)count); return (cp - msg);}doaddauth(hp, cp, buflen, np, dp) register HEADER *hp; char *cp; int buflen; struct namebuf *np; struct databuf *dp;{ char dnbuf[MAXDNAME]; int n; getname(np, dnbuf, sizeof(dnbuf)); if (stale(dp) || (n = make_rr(dnbuf, dp, cp, buflen, 1)) <= 0) {#ifdef DEBUG if (debug) fprintf(ddt,"doaddauth: can't add '%s' (%d)\n", dnbuf, buflen);#endif return(0); } else { hp->nscount = htons(1); return(n); }}/* * Get the domain name of 'np' and put in 'buf'. Bounds checking is done. */getname(np, buf, buflen) struct namebuf *np; char *buf; int buflen;{ register char *cp; register int i; cp = buf; while (np != NULL) { if ((i = strlen(np->n_dname))+1 >= buflen) { *cp = '\0'; syslog(LOG_ERR, "domain name too long: %s...\n", buf);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?