📄 domain.c
字号:
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;
SysLfree(rrp->comment);
SysLfree(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:
SysLfree(rrp->rdata.name);
break;
case TYPE_HINFO:
SysLfree(rrp->rdata.hinfo.cpu);
SysLfree(rrp->rdata.hinfo.os);
break;
case TYPE_MX:
SysLfree(rrp->rdata.mx.exch);
break;
case TYPE_SOA:
SysLfree(rrp->rdata.soa.mname);
SysLfree(rrp->rdata.soa.rname);
break;
}
}
SysLfree(rrp);
}
}
static struct rr *make_rr(int source, char *dname, u_int16 dclass,
u_int16 dtype, int32 ttl, u_int16 rdl, void *data)
{
register struct rr *newrr;
newrr = (struct rr *)SysLcalloc(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(struct rr *rrlp)
{
register struct rr *rrp, *test_rrp;
struct rr **rrpp, *result_rrlp;
//int32 elapsed; /*************已经修改********************/
int count = 0;
rrpp = &result_rrlp;
for(rrp = Dcache; (test_rrp = rrp) != NULL;){
rrp = rrp->next;
/* timeout entries */
if(test_rrp->ttl > 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
** We do not use the real file access , so we empty this function and just return NULL
** Lingming 8/19/1999
**/
static struct rr *get_rr(KFILE *fp, struct rr *lastrrp)
{
return NULL;
}
/* Print a resource record */
/** We do not use the real file access , so we empty this function and just return
** Lingming 8/19/1999
**/
static void
put_rr(KFILE *fp, struct rr *rrp)
{
return;
}
/* Search local database for resource records.
* Returns RR list, or NULL if no record found.
* We do not use the real file access , so we empty this function and just return NULL
* Lingming 8/19/1999
*/
static struct rr *dfile_search(struct rr *rrlp)
{
return NULL;
}
/* Process which will add new resource records from the cache
* to the local file, eliminating duplicates while it goes.
* We do not use the real file access , so we empty this function and just return
* Lingming 8/19/1999
*/
static void
dfile_update(s,unused,p)
int s;
void *unused;
void *p;
{
return;
}
/**
** Domain Server Utilities
**/
static void
dumpdomain(dhp,rtt)
struct dhdr *dhp;
int32 rtt;
{
//struct rr *rrp; 已经修改
//char * stuff; 已经修改
}
static int
dns_makequery(op,srrp,buffer,buflen)
u_int16 op; /* operation */
struct rr *srrp;/* Search RR */
u_int8 *buffer; /* Area for query */
u_int16 buflen; /* Length of same */
{
u_int8 *cp;
char *cp1;
char *dname, *sname;
u_int16 parameter;
//u_int16 dlen,len;
u_int16 len;
unsigned long dlen;
cp = buffer;
/* Use millisecond clock for timestamping */
cp = (u_int8 *)put16(cp,(u_int16)mtime());
parameter = (op << 11)
| 0x0100; /* Recursion desired */
cp = (u_int8 *)put16(cp,parameter);
cp = (u_int8 *)put16(cp,1);
cp = (u_int8 *)put16(cp,0);
cp = (u_int8 *)put16(cp,0);
cp = (u_int8 *)put16(cp,0);
sname = strdup(srrp->name);
dname = sname;
dlen = strlen(dname);
for(;;){
/* Look for next dot */
cp1 = (char*)strchr(dname,(int)'.');
if(cp1 != NULL)
len = cp1-dname; /* More to come */
else
len =(unsigned short)dlen; /* Last component */
*cp++ =(unsigned char)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;
}
SysLfree(sname);
cp = (u_int8 *)put16(cp,srrp->type);
cp = (u_int8 *)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 dhdr *dhp;
struct dserver *dp; /* server list */
int32 rtt,abserr;
int tried = 0; /* server list has been retried (count) */
u_int8 *buf;
int n;
if((dp = Dservers) == NULL)
return -1;
if ((buf = (u_int8 *)SysLcalloc(512)) == NULL)
return -1;
for(;;){
int len;
struct sockaddr_in server_in;
int s;
int rval;
n = 0;
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;
//server_in.sin_port = htons(IPPORT_DOMAIN);
//server_in.sin_addr.s_addr = htonl(dp->address);
memset(buf, 0, 512);
len = dns_makequery(0, rrlp, buf, 512);
s = udpOpen();
udpConnect(s, &server_in, 0);
//if(sendto(s,buf,len,0,(struct sockaddr *)&server_in,sizeof(server_in)) == -1)
//perror("domain sendto");
udpWrite(s, buf, len);
// delay(500);
delay(3000);
while(1) {
memset(buf, 0, 512);
rval = udpRead(s, buf, 512); //maybe read part data
n++;
if ((rval > 0) || (n == 100)) break;
//if(rval > 0) break;
}
if(rval > 0) break;
udpClose(s);
if(rval > 12) break; //no use
//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 *) SysLcalloc(sizeof(struct dhdr));
memset(dhp, 0, sizeof(struct dhdr));
//ntohdomain(dhp,&bp); /* Convert to local format */
if (getdnshdr(dhp, buf) < 0) return -1;
/* Compute and update the round trip time */
rtt = (int32) ((u_int16)mtime() - 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 = mtime()/1000 + Dfile_wait_relative;
if(Dfile_updater == NULL){
//Dfile_updater = newproc("domain update",
// 80,dfile_update,0,NULL,NULL,0);// the origin stk is 512 LM 2000/09/22
}
SysLfree(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,(int)'.') == NULL && Dsuffix != NULL){
/* Append default suffix */
tname = (char *)SysLcalloc(strlen(sname)+strlen(Dsuffix)+2);
sprintf(tname,"%s.%s",sname,Dsuffix);
SysLfree(sname);
sname = tname;
}
if(sname[strlen(sname)-1] != '.'){
/* Append trailing dot */
tname = (char *)SysLcalloc(strlen(sname)+2);
sprintf(tname,"%s.",sname);
SysLfree(sname);
sname = tname;
}
return sname;
}
/* Search for resource records.
* Returns RR list, or NULL if no record found.
*/
static struct rr *resolver(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(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(char *dname, u_int16 dtype)
{
struct rr *qrrp;
struct rr *result_rrlp;
char *sname;
int looping = MAXCNAME;
if(dname == NULL)
return NULL;
sname = checksuffix(dname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -