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

📄 domain.c

📁 uCLinux下的一个TCP/IP协议栈源码
💻 C
📖 第 1 页 / 共 3 页
字号:
register struct rr *rrlp;
{
	register struct rr **rrpp;
	struct rr *result_rrlp;

	rrpp = &result_rrlp;
	while(rrlp != NULL){
		*rrpp = copy_rr(rrlp);
		rrpp = &(*rrpp)->next;
		rrlp = rrlp->next;
	}
	*rrpp = NULL;
	return result_rrlp;
}

/* Free (list of) resource records */
void
free_rr(rrlp)
register struct rr *rrlp;
{
	register struct rr *rrp;

	while((rrp = rrlp) != NULL){
		rrlp = rrlp->next;

		free(rrp->comment);
		free(rrp->name);
		if(rrp->rdlength > 0){
			switch(rrp->type){
			case TYPE_A:
				break;	/* Nothing allocated in rdata section */
			case TYPE_CNAME:
			case TYPE_MB:
			case TYPE_MG:
			case TYPE_MR:
			case TYPE_NS:
			case TYPE_PTR:
			case TYPE_TXT:
				free(rrp->rdata.name);
				break;
			case TYPE_HINFO:
				free(rrp->rdata.hinfo.cpu);
				free(rrp->rdata.hinfo.os);
				break;
			case TYPE_MX:
				free(rrp->rdata.mx.exch);
				break;
			case TYPE_SOA:
				free(rrp->rdata.soa.mname);
				free(rrp->rdata.soa.rname);
				break;
			}
		}
		free(rrp);
	}
}

static struct rr *
make_rr(source,dname,dclass,dtype,ttl,rdl,data)
int source;
char *dname;
uint16 dclass;
uint16 dtype;
int32 ttl;
uint16 rdl;
void *data;
{
	register struct rr *newrr;

	newrr = (struct rr *)callocw(1,sizeof(struct rr));
	newrr->source = source;
	newrr->name = strdup(dname);
	newrr->class = dclass;
	newrr->type = dtype;
	newrr->ttl = ttl;
	if((newrr->rdlength = rdl) == 0)
		return newrr;

	switch(dtype){
	case TYPE_A:
	  {
		register int32 *ap = (int32 *)data;
		newrr->rdata.addr = *ap;
		break;
	  }
	case TYPE_CNAME:
	case TYPE_MB:
	case TYPE_MG:
	case TYPE_MR:
	case TYPE_NS:
	case TYPE_PTR:
	case TYPE_TXT:
	  {
		newrr->rdata.name = strdup((char *)data);
		break;
	  }
	case TYPE_HINFO:
	  {
		register struct hinfo *hinfop = (struct hinfo *)data;
		newrr->rdata.hinfo.cpu = strdup(hinfop->cpu);
		newrr->rdata.hinfo.os = strdup(hinfop->os);
		break;
	  }
	case TYPE_MX:
	  {
		register struct mx *mxp = (struct mx *)data;
		newrr->rdata.mx.pref = mxp->pref;
		newrr->rdata.mx.exch = strdup(mxp->exch);
		break;
	  }
	case TYPE_SOA:
	  {
		register struct soa *soap = (struct soa *)data;
		newrr->rdata.soa.mname = 	strdup(soap->mname);
		newrr->rdata.soa.rname = 	strdup(soap->rname);
		newrr->rdata.soa.serial = 	soap->serial;
		newrr->rdata.soa.refresh = 	soap->refresh;
		newrr->rdata.soa.retry = 	soap->retry;
		newrr->rdata.soa.expire = 	soap->expire;
		newrr->rdata.soa.minimum = 	soap->minimum;
		break;
	  }
	}
	return newrr;
}


/**
 **	Domain Cache Utilities
 **/

static void
dcache_add(rrlp)
register struct rr *rrlp;
{
	register struct rr *last_rrp;
	struct rr *save_rrp;

	if(rrlp == NULL)
		return;

	save_rrp = rrlp;
	last_rrp = NULL;
	while(rrlp != NULL){
		rrlp->last = last_rrp;
		last_rrp = rrlp;
		rrlp = rrlp->next;
	}
	last_rrp->next = Dcache;
	if(Dcache != NULL)
		Dcache->last = last_rrp;
	Dcache = save_rrp;
}

static void
dcache_drop(rrp)
register struct rr *rrp;
{
	if(rrp->last != NULL)
		rrp->last->next = rrp->next;
	else
		Dcache = rrp->next;
	if(rrp->next != NULL)
		rrp->next->last = rrp->last;
	rrp->last =
	rrp->next = NULL;
}

