ns_req.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,919 行 · 第 1/3 页
C
1,919 行
strcpy(buf, "Name_Too_Long"); return; } if (cp != buf) *cp++ = '.'; (void) strcpy(cp, np->n_dname); cp += i; buflen -= (i+1); np = np->n_parent; } *cp = '\0';}/* * Do a zone transfer. SOA record already sent. */#ifdef AUTHENdoaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, isroot, rootdname) register struct namebuf *np; FILE *rfp; AUTH_DAT *ns_ad; int isaquery; int auth_type; int auth_version; int isroot; char *rootdname;#elsedoaxfr(np, rfp, isroot) register struct namebuf *np; FILE *rfp; int isroot;#endif AUTHEN{ register struct databuf *dp; register int n; struct hashbuf *htp; struct databuf *gdp; /* glue databuf */ struct namebuf *gnp; /* glue namebuf */ struct namebuf **npp, **nppend; /* MAXDATA below was changed from PAXCKETSZ to accomodate data items larger than 512 bytes. Will this create conflicts with 883? */ char msg[MAXDATA]; char *cp; char *fname; char dname[MAXDNAME]; HEADER *hp = (HEADER *) msg; int fndns;#ifdef AUTHEN char *dnptr; int cred_len;#endif AUTHEN#ifdef DEBUG if (debug && isroot) fprintf(ddt,"doaxfr()\n");#endif fndns = 0; hp->id = 0;#ifdef AUTHEN if(isaquery) hp->opcode = AQUERY; else#endif AUTHEN hp->opcode = QUERY; hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0; hp->qr = 1; hp->rcode = NOERROR; hp->qdcount = 0; hp->ancount = htons(1); hp->nscount = 0;#ifdef AUTHEN if(isaquery) hp->arcount = htons(1); else#endif AUTHEN hp->arcount = 0; cp = msg + sizeof(HEADER); getname(np, dname, sizeof(dname));#ifdef AUTHEN if(isroot) getname(np, rootdname, MAXDNAME);#endif AUTHEN /* first do data records */ for (dp = np->n_data; dp != NULL; dp = dp->d_next) { /* * Skip the root SOA record (marks end of data); * don't send SOA for subdomains, as we're not sending them. */#ifdef AUTHEN if (dp->d_type == T_SOA) continue;#else AUTHEN if (dp->d_type == T_SOA) continue;#endif AUTHEN if (dp->d_type == T_NS) fndns = 1; if (dp->d_zone == 0 || stale(dp)) continue; if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0) continue;#ifdef AUTHEN if(isaquery) { if(auth_type == AUTH_KRB && auth_version == ONE) { cp += n; dnptr = dname; if(dp->d_type != T_SOA && dp->d_type != T_AXFR) res_dotname_rmhead(&dnptr); hp->arcount = htons(1); if((cred_len = res_mks_krbcred(auth_version, "", "", ns_ad, hp, cp, MAXDATA - (cp -(char *)hp), dnptr, dp->d_type, dp->d_class)) < RET_OK) { syslog(LOG_ERR, "%s, %d:", "bad res_mks_krbcred call in doaxfr", cred_len); exit(1); } n += cred_len; cp = msg + sizeof(HEADER); } else hp->arcount = 0; }#endif AUTHEN fwritemsg(rfp, msg, n + sizeof(HEADER)); if (dp->d_type == T_NS) { /* Glue the sub domains together by sending * the address records for the sub domain * name servers along. */ htp = hashtab; cp = msg + sizeof(HEADER); gnp = nlookup(dp->d_data, &htp, &fname, 0); if (gnp == NULL || fname != dp->d_data) continue; for(gdp=gnp->n_data; gdp != NULL; gdp=gdp->d_next) { if (gdp->d_type != T_A || stale(gdp)) continue; if ((n = make_rr(fname, gdp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0) continue;#ifdef AUTHEN if(isaquery) { if(auth_type == AUTH_KRB) { cp += n; dnptr = fname; if(gdp->d_type != T_SOA && gdp->d_type != T_AXFR) res_dotname_rmhead(&dnptr); hp->arcount = htons(1); if((cred_len = res_mks_krbcred( auth_version, "", "", ns_ad, hp, cp, MAXDATA - (cp - (char *)hp), dnptr, gdp->d_type, gdp->d_class)) < RET_OK) { syslog(LOG_ERR, "%s:", "bad res_mks_krbcred call in doaxfr"); exit(1); } n += cred_len; cp = msg + sizeof(HEADER); } else hp->arcount = 0; }#endif AUTHEN fwritemsg(rfp, msg, n + sizeof(HEADER)); } } } /* next do subdomains, unless delegated */ if ((isroot == 0 && fndns) || np->n_hash == NULL) return; npp = np->n_hash->h_tab; nppend = npp + np->n_hash->h_size; while (npp < nppend) { for (np = *npp++; np != NULL; np = np->n_next) {#ifdef AUTHEN doaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, 0, rootdname);#else AUTHEN doaxfr(np, rfp, 0);#endif AUTHEN } }#ifdef DEBUG if (debug && isroot) fprintf(ddt,"exit doaxfr()\n");#endif}#ifdef ALLOW_UPDATES/* * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update. If this is the * primary server for the zone being updated, we update the zone's serial * number and then call doupdate directly. If this is a secondary, we just * forward the update; this way, if the primary update fails (e.g., if the * primary is unavailable), we don't update the secondary; if the primary * update suceeds, ns_resp will get called with the response (when it comes * in), and then update the secondary's copy. */InitDynUpdate(hp, nsp, msg, msglen, startcp, from, qsp, dfd) register HEADER *hp; struct databuf *nsp[]; char *msg; int msglen; char *startcp; struct sockaddr_in *from; struct qstream *qsp; int dfd;{ struct zoneinfo *zp; char dnbuf[MAXDNAME]; struct hashbuf *htp = hashtab; /* lookup relative to root */ struct namebuf *np; struct databuf *olddp, *newdp, *dp; struct databuf **nspp; char *fname; char *data; register u_char *cp = startcp; short class, type; int n, size, zonenum; char ZoneName[MAXDNAME], *znp; if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR InitDynUpdate expand name failed\n");#endif hp->rcode = FORMERR; return(FORMERR); } cp += n; GETSHORT(type, cp); if (type == T_SOA) { /* T_SOA updates not allowed */ hp->rcode = REFUSED;#ifdef DEBUG if (debug) fprintf(ddt, "InitDynUpdate: REFUSED - SOA update\n");#endif return(REFUSED); } GETSHORT(class, cp); cp += sizeof(u_long); GETSHORT(size, cp); data = cp;/****XXX - need bounds checking here ****/ cp += size; if ((zonenum = findzone(dnbuf, class)) == 0) { /* zone not found */ hp->rcode = NXDOMAIN; return(NXDOMAIN); } zp = &zones[zonenum]; /* Disallow updates for which we aren't authoratative. Note: the following test doesn't work right: If it's for a non-local zone, we will think it's a primary but be unable to lookup the namebuf, thus returning 'NXDOMAIN' */ if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) { hp->rcode = REFUSED;#ifdef DEBUG if (debug) fprintf(ddt, "InitDynUpdate: REFUSED - non-primary, non-sedondary update\n");#endif return(REFUSED); } /* * Lookup the zone namebuf. Lookup "xyz" not "xyz.", since * otherwise the lookup fails, because '.' may have a nil n_hash * associated with it. */ strcpy(ZoneName, zp->z_origin); znp = &ZoneName[strlen(ZoneName) - 1]; if (*znp == '.') *znp = NULL; np = nlookup(ZoneName, &htp, &fname, 0); if ((np == NULL) || (fname != ZoneName)) {#ifdef DEBUG if (debug) fprintf(ddt, "InitDynUpdate: lookup failed on zone (%s)\n", ZoneName);#endif DEBUG syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n", ZoneName); hp->rcode = NXDOMAIN; return(NXDOMAIN); } /* * If this is the primary copy increment the serial number. Don't * increment the serial number if this is a secondary; this way, if 2 * different secondaries both update the primary, they will both have * lower serial numbers than the primary has, and hence eventually * refresh and get all updates and become consistent. * * Note that the serial number must be incremented in both the zone * data structure and the zone's namebuf. */ switch (zp->z_type) { case Z_SECONDARY: /* forward update to primary */ nspp = nsp; dp = np->n_data; while (dp != NULL) { if (match(dp, class, T_NS)) { if (nspp < &nsp[NSMAX-1]) *nspp++ = dp; else break; } dp = dp->d_next; } *nspp = NULL; /* Delimiter */ if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL) < 0) { hp->rcode = SERVFAIL; return(SERVFAIL); } return(FORWARDED); case Z_PRIMARY: zp->z_serial++; olddp = np->n_data; /* old databuf */ /* Find the SOA record */ for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next) if (match(olddp, class, T_SOA)) break; if (olddp == NULL) {#ifdef DEBUG if (debug) fprintf(ddt,"InitDynUpdate: Couldn't find SOA record for '%s'\n", ZoneName);#endif DEBUG syslog(LOG_ERR, "InitDynUpdate: Couldn't find SOA record for '%s'\n", ZoneName); hp->rcode = NXDOMAIN; return(NXDOMAIN); } newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl, olddp->d_data, olddp->d_size); newdp->d_zone = olddp->d_zone; cp = newdp->d_data; cp += strlen(cp) + 1; /* skip origin string */ cp += strlen(cp) + 1; /* skip in-charge string */ putlong((u_long)(zp->z_serial), cp);#ifdef DEBUG if (debug >= 4) { fprintf(ddt, "after stuffing data into newdp:\n"); printSOAdata(newdp); }#endif DEBUG if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE, hashtab)) != NOERROR) {#ifdef DEBUG if (debug) fprintf(ddt,"InitDynUpdate: SOA update failed\n");#endif DEBUG hp->rcode = NOCHANGE; return(NOCHANGE); } /* Now update the RR itself */ if (doupdate(msg, msglen, msg + sizeof(HEADER), zonenum, (struct databuf *)0, DB_NODATA) < 0) {#ifdef DEBUG if (debug) fprintf(ddt,"InitDynUpdate: doupdate failed\n");#endif DEBUG /* doupdate fills in rcode */ return(hp->rcode); } zp->hasChanged++; return(NOERROR); }}#ifdef DEBUG/* * Print the contents of the data in databuf pointed to by dp for an SOA record */printSOAdata(dp) struct databuf *dp;{ register u_char *cp; if (!debug) return; /* Otherwise fprintf to ddt will bomb */ cp = dp->d_data; fprintf(ddt, "printSOAdata(%x): origin(%x)='%s'\n", dp, cp, cp); cp += strlen(cp) + 1; /* skip origin string */ fprintf(ddt, "printSOAdata: in-charge(%x)='%s'\n", cp, cp); cp += strlen(cp) + 1; /* skip in-charge string */ fprintf(ddt, "printSOAdata: serial(%x)=%d\n", cp, _getlong(cp));}#endif DEBUG#endif ALLOW_UPDATES#ifdef ULTRIXFUNCstruct databuf *rm_datum(flag, dp, np, pdp)register struct databuf *pdp, *dp;register struct namebuf *np;int flag;{ register struct databuf *ndp = dp->d_next;#ifdef DEBUG if (debug > 2) fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n", dp, np->n_data, pdp, ndp);#endif DEBUG rminv(flag, dp); if (pdp == NULL) { if(flag) np->n_loaddb = ndp; else np->n_data = ndp; } else pdp->d_next = ndp; (void) free((char *)dp); return(ndp);}#else ULTRIXFUNCstruct databuf *rm_datum(dp, np, pdp)register struct databuf *pdp, *dp;register struct namebuf *np;{ register struct databuf *ndp = dp->d_next;#ifdef DEBUG if (debug > 2) fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n", dp, np->n_data, pdp, ndp);#endif DEBUG if (pdp == NULL) np->n_data = ndp; else pdp->d_next = ndp; rminv(dp); (void) free((char *)dp); return(ndp);}#endif ULTRIXFUNC#ifdef AUTHENstartxfr(qsp, np, isaquery, ns_ad, auth_type, auth_version, msg, msglen, rr, dname, type, class) struct qstream *qsp; struct namebuf *np; int isaquery; AUTH_DAT *ns_ad; int auth_type; int auth_version; char *msg; int msglen; char *rr; char *dname; int type; int class;#elsestartxfr(qsp, np, msg, msglen) struct qstream *qsp; struct namebuf *np; char *msg; int msglen;#endif AUTHEN{ register FILE *rfp; int fdstat;char buff[MAXDNAME];#ifdef AUTHEN int cred_len;#endif#ifdef DEBUG if (debug >= 5) fprintf(ddt,"startxfr()\n");#endif /* * child does the work while * the parent continues */ if (fork() == 0) {#ifdef DEBUG if (debug >= 5) fprintf(ddt,"startxfr: child pid %d\n", getpid());#endif rfp = fdopen(qsp->s_rfd, "w"); setproctitle("zone XFR to", qsp->s_rfd); fdstat = fcntl(qsp->s_rfd, F_GETFL, 0); if (fdstat != -1) (void) fcntl(qsp->s_rfd, F_SETFL, fdstat & ~FNDELAY); fwritemsg(rfp, msg, msglen);#ifdef AUTHEN doaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, 1,buff);#else doaxfr(np, rfp, 1);#endif AUTHEN/* fix the old cred */#ifdef AUTHEN if(isaquery) { /* switch on auth type */ if((cred_len = res_mks_krbcred(auth_version, "", "", ns_ad, msg, rr, BUFSIZ - msglen, dname, T_SOA, class)) < RET_OK) { syslog(LOG_ERR, " Couldn't send last SOA of AXFR to %s\n", ns_ad->pinst); (void)fflush(rfp); exit(0); } msglen = (rr - msg) + cred_len; }#endif AUTHEN fwritemsg(rfp, msg, msglen); (void) fflush(rfp); exit(0); } qsp->s_time = tt.tv_sec; qsp->s_refcnt--;}#ifdef AUTHEN/* * Copy databuf into a resource record for replies. * Return size of RR if OK, -1 if buffer is full. */fixup_rrs(buf, buflen, cutoff, shift) u_char *buf; register int buflen; int cutoff; int shift;{ register u_char *cp = buf; register u_char *sp; register int n; int type; for(; buflen > 0;){ if((n = fixup_rr(cp, cutoff, shift)) < 0) return(-1); cp += n; buflen -= n; GETSHORT(type, cp); cp += sizeof(u_short) + sizeof(u_long); GETSHORT(n, cp); sp = cp; cp += n; buflen -= 3 * sizeof(u_short) + sizeof(u_long) + n; switch (type) { case T_CNAME: case T_MG: case T_MR: case T_PTR: case T_MB: case T_NS: if ((n = fixup_rr(sp, cutoff, shift)) < 0) return(-1); break; case T_SOA: case T_MINFO: if ((n = fixup_rr(sp, cutoff, shift)) < 0) return(-1); sp += n; if ((n = fixup_rr(sp, cutoff, shift)) < 0) return(-1); break; case T_MX: sp += sizeof(u_short); if ((n = fixup_rr(sp, cutoff, shift)) < 0) return(-1); break; } } return ((int)(cp - buf));}fixup_rr(comp_dn, cutoff, shift) u_char *comp_dn; int cutoff; register int shift;{ register u_char *cp; register int val, n; cp = comp_dn; /* * fetch next label in domain name */ while (n = *cp++) { /* * Check for indirection */ switch (n & INDIR_MASK) { case 0: cp += n; break; case INDIR_MASK: val = (((n & 0x3f) << 8) | (*cp & 0xff)); if (val >= cutoff) { val = val + shift; --cp; *cp++ = (val >> 8) | INDIR_MASK; *cp++ = val % 256; } else cp++; return ((int)(cp - comp_dn)); default: return (-1); /* flag error */ } } return ((int)(cp - comp_dn));}#endif AUTHEN
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?