logo资料库

DNS域名解析代碼.pdf

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
SYSTEMTIME tnow; GetLocalTime(&tnow); cout << setfill ('0') << setw(4) << tnow.wYear << "-" #include #include #include #include "winsock.h" #include "windows.h" #pragma comment(lib, "wsock32") using namespace std; #define BUFF_LEN 1024 void disTime() { } /*** 定义结构存储 dns 解析条目以优化查询过程 ***/ typedef struct filenode{ // 每一个节点存储一条域名解析信息 int IP[4]; // IPv4 的四个数据段 } Filenode; // 填充返回客户端的 buffer void fillInBuf(char *buf, int bufLen, const Filenode *localadd, int pos) { char dmName[100]; // 网址 int frequency; // 访问频率 << setw(2) << tnow.wMonth << "-" << setw(2) << tnow.wDay << " " << setw(2) << tnow.wHour << ":" << setw(2) << tnow.wMinute << ":" << setw(2) << tnow.wSecond << endl; buf[4] = 0x00, buf[5] = 0x01; // 首部 Questions count 字段填充为 0x0001 buf[6] = 0x00, buf[7] = 0x01; // 首部 Answer RRS 字段填充为 0001 buf[8] = 0x00, buf[9] = 0x00; // 首部 Authority RRS 字段填充为 0000 buf[10] = 0x00, buf[11] = 0x00; // 首部 Additional RRS 字段填充为 0000 // buffLen 是查询报的长度,在其后填充 Answer // 这两个字节是域名 // 网络类型 type 为 A(0x0001),代表 IPv4 // 网络级别 class 为 IN(0x0001),代表 Internet // Answer 域 buf[bufLen] = 0xc0; buf[bufLen+1] = 0x0c; buf[bufLen+2] = 0x00; buf[bufLen+3] = 0x01; buf[bufLen+4] = 0x00; buf[bufLen+5] = 0x01; buf[bufLen+6] = 0x00; buf[bufLen+7] = 0x00; buf[bufLen+8] = 0x02;
buf[bufLen+9] = 0x58; buf[bufLen+10] = 0x00; buf[bufLen+11] = 0x04; // 以上 2 字节是 Data Length,4byte,32 位 IPv4 地址 // 以上四个字节为生命期 TTL,0x0258 秒,为 10 分钟 buf[bufLen+12] = localadd[pos-1].IP[0]; buf[bufLen+13] = localadd[pos-1].IP[1]; buf[bufLen+14] = localadd[pos-1].IP[2]; buf[bufLen+15] = localadd[pos-1].IP[3]; // 回复的 IPv4 地址 int temp1 = buffer[begin]; temp1 = (temp1 >= 0 ? temp1 : (temp1+256) ) * 0x100; int temp2 = buffer[begin+1]; temp1 += (temp2 >= 0 ? temp2 : (temp2+256)); return temp1; } int headPart(char *buffer, int begin) { } /*** 逐字段解析 DNS 报文首部 ***/ void analys(int stLen, char *buffer) { int part; cout << hex; for (int i = 0; i < stLen; i++) { } part = buffer[i]; part = part >= 0 ? part : (part+256); cout << " " << setfill('0') << setw(2) << part;//默认空出来的用 0 填充 // Dns 报文首部解析 // 0、1字节为 Transaction ID part = headPart(buffer, 0); cout << endl << " ID " << setw(4) << part; // 2、3 字节为 Flags part = headPart(buffer, 2);//解析“2、3”字节的内容 cout << ", QR " << part / 0x8000; cout << ", OPCODE " << part % 0x8000 / 0x800; cout << ", AA " << part % 0x800 / 0x400; cout << ", TC " << part % 0x400 / 0x200; cout << ", RD " << part % 0x200 / 0x100; cout << ", RA " << part % 0x100 / 0x80; cout << ", Z " << part % 0x80 / 0x10; cout << ", RCODE " << part % 0x10;
// 4、5 字节为 Questions count part = headPart(buffer, 4); cout << endl << " QDCOUNT " << part; // 6、7 字节为 Answer RRS part = headPart(buffer, 6); cout << ", ANCOUNT " << part; // 8、9 字节为 Authority RRS part = headPart(buffer, 8); cout << ", NSCOUNT " << part; // 10、11 字节为 Additional RRS part = headPart(buffer, 10); cout << ", ARCOUNT " << part; cout << dec << endl; SOCKADDR_IN SvrAdd; SvrAdd.sin_addr.S_un.S_addr=inet_addr(addr); // IP,inet_addr 将一个点间隔地址转换成 } /*** 发送给远程服务器函数定义 ***/ int SendtoServer(SOCKET sockTo, const char FAR * buf, int len, char *addr, USHORT port) // 发送 UDP 包 { 一个 in_addr AF_INET 表示处于 Internet 域 } /*** 从本地文件加载域名对应的 IPv4 地址到内存 ***/ bool loadFile (const char *fileName, int &count, Filenode *localadd)//count 传引用调用,改变了 值 { // 将文件内容读入 Memory for (count = 0; !feof(fptr); count++) { fscanf(fptr, "%d.%d.%d.%d %s", localadd[count].frequency = 0; // 初始化访问次数 } &localadd[count].IP[0], &localadd[count].IP[1], &localadd[count].IP[2], &localadd[count].IP[3], localadd[count].dmName); FILE * fptr; if ( (fptr = fopen(fileName, "r")) == NULL) return false; SvrAdd.sin_family=AF_INET; // AF 表示 ADDRESS FAMILY 地址族, SvrAdd.sin_port=htons(port); // 端口,16 位整数转换成网络字节序 return sendto(sockTo, buf, len, 0, (sockaddr *)&SvrAdd, sizeof(sockaddr));
fclose(fptr); return true; } int main(int argc, char* argv[]) { SOCKET s; wsd; //WSADATA 结构被用来保存函数 WSAStartup 返回的 Windows WSADATA Sockets 初始化信息 int bufLen, i, j, k; // 查询总次数 char Dnsfile[64] = "dnsrelay.txt"; cout << "DNSRELAY, Version 1.0, Build: Apr 14 2011 10:47:43" << endl << "Usage: dnsrelay [-d | -dd] [] []" << endl; int total=1; int seqno = -1; int netType = 1; // IPv4 int netClass = 1; // Internet int dbgLvr = 0; char addr[16] = "202.106.0.20"; // 默认 dns 远程服务器地址 bool flag = false; if (argv[i][0] == '-' && argv[i][1] == 'd') { } else if (argv[i][0] >= '0' && argv[i][0] <= '9') { for (i = 1; i < argc; i++) { if (argv[i][2] == 'd' && !argv[i][3]) //-dd else if (!argv[i][2]) dbgLvr = 1;//-d dbgLvr = 2; if (argv[i][j] != '.' && (argv[i][j] < '0' || argv[i][j] > '9')) { //等于'.'继续往后判断 } flag = true; break; for (j = 0; argv[i][j] != 0; j++) { } if (flag) { // 非 IP 地址认为是 db-file } else { memset(Dnsfile, 0, 64); strcpy(Dnsfile, argv[i]); memset(addr, 0, 16); //输入指定远程服务器地址 strcpy(addr, argv[i]);
} } else { } memset(Dnsfile, 0, 64); strcpy(Dnsfile, argv[i]); } // end processing commands unsigned long uladdr; uladdr = inet_addr(addr);//判断指定的远程服务器地址是否有效 if (uladdr == INADDR_NONE) { //无效 } cout << "Name Server " << addr << ":53." << endl cout << "Bad IP Address Input! Ignored!" << endl; memset(addr, 0, 16); strcpy(addr, "202.106.0.20"); << "Debug Level " << dbgLvr << "." << endl;//显示 debug 类型,1 为-d,2 为-dd //操作系统根据请求的 Socket 版本 /*** 初始化模块 ***/ // 初始化套接字动态库 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {//使用 Socket 的程序在使用 Socket 之前必 须调用 WSAStartup 函数,当一个应用程序调用 WSAStartup 函数时, 来搜索相应的 Socket 库, 用程序中。以后应用程序就可以调用所请求的 Socket 库中的其它 Socket 函数了。 printf("WSAStartup failed !\n"); // 初始化失败 return 1; //然后绑定找到的 Socket 库到该应 } // 创建套接字 s = socket(AF_INET, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { WSACleanup(); // 终止对 Winsock DLL 的使用,并释放资源,以备下一次使用 } printf("Socket Error #%d\n", WSAGetLastError()); return 1; SOCKET socketSrv = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrSrv; // 用于创建本地服务器 SOCKADDR_IN addrClient; // 接收外来数据 char buf[BUFF_LEN]; // 存储应用层字段的全部内容 int len = sizeof(SOCKADDR);
// 设置服务器地址 ZeroMemory(buf, BUFF_LEN); // 清空 buffer addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // IP addrSrv.sin_family = AF_INET; // 处于 Internet 域 addrSrv.sin_port = htons(53); // dns 专用端口号 53 printf("Error #%d\n", WSAGetLastError()); // 绑定套接字 cout <<"Bind UDP port 53..." ; bufLen = bind(socketSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); if (bufLen == SOCKET_ERROR) { closesocket(s); WSACleanup(); // 绑定错误,关闭套接字并释放资源 return -1; } cout << "Done!" << endl; /*** 读取本地 dnsrelay 文件 ***/ cout << "Try to load table \""<< Dnsfile <<"\" ..."; int num = 0; Filenode localadd[BUFF_LEN]; if (loadFile(Dnsfile, num, localadd) == false) // loadFile 函数原型在前面定义 else { cout << "Ignored!" << endl; cout << "Done!" << endl << num << " names loaded." << endl;//多少个条目被加载,num 传引用调用, } 值改变 /*** 客户端请求响应及远程服务器请求(中继)模块 ***/ SOCKADDR_IN quest[BUFF_LEN]; char domainName[100] = {0}; // 记录域名 flag = false; // 标记本地查询结果 // 各条客户端请求 // 用来做 ID 转换 char id[BUFF_LEN][2]; k = 0; while (true) { bufLen = recvfrom(socketSrv, buf, BUFF_LEN, 0, (SOCKADDR*)&addrClient, &len); // 接 收一个 UDP 包////////////////////////////////////////// 则为远程服务器发来,否则为本地请求……? 求序号……? if (dbgLvr == 2) { if (ntohs(addrClient.sin_port) == 53) { // 字节序转换;端口为 53(0x0035) int x = buf[0]*16 + buf[1]; // ID 逆变换,x 作为其对应的请
inet_ntoa(addrClient.sin_addr) << ":" << inet_ntoa(quest[x].sin_addr) << ":" << to " << cout << "SEND } cout << "RECV from " << << " (" << bufLen << " bytes) "; analys(bufLen, buf); ntohs(addrClient.sin_port) ntohs(quest[x].sin_port) << " [ID "; int tem1,tem2; tem1 = buf[0]; tem1 = tem1 >= 0 ? tem1 : (tem1+256); tem2 = buf[1]; tem2 = tem2 >= 0 ? tem2 : (tem2+256); cout << setfill('0') << setw(2) << hex << tem1 << setw(2) << tem2; cout << "-> "; tem1 = id[x][0]; tem1 = tem1 >= 0 ? tem1 : (tem1+256); tem2 = id[x][1]; tem2 = tem2 >= 0 ? tem2 : (tem2+256); cout << setfill('0') << setw(2) << tem1 << setw(2) << tem2; cout << "]" << endl; cout << dec; buf[0] = id[x][0]; buf[1] = id[x][1]; 端 memset(domainName, 0, 100); if (sendto(socketSrv, buf, BUFF_LEN, 0, } // end of if PORT == 53 else { quest[k] = addrClient; (sockaddr*)&quest[x], sizeof(sockaddr)) == SOCKET_ERROR) cout << "sendto() Error #" << WSAGetLastError() << endl; // 转发回客户 for (i=13, j=0; buf[i]!='\0'; i++, j++) { // 取出网址 信息,i = 12……? if(buf[i] > ' ') domainName[j] = buf[i]; else } domainName[j+1] = '\0'; int tem1 = netType, tem2 = netClass; netType = buf[i+1]*256 + buf[i+2]; domainName[j] = '.';
netClass = buf[i+3]*256 + buf[i+4]; if ( k > 0 && buf[0] == id[k-1][0] && buf[1] == id[k-1][1] && netType == tem1 && netClass == tem2) // 避免重复查询 continue; seqno++; if (dbgLvr == 2) { ntohs(addrClient.sin_port) cout << "RECV from " << inet_ntoa(addrClient.sin_addr) << ":" << << " (" << bufLen << " bytes) "; analys(bufLen, buf); } flag = false; for (i=0; netType == 1 && (i= 0 ? tem1 : (tem1+256); tem2 = id[k][1]; tem2 = tem2 >= 0 ? tem2 : (tem2+256); cout << setfill('0') << setw(2) << hex << tem1 << setw(2) << tem2; cout << "-> ";
分享到:
收藏