/* Search cache for resource records, removing them from the cache.
 * Also, timeout cache entries, and trim cache to size.
 * (Calling with NULL is legal -- will timeout & trim only.)
 * Note that an answer from the cache cannot be authoritative, because
 * we cannot guarantee that all the entries remain from a previous request.
 * Returns RR list, or NULL if no record found.
 */
static struct rr *
dcache_search(rrlp)
struct rr *rrlp;
{
	register struct rr *rrp, *test_rrp;
	struct rr **rrpp, *result_rrlp;
	int32 elapsed;
	time_t now;
	int count = 0;

#ifdef DEBUG
	if(Dtrace && rrlp != NULL){
		printf("dcache_search: searching for %s\n",rrlp->name);
	}
#endif

	elapsed = (int32)(time(&now) - Dcache_time);
	Dcache_time = now;

	rrpp = &result_rrlp;
	for(rrp = Dcache; (test_rrp = rrp) != NULL;){
		rrp = rrp->next;
					/* timeout entries */
		if(test_rrp->ttl > 0L
		&& (test_rrp->ttl -= elapsed) <= 0L)
			test_rrp->ttl = 0L;

		if(compare_rr_list(rrlp,test_rrp) == 0){
			dcache_drop( *rrpp = test_rrp );
			rrpp = &(*rrpp)->next;
		} else if(test_rrp->source == RR_FILE && ++count > Dcache_size){
			dcache_drop(test_rrp);
			free_rr(test_rrp);
		}
	}
	*rrpp = NULL;
	return result_rrlp;
}

/* Move a list of resource records to the cache, removing duplicates. */
static void
dcache_update(rrlp)
register struct rr *rrlp;
{
	if(rrlp == NULL)
		return;

	free_rr(dcache_search(rrlp));	/* remove duplicates, first */
	dcache_add(rrlp);
}


/**
 **	File Utilities
 **/

static struct rr *
get_rr(fp,lastrrp)
FILE *fp;
struct rr *lastrrp;
{
	char *line,*lp,*strtok();
	struct rr *rrp;
	char *name,*ttl,*class,*type,*data;
	int i;

	line = mallocw(256);
	if(fgets(line,256,fp) == NULL){
		free(line);
		return NULL;
	}

	rrp = (struct rr *)callocw(1,sizeof(struct rr));
	rrp->source = RR_FILE;

	if(line[0] == '\0' || line[0] == '#' || line[0] == ';'){
		rrp->comment = line;
		return rrp;
	}

	if(!isspace(line[0]) || lastrrp == NULL){
		name = strtok(line,delim);
		lp = NULL;
	} else {	/* Name field is missing */
		name = lastrrp->name;
		lp = line;
	}
	if(name == NULL || (i = strlen(name)) == 0){
		rrp->comment = strdup("\n");
		free(line);
		return rrp;
	}

	if(name[i-1] != '.'){
		/* Tack on a trailing period if it's not there */
		/* !!! need to implement $ORIGIN suffix here */
		rrp->name = mallocw(i+2);
		strcpy(rrp->name,name);
		strcat(rrp->name,".");
	} else
		rrp->name = strdup(name);

	ttl = strtok(lp,delim);

	if(ttl == NULL || (!isdigit(ttl[0]) && ttl[0] != '-')){
		/* Optional ttl field is missing */
		rrp->ttl = TTL_MISSING;
		class = ttl;
	} else {
		rrp->ttl = atol(ttl);
		class = strtok(NULL,delim);
	}

	if(class == NULL){
		/* we're in trouble, but keep processing */
		rrp->class = CLASS_MISSING;
		type = class;
	} else if(class[0] == '<'){
		rrp->class = atoi(&class[1]);
		type = strtok(NULL,delim);
	} else if(stricmp(class,"IN") == 0){
		rrp->class = CLASS_IN;
		type = strtok(NULL,delim);
	} else {
		/* Optional class field is missing; assume IN */
		rrp->class = CLASS_IN;
		type = class;
	}

	if(type == NULL){
		/* we're in trouble, but keep processing */
		rrp->type = TYPE_MISSING;
		data = type;
	} else if(type[0] == '{'){
		rrp->type = atoi(&class[1]);
		data = strtok(NULL,delim);
	} else {
		rrp->type = TYPE_MISSING;
		for(i=1;i<Ndtypes;i++){
			if(stricmp(type,Dtypes[i]) == 0){
				rrp->type = i;
				data = strtok(NULL,delim);
				break;
			}
		}
	}

