#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
/*
typedef unsigned char __uint8_t;
typedef short __int16_t;
typedef unsigned short __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
typedef long long __int64_t;
typedef unsigned long long __uint64_t;
typedef long __darwin_intptr_t;
typedef unsigned int __darwin_natural_t;
*/
struct DNS{
unsigned short tranID;//16
unsigned short flags;
unsigned short questionsnum;
unsigned short answerNum;
unsigned short authorityNum;
unsigned short additionalNum;
};
int fillInDns(char * newInput,char * input){
char * tmp = input;
char * oldTmp = input;
char * tmp_new = newInput;
int count = 0;
int len=0;
while ((*tmp)!='\0') {
if (*tmp == '.') {
*tmp_new = (unsigned char)count;//int to char
tmp_new+=1;
memcpy(tmp_new, oldTmp, count);
oldTmp = oldTmp+count+1;
tmp_new = tmp_new+count;
len = len + count + 1;
count = 0;
}else{
count+=1;
}
tmp = tmp+1;
}
//因为最后没有'.',所以需要在进行一次赋值:
*tmp_new = (unsigned char)count;//int to char
tmp_new+=1;
memcpy(tmp_new, oldTmp, count);
*(tmp_new+count) = (unsigned char)0;
len = len+count+1;
return len;
}
int sendToLocalDns(int sock,struct sockaddr_in * dnsAddr,char * input,char * in){
char sendBuf[1024];
memset(sendBuf, 0, sizeof(sendBuf));//清零sendBuf
//1.填充DNS报文头部:
struct DNS *dns = (struct DNS*)malloc(sizeof(struct DNS));
char * dnsC = (char *)dns;
dns->tranID = htons(0xff00);
dns->flags = htons(0x0100);
dns->questionsnum = htons(1);
dns->answerNum = htons(0);
dns->authorityNum = htons(0);
dns->additionalNum = htons(0);
//2.填充DNS报文正文:
char input_send[50];
int input_send_len;
int input_send_real_len;
memset(input_send, 0, sizeof(input_send));//清零
input_send_len = fillInDns(input_send,input);//更改域名格式
memcpy(sendBuf, dnsC, 12);//头部copy
memcpy(sendBuf+12, input_send, input_send_len);//正文域名copy
input_send_real_len = ((input_send_len/4)+1)*4;//以4Byte对齐
memcpy(in, input_send, input_send_real_len);//本地保存,接收报文时用
memset(sendBuf+12+input_send_real_len, 1, 1);//尾部赋值 Type
memset(sendBuf+12+input_send_real_len+2, 1, 1);//尾部赋值 Class
//3.发送:
if (sendto(sock, sendBuf, sizeof(sendBuf), 0, (struct sockaddr*)dnsAddr, sizeof(struct sockaddr))==-1) {
printf("send error!\n");
exit(1);
}
free(dns);
return input_send_real_len;
}
void recFromLocalDns(int sock,int input_send_real_len,char * in){
char recBuf[1024];//接收缓冲
memset(recBuf, 0, sizeof(recBuf));//清零recBuf
struct sockaddr_in srcAddr;
socklen_t srcAddrLen = sizeof(struct sockaddr_in);
if (recvfrom(sock, recBuf, sizeof(recBuf), 0, (struct sockaddr*)&srcAddr, &srcAddrLen) == -1) {
printf("rec error!\n");
exit(1);
}
// printf("%p\n",recBuf);
char * type = recBuf+12+input_send_real_len;
type = type+5;
int typeInt = ntohs(*(unsigned short*)type);
int ttl = ntohl(*(unsigned int*)(type+4));
int lenOfIp = ntohs(*(unsigned short*)(type+8));
char * ip = type+10;
char ipChar[50];//用来存放ip地址
char ipPrint[50];
memset(ipChar, 0, sizeof(ipChar));
memset(ipPrint, 0, sizeof(ipPrint));
if ((strncmp(recBuf+12, in, input_send_real_len)==0)&&(typeInt==1)) {
memcpy(ipChar, ip, lenOfIp);
inet_ntop(AF_INET, ipChar, ipPrint, sizeof(ipPrint));
printf("ip is %s,ttl is %d\n",ipPrint,ttl);
}
}
int main(int argc, const char * argv[]) {
//创建套接字:
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("socket error!\n");
exit(1);
}
//创建DNS本地服务器地址:
struct sockaddr_in dnsAddr;
dnsAddr.sin_family = AF_INET;
dnsAddr.sin_port = htons(53);
dnsAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
//输入要查询的域名:
char input[50];
printf("请输入要查询的域名:\n");
scanf("%s",input);
//发送dns请求到dns本地服务器:
int input_send_len;
char in[50];
input_send_len = sendToLocalDns(sock, &dnsAddr,input,in);
//接收dns回应:
recFromLocalDns(sock,input_send_len,in);
return 0;
}