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

📄 res_send.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
				}				res_close();				goto next_ns;			}			resplen = ns_get16(ans);			if (resplen > anssiz) {				Dprint(_res.options & RES_DEBUG,				       (stdout, ";; response truncated\n")				       );				truncated = 1;				len = anssiz;			} else				len = resplen;			if (len < HFIXEDSZ) {				/*				 * Undersized message.				 */				Dprint(_res.options & RES_DEBUG,				       (stdout, ";; undersized: %d\n", len));				terrno = EMSGSIZE;				badns |= (1 << ns);				res_close();				goto next_ns;			}			cp = ans;			while (len != 0 &&			       (n = read(s, (char *)cp, (int)len)) > 0) {				cp += n;				len -= n;			}			if (n <= 0) {				terrno = errno;				Perror(stderr, "read(vc)", errno);				res_close();				goto next_ns;			}			if (truncated) {				/*				 * Flush rest of answer				 * so connection stays in synch.				 */				anhp->tc = 1;				len = resplen - anssiz;				while (len != 0) {					char junk[PACKETSZ];					n = (len > sizeof(junk)					     ? sizeof(junk)					     : len);					if ((n = read(s, junk, n)) > 0)						len -= n;					else						break;				}			}			/*			 * 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. Anyway drop the packet and			 * wait for the correct one.			 */			if (hp->id != anhp->id) {				DprintQ((_res.options & RES_DEBUG) ||					(_res.pfcode & RES_PRF_REPLY),					(stdout, ";; old answer (unexpected):\n"),					ans, (resplen>anssiz)?anssiz:resplen);				goto read_len;			}		} else {			/*			 * Use datagrams.			 */#ifndef NOPOLL			struct pollfd pfd;			int msec;#endif			struct timeval timeout;#ifndef NOSELECT			fd_set dsmask, *dsmaskp;			int dsmasklen;#endif			struct sockaddr_in from;			int fromlen;			if ((s < 0) || vc) {				if (vc)					res_close();				s = socket(PF_INET, SOCK_DGRAM, 0);				if (s < 0) {#ifndef CAN_RECONNECT bad_dg_sock:#endif					terrno = errno;					Perror(stderr, "socket(dg)", errno);					return (-1);				}				connected = 0;			}#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 we have sent queries to at least two servers,			 * however, we don't want to remain connected,			 * as we wish to receive answers from the first			 * server to respond.			 */			if (_res.nscount == 1 || (try == 0 && ns == 0)) {				/*				 * Connect only if we are sure we won't				 * receive a response from another server.				 */				if (!connected) {					if (connect(s, (struct sockaddr *)nsap,						    sizeof *nsap						    ) < 0) {						Aerror(stderr,						       "connect(dg)",						       errno, *nsap);						badns |= (1 << ns);						res_close();						goto next_ns;					}					connected = 1;				}				if (send(s, (char*)buf, buflen, 0) != buflen) {					Perror(stderr, "send", errno);					badns |= (1 << ns);					res_close();					goto next_ns;				}			} else {				/*				 * Disconnect if we want to listen				 * for responses from more than one server.				 */				if (connected) {#ifdef CAN_RECONNECT					struct sockaddr_in no_addr;					no_addr.sin_family = AF_INET;					no_addr.sin_addr.s_addr = INADDR_ANY;					no_addr.sin_port = 0;					(void) connect(s,						       (struct sockaddr *)						        &no_addr,						       sizeof no_addr);#else					int s1 = socket(PF_INET, SOCK_DGRAM,0);					if (s1 < 0)						goto bad_dg_sock;					(void) dup2(s1, s);					(void) close(s1);					Dprint(_res.options & RES_DEBUG,						(stdout, ";; new DG socket\n"))#endif /* CAN_RECONNECT */					connected = 0;					errno = 0;				}#endif /* !CANNOT_CONNECT_DGRAM */				if (sendto(s, (char*)buf, buflen, 0,					   (struct sockaddr *)nsap,					   sizeof *nsap)				    != buflen) {					Aerror(stderr, "sendto", errno, *nsap);					badns |= (1 << ns);					res_close();					goto next_ns;				}#ifndef CANNOT_CONNECT_DGRAM			}#endif /* !CANNOT_CONNECT_DGRAM */			/*			 * Wait for reply			 */#ifndef NOPOLL    othersyscall:			if (use_poll) {				msec = (_res.retrans << try) * 1000;				if (try > 0)					msec /= _res.nscount;				if (msec <= 0)					msec = 1000;			} else {#endif				timeout.tv_sec = (_res.retrans << try);				if (try > 0)					timeout.tv_sec /= _res.nscount;				if ((long) timeout.tv_sec <= 0)					timeout.tv_sec = 1;				timeout.tv_usec = 0;#ifndef NOPOLL			}#endif    wait:			if (s < 0) {				Perror(stderr, "s out-of-bounds", EMFILE);				res_close();				goto next_ns;			}#ifndef NOPOLL			if (use_poll) {				struct sigaction sa, osa;				int sigsys_installed = 0;				pfd.fd = s;				pfd.events = POLLIN;				if (use_poll == 1) {					bzero(&sa, sizeof(sa));					sa.sa_handler = SIG_IGN;					if (sigaction(SIGSYS, &sa, &osa) >= 0)						sigsys_installed = 1;				}				n = poll(&pfd, 1, msec);				if (sigsys_installed == 1) {					int oerrno = errno;					sigaction(SIGSYS, &osa, NULL);					errno = oerrno;				}				/* XXX why does nosys() return EINVAL? */				if (n < 0 && (errno == ENOSYS ||				    errno == EINVAL)) {					use_poll = 0;					goto othersyscall;				} else if (use_poll == 1)					use_poll = 2;				if (n < 0) {					if (errno == EINTR)						goto wait;					Perror(stderr, "poll", errno);					res_close();					goto next_ns;				}			} else {#endif#ifndef NOSELECT				dsmasklen = howmany(s + 1, NFDBITS) *					    sizeof(fd_mask);				if (dsmasklen > sizeof(fd_set)) {					dsmaskp = (fd_set *)malloc(dsmasklen);					if (dsmaskp == NULL) {						res_close();						goto next_ns;					}				} else					dsmaskp = &dsmask;				/* only zero what we need */				bzero((char *)dsmaskp, dsmasklen);				FD_SET(s, dsmaskp);				n = select(s + 1, dsmaskp, (fd_set *)NULL,					   (fd_set *)NULL, &timeout);				if (dsmaskp != &dsmask)					free(dsmaskp);				if (n < 0) {					if (errno == EINTR)						goto wait;					Perror(stderr, "select", errno);					res_close();					goto next_ns;				}#endif#ifndef NOPOLL			}#endif#ifdef NOSELECT			setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);#else			if (n == 0) {				/*				 * timeout				 */				Dprint(_res.options & RES_DEBUG,				       (stdout, ";; timeout\n"));				gotsomewhere = 1;				res_close();				goto next_ns;			}#endif			errno = 0;			fromlen = sizeof(struct sockaddr_in);			resplen = recvfrom(s, (char*)ans, anssiz, 0,					   (struct sockaddr *)&from, &fromlen);			if (resplen <= 0) {#ifdef NOSELECT				if (errno == ETIMEDOUT) {					Dprint(_res.options & RES_DEBUG,					       (stdout, ";; timeout\n"));					gotsomewhere = 1;					res_close();					goto next_ns;				}#endif				Perror(stderr, "recvfrom", errno);				res_close();				goto next_ns;			}			gotsomewhere = 1;			if (resplen < HFIXEDSZ) {				/*				 * Undersized message.				 */				Dprint(_res.options & RES_DEBUG,				       (stdout, ";; undersized: %d\n",					resplen));				terrno = EMSGSIZE;				badns |= (1 << ns);				res_close();				goto next_ns;			}			if (hp->id != anhp->id) {				/*				 * response from old query, ignore it.				 * XXX - potential security hazard could				 *	 be detected here.				 */				DprintQ((_res.options & RES_DEBUG) ||					(_res.pfcode & RES_PRF_REPLY),					(stdout, ";; old answer:\n"),					ans, (resplen>anssiz)?anssiz:resplen);				goto wait;			}#ifdef CHECK_SRVR_ADDR			if (!(_res.options & RES_INSECURE1) &&			    !res_isourserver(&from)) {				/*				 * response from wrong server? ignore it.				 * XXX - potential security hazard could				 *	 be detected here.				 */				DprintQ((_res.options & RES_DEBUG) ||					(_res.pfcode & RES_PRF_REPLY),					(stdout, ";; not our server:\n"),					ans, (resplen>anssiz)?anssiz:resplen);				goto wait;			}#endif			if (!(_res.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((_res.options & RES_DEBUG) ||					(_res.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(_res.options & RES_DEBUG,					(stdout, "server rejected query:\n"),					ans, (resplen>anssiz)?anssiz:resplen);				badns |= (1 << ns);				res_close();				/* don't retry if called from dig */				if (!_res.pfcode)					goto next_ns;			}			if (!(_res.options & RES_IGNTC) && anhp->tc) {				/*				 * get rest of answer;				 * use TCP with same server.				 */				Dprint(_res.options & RES_DEBUG,				       (stdout, ";; truncated answer\n"));				v_circuit = 1;				res_close();				goto same_ns;			}		} /*if vc/dg*/		Dprint((_res.options & RES_DEBUG) ||		       ((_res.pfcode & RES_PRF_REPLY) &&			(_res.pfcode & RES_PRF_HEAD1)),		       (stdout, ";; got answer:\n"));		DprintQ((_res.options & RES_DEBUG) ||			(_res.pfcode & RES_PRF_REPLY),			(stdout, "%s", ""),			ans, (resplen>anssiz)?anssiz:resplen);		/*		 * If using virtual circuits, we assume that the first server		 * is preferred over the rest (i.e. it is on the local		 * machine) and only keep that one open.		 * If we have temporarily opened a virtual circuit,		 * or if we haven't been asked to keep a socket open,		 * close the socket.		 */		if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||		    !(_res.options & RES_STAYOPEN)) {			res_close();		}		if (Rhook) {			int done = 0, loops = 0;			do {				res_sendhookact act;				act = (*Rhook)(nsap, buf, buflen,					       ans, anssiz, &resplen);				switch (act) {				case res_goahead:				case res_done:					done = 1;					break;				case res_nextns:					res_close();					goto next_ns;				case res_modified:					/* give the hook another try */					if (++loops < 42) /*doug adams*/						break;					/*FALLTHROUGH*/				case res_error:					/*FALLTHROUGH*/				default:					return (-1);				}			} while (!done);		}		return (resplen);    next_ns: ;	   } /*foreach ns*/	} /*foreach retry*/	res_close();	if (!v_circuit) {		if (!gotsomewhere)			errno = ECONNREFUSED;	/* no nameservers found */		else			errno = ETIMEDOUT;	/* no answer obtained */	} else		errno = terrno;	return (-1);}/* * This routine is for closing the socket if a virtual circuit is used and * the program wants to close it.  This provides support for endhostent() * which expects to close the socket. * * This routine is not expected to be user visible. */voidres_close(){	if (s >= 0) {		(void) close(s);		s = -1;		connected = 0;		vc = 0;	}}

⌨️ 快捷键说明

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