	if(rrp->type == TYPE_MISSING){
		data = NULL;
	}

	if(data == NULL){
		/* Empty record, just return */
		free(line);
		return rrp;
	}
	switch(rrp->type){
	case TYPE_A:
		rrp->rdlength = 4;
		rrp->rdata.addr = aton(data);
		break;
	case TYPE_CNAME:
	case TYPE_MB:
	case TYPE_MG:
	case TYPE_MR:
	case TYPE_NS:
	case TYPE_PTR:
	case TYPE_TXT:
		rrp->rdlength = strlen(data);
		rrp->rdata.name = strdup(data);
		break;
	case TYPE_HINFO:
		rrp->rdlength = strlen(data);
		rrp->rdata.hinfo.cpu = strdup(data);
		if((data = strtok(NULL,delim)) != NULL){
			rrp->rdlength += strlen(data);
			rrp->rdata.hinfo.os = strdup(data);
		}
		break;
	case TYPE_MX:
		rrp->rdata.mx.pref = atoi(data);
		rrp->rdlength = 2;

		/* Get domain name of exchanger */
		if((data = strtok(NULL,delim)) != NULL){
			rrp->rdlength += strlen(data);
			rrp->rdata.mx.exch = strdup(data);
		}
		break;
	case TYPE_SOA:
		/* Get domain name of master name server */
		rrp->rdlength = strlen(data);
		rrp->rdata.soa.mname = strdup(data);

		/* Get domain name of irresponsible person */
		if((data = strtok(NULL,delim)) != NULL){
			rrp->rdata.soa.rname = strdup(data);
			rrp->rdlength += strlen(data);
		}
		data = strtok(NULL,delim);
		rrp->rdata.soa.serial = atol(data);
		data = strtok(NULL,delim);
		rrp->rdata.soa.refresh = atol(data);
		data = strtok(NULL,delim);
		rrp->rdata.soa.retry = atol(data);
		data = strtok(NULL,delim);
		rrp->rdata.soa.expire = atol(data);
		data = strtok(NULL,delim);
		rrp->rdata.soa.minimum = atol(data);
		rrp->rdlength += 20;
		break;
	}

	/* !!! need to handle trailing comments */
	free(line);
	return rrp;
}

/* Print a resource record */
static void
put_rr(fp,rrp)
FILE *fp;
struct rr *rrp;
{
	char * stuff;

	if(fp == NULL || rrp == NULL)
		return;

	if(rrp->name == NULL && rrp->comment != NULL){
		fprintf(fp,"%s",rrp->comment);
		return;
	}

	fprintf(fp,"%s",rrp->name);
	if(rrp->ttl != TTL_MISSING)
		fprintf(fp,"\t%ld",rrp->ttl);
	if(rrp->class == CLASS_IN)
		fprintf(fp,"\tIN");
	else
		fprintf(fp,"\t<%u>",rrp->class);

	stuff = dtype(rrp->type);
	fprintf(fp,"\t%s",stuff);
	if(rrp->rdlength == 0){
		/* Null data portion, indicates nonexistent record */
		/* or unsupported type.  Hopefully, these will filter */
		/* as time goes by. */
		fprintf(fp,"\n");
		return;
	}
	switch(rrp->type){
	case TYPE_A:
		fprintf(fp,"\t%s\n",inet_ntoa(rrp->rdata.addr));
		break;
	case TYPE_CNAME:
	case TYPE_MB:
	case TYPE_MG:
	case TYPE_MR:
	case TYPE_NS:
	case TYPE_PTR:
	case TYPE_TXT:
		/* These are all printable text strings */
		fprintf(fp,"\t%s\n",rrp->rdata.data);
		break;
	case TYPE_HINFO:
		fprintf(fp,"\t%s\t%s\n",
		 rrp->rdata.hinfo.cpu,
		 rrp->rdata.hinfo.os);
		break;
	case TYPE_MX:
		fprintf(fp,"\t%u\t%s\n",
		 rrp->rdata.mx.pref,
		 rrp->rdata.mx.exch);
		break;
	case TYPE_SOA:
		fprintf(fp,"\t%s\t%s\t%lu\t%lu\t%lu\t%lu\t%lu\n",
		 rrp->rdata.soa.mname,rrp->rdata.soa.rname,
		 rrp->rdata.soa.serial,rrp->rdata.soa.refresh,
		 rrp->rdata.soa.retry,rrp->rdata.soa.expire,
		 rrp->rdata.soa.minimum);
		break;
	default:
		fprintf(fp,"\n");
		break;
	}
}

/* Search local database for resource records.
 * Returns RR list, or NULL if no record found.
 */
