📄 dns_util.c.svn-base
字号:
/***************************************************************************************
* Copyright c 2000 D-Link Corporation All rights reserved.
*
* This is unpublished proprietary source code of D-Link Corporation
*
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
***************************************************************************************
*/
/* include files declaration */
#include <l3/inc/phase2.h>
#include <l3/ap/dnsr/h/dns.h>
/*
* Reinventing the wheel for more portable programs.
* If you're not using ASCII, you'll have to redefine these.
*/
#ifndef GLUE_ISADIGIT
#define GLUE_ISADIGIT(_c_) \
((_c_) >= '0' && (_c_) <= '9')
#endif /* GLUE_ISADIGIT */
#ifndef GLUE_DIGIT
#define GLUE_DIGIT(_c_) \
((_c_) - '0')
#endif /* GLUE_DIGIT */
#ifndef GLUE_ISUPPER
#define GLUE_ISUPPER(_c_) \
((_c_) >= 'A' && (_c_) <= 'Z')
#endif /* GLUE_ISUPPER */
#ifndef GLUE_LOWER
#define GLUE_LOWER(_c_) \
((_c_) + 'a' - 'A')
#endif /* GLUE_LOWER */
/*
* Notes on address sorting:
*
* (1) Using a preference list it's easier to count from the beginning
* of the list (best is zero, next best -1, etc) rather than
* knowing in advance how many ranks there are. At the same time,
* the randomization stuff is easier to do if we use unsigned
* numbers. So stand the metric number on its head, make larger
* numbers denote worse addresses rather than better addresses.
*
* (2) Within a catagory, address order should be somewhat randomized,
* so that repeated attempts to contact a machine with a down interface
* will have some chance of getting through.
*
*
* Reinventing the wheel for more portable programs.
* If you're not using ASCII, you'll have to redefine these.
*
*
* Default preference list for applications that don't specify one.
*
* If DNS_PREFER_LOCAL_ADDRESSES is defined, we give preference to
* addresses on locally attached subnets.
*/
/*
* Return an unsigned number indicating how good the address is.
* The higher the number, the WORSE the address. The specific values
* are of nobody's business outside this routine, and may be changed
* without notice.
*/
/*
* Returns error code or length of compressed name. If buffer is
* NULL, just skip over name, don't convert it into text format.
*/
int dns_decode_name
(char *buffer,
int buffer_length,
unsigned char *name,
unsigned char *msg,
unsigned msg_len)
{
int i, n, result = 0, still_counting = TRUE;
if (name == 0)
return (int) DNS_ERROR_BAD_ARGS;
do
{
switch ((n = *name) & DNS_COMPRESSION_MASK)
{
case DNS_COMPRESSION_POINTER:
/*
* Flag bits of count byte say this is a compression pointer
* relative to the start of the message. Follow it.
*/
if (msg == 0)
return (int) DNS_ERROR_BAD_NAME;
if (still_counting)
result += 2;
still_counting = 0;
name = msg + ((name[0] & ~DNS_COMPRESSION_MASK) << 8) + name[1];
if (name >= msg + msg_len)
return (int) DNS_ERROR_BAD_NAME;
continue;
case 0:
/*
* Flag bits are zero, this is a normal count byte. Handle conversion
* of counted string to null-terminated string, using backslash to quote
* as necessary.
*/
if (still_counting)
result += n + 1;
if (buffer != 0)
{
for (i = 1; i <= n; ++i)
{
switch (name[i])
{
case '\0':
if ((buffer_length -= 4) < 0)
return (int) DNS_ERROR_NAME_TOO_LONG;
*buffer++ = '\\';
*buffer++ = '0'; *buffer++ = '0'; *buffer++ = '0';
break;
case '\\':
case '.':
if (--buffer_length < 0)
return (int) DNS_ERROR_NAME_TOO_LONG;
*buffer++ = '\\';
/* Fall through */
default:
if (--buffer_length < 0)
return (int) DNS_ERROR_NAME_TOO_LONG;
*buffer++ = name[i];
} /* switch */
} /* for loop */
} /* if (buffer != 0) */
name += n + 1;
if (buffer != 0)
{
if (--buffer_length < 0)
return (int) DNS_ERROR_NAME_TOO_LONG;
*buffer++ = (char) (*name == 0 ? '\0' : '.');
}
continue;
default:
/*
* Flag bits of count byte have unknown value, barf.
*/
return (int) DNS_ERROR_BAD_NAME;
} /* switch ((n = *name) & DNS_COMPRESSION_MASK) */
} while (n != 0 && (buffer != 0 || still_counting));
return result;
}
/*
* Returns error code or length of encoded name. If first argument is
* 0, doesn't encode, just computes encoded length.
*/
int dns_encode_name
(unsigned char *buffer,
unsigned buffer_length,
char *name)
{
unsigned char *b = buffer;
if (name == 0)
return (int) DNS_ERROR_BAD_ARGS;
if (buffer_length > DNS_MAX_DOMAIN_NAME)
buffer_length = DNS_MAX_DOMAIN_NAME;
do
{
int i = 0;
while (*name != '\0' && *name != '.')
{
if ((unsigned)(b - buffer) >= buffer_length)
return (int) DNS_ERROR_NAME_TOO_LONG;
++i;
if (*name == '\\')
{
++name;
if (GLUE_ISADIGIT(name[0]))
{
if (!GLUE_ISADIGIT(name[1]) || !GLUE_ISADIGIT(name[2]))
return (int) DNS_ERROR_BAD_NAME;
if (buffer != 0)
b[i] = (unsigned char)
(GLUE_DIGIT(name[0]) * 100 +
GLUE_DIGIT(name[1]) * 10 +
GLUE_DIGIT(name[2]));
name += 3;
continue;
}
}
if (buffer != 0)
b[i] = *name;
++name;
} /* while */
if (i >= DNS_MAX_DOMAIN_LABEL)
return (int) DNS_ERROR_LABEL_TOO_LONG;
if (buffer != 0)
*b = (unsigned char) i;
b += i + 1;
} while (*name++ != '\0');
if ((unsigned)(b - buffer) >= buffer_length)
return (int) DNS_ERROR_NAME_TOO_LONG;
if (buffer != 0)
*b = 0;
return (int) (b - buffer + 1);
}
/*
* Returns error code.
*/
enum dns_error dns_decode_header
(unsigned char *msg,
unsigned msg_len,
struct dns_header *hdr)
{
UI32_T flags;
if (msg_len < DNS_HDR_LENGTH)
return DNS_ERROR_BAD_ARGS;
flags = dns_decode_bits32(msg + DNS_HDR_FLAGS);
hdr->qdcount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_QDCOUNT);
hdr->ancount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_ANCOUNT);
hdr->nscount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_NSCOUNT);
hdr->arcount = (UI16_T )dns_decode_bits16(msg + DNS_HDR_ARCOUNT);
hdr->id = (UI16_T ) DNS_LDB(flags, DNS_HDR_ID);
hdr->resp = (unsigned) DNS_LDB(flags, DNS_HDR_RESP);
hdr->op = (unsigned) DNS_LDB(flags, DNS_HDR_OP);
hdr->aa = (unsigned) DNS_LDB(flags, DNS_HDR_AA);
hdr->tc = (unsigned) DNS_LDB(flags, DNS_HDR_TC);
hdr->rd = (unsigned) DNS_LDB(flags, DNS_HDR_RD);
hdr->ra = (unsigned) DNS_LDB(flags, DNS_HDR_RA);
hdr->rcode = (unsigned) DNS_LDB(flags, DNS_HDR_RCODE);
#if 0
DBG_L3_Printf("dns_decode_header qdcount = %d\n",hdr->qdcount);
DBG_L3_Printf("dns_decode_header ancount = %d\n",hdr->ancount);
DBG_L3_Printf("dns_decode_header nscount = %d\n",hdr->nscount);
DBG_L3_Printf("dns_decode_header arcount = %d\n",hdr->arcount);
DBG_L3_Printf("dns_decode_header id = %d\n",hdr->id);
DBG_L3_Printf("dns_decode_header resp = %d\n",hdr->resp);
DBG_L3_Printf("dns_decode_header op = %d\n",hdr->op);
DBG_L3_Printf("dns_decode_header aa = %d\n",hdr->aa);
DBG_L3_Printf("dns_decode_header tc = %d\n",hdr->tc);
DBG_L3_Printf("dns_decode_header rd = %d\n",hdr->rd);
DBG_L3_Printf("dns_decode_header ra = %d\n",hdr->ra);
DBG_L3_Printf("dns_decode_header rcode = %d\n",hdr->rcode);
#endif
return DNS_ERROR_OK;
}
/*
* Check a DNS response message for legality.
*
* Checks message headers.
*
* Checks CNAMEs in Answer section to make sure they form a valid path
* from the QNAME to the name(s) of any other RRs in the Answer section.
*
* I can't think of any way that the non-CNAME RRs in the Answer
* could legitimately have different names from each other, but
* I'm not going to put such a check into this code until I have
* time to double check this in the RFCs.
*
* Returns status code.
*/
enum dns_error dns_bless_message
(unsigned char *msg, /* Network message ("packet") */
unsigned msg_len, /* Length of message */
struct dns_header *hdr, /* DNS header */
struct dns_rr rrs[], /* RRs from message */
unsigned n_rrs) /* Length of rrs[] */
{
int i, n, matched;
enum dns_error err;
unsigned char *cqname;
if (msg == 0 || msg_len <= 0 || hdr == 0 || rrs == 0)
return DNS_ERROR_BAD_ARGS;
/*
* Check values in the received header.
*
* The message must be a response.
* The only opcode we support is QUERY.
* The server must claim to support recursion.
* The server may not claim to be authoritative for all classes.
*/
if (!hdr->resp || hdr->op != DNS_OPCODE_QUERY || !hdr->rd ||
(hdr->aa && rrs[0].class == DNS_C_ANY))
return DNS_ERROR_BAD_PROTOCOL;
if (hdr->tc)
return DNS_ERROR_TRUNCATED;
if (!hdr->ra)
return DNS_ERROR_NO_RECURSION;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -