⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 res_send.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef HAVE_SA_LEN	/* There are people do not set sa_len.  Be forgiving to them. */	if (sa->sa_len)		return (sa->sa_len);#endif	if (sa->sa_family == AF_INET)		return (sizeof(struct sockaddr_in));	else if (sa->sa_family == AF_INET6)		return (sizeof(struct sockaddr_in6));	else		return (0);	/* unknown, die on connect */}/* * pick appropriate nsaddr_list for use.  see res_init() for initialization. */static struct sockaddr *get_nsaddr(statp, n)	res_state statp;	size_t n;{	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {		/*		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger		 *   than struct sockaddr, and		 * - user code did not update statp->nsaddr_list[n].		 */		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];	} else {		/*		 * - user code updated statp->nsaddr_list[n], or		 * - statp->nsaddr_list[n] has the same content as		 *   EXT(statp).ext->nsaddrs[n].		 */		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];	}}static intsend_vc(res_state statp,	const u_char *buf, int buflen, u_char *ans, int anssiz,	int *terrno, int ns){	const HEADER *hp = (const HEADER *) buf;	HEADER *anhp = (HEADER *) ans;	struct sockaddr *nsap;	int nsaplen;	int truncating, connreset, resplen, n;	struct iovec iov[2];	u_short len;	u_char *cp;	void *tmp;	nsap = get_nsaddr(statp, ns);	nsaplen = get_salen(nsap);	connreset = 0; same_ns:	truncating = 0;	/* Are we still talking to whom we want to talk to? */	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {		struct sockaddr_storage peer;		ISC_SOCKLEN_T size = sizeof peer;		if (getpeername(statp->_vcsock,				(struct sockaddr *)&peer, &size) < 0 ||		    !sock_eq((struct sockaddr *)&peer, nsap)) {			res_nclose(statp);			statp->_flags &= ~RES_F_VC;		}	}	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {		if (statp->_vcsock >= 0)			res_nclose(statp);		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);		if (statp->_vcsock > highestFD) {			res_nclose(statp);			errno = ENOTSOCK;		}		if (statp->_vcsock < 0) {			switch (errno) {			case EPROTONOSUPPORT:#ifdef EPFNOSUPPORT			case EPFNOSUPPORT:#endif			case EAFNOSUPPORT:				Perror(statp, stderr, "socket(vc)", errno);				return (0);			default:				*terrno = errno;				Perror(statp, stderr, "socket(vc)", errno);				return (-1);			}		}		errno = 0;		if (connect(statp->_vcsock, nsap, nsaplen) < 0) {			*terrno = errno;			Aerror(statp, stderr, "connect/vc", errno, nsap,			    nsaplen);			res_nclose(statp);			return (0);		}		statp->_flags |= RES_F_VC;	}	/*	 * Send length & message	 */	ns_put16((u_short)buflen, (u_char*)&len);	iov[0] = evConsIovec(&len, INT16SZ);	DE_CONST(buf, tmp);	iov[1] = evConsIovec(tmp, buflen);	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {		*terrno = errno;		Perror(statp, stderr, "write failed", errno);		res_nclose(statp);		return (0);	}	/*	 * Receive length & response	 */ read_len:	cp = ans;	len = INT16SZ;	while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) {		cp += n;		if ((len -= n) == 0)			break;	}	if (n <= 0) {		*terrno = errno;		Perror(statp, stderr, "read failed", errno);		res_nclose(statp);		/*		 * A long running process might get its TCP		 * connection reset if the remote server was		 * restarted.  Requery the server instead of		 * trying a new one.  When there is only one		 * server, this means that a query might work		 * instead of failing.  We only allow one reset		 * per query to prevent looping.		 */		if (*terrno == ECONNRESET && !connreset) {			connreset = 1;			res_nclose(statp);			goto same_ns;		}		res_nclose(statp);		return (0);	}	resplen = ns_get16(ans);	if (resplen > anssiz) {		Dprint(statp->options & RES_DEBUG,		       (stdout, ";; response truncated\n")		       );		truncating = 1;		len = anssiz;	} else		len = resplen;	if (len < HFIXEDSZ) {		/*		 * Undersized message.		 */		Dprint(statp->options & RES_DEBUG,		       (stdout, ";; undersized: %d\n", len));		*terrno = EMSGSIZE;		res_nclose(statp);		return (0);	}	cp = ans;	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){		cp += n;		len -= n;	}	if (n <= 0) {		*terrno = errno;		Perror(statp, stderr, "read(vc)", errno);		res_nclose(statp);		return (0);	}	if (truncating) {		/*		 * Flush rest of answer so connection stays in synch.		 */		anhp->tc = 1;		len = resplen - anssiz;		while (len != 0) {			char junk[PACKETSZ];			n = read(statp->_vcsock, junk,				 (len > sizeof junk) ? sizeof junk : len);			if (n > 0)				len -= n;			else				break;		}	}	/*	 * If the calling applicating has bailed out of	 * a previous call and failed to arrange to have	 * the circuit closed or the server has got	 * itself confused, then drop the packet and	 * wait for the correct one.	 */	if (hp->id != anhp->id) {		DprintQ((statp->options & RES_DEBUG) ||			(statp->pfcode & RES_PRF_REPLY),			(stdout, ";; old answer (unexpected):\n"),			ans, (resplen > anssiz) ? anssiz: resplen);		goto read_len;	}	/*	 * All is well, or the error is fatal.  Signal that the	 * next nameserver ought not be tried.	 */	return (resplen);}static intsend_dg(res_state statp,	const u_char *buf, int buflen, u_char *ans, int anssiz,	int *terrno, int ns, int *v_circuit, int *gotsomewhere){	const HEADER *hp = (const HEADER *) buf;	HEADER *anhp = (HEADER *) ans;	const struct sockaddr *nsap;	int nsaplen;	struct timespec now, timeout, finish;	fd_set dsmask;	struct sockaddr_storage from;	ISC_SOCKLEN_T fromlen;	int resplen, seconds, n, s;	nsap = get_nsaddr(statp, ns);	nsaplen = get_salen(nsap);	if (EXT(statp).nssocks[ns] == -1) {		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);		if (EXT(statp).nssocks[ns] > highestFD) {			res_nclose(statp);			errno = ENOTSOCK;		}		if (EXT(statp).nssocks[ns] < 0) {			switch (errno) {			case EPROTONOSUPPORT:#ifdef EPFNOSUPPORT			case EPFNOSUPPORT:#endif			case EAFNOSUPPORT:				Perror(statp, stderr, "socket(dg)", errno);				return (0);			default:				*terrno = errno;				Perror(statp, stderr, "socket(dg)", errno);				return (-1);			}		}#ifndef CANNOT_CONNECT_DGRAM		/*		 * On a 4.3BSD+ machine (client and server,		 * actually), sending to a nameserver datagram		 * port with no nameserver will cause an		 * ICMP port unreachable message to be returned.		 * If our datagram socket is "connected" to the		 * server, we get an ECONNREFUSED error on the next		 * socket operation, and select returns if the		 * error message is received.  We can thus detect		 * the absence of a nameserver without timing out.		 */		if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {			Aerror(statp, stderr, "connect(dg)", errno, nsap,			    nsaplen);			res_nclose(statp);			return (0);		}#endif /* !CANNOT_CONNECT_DGRAM */		Dprint(statp->options & RES_DEBUG,		       (stdout, ";; new DG socket\n"))	}	s = EXT(statp).nssocks[ns];#ifndef CANNOT_CONNECT_DGRAM	if (send(s, (const char*)buf, buflen, 0) != buflen) {		Perror(statp, stderr, "send", errno);		res_nclose(statp);		return (0);	}#else /* !CANNOT_CONNECT_DGRAM */	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)	{		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);		res_nclose(statp);		return (0);	}#endif /* !CANNOT_CONNECT_DGRAM */	/*	 * Wait for reply.	 */	seconds = (statp->retrans << ns);	if (ns > 0)		seconds /= statp->nscount;	if (seconds <= 0)		seconds = 1;	now = evNowTime();	timeout = evConsTime(seconds, 0);	finish = evAddTime(now, timeout);	goto nonow; wait:	now = evNowTime(); nonow:	FD_ZERO(&dsmask);	FD_SET(s, &dsmask);	if (evCmpTime(finish, now) > 0)		timeout = evSubTime(finish, now);	else		timeout = evConsTime(0, 0);	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);	if (n == 0) {		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));		*gotsomewhere = 1;		return (0);	}	if (n < 0) {		if (errno == EINTR)			goto wait;		Perror(statp, stderr, "select", errno);		res_nclose(statp);		return (0);	}	errno = 0;	fromlen = sizeof(from);	resplen = recvfrom(s, (char*)ans, anssiz,0,			   (struct sockaddr *)&from, &fromlen);	if (resplen <= 0) {		Perror(statp, stderr, "recvfrom", errno);		res_nclose(statp);		return (0);	}	*gotsomewhere = 1;	if (resplen < HFIXEDSZ) {		/*		 * Undersized message.		 */		Dprint(statp->options & RES_DEBUG,		       (stdout, ";; undersized: %d\n",			resplen));		*terrno = EMSGSIZE;		res_nclose(statp);		return (0);	}	if (hp->id != anhp->id) {		/*		 * response from old query, ignore it.		 * XXX - potential security hazard could		 *	 be detected here.		 */		DprintQ((statp->options & RES_DEBUG) ||			(statp->pfcode & RES_PRF_REPLY),			(stdout, ";; old answer:\n"),			ans, (resplen > anssiz) ? anssiz : resplen);		goto wait;	}	if (!(statp->options & RES_INSECURE1) &&	    !res_ourserver_p(statp, (struct sockaddr *)&from)) {		/*		 * response from wrong server? ignore it.		 * XXX - potential security hazard could		 *	 be detected here.		 */		DprintQ((statp->options & RES_DEBUG) ||			(statp->pfcode & RES_PRF_REPLY),			(stdout, ";; not our server:\n"),			ans, (resplen > anssiz) ? anssiz : resplen);		goto wait;	}#ifdef RES_USE_EDNS0	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {		/*		 * Do not retry if the server do not understand EDNS0.		 * The case has to be captured here, as FORMERR packet do not		 * carry query section, hence res_queriesmatch() returns 0.		 */		DprintQ(statp->options & RES_DEBUG,			(stdout, "server rejected query with EDNS0:\n"),			ans, (resplen > anssiz) ? anssiz : resplen);		/* record the error */		statp->_flags |= RES_F_EDNS0ERR;		res_nclose(statp);		return (0);	}#endif	if (!(statp->options & RES_INSECURE2) &&	    !res_queriesmatch(buf, buf + buflen,			      ans, ans + anssiz)) {		/*		 * response contains wrong query? ignore it.		 * XXX - potential security hazard could		 *	 be detected here.		 */		DprintQ((statp->options & RES_DEBUG) ||			(statp->pfcode & RES_PRF_REPLY),			(stdout, ";; wrong query name:\n"),			ans, (resplen > anssiz) ? anssiz : resplen);		goto wait;	}	if (anhp->rcode == SERVFAIL ||	    anhp->rcode == NOTIMP ||	    anhp->rcode == REFUSED) {		DprintQ(statp->options & RES_DEBUG,			(stdout, "server rejected query:\n"),			ans, (resplen > anssiz) ? anssiz : resplen);		res_nclose(statp);		/* don't retry if called from dig */		if (!statp->pfcode)			return (0);	}	if (!(statp->options & RES_IGNTC) && anhp->tc) {		/*		 * To get the rest of answer,		 * use TCP with same server.		 */		Dprint(statp->options & RES_DEBUG,		       (stdout, ";; truncated answer\n"));		*v_circuit = 1;		res_nclose(statp);		return (1);	}	/*	 * All is well, or the error is fatal.  Signal that the	 * next nameserver ought not be tried.	 */	return (resplen);}static voidAerror(const res_state statp, FILE *file, const char *string, int error,       const struct sockaddr *address, int alen){	int save = errno;	char hbuf[NI_MAXHOST];	char sbuf[NI_MAXSERV];	alen = alen;	if ((statp->options & RES_DEBUG) != 0U) {		if (getnameinfo(address, alen, hbuf, sizeof(hbuf),		    sbuf, sizeof(sbuf), niflags)) {			strncpy(hbuf, "?", sizeof(hbuf) - 1);			hbuf[sizeof(hbuf) - 1] = '\0';			strncpy(sbuf, "?", sizeof(sbuf) - 1);			sbuf[sizeof(sbuf) - 1] = '\0';		}		fprintf(file, "res_send: %s ([%s].%s): %s\n",			string, hbuf, sbuf, strerror(error));	}	errno = save;}static voidPerror(const res_state statp, FILE *file, const char *string, int error) {	int save = errno;	if ((statp->options & RES_DEBUG) != 0U)		fprintf(file, "res_send: %s: %s\n",			string, strerror(error));	errno = save;}static intsock_eq(struct sockaddr *a, struct sockaddr *b) {	struct sockaddr_in *a4, *b4;	struct sockaddr_in6 *a6, *b6;	if (a->sa_family != b->sa_family)		return 0;	switch (a->sa_family) {	case AF_INET:		a4 = (struct sockaddr_in *)a;		b4 = (struct sockaddr_in *)b;		return a4->sin_port == b4->sin_port &&		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;	case AF_INET6:		a6 = (struct sockaddr_in6 *)a;		b6 = (struct sockaddr_in6 *)b;		return a6->sin6_port == b6->sin6_port &&#ifdef HAVE_SIN6_SCOPE_ID		    a6->sin6_scope_id == b6->sin6_scope_id &&#endif		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);	default:		return 0;	}}#ifdef NEED_PSELECT/* XXX needs to move to the porting library. */static intpselect(int nfds, void *rfds, void *wfds, void *efds,	struct timespec *tsp, const sigset_t *sigmask){	struct timeval tv, *tvp;	sigset_t sigs;	int n;	if (tsp) {		tvp = &tv;		tv = evTimeVal(*tsp);	} else		tvp = NULL;	if (sigmask)		sigprocmask(SIG_SETMASK, sigmask, &sigs);	n = select(nfds, rfds, wfds, efds, tvp);	if (sigmask)		sigprocmask(SIG_SETMASK, &sigs, NULL);	if (tsp)		*tsp = evTimeSpec(tv);	return (n);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -