/************************************
编译:
gcc -g -o dns dns.c -lresolv
测试:
./dns gmail.com
结果:
pref domain name
20 alt2.gmail-smtp-in.l.google.com
30 alt3.gmail-smtp-in.l.google.com
40 alt4.gmail-smtp-in.l.google.com
5 gmail-smtp-in.l.google.com
10 alt1.gmail-smtp-in.l.google.com
*************************************/
//-----------------------------------
// dns.h
#ifndef DNS_H
#define DNS_H
#define DNS_MSG_END -2
#define dns_mx_query(str) dns_resolve((str), T_MX)
#define dns_mx_expand() dns_findmx(T_MX)
#define foreach_mxrr(p, dn) while(dns_mx_expand() != DNS_MSG_END \
&& (!dns_get_mxrr(&p, dn, MAXDNAME)))
void dns_init(void);
int dns_get_mxrr(unsigned short *, unsigned char *, unsigned int);
int dns_resolve(char *, int);
int dns_findmx(int);
#endif
//-----------------------------------
//dns.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys types.h="">
#include <netinet in.h="">
#include <arpa nameser.h="">
#include <resolv.h>
#include <errno.h>
#include "dns.h"
extern int res_query();
extern int res_search();
extern int errno;
extern int h_errno;
HEADER *hdr;
unsigned char *buf;
static int response_len;
static unsigned char *response_end;
static unsigned char *response_pos;
static int num_answers;
static char name[MAXDNAME];
unsigned short pref;
static unsigned short getshort(unsigned char *c)
{
unsigned short u;
u = c[0];
return (u << 8) + c[1];
}
int dns_resolve(char *domain, int type)
{
int n;
int i;
errno = 0;
if (domain == NULL)
return -1;
response_len = res_search(domain, C_IN, type, buf, PACKETSZ);
if (response_len <= 0)
return -1;
if (response_len >= PACKETSZ)
response_len = PACKETSZ;
response_end = buf + response_len;
response_pos = buf + sizeof(HEADER);
n = ntohs(hdr->qdcount);
while (n-- > 0) {
i = dn_expand(buf, response_end, response_pos, name, MAXDNAME);
response_pos += i;
i = response_end - response_pos;
if (i < QFIXEDSZ) return -1;
response_pos += QFIXEDSZ;
}
num_answers = ntohs(hdr->ancount);
return num_answers;
}
int dns_findmx(int want_type)
{
unsigned short rrtype;
unsigned short rrdlen;
int i;
if (num_answers <= 0) return DNS_MSG_END;
num_answers--;
if (response_pos == response_end) return -1;
i = dn_expand(buf, response_end, response_pos, name, MAXDNAME);
if (i < 0) return -1;
response_pos += i;
i = response_end - response_pos;
if (i < 10) return -1;
rrtype = getshort(response_pos);
rrdlen = getshort(response_pos + 8);
response_pos += 10;
if (rrtype == want_type) {
if (rrdlen < 3) return -1;
pref = (response_pos[0] << 8) + response_pos[1];
memset(name, 0, MAXDNAME);
if (dn_expand(buf, response_end, response_pos + 2, name, MAXDNAME) < 0)
return -1;
response_pos += rrdlen;
return strlen(name);
}
response_pos += rrdlen;
return 0;
}
void dns_init()
{
res_init();
memset(name, 0, MAXDNAME);
}
int dns_get_mxrr(unsigned short *p, unsigned char *dn, unsigned int len)
{
*p = pref;
strncpy(dn, name, len);
if (len < (strlen(name) + 1))
return -1;
return 0;
}
int main(int argc, char **argv)
{
char dname[MAXDNAME];
int i;
unsigned short p;
buf = (unsigned char *)calloc(1, PACKETSZ);
if (buf == NULL) {
fprintf(stderr, "calloc for response.buf failed");
exit(-1);
}
hdr = (void *)buf;
dns_init();
if (argc != 2) {
fprintf(stderr, "bad argument\n");
exit(-1);
}
i = dns_mx_query(argv[1]);
if (i < 0) {
fprintf(stderr, "err\n");
return 0;
}
printf("pref\tdomain name\n");
foreach_mxrr(p, dname) {
printf("%d\t%s\n", p, dname);
}
if (buf) {
free(buf);
buf = NULL;
}
return 0;
}
网友评论