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

📄 nonamed.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	nonamed 1.6 - not a name daemon, but plays one on TV. *							Author: Kees J. Bot *								29 Nov 1994 *//* Use the file reading gethostent() family of functions. */#define sethostent	_sethostent#define endhostent	_endhostent#define gethostent	_gethostent#define gethostbyname	_gethostbyname#define gethostbyaddr	_gethostbyaddr#define nil 0#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <time.h>#include <limits.h>#include <signal.h>#include <assert.h>#include <sys/ioctl.h>#include <sys/asynchio.h>#include <net/hton.h>#include <net/netlib.h>#include <net/gen/in.h>#include <net/gen/inet.h>#include <net/gen/nameser.h>#include <net/gen/resolv.h>#include <net/gen/netdb.h>#include <net/gen/socket.h>#include <net/gen/tcp.h>#include <net/gen/tcp_io.h>#include <net/gen/udp.h>#include <net/gen/udp_hdr.h>#include <net/gen/udp_io.h>#define TTL		3600	/* Time to live for any kind of information. */#define SHORT_TIMEOUT	   2	/* If you expect an answer soon. */#define MEDIUM_TIMEOUT	   4	/* Soon, but not that soon. */#define LONG_TIMEOUT	 300	/* For stream connections to a real named. */#define N_SEARCHES	   5	/* Send out this many named broadcasts. */#define N_EXPECTS	   2	/* This many expect timeouts worry us. */#define N_IDS		 256	/* Keep track of this many queries. */#define NO_IP	HTONL(0x00000000L)	/* IP address unknown. */#define NO_FD		(-1)	/* No name daemon channel here. */unsigned debug= 0;		/* Debug level. */#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))#define arraylimit(a)	((a) + arraysize(a))#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))void report(const char *label){	fprintf(stderr, "nonamed: %s: %s\n", label, strerror(errno));}void fatal(const char *label){	report(label);	if (debug >= 3) { fflush(nil); abort(); }	exit(1);}void *allocate(void *mem, size_t size){	if ((mem= mem == nil ? malloc(size) : realloc(mem, size)) == nil)		fatal("malloc()");	return mem;}void deallocate(void *mem){	if (mem != nil) free(mem);}typedef int handler_t(void *data, int expired);/* All actions are in the form of "jobs". */typedef struct job {	struct job	*next, **prev;	/* To make a job queue. */	handler_t	*handler;	/* Function to handle this job. */	time_t		timeout;	/* Moment it times out. */	void		*data;		/* Data associated with the job. */} job_t;/* Some jobs don't time out. */#define NEVER		((time_t) ((time_t) -1 < 0 ? LONG_MAX : ULONG_MAX))/* Others are immediate. */#define IMMEDIATE	((time_t) 0)job_t *queue;		/* Main job queue. */void newjob(handler_t *handler, time_t timeout, void *data)/* Create a new job with the given handler, timeout time and data. */{	job_t *job, **prev;	job= allocate(nil, sizeof(*job));	job->handler= handler;	job->timeout= timeout;	job->data= data;	for (prev= &queue; *prev != nil; prev= &(*prev)->next) {		if (job->timeout < (*prev)->timeout) break;	}	job->next= *prev;	job->prev= prev;	*prev= job;	if (job->next != nil) job->next->prev= &job->next;}int execjob(job_t *job, int expired)/* Execute a job by calling the handler.  Remove the job if it returns true, * indicating that it is done.  Expired is set if the job timed out.  It is * otherwise called to check for I/O. */{	if ((*job->handler)(job->data, expired)) {		*job->prev= job->next;		if (job->next != nil) job->next->prev= job->prev;		deallocate(job);		return 1;	}	return 0;}void force_expire(handler_t *handler)/* Force jobs to expire immediately, the named searcher for instance. */{	job_t *job, **prev= &queue;	while ((job= *prev) != nil) {		if (job->handler == handler && job->timeout != IMMEDIATE) {			*prev= job->next;			if (job->next != nil) job->next->prev= prev;			newjob(job->handler, IMMEDIATE, job->data);			deallocate(job);		} else {			prev= &job->next;		}	}}char *itoa(char *fmt, u32_t i){	static char output[32 + 3 * sizeof(i)];	sprintf(output, fmt, (unsigned long) i);	return output;}void pack16(u8_t *buf, u16_t s)/* Pack a 16 bit value into a byte array. */{	buf[0]= ((u8_t *) &s)[0];	buf[1]= ((u8_t *) &s)[1];}void pack32(u8_t *buf, u32_t l)/* Pack a 32 bit value into a byte array. */{	buf[0]= ((u8_t *) &l)[0];	buf[1]= ((u8_t *) &l)[1];	buf[2]= ((u8_t *) &l)[2];	buf[3]= ((u8_t *) &l)[3];}u16_t upack16(u8_t *buf)/* Unpack a 16 bit value in network byte order from a byte array. */{	u16_t s;	((u8_t *) &s)[0]= buf[0];	((u8_t *) &s)[1]= buf[1];	return s;}u32_t upack32(u8_t *buf)/* Unpack a 32 bit value in network byte order from a byte array. */{	u32_t l;	((u8_t *) &l)[0]= buf[0];	((u8_t *) &l)[1]= buf[1];	((u8_t *) &l)[2]= buf[2];	((u8_t *) &l)[3]= buf[3];	return l;}void dns_tell(u8_t *buf, size_t size)/* Explain a DNS packet, for debug purposes. */{	dns_hdr_t *hp= (dns_hdr_t *) buf;	u8_t *cp, *end;	int r, i, j;	u16_t type, class, rdlength;	u32_t ttl;	u8_t name[MAXDNAME];	u16_t counts[3];	static char labels[3][4]= { "AN:", "NS:", "AR:" };	if (size < sizeof(dns_hdr_t)) return;	printf("DNS %s:", (hp->dh_flag1 & DHF_QR) ? "reply" : "query");	r= hp->dh_flag2 & DHF_RCODE;	printf(" %s", r == NOERROR ? "NOERROR" :			r == FORMERR ? "FORMERR" :			r == SERVFAIL ? "SERVFAIL" :			r == NXDOMAIN ? "NXDOMAIN" :			r == NOTIMP ? "NOTIMP" :			r == REFUSED ? "REFUSED" : itoa("ERR_%lu", r));	if (hp->dh_flag1 & DHF_AA) printf(" AA");	if (hp->dh_flag1 & DHF_TC) printf(" TC");	if (hp->dh_flag1 & DHF_RD) printf(" RD");	if (hp->dh_flag1 & DHF_RA) printf(" RA");	if (hp->dh_flag1 & DHF_PR) printf(" PR");	fputc('\n', stdout);	cp = buf + sizeof(dns_hdr_t);	end= buf + size;	for (i= 0; i < ntohs(hp->dh_qdcount); i++) {		r= dn_expand(buf, end, cp, name, MAXDNAME);		if (r == -1) return;		cp+= r;		if (cp + 2 * sizeof(u16_t) > end) return;		type= ntohs(upack16(cp));		cp+= sizeof(u16_t);		class= ntohs(upack16(cp));		cp+= sizeof(u16_t);		printf("  QD: %-20s", (char *) name);		printf(" %3s", class == C_IN ? "IN" : itoa("C_%lu", class));		printf(" %3s\n", type == T_A ? "A" :				type == T_MX ? "MX" :				type == T_NS ? "NS" :				type == T_ANY ? "ANY" :				type == T_PTR ? "PTR" : itoa("T_%lu", type));	}	counts[0]= ntohs(hp->dh_ancount);	counts[1]= ntohs(hp->dh_nscount);	counts[2]= ntohs(hp->dh_arcount);	for (i= 0; i < 3; i++) {		for (j= 0; j < counts[i]; j++) {			r= dn_expand(buf, end, cp, name, MAXDNAME);			if (r == -1) return;			cp+= r;			type= ntohs(upack16(cp));			cp+= sizeof(u16_t);			class= ntohs(upack16(cp));			cp+= sizeof(u16_t);			ttl= ntohl(upack32(cp));			cp+= sizeof(u32_t);			rdlength= ntohs(upack16(cp));			cp+= sizeof(u16_t);			printf("  %s %-20s", labels[i], (char *) name);			printf(" %6lu", ttl);			printf(" %3s", class == C_IN ? "IN" :						itoa("C_%lu", class));			printf(" %3s", type == T_A ? "A" :					type == T_MX ? "MX" :					type == T_NS ? "NS" :					type == T_ANY ? "ANY" :					type == T_PTR ? "PTR" :						itoa("T_%lu", type));			if (type == T_PTR || type == T_NS) {				r= dn_expand(buf, end, cp, name, MAXDNAME);				if (r == -1) strcpy((char *) name, "???");				printf("  %s\n", (char *) name);			} else			if (type == T_A && rdlength == sizeof(ipaddr_t)) {				printf("  %s\n", inet_ntoa(upack32(cp)));			} else			if (type == T_MX) {				printf("  %5u", ntohs(upack16(cp)));				r= dn_expand(buf, end, cp + sizeof(u16_t),							name, MAXDNAME);				if (r == -1) strcpy((char *) name, "???");				printf("  %s\n", (char *) name);			} else {				printf("  ...\n");			}			cp+= rdlength;		}	}}int dns_decode(u8_t *buf, size_t size, u8_t *name)/* Decode a DNS message, but only if it is an "IN" or "IN" query.  Return * -1 on error, 0 if can't be answered, and the query type if it may possibly * be answered.  In the latter case the name array is filled with the null * terminated name whose address is queried.  Name must be MAXDNAME+1 bytes. */{	dns_hdr_t *hp= (dns_hdr_t *) buf;	u8_t *cp, *end;	int r;	u16_t qtype, qclass;	if (size < sizeof(dns_hdr_t)) return -1;	if ((hp->dh_flag1 & DHF_QR) != 0) return 0;	if ((hp->dh_flag1 & DHF_OPCODE) != (QUERY << 3)) return 0;	if ((hp->dh_flag1 & DHF_TC) != 0) return 0;	if (ntohs(hp->dh_qdcount) != 1) return 0;	/* ? */	if (ntohs(hp->dh_ancount) != 0) return 0;	if (ntohs(hp->dh_nscount) != 0) return 0;	if (ntohs(hp->dh_arcount) != 0) return 0;	cp = buf + sizeof(dns_hdr_t);	end= buf + size;	r= dn_expand(buf, end, cp, name, MAXDNAME);	if (r == -1) return -1;	cp+= r;	if (cp + 2 * sizeof(u16_t) > end) return -1;	qtype= upack16(cp);	cp+= sizeof(u16_t);	qclass= upack16(cp);	cp+= sizeof(u16_t);	if (qclass != HTONS(C_IN)) return 0;	return ntohs(qtype);}ipaddr_t arpa_addr(u8_t *name)/* Change a name in the ARPA domain to an IP address. */{	u8_t octets[4];	int i, d;	/* Expect four dot separated decimal numbers and a dot. */	for (i= 0; i < 4; i++) {		d= 0;		do {			if (!between('0', *name, '9')) return NO_IP;			d= 10*d + (*name++ - '0');			if (d > 0xFF) return NO_IP;		} while (between('0', *name, '9'));		if (*name++ != '.') return NO_IP;		octets[i]= d;	}	if (strcasecmp((char *) name, "IN-ADDR.ARPA") != 0) return NO_IP;	return htonl(	  ((ipaddr_t) octets[0] <<  0)			| ((ipaddr_t) octets[1] <<  8)			| ((ipaddr_t) octets[2] << 16)			| ((ipaddr_t) octets[3] << 24));}typedef struct id2id {	u16_t		id;		/* ID of old query. */	u16_t		port;		/* Reply port. */	ipaddr_t	ip;		/* Reply address. */} id2id_t;id2id_t id2id[N_IDS];u16_t id_counter;u16_t new_id(u16_t in_id, u16_t in_port, ipaddr_t in_ip)/* An incoming UDP query must be relabeled with a new ID before it can be * send on to a real name daemon. */{	static int init;	id2id_t *idp;	u16_t id;	if (!init) {		for (idp= id2id; idp < arraylimit(id2id); idp++) idp->ip= NO_IP;		init= 1;	}	id= id_counter++;	idp= &id2id[id % N_IDS];	idp->id= in_id;	idp->port= in_port;	idp->ip= in_ip;	return htons(id);}int old_id(u16_t id, u16_t *out_id, u16_t *out_port, ipaddr_t *out_ip)/* Translate an reply id back to the id, port, and address used in the query. * Return true if the translation is possible. */{	id= ntohs(id);	if ((u16_t) (id_counter - id) > N_IDS) {		/* Too old. */		return 0;	} else {		/* We know this one. */		id2id_t *idp= &id2id[id % N_IDS];		if (idp->ip == NO_IP) return 0;		*out_id= idp->id;		*out_port= idp->port;		*out_ip= idp->ip;		return 1;	}}char *tcp_device, *udp_device;		/* TCP and UDP device names. */int udp_fd;				/* To send or receive UDP packets. */time_t now;				/* Current time. */asynchio_t asyn;			/* For I/O in progress. */ipaddr_t named_ip = NO_IP;		/* Address of a real name server. */int search_ct= -1;			/* Real named search status. */int do_fail;				/* Do failure replies if true. */int expect_ct= 0;			/* Goes up when expecting answers. */ipaddr_t my_ip;				/* IP address of this machine. */u16_t my_port, named_port;		/* Port numbers, normally "domain". */#define searching()		(search_ct > 0)#define start_searching()	((void) (search_ct= -1))#define stop_searching()	((void) (search_ct= 0))#define expecting()		(expect_ct > 0)#define start_expect()		((void) (expect_ct= N_EXPECTS))#define stop_expect()		((void) (expect_ct= 0))handler_t job_setup_listen, job_listen, job_setup_connect, job_connect;handler_t job_read_udp, job_read_query, job_write_query, job_read_reply;handler_t job_write_query, job_write_reply, job_find_named, job_expect_named;typedef struct data_cl {	/* Data for connect or listen jobs. */	int		fd;		/* Open TCP channel. */	int		dn_fd;		/* TCP channel to the name daemon. */	int		retry;		/* Retrying a connect? */	nwio_tcpcl_t	tcpcl;		/* Flags. */} data_cl_t;typedef struct data_rw {	/* Data for TCP read or write jobs. */	int		r_fd;		/* Read from this TCP channel. */	int		w_fd;		/* And write to this TCP channel. */	struct data_rw	*rev;		/* Optional reverse TCP channel. */	u8_t		*buf;		/* Buffer for bytes to transfer. */	ssize_t		offset;		/* Offset in buf to r/w at. */	size_t		size;		/* Size of buf. */} data_rw_t;void named_search(void)/* Start a search for a new name daemon. */{	if (named_ip != NO_IP) {		/* Forget the current name daemon if there is a hosts file		 * with a "localhost" entry.		 */		struct hostent *he;		ipaddr_t ip;		while ((he= gethostent()) != nil) {			memcpy(&ip, he->h_addr, sizeof(ip));			if ((ntohl(ip) & 0xFF000000L) == 0x7F000000L) {				do_fail= 0;				named_ip= NO_IP;			}		}		endhostent();	}	start_searching();	force_expire(job_find_named);}#if __minix_vmdint job_setup_listen(void *data, int expired)

⌨️ 快捷键说明

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