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

📄 res_send.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * 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)) {				/*				 * Don't use connect if we might				 * still receive a response				 * from another server.				 */				if (connected == 0) {			if (connect(s, (struct sockaddr *)&_res.nsaddr_list[ns],					    sizeof(struct sockaddr)) < 0) {#ifdef DEBUG						if (_res.options & RES_DEBUG)							perror("connect");#endif /* DEBUG */						continue;					}					connected = 1;				}				if (send(s, buf, buflen, 0) != buflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("send");#endif /* DEBUG */					continue;				}			} else {				/*				 * Disconnect if we want to listen				 * for responses from more than one server.				 */				if (connected) {					(void) connect(s, &no_addr,					    sizeof(no_addr));					connected = 0;				}#endif /* BSD */				if (sendto(s, buf, buflen, 0,				    (struct sockaddr *)&_res.nsaddr_list[ns],				    sizeof(struct sockaddr)) != buflen) {#ifdef DEBUG					if (_res.options & RES_DEBUG)						perror("sendto");#endif /* DEBUG */					continue;				}#if	BSD >= 43			}#endif /* BSD */			/*			 * Wait for reply			 */			timeout.tv_sec = (_res.retrans << try);			if (try > 0)				timeout.tv_sec /= _res.nscount;			if (timeout.tv_sec <= 0)				timeout.tv_sec = 1;			timeout.tv_usec = 0;wait:			FD_ZERO(&dsmask);			FD_SET(s, &dsmask);			n = select(s+1, &dsmask, (fd_set *)NULL,				(fd_set *)NULL, &timeout);			if (n < 0) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("select");#endif /* DEBUG */				continue;			}			if (n == 0) {				/*				 * timeout				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("timeout\n");#endif /* DEBUG */#if BSD >= 43				gotsomewhere = 1;#endif				continue;			}			if ((resplen = recv(s, answer, anslen, 0)) <= 0) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("recvfrom");#endif /* DEBUG */				continue;			}			gotsomewhere = 1;			if (id != anhp->id) {				/*				 * response from old query, ignore it				 */#ifdef DEBUG				if (_res.options & RES_DEBUG) {					printf("old answer:\n");					__p_query(answer);				}#endif /* DEBUG */				goto wait;			}			if (!(_res.options & RES_IGNTC) && anhp->tc) {				/*				 * get rest of answer;				 * use TCP with same server.				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("truncated answer\n");#endif /* DEBUG */				(void) close(s);				s = -1;				v_circuit = 1;				goto usevc;			}#else /* _MINIX */			/*			 * Use datagrams.			 */			if (s < 0) {				s = udp_connect();				if (s < 0) {					terrno = errno;#ifdef DEBUG					if (_res.options & RES_DEBUG)					    perror("udp_connect failed");#endif /* DEBUG */					continue;				}			}			if (udp_sendto(s, buf, buflen, _res.nsaddr_list[ns],				_res.nsport_list[ns]) != buflen) {#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("sendto");#endif /* DEBUG */				continue;			}			/*			 * Wait for reply			 */			timeout= (_res.retrans << try);			if (try > 0)				timeout /= _res.nscount;			if (timeout <= 0)				timeout= 1;wait:			if ((resplen= udp_receive(s, answer, anslen, timeout))				== -1)			{				if (errno == EINTR)				{				/*				 * timeout				 */#ifdef DEBUG					if (_res.options & RES_DEBUG)						printf("timeout\n");#endif /* DEBUG */					gotsomewhere = 1;				}				else				{#ifdef DEBUG				if (_res.options & RES_DEBUG)					perror("udp_receive");#endif /* DEBUG */				}				continue;			}			gotsomewhere = 1;			if (id != anhp->dh_id) {				/*				 * response from old query, ignore it				 */#ifdef DEBUG				if (_res.options & RES_DEBUG) {					printf("old answer:\n");					__p_query(answer);				}#endif /* DEBUG */				goto wait;			}			if (!(_res.options & RES_IGNTC) &&				(anhp->dh_flag1 & DHF_TC)) {				/*				 * get rest of answer;				 * use TCP with same server.				 */#ifdef DEBUG				if (_res.options & RES_DEBUG)					printf("truncated answer\n");#endif /* DEBUG */				(void) close(s);				s = -1;				v_circuit = 1;				goto usevc;			}#endif /* !_MINIX */		}#ifdef DEBUG		if (_res.options & RES_DEBUG) {			printf("got answer:\n");			__p_query(answer);		}#endif /* DEBUG */		/*		 * 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) == 0 || ns != 0)) ||		    (_res.options & RES_STAYOPEN) == 0) {			(void) close(s);			s = -1;		}		return (resplen);	   }	}	if (s >= 0) {		(void) close(s);		s = -1;	}	if (v_circuit == 0)		if (gotsomewhere == 0)			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. */void_res_close(){	if (s != -1) {		(void) close(s);		s = -1;	}}#if _MINIXstatic int tcp_connect(host, port, terrno)ipaddr_t host;tcpport_t port;int *terrno;{	char *dev_name;	int fd;	int error;	nwio_tcpconf_t tcpconf;	nwio_tcpcl_t clopt;	dev_name= getenv("TCP_DEVICE");	if (!dev_name)		dev_name= TCP_DEVICE;	fd= open(dev_name, O_RDWR);	if (fd == -1)	{		*terrno= errno;		return -1;	}	tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;	tcpconf.nwtc_remaddr= host;	tcpconf.nwtc_remport= port;	error= ioctl(fd, NWIOSTCPCONF, &tcpconf);	if (error == -1)	{		*terrno= errno;		close(fd);		return -1;	}	clopt.nwtcl_flags= 0;	error= ioctl(fd, NWIOTCPCONN, &clopt);	if (error == -1)	{		*terrno= errno;		close(fd);		return -1;	}	*terrno= 0;	return fd;}static int tcpip_writeall(fd, buf, siz)int fd;const char *buf;size_t siz;{	size_t siz_org;	int nbytes;	siz_org= siz;	while (siz)	{		nbytes= write(fd, buf, siz);		if (nbytes <= 0)			return siz_org-siz;		assert(siz >= nbytes);		buf += nbytes;		siz -= nbytes;	}	return siz_org;}static int udp_connect(){	nwio_udpopt_t udpopt;	char *dev_name;	int fd, r, terrno;	dev_name= getenv("UDP_DEVICE");	if (!dev_name)		dev_name= UDP_DEVICE;	fd= open(dev_name, O_RDWR);	if (fd == -1)		return -1;	udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC |		NWUO_EN_BROAD | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL |		NWUO_DI_IPOPT;	r= ioctl(fd, NWIOSUDPOPT, &udpopt);	if (r == -1)	{		terrno= errno;		close(fd);		errno= terrno;		return -1;	}	return fd;}static int udp_sendto(fd, buf, buflen, addr, port)int fd;const char *buf;unsigned buflen;ipaddr_t addr;udpport_t port;{	char *newbuf;	udp_io_hdr_t *udp_io_hdr;	int r, terrno;	newbuf= malloc(sizeof(*udp_io_hdr) + buflen);	if (newbuf == NULL)	{		errno= ENOMEM;		return -1;	}	udp_io_hdr= (udp_io_hdr_t *)newbuf;	udp_io_hdr->uih_dst_addr= addr;	udp_io_hdr->uih_dst_port= port;	udp_io_hdr->uih_ip_opt_len= 0;	udp_io_hdr->uih_data_len= buflen;	memcpy(newbuf + sizeof(*udp_io_hdr), buf, buflen);	r= write(fd, newbuf, sizeof(*udp_io_hdr) + buflen);	terrno= errno;	free(newbuf);	if (r >= sizeof(*udp_io_hdr))		r -= sizeof(*udp_io_hdr);	errno= terrno;	return r;}static void alarm_handler(sig)int sig;{	signal(SIGALRM, alarm_handler);	alarm(1);}static int udp_receive(fd, buf, buflen, timeout)int fd;char *buf;unsigned buflen;time_t timeout;{	char *newbuf;	udp_io_hdr_t *udp_io_hdr;	int r, terrno;	void (*u_handler) _ARGS(( int sig ));	time_t u_timeout;	newbuf= malloc(sizeof(*udp_io_hdr) + buflen);	if (newbuf == NULL)	{		errno= ENOMEM;		return -1;	}	u_handler= signal(SIGALRM, alarm_handler);	u_timeout= alarm(timeout);	r= read(fd, newbuf, sizeof(*udp_io_hdr) + buflen);	terrno= errno;	if (r < 0 || r <= sizeof(*udp_io_hdr))	{		if (r > 0)			r= 0;		free(newbuf);		alarm(0);		signal(SIGALRM, u_handler);		alarm(u_timeout);		errno= terrno;		return r;	}	memcpy(buf, newbuf + sizeof(*udp_io_hdr), r - sizeof(*udp_io_hdr));	free(newbuf);	alarm(0);	signal(SIGALRM, u_handler);	alarm(u_timeout);	return r-sizeof(*udp_io_hdr);}#endif

⌨️ 快捷键说明

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