#include "loc.h"
short rr_errno;
void
usage ()
{
(void) fprintf (stderr,
"Usage: %s: [-v] [-d nnn] hostname\n", progname);
exit (2);
}
void
panic (message)
char *message;
{
(void) fprintf (stderr,
"%s: %s\n", progname, message);
exit (2);
}
#ifndef ARPA_ROOT
#define ARPA_ROOT "in-addr.arpa"
#endif
char *
in_addr_arpa (dottedquad)
char *dottedquad;
{
static char addrbuf[4 * 4 + sizeof (ARPA_ROOT) + 2];
unsigned int a[4];
register int n;
n = sscanf (dottedquad, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3]);
switch (n)
{
case 4:
(void) sprintf (addrbuf, "%u.%u.%u.%u.%s.",
a[3] & 0xff, a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
break;
case 3:
(void) sprintf (addrbuf, "%u.%u.%u.%s.",
a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
break;
case 2:
(void) sprintf (addrbuf, "%u.%u.%s.",
a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
break;
case 1:
(void) sprintf (addrbuf, "%u.%s.",
a[0] & 0xff, ARPA_ROOT);
break;
default:
return (NULL);
}
while (--n >= 0)
if (a[n] > 255)
return (NULL);
return (addrbuf);
}
char *
getlocbyname (name, is_network)
const char *name;
short is_network;
{
char *result;
struct list_in_addr *list, *p;
result = findRR (name, T_LOC);
if (result != NULL)
{
if (debug >= 2)
printf ("LOC record found for the name %s\n", name);
return result;
}
else
{
if (!is_network)
{
list = findA (name);
if (debug >= 2)
printf ("No LOC record found for the name %s, trying addresses\n", name);
if (list != NULL)
{
for (p = list; p != NULL; p = p->next)
{
if (debug >= 2)
printf ("Trying address %s\n", inet_ntoa (p->addr));
result = getlocbyaddr (p->addr, NULL);
if (result != NULL)
return result;
}
return NULL;
}
else
{
if (debug >= 2)
printf (" No A record found for %s\n", name);
return NULL;
}
}
else
{
if (debug >= 2)
printf ("No LOC record found for the network name %s\n", name);
return NULL;
}
}
}
char *
getlocbyaddr (addr, mask)
const struct in_addr addr;
const struct in_addr *mask;
{
struct in_addr netaddr;
u_int32_t a;
struct in_addr themask;
char *text_addr, *text_mask;
if (mask == NULL)
{
themask.s_addr = (u_int32_t) 0;
}
else
{
themask = *mask;
}
text_addr = (char *) malloc (256);
text_mask = (char *) malloc (256);
strcpy (text_addr, inet_ntoa (addr));
strcpy (text_mask, inet_ntoa (themask));
if (debug >= 2)
printf ("Testing address %s/%s\n", text_addr, text_mask);
if (mask == NULL)
{
a = ntohl (addr.s_addr);
if (IN_CLASSA (a))
{
netaddr.s_addr = htonl (a & IN_CLASSA_NET);
}
else if (IN_CLASSB (a))
{
netaddr.s_addr = htonl (a & IN_CLASSB_NET);
}
else if (IN_CLASSC (a))
{
netaddr.s_addr = htonl (a & IN_CLASSC_NET);
}
else
{
}
return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, mask);
}
else
{
netaddr.s_addr = addr.s_addr & themask.s_addr;
return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, mask);
}
}
char *
getlocbynet (name, addr, mask)
char *name;
struct in_addr addr;
struct in_addr *mask;
{
char *network;
char *result, *result_int;
struct list_in_addr *list;
if (debug >= 2)
printf ("Testing network %s\n", name);
network = findRR (name, T_PTR);
if (network == NULL)
{
if (debug >= 2)
printf ("No name for network %s\n", name);
return NULL;
}
else
{
result = getlocbyname (network, TRUE);
list = findA (network);
if (list == NULL)
{
return result;
}
else if ((mask != NULL) &&
((mask->s_addr) == (list->addr.s_addr)))
{
return result;
}
else
{
result_int = getlocbyaddr (addr, &list->addr);
if (result_int == NULL)
return result;
else
return result_int;
}
}
}
int
skipName (cp, endOfMsg)
u_char *cp;
u_char *endOfMsg;
{
int n;
if ((n = dn_skipname (cp, endOfMsg)) < 0)
{
panic ("dn_skipname failed\n");
}
return (n);
}
int
skipToData (cp, type, class, ttl, dlen, endOfMsg)
u_char *cp;
u_short *type;
u_short *class;
u_int32_t *ttl;
u_short *dlen;
u_char *endOfMsg;
{
u_char *tmp_cp = cp;
tmp_cp += skipName (tmp_cp, endOfMsg);
GETSHORT (*type, tmp_cp);
GETSHORT (*class, tmp_cp);
GETLONG (*ttl, tmp_cp);
GETSHORT (*dlen, tmp_cp);
return (tmp_cp - cp);
}
char *
findRR (domain, requested_type)
char *domain;
int requested_type;
{
char *result, *message;
union
{
HEADER hdr;
u_char buf[PACKETSZ];
}
response;
short found = 0;
int responseLen;
u_char *cp;
u_char *endOfMsg;
u_short class;
u_short type;
u_int32_t ttl;
u_short dlen;
int i, count, dup;
char *ptrList[1];
int ptrNum = 0;
struct in_addr addr;
result = (char *) malloc (256);
message = (char *) malloc (256);
if ((responseLen =
res_query (domain,
C_IN,
requested_type,
(u_char *) & response,
sizeof (response)))
< 0)
{
rr_errno = h_errno;
return NULL;
}
endOfMsg = response.buf + responseLen;
cp = response.buf + sizeof (HEADER);
cp += skipName (cp, endOfMsg) + QFIXEDSZ;
count = ntohs (response.hdr.ancount) +
ntohs (response.hdr.nscount);
while ((--count >= 0)
&& (cp < endOfMsg))
{
cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);
if (type == requested_type)
{
switch (requested_type)
{
case (T_LOC):
loc_ntoa (cp, result);
return result;
break;
case (T_PTR):
ptrList[ptrNum] = (char *) malloc (MAXDNAME);
if (ptrList[ptrNum] == NULL)
{
panic ("Malloc failed");
}
if (dn_expand (response.buf,
endOfMsg,
cp,
(u_char *) ptrList[ptrNum],
MAXDNAME)
< 0)
{
panic ("dn_expand failed");
}
for (i = 0, dup = 0; (i < ptrNum) && !dup; i++)
dup = !strcasecmp (ptrList[i], ptrList[ptrNum]);
if (dup)
free (ptrList[ptrNum]);
else
ptrNum++;
strcpy (result, ptrList[0]);
return result;
break;
case (T_A):
bcopy ((char *) cp, (char *) &addr, INADDRSZ);
strcat (result, " ");
strcat (result, inet_ntoa (addr));
found = 1;
break;
default:
sprintf (message, "Unexpected type %u", requested_type);
panic (message);
}
}
cp += dlen;
}
if (found)
return result;
else
return NULL;
}
struct list_in_addr *
findA (domain)
char *domain;
{
struct list_in_addr *result, *end;
union
{
HEADER hdr;
u_char buf[PACKETSZ];
}
response;
int responseLen;
u_char *cp;
u_char *endOfMsg;
u_short class;
u_short type;
u_int32_t ttl;
u_short dlen;
int count;
struct in_addr addr;
end = NULL;
result = NULL;
if ((responseLen =
res_query (domain,
C_IN,
T_A,
(u_char *) & response,
sizeof (response)))
< 0)
{
rr_errno = h_errno;
return NULL;
}
endOfMsg = response.buf + responseLen;
cp = response.buf + sizeof (HEADER);
cp += skipName (cp, endOfMsg) + QFIXEDSZ;
count = ntohs (response.hdr.ancount) +
ntohs (response.hdr.nscount);
while ((--count >= 0)
&& (cp < endOfMsg))
{
cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);
if (type == T_A)
{
bcopy ((char *) cp, (char *) &addr, INADDRSZ);
if (end == NULL)
{
result = (void *) malloc (sizeof (struct list_in_addr));
result->addr = addr;
result->next = NULL;
end = result;
}
else
{
end->next = (void *) malloc (sizeof (struct list_in_addr));
end = end->next;
end->addr = addr;
end->next = NULL;
}
}
cp += dlen;
}
return result;
}