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

📄 nonamed.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
int job_read_query(void *data, int expired)/* Read TCP queries. */{	data_rw_t *data_rw= data;	ssize_t count;	dns_hdr_t *hp;	/* Try to read count bytes. */	count= asyn_read(&asyn, data_rw->r_fd,				data_rw->buf + data_rw->offset,				data_rw->size - data_rw->offset);	if (count < 0) {		if (errno == EINPROGRESS && !expired) return 0;		if (errno == EIO) fatal(tcp_device);		/* Remote end is late, or an error occurred. */		if (debug >= 2)			printf(": TCP read query: %s\n", strerror(errno));		close_relay(data_rw);		return 1;	}	if (debug >= 2) {		printf(": TCP read query, %d/%u bytes\n",				data_rw->offset + count, data_rw->size);	}	if (count == 0) {		/* EOF. */		close_relay(data_rw);		return 1;	}	data_rw->offset+= count;	if (data_rw->offset == data_rw->size) {		data_rw->size= sizeof(u16_t) + ntohs(upack16(data_rw->buf));		if (data_rw->size < sizeof(u16_t)) {			/* Malformed. */			close_relay(data_rw);			return 1;		}		if (data_rw->offset < data_rw->size) {			/* Query not complete, read more. */			data_rw->buf= allocate(data_rw->buf, data_rw->size);			newjob(job_read_query, now + LONG_TIMEOUT, data_rw);			return 1;		}	}	if (debug >= 1) tcp_dns_tell(data_rw->r_fd, data_rw->buf);	/* Relay or reply. */	count= data_rw->size;	hp= (dns_hdr_t *) (data_rw->buf + sizeof(u16_t));	if (count < sizeof(u16_t) + sizeof(dns_hdr_t)) {		close_relay(data_rw);		return 1;	}	if (data_rw->w_fd != data_rw->r_fd) {		/* We have a real name daemon to do the work. */		data_rw->offset= 0;		newjob(job_write_query, now + LONG_TIMEOUT, data_rw);	} else {		/* No real name daemon around, so use the hosts file. */		u8_t rbuf[sizeof(u16_t) + PACKETSZ + 32];		/* Build a reply packet. */		count= compose_reply((u8_t *) hp,					count - sizeof(u16_t),					rbuf + sizeof(u16_t),					PACKETSZ);		pack16(rbuf, htons(count));		/* Start a reply write. */		data_rw->size= sizeof(u16_t) + count;		data_rw->buf= allocate(data_rw->buf, data_rw->size);		memcpy(data_rw->buf, rbuf, data_rw->size);		data_rw->offset= 0;		newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);	}	return 1;}int job_write_query(void *data, int expired)/* Relay a TCP query to the name daemon. */{	data_rw_t *data_rw= data;	ssize_t count;	/* Try to write count bytes to the name daemon. */	count= asyn_write(&asyn, data_rw->w_fd,				data_rw->buf + data_rw->offset,				data_rw->size - data_rw->offset);	if (count <= 0) {		if (errno == EINPROGRESS && !expired) return 0;		if (errno == EIO) fatal(tcp_device);		/* A write expired or failed (usually a broken connection.) */		if (debug >= 2)			printf(": TCP write query: %s\n", strerror(errno));		close_relay(data_rw);		return 1;	}	if (debug >= 2) {		printf(": TCP write query, %d/%u bytes\n",				data_rw->offset + count, data_rw->size);	}	data_rw->offset+= count;	if (data_rw->offset < data_rw->size) {		/* Partial write, continue. */		newjob(job_write_query, now + LONG_TIMEOUT, data_rw);		return 1;	}	if (debug >= 1) tcp_dns_tell(data_rw->w_fd, data_rw->buf);	/* Query fully send on, go read more queries. */	data_rw->offset= 0;	data_rw->size= sizeof(u16_t);	newjob(job_read_query, now + LONG_TIMEOUT, data_rw);	return 1;}int job_read_reply(void *data, int expired)/* Real a TCP reply from the real name daemon. */{	data_rw_t *data_rw= data;	ssize_t count;	/* Try to read count bytes. */	count= asyn_read(&asyn, data_rw->r_fd,				data_rw->buf + data_rw->offset,				data_rw->size - data_rw->offset);	if (count < 0) {		if (errno == EINPROGRESS && !expired) return 0;		if (errno == EIO) fatal(tcp_device);		/* Remote end is late, or an error occurred. */		if (debug >= 2)			printf(": TCP read reply: %s\n", strerror(errno));		close_relay(data_rw);		return 1;	}	if (debug >= 2) {		printf(": TCP read reply, %d/%u bytes\n",				data_rw->offset + count, data_rw->size);	}	if (count == 0) {		/* EOF. */		close_relay(data_rw);		return 1;	}	data_rw->offset+= count;	if (data_rw->offset == data_rw->size) {		data_rw->size= sizeof(u16_t) + ntohs(upack16(data_rw->buf));		if (data_rw->size < sizeof(u16_t)) {			/* Malformed. */			close_relay(data_rw);			return 1;		}		if (data_rw->offset < data_rw->size) {			/* Reply not complete, read more. */			data_rw->buf= allocate(data_rw->buf, data_rw->size);			newjob(job_read_reply, now + LONG_TIMEOUT, data_rw);			return 1;		}	}	if (debug >= 1) tcp_dns_tell(data_rw->r_fd, data_rw->buf);	/* Reply fully read, send it on. */	data_rw->offset= 0;	newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);	return 1;}int job_write_reply(void *data, int expired)/* Send a TCP reply to the client. */{	data_rw_t *data_rw= data;	ssize_t count;	/* Try to write count bytes to the client. */	count= asyn_write(&asyn, data_rw->w_fd,				data_rw->buf + data_rw->offset,				data_rw->size - data_rw->offset);	if (count <= 0) {		if (errno == EINPROGRESS && !expired) return 0;		if (errno == EIO) fatal(tcp_device);		/* A write expired or failed (usually a broken connection.) */		if (debug >= 2)			printf(": TCP write reply: %s\n", strerror(errno));		close_relay(data_rw);		return 1;	}	if (debug >= 2) {		printf(": TCP write reply, %d/%u bytes\n",				data_rw->offset + count, data_rw->size);	}	data_rw->offset+= count;	if (data_rw->offset < data_rw->size) {		/* Partial write, continue. */		newjob(job_write_reply, now + LONG_TIMEOUT, data_rw);		return 1;	}	if (debug >= 1) tcp_dns_tell(data_rw->w_fd, data_rw->buf);	/* Reply fully send on, go read more replies (or queries). */	data_rw->offset= 0;	data_rw->size= sizeof(u16_t);	newjob(data_rw->w_fd != data_rw->r_fd			? job_read_reply : job_read_query,				now + LONG_TIMEOUT, data_rw);	return 1;}#endif /* __minix_vmd */void named_probe(ipaddr_t ip)/* Probe a name daemon, either direct or by broadcast. */{	u8_t udp_buf[sizeof(udp_io_hdr_t) + PACKETSZ];	udp_io_hdr_t *udp_hdr= (udp_io_hdr_t *) udp_buf;	dns_hdr_t *dns_hdr= (dns_hdr_t *) (udp_hdr + 1);	u8_t *cp= (u8_t *) (dns_hdr + 1);	int len;	/* Send a simple DNS query that all name servers can answer easily:	 * "What are the name servers for the root domain?"	 */	dns_hdr->dh_id= new_id(0, my_port, my_ip);	dns_hdr->dh_flag1= 0;	dns_hdr->dh_flag2= 0;	dns_hdr->dh_qdcount= HTONS(1);	dns_hdr->dh_ancount= HTONS(0);	dns_hdr->dh_nscount= HTONS(0);	dns_hdr->dh_arcount= HTONS(0);	*cp++= 0;	/* Null name. */	pack16(cp, HTONS(T_NS));	cp+= sizeof(u16_t);	pack16(cp, HTONS(C_IN));	cp+= sizeof(u16_t);	if (debug >= 1) {		printf("PROBE %s ", inet_ntoa(ip));		dns_tell((u8_t *) dns_hdr, cp - (u8_t *) dns_hdr);	}	udp_hdr->uih_src_addr= my_ip;	udp_hdr->uih_dst_addr= ip;	udp_hdr->uih_src_port= my_port;	udp_hdr->uih_dst_port= named_port;	udp_hdr->uih_ip_opt_len= 0;	udp_hdr->uih_data_len= cp - udp_buf - sizeof(*udp_hdr);	if (write(udp_fd, udp_buf, cp - udp_buf) < 0) fatal(udp_device);}int job_find_named(void *data, int expired)/* Look for a real name daemon to answer real DNS queries. */{	if (!expired) return 0;	if (debug >= 2) printf(": Find named\n");	/* New search? */	if (search_ct < 0) search_ct= N_SEARCHES;	if (--search_ct < 0) {		/* End of search.  Failure replies may be sent if we didn't		 * find a name daemon.  Search again after a long time.		 */		do_fail= 1;		newjob(job_find_named, now + TTL, nil);		force_expire(job_setup_connect);		return 1;	}	/* Broadcast a named probe. */	named_probe(HTONL(0xFFFFFFFFL));	/* Schedule the next call. */	newjob(job_find_named, now + SHORT_TIMEOUT, nil);	return 1;}int job_expect_named(void *data, int expired)/* The real name server is expected to answer by now. */{	if (!expired) return 0;	if (debug >= 2) printf(": Expect named\n");	if (expect_ct > 0) {		if (--expect_ct > 0) {			/* Probe the current name daemon. */			named_probe(named_ip);			newjob(job_expect_named, now + SHORT_TIMEOUT, nil);		} else {			/* Still no answer. */			if (!searching()) named_search();		}	}	return 1;}int force_search;void sig_handler(int sig)/* A signal forces a search for a real name daemon, etc. */{	switch (sig) {	case SIGHUP:	force_search= 1;	break;	case SIGUSR1:	debug++;		break;	case SIGUSR2:	debug= 0;		break;	}}void usage(void){	fprintf(stderr,		"Usage: nonamed [-d[level]] [-p port] [-n address[/port]]\n");	exit(1);}void main(int argc, char **argv){	job_t *job;	nwio_udpopt_t udpopt;	int i;	struct servent *servent;	struct sigaction sa;	if ((servent= getservbyname("domain", nil)) == nil) {		fprintf(stderr, "nonamed: \"domain\": unknown service\n");		exit(1);	}	my_port= servent->s_port;	named_port= servent->s_port;	i= 1;	while (i < argc) {		char *opt= argv[i++], *p, *end;		if (*opt++ != '-') usage();		if (opt[0] == '-' && opt[1] == 0) break;		switch (*opt++) {		case 'd':			debug= 1;			if (*opt != 0) {				debug= strtoul(opt, &end, 10);				if (*end != 0) usage();			}			break;		case 'p':			if (*opt == 0) {				if (i == argc) usage();				opt= argv[i++];			}			my_port= htons(strtoul(opt, &end, 0));			if (opt == end || *end != 0) usage();			break;		case 'n':			if (*opt == 0) {				if (i == argc) usage();				opt= argv[i++];			}			if ((p= strchr(opt, '/')) != nil) *p++= 0;			if (!inet_aton(opt, &named_ip)) usage();			if (p != nil) {				named_port= htons(strtoul(p, &end, 0));				if (p == end || *end != 0) usage();				p[-1]= '/';			}			stop_searching();			break;		default:			usage();		}	}	if (i != argc) usage();	/* Don't die on broken pipes, seek a real name daemon on hangup, etc. */	sa.sa_handler= SIG_IGN;	sigemptyset(&sa.sa_mask);	sa.sa_flags= 0;	sigaction(SIGPIPE, &sa, nil);	sa.sa_handler= sig_handler;	sigaction(SIGHUP, &sa, nil);	sigaction(SIGUSR1, &sa, nil);	sigaction(SIGUSR2, &sa, nil);	/* TCP and UDP device names. */	if ((tcp_device= getenv("TCP_DEVICE")) == nil) tcp_device= TCP_DEVICE;	if ((udp_device= getenv("UDP_DEVICE")) == nil) udp_device= UDP_DEVICE;	/* Open an UDP channel for incoming DNS queries. */	if ((udp_fd= open(udp_device, O_RDWR)) < 0) fatal(udp_device);	udpopt.nwuo_flags= NWUO_EXCL | NWUO_LP_SET | NWUO_EN_LOC		| NWUO_DI_BROAD | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL		| NWUO_DI_IPOPT;	udpopt.nwuo_locport= my_port;	if (ioctl(udp_fd, NWIOSUDPOPT, &udpopt) == -1) fatal(udp_device);	/* Get the local machine's IP address. */	if (ioctl(udp_fd, NWIOGUDPOPT, &udpopt) == -1) fatal(udp_device);	my_ip= udpopt.nwuo_locaddr;	if (debug >= 2) printf("my IP address is %s\n", inet_ntoa(my_ip));	/* Jobs that start the ball rolling. */	newjob(job_read_udp, NEVER, nil);	newjob(job_setup_listen, IMMEDIATE, nil);	newjob(job_find_named, IMMEDIATE, nil);	now= time(nil);	while (1) {		/* There is always something in the queue with a timeout. */		assert(queue != nil);		assert(queue->timeout != NEVER);		/* Any expired jobs? */		while (queue->timeout <= now) {			(void) execjob(queue, 1);			assert(queue != nil);			assert(queue->timeout != NEVER);		}		/* Check I/O jobs. */		for (job= queue; job != nil; job= job->next) {			if (execjob(job, 0)) break;		}		if (queue->timeout != IMMEDIATE) {			struct timeval tv;			tv.tv_sec= queue->timeout;			tv.tv_usec= 0;			if (debug >= 2) {				unsigned long s= tv.tv_sec - now;				printf("I/O wait (expire in %02ld:%02ld)\n",							s / 60, s % 60);			}			fflush(stdout);			if (asyn_wait(&asyn, 0, &tv) < 0) {				if (errno != EINTR && errno != EAGAIN)					fatal("fwait()");			}			now= time(nil);		}		if (force_search) {			/* Hangup makes us go back to square one. */			force_search= 0;			named_search();		}	}}

⌨️ 快捷键说明

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