📄 domain.c
字号:
/*
* DOMAIN.C -- domain name system stub resolver
* Original code by zhengkaidong&lingming
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys\lmalloc.h>
#include "net.h"
#include "netudp.h"
#include "netconf.h"
#include "domain.h"
#include "InetAddr.h"
//#undef DEBUG /* for certain trace messages */
//#undef DEBUG_PAIN /* for painful debugging */
struct rr *Dcache = NULL; /* Cache of resource records */
int Dcache_size = 20; /* size limit */
int Dfile_clean = FALSE; /* discard expired records (flag) */
int Dfile_reading = 0; /* read interlock (count) */
int Dfile_writing = 0; /* write interlock (count) */
struct proc *Dfile_updater = NULL;
int32 Dfile_wait_absolute = 0L; /* timeout Clock time */
int Dfile_wait_relative = 300; /* timeout file activity (seconds) */
struct dserver *Dservers = NULL; /* List of potential servers */
int Dserver_retries = 2; /* Attempts to reach servers */
char *Dsuffix = NULL; /* Default suffix for names without periods */
int Dtrace = FALSE;
static char *Dtypes[] = {
"",
"A",
"NS",
"MD",
"MF",
"CNAME",
"SOA",
"MB",
"MG",
"MR",
"NULL",
"WKS",
"PTR",
"HINFO",
"MINFO",
"MX",
"TXT"
};
static int Ndtypes = 17;
// static char delim[] = " \t\r\n"; 已经修改
/*static int docache(int argc,char *argv[],void *p);
static int dosuffix(int argc,char *argv[],void *p);
static int docacheclean(int argc,char *argv[],void *p);
static int docachelist(int argc,char *argv[],void *p);
static int docachesize(int argc,char *argv[],void *p);
static int docachewait(int argc,char *argv[],void *p);
*/
static void dlist_add(struct dserver *dp);
static void dlist_drop(struct dserver *dp);
/*
static int dodnsadd(int argc,char *argv[],void *p);
static int dodnsdrop(int argc,char *argv[],void *p);
static int dodnslist(int argc,char *argv[],void *p);
static int dodnsquery(int argc,char *argv[],void *p);
static int dodnsretry(int argc,char *argv[],void *p);
static int dodnstrace(int argc,char *argv[],void *p);*/
static char * dtype(int value);
static int check_ttl(struct rr *rrlp);
static int compare_rr(struct rr *search_rrp,struct rr *target_rrp);
static int compare_rr_list(struct rr *rrlp,struct rr *target_rrp);
static struct rr *copy_rr(struct rr *rrp);
static struct rr *copy_rr_list(struct rr *rrlp);
static struct rr *make_rr(int source,
char *dname,u_int16 class,u_int16 type,int32 ttl,u_int16 rdl,void *data);
static void dcache_add(struct rr *rrlp);
static void dcache_drop(struct rr *rrp);
static struct rr *dcache_search(struct rr *rrlp);
static void dcache_update(struct rr *rrlp);
static struct rr *get_rr(KFILE *fp, struct rr *lastrrp);
static void put_rr(KFILE *fp,struct rr *rrp);
static struct rr *dfile_search(struct rr *rrlp);
static void dfile_update(int s,void *unused,void *p);
static void dumpdomain(struct dhdr *dhp,int32 rtt);
static int dns_makequery(u_int16 op,struct rr *rrp,
u_int8 *buffer,u_int16 buflen);
static int dns_query(struct rr *rrlp);
static int isaddr(char *s);/* we may use it in other program*/
static char *checksuffix(char *dname);
static struct rr *resolver(struct rr *rrlp);
char *strdup(const char *s);
static u_int8 *put16(u_int8 *cp, u_int16 x);
static u_int8 *put32(u_int8 *cp, int32 x);
static u_int16 get16(u_int8 *cp);
static int32 get32(u_int8 *cp);
static int dn_expand(u_int8 *msg,u_int8 *eom,
u_int8 *compressed,char *full,int fullen);
static u_int8 *getq(struct rr **rrpp,u_int8 *msg,u_int8 *cp);
static u_int8 *ntohrr(struct rr **rrpp,u_int8 *msg,u_int8 *cp);
int setint(int *var, char *label, int argc, char *argv[]);
void free_rr(struct rr *rrlp);
struct rr *inverse_a(int32 ip_address);
struct rr *resolve_rr(char *dname,u_int16 dtype);
char *resolve_a(int32 ip_address, int shorten);
struct rr *resolve_mailb(char *name);
/**
** Domain Resolver Commands
**/
/*static struct cmds Dcmds[] = {
"addserver", dodnsadd, 0, 2, "add <hostid>",
"dropserver", dodnsdrop, 0, 2, "drop <hostid>",
"list", dodnslist, 0, 0, NULL,
"query", dodnsquery, 512, 2, "query <hostid>",
"retry", dodnsretry, 0, 0, NULL,
"suffix", dosuffix, 0, 0, NULL,
"trace", dodnstrace, 0, 0, NULL,
"cache", docache, 0, 0, NULL,
NULL,
};
static struct cmds Dcachecmds[] = {
"clean", docacheclean, 0, 0, NULL,
"list", docachelist, 512, 0, NULL,
"size", docachesize, 0, 0, NULL,
"wait", docachewait, 0, 0, NULL,
NULL,
};
int
dodomain(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Dcmds,argc,argv,p);
}
static int
docache(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Dcachecmds,argc,argv,p);
}
static int
dosuffix(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2){
return 0;
}
SysLfree(Dsuffix);
Dsuffix = strdup(argv[1]);
return 0;
}
static int
docacheclean(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return 0;
}
static int
docachelist(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct rr *rrp;
struct session *sp;
int row = 25;
(void)dcache_search(NULL);
return 0;
}
static int
docachesize(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int newsize;
int oldsize;
int result;
newsize = oldsize = Dcache_size;
result = setint( &newsize, "memory cache size", argc,argv );
if(newsize > 0){
Dcache_size = newsize;
if(newsize < oldsize){
(void)dcache_search(NULL); // update size
}
}
return result;
}
static int
docachewait(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setint( &Dfile_wait_relative, "time before file update (seconds)", argc,argv );
}*/
static void
dlist_add(struct dserver *dp)
{
struct dserver *server;
server = Dservers;
while (server != NULL) {
if (server->address == dp->address) return;
else server = server->next;
}
dp->prev = NULL;
dp->next = Dservers;
if(Dservers != NULL)
Dservers->prev = dp;
Dservers = dp;
}
static void
dlist_drop(dp)
register struct dserver *dp;
{
if(dp->prev != NULL)
dp->prev->next = dp->next;
else
Dservers = dp->next;
if(dp->next != NULL)
dp->next->prev = dp->prev;
}
/*static int
dodnsadd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 address;
char *tempstr;
if((address = resolve(argv[1])) == 0L){
sprintf(tempstr,"Resolver %s unknown\n",argv[1]);
//Disp16String(tempstr,10,10);
return 1;
}
return add_nameserver(address);
}*/
int add_nameserver(address)
int32 address;
{
struct dserver *dp;
if ((dp = (struct dserver *)SysLcalloc(sizeof(struct dserver))) == NULL)
return -1;
dp->address = address;
dp->srtt = INITRTT;
dp->mdev = 0;
dp->timeout = 2 * dp->mdev + dp->srtt + 3;
dlist_add(dp);
return 0;
}
/*static int
dodnsdrop(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct dserver *dp;
int32 addr;
addr = resolve(argv[1]);
for(dp = Dservers;dp != NULL;dp = dp->next)
if(addr == dp->address)
break;
if(dp == NULL){
//Disp16String("Not found",10,10);
return 1;
}
dlist_drop(dp);
SysLfree(dp);
return 0;
}
static int
dodnslist(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct dserver *dp;
return 0;
}
static int
dodnsquery(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct rr *rrp;
struct rr *result_rrlp;
char *sname;
struct session *sp;
int row = 25;
if ( isaddr( argv[1] ) ) {
result_rrlp = inverse_a( atol( argv[1] ) );
} else {
sname = checksuffix( argv[1] );
rrp = make_rr(RR_QUERY,sname,CLASS_IN,TYPE_ANY,0,0,NULL);
SysLfree(sname);
dns_query(rrp);
result_rrlp = dcache_search(rrp);
free_rr(rrp);
}
return 0;
}
static int
dodnsretry(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setint( &Dserver_retries, "server retries", argc,argv );
}
static int
dodnstrace(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return 0;
}*/
/**
** Domain Resource Record Utilities
**/
static char *
dtype(value)
int value;
{
static char buf[10];
if (value < Ndtypes)
return Dtypes[value];
sprintf( buf, "{%d}", value);
return buf;
}
/* check list of resource records for any expired ones.
* returns number of expired records.
*/
static int
check_ttl(rrlp)
register struct rr *rrlp;
{
int count = 0;
while(rrlp != NULL){
if(rrlp->ttl == 0L)
count++;
rrlp = rrlp->next;
}
return count;
}
/* Compare two resource records.
* returns 0 if match, nonzero otherwise.
*/
static int
compare_rr(search_rrp,target_rrp)
register struct rr *search_rrp,*target_rrp;
{
int i;
if(search_rrp == NULL || target_rrp == NULL)
return -32765;
if(search_rrp->class != target_rrp->class)
return -32763;
if(search_rrp->type != TYPE_ANY
&& search_rrp->type != target_rrp->type
&& (search_rrp->source != RR_QUERY
|| (target_rrp->type != TYPE_CNAME
&& target_rrp->type != TYPE_PTR)))
return -32761;
if(search_rrp->source != RR_INQUERY){
if((i = strlen(search_rrp->name)) != (signed int)(strlen(target_rrp->name)))
return -32759;
if((i = strncmp(search_rrp->name,target_rrp->name,i)) != 0)/*modified by zkd 8.19 1999*/
return i;
/* match negative records so that they are replaced */
if(target_rrp->rdlength == 0)
return 0;
}
/* if a query has gotten this far, match it */
if(search_rrp->source == RR_QUERY)
return 0;
/* ensure negative records don't replace older records */
if(search_rrp->rdlength == 0)
return -32757;
/* match expired records so that they are replaced */
if(search_rrp->source != RR_INQUERY){
if(target_rrp->ttl == 0L)
return 0;
}
/* Note: rdlengths are not compared because they vary depending
* on the representation (ASCII or encoded) this record was
* generated from.
*/
switch(search_rrp->type){
case TYPE_A:
i = search_rrp->rdata.addr != target_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:
i = strcmp(search_rrp->rdata.data,target_rrp->rdata.data);
break;
case TYPE_HINFO:
i = strcmp(search_rrp->rdata.hinfo.cpu,target_rrp->rdata.hinfo.cpu) ||
strcmp(search_rrp->rdata.hinfo.os,target_rrp->rdata.hinfo.os);
break;
case TYPE_MX:
i = strcmp(search_rrp->rdata.mx.exch,target_rrp->rdata.mx.exch);
break;
case TYPE_SOA:
i = search_rrp->rdata.soa.serial != target_rrp->rdata.soa.serial;
break;
default:
i = -32755; /* unsupported */
}
return i;
}
static int
compare_rr_list(rrlp,target_rrp)
register struct rr *rrlp,*target_rrp;
{
while(rrlp != NULL){
if(compare_rr(rrlp,target_rrp) == 0)
return 0;
rrlp = rrlp->next;
}
return -32767;
}
/* Make a new copy of a resource record */
static struct rr *copy_rr(struct rr *rrp)
{
register struct rr *newrr;
if(rrp == NULL)
return NULL;
newrr = (struct rr *)SysLcalloc(sizeof(struct rr));
newrr->source = rrp->source;
newrr->name = strdup(rrp->name);
newrr->type = rrp->type;
newrr->class = rrp->class;
newrr->ttl = rrp->ttl;
if((newrr->rdlength = rrp->rdlength) == 0)
return newrr;
switch(rrp->type){
case TYPE_A:
newrr->rdata.addr = 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:
newrr->rdata.name = strdup(rrp->rdata.name);
break;
case TYPE_HINFO:
newrr->rdata.hinfo.cpu = strdup(rrp->rdata.hinfo.cpu);
newrr->rdata.hinfo.os = strdup(rrp->rdata.hinfo.os);
break;
case TYPE_MX:
newrr->rdata.mx.pref = rrp->rdata.mx.pref;
newrr->rdata.mx.exch = strdup(rrp->rdata.mx.exch);
break;
case TYPE_SOA:
newrr->rdata.soa.mname = strdup(rrp->rdata.soa.mname);
newrr->rdata.soa.rname = strdup(rrp->rdata.soa.rname);
newrr->rdata.soa.serial = rrp->rdata.soa.serial;
newrr->rdata.soa.refresh = rrp->rdata.soa.refresh;
newrr->rdata.soa.retry = rrp->rdata.soa.retry;
newrr->rdata.soa.expire = rrp->rdata.soa.expire;
newrr->rdata.soa.minimum = rrp->rdata.soa.minimum;
break;
}
return newrr;
}
static struct rr *copy_rr_list(struct rr *rrlp)
{
register struct rr **rrpp;
struct rr *result_rrlp;
rrpp = &result_rrlp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -