首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

用C语言兑现已知hostname返回DNS header和IP地址

2013-07-09 
用C语言实现已知hostname返回DNS header和IP地址// standard includes#include stdio.h#include string

用C语言实现已知hostname返回DNS header和IP地址


// standard includes
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>

// networking includes
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

#define STUDENT_SPECIFY 0
#define DNS_IP "8.8.8.8"

char* resolve_name(char* hostname);
void retrieve_data(char* inetaddr, char* hostname, char* requestpath);
void convert_host_format(unsigned char* dns, unsigned char* host);
void hexdump(char* data, int sz);

int main(int argc, char** argv) {
if (argc != 2) err(1, "Example: %s www.ietf.org/rfc/rfc1149.txt", argv[0]);

char path[80];
strcpy(path, strchr(argv[1], '/'));

char host[80];
strcpy(host, strtok(argv[1], "/"));

char* host_ip = resolve_name(host);
retrieve_data(host_ip, host, path);

printf("\n\n");
return 0;
}


void convert_host_format(unsigned char* dns, unsigned char* host) {
int lock = 0, i;

strcat((char*) host, ".");

for (i = 0; i < (int) strlen((char*) host); i++) {
if (host[i] == '.') {
*dns++ = i - lock;
for (; lock < i; lock++) {
*dns++ = host[lock];
}
lock++; //or lock=i+1;
}
}
*dns++ = '\0';
}



void hexdump(char* data, int sz) {
int i;
for (i = 0; i < sz; i++) {
printf("%02hhx", *(data + i));
if ((i+1) % 16 == 0) {
printf("\n");
} else if (i != (sz - 1)) {
printf(":");
}
}
}


#define STRING ""
#define VALUE 0
char* resolve_name(char* hostname) {
int socketid;
struct sockaddr_in socket_info;
char* return_ip = malloc(sizeof(char) * 18);

if ((socketid = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) err(1, "socket(2) failed");

// configure the socket_info
memset((char *) &socket_info, 0, sizeof(socket_info));
socket_info.sin_family = AF_INET;
socket_info.sin_port = htons(53);
if (inet_aton(DNS_IP, &socket_info.sin_addr) == 0) err(1, "inet_aton(3) failed");

char buffer[2046]; // input and output buffer

// header
uint16_t header[6] = { // [NB:1]
VALUE, // 2 byte ID: this is arbitrary
VALUE, // flags 
VALUE, // number of questions
VALUE, // number of answers
VALUE, // number of nameservers
VALUE // number of additional records
};

char converted_name[80]; 
convert_host_format(converted_name, hostname);



// construct the buffer
memcpy(buffer, header, sizeof(header)); // copy the header into the
memcpy(buffer + sizeof(header), converted_name, strlen(converted_name)); // copy the string after the header (including the null)
*(buffer + sizeof(header) + strlen(converted_name) + 1) = 0x00; // append the query type after the string (CNAME)
*(buffer + sizeof(header) + strlen(converted_name) + 2) = 0x01;
*(buffer + sizeof(header) + strlen(converted_name) + 3) = 0x00; // append the address type after the query type (AN)
*(buffer + sizeof(header) + strlen(converted_name) + 4) = 0x01;

int buffer_size = sizeof(header) + strlen(converted_name) + 5;

// send the packet
sendto(socketid, (char*) buffer, buffer_size, 0, (struct sockaddr*) &socket_info, sizeof(socket_info));
// get the response
recvfrom(socketid, (char*) buffer, 2046, 0, (struct sockaddr*) &socket_info, sizeof(socket_info));


sprintf(return_ip,"%hhu.%hhu.%hhu.%hhu", buffer[VALUE], buffer[VALUE], buffer[VALUE], buffer[VALUE]);

close(socketid);
return return_ip;
}

#define HTTP_BUF_LEN 2096
void retrieve_data(char* inetaddr, char* hostname, char* requestpath) {
int socketid;
struct sockaddr_in socket_info;
char buffer[HTTP_BUF_LEN];

if ((socketid = socket(AF_INET, SOCK_STREAM, 0)) < 0) err(1, "socket(2) failed");

memset((char *) &socket_info, 0, sizeof(socket_info));
socket_info.sin_family = AF_INET;
socket_info.sin_port = htons(80);
if (inet_aton(inetaddr, &socket_info.sin_addr.s_addr) == 0) err(1, "inet_aton(3) failed");

if (connect(socketid, (struct sockaddr*) &socket_info, sizeof(socket_info)) != 0) err(1, "connect(2) failed");

const char* request_format_string = "GET %s %s HTTP: \r\n";
sprintf(buffer, request_format_string, requestpath, hostname);
send(socketid, buffer, strlen(buffer), 0);

int bytes_read;
int strip_header = 1;
while ((bytes_read = recv(socketid, buffer, sizeof(buffer), 0)) > 0) {
if (strip_header) {
char* end_of_header = strstr(buffer, "\r\n\r\n");
printf("%s", end_of_header);
strip_header = 0;
} else {
printf("%s", buffer);
}
}

close(socketid);
}


把resolve_name的header里面的VALUE换成DNS的header,然后return_ip里面buffer的几个VALUE是返回的一个IP,能够指点一下该填什么吗?对网络不怎么熟悉。。。
------解决方案--------------------


同步接口是有现成的:
NAME
       res_init,   res_query,   res_search,  res_querydomain,  res_mkquery,  res_send,
       dn_comp, dn_expand - resolver routines

SYNOPSIS
       #include <netinet/in.h>
       #include <arpa/nameser.h>
       #include <resolv.h>
       extern struct state _res;

       int res_init(void);

       int res_query(const char *dname, int class, int type,
              unsigned char *answer, int anslen);

       int res_search(const char *dname, int class, int type,
              unsigned char *answer, int anslen);

       int res_querydomain(const char *name, const char *domain,
              int class, int type, unsigned char *answer,
              int anslen);

不过要做异步的还是要自己实现协议解析。

热点排行