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 + -
显示快捷键?