📄 domain.c
字号:
put_rr(new_fp,frrp);
rrpp = &(*rrpp)->next;
frrp->source = RR_FILE;
break;
}
}
*rrpp = NULL;
/* open up the old file, concurrently with everyone else */
if((old_fp = fopen(Dfile,READ_TEXT)) == NULL){
/* great! no old file, so we're ready to go. */
fclose(new_fp);
rename(newname,Dfile);
free_rr(rrlp);
break;
}
if(fstat(fileno(old_fp),&old_stat) != 0){
printf("dfile_update: can't get old_file status!\n");
fclose(new_fp);
fclose(old_fp);
free_rr(rrlp);
break;
}
if((elapsed = (int32)(new_stat.st_ctime - old_stat.st_ctime)) < 0L)
elapsed = -elapsed; /* file times are inconsistant */
/* Now append any non-duplicate records */
oldrrp = NULL;
while((frrp = get_rr(old_fp,oldrrp)) != NULL){
free_rr(oldrrp);
if(frrp->name == NULL
&& frrp->comment != NULL)
put_rr(new_fp,frrp);
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;
if(frrp->ttl != 0 || !Dfile_clean)
put_rr(new_fp,frrp);
}
oldrrp = frrp;
if(!main_exit)
kwait(NULL); /* run in background */
}
free_rr(oldrrp);
fclose(new_fp);
fclose(old_fp);
free_rr(rrlp);
/* wait for everyone else to finish reading */
Dfile_writing++;
while(Dfile_reading > 0)
kwait(&Dfile_writing);
unlink(Dfile);
rename(newname,Dfile);
Dfile_writing = 0;
ksignal(&Dfile_reading,0);
}
free(newname);
logmsg(-1,"update Domain.txt finished");
Dfile_updater = NULL;
}
/**
** Domain Server Utilities
**/
static void
dumpdomain(dhp,rtt)
struct dhdr *dhp;
int32 rtt;
{
struct rr *rrp;
char * stuff;
printf("response id %u (rtt %lu sec) qr %u opcode %u aa %u tc %u rd %u ra %u rcode %u\n",
dhp->id,(long)rtt / 1000L,
dhp->qr,dhp->opcode,dhp->aa,dhp->tc,dhp->rd,
dhp->ra,dhp->rcode);
printf("%u questions:\n",dhp->qdcount);
for(rrp = dhp->questions; rrp != NULL; rrp = rrp->next){
stuff = dtype(rrp->type);
printf("%s type %s class %u\n",rrp->name,
stuff,rrp->class);
}
printf("%u answers:\n",dhp->ancount);
for(rrp = dhp->answers; rrp != NULL; rrp = rrp->next){
put_rr(stdout,rrp);
}
printf("%u authority:\n",dhp->nscount);
for(rrp = dhp->authority; rrp != NULL; rrp = rrp->next){
put_rr(stdout,rrp);
}
printf("%u additional:\n",dhp->arcount);
for(rrp = dhp->additional; rrp != NULL; rrp = rrp->next){
put_rr(stdout,rrp);
}
fflush(stdout);
}
static int
dns_makequery(op,srrp,buffer,buflen)
uint16 op; /* operation */
struct rr *srrp;/* Search RR */
uint8 *buffer; /* Area for query */
uint16 buflen; /* Length of same */
{
uint8 *cp;
char *cp1;
char *dname, *sname;
uint16 parameter;
uint16 dlen,len;
cp = buffer;
/* Use millisecond clock for timestamping */
cp = put16(cp,(uint16)msclock());
parameter = (op << 11)
| 0x0100; /* Recursion desired */
cp = put16(cp,parameter);
cp = put16(cp,1);
cp = put16(cp,0);
cp = put16(cp,0);
cp = put16(cp,0);
sname = strdup(srrp->name);
dname = sname;
dlen = strlen(dname);
for(;;){
/* Look for next dot */
cp1 = strchr(dname,'.');
if(cp1 != NULL)
len = cp1-dname; /* More to come */
else
len = dlen; /* Last component */
*cp++ = len; /* Write length of component */
if(len == 0)
break;
/* Copy component up to (but not including) dot */
strncpy((char *)cp,dname,len);
cp += len;
if(cp1 == NULL){
*cp++ = 0; /* Last one; write null and finish */
break;
}
dname += len+1;
dlen -= len+1;
}
free(sname);
cp = put16(cp,srrp->type);
cp = put16(cp,srrp->class);
return cp - buffer;
}
/* domain server resolution loop
* returns: any answers in cache.
* (future features)
* multiple queries.
* inverse queries.
* return value: 0 if something added to cache, -1 if error
*/
static int
dns_query(rrlp)
struct rr *rrlp;
{
struct mbuf *bp;
struct dhdr *dhp;
struct dserver *dp; /* server list */
int32 rtt,abserr;
int tried = 0; /* server list has been retried (count) */
if((dp = Dservers) == NULL)
return -1;
for(;;){
uint8 *buf;
int len;
struct sockaddr_in server_in;
int s;
int rval;
dp->queries++;
s = socket(AF_INET,SOCK_DGRAM,0);
server_in.sin_family = AF_INET;
server_in.sin_port = IPPORT_DOMAIN;
server_in.sin_addr.s_addr = dp->address;
if(Dtrace){
printf("dns_query: querying server %s for %s\n",
inet_ntoa(dp->address),rrlp->name);
}
buf = mallocw(512);
len = dns_makequery(0,rrlp,buf,512);
if(sendto(s,buf,len,0,(struct sockaddr *)&server_in,sizeof(server_in)) == -1)
perror("domain sendto");
FREE(buf);
kalarm(max(dp->timeout,100));
/* Wait for something to happen */
rval = recv_mbuf(s,&bp,0,NULL,0);
kalarm(0L);
close_s(s);
if(Dtrace){
if(errno == 0)
printf("dns_query: received message length %d\n",rval);
else
perror("dns_query");
}
if(rval > 0)
break;
if(errno == EABORT)
return -1; /* Killed by "reset" command */
/* Timeout; back off this one and try another server */
dp->timeout <<= 1;
if((dp = dp->next) == NULL){
dp = Dservers;
if(Dserver_retries > 0 && ++tried > Dserver_retries)
return -1;
}
}
/* got a response */
dp->responses++;
dhp = (struct dhdr *) mallocw(sizeof(struct dhdr));
ntohdomain(dhp,&bp); /* Convert to local format */
/* Compute and update the round trip time */
rtt = (int32) ((uint16)msclock() - dhp->id);
abserr = rtt > dp->srtt ? rtt - dp->srtt : dp->srtt - rtt;
dp->srtt = ((AGAIN-1) * dp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
dp->mdev = ((DGAIN-1) * dp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
dp->timeout = 4 * dp->mdev + dp->srtt;
/* move to top of list for next time */
if(dp->prev != NULL){
dlist_drop(dp);
dlist_add(dp);
}
if(Dtrace)
dumpdomain(dhp,rtt);
/* Add negative reply to answers. This assumes that there was
* only one question, which is true for all questions we send.
*/
if(dhp->aa && (dhp->rcode == NAME_ERROR || dhp->ancount == 0)){
register struct rr *rrp;
long ttl = 600L; /* Default TTL for negative records */
/* look for SOA ttl */
for(rrp = dhp->authority; rrp != NULL; rrp = rrp->next){
if(rrp->type == TYPE_SOA)
ttl = rrp->ttl;
}
/* make the questions the negative answers */
for(rrp = dhp->questions; rrp != NULL; rrp = rrp->next)
rrp->ttl = ttl;
} else {
free_rr(dhp->questions);
dhp->questions = NULL;
}
/* post in reverse order to maintain original order */
dcache_update(dhp->additional);
dcache_update(dhp->authority);
dcache_update(dhp->answers);
dcache_update(dhp->questions);
Dfile_wait_absolute = secclock() + Dfile_wait_relative;
if(Dfile_updater == NULL){
Dfile_updater = newproc("domain update",
512,dfile_update,0,NULL,NULL,0);
}
#ifdef DEBUG
if(Dtrace)
keywait(NULL,1); /* so we can look around */
#endif
free(dhp);
return 0;
}
/**
** Resolver Utilities
**/
/* Return TRUE if string appears to be an IP address in dotted decimal;
* return FALSE otherwise (i.e., if string is a domain name)
*/
static int
isaddr(s)
register char *s;
{
char c;
if(s == NULL)
return TRUE; /* Can't happen */
while((c = *s++) != '\0'){
if(c != '[' && c != ']' && !isdigit(c) && c != '.')
return FALSE;
}
return TRUE;
}
/* Return "normalized" domain name, with default suffix and trailing '.'
*/
static char *
checksuffix(dname)
char *dname;
{
char *sname, *tname;
sname = strdup(dname);
if(strchr(sname,'.') == NULL && Dsuffix != NULL){
/* Append default suffix */
tname = mallocw(strlen(sname)+strlen(Dsuffix)+2);
sprintf(tname,"%s.%s",sname,Dsuffix);
free(sname);
sname = tname;
}
if(sname[strlen(sname)-1] != '.'){
/* Append trailing dot */
tname = mallocw(strlen(sname)+2);
sprintf(tname,"%s.",sname);
free(sname);
sname = tname;
}
return sname;
}
/* Search for resource records.
* Returns RR list, or NULL if no record found.
*/
static struct rr *
resolver(rrlp)
register struct rr *rrlp;
{
register struct rr *result_rrlp;
if((result_rrlp = dcache_search(rrlp)) == NULL){
result_rrlp = dfile_search(rrlp);
}
if(result_rrlp == NULL || check_ttl(result_rrlp) != 0){
dcache_add(result_rrlp); /* save any expired RRs */
if(dns_query(rrlp) == -1)
return NULL;
result_rrlp = dcache_search(rrlp);
}
dcache_add(copy_rr_list(result_rrlp));
return result_rrlp;
}
/* general entry point for address -> domain name resolution.
* Returns RR list, or NULL if no record found.
*/
struct rr *
inverse_a(ip_address)
int32 ip_address;
{
struct rr *prrp;
struct rr *result_rrlp;
char pname[30];
if(ip_address == 0L)
return NULL;
sprintf( pname, "%u.%u.%u.%u.IN-ADDR.ARPA.",
lobyte(loword(ip_address)),
hibyte(loword(ip_address)),
lobyte(hiword(ip_address)),
hibyte(hiword(ip_address)) );
prrp = make_rr(RR_QUERY,pname,CLASS_IN,TYPE_PTR,0,0,NULL);
prrp->next = /* make list to speed search */
make_rr(RR_INQUERY,NULL,CLASS_IN,TYPE_A,0,4,&ip_address);
result_rrlp = resolver(prrp);
free_rr(prrp);
return result_rrlp;
}
/* general entry point for domain name -> resource resolution.
* Returns RR list, or NULL if no record found.
*/
struct rr *
resolve_rr(dname,dtype)
char *dname;
uint16 dtype;
{
struct rr *qrrp;
struct rr *result_rrlp;
char *sname;
int looping = MAXCNAME;
if(dname == NULL)
return NULL;
sname = checksuffix(dname);
qrrp = make_rr(RR_QUERY,sname,CLASS_IN,dtype,0,0,NULL);
FREE(sname);
while(looping > 0){
if((result_rrlp=resolver(qrrp)) == NULL
|| result_rrlp->type == dtype)
break;
#ifdef DEBUG
if(Dtrace)
put_rr(stdout,result_rrlp);
#endif
/* Should be CNAME or PTR record */
/* Replace name and try again */
free(qrrp->name);
qrrp->name = strdup(result_rrlp->rdata.name);
free_rr(result_rrlp);
result_rrlp = NULL;
looping--;
}
free_rr(qrrp);
return result_rrlp;
}
/* main entry point for address -> domain name resolution.
* Returns string, or NULL if no name found.
*/
char *
resolve_a(ip_address,shorten)
int32 ip_address; /* search address */
int shorten; /* return only first part of name (flag)*/
{
struct rr *save_rrlp, *rrlp;
char *result = NULL;
for( rrlp = save_rrlp = inverse_a(ip_address);
rrlp != NULL && result == NULL;
rrlp = rrlp->next ){
if(rrlp->rdlength > 0){
switch(rrlp->type){
case TYPE_PTR:
result = strdup(rrlp->rdata.name);
break;
case TYPE_A:
result = strdup(rrlp->name);
break;
}
}
}
free_rr(save_rrlp);
if(result != NULL && shorten){
int dot;
char *shortened;
if((dot = strcspn(result, ".")) == 0){
shortened = mallocw(dot+1);
strncpy(shortened, result, dot);
shortened[dot] = '\0';
free(result);
result = shortened;
}
}
return result;
}
/* Main entry point for domain name -> address resolution.
* Returns 0 if name is currently unresolvable.
*/
int32
resolve(name)
char *name;
{
register struct rr *rrlp;
int32 ip_address = 0;
if(name == NULL)
return 0;
if(isaddr(name))
return aton(name);
if((rrlp = resolve_rr(name,TYPE_A)) != NULL
&& rrlp->rdlength > 0)
ip_address = rrlp->rdata.addr;
/* multi-homed hosts are handled here */
if(rrlp != NULL && rrlp->next != NULL) {
register struct rr *rrp;
register struct route *rp;
uint16 cost = MAXINT16;
rrp = rrlp;
/* choose the best of a set of routes */
while(rrp != NULL) {
if(rrp->rdlength > 0
&& (rp = rt_lookup(rrp->rdata.addr)) != NULL
&& rp->metric <= cost) {
ip_address = rrp->rdata.addr;
cost = rp->metric;
}
rrp = rrp->next;
}
}
free_rr(rrlp);
return ip_address;
}
/* Main entry point for MX record lookup.
* Returns 0 if name is currently unresolvable.
*/
int32
resolve_mx(name)
char *name;
{
register struct rr *rrp, *arrp;
char *sname, *tmp, *cp;
int32 addr, ip_address = 0;
uint16 pref = MAXINT16;
if(name == NULL)
return 0;
if(isaddr(name)){
if((sname = resolve_a(aton(name),FALSE)) == NULL)
return 0;
}
else
sname = strdup(name);
cp = sname;
while(1){
rrp = arrp = resolve_rr(sname,TYPE_MX);
/* Search this list of rr's for an MX record */
while(rrp != NULL){
if(rrp->rdlength > 0 && rrp->rdata.mx.pref <= pref &&
(addr = resolve(rrp->rdata.mx.exch)) != 0L){
pref = rrp->rdata.mx.pref;
ip_address = addr;
}
rrp = rrp->next;
}
free_rr(arrp);
if(ip_address != 0)
break;
/* Compose wild card one level up */
if((cp = strchr(cp,'.')) == NULL)
break;
tmp = mallocw(strlen(cp)+2);
sprintf(tmp,"*%s",cp); /* wildcard expansion */
free(sname);
sname = tmp;
cp = sname + 2;
}
free(sname);
return ip_address;
}
/* Search for local records of the MB, MG and MR type. Returns list of
* matching records.
*/
struct rr *
resolve_mailb(name)
char *name; /* local username, without trailing dot */
{
register struct rr *result_rrlp;
struct rr *rrlp;
char *sname;
/* Append trailing dot */
sname = mallocw(strlen(name)+2);
sprintf(sname,"%s.",name);
rrlp = make_rr(RR_QUERY,sname,CLASS_IN,TYPE_MB,0,0,NULL);
rrlp->next = make_rr(RR_QUERY,sname,CLASS_IN,TYPE_MG,0,0,NULL);
rrlp->next->next = make_rr(RR_QUERY,sname,CLASS_IN,TYPE_MR,0,0,NULL);
FREE(sname);
if((result_rrlp = dcache_search(rrlp)) == NULL){
result_rrlp = dfile_search(rrlp);
}
free_rr(rrlp);
if(Dsuffix != NULL){
rrlp = result_rrlp;
while(rrlp != NULL){ /* add domain suffix to data */
if(rrlp->rdlength > 0 &&
rrlp->rdata.name[rrlp->rdlength-1] != '.'){
sname = mallocw(rrlp->rdlength +
strlen(Dsuffix)+2);
sprintf(sname,"%s.%s",rrlp->rdata.name,Dsuffix);
free(rrlp->rdata.name);
rrlp->rdata.name = sname;
rrlp->rdlength = strlen(sname);
}
rrlp = rrlp->next;
}
}
dcache_add(copy_rr_list(result_rrlp));
return result_rrlp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -