📄 dnsclnt.c
字号:
/* FUNCTION: dns_lookup()
*
* dns_lookup() - check state of a DNS client request previously
* launched with dns_query(). Passed IP address is filled in (in net
* endian) if DNS query was resolved without error, else this clears
* passed Ip address and returns non-zero ENP_ code.
*
*
* PARAM1: ip_addr * ip
* PARAM2: char * name
*
* RETURNS: ENP_SEND_PENDING if request is still on the net, or ENP_TIMEOUT
* if request timed out (or was never made), or 0 (SUCCESS) if passed IP
* is filled in and everything is peachy, or other ENP errors if
* detected.
*/
int
dns_lookup(ip_addr * ip, char * name)
{
int entry;
int e;
*ip = 0L;
e = dnc_lookup(name, &entry);
if (e == 0)
*ip = dns_qs[entry].ipaddr_list[0]; /* return IP address */
return e;
}
/* FUNCTION: t_gethostbyname()
*
* does a DNS lookup of the host named in name and fills in the
* passed in p_hostent structure accordingly. its up to the caller to
* prepopulate the hostent structure with an array of pointers to 4
* byte buffers. see how gethostbyname() below calls
* t_gethostbyname() for an example of how to do this.
*
*
* PARAM1: char *name
* PARAM2: struct hostent *p_hostent
* PARAM3: char type request type: A or SOA
*
* RETURNS: 0 if successful, ENP_SEND_PENDING if DNS lookup is in progress
*/
#ifdef DNS_CLIENT_UPDT
int t_gethostbyname(char *name, struct hostent *p_hostent, char type)
#else
int t_gethostbyname(char *name, struct hostent *p_hostent)
#endif /* DNS_CLIENT_UPDT */
{
char * cp;
ip_addr address;
unsigned int snbits;
int i;
int entry; /* dns entry index */
int e;
/* first see if the passed in name looks like a dot notation IP address */
cp = parse_ipad(&address,&snbits,name);
/* if it does look like an dot notation IP address,
don't both with the DNS lookup */
if (!cp)
{
/* fill in the hostent structure */
p_hostent->h_name = name;
p_hostent->h_aliases = NULL; /* we don't do the aliases */
p_hostent->h_addrtype = 2; /* AF_INET */
p_hostent->h_length = 4; /* length of IP address */
/* if this is true it means the caller didn't set up the host_ent
right, there's no place to store the IP address */
if (!(p_hostent->h_addr_list) || !(p_hostent->h_addr_list[0]))
return ENP_PARAM;
else
{
/* copy the parsed IP address to the first h_addr_list buffer */
MEMCPY(p_hostent->h_addr_list[0],&address,4);
/* and zero out the rest */
for (i = 1; i < MAXDNSADDRS; ++i)
{
p_hostent->h_addr_list[i] = 0;
}
}
return 0; /* success */
}
/* if no DNS servers are set up, the lookup will not work */
if (!dns_servers[0])
return ENP_LOGIC;
/* see if we already have an entry for the host */
e = dnc_lookup(name, &entry);
/* if so, and it's a completed request... */
if (e == 0)
{
/* fill in the hostent structure */
p_hostent->h_name = name;
p_hostent->h_aliases = NULL; /* we don't do the aliases */
p_hostent->h_addrtype = 2; /* AF_INET */
p_hostent->h_length = 4; /* length of IP address */
#ifdef DNS_CLIENT_UPDT
p_hostent->h_rcode = dns_qs[entry].rcode;
#endif /* DNS_CLIENT_UPDT */
/* if this is true it means the caller didn't set up the host_ent
right, there's no place to store the IP address */
if (!(p_hostent->h_addr_list))
return ENP_PARAM;
else
{
/* copy the IP addresses in the entry to the h_addr_list */
for (i = 0; i < MAXDNSADDRS; ++i)
{
/* if no more addresses in entry, no more to copy */
if (!dns_qs[entry].ipaddr_list[i])
break;
/* if caller didn't set up hostent right */
if (!(p_hostent->h_addr_list[i]))
return ENP_PARAM;
/* copy the IP address to the h_addr_list */
MEMCPY(p_hostent->h_addr_list[i],
&dns_qs[entry].ipaddr_list[i],4);
}
/* zero out the unused h_addr_list entries */
for ( ; i < MAXDNSADDRS; ++i)
p_hostent->h_addr_list[i] = 0;
}
return 0; /* success */
}
/* else, if dnc_lookup() found the entry, return its status */
else if (e != ENP_PARAM)
{
return e;
}
/* there is no entry for the host so make sure we have a spare entry */
/* try to make room if necessary */
dnc_makeroom();
/* look for an available entry */
for (entry = 0; entry < MAXDNSENTRY; entry++)
if (dns_qs[entry].id == 0) /* found empty entry? */
break;
/* sanity check to make sure we really have a free entry */
if (entry >= MAXDNSENTRY)
{
dtrap("dnsclnt 5\n"); /* may need to increase MAXDNSENTRY */
return ENP_RESOURCE;
}
/* prepare entry for use and copy in name */
MEMSET(&dns_qs[entry], 0, sizeof(dns_qs[entry])); /* clear entry */
strncpy(dns_qs[entry].dns_name, name, MAXDNSNAME-1); /* copy in name */
dns_qs[entry].id = dnsids++; /* set ID for this transaction */
#ifdef DNS_CLIENT_UPDT
dns_qs[entry].type = type; /* set request type */
#endif /* DNS_CLIENT_UPDT */
if (dnsids == 0) /* don't allow ID of 0 */
dnsids++;
#ifdef DNS_CLIENT_UPDT
if (type == DNS_UPDT) /* UPDATE packet */
{
strncpy(dns_qs[entry].h_z_name, p_hostent->h_z_name, MAXDNSNAME-1);
dns_qs[entry].h_add_ipaddr = p_hostent->h_add_ipaddr;
dns_qs[entry].h_ttl = p_hostent->h_ttl;
}
#endif /* DNS_CLIENT_UPDT */
/* get UDP port for packet, keep for ID */
dns_qs[entry].lport = udp_socket();
dnsc_active++; /* maintain global dns pending count */
dnsc_requests++; /* count this request */
e = dnc_sendreq(entry);
if (e == 0) /* first packet sent OK */
return ENP_SEND_PENDING;
else /* some kind of error */
return e;
}
/* hostent structure returned by gethostbyname() */
static struct hostent gethostbyname_ent;
/* array of pointers addressed by hostent h_addr_list field */
static char *gethostbyname_ip_ptrs[MAXDNSADDRS];
/* buffers for IP addresses addressed by pointer array, a mess aint it */
static char gethostbyname_ip_addresses[MAXDNSADDRS][4];
/* FUNCTION: *gethostbyname()
*
* "standard" Unixey version of gethostbyname() that is not
* re-entrant. returns pointer to static hostent structure if
* successful, NULL if not successful. note that its not completely
* standard in that the list of aliases returned by the DNS lookup
* will not be in the hostent.
*
*
* PARAM1: char *name
*
* RETURNS: pointer to static hostent structure if successful, NULL if not.
*/
#ifdef DNS_CLIENT_UPDT
struct hostent * gethostbyname(char *name, char type)
#else
struct hostent * gethostbyname(char *name)
#endif /* DNS_CLIENT_UPDT */
{
int i;
int rc = 0;
unsigned long tmo;
/* set up array of pointers to point to IP address buffers */
/* t_gethostbyname() will set to NULL those pointers in this array
that do not point to IP addresses once DNS lookup is done */
for (i = 0; i < MAXDNSADDRS; ++i)
{
gethostbyname_ip_ptrs[i] = gethostbyname_ip_addresses[i];
}
/* set h_addr_list field to point to array of pointers */
gethostbyname_ent.h_addr_list = gethostbyname_ip_ptrs;
/* we will call t_gethostbyname() until it either succeeds, fails or
we time out trying */
tmo = cticks + (5 * TPS);
while (tmo > cticks)
{
/* let t_gethostbyname() do the actual work */
#ifdef DNS_CLIENT_UPDT
rc = t_gethostbyname(name,&gethostbyname_ent, type);
#else
rc = t_gethostbyname(name,&gethostbyname_ent);
#endif
/* if it succeeds, t_gethostbyname() returns 0. if it hard
* fails, t_gethostbyname() returns negative number, so
*/
if (rc <= 0)
break;
/* if it returns a positive number, a request is pending so
yield and loop to try again until we time out */
tk_yield();
}
/* rc != 0 implies we either failed or timed out trying so return
* NULL to indicate failure, else return address of static
* hostent. if you want to be able to retrieve the error code via
* whatever mechanism you are using to implement errno on your
* target system,
*/
return rc ? NULL : &gethostbyname_ent;
}
#ifdef DNS_CLIENT_UPDT
/* FUNCTION: unsigned dns_update()
*
* dns_update- sends a DNS UPDATE packet to the authoritative server
* of the specified domain name. This routine uses the getsoa call
* to get the authoritative server of the domain name. It then sends
* the UPDATE packet to the authoritative server.
*
*
* PARAM1: char *soa_mname domain name
* PARAM2: char *dname host name
* PARAM3: ip_addr ipaddress ip address
* PARAM4: unsigned long ttl ttl value
*
* RETURNS: NULL if successful, else returns one of the UPDATE errors.
*/
int
dns_update(char *soa_mname, char *dname, ip_addr ipaddr, unsigned long ttl,
void * pio)
{
struct hostent * p;
unsigned char * ucp;
ip_addr save_dns_srvr;
/* get authoritative name server for specified domain */
p = getsoa(soa_mname);
/*
* If we received a hostent structure, send the update packet to the
* received IP address
*/
if (p)
{
ucp = (unsigned char *) *(p->h_addr_list);
MEMCPY(&save_dns_srvr, dns_servers, 4);
MEMCPY(dns_servers, ucp, 4);
ns_printf(pio," sending update packet to %d.%d.%d.%d\n",
*ucp, *(ucp + 1), *(ucp + 2), *(ucp + 3));
p->h_z_name = soa_mname;
p->h_add_ipaddr = ipaddr;
p->h_ttl = ttl;
p = gethostbyname(dname, 5);
MEMCPY(dns_servers, &save_dns_srvr, 4);
if (p)
return p->h_rcode; /* Return the output of UPDATE packet */
}
return -1; /* authoritative name server not found */
}
/* FUNCTION: hostent * getsoa(soa_mname)
*
* PARAM1: char *soa_mname zone name
*
* RETURNS: Name of the authoritative name server for the zone.
*/
struct hostent * getsoa(char * soa_mname)
{
struct hostent * p;
p = gethostbyname(soa_mname, 2);
return p;
}
#endif /* DNS_CLIENT_UPDT */
#ifdef NET_STATS
/* FUNCTION: dns_state()
*
* PARAM1: void * pio
*
* RETURNS:
*/
int
dns_state(void * pio)
{
int i;
ns_printf(pio,"DNS servers:");
for (i = 0; i < MAXDNSSERVERS; i++)
ns_printf(pio,"%u.%u.%u.%u ", PUSH_IPADDR(dns_servers[i]) );
ns_printf(pio,"\nDNS cache:\n");
for (i = 0; i < MAXDNSENTRY; i++)
{
ns_printf(pio,"name: %s, IP: %u.%u.%u.%u, ",
dns_qs[i].dns_name, PUSH_IPADDR(dns_qs[i].ipaddr_list[0]) );
ns_printf(pio,"retry:%d, ID:%d, rcode:%d, err:%d\n",
dns_qs[i].tries, dns_qs[i].id, dns_qs[i].rcode, dns_qs[i].err);
}
ns_printf(pio,"protocol/implementation runtime errors:%lu\n", dnsc_errors);
ns_printf(pio,"requests sent:%lu\n", dnsc_requests);
#ifdef DNS_CLIENT_UPDT
ns_printf(pio, "Updates sent:%lu\n", dnsc_updates);
#endif /* DNS_CLIENT_UPDT */
ns_printf(pio,"replies received:%lu\n", dnsc_replies);
ns_printf(pio,"usable replies:%lu\n", dnsc_good);
ns_printf(pio,"total retries:%lu\n", dnsc_retry);
ns_printf(pio,"timeouts:%lu\n", dnsc_tmos);
return 0;
}
#endif /* NET_STATS */
#endif /* DNS_CLIENT */
/* end of file dnsclnt.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -