Commit 9557deb6 authored by Ted Lemon's avatar Ted Lemon
Browse files

Adjust indentation; fix up calling conventions

parent 3951e13c
/* dns.c
Domain Name Service subroutine. */
Domain Name Service subroutines. */
/*
* Copyright (C) 1992 by Ted Lemon.
......@@ -39,51 +39,52 @@
* substantially modified for use in the Internet Software Consortium
* DHCP suite.
*
* These later modifications were done on behalf of the Internet Software Consortium
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
* Enterprises. To learn more about the Internet Software Consortium,
* see ``http://www.vix.com/isc''. To learn more about Vixie
* Enterprises, see ``http://www.vix.com''.
* These later modifications were done on behalf of the Internet
* Software Consortium by Ted Lemon <mellon@fugue.com> in cooperation
* with Vixie Enterprises. To learn more about the Internet Software
* Consortium, see ``http://www.vix.com/isc''. To learn more about
* Vixie Enterprises, see ``http://www.vix.com''.
*/
#ifndef lint
static char copyright[] =
"$Id: dns.c,v 1.1 1997/03/08 02:24:16 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
"$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";
#endif /* not lint */
#include "dhcpd.h"
#include "arpa/nameser.h"
int dns_protocol_initialized;
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 *));
/* Initialize the DNS protocol. */
void dns_startup (handler)
void (*handler) PROTO ((struct iaddr, u_int8_t *, int));
void dns_startup ()
{
struct protoent *proto;
int protocol = 1;
struct servent *srv;
u_int16_t dns_port = htons (53);
struct sockaddr_in from;
int fd;
/* Only initialize icmp once. */
if (icmp_protocol_initialized)
error ("attempted to reinitialize icmp protocol");
icmp_protocol_initialized = 1;
if (dns_protocol_initialized)
error ("attempted to reinitialize dns protocol");
dns_protocol_initialized = 1;
/* Get the protocol number (should be 1). */
proto = getprotobyname ("icmp");
if (proto)
protocol = proto -> p_proto;
srv = getsrvbyname ("domain", "tcp");
if (srv)
port = srv -> s_port;
/* Get a raw socket for the ICMP protocol. */
icmp_protocol_fd = socket (AF_INET, SOCK_RAW, protocol);
if (!icmp_protocol_fd)
error ("unable to create icmp socket: %m");
if (setsockopt (icmp_protocol_fd, SOL_SOCKET, SO_DONTROUTE,
(char *)&routep, sizeof routep))
error ("Can't set SO_DONTROUTE on ICMP socket: %m");
dns_protocol_fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!dns_protocol_fd)
error ("unable to create dns socket: %m");
add_protocol ("icmp", icmp_protocol_fd, icmp_echoreply, handler);
add_protocol ("dns", dns_protocol_fd, dns_packet, 0);
}
/* Label manipulation stuff; see RFC1035, page 28 section 4.1.2 and
......@@ -93,50 +94,49 @@ void dns_startup (handler)
the label in the first character, the contents of the label in subsequent
characters, and returning the length of the conglomeration. */
addlabel (buf, label)
unsigned char *buf;
unsigned char *label;
static int addlabel (buf, label)
u_int8_t *buf;
char *label;
{
*buf = strlen (label);
strcpy (buf + 1, label);
return *buf + 1;
*buf = strlen (label);
memcpy (buf + 1, label, *buf);
return *buf + 1;
}
/* skipname skips over all of the labels in a single domain name,
returning the length of the domain name. */
skipname (label)
unsigned char *label;
static int skipname (label)
u_int8_t *label;
{
if (*label & INDIR_MASK)
return 2;
if (*label == 0)
return 1;
return *label + 1 + skipname (label + *label + 1);
if (*label & INDIR_MASK)
return 2;
if (*label == 0)
return 1;
return *label + 1 + skipname (label + *label + 1);
}
/* copy_out_name copies out the name appearing at the specified location
into a string, stored as fields seperated by dots rather than lengths
and labels. The length of the label-formatted name is returned. */
copy_out_name (base, name, buf)
unsigned char *base;
unsigned char *name;
unsigned char *buf;
static int copy_out_name (base, name, buf)
u_int8_t *base;
u_int8_t *name;
char *buf;
{
if (*name & INDIR_MASK)
{
int offset = (*name & ~INDIR_MASK) + (*name + 1);
return copy_out_name (base, base + offset, buf);
}
if (!*name)
{
*buf = 0;
return 1;
}
memcpy (buf, name + 1, *name);
*(buf + *name) = '.';
return *name + 1 + copy_out_name (base, name + *name + 1, buf + *name + 1);
if (*name & INDIR_MASK) {
int offset = (*name & ~INDIR_MASK) + (*name + 1);
return copy_out_name (base, base + offset, buf);
}
if (!*name) {
*buf = 0;
return 1;
}
memcpy (buf, name + 1, *name);
*(buf + *name) = '.';
return (*name + 1
+ copy_out_name (base, name + *name + 1, buf + *name + 1));
}
/* ns_inaddr_lookup constructs a PTR lookup query for an internet address -
......@@ -145,188 +145,153 @@ 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. */
ns_inaddr_lookup (inaddr, timeout, callback)
Address *inaddr;
int timeout;
void (*callback) (char *);
int ns_inaddr_lookup (server, id, inaddr)
struct sockaddr_in *server;
u_int16_t id;
struct iaddr inaddr;
{
unsigned char namebuf [MAXDNAME];
unsigned char *s = namebuf;
unsigned char *label;
int i;
unsigned char c;
for (i = 3; i >= 0; --i)
{
label = s++;
*label = 1;
c = inaddr -> addr [i];
if (c > 100)
{
++*label;
*s++ = '0' + c / 100;
unsigned char namebuf [512];
unsigned char *s = namebuf;
unsigned char *label;
int i;
unsigned char c;
for (i = 3; i >= 0; --i) {
label = s++;
*label = 1;
c = inaddr -> addr [i];
if (c > 100) {
++*label;
*s++ = '0' + c / 100;
}
if (c > 10) {
++*label;
*s++ = '0' + ((c / 10) % 10);
}
*s++ = '0' + (c % 10);
}
if (c > 10)
{
++*label;
*s++ = '0' + ((c / 10) % 10);
}
*s++ = '0' + (c % 10);
}
s += addlabel (s, "in-addr");
s += addlabel (s, "arpa");
*s = 0;
nslookup (namebuf, T_PTR, C_IN, timeout, callback);
s += addlabel (s, "in-addr");
s += addlabel (s, "arpa");
*s++ = 0;
return nslookup (server, id, namebuf, s - namebuf, T_PTR, C_IN);
}
nslookup (qname, qtype, qclass, timeout, callback)
char *qname;
int qtype;
int qclass;
int timeout;
void (*callback) (char *);
{
HEADER hdr;
unsigned char buf [MTUSIZE];
unsigned char query [PACKETSZ];
unsigned char *s;
int len;
void ns_timeout ();
int i;
/* Construct a query ID... */
do
ns_query_id = random ();
while (ns_query_id < 2048);
memset (&hdr, 0, sizeof hdr);
hdr.id = ns_query_id;
hdr.rd = 1;
hdr.opcode = QUERY;
hdr.qdcount = 1;
nsswap (&hdr);
memcpy (query, &hdr, sizeof hdr);
len = sizeof hdr;
strcpy (&query [len], qname);
len += strlen (qname) + 1;
s = &query [len];
PUTSHORT (qtype, s);
len += sizeof (short);
PUTSHORT (qclass, s);
len += sizeof (short);
/* Tack on an extra zero for the checksummer... */
*s++ = 0;
/* Create the packet header... */
len = build_udp_packet (buf, sizeof buf, query, len,
ns_query_id, NAMESERVER_PORT,
&myiaddr, &nsiaddr);
/* Save the callback vector... */
ns_callback = callback;
/* Push a packet out, retrying in an exponential decay starting
with one second, and time out when the user specifies... */
pushpacket (buf, len, (void (*) (char *, int))0, ns_timeout, timeout, 1);
}
/* Construct and transmit a name server query. */
void ns_timeout ()
int nslookup (server, id, qname, namelen, qtype, qclass)
struct sockaddr_in *server;
u_int8_t id;
char *qname;
int namelen;
u_int16_t qtype;
u_int16_t qclass;
{
void (*callback) (char *) = ns_callback;
ns_callback = (void (*) (char *))0;
ns_query_id = 0;
(*callback) ((char *)0);
HEADER *hdr;
unsigned char query [512];
unsigned char *s;
int len;
int i;
/* Construct a header... */
hdr = (HEADER *)query;
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);
memcpy (s, qname, namelen);
s += namelen;
/* Set the query type. */
putUShort (s, qtype);
s += sizeof (u_int16_t);
/* Set the query class. */
putUShort (s, qclass);
s += sizeof (u_int16_t);
/* 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;
}
ns_packet (ns_header, udp, ip, machine_header)
HEADER *ns_header;
struct udphdr *udp;
struct ip *ip;
unsigned char *machine_header;
/* Process a reply from a name server. */
dns_packet (protocol)
struct protocol *protocol;
{
unsigned char *base = (unsigned char *)(ns_header + 1);
unsigned char *dptr;
void (*callback) (char *) = ns_callback;
int type;
int class;
int ttl;
int rdlength;
char nbuf [MAXDNAME];
HEADER *ns_header;
struct sockaddr_in from;
int fl;
unsigned char buf [4096];
unsigned char nbuf [512];
unsigned char *base;
unsigned char *dptr;
int type;
int class;
int ttl;
int rdlength;
char nbuf [MAXDNAME];
len = sizeof from;
status = recvfrom (protocol -> fd, icbuf, sizeof icbuf, 0,
(struct sockaddr *)&from, &len);
if (status < 0) {
warn ("icmp_echoreply: %m");
return;
}
nsswap (ns_header);
ns_header = (HEADER *)buf;
base = (unsigned char *)(ns_header + 1);
/* Ignore invalid packets... */
if (ns_header -> id != ns_query_id)
{
printf ("Unexpected NS message; id = %d\n", ns_header -> id);
return;
}
/* We have our response, so shut down the protocol... */
ns_callback = (void (*) (char *))0;
ns_query_id = 0;
stop_pushing ();
if (ntohs (ns_header -> id) > ns_query_max) {
printf ("Out-of-range NS message; id = %d\n",
ntohs (ns_header -> id));
return;
}
/* Parse the response... */
dptr = base;
dptr = base;
/* Skip over the query name... */
dptr += skipname (dptr);
dptr += skipname (dptr);
/* Skip over the query type and the query class. */
dptr += 2 * sizeof (short);
dptr += 2 * sizeof (short);
/* Skip over the reply name... */
dptr += skipname (dptr);
dptr += skipname (dptr);
/* Extract the numeric fields: */
GETSHORT (type, dptr);
GETSHORT (class, dptr);
GETLONG (ttl, dptr);
GETSHORT (rdlength, dptr);
switch (type)
{
case T_A:
printf ("A record; value is ");
printiaddr (dptr);
if (callback)
(*callback) (dptr);
break;
case T_CNAME:
case T_PTR:
copy_out_name (base, dptr, nbuf);
printf ("Domain name; value is %s\n", nbuf);
if (callback)
(*callback) (nbuf);
return;
#ifdef T_TXT
case T_TXT:
printf ("Text string; value is %s\n", dptr);
if (callback)
(*callback) (dptr);
break;
#endif /* T_TXT */
default:
printf ("unhandled type: %x\n", type);
}
if (callback)
(*callback) ((char *)1);
}
#if BYTE_ORDER == LITTLE_ENDIAN
nsswap (hdr)
HEADER *hdr;
{
shortswap (hdr -> opcode);
shortswap (hdr -> qdcount);
shortswap (hdr -> ancount);
shortswap (hdr -> nscount);
shortswap (hdr -> arcount);
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;
default:
printf ("unhandled type: %x\n", type);
}
}
#endif
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