ns_resp.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,318 行 · 第 1/4 页
C
2,318 行
hp->arcount = htons((u_short)1); tmplen -= authen_rrlen; if((authenlen = res_mks_krbcred(ONE, "", "", &qp->q_ad, tmpmsg, tmpmsg + tmplen, BUFSIZ - tmplen, dnameptr, type_authenrr, class_authenrr)) < RET_OK) goto servfail; tmplen += authenlen; } (void) send_msg(tmpmsg, tmplen, qp); hp->arcount = 0; qremove(qp); return;#else AUTHENreturn_msg:#ifdef STATS stats[S_RESPOK].cnt++;#endif /* The "standard" return code */ hp->qr = 1; hp->id = qp->q_id; hp->rd = 1; hp->ra = 1; (void) send_msg(msg, msglen, qp); qremove(qp); return;return_newmsg:#ifdef STATS stats[S_RESPOK].cnt++;#endif if (addcount) { n = doaddinfo(hp, cp, buflen); cp += n; buflen -= n; } hp->id = qp->q_id; hp->rd = 1; hp->ra = 1; hp->qr = 1; (void) send_msg(newmsg, cp - newmsg, qp); qremove(qp); return;servfail:#ifdef STATS stats[S_RESPFAIL].cnt++;#endif hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg); hp->rcode = SERVFAIL; hp->id = qp->q_id; hp->rd = 1; hp->ra = 1; hp->qr = 1; (void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp); qremove(qp); return;#endif AUTHEN}/* * Decode the resource record 'rrp' and update the database. * If savens is true, record pointer for forwarding queries a second time. */#ifdef AUTHENdoupdate(msg, msglen, rrp, zone, savens, authen_type, authen_ver, flags) char *msg ; u_char *rrp; struct databuf **savens; int msglen, zone, flags; int authen_type; int authen_ver;{#else AUTHENdoupdate(msg, msglen, rrp, zone, savens, flags) char *msg ; u_char *rrp; struct databuf **savens; int msglen, zone, flags;{#endif AUTHEN register u_char *cp; register int n; int class, type, dlen, n1; u_long ttl; struct databuf *dp; char dname[MAXDNAME]; u_char *cp1; u_char data[BUFSIZ]; register HEADER *hp = (HEADER *) msg;#ifdef DEBUG if (debug > 2) fprintf(ddt,"doupdate(zone %d, savens %x, flags %x)\n", zone, savens, flags);#endif cp = rrp; if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp);/* KLUDGE ALERT This kludge sponsored in part by John Williams and brought to you by Bill Brown and a tight field test schedule. If this named is running as a slave and the data being placed in the database is auth or password info, then set the ttl to two minutes. This will allow a slave to pick up new password info from the database at two minute intervals.*/ { /* begin KLUDGE */ char *kld_head; if((forward_only && fwdtab)) { /* We are a slave */ kld_head = dname; res_dotname_rmhead(&kld_head); kld_head = res_dotname_head(kld_head); if( !strcmp(kld_head, "auth") || !strcmp(kld_head, "passwd")) /* this is auth or passwd info */ ttl = 120; } } /* end KLUDGE */ GETSHORT(dlen, cp);#ifdef DEBUG if (debug > 2) fprintf(ddt,"doupdate: dname %s type %d class %d ttl %d\n", dname, type, class, ttl);#endif /* * Convert the resource record data into the internal * database format. */ switch (type) { case T_A: case T_WKS: case T_HINFO: case T_UINFO: case T_UID: case T_GID: case T_TXT:#ifdef ALLOW_T_UNSPEC case T_UNSPEC:#endif ALLOW_T_UNSPEC cp1 = cp; n = dlen; cp += n; break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: if ((n = dn_expand(msg, msg + msglen, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 = data; n = strlen(data) + 1; break; case T_MINFO: case T_SOA: if ((n = dn_expand(msg, msg + msglen, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 = data + (n = strlen(data) + 1); n1 = sizeof(data) - n; if (type == T_SOA) n1 -= 5 * sizeof(u_long); if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 += strlen(cp1) + 1; if (type == T_SOA) { bcopy(cp, cp1, n = 5 * sizeof(u_long)); cp += n; cp1 += n; } n = cp1 - data; cp1 = data; break; case T_MX: /* grab preference */ bcopy(cp,data,sizeof(u_short)); cp1 = data + sizeof(u_short); cp += sizeof(u_short); /* get name */ if ((n = dn_expand(msg, msg + msglen, cp, cp1, sizeof(data)-sizeof(u_short))) < 0) return(-1); cp += n; /* compute end of data */ cp1 += strlen(cp1) + 1; /* compute size of data */ n = cp1 - data; cp1 = data; break; default:#ifdef DEBUG if (debug >= 3) fprintf(ddt,"unknown type %d\n", type);#endif return ((cp - rrp) + dlen); } if (n > MAXDATA) {#ifdef DEBUG if (debug) fprintf(ddt, "update type %d: %d bytes is too much data\n", type, n);#endif 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(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 */#ifdef DEBUG if (debug) fprintf(ddt, "UDPATE: REFUSED - SOA delete\n");#endif 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 ( (opcode == UPDATED) || (opcode == UPDATEDA) ) { if (cp != msg + msglen) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR UPDATE message length off\n");#endif hp->rcode = FORMERR; return(-1); } } if ((zonenum = findzone(dname, class)) == 0) { hp->rcode = NXDOMAIN; return(-1); } if ( (opcode == UPDATED) || (opcode == UPDATEM) ) { /* Make a dp for use in db_update, as old dp */ dp = savedata(class, type, 0, cp1, n); dp->d_zone = zonenum; n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE, hashtab); if (n != OK) {#ifdef DEBUG if (debug) fprintf(ddt,"UPDATE: db_update failed\n");#endif DEBUG free( (struct databuf *) 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; 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( (struct databuf *) dp); /* Ok for UPDATEMA not to have deleted any RRs */ if (!DeletedOne && opcode == UPDATEDA) {#ifdef DEBUG if (debug) fprintf(ddt,"UPDATE: db_update failed\n");#endif DEBUG hp->rcode = NOCHANGE; return(-1); } } if ( (opcode == UPDATED) || (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) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR UPDATE expand name failed\n");#endif 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) {#ifdef DEBUG if (debug) fprintf(ddt,"UPDATE: too much data\n");#endif hp->rcode = NOCHANGE; return(-1); } if (cp != msg + msglen) {#ifdef DEBUG if (debug) fprintf(ddt,"FORMERR UPDATE message length off\n");#endif hp->rcode = FORMERR; return(-1); } if ((zonenum = findzone(dname, class)) == 0) { hp->rcode = NXDOMAIN; return(-1); } dp = savedata(class, type, ttl, cp1, n); dp->d_zone = zonenum; if ((n = db_update(dname, NULL, dp, DB_NODATA, hashtab)) != OK) {#ifdef DEBUG if (debug) fprintf(ddt,"UPDATE: db_update failed\n");#endif hp->rcode = NOCHANGE; return (-1); } else return (cp - rrp); }#endif ALLOW_UPDATES if (zone == 0) ttl += tt.tv_sec;#ifdef AUTHEN dp = savedata(class, type, ttl, authen_type, authen_ver, cp1, n);#else AUTHEN dp = savedata(class, type, ttl, cp1, n);#endif AUTHEN dp->d_zone = zone; 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 (void) free((char *)dp); } else if (type == T_NS && savens != NULL) *savens = dp; return (cp - rrp);}send_msg(msg, msglen, qp) char *msg; int msglen; struct qinfo *qp;{ extern struct qinfo *qhead;#ifdef DEBUG struct qinfo *tqp;#endif DEBUG if (qp->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_dfd, 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) {#ifdef DEBUG if (debug) fprintf(ddt, "sendto error errno= %d\n",errno);#endif return(1); }#ifdef STATS stats[S_OUTPKTS].cnt++;#endif } else { (void) writemsg(qp->q_stream->s_rfd, msg, msglen); qp->q_stream->s_time = tt.tv_sec; qp->q_stream->s_refcnt--; } return(0);}prime(class, type, oqp) int class, type; register struct qinfo *oqp;{ char dname[BUFSIZ]; if (oqp->q_msg == NULL) return; if (dn_expand(oqp->q_msg, oqp->q_msg + oqp->q_msglen, oqp->q_msg + sizeof(HEADER), dname, sizeof(dname)) < 0) return;#ifdef DEBUG if (debug >= 2) fprintf(ddt,"prime: %s\n", dname);#endif (void) sysquery(dname, class, type);}prime_cache(){ register struct qinfo *qp;#ifdef DEBUG if (debug) fprintf(ddt,"prime_cache: priming = %d\n", priming);#endif#ifdef STATS stats[S_PRIMECACHE].cnt++;#endif if (!priming && fcachetab->h_tab[0] != NULL) { priming++; if ((qp = sysquery("", C_IN, T_NS)) == NULL) priming = 0; else qp->q_system = PRIMING_CACHE; } needs_prime_cache = 0; return;}struct qinfo *sysquery(dname, class, type) char *dname; int class, type;{ extern struct qinfo *qhead; extern int nsid; register struct qinfo *qp, *oqp; register HEADER *hp; struct namebuf *np; struct databuf *nsp[NSMAX]; struct hashbuf *htp; char *fname; int count;#ifdef AUTHEN char *krbnameptr; char *dnameptr; int authenlen; int msglen;#endif AUTHEN#ifdef DEBUG if (debug > 2) fprintf(ddt,"sysquery(%s, %d, %d)\n", dname, class, type);#endif#ifdef STATS stats[S_SYSQUERIES].cnt++;#endif htp = hashtab; if (priming && dname[0] == '\0') np = NULL; else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {#ifdef DEBUG if (debug) fprintf(ddt,"sysquery: nlookup error on %s?\n", dname);#endif return(0); } switch (findns(&np, class, nsp, &count)) { case NXDOMAIN: case SERVFAIL:#ifdef DEBUG if (debug) fprintf(ddt,"sysquery: findns error on %s?\n", dname);#endif return(0); } /* build new qinfo struct */ qp = qnew(); qp->q_cmsg = qp->q_msg = NULL; qp->q_dfd = ds; qp->q_fwd = fwdtab; qp->q_addr[0].stime = tt; qp->q_system++;#ifdef AUTHEN strcpy(qp->q_dname, dname); qp->q_type = type; qp->q_class = class; strcpy(qp->q_dname_curr, dname); qp->q_type_curr = type; qp->q_class_curr = class; if(netsafe && class == C_HS) { qp->q_type_in = AQUERY; qp->q_type_out = AQUERY; qp->q_authentype_in = AUTH_KRB; qp->q_authenver_in = ONE; qp->q_authentype_out = AUTH_KRB; qp->q_authenver_out = ONE; } else { qp->q_type_in = QUERY; qp->q_type_out = QUERY; qp->q_authentype_in = AUTH_NONE; qp->q_authenver_in = ZERO; qp->q_authentype_out = AUTH_NONE; qp->q_authenver_out = ZERO; } #endif AUTHEN if ((qp->q_msg = malloc(BUFSIZ)) == NULL) { qfree(qp);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?