static struct rr *
dfile_search(rrlp)
struct rr *rrlp;
{
	register struct rr *frrp;
	struct rr **rrpp, *result_rrlp, *oldrrp;
	int32 elapsed;
	FILE *dbase;
	struct stat dstat;

#ifdef DEBUG
	if(Dtrace){
		printf("dfile_search: searching for %s\n",rrlp->name);
	}
#endif

	while(Dfile_writing > 0)
		kwait(&Dfile_reading);
	Dfile_reading++;

	if((dbase = fopen(Dfile,READ_TEXT)) == NULL){
		Dfile_reading--;
		return NULL;
	}
	if(fstat(fileno(dbase),&dstat) != 0){
		printf("dfile_search: can't get file status\n");
		fclose(dbase);
		Dfile_reading--;
		return NULL;
	}
	if((elapsed = (int32)(Dcache_time - (time_t)dstat.st_ctime)) < 0L)
		elapsed = -elapsed;	/* arbitrary time mismatch */

	result_rrlp = NULL;		/* for contiguous test below */
	oldrrp = NULL;
	rrpp = &result_rrlp;
	while((frrp = get_rr(dbase,oldrrp)) != NULL){
		free_rr(oldrrp);
		if(frrp->type != TYPE_MISSING
		&& frrp->rdlength > 0
		&& compare_rr_list(rrlp,frrp) == 0){
			if(frrp->ttl > 0L
			&& (frrp->ttl -= elapsed) <= 0L)
				frrp->ttl = 0L;
			*rrpp = frrp;
			rrpp = &(*rrpp)->next;
			oldrrp = copy_rr(frrp);
		} else {
			oldrrp = frrp;
			/*
				All records of the same name and the same type
				are contiguous.  Therefore, for a single query,
				we can stop searching.  Multiple queries must
				read the whole file.
			*/
			if(rrlp->type != TYPE_ANY
			&& rrlp->next == NULL
			&& result_rrlp != NULL)
				break;
		}
		if(!main_exit)
			kwait(NULL);	/* run multiple sessions */
	}
	free_rr(oldrrp);
	*rrpp = NULL;

	fclose(dbase);

	if(--Dfile_reading <= 0){
		Dfile_reading = 0;
		ksignal(&Dfile_writing,0);
	}

	return result_rrlp;
}

/* Process which will add new resource records from the cache
 * to the local file, eliminating duplicates while it goes.
 */
static void
dfile_update(s,unused,p)
int s;
void *unused;
void *p;
{
	struct rr **rrpp, *rrlp, *oldrrp;
	char *newname;
	FILE *old_fp, *new_fp;
	struct stat old_stat, new_stat;

	logmsg(-1,"update Domain.txt initiated");

	/* Produce output on command session rather than the one
	 * that invoked us
	 */
	fclose(stdin);
	stdin = fdup(Cmdpp->input);
	fclose(stdout);
	stdout = fdup(Cmdpp->output);

	newname = strdup(Dfile);
	strcpy(&newname[strlen(newname)-3],"tmp");

	while(Dfile_wait_absolute != 0L && !main_exit){
		register struct rr *frrp;
		int32 elapsed;

		while(Dfile_wait_absolute != 0L){
			elapsed = Dfile_wait_absolute - secclock();
			Dfile_wait_absolute = 0L;
			if(elapsed > 0L && !main_exit){
				kalarm(elapsed*1000L);
				kwait(&Dfile_wait_absolute);
				kalarm(0L);
			}
		}

		logmsg(-1,"update Domain.txt");

		/* create new file for copy */
		if((new_fp = fopen(newname,WRITE_TEXT)) == NULL){
			printf("dfile_update: can't create %s!\n",newname);
			break;
		}
		if(fstat(fileno(new_fp),&new_stat) != 0){
			printf("dfile_update: can't get new_file status!\n");
			fclose(new_fp);
			break;
		}

		kwait(NULL);	/* file operations can be slow */

		/* timeout the cache one last time before writing */
		(void)dcache_search(NULL);

		/* copy new RRs out to the new file */
		/* (can't wait here, the cache might change) */
		rrpp = &rrlp;
		for(frrp = Dcache; frrp != NULL; frrp = frrp->next ){
			switch(frrp->source){
			case RR_QUESTION:
			case RR_ANSWER:
			case RR_AUTHORITY:
			case RR_ADDITIONAL:
				*rrpp = copy_rr(frrp);
				if(frrp->type != TYPE_MISSING
				&& frrp->rdlength > 0)

⌨️ 快捷键说明

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