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 << "-> ";