?? dnsmx.cpp
字號:
/*
* The code I found by Bob Quinn was not complete - I hacked it to
* completion just to see what the issues were with getting MX entries.
*
* Part of the hacking involved extracting code from Unix BIND which
* does the low level packet parsing. (The dn_ routines)
*
* It needs to determine the DNS server's IP address - right now it is
* hard coded into this program. NSLOOKUP probably looks in the
* registry for that value.
*
* - David
*/
/*---------------------------------------------------------------------
*
* Program: DNS_QRY.EXE Query DNS Server, and parse response
*
* filename: DNS_QRY.c
*
* Copyright by Bob Quinn, 1997 http://www.sockets.com
*
* Description:
* Not a test application, per se, but designed to allow custom
* queries of DNS records by actually sending and receiving DNS
* messages, rather than relying on the hostname resolution APIs
* to do it for me. The big advantage is that I can ask for any
* DNS record types that I want. The downside is that I have to
* hard-code the DNS server myself, or peak at the implementation's
* configuration (e.g. MSTCP) for the config'd server(s).
*
* I started creating this in response to a Frequently Asked Question
* on one of the WinSock mailing lists for a way to use WinSock to
* retrieve an MX record.
*
* NOTE: Eventually, I'd like to provide the same command-line
* capabilities as available from BSD Unix NSLOOKUP utility.
*
* Editing History:
* 8/17/97 rcq started work -- STOPPED BEFORE GOT IT WORKING
* (serious byte order problems and buffer/format
* management problems in general, causing Format Err).
* 2/15/98 mjd got query and reply working, working on decoding reply
*
*
*
---------------------------------------------------------------------*/
#include "stdafx.h"
#include "tools.h"
#include <stdio.h>
#define ASCII_NULL '\0'
#define MAXHOSTNAME 256
#define BUFSIZE 2048
//#define BUFSIZE 4096
/* DNS Header Format
*
* All DNS Message Formats have basically the same structure
* (note that an RR (DNS Resource Record) is described in
* the other structures that follow this header description):
*
* +--------------------------------+
* | DNS Header: <defined below> |
* +--------------------------------+
* | Question: type of query |
* | QNAME: <see below> |
* | QTYPE: 2-octet RR type |
* | QCLASS: 2-octet RR class |
* +--------------------------------+
* | Answer: RR answer to query |
* +--------------------------------+
* | Authority: RR for name server |
* +--------------------------------+
* | Additional: RR(s) other info |
* +--------------------------------+
*
* QNAME is a variable length field where each portion of the
* "dotted-notation" domain name is replaced by the number of
* octets to follow. So, for example, the domain name
* "www.sockets.com" is represented by:
*
* 0 1
* octet 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |3|w|w|w|7|s|o|c|k|e|t|s|3|c|o|m|0|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* NOTE: The last section, "Additional," often contains records
* for queries the server anticipates will be sent (to reduce
* traffic). For example, a response to an MX query, would
* usually have the A record in additional information.
*/
typedef struct dns_hdr
{
u_short dns_id; /* client query ID number */
u_short dns_flags; /* qualify contents <see below> */
u_short dns_q_count; /* number of questions */
u_short dns_rr_count; /* number of answer RRs */
u_short dns_auth_count; /* number of authority RRs */
u_short dns_add_count; /* number of additional RRs */
} DNS_HDR, *PDNS_HDR, FAR *LPDNS_HDR;
#define DNS_HDR_LEN 12
/* DNS Flags field values
*
* bits: 0 1-4 5 6 7 8 9-11 12-15
* +----+--------+----+----+----+----+--------+-------+
* | QR | opcode | AA | TC | RD | RA | <zero> | rcode |
* +----+--------+----+----+----+----+--------+-------+
*
* QR: 0 for query, and 1 for response
* opcode: type of query (0: standard, and 1: inverse query)
* AA: set if answer from domain authority
* TC: set if message had to be truncated
* RD: set if recursive query desired
* RA: set if recursion is available from server
* <zero>: reserved field
* rcode: resulting error non-zero value from authoritative
* server (0: no error, 3: name does not exist)
*/
#define DNS_FLAG_QR 0x8000
#define DNS_FLAG_AA 0x0400
#define DNS_FLAG_TC 0x0200
#define DNS_FLAG_RD 0x0100
#define DNS_FLAG_RA 0x0080
#define DNS_RCODE_MASK 0x000F
#define DNS_OPCODE_MASK 0x7800
/* DNS Opcode (type of query) */
char *DNS_Opcode[] =
{
"Standard Query", /* 0: QUERY */
"Inverse Query", /* 1: IQUERY */
"Server Status Request", /* 2: STATUS */
};
/* DNS Response Codes (error descriptions) */
char *DNS_RCode[] =
{
"No Error", /* 0: ok */
"Format Error", /* 1: bad query */
"Server Failure", /* 2: server is hosed */
"Name Error", /* 3: name doesn't exist (authoritative) */
"Not Implemented", /* 4: server doesn't support query */
"Refused" /* 5: server refused request */
};
/* DNS Generic Resource Record format (from RFC 1034 and 1035)
*
* NOTE: The first field in the DNS RR Record header is always
* the domain name in QNAME format (see earlier description)
*/
typedef struct dns_rr_hdr
{
u_short rr_type; /* RR type code (e.g. A, MX, NS, etc.) */
u_short rr_class; /* RR class code (IN for Internet) */
u_long rr_ttl; /* Time-to-live for resource */
u_short rr_rdlength; /* length of RDATA field (in octets) */
u_short rr_rdata; /* (fieldname used as a ptr) */
} DNS_RR_HDR, *PDNS_RR_HDR, FAR *LPDNS_RR_HDR;
#define DNS_RR_HDR_LEN 12
/* DNS Resource Record RDATA Field Descriptions
*
* The RDATA field contains resource record data associated
* with the specified domain name
*
* Type Value Description
* -------------------------------------------------------------
* A 1 IP Address (32-bit IP version 4)
* NS 2 Name server QNAME (for referrals & recursive queries)
* CNAME 5 Canonical name of an alias (in QNAME format)
* SOA 6 Start of Zone Transfer (see definition below)
* WKS 11 Well-known services (see definition below)
* PTR 12 QNAME pointing to other nodes (e.g. in inverse lookups)
* HINFO 13 Host Information (CPU string, then OS string)
* MX 15 Mail server preference and QNAME (see below)
*/
char *DNS_RR_Type [] =
{
"<invalid>",
"A", // 1: Host Address
"NS", // 2: Authoritative Name Server
"MD", // 3: <obsolete>
"MF", // 4: <obsolete>
"CNAME", // 5: The true, canonical name for an alias
"SOA", // 6: Start-of-Zone of authority record
"MB", // 7: Mailbox <experimental>
"MG", // 8: Mailgroup <experimental>
"MR", // 9: Mail Rename Domain Name <experimental>
"NULL", // 10: NULL Resource Record <experimental>
"WKS", // 11: Well-known service description
"PTR", // 12: Domain Name Pointer
"HINFO", // 13: Host Information
"MINFO", // 14: Mailbox or Mail List information
"MX", // 15: Mail Exchange (from RFC 974)
"TXT" // 16: Text String
};
#define DNS_RRTYPE_A 1
#define DNS_RRTYPE_NS 2
#define DNS_RRTYPE_CNAME 5
#define DNS_RRTYPE_SOA 6
#define DNS_RRTYPE_WKS 11
#define DNS_RRTYPE_PTR 12
#define DNS_RRTYPE_HINFO 13
#define DNS_RRTYPE_MX 15
/* DNS Resource Record Classes:
*
* One almost always uses Internet RR Class (also note: the
* class value 255 denotes a wildcard, all classes)
*/
char *DNS_RR_Class [] =
{
"<invalid>",
"IN", // 1: Internet - used for most queries!
"CS", // 2: CSNET <obsolete>
"CH", // 3: CHAOS Net
"HS" // 4: Hesiod
};
#define DNS_RRCLASS_IN 1
#define DNS_RRCLASS_CS 2
#define DNS_RRCLASS_CH 3
#define DNS_RRCLASS_HS 4
/* DNS SOA Resource Data Field
*
* NOTE: First two fields not shown here. They are:
* MNAME: QNAME of primary server for this zone
* RNAME: QNAME of mailbox of admin for this zone
*/
typedef struct dns_rdata_soa
{
u_long soa_serial; /* data version for this zone */
u_long soa_refresh; /* time-to-live for data (in seconds) */
u_long soa_retry; /* time between retrieds (in seconds) */
u_long soa_expire; /* time until zone not auth (in seconds) */
u_long soa_minimum; /* default TTL for RRs (in seconds) */
} DNS_RDATA_SOA, PDNS_RDATA_SOA, FAR *LPDNS_RDATA_SOA;
#define DNS_SOA_LEN 20
/* DNS WKS Resource Data Field (RFC 1035)
*
* NOTE: The bitmap field is variable length, with as many
* octets necessary to indicate the bit field for the port
* number.
*/
typedef struct dns_rdata_wks
{
u_long wks_addr; /* IPv4 address */
u_char wks_protocol; /* Protocol (e.g. 6=TCP, 17=UDP) */
u_char wks_bitmap; /* e.g. bit 26 = SMTP (port 25) */
} DNS_RDATA_WKS, *PDNS_RDATA_WKS, FAR *LPDNS_RDATA_WKS;
#define DNS_WKX_LEN 6
/* DNS MX Resource Data Field
*/
typedef struct dns_rdata_mx
{
u_short mx_pref; /* Preference value */
u_short mx_xchange; /* QNAME (field used as ptr) */
} DNS_RDATA_MX, *PDNS_RDATA_MX, FAR *LPDNS_RDATA_MX;
#define DNS_MX_LEN 4
/* Variables used for DNS Header construction & parsing */
PDNS_HDR pDNShdr;
PDNS_RR_HDR pDNS_RR;
PDNS_RDATA_SOA pDNS_SOA;
PDNS_RDATA_WKS pDNS_WKS;
PDNS_RDATA_MX pDNS_MX;
/* For Parsing Names in a Reply */
#define INDIR_MASK 0xc0
/* Number of bytes of fixed size data in query structure */
#define QFIXEDSZ 4
/* number of bytes of fixed size data in resource record */
#define RRFIXEDSZ 10
/* Processor Types */
char *aszProcessor[] =
{
"",
"",
"",
"Intel 386",
"Intel 486",
"Intel Pentium"
};
void GetQName( char FAR *pszHostName, char FAR *pQName );
void PrintQName( char FAR *pQName );
int PutQName( char FAR *pszHostName, char FAR *pQName );
u_short
_getshort(char *msgp)
{
register u_char *p = (u_char *) msgp;
register u_short u;
u = *p++ << 8;
return ((u_short)(u | *p));
}
u_long
_getlong(char *msgp)
{
register u_char *p = (u_char *) msgp;
register u_long u;
u = *p++; u <<= 8;
u |= *p++; u <<= 8;
u |= *p++; u <<= 8;
return (u | *p);
}
/*
* Expand compressed domain name 'comp_dn' to full domain name.
* 'msg' is a pointer to the begining of the message,
* 'eomorig' points to the first location after the message,
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
* Return size of compressed name or -1 if there was an error.
*/
int dn_expand(char *msg,char *eomorig,char *comp_dn,char *exp_dn,int length)
{
register char *cp, *dn;
register int n, c;
char *eom;
int len = -1, checked = 0;
dn = exp_dn;
cp = comp_dn;
eom = exp_dn + length - 1;
/*
* fetch next label in domain name
*/
while (n = *cp++) {
/*
* Check for indirection
*/
switch (n & INDIR_MASK) {
case 0:
if (dn != exp_dn) {
if (dn >= eom)
return (-1);
*dn++ = '.';
}
if (dn+n >= eom)
return (-1);
checked += n + 1;
while (--n >= 0) {
if ((c = *cp++) == '.') {
if (dn+n+1 >= eom)
return (-1);
*dn++ = '\\';
}
*dn++ = c;
if (cp >= eomorig) /* out of range */
return(-1);
}
break;
case INDIR_MASK:
if (len < 0)
len = cp - comp_dn + 1;
cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
if (cp < msg || cp >= eomorig) /* out of range */
return(-1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -