ns_forw.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 864 行 · 第 1/2 页
C
864 行
if (found_arr == 0 && qp->q_system == 0) (void) sysquery(dname, class, T_A);skipserver: ; }out:#ifdef DEBUG if (debug >= 3) fprintf(ddt,"nslookup: %d ns addrs total\n", n);#endif qp->q_naddr = n; if (n > 1) qsort((char *)qp->q_addr, n, sizeof(struct qserv), qcomp); return (n - naddr);}qcomp(qs1, qs2) struct qserv *qs1, *qs2;{ return (qs1->nsdata->d_nstime - qs2->nsdata->d_nstime);}/* * Arrange that forwarded query (qp) is retried after t seconds. */schedretry(qp, t) struct qinfo *qp; time_t t;{ register struct qinfo *qp1, *qp2;#ifdef DEBUG if (debug > 3) { fprintf(ddt,"schedretry(%#x, %dsec)\n", qp, t); if (qp->q_time) fprintf(ddt,"WARNING: schedretry(%x,%d) q_time already %d\n", qp->q_time); }#endif t += (u_long) tt.tv_sec; qp->q_time = t; if ((qp1 = retryqp) == NULL) { retryqp = qp; qp->q_next = NULL; return; } while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t) qp1 = qp2;#ifdef ULTRIXFUNC if(qp1 == retryqp) if(qp1->q_time > t) { retryqp = qp; retryqp->q_next= qp1; return; }#endif ULTRIXFUNC qp1->q_next = qp; qp->q_next = qp2;}/* * Unsched is called to remove a forwarded query entry. */unsched(qp) struct qinfo *qp;{ register struct qinfo *np;#ifdef DEBUG if (debug > 3) { fprintf(ddt,"unsched(%#x, %d )\n", qp, ntohs(qp->q_id)); }#endif if( retryqp == qp ) { retryqp = qp->q_next; } else { for( np=retryqp; np->q_next != QINFO_NULL; np = np->q_next ) { if( np->q_next != qp) continue; np->q_next = qp->q_next; /* dequeue */ break; } } qp->q_next = QINFO_NULL; /* sanity check */ qp->q_time = 0;}/* * Retry is called to retransmit query 'qp'. */retry(qp) register struct qinfo *qp;{ register int n; register HEADER *hp;#ifdef AUTHEN char *dnameptr; int authen_len; int m; char *krbnameptr; char *src; char *dest;#endif AUTHEN#ifdef DEBUG if (debug > 3) fprintf(ddt,"retry(x%x) id=%d\n", qp, ntohs(qp->q_id));#endif if((HEADER *)qp->q_msg == NULL) { /*** XXX ***/ qremove(qp); return; } /*** XXX ***/ /* try next address */ n = qp->q_curaddr; if (qp->q_fwd) { qp->q_fwd = qp->q_fwd->next; if (qp->q_fwd) goto found; /* out of forwarders, try direct queries */ } else ++qp->q_addr[n].nretry; if (!forward_only) { do { if (++n >= qp->q_naddr) n = 0; if (qp->q_addr[n].nretry < MAXRETRY) goto found; } while (n != qp->q_curaddr); } /* * Give up. Can't reach destination. */ hp = (HEADER *)(qp->q_cmsg ? qp->q_cmsg : qp->q_msg); if (qp->q_system == PRIMING_CACHE) { /* Can't give up priming */ unsched(qp); schedretry(qp, (time_t)60*60); /* 1 hour */ hp->rcode = NOERROR; /* Lets be safe, reset the query */ hp->qr = hp->aa = 0;#ifdef ULTRIXFUNC qp->q_fwd = qp->q_fwdorig;#else ULTRIXFUNC qp->q_fwd = fwdtab;#endif ULTRIXFUNC for (n = 0; n < qp->q_naddr; n++) qp->q_addr[n].nretry = 0; return; }#ifdef DEBUG if (debug >= 5) fprintf(ddt,"give up\n");#endif n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen); hp->id = qp->q_id; hp->qr = 1; hp->ra = 1; hp->rd = 1; hp->rcode = SERVFAIL;#ifdef DEBUG if (debug >= 10) fp_query(qp->q_msg, ddt);#endif#ifdef AUTHEN authen_len = dn_skipname((u_char *)hp + sizeof(HEADER), (u_char *)hp + n); if(hp->opcode = AQUERY && qp->q_type_in == QUERY && qp->q_type_out == AQUERY && n - (sizeof(HEADER) + authen_len + AQFIXEDSZ) > 0) { if(fixup_rrs((char *)hp + sizeof(HEADER) + authen_len + AQFIXEDSZ, n - (sizeof(HEADER) + authen_len + AQFIXEDSZ), (int)(sizeof(HEADER) + authen_len), -(2 * sizeof(u_short))) < 0) { qremove(qp); return; } dest = authen_len + sizeof(HEADER) + (2 * sizeof(u_short)) + (char *)hp; src = dest + (2 * sizeof(u_short)); bcopy(src, dest, n - (src - (char *)hp)); hp->opcode = QUERY; n -= 2 * sizeof(u_short); } if((hp->opcode == AQUERY && qp->q_authentype_in == AUTH_KRB && qp->q_authenver_in == ONE)) { dnameptr = qp->q_dname; if (qp->q_type != T_SOA && qp->q_type != T_AXFR) res_dotname_rmhead(&dnameptr); hp->arcount = htons(1); if((authen_len = res_mks_krbcred(ONE, "", "", qp->q_ad, hp, hp + n, BUFSIZ - n, dnameptr, qp->q_type, qp->q_class)) < RET_OK) { qremove(qp); return; } n += authen_len; }#endif AUTHEN if (send_msg((char *)hp, n, qp)) {#ifdef DEBUG if (debug) fprintf(ddt,"gave up retry(x%x) nsid=%d id=%d\n", qp, ntohs(qp->q_nsid), ntohs(qp->q_id));#endif } qremove(qp); return;found: if (qp->q_fwd == 0 && qp->q_addr[n].nretry == 0) qp->q_addr[n].stime = tt; qp->q_curaddr = n; hp = (HEADER *)qp->q_msg; hp->rd = (qp->q_fwd ? 1 : 0);#ifdef DEBUG if (debug) if(qp->q_addr[n].nsdata) fprintf(ddt,"%s(addr=%d n=%d) -> %s %d (%d) nsid=%d id=%d %dms\n", (qp->q_fwd ? "reforw" : "resend"), n, qp->q_addr[n].nretry, inet_ntoa(Q_NEXTADDR(qp,n)->sin_addr), ds, ntohs(Q_NEXTADDR(qp,n)->sin_port), ntohs(qp->q_nsid), ntohs(qp->q_id), qp->q_addr[n].nsdata->d_nstime); else fprintf(ddt,"%s(addr=%d n=%d) -> %s %d (%d) nsid=%d id=%d\n", (qp->q_fwd ? "reforw" : "resend"), n, qp->q_addr[n].nretry, inet_ntoa(Q_NEXTADDR(qp,n)->sin_addr), ds, ntohs(Q_NEXTADDR(qp,n)->sin_port), ntohs(qp->q_nsid), ntohs(qp->q_id)); if ( debug >= 10) fp_query(qp->q_msg, ddt);#endif. /* NOSTRICT */#ifdef AUTHEN m = qp->q_msglen; if((hp->opcode == AQUERY && qp->q_authentype_out == AUTH_KRB && qp->q_authenver_out == ONE)) { krbnameptr = res_dotname_head(Q_NEXTNAME(qp, n)); dnameptr = qp->q_dname_curr; if (qp->q_type_curr != T_SOA && qp->q_type_curr != T_AXFR) res_dotname_rmhead(&dnameptr); hp->arcount = htons(1); if((authen_len = res_mkl_krbcred(ONE, "named", krbnameptr, Q_NEXTCRED(qp,n), hp, m + (char *)hp, BUFSIZ - m, dnameptr, qp->q_type_curr, qp->q_class_curr)) < RET_OK) { free(krbnameptr); qremove(qp); return; } free(krbnameptr); m += authen_len; }#endif AUTHEN #ifdef AUTHEN if (sendto(ds, qp->q_msg, m, 0, (struct sockaddr *)Q_NEXTADDR(qp,n), sizeof(struct sockaddr_in)) < 0){#else AUTHEN if (sendto(ds, qp->q_msg, qp->q_msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,n), sizeof(struct sockaddr_in)) < 0){#endif AUTHEN#ifdef DEBUG if (debug > 3) fprintf(ddt,"error resending msg errno=%d\n",errno);#endif } hp->rd = 0; /* leave set to 0 for dup detection */#ifdef STATS stats[S_OUTPKTS].cnt++;#endif unsched(qp); schedretry(qp, qp->q_fwd ? (2*RETRYBASE) : retrytime(qp)); return;}/* * Compute retry time for the next server for a query. * Use a minimum time of RETRYBASE (4 sec.) or twice the estimated * service time; * back off exponentially on retries, but place a 45-sec. * ceiling on retry times for now. (This is because we don't hold a reference * on servers or their addresses, and we have to finish before they time out.) */time_tretrytime(qp)register struct qinfo *qp;{ time_t t; struct qserv *ns = &qp->q_addr[qp->q_curaddr];#ifdef DEBUG if (debug > 3) fprintf(ddt,"retrytime: nstime %dms.\n", ns->nsdata->d_nstime / 1000);#endif t = (time_t) MAX(RETRYBASE, 2 * ns->nsdata->d_nstime / 1000); t <<= ns->nretry; t = MIN(t, 45); /* max. retry timeout for now */#ifdef notdef if (qp->q_system) return ((2 * t) + 5); /* system queries can wait. */#endif return (t);}qflush(){ while (qhead) qremove(qhead); qhead = QINFO_NULL;}qremove(qp)register struct qinfo *qp;{#ifdef DEBUG if(debug > 3) fprintf(ddt,"qremove(x%x)\n", qp);#endif unsched(qp); /* get off queue first */ qfree(qp);}struct qinfo *qfindid(id)register u_short id;{ register struct qinfo *qp;#ifdef DEBUG if(debug > 3) fprintf(ddt,"qfindid(%d)\n", ntohs(id));#endif for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) { if (qp->q_nsid == id) return(qp); }#ifdef DEBUG if (debug >= 5) fprintf(ddt,"qp not found\n");#endif return(NULL);}struct qinfo *qnew(){ register struct qinfo *qp; if ((qp = (struct qinfo *)calloc(1, sizeof(struct qinfo))) == NULL) {#ifdef DEBUG if (debug >= 5) fprintf(ddt,"qnew: calloc error\n");#endif syslog(LOG_ERR, "forw: %m"); exit(12); }#ifdef DEBUG if (debug >= 5) fprintf(ddt,"qnew(x%x)\n", qp);#endif qp->q_link = qhead; qhead = qp; return( qp );}qfree(qp)struct qinfo *qp;{ register struct qinfo *np;#ifdef ULTRIXFUNC struct fwdinfo *fwd_ptr; struct fwdinfo *temp_ptr;#endif ULTRIXFUNC#ifdef DEBUG if(debug > 3) fprintf(ddt,"qfree( x%x )\n", qp); if(debug && qp->q_next) fprintf(ddt,"WARNING: qfree of linked ptr x%x\n", qp);#endif if (qp->q_msg) free(qp->q_msg); if (qp->q_cmsg) free(qp->q_cmsg); if( qhead == qp ) { qhead = qp->q_link; } else { for( np=qhead; np->q_link != QINFO_NULL; np = np->q_link ) { if( np->q_link != qp ) continue; np->q_link = qp->q_link; /* dequeue */ break; } }#ifdef ULTRIXFUNC for(fwd_ptr = qp->q_fwdorig; fwd_ptr != NULL; temp_ptr = fwd_ptr, fwd_ptr = fwd_ptr->next, free(temp_ptr));#endif ULTRIXFUNC (void)free((char *)qp);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?