📄 udp_dom.c
字号:
nans = intel16(qp->h.ancount); /* number of answers */
rcode = DRCODE & intel16(qp->h.flags); /* return code for this message*/
if (rcode > 0)
return(rcode);
if (nans > 0 && /* at least one answer */
(intel16(qp->h.flags) & DQR)) { /* response flag is set */
p = (byte *)&qp->x; /* where question starts */
i = unpackdom((char*)space,(char*)p,(char*)qp); /* unpack question name */
/* spec defines name then QTYPE + QCLASS = 4 bytes */
p += i+4;
/*
* at this point, there may be several answers. We will take the first
* one which has an IP number. There may be other types of answers that
* we want to support later.
*/
while (nans-- > 0) { /* look at each answer */
i = unpackdom((char*)space,(char*)p,(char*)qp); /* answer name to unpack */
/* n_puts(space);*/
p += i; /* account for string */
rrp = (struct rrpart *)p; /* resource record here */
/*
* check things which might not align on 68000 chip one byte at a time
*/
if (!*p && *(p+1) == dtype && /* correct type and class */
!*(p+2) && *(p+3) == DIN) {
unpacker(data,rrp,qp); /* get data we're looking for */
return(0); /* successful return */
}
movmem(&rrp->rdlength,&j,2); /* 68000 alignment */
p += 10+intel16(j); /* length of rest of RR */
}
}
return(-1); /* generic failed to parse */
}
/*********************************************************************/
/* getdomain
* Look at the results to see if our DOMAIN request is ready.
* It may be a timeout, which requires another query.
*/
static int udpdom( byte dtype, unpacker_funct unpacker, void *data )
{
int i,uret;
uret = sock_fastread((sock_type*)dom_sock, (byte*)question, sizeof(struct useek ));
/* this does not happen */
if (uret < 0) {
/* netputevent(USERCLASS,DOMFAIL,-1); */
return(0); /* ?? why'd I change this? -md */
// return(-1);
}
/* num = intel16(question->h.ident); */ /* get machine number */
/*
* check to see if the necessary information was in the UDP response
*/
i = (int) ddextract(question, dtype, unpacker, data);
switch (i) {
case 0: return(1); /* we got a response */
case 3: return(0); /* name does not exist */
case -1:return( 0 ); /* strange return code from ddextract */
default:return( 0 ); /* dunno */
}
}
/**************************************************************************/
/* Sdomain
* DOMAIN based name lookup
* query a domain name server to get resource record data
* Returns the data on a machine from a particular RR type.
* Events generated will have this number tagged with them.
* Returns various negative numbers on error conditions.
*
* if adddom is nonzero, add default domain
*
* Returns true if we got data, false otherwise.
*/
static int Sdomain( char *mname, byte dtype, unpacker_funct unpacker,
void *data, int adddom, longword nameserver, byte *timedout,
sockfunct_t fn ) // S. Lawson
/* int *timedout; set to 1 on timeout */
{
char namebuff[512];
/* int domainsremaining; */
int /*status,*/ i;
int result;
int fnbroke; // S. Lawson
result = 0;
fnbroke = 0; // S. Lawson
*timedout = 1;
if (!nameserver) { /* no nameserver, give up now */
outs("No nameserver defined!\n\r");
return(0);
}
while (*mname && *mname < 33) mname ++; /* kill leading spaces */
if (!(*mname))
return(0);
qinit(); /* initialize some flag fields */
strcpy( namebuff, mname );
if ( adddom ) {
if(namebuff[strlen(namebuff)-1] != '.') { /* if no trailing dot */
if(loc_domain) { /* there is a search list */
// domainsremaining = countpaths( loc_domain ); // why this here? -md
strcat(namebuff,".");
strcat(namebuff,getpath(loc_domain,1));
}
} else
namebuff[ strlen(namebuff)-1] = 0; /* kill trailing dot */
}
/*
* This is not terribly good, but it attempts to use a binary
* exponentially increasing delays.
*/
for ( i = 2; i < 17; i *= 2) {
sendom(namebuff,nameserver, 0xf001, dtype); /* try UDP */
ip_timer_init( dom_sock, i );
do {
kbhit();
tcp_tick( dom_sock );
if (ip_timer_expired( dom_sock )) break;
if ( watcbroke ) {
break;
}
if (chk_timeout( timeoutwhen ))
break;
// S. Lawson - call the idle/break function
if (fn && fn(NULL)!=0) {
result=fnbroke=-1;
*timedout=1;
break;
}
if ( sock_dataready( dom_sock )) *timedout = 0;
} while ( *timedout );
if ( !*timedout ) break; /* got an answer */
}
if ( !*timedout && !fnbroke) // S. Lawson
result = udpdom(dtype, unpacker, data); /* process the received data */
sock_close( dom_sock );
return( result );
}
/*
* nextdomain - given domain and count = 0,1,2,..., return next larger
* domain or NULL when no more are available
*/
static char *nextdomain( char *domain, int count )
{
char *p;
int i;
p = domain;
// S. Lawson
#ifdef SCANDOMAIN // scan all domain pieces
for (i = 0; i < count; ++i) {
p = strchr( p, '.' );
if (!p) return( NULL );
++p;
}
#else // whole domain name only
if (count > 0) return NULL;
#endif
return( p );
}
/*
* Perform a nameserver lookup of specified type using specified
* unpacker to extract data, if found.
*/
static int do_ns_lookup( char *name, byte dtype,
unpacker_funct unpacker, void *data, sockfunct_t fn ) // S. Lawson
{
/* longword temp; */
int result = 0; // init to false
int count, i;
byte timeout[ MAX_NAMESERVERS ];
struct useek qp; /* temp buffer */
udp_Socket ds; /* temp buffer */
word oldhndlcbrk;
question = &qp;
dom_sock = &ds;
if (!name) return( 0 );
rip( name );
if (!_domaintimeout) _domaintimeout = sock_delay << 2;
timeoutwhen = set_timeout( _domaintimeout );
count = 0;
memset( &timeout, 0, sizeof( timeout ));
oldhndlcbrk = wathndlcbrk;
wathndlcbrk = 1; /* enable special interrupt mode */
watcbroke = 0;
do {
if ( (loc_domain = nextdomain( def_domain, count )) == NULL )
count = -1; /* use default name */
for ( i = 0; i < _last_nameserver ; ++i ) {
if (!timeout[i])
if ((result = Sdomain( name, dtype, unpacker, data, count != -1 ,
def_nameservers[i], &timeout[i], fn)) == 1) // S. Lawson
break; /* got name, bail out of loop */
if (result==-1) break; // S. Lawson
}
if (count == -1) break;
count++;
} while (!result);
watcbroke = 0; /* always clean up */
wathndlcbrk = oldhndlcbrk;
if (result==-1) result=0; // S. Lawson
return( result );
}
// S. Lawson - keep a resolve(char *) version
longword resolve( char *name )
{
return (resolve_fn(name,NULL));
}
/*
* resolve()
* convert domain name -> address resolution.
* returns 0 if name is unresolvable right now
*/
longword resolve_fn( char *name, sockfunct_t fn ) // S. Lawson
{
longword ipaddr;
// S. Lawson
#define DNSCACHESIZE 4 // cache up to 4 names
#define DNSCACHELENGTH 32 // up to 32 characters
#define DNSCACHETIMEOUT 120 // for up to 2 minutes
static char DNScacheName[DNSCACHESIZE][DNSCACHELENGTH];
static longword DNScacheIP[DNSCACHESIZE];
static longword DNScacheTimeout[DNSCACHESIZE]={0,0,0,0};
static char DNScacheNext=0;
int DNScacheScan;
if( !name ) return 0L;
rip( name ); // S. Lawson - trim for cache scan
if ( isaddr( name ))
return( aton( name ));
// S. Lawson
for (DNScacheScan=0 ; DNScacheScan<DNSCACHESIZE ; DNScacheScan++) {
if (DNScacheTimeout[DNScacheScan]==0L) continue;
if (chk_timeout(DNScacheTimeout[DNScacheScan])) {
DNScacheTimeout[DNScacheScan]=0L;
continue;
}
if(!strcmpi(DNScacheName[DNScacheScan],name))
return DNScacheIP[DNScacheScan];
}
#ifdef NOTUSED // S. Lawson
if( do_ns_lookup(name, DTYPEA, typea_unpacker, &ipaddr) )
return (intel(ipaddr));
else return (0L);
#else // S. Lawson
if( do_ns_lookup(name, DTYPEA, typea_unpacker, &ipaddr, fn) ) {
strncpy(DNScacheName[DNScacheNext], name, DNSCACHELENGTH);
DNScacheName[DNScacheNext][DNSCACHELENGTH-1]='\0';
DNScacheIP[DNScacheNext]=intel(ipaddr);
DNScacheTimeout[DNScacheNext]=set_timeout(DNSCACHETIMEOUT);
if (++DNScacheNext>=DNSCACHESIZE) DNScacheNext=0;
return (intel(ipaddr));
}
return (0L);
#endif // S. Lawson
}
// S. Lawson - keep version w/o fn
int reverse_addr_lookup( longword ipaddr, char *name )
{
return(reverse_addr_lookup_fn(ipaddr, name, NULL));
}
/*
* reverse_addr_lookup()
* lookup a hostname based on IP address
* (PTR lookups in the .in-addr.arpa domain)
*
* Returns true if the info was found, false otherwise.
*
* assumes: name buffer is big enough for the longest hostname
*/
int reverse_addr_lookup_fn( longword ipaddr, char *name, sockfunct_t fn )
{
char revname[64];
inet_ntoa( revname, ntohl(ipaddr) ); /* ntohl flips order */
strcat(revname, ".IN-ADDR.ARPA.");
return ( do_ns_lookup(revname, DTYPEPTR, typeptr_unpacker, (void*)name, fn) ); // S. Lawson
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -