DNS服务器解析

/*************************************************************************
    > File Name: MyFiles/C和C++程序/socket/getIP.c
    > Author: mr_zys
    > Mail: [email protected]
    > Created Time: Thu 12 Jun 2014 05:22:06 PM CST
    > Operating System: Ubuntu 12.04 LTS
    > Programming Language: Linux c
    > Compiler: gcc
    > Description: this is a program with Linux socket APIs to ask DNS server for domain name's IP adress!
 ************************************************************************/
 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
 
#define MAX_SIZE 1024
#define SERVER_PORT 53
 
void setHead(unsigned char *buf)
{
    buf[0] = 0x00;
    buf[1] = 0;
    buf[2] = 0x01;
    buf[3] = 0;
    buf[4] = 0;
    buf[5] = 1;
    buf[6] = 0;
    buf[7] = 0;
    buf[8] = buf[9] = buf[10] = buf[11] = 0;
}
 
void setQuery(char *name, unsigned char *buf, int len)
{
    strcat(buf+12,name);			//把name接到buff[12]后面 
    int pos = len + 12;				//pos表示buff中字符串的末位 buf[0--11] buf[12---len] buf[pos--pos+3]  
    buf[pos] = 0;
    buf[pos+1] = 1;
    buf[pos+2] = 0;
    buf[pos+3] = 1;
}
int changeDN(char *DN,char *name)
{
    int i = strlen(DN) - 1;		//获取文件名实际长度 
    int j = i + 1;
    int k;
    name[j+1] = 0;
    for(k = 0; i >= 0; i--,j--) {
        if(DN[i] == '.') {				//扫描 . 分隔符 			
            name[j] = k;
            k = 0;
        }
        else {
            name[j] = DN[i];		 //从后向前获取信息
            k++;
        }
    }
    name[0] = k;
    return (strlen(DN) + 2);			//www.cctv.com.cn ---> 3www4cctv3com2cn0 
}
void printName(int len, char *name)
{
    int i;
    for(i = 0; i < len; i++) printf("%x.",name[i]);
    printf("\n");
}
 
 
 //发送DNS包  
int sendDNSPacket(unsigned char *buf, int len, char *recvMsg)
{
    int s;
    struct sockaddr_in sin;
 
    memset(&sin,0,sizeof(sin));
    sin.sin_addr.s_addr = inet_addr("127.0.0.1");			//设置DNS域名 
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SERVER_PORT);
 
    s = socket(PF_INET,SOCK_DGRAM,0);
    sendto(s,buf,len,0,(struct sockaddr *)&sin,sizeof(sin));
    return recv(s,recvMsg,MAX_SIZE,0);
 
}

//打印IP地址 
void resolve(unsigned char *recvMsg, int len, int len_recvMsg)
{
    int pos = len;
    int cnt = 12;
    while(pos < len_recvMsg) {
        unsigned char now_pos = recvMsg[pos+1];
        unsigned char retype = recvMsg[pos+3];
        unsigned char reclass = recvMsg[pos+5];
        unsigned char offset = recvMsg[pos+11];
        if(retype == 1) {
            if(now_pos == cnt && reclass == 1) {
                printf("%u.%u.%u.%u\n",recvMsg[pos+12],recvMsg[pos+13],recvMsg[pos+14],recvMsg[pos+15]);
            }
        }
        else if(retype == 5) {
            cnt = pos + 12 ;
        }
        pos = pos + 12 + offset;
    }
}
int main()
{
    unsigned char buf[MAX_SIZE]; /* socket发送的数据 */
    char DN[MAX_SIZE]; /* 将要解析的域名(www.xxx.xxx) */
    char name[MAX_SIZE]; /* 转换为符合DNS报文格式的域名 */
    char recvMsg[MAX_SIZE]; /* 接收的数据 */
    int len = 0; /* socket发送数据的长度 */
    int s = 0; /* socket handler */
 	  int j = 0;
 	  int i = 0;
 	  int len_recvMsg = 0;
    printf("输入需要解析的域名:");
    scanf("%s",DN);
     
    len = changeDN(DN,name);
    //printName(len,name); /* 打印转换后的域名,检测是否转换正确 */
    
    //printf("len is %d\n",len);
    setHead(buf);						//buf清空 
    setQuery(name,buf,len);
    len += 16;
    len_recvMsg = sendDNSPacket(buf,len,recvMsg);
    printf("接收的报文长度为 %d 字节\n",len_recvMsg);
    printf("下面是接收报文的16进制表示:\n");
    for(i = 0; i < len_recvMsg; i++) {
        printf("%x.",(unsigned char)recvMsg[i]);
    }
    printf("\n");
    printf("%s的IP地址为:\n",DN);
    resolve(recvMsg,len,len_recvMsg);
 
}

猜你喜欢

转载自blog.csdn.net/fuhanga123/article/details/78229224