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

📄 nonamed.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Set up a listening channel for TCP DNS queries. */{	data_cl_t *data_cl= data;	nwio_tcpconf_t tcpconf;	nwio_tcpopt_t tcpopt;	int fd;	if (!expired) return 0;	if (debug >= 2) printf(": Setup listen\n");	if (data_cl == nil) {		if ((fd= open(tcp_device, O_RDWR)) < 0) {			if (errno != EMFILE) report(tcp_device);			newjob(job_setup_listen, now + SHORT_TIMEOUT, nil);			return 1;		}		tcpconf.nwtc_flags= NWTC_SHARED | NWTC_LP_SET | NWTC_UNSET_RA							| NWTC_UNSET_RP;		tcpconf.nwtc_locport= my_port;		if (ioctl(fd, NWIOSTCPCONF, &tcpconf) == -1) fatal(tcp_device);		tcpopt.nwto_flags= NWTO_DEL_RST;		if (ioctl(fd, NWIOSTCPOPT, &tcpopt) == -1) fatal(tcp_device);		data_cl= allocate(nil, sizeof(*data_cl));		data_cl->fd= fd;		data_cl->tcpcl.nwtcl_flags= 0;	}	/* And listen. */	newjob(job_listen, NEVER, data_cl);	return 1;}int job_listen(void *data, int expired)/* A connection on the TCP DNS query channel. */{	data_cl_t *data_cl= data;	/* Wait for a client. */	if (asyn_ioctl(&asyn, data_cl->fd, NWIOTCPLISTEN, &data_cl->tcpcl) < 0)	{		if (errno == EINPROGRESS) return 0;		report(tcp_device);		/* Try again after a short time. */		newjob(job_setup_listen, now + SHORT_TIMEOUT, data_cl);		return 1;	}	if (debug >= 2) printf(": Listen\n");	/* Immediately resume listening. */	newjob(job_setup_listen, IMMEDIATE, nil);	/* Set up a connect to the real name daemon in one second. */	data_cl->retry= 0;	newjob(job_setup_connect, IMMEDIATE, data_cl);	return 1;}void start_relay(int fd, int dn_fd)/* Start one or two read jobs after job_setup_connect() or job_connect(). */{	data_rw_t *query;	/* Client to DNS daemon relay. */	data_rw_t *reply;	/* DNS daemon to client relay. */	query= allocate(nil, sizeof(*query));	query->r_fd= fd;	query->buf= allocate(nil, sizeof(u16_t));	query->offset= 0;	query->size= sizeof(u16_t);	if (dn_fd == NO_FD) {		/* Answer mode. */		query->w_fd= fd;		query->rev= nil;	} else {		/* Relay mode. */		reply= allocate(nil, sizeof(*reply));		reply->r_fd= dn_fd;		reply->w_fd= fd;		reply->buf= allocate(nil, sizeof(u16_t));		reply->offset= 0;		reply->size= sizeof(u16_t);		reply->rev= query;		query->w_fd= dn_fd;		query->rev= reply;		newjob(job_read_reply, now + LONG_TIMEOUT, reply);	}	newjob(job_read_query, now + LONG_TIMEOUT, query);}void close_relay(data_rw_t *data_rw)/* Close a relay channel. */{	if (data_rw->rev != nil) {		/* Other end still active, signal EOF. */		(void) ioctl(data_rw->w_fd, NWIOTCPSHUTDOWN, nil);		data_rw->rev->rev= nil;	} else {		/* Close both ends down. */		asyn_close(&asyn, data_rw->r_fd);		close(data_rw->r_fd);		if (data_rw->w_fd != data_rw->r_fd) {			asyn_close(&asyn, data_rw->w_fd);			close(data_rw->w_fd);		}	}	deallocate(data_rw->buf);	deallocate(data_rw);}int job_setup_connect(void *data, int expired)/* Set up a connect for a TCP channel to the real name daemon. */{	nwio_tcpconf_t tcpconf;	int dn_fd;	data_cl_t *data_cl= data;	if (!expired) return 0;	if (debug >= 2) printf(": Setup connect\n");	if (named_ip == NO_IP) {		if (searching()) {			/* Wait for a name daemon to be found. */			newjob(job_setup_connect, NEVER, data_cl);			return 1;		}		/* Continue with the read job. */		start_relay(data_cl->fd, NO_FD);		deallocate(data_cl);		return 1;	}	if ((dn_fd= open(tcp_device, O_RDWR)) < 0) {		if (errno != EMFILE) report(tcp_device);		if (++data_cl->retry < 5) {			/* Retry. */			newjob(job_setup_connect, now + SHORT_TIMEOUT, data_cl);		} else {			/* Reply myself (bound to fail). */			start_relay(data_cl->fd, NO_FD);			deallocate(data_cl);		}		return 1;	}	tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;	tcpconf.nwtc_remaddr= named_ip;	tcpconf.nwtc_remport= named_port;	if (ioctl(dn_fd, NWIOSTCPCONF, &tcpconf) == -1) fatal(tcp_device);	/* And connect. */	data_cl->dn_fd= dn_fd;	data_cl->tcpcl.nwtcl_flags= 0;	newjob(job_connect, NEVER, data_cl);	return 1;}int job_connect(void *data, int expired)/* Connect to a TCP DNS query channel. */{	data_cl_t *data_cl= data;	/* Try to connect. */	if (asyn_ioctl(&asyn, data_cl->dn_fd, NWIOTCPCONN, &data_cl->tcpcl) < 0)	{		if (errno == EINPROGRESS) return 0;		if (errno == EIO) fatal(tcp_device);		/* Connection refused. */		if (debug >= 2) printf(": Connect: %s\n", strerror(errno));		asyn_close(&asyn, data_cl->dn_fd);		close(data_cl->dn_fd);		data_cl->dn_fd= NO_FD;		if (++data_cl->retry < 5) {			/* Search a new name daemon. */			if (!searching()) named_search();			newjob(job_setup_connect, NEVER, data_cl);			return 1;		}		/* Reply with a failure eventually. */	}	if (debug >= 2) printf(": Connect\n");	/* Read the query from the user, send on to the name daemon, etc. */	start_relay(data_cl->fd, data_cl->dn_fd);	deallocate(data_cl);	return 1;}#else /* !__minix_vmd */int job_dummy(void *data, int expired){	return 1;}#define job_setup_listen	job_dummy#define job_setup_connect	job_dummy#endif /* !__minix_vmd */size_t compose_reply(u8_t *qbuf, size_t qsize, u8_t *rbuf, size_t rsize)/* Build a reply message in rbuf as answer to the query in qbuf. */{	dns_hdr_t *qhp= (dns_hdr_t *) qbuf;	dns_hdr_t *rhp= (dns_hdr_t *) rbuf;	u8_t *cp0, *cp= (u8_t *) (rhp + 1);	u8_t *dnptrs[32];	struct hostent *he;	u8_t name[MAXDNAME+1];	int r;	u16_t qtype;	ipaddr_t ip;	char *dot;	rhp->dh_id= qhp->dh_id;	rhp->dh_flag1= (qhp->dh_flag1 | DHF_QR | DHF_AA) & ~(DHF_TC);	rhp->dh_flag2= (qhp->dh_flag2)			& ~(DHF_RA | DHF_PR | DHF_UNUSED | DHF_RCODE);	rhp->dh_qdcount= HTONS(0);	rhp->dh_ancount= HTONS(0);	rhp->dh_nscount= HTONS(0);	rhp->dh_arcount= HTONS(0);	dnptrs[0]= (u8_t *) rhp;	dnptrs[1]= nil;	/* Check and decode the query. */	r= dns_decode(qbuf, qsize, name);	if (r <= 0) {		rhp->dh_flag2|= (r == 0 ? NOTIMP : FORMERR);		return sizeof(*rhp);	}	qtype= r;	/* Repeat the question in the answer. */	r= dn_comp(name, cp, rsize - (rbuf - cp), dnptrs, arraylimit(dnptrs));	if (r == -1) {		rhp->dh_flag2 |= FORMERR;		return sizeof(*rhp);	}	cp+= r;	pack16(cp, htons(qtype));	cp+= sizeof(u16_t);	pack16(cp, HTONS(C_IN));	cp+= sizeof(u16_t);	rhp->dh_qdcount= HTONS(1);	if (qtype == T_PTR) {		/* Reverse lookup. */		he= nil;		if ((ip= arpa_addr(name)) != NO_IP)			he= gethostbyaddr((char *) &ip, sizeof(ip), AF_INET);	} else	if ((he= gethostbyname((char *) name)) != nil) {		/* Normal name match. */		;	} else	if ((dot= strchr((char *) name, '.')) != nil) {		/* We are desparate for a match; strip the domain. */		char domain[MAXDNAME];		*dot= 0;		if (getdomainname(domain, sizeof(domain)) != -1					&& strcasecmp(dot+1, domain) == 0) {			he= gethostbyname((char *) name);		}		*dot= '.';	}	if (he == nil) {		rhp->dh_flag2 |= NXDOMAIN;		return cp - rbuf;	}	if (qtype != T_PTR && qtype != T_A && qtype != T_ANY) {		/* Succeed, but the answer is empty. */		return cp - rbuf;	}	/* Make an answer that looks one of these two:	 *   1.200.9.192.in-addr.arpa  3600  IN  PTR  darask.home.cs.vu.nl	 *   darask.home.cs.vu.nl      3600  IN    A  192.9.200.1	 */	r= dn_comp(name, cp, rsize - (rbuf - cp), dnptrs, arraylimit(dnptrs));	if (r == -1) {		rhp->dh_flag2 |= FORMERR;		return cp - rbuf;	}	cp0= cp;	cp+= r;	pack16(cp, qtype == T_PTR ? HTONS(T_PTR) : HTONS(T_A));	cp+= sizeof(u16_t);	pack16(cp, HTONS(C_IN));	cp+= sizeof(u16_t);	pack32(cp, HTONL((long) TTL));	cp+= sizeof(u32_t);	if (qtype == T_PTR) {		r= dn_comp((u8_t *) he->h_name,			cp + sizeof(u16_t),			rsize - sizeof(u16_t) - (rbuf - cp),			dnptrs, arraylimit(dnptrs));		if (r == -1) {			rhp->dh_flag2 |= FORMERR;			return cp0 - rbuf;		}		pack16(cp, htons(r));		cp+= sizeof(u16_t) + r;	} else {		/* T_A */		pack16(cp, HTONS(sizeof(u32_t)));		cp+= sizeof(u16_t);		memcpy(cp, he->h_addr, sizeof(u32_t));		cp+= sizeof(u32_t);	}	rhp->dh_ancount= HTONS(1);	return cp - rbuf;}/* Max DNS datagram with UDP header. */#define UDP_PACKETSZ	(sizeof(udp_io_hdr_t) + PACKETSZ)int job_read_udp(void *data, int expired)/* Read UDP queries and replies. */{	ssize_t count;	static union {		udp_io_hdr_t hdr;		char buf[UDP_PACKETSZ];	} u;	dns_hdr_t *hp;	u16_t id, port;	ipaddr_t ip;	assert(!expired);	/* Try to read a packet. */	count= asyn_read(&asyn, udp_fd, u.buf, UDP_PACKETSZ);	if (count < 0) {		if (errno == EINPROGRESS && !expired) return 0;		if (errno == EIO) fatal(tcp_device);		if (debug >= 2) printf(": UDP read: %s\n", strerror(errno));	} else {		if (debug >= 2) {			printf(": UDP read, %d bytes\n",						count - sizeof(udp_io_hdr_t));		}	}	/* Restart job no matter what. */	newjob(job_read_udp, NEVER, nil);	if (count < (ssize_t) (sizeof(udp_io_hdr_t) + sizeof(dns_hdr_t)))		return 1;	hp= (dns_hdr_t *) (&u.hdr + 1);	if (debug >= 1) {		printf("%s/%u UDP ", inet_ntoa(u.hdr.uih_src_addr),					ntohs(u.hdr.uih_src_port));		dns_tell((u8_t *) hp, count - sizeof(udp_io_hdr_t));	}	if (hp->dh_flag1 & DHF_QR) {		/* This is a remote named reply, not a query. */		if (expecting()) {			stop_expect();			force_expire(job_expect_named);		}		/* Response to a query once relayed? */		if (!old_id(hp->dh_id, &id, &port, &ip)) return 1;		if (port == my_port && ip == my_ip) {			/* We have found a name server! */			if (searching()) {				named_ip= u.hdr.uih_src_addr;				if (debug >= 1) {					printf("Real named = %s\n",							inet_ntoa(named_ip));				}				stop_searching();				force_expire(job_find_named);				force_expire(job_setup_connect);			}			return 1;		}		/* Send the reply to the process that asked for it. */		hp->dh_id= id;		u.hdr.uih_src_addr= my_ip;		u.hdr.uih_dst_addr= ip;		u.hdr.uih_src_port= my_port;		u.hdr.uih_dst_port= port;		if (debug >= 1) {			printf("To client %s/%u\n", inet_ntoa(ip),							ntohs(port));		}		if (write(udp_fd, u.buf, count) < 0) fatal(udp_device);	} else	if (named_ip != NO_IP) {		/* We have a real name daemon to handle the query. */		id= new_id(hp->dh_id, u.hdr.uih_src_port, u.hdr.uih_src_addr);		hp->dh_id= id;		u.hdr.uih_src_addr= my_ip;		u.hdr.uih_dst_addr= named_ip;		u.hdr.uih_src_port= my_port;		u.hdr.uih_dst_port= named_port;		if (debug >= 1) {			printf("To named %s/%u\n", inet_ntoa(named_ip),							ntohs(named_port));		}		if (write(udp_fd, u.buf, count) < 0) fatal(udp_device);		if (!expecting()) {			start_expect();			newjob(job_expect_named, now + MEDIUM_TIMEOUT, nil);		}	} else {		/* No real name daemon around, so use the hosts file. */		u8_t rbuf[UDP_PACKETSZ + 32];		size_t rsize;		udp_io_hdr_t *rhdr= (udp_io_hdr_t *) rbuf;		dns_hdr_t *rhp= (dns_hdr_t *) (rhdr + 1);		/* Build a reply packet. */		rsize= compose_reply((u8_t *) hp,					count - sizeof(udp_io_hdr_t),					rbuf + sizeof(udp_io_hdr_t),					PACKETSZ);		rhdr->uih_src_addr= my_ip;		rhdr->uih_dst_addr= u.hdr.uih_src_addr;		rhdr->uih_src_port= my_port;		rhdr->uih_dst_port= u.hdr.uih_src_port;		rhdr->uih_ip_opt_len= 0;		rhdr->uih_data_len= rsize;		/* Don't send failure messages at startup. */		if (!do_fail && (rhp->dh_flag2 & DHF_RCODE) != 0)			return 1;		/* Send a DNS reply. */		if (debug >= 1) {			printf("%s/%u UDP ", inet_ntoa(rhdr->uih_dst_addr),						ntohs(rhdr->uih_dst_port));			dns_tell(rbuf + sizeof(udp_io_hdr_t), rsize);		}		if (write(udp_fd, rbuf, sizeof(udp_io_hdr_t) + rsize) < 0)			fatal(udp_device);	}	return 1;}#if __minix_vmdchar *tcp_dns_tell(int fd, u8_t *buf)/* Tell about a DNS packet on a TCP channel. */{	nwio_tcpconf_t tcpconf;	if (ioctl(fd, NWIOGTCPCONF, &tcpconf) < 0) {		printf("???/?? TCP ");	} else {		printf("%s/%u TCP ", inet_ntoa(tcpconf.nwtc_remaddr),					ntohs(tcpconf.nwtc_remport));	}	dns_tell(buf + sizeof(u16_t), ntohs(upack16(buf)));}

⌨️ 快捷键说明

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