Commit 125e9766 authored by Ted Lemon's avatar Ted Lemon
Browse files

Use new resolv.conf parser. Clean up some code. Add experimental (and...

Use new resolv.conf parser.   Clean up some code.   Add experimental (and non-functional) zone discovery code.
parent a198e267
......@@ -48,7 +48,7 @@
#ifndef lint
static char copyright[] =
"$Id: dns.c,v 1.2 1997/03/29 01:25:32 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
"$Id: dns.c,v 1.3 1997/05/09 08:02:33 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -60,13 +60,15 @@ int dns_protocol_fd;
static int addlabel PROTO ((u_int8_t *, char *));
static int skipname PROTO ((u_int8_t *));
static int copy_out_name PROTO ((u_int8_t *, u_int8_t *, char *));
static int nslookup PROTO ((u_int8_t, char *, int, u_int16_t, u_int16_t));
static int zonelookup PROTO ((u_int8_t, char *, int, u_int16_t));
u_int16_t dns_port;
/* Initialize the DNS protocol. */
void dns_startup ()
{
struct servent *srv;
u_int16_t dns_port = htons (53);
struct sockaddr_in from;
/* Only initialize icmp once. */
......@@ -75,15 +77,19 @@ void dns_startup ()
dns_protocol_initialized = 1;
/* Get the protocol number (should be 1). */
srv = getsrvbyname ("domain", "tcp");
srv = getservbyname ("domain", "tcp");
if (srv)
port = srv -> s_port;
dns_port = srv -> s_port;
else
dns_port = htons (53);
/* Get a raw socket for the ICMP protocol. */
/* Get a socket for the DNS protocol. */
dns_protocol_fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!dns_protocol_fd)
error ("unable to create dns socket: %m");
pick_name_server ();
add_protocol ("dns", dns_protocol_fd, dns_packet, 0);
}
......@@ -145,8 +151,7 @@ static int copy_out_name (base, name, buf)
called with a null pointer. Otherwise, the callback is called with the
address of the string returned by the name server. */
int ns_inaddr_lookup (server, id, inaddr)
struct sockaddr_in *server;
int ns_inaddr_lookup (id, inaddr)
u_int16_t id;
struct iaddr inaddr;
{
......@@ -159,7 +164,7 @@ int ns_inaddr_lookup (server, id, inaddr)
for (i = 3; i >= 0; --i) {
label = s++;
*label = 1;
c = inaddr -> addr [i];
c = inaddr.iabuf [i];
if (c > 100) {
++*label;
*s++ = '0' + c / 100;
......@@ -173,13 +178,13 @@ int ns_inaddr_lookup (server, id, inaddr)
s += addlabel (s, "in-addr");
s += addlabel (s, "arpa");
*s++ = 0;
return nslookup (server, id, namebuf, s - namebuf, T_PTR, C_IN);
/* return nslookup (id, namebuf, s - namebuf, T_PTR, C_IN); */
return zonelookup (id, namebuf, s - namebuf, C_IN);
}
/* Construct and transmit a name server query. */
int nslookup (server, id, qname, namelen, qtype, qclass)
struct sockaddr_in *server;
static int nslookup (id, qname, namelen, qtype, qclass)
u_int8_t id;
char *qname;
int namelen;
......@@ -188,20 +193,21 @@ int nslookup (server, id, qname, namelen, qtype, qclass)
{
HEADER *hdr;
unsigned char query [512];
unsigned char *s;
u_int8_t *s;
int len;
int i;
int i, status;
struct sockaddr_in *server = pick_name_server ();
/* Construct a header... */
hdr = (HEADER *)query;
memset (&hdr, 0, sizeof hdr);
memset (hdr, 0, sizeof *hdr);
hdr -> id = htons (id);
hdr -> rd = 1;
hdr -> opcode = QUERY;
hdr -> qdcount = htons (1);
/* Copy in the name we're looking up. */
s = (u_int8_t)(hdr + 1);
s = (u_int8_t *)(hdr + 1);
memcpy (s, qname, namelen);
s += namelen;
......@@ -223,9 +229,88 @@ int nslookup (server, id, qname, namelen, qtype, qclass)
return 1;
}
/* Construct a query for the SOA for a specified name.
Try every possible SOA name starting from the name specified and going
to the root name - e.g., for
215.5.5.192.in-addr.arpa, look for SOAs matching:
215.5.5.5.192.in-addr.arpa
5.5.192.in-addr.arpa
5.192.in-addr.arpa
192.in-addr.arpa
in-addr.arpa
arpa */
static int zonelookup (id, qname, namelen, qclass)
u_int8_t id;
char *qname;
int namelen;
u_int16_t qclass;
{
HEADER *hdr;
unsigned char query [512];
u_int8_t *s, *nptr;
int len;
int i, status, count;
struct sockaddr_in *server = pick_name_server ();
/* Construct a header... */
hdr = (HEADER *)query;
memset (hdr, 0, sizeof *hdr);
hdr -> id = htons (id);
hdr -> rd = 1;
hdr -> opcode = QUERY;
/* Copy in the name we're looking up. */
s = (u_int8_t *)(hdr + 1);
memcpy (s, qname, namelen);
s += namelen;
/* Set the query type. */
putUShort (s, T_SOA);
s += sizeof (u_int16_t);
/* Set the query class. */
putUShort (s, qclass);
s += sizeof (u_int16_t);
count = 1;
/* Now query up the hierarchy. */
nptr = (u_int8_t *)(hdr + 1);
while (*(nptr += *nptr + 1)) {
/* Store a compressed reference from the full name. */
putUShort (s, ntohs (htons (0xC000) |
htons (nptr - &query [0])));
s += sizeof (u_int16_t);
/* Store the query type. */
putUShort (s, T_SOA);
s += sizeof (u_int16_t);
putUShort (s, qclass);
s += sizeof (u_int16_t);
/* Increment the query count... */
++count;
break;
}
hdr -> qdcount = htons (count);
dump_raw (query, s - query);
/* Send the query. */
status = sendto (dns_protocol_fd, query, s - query, 0,
(struct sockaddr *)server, sizeof *server);
/* If the send failed, report the failure. */
if (status < 0)
return 0;
return 1;
}
/* Process a reply from a name server. */
dns_packet (protocol)
void dns_packet (protocol)
struct protocol *protocol;
{
HEADER *ns_header;
......@@ -235,14 +320,15 @@ dns_packet (protocol)
unsigned char nbuf [512];
unsigned char *base;
unsigned char *dptr;
int type;
int class;
int ttl;
int rdlength;
char nbuf [MAXDNAME];
u_int16_t type;
u_int16_t class;
TIME ttl;
u_int16_t rdlength;
int len, status;
int i;
len = sizeof from;
status = recvfrom (protocol -> fd, icbuf, sizeof icbuf, 0,
status = recvfrom (protocol -> fd, buf, sizeof buf, 0,
(struct sockaddr *)&from, &len);
if (status < 0) {
warn ("icmp_echoreply: %m");
......@@ -252,46 +338,60 @@ dns_packet (protocol)
ns_header = (HEADER *)buf;
base = (unsigned char *)(ns_header + 1);
#if 0
/* Ignore invalid packets... */
if (ntohs (ns_header -> id) > ns_query_max) {
printf ("Out-of-range NS message; id = %d\n",
ntohs (ns_header -> id));
return;
}
#endif
/* Parse the response... */
dptr = base;
/* Skip over the query name... */
dptr += skipname (dptr);
/* Skip over the query type and the query class. */
dptr += 2 * sizeof (short);
/* Skip over the reply name... */
dptr += skipname (dptr);
/* Extract the numeric fields: */
getUShort (dptr, (u_int8_t *)&type);
dptr += sizeof type;
getULong (dptr, (u_int8_t *)&class);
dptr += sizeof class;
getULong (dptr, (u_int8_t *)&ttl);
dptr += sizeof ttl;
getUShort (dptr, (u_int8_t *)&rdlength);
dptr += sizeof rdlength;
switch (type) {
case T_A:
printf ("A record; value is %d.%d.%d.%d",
dptr [0], dptr [1], dptr [2], dptr [3]);
break;
case T_CNAME:
case T_PTR:
copy_out_name (base, dptr, nbuf);
printf ("Domain name; value is %s\n", nbuf);
return;
/* Skip over the queries... */
for (i = 0; i < ntohs (ns_header -> qdcount); i++) {
dptr += skipname (dptr);
/* Skip over the query type and query class. */
dptr += 2 * sizeof (u_int16_t);
}
default:
printf ("unhandled type: %x\n", type);
/* Process the answers... */
for (i = 0; i < ntohs (ns_header -> ancount); i++) {
/* Skip over the name we looked up. */
dptr += skipname (dptr);
/* Get the type. */
type = getUShort (dptr);
dptr += sizeof type;
/* Get the class. */
class = getUShort (dptr);
dptr += sizeof class;
/* Get the time-to-live. */
ttl = getULong (dptr);
dptr += sizeof ttl;
/* Get the length of the reply. */
rdlength = getUShort (dptr);
dptr += sizeof rdlength;
switch (type) {
case T_A:
note ("A record; value is %d.%d.%d.%d",
dptr [0], dptr [1], dptr [2], dptr [3]);
break;
case T_CNAME:
case T_PTR:
copy_out_name (base, dptr, nbuf);
note ("Domain name; value is %s\n", nbuf);
return;
default:
note ("unhandled type: %x", type);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment