ns_resp.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,318 行 · 第 1/4 页
C
2,318 行
return(0); }#ifdef AUTHEN qp->q_msglen = res_mkquery(qp->q_type_out, dname, class, type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);#else AUTHEN qp->q_msglen = res_mkquery(QUERY, dname, class, type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);#endif AUTHEN hp = (HEADER *) qp->q_msg; hp->id = qp->q_nsid = htons((u_short)++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) {#ifdef DEBUG if (debug >= 3) fprintf(ddt, "sysquery: duplicate\n");#endif qfree(qp); return(0); } } if (nslookup(nsp, qp) == 0) {#ifdef DEBUG if (debug) fprintf(ddt,"resp: no addrs found for NS's\n");#endif qfree(qp); return(0); }#ifdef ULTRIXFUNC schedretry(qp, qp->q_fwd ? (2*RETRYBASE): retrytime(qp) );#else ULTRIXFUNC schedretry(qp, retrytime(qp));#endif ULTRIXFUNC if (qp->q_fwd == 0) qp->q_addr[0].stime = tt;#ifdef AUTHEN if(netsafe && class == C_HS) { krbnameptr = res_dotname_head(Q_NEXTNAME(qp,0)); dnameptr = dname; if(type != T_SOA && type != T_AXFR) res_dotname_rmhead(&dnameptr); if((authenlen = res_mkl_krbcred(ONE, "named", krbnameptr, Q_NEXTCRED(qp,0), qp->q_msg, qp->q_msg + qp->q_msglen, BUFSIZ - qp->q_msglen, dnameptr, type, class)) < RET_OK) return(0); msglen = qp->q_msglen + authenlen; }#endif AUTHEN#ifdef DEBUG if (debug) fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %dms\n", inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr), qp->q_dfd, ntohs(Q_NEXTADDR(qp,0)->sin_port), ntohs(qp->q_nsid), ntohs(qp->q_id), qp->q_addr[0].nsdata->d_nstime); if ( debug >= 10) fp_query(qp->q_msg, ddt);#endif#ifdef AUTHEN if (sendto(qp->q_dfd, qp->q_msg, msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,0), sizeof(struct sockaddr_in)) < 0){#else AUTHEN if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,0), sizeof(struct sockaddr_in)) < 0){#endif AUTHEN#ifdef DEBUG if (debug) fprintf(ddt, "sendto error errno= %d\n",errno);#endif }#ifdef STATS stats[S_OUTPKTS].cnt++;#endif return(qp);}/* * Check the list of root servers after receiving a response * to a query for the root servers. */check_root(){ register struct databuf *dp, *pdp; register struct namebuf *np; int count = 0; priming = 0; for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) if (np->n_dname[0] == '\0') break; if (np == NULL) { syslog(LOG_ERR, "check_root: Can't find root!\n"); return; } for (dp = np->n_data; dp != NULL; dp = dp->d_next) if (dp->d_type == T_NS) count++;#ifdef DEBUG if (debug) fprintf(ddt,"%d root servers\n", count);#endif if (count < MINROOTS) { syslog(LOG_WARNING, "check_root: %d root servers after query to root server < min", count); return; } pdp = NULL; dp = np->n_data; while (dp != NULL) { if (dp->d_type == T_NS && dp->d_zone == 0 && dp->d_ttl < tt.tv_sec) {#ifdef DEBUG if (debug) fprintf(ddt,"deleting old root server '%s'\n", dp->d_data);#endif#ifdef ULTRIXFUNC dp = rm_datum(0, dp, np, pdp);#endif ULTRIXFUNC /* SHOULD DELETE FROM HINTS ALSO */ continue; } pdp = dp; dp = dp->d_next; } check_ns();}/* * Check the root to make sure that for each NS record we have a A RR */check_ns(){ register struct databuf *dp, *tdp; register struct namebuf *np, *tnp; struct hashbuf *htp; char *dname; int found_arr; char *fname; time_t curtime;#ifdef DEBUG if (debug >= 2) fprintf(ddt,"check_ns()\n");#endif#ifdef STATS stats[S_CHECKNS].cnt++;#endif curtime = (u_long) tt.tv_sec; for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) { if (np->n_dname[0] != 0) continue; for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (dp->d_type != T_NS) continue; /* look for A records */ dname = dp->d_data; htp = hashtab; tnp = nlookup(dname, &htp, &fname, 0); if (tnp == NULL || fname != dname) {#ifdef DEBUG if (debug >= 3) fprintf(ddt,"check_ns: %s: not found %s %x\n", dname, fname, tnp);#endif (void) sysquery(dname, dp->d_class, T_A); continue; } /* look for name server addresses */ found_arr = 0; for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) { if (tdp->d_type != T_A || tdp->d_class != dp->d_class) continue; if ((tdp->d_zone == 0) && (tdp->d_ttl < curtime)) {#ifdef DEBUG if (debug >= 3) fprintf(ddt,"check_ns: stale entry '%s'\n", tnp->n_dname);#endif /* Cache invalidate the address RR's */ delete_all(tnp, dp->d_class, T_A); found_arr = 0; break; } found_arr++; } if (!found_arr) (void) sysquery(dname, dp->d_class, T_A); } }}#define MAXCLASS 255 /* belongs elsewhere */int norootlogged[MAXCLASS];/* * Find NS's or an SOA for the given dname (np) and fill in the * nsp array. Returns OK on success, and SERVFAIL on error. * We return NXDOMAIN to indicate we are authoritative. */findns(npp, class, nsp, countp) register struct namebuf **npp; struct databuf **nsp; int *countp;{ register struct namebuf *np = *npp; register struct databuf *dp; register struct databuf **nspp; struct hashbuf *htp = hashtab; if (priming && (np == NULL || np->n_dname[0] == '\0')) htp = fcachetab;try_again:/*#ifdef AUTHEN if (htp == fcachetab && !(forward_only && fwdtab))#else AUTHEN*/ if (htp == fcachetab)/*#endif AUTHEN*/ needs_prime_cache = 1; while (np == NULL && htp != NULL) {#ifdef DEBUG if (debug > 2) fprintf(ddt, "findns: using %s\n", htp == hashtab ? "cache" : "hints");#endif for (np = htp->h_tab[0]; np != NULL; np = np->n_next) if (np->n_dname[0] == '\0') break; htp = (htp == hashtab ? fcachetab : NULL); /* Fallback */ } while(np != NULL) {#ifdef DEBUG if (debug >= 5) fprintf(ddt, "findns: np 0x%x\n", np);#endif /* Look first for SOA records. */ for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (dp->d_zone != 0 && match(dp, class, T_SOA)) {#ifdef DEBUG if (debug >= 3) fprintf(ddt,"findns: SOA found\n");#endif if (zones[dp->d_zone].z_auth) { *npp = np; nsp[0] = dp; return(NXDOMAIN); } else return (SERVFAIL); } } /* If no SOA records, look for NS records. */ nspp = &nsp[0]; *nspp = NULL; for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (dp->d_type != T_NS || (dp->d_class != class && class != C_ANY)) continue; /* * Don't use records that may become invalid to * reference later when we do the rtt computation. * Never delete our safety-belt information! */ if ((dp->d_zone == 0) && (dp->d_ttl < (tt.tv_sec+900)) && !(dp->d_flags & DB_F_HINT)) {#ifdef DEBUG if (debug) fprintf(ddt,"findns: stale entry '%s'\n", np->n_dname);#endif /* Cache invalidate the NS RR's */ if (dp->d_ttl < tt.tv_sec) delete_all(np, class, T_NS); goto try_parent; } if (nspp < &nsp[NSMAX-1]) *nspp++ = dp; } *countp = nspp - nsp; if (*countp > 0) {#ifdef DEBUG if (debug >= 3) fprintf(ddt,"findns: %d NS's added for '%s'\n", *countp, np->n_dname);#endif *nspp = NULL; *npp = np; return(OK); /* Success, got some NS's */ }try_parent: np = np->n_parent; } if (htp) goto try_again;#ifdef DEBUG if (debug) fprintf(ddt, "findns: No root nameservers for class %d?\n", class);#endif if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) { norootlogged[class] = 1; syslog(LOG_ERR, "No root nameservers for class %d\n", class); } return(SERVFAIL);}/* * Extract RR's from the given node that match class and type. * Return number of bytes added to response. * If no matching data is found, then 0 is returned. * Authoritative answer bit is set in response if appropriate. */#ifdef AUTHENfinddata(np, class, type, hp, dnamep, lenp, countp, authtype, authver, ans_type, ans_class) struct namebuf *np; int class, type; register HEADER *hp; char **dnamep; int *lenp, *countp; int authtype, authver; int *ans_type, *ans_class;{#else AUTHENfinddata(np, class, type, hp, dnamep, lenp, countp) struct namebuf *np; int class, type; register HEADER *hp; char **dnamep; int *lenp, *countp;{#endif AUTHEN register struct databuf *dp; register char *cp; int buflen, n, count = 0, foundstale = 0;#ifdef AUTHEN int foundnotauth = 0;#endif AUTHEN buflen = *lenp; cp = ((char *)hp) + *countp; for (dp = np->n_data; dp != NULL; dp = dp->d_next) { if (!wanted(dp, class, type)) {#ifdef notdef if (type == T_CNAME && class == dp->d_class) { /* any data means no CNAME exists */ *countp = 0; return(0); }#endif continue; } if (stale(dp)) { /* * Don't use stale data. * Would like to call delete_all here * and continue, but the data chain would get * munged; can't restart, as make_rr has side * effects (leaving pointers in dnptr). * Just skip this entry for now * and call delete_all at the end. */#ifdef DEBUG if (debug >=3) fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname);#endif if (dp->d_zone == 0) foundstale++; continue; }#ifdef AUTHEN if(not_authen(authtype, authver, dp)) { foundnotauth = 1; continue; }#endif AUTHEN if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) { hp->tc = 1; *countp = count; return(*lenp - buflen); } cp += n; buflen -= n; count++;#ifdef AUTHEN if(count == 1) { *ans_type = dp->d_type; *ans_class = dp->d_class; }#endif AUTHEN#ifdef notdef /* this isn't right for glue records, aa is set in ns_req */ if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY) hp->aa = 1; /* XXX */#endif if (dp->d_type == T_CNAME) { if (type != T_ANY) { /* or T_NS? */ *dnamep = dp->d_data; if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY) /* XXX */ hp->aa = 1; /* XXX */ } break; } } /* * Cache invalidate the other RR's of same type * if some have timed out */#ifdef AUTHEN if (foundstale || foundnotauth)#else AUTHEN if (foundstale)#endif AUTHEN delete_all(np, class, type);#ifdef DEBUG if (debug >=3) fprintf(ddt,"finddata: added %d class %d type %d RRs\n", count, class, type);#endif *countp = count; return(*lenp - buflen);}/* * Do we want this data record based on the class and type? */wanted(dp, class, type) struct databuf *dp; int class, type;{#ifdef DEBUG if (debug > 3) fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type, dp->d_class, dp->d_type);#endif if (dp->d_class != class && class != C_ANY) return (0); if (type == dp->d_type) return (1); switch (dp->d_type) { case T_ANY: case T_CNAME: return (1); } switch (type) { case T_TXT: return(dp->d_type == T_TXT); case T_ANY: return (1); case T_MAILB: switch (dp->d_type) { case T_MR: case T_MB: case T_MG: case T_MINFO: return (1); } break; case T_AXFR: if (dp->d_type == T_SOA) return (1); } return (0);}/* * Add RR entries from dpp array to a query/response. * Return the number of bytes added or negative the amount * added if truncation was required. Typically you are * adding NS records to a response. */add_data(np, dpp, cp, buflen) struct namebuf *np; struct databuf **dpp; register char *cp; int buflen;{ register struct databuf *dp; char dname[MAXDNAME]; register int n, count = 0; getname(np, dname, sizeof(dname)); for(dp = *dpp++; dp != NULL; dp = *dpp++) { if (stale(dp)) continue; /* ignore old cache entry */ if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) return(-count); /* Truncation */ cp += n; buflen -= n; count += n; } return(count);}/* * This is best thought of as a "cache invalidate" function. * It is called whenever a piece of data is determined to have * timed out. It is better to have no information, than to * have partial information you pass off as complete. */delete_all(np, class, type)register struct namebuf *np;int class, type;{ register struct databuf *dp, *pdp;#ifdef DEBUG if (debug > 2) fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n", np->n_dname, np, class, type);#endif pdp = NULL; dp = np->n_data; while (dp != NULL) { if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT) && match(dp, class, type)) {#ifdef ULTRIXFUNC dp = rm_datum(0, dp, np, pdp);#endif ULTRIXFUNC continue; } pdp = dp; dp = dp->d_next; }}#ifdef AUTHENnot_authen(authentype, authenver, dp) int authentype, authenver; struct databuf *dp;{ if(dp->d_authen_type == AUTH_CACHE) return(0); if (authentype == dp->d_authen_type && authenver == dp->d_authen_ver) return(0); if (authentype == AUTH_NONE) return(0); return(-1);}#endif AUTHEN
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?